dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / tools / ctf / stabs / common / fth_struct.c
blobd3bd2ef0d11111388e86550510c0d469e5c56b19
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Used to dump structures and unions in forth mode.
32 * structures and unions are a bit more complicated than enums. To make things
33 * just that much more interesting, we have to dump the members in reverse
34 * order, which is nice. But wait! It gets better! For compatibility reasons,
35 * we need to dump the members in reverse-offset order, even if member-specific
36 * mode was used to request the members in something other than that order.
38 * The header op prints the macro header and saves the type being printed.
40 * In member-specific mode, the member op will be invoked for each structure
41 * or union member. The member op adds the member name, format, type ID,
42 * and offset to a list, sorted in reverse order by offset.
44 * The trailer op is called when the structure or enum is complete. If no
45 * members were specifically requested, then the trailer iterates through all
46 * of the members of the structure, pretending they were. Each member is thus
47 * added, in reverse-offset order, to the list used in specific-member mode.
48 * Either way, we then proceed through the list, dumping each member out with
49 * fth_print_member. Structure and union members are printed out differently,
50 * depending on member type, as follows:
52 * Integer:
53 * Normal integers: ' <format> <offset> <type>-field <name>
54 * <format> defaults to ".d" for enums, ".x" for others
55 * <offset> is the member offset, in bytes.
56 * <type> is "byte", "short", "long", or "ext" for 8-, 16-, 32-, and
57 * 64-bit integers, respectively.
58 * <name> is the name of the member being printed
60 * Bitfields: ' <format> <shift> <mask> <offset> bits-field <name>
61 * <format> defaults to ".x"
62 * <shift> is the number of times to right-shift the masked value
63 * <mask> use to extract the bit-field value from the read value
64 * <offset> is the member offset, in bytes
65 * <name> is the name of the member being printed
67 * Float: Ignored
69 * Pointer: ' <format> <offset> ptr-field <name>
70 * <format> defaults to .x
71 * <offset> is in bytes
72 * <name> is the name of the member being printed
74 * Array:
75 * Arrays have a content-type-specific prefix, followed by an array
76 * suffix. The resulting line looks like this if the array contents
77 * type is an integer, a pointer, or an enum:
79 * ' <fldc> ' <fmt> <sz> <elsz> <off> array-field <name>
81 * The following is printed for array contents that are arrays:
83 * ' noop ' .x <sz> <elsz> <off> array-field <name>
85 * The following is printed for array contents that are structs:
87 * ' noop ' <fmt> <sz> <elsz> <off> array-field <name>
89 * <fldc> is "c@", "w@", "l@", or "x@", depending on whether array
90 * elements are 8, 16, 32 or 64 bits wide.
91 * <fmt> defaults to ".x"
92 * <sz> is the size of the array, in bytes
93 * <elsz> is the size of the array elements
94 * <off> is the member offset, in bytes
95 * <name> is the nam eof the member being printed
97 * Struct/Union: ' <format> <offset> struct-field <name>
98 * <format> defaults to ".x"
99 * <offset> is the member offset, in bytes
100 * <name> is the name of the member being printed
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include <string.h>
107 #include "ctf_headers.h"
108 #include "forth.h"
109 #include "list.h"
110 #include "memory.h"
112 static ctf_id_t fth_str_curtid;
113 static list_t *fth_str_curmems;
116 * Node type for the member-storage list (fth_str_curmems) built by
117 * fth_struct_members()
119 typedef struct fth_str_mem {
120 char *fsm_memname;
121 char *fsm_format;
122 ctf_id_t fsm_tid;
123 ulong_t fsm_off;
124 } fth_str_mem_t;
126 typedef struct fth_struct_members_data {
127 char *fsmd_strname;
128 char *fsmd_memfilter;
129 char *fsmd_format;
130 int fsmd_matched;
131 } fth_struct_members_data_t;
133 static int fth_print_member(fth_str_mem_t *, int);
135 /* Comparison routined used to insert members into the fth_str_curmems list */
136 static int
137 fth_struct_memcmp(void *m1, void *m2)
139 fth_str_mem_t *mem1 = m1, *mem2 = m2;
141 if (mem1->fsm_off < mem2->fsm_off)
142 return (1);
143 else if (mem1->fsm_off > mem2->fsm_off)
144 return (-1);
145 else
146 return (0);
149 static void
150 fth_free_str_mem(fth_str_mem_t *mem)
152 free(mem->fsm_memname);
153 if (mem->fsm_format)
154 free(mem->fsm_format);
155 free(mem);
158 static int
159 fth_struct_header(ctf_id_t tid)
161 ssize_t sz;
163 fth_str_curtid = tid;
164 fth_str_curmems = NULL;
166 if ((sz = ctf_type_size(ctf, fth_str_curtid)) == CTF_ERR)
167 return (parse_warn("Can't get size for %s", fth_curtype));
169 (void) fprintf(out, "\n");
170 (void) fprintf(out, "vocabulary %s-words\n", fth_curtype);
171 (void) fprintf(out, "h# %x constant %s-sz\n", sz, fth_curtype);
172 (void) fprintf(out, "%x ' %s-words c-struct .%s\n", sz, fth_curtype,
173 fth_curtype);
174 (void) fprintf(out, "also %s-words definitions\n\n", fth_curtype);
176 return (0);
179 /* Print the array prefix for integer and pointer members */
180 static int
181 fth_print_level(uint_t bits, char *format)
183 if ((bits & (bits - 1)) != 0 ||(bits % 8) != 0 || bits > 64) {
184 return (parse_warn("Unexpected bit size %d in %s",
185 bits, fth_curtype));
188 (void) fprintf(out, "' %c@ ' %s", " cw l x"[bits / 8], format);
190 return (0);
194 * Return the format to be used to print the member. If one of the builtin
195 * formats "d" or "x" were specified, return ".d" or ".x", respectively.
196 * Otherwise, use the user-provided format as is, or use the default if none
197 * was provided.
199 static char *
200 fth_convert_format(char *format, char *def)
202 static char dot[3] = ".";
204 if (format == NULL)
205 return (def);
206 else if (strlen(format) == 1) {
207 dot[1] = *format;
208 return (dot);
209 } else
210 return (format);
213 static int
214 fth_print_integer(const char *memname, ulong_t off, uint_t bits, char *format,
215 int level)
217 format = fth_convert_format(format, ".x");
219 if (bits > 64) {
220 return (parse_warn("%s.%s is too large (>8 bytes)",
221 fth_curtype, memname));
224 if (level != 0)
225 return (fth_print_level(bits, format));
227 if ((bits % NBBY) != 0 || (bits & (bits - 1)) != 0) {
228 /* bit field */
229 uint_t offset, shift, mask;
231 offset = (off / 32) * 4;
232 shift = 32 - ((off % 32) + bits);
233 mask = ((1 << bits) - 1) << shift;
235 (void) fprintf(out, "' %s %x %x %x bits-field %s\n",
236 format, shift, mask, offset, memname);
238 } else {
239 char *type[] = {
240 NULL, "byte", "short", NULL, "long",
241 NULL, NULL, NULL, "ext"
244 (void) fprintf(out, "' %s %lx %s-field %s\n", format, off / 8,
245 type[bits / 8], memname);
248 return (0);
251 static int
252 fth_print_pointer(const char *memname, ulong_t off, uint_t bits, char *format,
253 int level)
255 format = fth_convert_format(format, ".x");
257 if (level != 0)
258 return (fth_print_level(bits, format));
260 (void) fprintf(out, "' %s %lx ptr-field %s\n", format, off / 8,
261 memname);
263 return (0);
266 static int
267 fth_print_struct(char *memname, ulong_t off, char *format,
268 int level)
270 format = fth_convert_format(format, ".x");
272 if (level != 0)
273 (void) fprintf(out, "' noop ' %s", format);
274 else {
275 (void) fprintf(out, "' %s %lx struct-field %s\n", format,
276 off / 8, memname);
279 return (0);
282 static int
283 fth_print_enum(char *memname, ulong_t off, char *format,
284 int level)
286 format = fth_convert_format(format, ".d");
288 if (level != 0)
289 (void) fprintf(out, "' l@ ' %s", format);
290 else {
291 (void) fprintf(out, "' %s %lx long-field %s\n", format, off / 8,
292 memname);
295 return (0);
298 static int
299 fth_print_array(char *memname, ctf_id_t tid, ulong_t off, ssize_t sz,
300 char *format, int level)
302 if (level != 0)
303 (void) fprintf(out, "' noop ' .x");
304 else {
305 fth_str_mem_t mem;
306 ctf_arinfo_t ar;
309 * print the prefix for the array contents type, then print
310 * the array macro
313 if (ctf_array_info(ctf, tid, &ar) == CTF_ERR) {
314 return (parse_warn("Can't read array in %s.%s",
315 fth_curtype, memname));
318 mem.fsm_memname = memname;
319 mem.fsm_format = format;
320 mem.fsm_tid = ar.ctr_contents;
321 mem.fsm_off = off;
323 if (fth_print_member(&mem, level + 1) < 0)
324 return (-1);
326 (void) fprintf(out, " %x %x %lx array-field %s\n", sz,
327 (sz / ar.ctr_nelems), off / 8, memname);
330 return (0);
333 /* dump a structure or union member */
334 static int
335 fth_print_member(fth_str_mem_t *mem, int level)
337 ctf_encoding_t e;
338 ctf_id_t tid;
339 int kind;
340 ssize_t sz;
342 if ((tid = ctf_type_resolve(ctf, mem->fsm_tid)) == CTF_ERR) {
343 return (parse_warn("Can't resolve %s.%s", fth_curtype,
344 mem->fsm_memname));
347 if ((kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
348 return (parse_warn("Can't get kind for %s.%s",
349 fth_curtype, mem->fsm_memname));
352 if ((sz = ctf_type_size(ctf, tid)) == CTF_ERR) {
353 return (parse_warn("Can't get size for %s.%s",
354 fth_curtype, mem->fsm_memname));
357 switch (kind) {
358 case CTF_K_INTEGER:
359 if (ctf_type_encoding(ctf, tid, &e) == CTF_ERR)
360 return (parse_warn("Can't get encoding for %ld", tid));
362 return (fth_print_integer(mem->fsm_memname, mem->fsm_off,
363 e.cte_bits, mem->fsm_format, level));
365 case CTF_K_FLOAT:
366 (void) parse_warn("Ignoring floating point member %s.%s",
367 fth_curtype, mem->fsm_memname);
368 return (0);
370 case CTF_K_POINTER:
371 return (fth_print_pointer(mem->fsm_memname, mem->fsm_off,
372 sz * 8, mem->fsm_format, level));
374 case CTF_K_ARRAY:
375 return (fth_print_array(mem->fsm_memname, tid, mem->fsm_off, sz,
376 mem->fsm_format, level));
378 case CTF_K_STRUCT:
379 case CTF_K_UNION:
380 return (fth_print_struct(mem->fsm_memname, mem->fsm_off,
381 mem->fsm_format, level));
383 case CTF_K_ENUM:
384 return (fth_print_enum(mem->fsm_memname, mem->fsm_off,
385 mem->fsm_format, level));
387 case CTF_K_FORWARD:
388 return (parse_warn("Type %ld in %s.%s is undefined", tid,
389 fth_curtype, mem->fsm_memname));
391 default:
392 return (parse_warn("Unexpected kind %d for %s.%s", kind,
393 fth_curtype, mem->fsm_memname));
398 * Add a member to list of members to be printed (fth_str_curmems). If
399 * fsmd_memfilter is non-null, only add this member if its name matches that
400 * in the filter.
402 static int
403 fth_struct_members_cb(const char *memname, ctf_id_t tid, ulong_t off, void *arg)
405 fth_struct_members_data_t *fsmd = arg;
406 fth_str_mem_t *mem;
408 if (fsmd->fsmd_memfilter != NULL && strcmp(fsmd->fsmd_memfilter,
409 memname) != 0)
410 return (0);
412 fsmd->fsmd_matched = 1;
414 mem = xcalloc(sizeof (fth_str_mem_t));
415 mem->fsm_memname = xstrdup(memname);
416 if (fsmd->fsmd_format)
417 mem->fsm_format = xstrdup(fsmd->fsmd_format);
418 mem->fsm_tid = tid;
419 mem->fsm_off = off;
421 slist_add(&fth_str_curmems, mem, fth_struct_memcmp);
423 return (0);
427 * If memfilter is non-null, iterate through the members of this type, causing
428 * every member to be added to the list. Otherwise, use the iterator and
429 * the callback to add only the specified member.
431 static int
432 fth_struct_members(char *memfilter, char *format)
434 fth_struct_members_data_t fsmd;
436 fsmd.fsmd_strname = fth_curtype;
437 fsmd.fsmd_memfilter = memfilter;
438 fsmd.fsmd_format = format;
439 fsmd.fsmd_matched = 0;
441 if (ctf_member_iter(ctf, fth_str_curtid, fth_struct_members_cb,
442 &fsmd) != 0)
443 return (-1);
445 if (memfilter != NULL && fsmd.fsmd_matched == 0) {
446 return (parse_warn("Invalid member %s.%s", fth_curtype,
447 memfilter));
450 return (0);
453 static int
454 fth_struct_trailer(void)
456 if (list_count(fth_str_curmems) == 0) {
457 if (fth_struct_members(NULL, NULL) < 0)
458 return (-1);
461 while (!list_empty(fth_str_curmems)) {
462 fth_str_mem_t *mem = list_remove(&fth_str_curmems,
463 list_first(fth_str_curmems), NULL, NULL);
465 if (fth_print_member(mem, 0) < 0)
466 return (-1);
468 fth_free_str_mem(mem);
471 (void) fprintf(out, "\n");
472 (void) fprintf(out, "kdbg-words definitions\n");
473 (void) fprintf(out, "previous\n");
474 (void) fprintf(out, "\n");
475 (void) fprintf(out, "\\ end %s section\n", fth_curtype);
476 (void) fprintf(out, "\n");
478 return (0);
481 fth_type_ops_t fth_struct_ops = {
482 fth_struct_header,
483 fth_struct_members,
484 fth_struct_trailer