Print this page
10823 should ignore DW_TAG_subprogram with DW_AT_declaration tags
10824 GCC7-derived CTF can double qualifiers on arrays
10825 ctfdump -c drops last type
10826 ctfdump -c goes off the rails with a missing parent
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/ctfdump/ctfdump.c
+++ new/usr/src/cmd/ctfdump/ctfdump.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright (c) 2019, Joyent, Inc.
13 + * Copyright 2019, Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Dump information about CTF containers.
18 18 */
19 19
20 20 #include <stdio.h>
21 21 #include <unistd.h>
22 22 #include <libctf.h>
23 23 #include <libgen.h>
24 24 #include <stdarg.h>
25 25 #include <stdlib.h>
26 26 #include <stddef.h>
27 27 #include <sys/sysmacros.h>
28 28 #include <sys/types.h>
29 29 #include <sys/stat.h>
30 30 #include <sys/note.h>
31 31 #include <fcntl.h>
32 32 #include <errno.h>
33 33 #include <string.h>
34 34 #include <strings.h>
35 35 #include <err.h>
36 36
37 37 #define MAX_NAMELEN (512)
38 38
39 39 typedef enum ctfdump_arg {
40 40 CTFDUMP_OBJECTS = 0x001,
41 41 CTFDUMP_FUNCTIONS = 0x002,
42 42 CTFDUMP_HEADER = 0x004,
43 43 CTFDUMP_LABELS = 0x008,
44 44 CTFDUMP_STRINGS = 0x010,
45 45 CTFDUMP_STATS = 0x020,
46 46 CTFDUMP_TYPES = 0x040,
47 47 CTFDUMP_DEFAULT = 0x07f,
48 48 CTFDUMP_OUTPUT = 0x080,
49 49 CTFDUMP_SOURCE = 0x100,
50 50 } ctfdump_arg_t;
51 51
52 52 typedef struct ctfdump_stat {
53 53 ulong_t cs_ndata; /* number of data objects */
54 54 ulong_t cs_nfuncs; /* number of functions */
55 55 ulong_t cs_nfuncargs; /* number of function args */
56 56 ulong_t cs_nfuncmax; /* largest number of args */
57 57 ulong_t cs_ntypes[CTF_K_MAX]; /* number of types */
58 58 ulong_t cs_nsmembs; /* number of struct members */
59 59 ulong_t cs_nsmax; /* largest number of members */
60 60 ulong_t cs_structsz; /* sum of structures sizes */
61 61 ulong_t cs_sszmax; /* largest structure */
62 62 ulong_t cs_numembs; /* number of union members */
63 63 ulong_t cs_numax; /* largest number of members */
64 64 ulong_t cs_unionsz; /* sum of unions sizes */
65 65 ulong_t cs_uszmax; /* largest union */
66 66 ulong_t cs_nemembs; /* number of enum members */
67 67 ulong_t cs_nemax; /* largest number of members */
68 68 ulong_t cs_nstrings; /* number of strings */
69 69 ulong_t cs_strsz; /* string size */
70 70 ulong_t cs_strmax; /* longest string */
71 71 } ctfdump_stat_t;
72 72
73 73 typedef struct {
74 74 char ci_name[MAX_NAMELEN];
75 75 ctf_id_t ci_id;
76 76 ulong_t ci_symidx;
77 77 ctf_funcinfo_t ci_funcinfo;
78 78 } ctf_idname_t;
79 79
80 80 static ctf_idname_t *idnames;
81 81 static const char *g_progname;
82 82 static ctfdump_arg_t g_dump;
83 83 static ctf_file_t *g_fp;
84 84 static ctfdump_stat_t g_stats;
85 85 static ctf_id_t *g_fargc;
86 86 static int g_nfargc;
87 87
88 88 static int g_exit = 0;
89 89
90 90 static const char *ctfdump_fpenc[] = {
91 91 NULL,
92 92 "SINGLE",
93 93 "DOUBLE",
94 94 "COMPLEX",
95 95 "DCOMPLEX",
96 96 "LDCOMPLEX",
97 97 "LDOUBLE",
98 98 "INTERVAL",
99 99 "DINTERVAL",
100 100 "LDINTERVAL",
101 101 "IMAGINARY",
102 102 "DIMAGINARY",
103 103 "LDIMAGINARY"
104 104 };
105 105
106 106 /*
107 107 * When stats are requested, we have to go through everything. To make our lives
108 108 * easier, we'll just always allow the code to print everything out, but only
109 109 * output it if we have actually enabled that section.
110 110 */
111 111 static void
112 112 ctfdump_printf(ctfdump_arg_t arg, const char *fmt, ...)
113 113 {
114 114 va_list ap;
115 115
116 116 if ((arg & g_dump) == 0)
117 117 return;
118 118
119 119 va_start(ap, fmt);
120 120 (void) vfprintf(stdout, fmt, ap);
121 121 va_end(ap);
122 122 }
123 123
124 124 static void
125 125 ctfdump_fatal(const char *fmt, ...)
126 126 {
127 127 va_list ap;
128 128
129 129 (void) fprintf(stderr, "%s: ", g_progname);
130 130 va_start(ap, fmt);
131 131 (void) vfprintf(stderr, fmt, ap);
132 132 va_end(ap);
133 133
134 134 exit(1);
135 135 }
136 136
137 137 static void
138 138 ctfdump_usage(const char *fmt, ...)
139 139 {
140 140 if (fmt != NULL) {
141 141 va_list ap;
142 142 (void) fprintf(stderr, "%s: ", g_progname);
143 143 va_start(ap, fmt);
144 144 (void) vfprintf(stderr, fmt, ap);
145 145 va_end(ap);
146 146 }
147 147
148 148 (void) fprintf(stderr, "Usage: %s [-cdfhlsSt] [-p parent] [-u outfile] "
149 149 "file\n"
150 150 "\n"
151 151 "\t-c dump C-style output\n"
152 152 "\t-d dump object data\n"
153 153 "\t-f dump function data\n"
154 154 "\t-h dump the CTF header\n"
155 155 "\t-l dump the label table\n"
156 156 "\t-p use parent to supply additional information\n"
157 157 "\t-s dump the string table\n"
158 158 "\t-S dump statistics about the CTF container\n"
159 159 "\t-t dump type information\n"
160 160 "\t-u dump uncompressed CTF data to outfile\n",
161 161 g_progname);
162 162 }
163 163
164 164 static void
165 165 ctfdump_title(ctfdump_arg_t arg, const char *header)
166 166 {
167 167 static const char line[] = "----------------------------------------"
168 168 "----------------------------------------";
169 169 ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header),
170 170 line);
171 171 }
172 172
173 173 static int
174 174 ctfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg)
175 175 {
176 176 _NOTE(ARGUNUSED(arg));
177 177
178 178 int len;
179 179
180 180 len = snprintf(NULL, 0, " [%lu] %ld", g_stats.cs_ndata, id);
181 181 ctfdump_printf(CTFDUMP_OBJECTS, " [%lu] %ld %*s%s (%lu)\n",
182 182 g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx);
183 183 g_stats.cs_ndata++;
184 184 return (0);
185 185 }
186 186
187 187 static void
188 188 ctfdump_objects(void)
189 189 {
190 190 ctfdump_title(CTFDUMP_OBJECTS, "Data Objects");
191 191 if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) {
192 192 warnx("failed to dump objects: %s",
193 193 ctf_errmsg(ctf_errno(g_fp)));
194 194 g_exit = 1;
195 195 }
196 196 }
197 197
198 198 static void
199 199 ctfdump_fargs_grow(int nargs)
200 200 {
201 201 if (g_nfargc < nargs) {
202 202 g_fargc = realloc(g_fargc, sizeof (ctf_id_t) * nargs);
203 203 if (g_fargc == NULL)
204 204 ctfdump_fatal("failed to get memory for %d "
205 205 "ctf_id_t's\n", nargs);
206 206 g_nfargc = nargs;
207 207 }
208 208 }
209 209
210 210 static int
211 211 ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc,
212 212 void *arg)
213 213 {
214 214 _NOTE(ARGUNUSED(arg));
215 215 int i;
216 216
217 217 if (ctc->ctc_argc != 0) {
218 218 ctfdump_fargs_grow(ctc->ctc_argc);
219 219 if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR)
220 220 ctfdump_fatal("failed to get arguments for function "
221 221 "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
222 222 }
223 223
224 224 ctfdump_printf(CTFDUMP_FUNCTIONS,
225 225 " [%lu] %s (%lu) returns: %ld args: (", g_stats.cs_nfuncs, name,
226 226 symidx, ctc->ctc_return);
227 227 for (i = 0; i < ctc->ctc_argc; i++)
228 228 ctfdump_printf(CTFDUMP_FUNCTIONS, "%ld%s", g_fargc[i],
229 229 i + 1 == ctc->ctc_argc ? "" : ", ");
230 230 if (ctc->ctc_flags & CTF_FUNC_VARARG)
231 231 ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...",
232 232 ctc->ctc_argc == 0 ? "" : ", ");
233 233 ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n");
234 234
235 235 g_stats.cs_nfuncs++;
236 236 g_stats.cs_nfuncargs += ctc->ctc_argc;
237 237 g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax);
238 238
239 239 return (0);
240 240 }
241 241
242 242 static void
243 243 ctfdump_functions(void)
244 244 {
245 245 ctfdump_title(CTFDUMP_FUNCTIONS, "Functions");
246 246
247 247 if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) {
248 248 warnx("failed to dump functions: %s",
249 249 ctf_errmsg(ctf_errno(g_fp)));
250 250 g_exit = 1;
251 251 }
252 252 }
253 253
254 254 static void
255 255 ctfdump_header(void)
256 256 {
257 257 const ctf_header_t *hp;
258 258 const char *parname, *parlabel;
259 259
260 260 ctfdump_title(CTFDUMP_HEADER, "CTF Header");
261 261 ctf_dataptr(g_fp, (const void **)&hp, NULL);
262 262 ctfdump_printf(CTFDUMP_HEADER, " cth_magic = 0x%04x\n",
263 263 hp->cth_magic);
264 264 ctfdump_printf(CTFDUMP_HEADER, " cth_version = %u\n",
265 265 hp->cth_version);
266 266 ctfdump_printf(CTFDUMP_HEADER, " cth_flags = 0x%02x\n",
267 267 ctf_flags(g_fp));
268 268 parname = ctf_parent_name(g_fp);
269 269 parlabel = ctf_parent_label(g_fp);
270 270 ctfdump_printf(CTFDUMP_HEADER, " cth_parlabel = %s\n",
271 271 parlabel == NULL ? "(anon)" : parlabel);
272 272 ctfdump_printf(CTFDUMP_HEADER, " cth_parname = %s\n",
273 273 parname == NULL ? "(anon)" : parname);
274 274 ctfdump_printf(CTFDUMP_HEADER, " cth_lbloff = %u\n",
275 275 hp->cth_lbloff);
276 276 ctfdump_printf(CTFDUMP_HEADER, " cth_objtoff = %u\n",
277 277 hp->cth_objtoff);
278 278 ctfdump_printf(CTFDUMP_HEADER, " cth_funcoff = %u\n",
279 279 hp->cth_funcoff);
280 280 ctfdump_printf(CTFDUMP_HEADER, " cth_typeoff = %u\n",
281 281 hp->cth_typeoff);
282 282 ctfdump_printf(CTFDUMP_HEADER, " cth_stroff = %u\n",
283 283 hp->cth_stroff);
284 284 ctfdump_printf(CTFDUMP_HEADER, " cth_strlen = %u\n",
285 285 hp->cth_strlen);
286 286 }
287 287
288 288 static int
289 289 ctfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg)
290 290 {
291 291 _NOTE(ARGUNUSED(arg));
292 292 ctfdump_printf(CTFDUMP_LABELS, " %5ld %s\n", li->ctb_typeidx, name);
293 293 return (0);
294 294 }
295 295
296 296 static void
297 297 ctfdump_labels(void)
298 298 {
299 299 ctfdump_title(CTFDUMP_LABELS, "Label Table");
300 300 if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) {
301 301 warnx("failed to dump labels: %s",
302 302 ctf_errmsg(ctf_errno(g_fp)));
303 303 g_exit = 1;
304 304 }
305 305 }
306 306
307 307 static int
308 308 ctfdump_strings_cb(const char *s, void *arg)
309 309 {
310 310 size_t len = strlen(s) + 1;
311 311 ulong_t *stroff = arg;
312 312 ctfdump_printf(CTFDUMP_STRINGS, " [%lu] %s\n", *stroff,
313 313 *s == '\0' ? "\\0" : s);
314 314 *stroff = *stroff + len;
315 315 g_stats.cs_nstrings++;
316 316 g_stats.cs_strsz += len;
317 317 g_stats.cs_strmax = MAX(g_stats.cs_strmax, len);
318 318 return (0);
319 319 }
320 320
321 321 static void
322 322 ctfdump_strings(void)
323 323 {
324 324 ulong_t stroff = 0;
325 325
326 326 ctfdump_title(CTFDUMP_STRINGS, "String Table");
327 327 if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) {
328 328 warnx("failed to dump strings: %s",
329 329 ctf_errmsg(ctf_errno(g_fp)));
330 330 g_exit = 1;
331 331 }
332 332 }
333 333
334 334 static void
335 335 ctfdump_stat_int(const char *name, ulong_t value)
336 336 {
337 337 ctfdump_printf(CTFDUMP_STATS, " %-36s= %lu\n", name, value);
338 338 }
339 339
340 340 static void
341 341 ctfdump_stat_fp(const char *name, float value)
342 342 {
343 343 ctfdump_printf(CTFDUMP_STATS, " %-36s= %.2f\n", name, value);
344 344 }
345 345
346 346 static void
347 347 ctfdump_stats(void)
348 348 {
349 349 int i;
350 350 ulong_t sum;
351 351
352 352 ctfdump_title(CTFDUMP_STATS, "CTF Statistics");
353 353
354 354 ctfdump_stat_int("total number of data objects", g_stats.cs_ndata);
355 355 ctfdump_printf(CTFDUMP_STATS, "\n");
356 356 ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs);
357 357 ctfdump_stat_int("total number of function arguments",
358 358 g_stats.cs_nfuncargs);
359 359 ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax);
360 360 if (g_stats.cs_nfuncs != 0)
361 361 ctfdump_stat_fp("average argument list length",
362 362 (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs);
363 363 ctfdump_printf(CTFDUMP_STATS, "\n");
364 364
365 365 sum = 0;
366 366 for (i = 0; i < CTF_K_MAX; i++)
367 367 sum += g_stats.cs_ntypes[i];
368 368 ctfdump_stat_int("total number of types", sum);
369 369 ctfdump_stat_int("total number of integers",
370 370 g_stats.cs_ntypes[CTF_K_INTEGER]);
371 371 ctfdump_stat_int("total number of floats",
372 372 g_stats.cs_ntypes[CTF_K_FLOAT]);
373 373 ctfdump_stat_int("total number of pointers",
374 374 g_stats.cs_ntypes[CTF_K_POINTER]);
375 375 ctfdump_stat_int("total number of arrays",
376 376 g_stats.cs_ntypes[CTF_K_ARRAY]);
377 377 ctfdump_stat_int("total number of func types",
378 378 g_stats.cs_ntypes[CTF_K_FUNCTION]);
379 379 ctfdump_stat_int("total number of structs",
380 380 g_stats.cs_ntypes[CTF_K_STRUCT]);
381 381 ctfdump_stat_int("total number of unions",
382 382 g_stats.cs_ntypes[CTF_K_UNION]);
383 383 ctfdump_stat_int("total number of enums",
384 384 g_stats.cs_ntypes[CTF_K_ENUM]);
385 385 ctfdump_stat_int("total number of forward tags",
386 386 g_stats.cs_ntypes[CTF_K_FORWARD]);
387 387 ctfdump_stat_int("total number of typedefs",
388 388 g_stats.cs_ntypes[CTF_K_TYPEDEF]);
389 389 ctfdump_stat_int("total number of volatile types",
390 390 g_stats.cs_ntypes[CTF_K_VOLATILE]);
391 391 ctfdump_stat_int("total number of const types",
392 392 g_stats.cs_ntypes[CTF_K_CONST]);
393 393 ctfdump_stat_int("total number of restrict types",
394 394 g_stats.cs_ntypes[CTF_K_RESTRICT]);
395 395 ctfdump_stat_int("total number of unknowns (holes)",
396 396 g_stats.cs_ntypes[CTF_K_UNKNOWN]);
397 397
398 398 ctfdump_printf(CTFDUMP_STATS, "\n");
399 399 ctfdump_stat_int("total number of struct members", g_stats.cs_nsmembs);
400 400 ctfdump_stat_int("maximum number of struct members", g_stats.cs_nsmax);
401 401 ctfdump_stat_int("total size of all structs", g_stats.cs_structsz);
402 402 ctfdump_stat_int("maximum size of a struct", g_stats.cs_sszmax);
403 403 if (g_stats.cs_ntypes[CTF_K_STRUCT] != 0) {
404 404 ctfdump_stat_fp("average number of struct members",
405 405 (float)g_stats.cs_nsmembs /
406 406 (float)g_stats.cs_ntypes[CTF_K_STRUCT]);
407 407 ctfdump_stat_fp("average size of a struct",
408 408 (float)g_stats.cs_structsz /
409 409 (float)g_stats.cs_ntypes[CTF_K_STRUCT]);
410 410 }
411 411 ctfdump_printf(CTFDUMP_STATS, "\n");
412 412 ctfdump_stat_int("total number of union members", g_stats.cs_numembs);
413 413 ctfdump_stat_int("maximum number of union members", g_stats.cs_numax);
414 414 ctfdump_stat_int("total size of all unions", g_stats.cs_unionsz);
415 415 ctfdump_stat_int("maximum size of a union", g_stats.cs_uszmax);
416 416 if (g_stats.cs_ntypes[CTF_K_UNION] != 0) {
417 417 ctfdump_stat_fp("average number of union members",
418 418 (float)g_stats.cs_numembs /
419 419 (float)g_stats.cs_ntypes[CTF_K_UNION]);
420 420 ctfdump_stat_fp("average size of a union",
421 421 (float)g_stats.cs_unionsz /
422 422 (float)g_stats.cs_ntypes[CTF_K_UNION]);
423 423 }
424 424 ctfdump_printf(CTFDUMP_STATS, "\n");
425 425
426 426 ctfdump_stat_int("total number of enum members", g_stats.cs_nemembs);
427 427 ctfdump_stat_int("maximum number of enum members", g_stats.cs_nemax);
428 428 if (g_stats.cs_ntypes[CTF_K_ENUM] != 0) {
429 429 ctfdump_stat_fp("average number of enum members",
430 430 (float)g_stats.cs_nemembs /
431 431 (float)g_stats.cs_ntypes[CTF_K_ENUM]);
432 432 }
433 433 ctfdump_printf(CTFDUMP_STATS, "\n");
434 434
435 435 ctfdump_stat_int("total number of strings", g_stats.cs_nstrings);
436 436 ctfdump_stat_int("bytes of string data", g_stats.cs_strsz);
437 437 ctfdump_stat_int("maximum string length", g_stats.cs_strmax);
438 438 if (g_stats.cs_nstrings != 0)
439 439 ctfdump_stat_fp("average string length",
440 440 (float)g_stats.cs_strsz / (float)g_stats.cs_nstrings);
441 441 ctfdump_printf(CTFDUMP_STATS, "\n");
442 442 }
443 443
444 444 static void
445 445 ctfdump_intenc_name(ctf_encoding_t *cte, char *buf, int len)
446 446 {
447 447 int off = 0;
448 448 boolean_t space = B_FALSE;
449 449
450 450 if (cte->cte_format == 0 || (cte->cte_format &
451 451 ~(CTF_INT_SIGNED | CTF_INT_CHAR | CTF_INT_BOOL |
452 452 CTF_INT_VARARGS)) != 0) {
453 453 (void) snprintf(buf, len, "0x%x", cte->cte_format);
454 454 return;
455 455 }
456 456
457 457 if (cte->cte_format & CTF_INT_SIGNED) {
458 458 off += snprintf(buf + off, MAX(len - off, 0), "%sSIGNED",
459 459 space == B_TRUE ? " " : "");
460 460 space = B_TRUE;
461 461 }
462 462
463 463 if (cte->cte_format & CTF_INT_CHAR) {
464 464 off += snprintf(buf + off, MAX(len - off, 0), "%sCHAR",
465 465 space == B_TRUE ? " " : "");
466 466 space = B_TRUE;
467 467 }
468 468
469 469 if (cte->cte_format & CTF_INT_BOOL) {
470 470 off += snprintf(buf + off, MAX(len - off, 0), "%sBOOL",
471 471 space == B_TRUE ? " " : "");
472 472 space = B_TRUE;
473 473 }
474 474
475 475 if (cte->cte_format & CTF_INT_VARARGS) {
476 476 off += snprintf(buf + off, MAX(len - off, 0), "%sVARARGS",
477 477 space == B_TRUE ? " " : "");
478 478 space = B_TRUE;
479 479 }
480 480 }
481 481
482 482 static int
483 483 ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
484 484 {
485 485 int *count = arg;
486 486 ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%ld off=%lu\n", member, type,
487 487 off);
488 488 *count = *count + 1;
489 489 return (0);
490 490 }
491 491
492 492 static int
493 493 ctfdump_enum_cb(const char *name, int value, void *arg)
494 494 {
495 495 int *count = arg;
496 496 ctfdump_printf(CTFDUMP_TYPES, "\t%s = %d\n", name, value);
497 497 *count = *count + 1;
498 498 return (0);
499 499 }
500 500
501 501 static int
502 502 ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg)
503 503 {
504 504 _NOTE(ARGUNUSED(arg));
505 505 int kind, i, count;
506 506 ctf_id_t ref;
507 507 char name[MAX_NAMELEN], ienc[128];
508 508 const char *encn;
509 509 ctf_funcinfo_t ctc;
510 510 ctf_arinfo_t ar;
511 511 ctf_encoding_t cte;
512 512 ssize_t size;
513 513
514 514 if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR)
515 515 ctfdump_fatal("encountered malformed ctf, type %s does not "
516 516 "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
517 517
518 518 if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) {
519 519 if (ctf_errno(g_fp) != ECTF_NOPARENT)
520 520 ctfdump_fatal("type %ld missing name: %s\n", id,
521 521 ctf_errmsg(ctf_errno(g_fp)));
522 522 (void) snprintf(name, sizeof (name), "(unknown %s)",
523 523 ctf_kind_name(g_fp, kind));
524 524 }
525 525
526 526 g_stats.cs_ntypes[kind]++;
527 527 if (root == B_TRUE)
528 528 ctfdump_printf(CTFDUMP_TYPES, " <%ld> ", id);
529 529 else
530 530 ctfdump_printf(CTFDUMP_TYPES, " [%ld] ", id);
531 531
532 532 switch (kind) {
533 533 case CTF_K_UNKNOWN:
534 534 break;
535 535 case CTF_K_INTEGER:
536 536 if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
537 537 ctfdump_fatal("failed to get encoding information "
538 538 "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
539 539 ctfdump_intenc_name(&cte, ienc, sizeof (ienc));
540 540 ctfdump_printf(CTFDUMP_TYPES,
541 541 "%s encoding=%s offset=%u bits=%u",
542 542 name, ienc, cte.cte_offset, cte.cte_bits);
543 543 break;
544 544 case CTF_K_FLOAT:
545 545 if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
546 546 ctfdump_fatal("failed to get encoding information "
547 547 "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
548 548 if (cte.cte_format < 1 || cte.cte_format > 12)
549 549 encn = "unknown";
550 550 else
551 551 encn = ctfdump_fpenc[cte.cte_format];
552 552 ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u "
553 553 "bits=%u", name, encn, cte.cte_offset, cte.cte_bits);
554 554 break;
555 555 case CTF_K_POINTER:
556 556 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
557 557 ctfdump_fatal("failed to get reference type for %s: "
558 558 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
559 559 ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
560 560 ref);
561 561 break;
562 562 case CTF_K_ARRAY:
563 563 if (ctf_array_info(g_fp, id, &ar) == CTF_ERR)
564 564 ctfdump_fatal("failed to get array information for "
565 565 "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
566 566 ctfdump_printf(CTFDUMP_TYPES, "%s contents: %ld, index: %ld",
567 567 name, ar.ctr_contents, ar.ctr_index);
568 568 break;
569 569 case CTF_K_FUNCTION:
570 570 if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR)
571 571 ctfdump_fatal("failed to get function info for %s: "
572 572 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
573 573 if (ctc.ctc_argc > 0) {
574 574 ctfdump_fargs_grow(ctc.ctc_argc);
575 575 if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) ==
576 576 CTF_ERR)
577 577 ctfdump_fatal("failed to get function "
578 578 "arguments for %s: %s\n", name,
579 579 ctf_errmsg(ctf_errno(g_fp)));
580 580 }
581 581 ctfdump_printf(CTFDUMP_TYPES,
582 582 "%s returns: %ld args: (", name, ctc.ctc_return);
583 583 for (i = 0; i < ctc.ctc_argc; i++) {
584 584 ctfdump_printf(CTFDUMP_TYPES, "%ld%s", g_fargc[i],
585 585 i + 1 == ctc.ctc_argc ? "" : ", ");
586 586 }
587 587 if (ctc.ctc_flags & CTF_FUNC_VARARG)
588 588 ctfdump_printf(CTFDUMP_TYPES, "%s...",
589 589 ctc.ctc_argc == 0 ? "" : ", ");
590 590 ctfdump_printf(CTFDUMP_TYPES, ")");
591 591 break;
592 592 case CTF_K_STRUCT:
593 593 case CTF_K_UNION:
594 594 size = ctf_type_size(g_fp, id);
595 595 if (size == CTF_ERR)
596 596 ctfdump_fatal("failed to get size of %s: %s\n", name,
597 597 ctf_errmsg(ctf_errno(g_fp)));
598 598 ctfdump_printf(CTFDUMP_TYPES, "%s (%zd bytes)\n", name, size);
599 599 count = 0;
600 600 if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0)
601 601 ctfdump_fatal("failed to iterate members of %s: %s\n",
602 602 name, ctf_errmsg(ctf_errno(g_fp)));
603 603 if (kind == CTF_K_STRUCT) {
604 604 g_stats.cs_nsmembs += count;
605 605 g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax);
606 606 g_stats.cs_structsz += size;
607 607 g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax);
608 608 } else {
609 609 g_stats.cs_numembs += count;
610 610 g_stats.cs_numax = MAX(count, g_stats.cs_numax);
611 611 g_stats.cs_unionsz += size;
612 612 g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax);
613 613 }
614 614 break;
615 615 case CTF_K_ENUM:
616 616 ctfdump_printf(CTFDUMP_TYPES, "%s\n", name);
617 617 count = 0;
618 618 if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0)
619 619 ctfdump_fatal("failed to iterate enumerators of %s: "
620 620 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
621 621 g_stats.cs_nemembs += count;
622 622 g_stats.cs_nemax = MAX(g_stats.cs_nemax, count);
623 623 break;
624 624 case CTF_K_FORWARD:
625 625 ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name);
626 626 break;
627 627 case CTF_K_TYPEDEF:
628 628 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
629 629 ctfdump_fatal("failed to get reference type for %s: "
630 630 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
631 631 ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %ld", name,
632 632 ref);
633 633 break;
634 634 case CTF_K_VOLATILE:
635 635 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
636 636 ctfdump_fatal("failed to get reference type for %s: "
637 637 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
638 638 ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
639 639 ref);
640 640 break;
641 641 case CTF_K_CONST:
642 642 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
643 643 ctfdump_fatal("failed to get reference type for %s: "
644 644 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
645 645 ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
646 646 ref);
647 647 break;
648 648 case CTF_K_RESTRICT:
649 649 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
650 650 ctfdump_fatal("failed to get reference type for %s: "
651 651 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
652 652 ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
653 653 ref);
654 654 break;
655 655 default:
656 656 ctfdump_fatal("encountered unknown kind for type %s: %d\n",
657 657 name, kind);
658 658 }
659 659
660 660 ctfdump_printf(CTFDUMP_TYPES, "\n");
661 661
662 662 return (0);
663 663 }
664 664
665 665 static void
666 666 ctfdump_types(void)
667 667 {
668 668 ctfdump_title(CTFDUMP_TYPES, "Types");
669 669
670 670 if (ctf_type_iter(g_fp, B_TRUE, ctfdump_types_cb, NULL) == CTF_ERR) {
671 671 warnx("failed to dump types: %s",
672 672 ctf_errmsg(ctf_errno(g_fp)));
673 673 g_exit = 1;
674 674 }
675 675 }
676 676
677 677 /*
↓ open down ↓ |
654 lines elided |
↑ open up ↑ |
678 678 * C-style output. This is designed mainly for comparison purposes, and doesn't
679 679 * produce directly valid C:
680 680 *
681 681 * - the declarations are sorted alphabetically not semantically
682 682 * - anonymous enums without other users are elided (e.g. IDCS_PROBE_SENT)
683 683 * - doubly-pointed-to functions are wrong (e.g. in kiconv_ops_t)
684 684 * - anon unions declared within SOUs aren't expanded
685 685 * - function arguments aren't expanded recursively
686 686 */
687 687
688 -static void
688 +static const char *
689 689 ctfsrc_refname(ctf_id_t id, char *buf, size_t bufsize)
690 690 {
691 691 ctf_id_t ref;
692 692
693 693 if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) {
694 694 ctfdump_fatal("failed to get reference type for %ld: "
695 695 "%s\n", id, ctf_errmsg(ctf_errno(g_fp)));
696 696 }
697 697
698 - (void) ctf_type_name(g_fp, ref, buf, bufsize);
698 + return (ctf_type_name(g_fp, ref, buf, bufsize));
699 699 }
700 700
701 701 static int
702 702 ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
703 703 {
704 704 _NOTE(ARGUNUSED(arg));
705 705 char name[MAX_NAMELEN];
706 706
707 707 if (ctf_type_cname(g_fp, type, name, sizeof (name), member) == NULL) {
708 708 if (ctf_errno(g_fp) != ECTF_NOPARENT) {
709 709 ctfdump_fatal("type %ld missing name: %s\n", type,
710 710 ctf_errmsg(ctf_errno(g_fp)));
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
711 711 }
712 712
713 713 (void) snprintf(name, sizeof (name), "unknown_t %s", member);
714 714 }
715 715
716 716 /*
717 717 * A byte offset is friendlier, but we'll print bits too if it's not
718 718 * aligned (i.e. a bitfield).
719 719 */
720 720 if (off % NBBY != 0) {
721 - (void) printf("\t%s; /* offset: %lu bytes (%lu bits) */\n",
721 + printf("\t%s; /* offset: %lu bytes (%lu bits) */\n",
722 722 name, off / NBBY, off);
723 723 } else {
724 - (void) printf("\t%s; /* offset: %lu bytes */\n",
724 + printf("\t%s; /* offset: %lu bytes */\n",
725 725 name, off / NBBY);
726 726 }
727 727 return (0);
728 728 }
729 729
730 730 static int
731 731 ctfsrc_enum_cb(const char *name, int value, void *arg)
732 732 {
733 733 _NOTE(ARGUNUSED(arg));
734 - (void) printf("\t%s = %d,\n", name, value);
734 + printf("\t%s = %d,\n", name, value);
735 735 return (0);
736 736 }
737 737
738 738 static int
739 739 is_anon_refname(const char *refname)
740 740 {
741 741 return ((strcmp(refname, "struct ") == 0 ||
742 742 strcmp(refname, "union ") == 0 ||
743 743 strcmp(refname, "enum ") == 0));
744 744 }
745 745
746 746 static int
747 747 ctfsrc_collect_types_cb(ctf_id_t id, boolean_t root, void *arg)
748 748 {
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
749 749 _NOTE(ARGUNUSED(root, arg));
750 750 (void) ctf_type_name(g_fp, id, idnames[id].ci_name,
751 751 sizeof (idnames[id].ci_name));
752 752 idnames[id].ci_id = id;
753 753 return (0);
754 754 }
755 755
756 756 static void
757 757 ctfsrc_type(ctf_id_t id, const char *name)
758 758 {
759 - char refname[MAX_NAMELEN];
759 + char refname[MAX_NAMELEN] = "unknown_t";
760 760 ctf_id_t ref;
761 761 ssize_t size;
762 762 int kind;
763 763
764 764 if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) {
765 765 ctfdump_fatal("encountered malformed ctf, type %s does not "
766 766 "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
767 767 }
768 768
769 769 switch (kind) {
770 770 case CTF_K_STRUCT:
771 771 case CTF_K_UNION:
772 772 /*
773 773 * Delay printing anonymous SOUs; a later typedef will usually
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
774 774 * pick them up.
775 775 */
776 776 if (is_anon_refname(name))
777 777 break;
778 778
779 779 if ((size = ctf_type_size(g_fp, id)) == CTF_ERR) {
780 780 ctfdump_fatal("failed to get size of %s: %s\n", name,
781 781 ctf_errmsg(ctf_errno(g_fp)));
782 782 }
783 783
784 - (void) printf("%s { /* 0x%x bytes */\n", name, size);
784 + printf("%s { /* 0x%x bytes */\n", name, size);
785 785
786 786 if (ctf_member_iter(g_fp, id, ctfsrc_member_cb, NULL) != 0) {
787 787 ctfdump_fatal("failed to iterate members of %s: %s\n",
788 788 name, ctf_errmsg(ctf_errno(g_fp)));
789 789 }
790 790
791 - (void) printf("};\n\n");
791 + printf("};\n\n");
792 792 break;
793 793 case CTF_K_ENUM:
794 794 /*
795 795 * This will throw away any anon enum that isn't followed by a
796 796 * typedef...
797 797 */
798 798 if (is_anon_refname(name))
799 799 break;
800 800
801 - (void) printf("%s {\n", name);
801 + printf("%s {\n", name);
802 802
803 803 if (ctf_enum_iter(g_fp, id, ctfsrc_enum_cb, NULL) != 0) {
804 804 ctfdump_fatal("failed to iterate enumerators of %s: "
805 805 "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
806 806 }
807 807
808 - (void) printf("};\n\n");
808 + printf("};\n\n");
809 809 break;
810 810 case CTF_K_TYPEDEF:
811 - ctfsrc_refname(id, refname, sizeof (refname));
811 + /*
812 + * If this fails, it's probably because the referent type is in
813 + * a parent container that was not supplied via -p.
814 + */
815 + if (ctfsrc_refname(id, refname, sizeof (refname)) == NULL) {
816 + printf("typedef %s %s;\n\n", refname, name);
817 + break;
818 + }
812 819
813 820 if (!is_anon_refname(refname)) {
814 821 (void) ctf_type_cname(g_fp,
815 822 ctf_type_reference(g_fp, id), refname,
816 823 sizeof (refname), name);
817 824
818 - (void) printf("typedef %s;\n\n", refname);
825 + printf("typedef %s;\n\n", refname);
819 826 break;
820 827 }
821 828
822 829 ref = ctf_type_reference(g_fp, id);
823 830
824 831 if (ctf_type_kind(g_fp, ref) == CTF_K_ENUM) {
825 - (void) printf("typedef enum {\n");
832 + printf("typedef enum {\n");
826 833
827 834 if (ctf_enum_iter(g_fp, ref,
828 835 ctfsrc_enum_cb, NULL) != 0) {
829 836 ctfdump_fatal("failed to iterate enumerators "
830 837 "of %s: %s\n", refname,
831 838 ctf_errmsg(ctf_errno(g_fp)));
832 839 }
833 840
834 - (void) printf("} %s;\n\n", name);
841 + printf("} %s;\n\n", name);
835 842 } else {
836 843 if ((size = ctf_type_size(g_fp, ref)) == CTF_ERR) {
837 844 ctfdump_fatal("failed to get size of %s: %s\n",
838 845 refname, ctf_errmsg(ctf_errno(g_fp)));
839 846 }
840 847
841 - (void) printf("typedef %s{ /* 0x%zx bytes */\n",
848 + printf("typedef %s{ /* 0x%zx bytes */\n",
842 849 refname, size);
843 850
844 851 if (ctf_member_iter(g_fp, ref,
845 852 ctfsrc_member_cb, NULL) != 0) {
846 853 ctfdump_fatal("failed to iterate members "
847 854 "of %s: %s\n", refname,
848 855 ctf_errmsg(ctf_errno(g_fp)));
849 856 }
850 857
851 - (void) printf("} %s;\n\n", name);
858 + printf("} %s;\n\n", name);
852 859 }
853 860
854 861 break;
855 862 case CTF_K_FORWARD:
856 - (void) printf("%s;\n\n", name);
863 + printf("%s;\n\n", name);
857 864 break;
858 865 case CTF_K_UNKNOWN:
859 866 case CTF_K_INTEGER:
860 867 case CTF_K_FLOAT:
861 868 case CTF_K_POINTER:
862 869 case CTF_K_ARRAY:
863 870 case CTF_K_FUNCTION:
864 871 case CTF_K_VOLATILE:
865 872 case CTF_K_CONST:
866 873 case CTF_K_RESTRICT:
867 874 break;
868 875 default:
869 876 ctfdump_fatal("encountered unknown kind for type %s: %d\n",
870 877 name, kind);
871 878 break;
872 879 }
873 880 }
874 881
875 882 static int
876 883 ctfsrc_collect_objects_cb(const char *name, ctf_id_t id,
877 884 ulong_t symidx, void *arg)
878 885 {
879 886 size_t *count = arg;
880 887
881 888 /* local static vars can have an unknown ID */
882 889 if (id == 0)
883 890 return (0);
884 891
885 892 (void) strlcpy(idnames[*count].ci_name, name,
886 893 sizeof (idnames[*count].ci_name));
887 894 idnames[*count].ci_id = id;
888 895 idnames[*count].ci_symidx = symidx;
889 896 *count = *count + 1;
890 897 return (0);
891 898 }
892 899
893 900 static void
894 901 ctfsrc_object(ctf_id_t id, const char *name)
895 902 {
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
896 903 char tname[MAX_NAMELEN];
897 904
898 905 if (ctf_type_cname(g_fp, id, tname, sizeof (tname), name) == NULL) {
899 906 if (ctf_errno(g_fp) != ECTF_NOPARENT) {
900 907 ctfdump_fatal("type %ld missing name: %s\n", id,
901 908 ctf_errmsg(ctf_errno(g_fp)));
902 909 }
903 910 (void) snprintf(tname, sizeof (tname), "unknown_t %s", name);
904 911 }
905 912
906 - (void) printf("extern %s;\n", tname);
913 + printf("extern %s;\n", tname);
907 914 }
908 915
909 916 static int
910 917 ctfsrc_collect_functions_cb(const char *name, ulong_t symidx,
911 918 ctf_funcinfo_t *ctc, void *arg)
912 919 {
913 920 size_t *count = arg;
914 921
915 922 (void) strlcpy(idnames[*count].ci_name, name,
916 923 sizeof (idnames[*count].ci_name));
917 924 bcopy(ctc, &idnames[*count].ci_funcinfo, sizeof (*ctc));
918 925 idnames[*count].ci_id = 0;
919 926 idnames[*count].ci_symidx = symidx;
920 927 *count = *count + 1;
921 928 return (0);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
922 929 }
923 930
924 931 static void
925 932 ctfsrc_function(ctf_idname_t *idn)
926 933 {
927 934 ctf_funcinfo_t *cfi = &idn->ci_funcinfo;
928 935 char name[MAX_NAMELEN] = "unknown_t";
929 936
930 937 (void) ctf_type_name(g_fp, cfi->ctc_return, name, sizeof (name));
931 938
932 - (void) printf("extern %s %s(", name, idn->ci_name);
939 + printf("extern %s %s(", name, idn->ci_name);
933 940
934 941 if (cfi->ctc_argc != 0) {
935 942 ctfdump_fargs_grow(cfi->ctc_argc);
936 943 if (ctf_func_args(g_fp, idn->ci_symidx,
937 944 g_nfargc, g_fargc) == CTF_ERR) {
938 945 ctfdump_fatal("failed to get arguments for function "
939 946 "%s: %s\n", idn->ci_name,
940 947 ctf_errmsg(ctf_errno(g_fp)));
941 948 }
942 949
943 950 for (size_t i = 0; i < cfi->ctc_argc; i++) {
944 951 ctf_id_t aid = g_fargc[i];
945 952
946 - name[0] = '\0';
953 + (void) strlcpy(name, "unknown_t", sizeof (name));
947 954
948 955 (void) ctf_type_name(g_fp, aid, name, sizeof (name));
949 956
950 - (void) printf("%s%s", name,
957 + printf("%s%s", name,
951 958 i + 1 == cfi->ctc_argc ? "" : ", ");
952 959 }
953 960 } else {
954 961 if (!(cfi->ctc_flags & CTF_FUNC_VARARG))
955 - (void) printf("void");
962 + printf("void");
956 963 }
957 964
958 965 if (cfi->ctc_flags & CTF_FUNC_VARARG)
959 - (void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", ");
966 + printf("%s...", cfi->ctc_argc == 0 ? "" : ", ");
960 967
961 - (void) printf(");\n");
968 + printf(");\n");
962 969 }
963 970
964 971 static int
965 972 idname_compare(const void *lhs, const void *rhs)
966 973 {
967 974 return (strcmp(((ctf_idname_t *)lhs)->ci_name,
968 975 ((ctf_idname_t *)rhs)->ci_name));
969 976 }
970 977
971 978 static void
972 979 ctfdump_source(void)
973 980 {
974 981 ulong_t nr_syms = ctf_nr_syms(g_fp);
975 982 ctf_id_t max_id = ctf_max_id(g_fp);
976 983 size_t count = 0;
977 984
978 - (void) printf("/* Types */\n\n");
985 + printf("/* Types */\n\n");
979 986
980 987 if ((idnames = calloc(max_id + 1, sizeof (idnames[0]))) == NULL) {
981 988 ctfdump_fatal("failed to alloc idnames: %s\n",
982 989 strerror(errno));
983 990 }
984 991
992 + /*
993 + * Prep for any unknown types (most likely, they exist in the parent,
994 + * but we weren't given the -p option).
995 + */
996 + for (size_t i = 0; i <= max_id; i++) {
997 + (void) strlcpy(idnames[i].ci_name, "unknown_t",
998 + sizeof (idnames[i].ci_name));
999 + }
1000 +
985 1001 if (ctf_type_iter(g_fp, B_TRUE, ctfsrc_collect_types_cb,
986 1002 idnames) == CTF_ERR) {
987 1003 warnx("failed to collect types: %s",
988 1004 ctf_errmsg(ctf_errno(g_fp)));
989 1005 g_exit = 1;
990 1006 }
991 1007
992 1008 qsort(idnames, max_id, sizeof (ctf_idname_t), idname_compare);
993 1009
994 - for (size_t i = 0; i < max_id; i++) {
1010 + for (size_t i = 0; i <= max_id; i++) {
995 1011 if (idnames[i].ci_id != 0)
996 1012 ctfsrc_type(idnames[i].ci_id, idnames[i].ci_name);
997 1013 }
998 1014
999 1015 free(idnames);
1000 1016
1001 - (void) printf("\n\n/* Data Objects */\n\n");
1017 + printf("\n\n/* Data Objects */\n\n");
1002 1018
1003 1019 if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
1004 1020 ctfdump_fatal("failed to alloc idnames: %s\n",
1005 1021 strerror(errno));
1006 1022 }
1007 1023
1008 1024 if (ctf_object_iter(g_fp, ctfsrc_collect_objects_cb,
1009 1025 &count) == CTF_ERR) {
1010 1026 warnx("failed to collect objects: %s",
1011 1027 ctf_errmsg(ctf_errno(g_fp)));
1012 1028 g_exit = 1;
1013 1029 }
1014 1030
1015 1031 qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);
1016 1032
1017 1033 for (size_t i = 0; i < count; i++)
1018 1034 ctfsrc_object(idnames[i].ci_id, idnames[i].ci_name);
1019 1035
1020 1036 free(idnames);
1021 1037
1022 - (void) printf("\n\n/* Functions */\n\n");
1038 + printf("\n\n/* Functions */\n\n");
1023 1039
1024 1040 if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
1025 1041 ctfdump_fatal("failed to alloc idnames: %s\n",
1026 1042 strerror(errno));
1027 1043 }
1028 1044
1029 1045 count = 0;
1030 1046
1031 1047 if (ctf_function_iter(g_fp, ctfsrc_collect_functions_cb,
1032 1048 &count) == CTF_ERR) {
1033 1049 warnx("failed to collect functions: %s",
1034 1050 ctf_errmsg(ctf_errno(g_fp)));
1035 1051 g_exit = 1;
1036 1052 }
1037 1053
1038 1054 qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);
1039 1055
1040 1056 for (size_t i = 0; i < count; i++)
1041 1057 ctfsrc_function(&idnames[i]);
1042 1058
1043 1059 free(idnames);
1044 1060 }
1045 1061
1046 1062 static void
1047 1063 ctfdump_output(const char *out)
1048 1064 {
1049 1065 int fd, ret;
1050 1066 const void *data;
1051 1067 size_t len;
1052 1068
1053 1069 ctf_dataptr(g_fp, &data, &len);
1054 1070 if ((fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
1055 1071 ctfdump_fatal("failed to open output file %s: %s\n", out,
1056 1072 strerror(errno));
1057 1073
1058 1074 while (len > 0) {
1059 1075 ret = write(fd, data, len);
1060 1076 if (ret == -1 && errno == EINTR)
1061 1077 continue;
1062 1078 else if (ret == -1 && (errno == EFAULT || errno == EBADF))
1063 1079 abort();
1064 1080 else if (ret == -1)
1065 1081 ctfdump_fatal("failed to write to %s: %s\n", out,
1066 1082 strerror(errno));
1067 1083 data = ((char *)data) + ret;
1068 1084 len -= ret;
1069 1085 }
1070 1086
1071 1087 do {
1072 1088 ret = close(fd);
1073 1089 } while (ret == -1 && errno == EINTR);
1074 1090 if (ret != 0 && errno == EBADF)
1075 1091 abort();
1076 1092 if (ret != 0)
1077 1093 ctfdump_fatal("failed to close %s: %s\n", out, strerror(errno));
1078 1094 }
1079 1095
1080 1096 int
1081 1097 main(int argc, char *argv[])
1082 1098 {
1083 1099 int c, fd, err;
1084 1100 const char *ufile = NULL, *parent = NULL;
1085 1101
1086 1102 g_progname = basename(argv[0]);
1087 1103 while ((c = getopt(argc, argv, ":cdfhlp:sStu:")) != -1) {
1088 1104 switch (c) {
1089 1105 case 'c':
1090 1106 g_dump |= CTFDUMP_SOURCE;
1091 1107 break;
1092 1108 case 'd':
1093 1109 g_dump |= CTFDUMP_OBJECTS;
1094 1110 break;
1095 1111 case 'f':
1096 1112 g_dump |= CTFDUMP_FUNCTIONS;
1097 1113 break;
1098 1114 case 'h':
1099 1115 g_dump |= CTFDUMP_HEADER;
1100 1116 break;
1101 1117 case 'l':
1102 1118 g_dump |= CTFDUMP_LABELS;
1103 1119 break;
1104 1120 case 'p':
1105 1121 parent = optarg;
1106 1122 break;
1107 1123 case 's':
1108 1124 g_dump |= CTFDUMP_STRINGS;
1109 1125 break;
1110 1126 case 'S':
1111 1127 g_dump |= CTFDUMP_STATS;
1112 1128 break;
1113 1129 case 't':
1114 1130 g_dump |= CTFDUMP_TYPES;
1115 1131 break;
1116 1132 case 'u':
1117 1133 g_dump |= CTFDUMP_OUTPUT;
1118 1134 ufile = optarg;
1119 1135 break;
1120 1136 case '?':
1121 1137 ctfdump_usage("Unknown option: -%c\n", optopt);
1122 1138 return (2);
1123 1139 case ':':
1124 1140 ctfdump_usage("Option -%c requires an operand\n",
1125 1141 optopt);
1126 1142 return (2);
1127 1143 }
1128 1144 }
1129 1145
1130 1146 argc -= optind;
1131 1147 argv += optind;
1132 1148
1133 1149 if ((g_dump & CTFDUMP_SOURCE) && !!(g_dump & ~CTFDUMP_SOURCE)) {
1134 1150 ctfdump_usage("-c must be specified on its own\n");
1135 1151 return (2);
1136 1152 }
1137 1153
1138 1154 /*
1139 1155 * Dump all information except C source by default.
1140 1156 */
1141 1157 if (g_dump == 0)
1142 1158 g_dump = CTFDUMP_DEFAULT;
1143 1159
1144 1160 if (argc != 1) {
1145 1161 ctfdump_usage("no file to dump\n");
1146 1162 return (2);
1147 1163 }
1148 1164
1149 1165 if ((fd = open(argv[0], O_RDONLY)) < 0)
1150 1166 ctfdump_fatal("failed to open file %s: %s\n", argv[0],
1151 1167 strerror(errno));
1152 1168
1153 1169 g_fp = ctf_fdopen(fd, &err);
1154 1170 if (g_fp == NULL)
1155 1171 ctfdump_fatal("failed to open file %s: %s\n", argv[0],
1156 1172 ctf_errmsg(err));
1157 1173
1158 1174 /*
1159 1175 * Check to see if this file needs a parent. If it does not and we were
1160 1176 * given one, that should be an error. If it does need one and the
1161 1177 * parent is not specified, that is fine, we just won't know how to
1162 1178 * find child types. If we are given a parent, check at least that the
1163 1179 * labels match.
1164 1180 */
1165 1181 if (ctf_parent_name(g_fp) == NULL) {
1166 1182 if (parent != NULL)
1167 1183 ctfdump_fatal("cannot use %s as a parent file, %s is "
1168 1184 "not a child\n", parent, argv[0]);
1169 1185 } else if (parent != NULL) {
1170 1186 const char *explabel, *label;
1171 1187 ctf_file_t *pfp = ctf_open(parent, &err);
1172 1188
1173 1189 if (pfp == NULL)
1174 1190 ctfdump_fatal("failed to open parent file %s: %s\n",
1175 1191 parent, ctf_errmsg(err));
1176 1192
1177 1193 /*
1178 1194 * Before we import the parent into the child, check that the
1179 1195 * labels match. While there is also the notion of the parent
1180 1196 * name, it's less straightforward to match that. Require that
1181 1197 * labels match.
1182 1198 */
1183 1199 explabel = ctf_parent_label(g_fp);
1184 1200 label = ctf_label_topmost(pfp);
1185 1201 if (explabel == NULL || label == NULL ||
1186 1202 strcmp(explabel, label) != 0) {
1187 1203 if (label == NULL)
1188 1204 label = "<missing>";
↓ open down ↓ |
156 lines elided |
↑ open up ↑ |
1189 1205 if (explabel == NULL)
1190 1206 explabel = "<missing>";
1191 1207 ctfdump_fatal("label mismatch between parent %s and "
1192 1208 "child %s, parent has %s, child expects %s\n",
1193 1209 parent, argv[0], label, explabel);
1194 1210 }
1195 1211
1196 1212 if (ctf_import(g_fp, pfp) != 0)
1197 1213 ctfdump_fatal("failed to import parent %s: %s\n",
1198 1214 parent, ctf_errmsg(ctf_errno(g_fp)));
1215 + } else {
1216 + if (g_dump & CTFDUMP_SOURCE) {
1217 + printf("/* Warning: parent \"%s\" not supplied: many "
1218 + "types will be unknown. */\n\n",
1219 + ctf_parent_name(g_fp));
1220 + } else {
1221 + fprintf(stderr, "warning: parent \"%s\" not supplied: "
1222 + "many types will be unknown\n\n",
1223 + ctf_parent_name(g_fp));
1224 + }
1199 1225 }
1200 1226
1201 1227 if (g_dump & CTFDUMP_SOURCE) {
1202 1228 ctfdump_source();
1203 1229 return (0);
1204 1230 }
1205 1231
1206 1232 /*
1207 1233 * If stats is set, we must run through everything exect CTFDUMP_OUTPUT.
1208 1234 * We also do CTFDUMP_STATS last as a result.
1209 1235 */
1210 1236 if (g_dump & CTFDUMP_HEADER)
1211 1237 ctfdump_header();
1212 1238
1213 1239 if (g_dump & (CTFDUMP_LABELS | CTFDUMP_STATS))
1214 1240 ctfdump_labels();
1215 1241
1216 1242 if (g_dump & (CTFDUMP_OBJECTS | CTFDUMP_STATS))
1217 1243 ctfdump_objects();
1218 1244
1219 1245 if (g_dump & (CTFDUMP_FUNCTIONS | CTFDUMP_STATS))
1220 1246 ctfdump_functions();
1221 1247
1222 1248 if (g_dump & (CTFDUMP_TYPES | CTFDUMP_STATS))
1223 1249 ctfdump_types();
1224 1250
1225 1251 if (g_dump & (CTFDUMP_STRINGS | CTFDUMP_STATS))
1226 1252 ctfdump_strings();
1227 1253
1228 1254 if (g_dump & CTFDUMP_STATS)
1229 1255 ctfdump_stats();
1230 1256
1231 1257 if (g_dump & CTFDUMP_OUTPUT)
1232 1258 ctfdump_output(ufile);
1233 1259
1234 1260 return (g_exit);
1235 1261 }
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX