1/* 2 * CDDL HEADER START 3 * 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. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "@(#)dump.c 1.12 05/06/08 SMI" 28 29#if !defined(__APPLE__) 30#include <sys/types.h> 31#include <sys/sysmacros.h> 32#include <sys/stat.h> 33#include <sys/mman.h> 34#else 35#include <sys/types.h> 36//#include <sys/sysmacros.h> 37#include <sys/stat.h> 38#include <sys/mman.h> 39 40#include "darwin_shim.h" 41#include <mach-o/loader.h> 42#include <mach-o/nlist.h> 43#include <mach-o/stab.h> 44 45int debug_level; 46const char *progname = "ctfdump"; 47#endif /* __APPLE__ */ 48 49#include <strings.h> 50#include <unistd.h> 51#include <stdlib.h> 52#include <stdio.h> 53#include <fcntl.h> 54#include <gelf.h> 55#include <zlib.h> 56 57#include "ctf_headers.h" 58#include "strtab.h" 59#include "ctftools.h" 60#include "utils.h" 61#include "symbol.h" 62 63#ifdef __APPLE__ 64extern caddr_t write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp); 65extern caddr_t write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp); 66struct ctf_buf { 67 strtab_t ctb_strtab; /* string table */ 68 caddr_t ctb_base; /* pointer to base of buffer */ 69 caddr_t ctb_end; /* pointer to end of buffer */ 70 caddr_t ctb_ptr; /* pointer to empty buffer space */ 71 size_t ctb_size; /* size of buffer */ 72 int nptent; /* number of processed types */ 73 int ntholes; /* number of type holes */ 74}; 75 76void write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname, caddr_t ctfdata, size_t ctfsize, int flags); 77 78#endif /* __APPLE__ */ 79 80#define WARN(x) { warn(x); return (E_ERROR); } 81 82/* 83 * Flags that indicate what data is to be displayed. An explicit `all' value is 84 * provided to allow the code to distinguish between a request for everything 85 * (currently requested by invoking ctfdump without flags) and individual 86 * requests for all of the types of data (an invocation with all flags). In the 87 * former case, we want to be able to implicitly adjust the definition of `all' 88 * based on the CTF version of the file being dumped. For example, if a v2 file 89 * is being dumped, `all' includes F_LABEL - a request to dump the label 90 * section. If a v1 file is being dumped, `all' does not include F_LABEL, 91 * because v1 CTF doesn't support labels. We need to be able to distinguish 92 * between `ctfdump foo', which has an implicit request for labels if `foo' 93 * supports them, and `ctfdump -l foo', which has an explicity request. In the 94 * latter case, we exit with an error if `foo' is a v1 CTF file. 95 */ 96static enum { 97 F_DATA = 0x01, /* show data object section */ 98 F_FUNC = 0x02, /* show function section */ 99 F_HDR = 0x04, /* show header */ 100 F_STR = 0x08, /* show string table */ 101 F_TYPES = 0x10, /* show type section */ 102 F_STATS = 0x20, /* show statistics */ 103 F_LABEL = 0x40, /* show label section */ 104 F_ALL = 0x80, /* explicit request for `all' */ 105 F_ALLMSK = 0xff /* show all sections and statistics */ 106} flags = 0; 107 108static struct { 109 ulong_t s_ndata; /* total number of data objects */ 110 ulong_t s_nfunc; /* total number of functions */ 111 ulong_t s_nargs; /* total number of function arguments */ 112 ulong_t s_argmax; /* longest argument list */ 113 ulong_t s_ntypes; /* total number of types */ 114 ulong_t s_types[16]; /* number of types by kind */ 115 ulong_t s_nsmem; /* total number of struct members */ 116 ulong_t s_nsbytes; /* total size of all structs */ 117 ulong_t s_smmax; /* largest struct in terms of members */ 118 ulong_t s_sbmax; /* largest struct in terms of bytes */ 119 ulong_t s_numem; /* total number of union members */ 120 ulong_t s_nubytes; /* total size of all unions */ 121 ulong_t s_ummax; /* largest union in terms of members */ 122 ulong_t s_ubmax; /* largest union in terms of bytes */ 123 ulong_t s_nemem; /* total number of enum members */ 124 ulong_t s_emmax; /* largest enum in terms of members */ 125 ulong_t s_nstr; /* total number of strings */ 126 size_t s_strlen; /* total length of all strings */ 127 size_t s_strmax; /* longest string length */ 128} stats; 129 130typedef struct ctf_data { 131 caddr_t cd_ctfdata; /* Pointer to the CTF data */ 132 size_t cd_ctflen; /* Length of CTF data */ 133 134 /* 135 * cd_symdata will be non-NULL if the CTF data is being retrieved from 136 * an ELF file with a symbol table. cd_strdata and cd_nsyms should be 137 * used only if cd_symdata is non-NULL. 138 */ 139 Elf_Data *cd_symdata; /* Symbol table */ 140 Elf_Data *cd_strdata; /* Symbol table strings */ 141 int cd_nsyms; /* Number of symbol table entries */ 142#if defined (__APPLE__) 143 Elf32_Word sh_link; 144#endif /* __APPLE__ */ 145} ctf_data_t; 146 147static const char * 148ref_to_str(uint_t name, const ctf_header_t *hp, const ctf_data_t *cd) 149{ 150 size_t offset = CTF_NAME_OFFSET(name); 151 const char *s = cd->cd_ctfdata + hp->cth_stroff + offset; 152 153 if (CTF_NAME_STID(name) != CTF_STRTAB_0) 154 return ("<< ??? - name in external strtab >>"); 155 156 if (offset >= hp->cth_strlen) 157 return ("<< ??? - name exceeds strlab len >>"); 158 159 if (hp->cth_stroff + offset >= cd->cd_ctflen) 160 return ("<< ??? - file truncated >>"); 161 162 if (s[0] == '\0') 163 return ("(anon)"); 164 165 return (s); 166} 167 168static const char * 169int_encoding_to_str(uint_t encoding) 170{ 171 static char buf[32]; 172 173 if (encoding == 0 || (encoding & ~(CTF_INT_SIGNED | CTF_INT_CHAR | 174 CTF_INT_BOOL | CTF_INT_VARARGS)) != 0) 175 (void) snprintf(buf, sizeof (buf), " 0x%x", encoding); 176 else { 177 buf[0] = '\0'; 178 if (encoding & CTF_INT_SIGNED) 179 (void) strcat(buf, " SIGNED"); 180 if (encoding & CTF_INT_CHAR) 181 (void) strcat(buf, " CHAR"); 182 if (encoding & CTF_INT_BOOL) 183 (void) strcat(buf, " BOOL"); 184 if (encoding & CTF_INT_VARARGS) 185 (void) strcat(buf, " VARARGS"); 186 } 187 188 return (buf + 1); 189} 190 191static const char * 192fp_encoding_to_str(uint_t encoding) 193{ 194 static const char *const encs[] = { 195 NULL, "SINGLE", "DOUBLE", "COMPLEX", "DCOMPLEX", "LDCOMPLEX", 196 "LDOUBLE", "INTERVAL", "DINTERVAL", "LDINTERVAL", "IMAGINARY", 197 "DIMAGINARY", "LDIMAGINARY" 198 }; 199 200 static char buf[16]; 201 202 if (encoding < 1 || encoding >= (sizeof (encs) / sizeof (char *))) { 203 (void) snprintf(buf, sizeof (buf), "%u", encoding); 204 return (buf); 205 } 206 207 return (encs[encoding]); 208} 209 210static void 211print_line(const char *s) 212{ 213 static const char line[] = "----------------------------------------" 214 "----------------------------------------"; 215 (void) printf("\n%s%.*s\n\n", s, (int)(78 - strlen(s)), line); 216} 217 218static int 219print_header(const ctf_header_t *hp, const ctf_data_t *cd) 220{ 221 print_line("- CTF Header "); 222 223 (void) printf(" cth_magic = 0x%04x\n", hp->cth_magic); 224 (void) printf(" cth_version = %u\n", hp->cth_version); 225 (void) printf(" cth_flags = 0x%02x\n", hp->cth_flags); 226 (void) printf(" cth_parlabel = %s\n", 227 ref_to_str(hp->cth_parlabel, hp, cd)); 228 (void) printf(" cth_parname = %s\n", 229 ref_to_str(hp->cth_parname, hp, cd)); 230 (void) printf(" cth_lbloff = %u\n", hp->cth_lbloff); 231 (void) printf(" cth_objtoff = %u\n", hp->cth_objtoff); 232 (void) printf(" cth_funcoff = %u\n", hp->cth_funcoff); 233 (void) printf(" cth_typeoff = %u\n", hp->cth_typeoff); 234 (void) printf(" cth_stroff = %u\n", hp->cth_stroff); 235 (void) printf(" cth_strlen = %u\n", hp->cth_strlen); 236 237 return (E_SUCCESS); 238} 239 240static int 241print_labeltable(const ctf_header_t *hp, const ctf_data_t *cd) 242{ 243 /* LINTED - pointer alignment */ 244 const ctf_lblent_t *ctl = (ctf_lblent_t *)(cd->cd_ctfdata + 245 hp->cth_lbloff); 246 ulong_t i, n = (hp->cth_objtoff - hp->cth_lbloff) / sizeof (*ctl); 247 248 print_line("- Label Table "); 249 250 if (hp->cth_lbloff & 3) 251 WARN("cth_lbloff is not aligned properly\n"); 252 if (hp->cth_lbloff >= cd->cd_ctflen) 253 WARN("file is truncated or cth_lbloff is corrupt\n"); 254 if (hp->cth_objtoff >= cd->cd_ctflen) 255 WARN("file is truncated or cth_objtoff is corrupt\n"); 256 if (hp->cth_lbloff > hp->cth_objtoff) 257 WARN("file is corrupt -- cth_lbloff > cth_objtoff\n"); 258 259 for (i = 0; i < n; i++, ctl++) { 260 (void) printf(" %5u %s\n", ctl->ctl_typeidx, 261 ref_to_str(ctl->ctl_label, hp, cd)); 262 } 263 264 return (E_SUCCESS); 265} 266 267#if defined(__APPLE__) 268static GElf_Sym * 269gelf_getsym_macho(Elf_Data * data, int ndx, GElf_Sym * sym, const char *base) 270{ 271 const struct nlist *nsym = (const struct nlist *)(data->d_buf); 272 const char *name; 273 char *tmp; 274 275 nsym += ndx; 276 name = base + nsym->n_un.n_strx; 277 278 if (0 == nsym->n_un.n_strx) // iff a null, "", name. 279 name = "null name"; // return NULL; 280 281 if ('_' == name[0]) 282 name++; // Lop off omnipresent underscore to match DWARF convention 283 284 sym->st_name = (GElf_Sxword)(name - base); 285 sym->st_value = nsym->n_value; 286 sym->st_size = 0; 287 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE)); 288 sym->st_other = 0; 289 sym->st_shndx = SHN_MACHO; /* Mark underlying file as Mach-o */ 290 291 if (nsym->n_type & N_STAB) { /* Detect C++ methods */ 292 293 switch(nsym->n_type) { 294 case N_FUN: 295 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC)); 296 break; 297 case N_GSYM: 298 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); 299 break; 300 default: 301 break; 302 } 303 304 } else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) || 305 (N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) { 306 307 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (nsym->n_desc)); 308 } else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) && 309 nsym->n_sect == NO_SECT) { 310 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */ 311 } 312 313 return sym; 314} 315 316static GElf_Sym * 317gelf_getsym_macho_64(Elf_Data * data, int ndx, GElf_Sym * sym, const char *base) 318{ 319 const struct nlist_64 *nsym = (const struct nlist_64 *)(data->d_buf); 320 const char *name; 321 char *tmp; 322 323 nsym += ndx; 324 name = base + nsym->n_un.n_strx; 325 326 if (0 == nsym->n_un.n_strx) // iff a null, "", name. 327 name = "null name"; // return NULL; 328 329 if ('_' == name[0]) 330 name++; // Lop off omnipresent underscore to match DWARF convention 331 332 sym->st_name = (GElf_Sxword)(name - base); 333 sym->st_value = nsym->n_value; 334 sym->st_size = 0; 335 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE)); 336 sym->st_other = 0; 337 sym->st_shndx = SHN_MACHO_64; /* Mark underlying file as Mach-o */ 338 339 if (nsym->n_type & N_STAB) { /* Detect C++ methods */ 340 341 switch(nsym->n_type) { 342 case N_FUN: 343 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC)); 344 break; 345 case N_GSYM: 346 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); 347 break; 348 default: 349 break; 350 } 351 352 } else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) || 353 (N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) { 354 355 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (nsym->n_desc)); 356 } else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) && 357 nsym->n_sect == NO_SECT) { 358 sym->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */ 359 } 360 361 return sym; 362} 363#endif /* __APPLE__ */ 364 365/* 366 * Given the current symbol index (-1 to start at the beginning of the symbol 367 * table) and the type of symbol to match, this function returns the index of 368 * the next matching symbol (if any), and places the name of that symbol in 369 * *namep. If no symbol is found, -1 is returned. 370 */ 371static int 372next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype, 373 char **namep) 374{ 375 int i; 376 377 for (i = symidx + 1; i < cd->cd_nsyms; i++) { 378 GElf_Sym sym; 379 char *name; 380 int type; 381 382#if defined(__APPLE__) 383 if (cd->sh_link == SHN_MACHO) { /* Underlying file is Mach-o */ 384 if (gelf_getsym_macho(cd->cd_symdata, i, &sym, (const char *)(cd->cd_strdata->d_buf)) == 0) 385 return (-1); 386 } 387 else if (cd->sh_link == SHN_MACHO_64) { /* Underlying file is Mach-o 64 */ 388 if (gelf_getsym_macho_64(cd->cd_symdata, i, &sym, (const char *)(cd->cd_strdata->d_buf)) == 0) 389 return (-1); 390 } 391 else 392#endif /* __APPLE__ */ 393 if (gelf_getsym(cd->cd_symdata, i, &sym) == 0) 394 return (-1); 395 396 name = (char *)cd->cd_strdata->d_buf + sym.st_name; 397 type = GELF_ST_TYPE(sym.st_info); 398 399 /* 400 * Skip various types of symbol table entries. 401 */ 402 if (type != matchtype || ignore_symbol(&sym, name)) 403 continue; 404 405 /* Found one */ 406 *namep = name; 407 return (i); 408 } 409 410 return (-1); 411} 412 413static int 414read_data(const ctf_header_t *hp, const ctf_data_t *cd) 415{ 416 /* LINTED - pointer alignment */ 417 const ushort_t *idp = (ushort_t *)(cd->cd_ctfdata + hp->cth_objtoff); 418 ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / sizeof (ushort_t); 419 420 if (flags != F_STATS) 421 print_line("- Data Objects "); 422 423 if (hp->cth_objtoff & 1) 424 WARN("cth_objtoff is not aligned properly\n"); 425 if (hp->cth_objtoff >= cd->cd_ctflen) 426 WARN("file is truncated or cth_objtoff is corrupt\n"); 427 if (hp->cth_funcoff >= cd->cd_ctflen) 428 WARN("file is truncated or cth_funcoff is corrupt\n"); 429 if (hp->cth_objtoff > hp->cth_funcoff) 430 WARN("file is corrupt -- cth_objtoff > cth_funcoff\n"); 431 432 if (flags != F_STATS) { 433 int symidx, len, i; 434 char *name = NULL; 435 436 for (symidx = -1, i = 0; i < n; i++) { 437 int nextsym; 438 439 if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, 440 symidx, STT_OBJECT, &name)) < 0) 441 name = NULL; 442 else 443 symidx = nextsym; 444 445 len = printf(" [%u] %u", i, *idp++); 446 if (name != NULL) 447 (void) printf("%*s%s (%u)", (15 - len), "", 448 name, symidx); 449 (void) putchar('\n'); 450 } 451 } 452 453 stats.s_ndata = n; 454 return (E_SUCCESS); 455} 456 457static int 458read_funcs(const ctf_header_t *hp, const ctf_data_t *cd) 459{ 460 /* LINTED - pointer alignment */ 461 const ushort_t *fp = (ushort_t *)(cd->cd_ctfdata + hp->cth_funcoff); 462 463 /* LINTED - pointer alignment */ 464 const ushort_t *end = (ushort_t *)(cd->cd_ctfdata + hp->cth_typeoff); 465 466 ulong_t id; 467 int symidx; 468 469 if (flags != F_STATS) 470 print_line("- Functions "); 471 472 if (hp->cth_funcoff & 1) 473 WARN("cth_funcoff is not aligned properly\n"); 474 if (hp->cth_funcoff >= cd->cd_ctflen) 475 WARN("file is truncated or cth_funcoff is corrupt\n"); 476 if (hp->cth_typeoff >= cd->cd_ctflen) 477 WARN("file is truncated or cth_typeoff is corrupt\n"); 478 if (hp->cth_funcoff > hp->cth_typeoff) 479 WARN("file is corrupt -- cth_funcoff > cth_typeoff\n"); 480 481 for (symidx = -1, id = 0; fp < end; id++) { 482 ushort_t info = *fp++; 483 ushort_t kind = CTF_INFO_KIND(info); 484 ushort_t n = CTF_INFO_VLEN(info); 485 ushort_t i; 486 int nextsym; 487 char *name; 488 489 if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, symidx, 490 STT_FUNC, &name)) < 0) 491 name = NULL; 492 else 493 symidx = nextsym; 494 495 if (kind == CTF_K_UNKNOWN && n == 0) 496 continue; /* skip padding */ 497 498 if (kind != CTF_K_FUNCTION) { 499 (void) printf(" [%lu] unexpected kind -- %u\n", 500 id, kind); 501 return (E_ERROR); 502 } 503 504 if (fp + n > end) { 505 (void) printf(" [%lu] vlen %u extends past section " 506 "boundary\n", id, n); 507 return (E_ERROR); 508 } 509 510 if (flags != F_STATS) { 511 (void) printf(" [%lu] FUNC ", id); 512 if (name != NULL) 513 (void) printf("(%s) ", name); 514 (void) printf("returns: %u args: (", *fp++); 515 516 if (n != 0) { 517 (void) printf("%u", *fp++); 518 for (i = 1; i < n; i++) 519 (void) printf(", %u", *fp++); 520 } 521 522 (void) printf(")\n"); 523 } else 524 fp += n + 1; /* skip to next function definition */ 525 526 stats.s_nfunc++; 527 stats.s_nargs += n; 528 stats.s_argmax = MAX(stats.s_argmax, n); 529 } 530 531 return (E_SUCCESS); 532} 533 534static int 535read_types(const ctf_header_t *hp, const ctf_data_t *cd) 536{ 537 /* LINTED - pointer alignment */ 538 const ctf_type_t *tp = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_typeoff); 539 540 /* LINTED - pointer alignment */ 541 const ctf_type_t *end = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_stroff); 542 543 ulong_t id; 544 545 if (flags != F_STATS) 546 print_line("- Types "); 547 548 if (hp->cth_typeoff & 3) 549 WARN("cth_typeoff is not aligned properly\n"); 550 if (hp->cth_typeoff >= cd->cd_ctflen) 551 WARN("file is truncated or cth_typeoff is corrupt\n"); 552 if (hp->cth_stroff >= cd->cd_ctflen) 553 WARN("file is truncated or cth_stroff is corrupt\n"); 554 if (hp->cth_typeoff > hp->cth_stroff) 555 WARN("file is corrupt -- cth_typeoff > cth_stroff\n"); 556 557 id = 1; 558 if (hp->cth_parlabel || hp->cth_parname) 559 id += 1 << CTF_PARENT_SHIFT; 560 561 for (/* */; tp < end; id++) { 562 ulong_t i, n = CTF_INFO_VLEN(tp->ctt_info); 563 size_t size, increment, vlen = 0; 564 int kind = CTF_INFO_KIND(tp->ctt_info); 565 566 union { 567 const void *ptr; 568 const ctf_array_t *ap; 569 const ctf_member_t *mp; 570 const ctf_lmember_t *lmp; 571 const ctf_enum_t *ep; 572 const ushort_t *argp; 573 } u; 574 575 if (flags != F_STATS) { 576 (void) printf(" %c%lu%c ", 577 "[<"[CTF_INFO_ISROOT(tp->ctt_info)], id, 578 "]>"[CTF_INFO_ISROOT(tp->ctt_info)]); 579 } 580 581 if (tp->ctt_size == CTF_LSIZE_SENT) { 582 increment = sizeof (ctf_type_t); 583 size = (size_t)CTF_TYPE_LSIZE(tp); 584 } else { 585 increment = sizeof (ctf_stype_t); 586 size = tp->ctt_size; 587 } 588 u.ptr = (caddr_t)tp + increment; 589 590 switch (kind) { 591 case CTF_K_INTEGER: 592 if (flags != F_STATS) { 593 uint_t encoding = *((const uint_t *)u.ptr); 594 595 (void) printf("INTEGER %s encoding=%s offset=%u" 596 " bits=%u", ref_to_str(tp->ctt_name, hp, 597 cd), int_encoding_to_str( 598 CTF_INT_ENCODING(encoding)), 599 CTF_INT_OFFSET(encoding), 600 CTF_INT_BITS(encoding)); 601 } 602 vlen = sizeof (uint_t); 603 break; 604 605 case CTF_K_FLOAT: 606 if (flags != F_STATS) { 607 uint_t encoding = *((const uint_t *)u.ptr); 608 609 (void) printf("FLOAT %s encoding=%s offset=%u " 610 "bits=%u", ref_to_str(tp->ctt_name, hp, 611 cd), fp_encoding_to_str( 612 CTF_FP_ENCODING(encoding)), 613 CTF_FP_OFFSET(encoding), 614 CTF_FP_BITS(encoding)); 615 } 616 vlen = sizeof (uint_t); 617 break; 618 619 case CTF_K_POINTER: 620 if (flags != F_STATS) { 621 (void) printf("POINTER %s refers to %u", 622 ref_to_str(tp->ctt_name, hp, cd), 623 tp->ctt_type); 624 } 625 break; 626 627 case CTF_K_ARRAY: 628 if (flags != F_STATS) { 629 (void) printf("ARRAY %s content: %u index: %u " 630 "nelems: %u\n", ref_to_str(tp->ctt_name, 631 hp, cd), u.ap->cta_contents, 632 u.ap->cta_index, u.ap->cta_nelems); 633 } 634 vlen = sizeof (ctf_array_t); 635 break; 636 637 case CTF_K_FUNCTION: 638 if (flags != F_STATS) { 639 (void) printf("FUNCTION %s returns: %u args: (", 640 ref_to_str(tp->ctt_name, hp, cd), 641 tp->ctt_type); 642 643 if (n != 0) { 644 (void) printf("%u", *u.argp++); 645 for (i = 1; i < n; i++, u.argp++) 646 (void) printf(", %u", *u.argp); 647 } 648 649 (void) printf(")"); 650 } 651 652 vlen = sizeof (ushort_t) * (n + (n & 1)); 653 break; 654 655 case CTF_K_STRUCT: 656 case CTF_K_UNION: 657 if (kind == CTF_K_STRUCT) { 658 stats.s_nsmem += n; 659 stats.s_smmax = MAX(stats.s_smmax, n); 660 stats.s_nsbytes += size; 661 stats.s_sbmax = MAX(stats.s_sbmax, size); 662 663 if (flags != F_STATS) 664 (void) printf("STRUCT"); 665 } else { 666 stats.s_numem += n; 667 stats.s_ummax = MAX(stats.s_ummax, n); 668 stats.s_nubytes += size; 669 stats.s_ubmax = MAX(stats.s_ubmax, size); 670 671 if (flags != F_STATS) 672 (void) printf("UNION"); 673 } 674 675 if (flags != F_STATS) { 676 (void) printf(" %s (%d bytes)\n", 677 ref_to_str(tp->ctt_name, hp, cd), size); 678 679 if (size >= CTF_LSTRUCT_THRESH) { 680 for (i = 0; i < n; i++, u.lmp++) { 681 (void) printf( 682 "\t%s type=%u off=%llu\n", 683 ref_to_str(u.lmp->ctlm_name, 684 hp, cd), u.lmp->ctlm_type, 685 CTF_LMEM_OFFSET(u.lmp)); 686 } 687 } else { 688 for (i = 0; i < n; i++, u.mp++) { 689 (void) printf( 690 "\t%s type=%u off=%u\n", 691 ref_to_str(u.mp->ctm_name, 692 hp, cd), u.mp->ctm_type, 693 u.mp->ctm_offset); 694 } 695 } 696 } 697 698 vlen = n * (size >= CTF_LSTRUCT_THRESH ? 699 sizeof (ctf_lmember_t) : sizeof (ctf_member_t)); 700 break; 701 702 case CTF_K_ENUM: 703 if (flags != F_STATS) { 704 (void) printf("ENUM %s\n", 705 ref_to_str(tp->ctt_name, hp, cd)); 706 707 for (i = 0; i < n; i++, u.ep++) { 708 (void) printf("\t%s = %d\n", 709 ref_to_str(u.ep->cte_name, hp, cd), 710 u.ep->cte_value); 711 } 712 } 713 714 stats.s_nemem += n; 715 stats.s_emmax = MAX(stats.s_emmax, n); 716 717 vlen = sizeof (ctf_enum_t) * n; 718 break; 719 720 case CTF_K_FORWARD: 721 if (flags != F_STATS) { 722 (void) printf("FORWARD %s", 723 ref_to_str(tp->ctt_name, hp, cd)); 724 } 725 break; 726 727 case CTF_K_TYPEDEF: 728 if (flags != F_STATS) { 729 (void) printf("TYPEDEF %s refers to %u", 730 ref_to_str(tp->ctt_name, hp, cd), 731 tp->ctt_type); 732 } 733 break; 734 735 case CTF_K_VOLATILE: 736 if (flags != F_STATS) { 737 (void) printf("VOLATILE %s refers to %u", 738 ref_to_str(tp->ctt_name, hp, cd), 739 tp->ctt_type); 740 } 741 break; 742 743 case CTF_K_CONST: 744 if (flags != F_STATS) { 745 (void) printf("CONST %s refers to %u", 746 ref_to_str(tp->ctt_name, hp, cd), 747 tp->ctt_type); 748 } 749 break; 750 751 case CTF_K_RESTRICT: 752 if (flags != F_STATS) { 753 (void) printf("RESTRICT %s refers to %u", 754 ref_to_str(tp->ctt_name, hp, cd), 755 tp->ctt_type); 756 } 757 break; 758 759 case CTF_K_UNKNOWN: 760 break; /* hole in type id space */ 761 762 default: 763 (void) printf("unexpected kind %u\n", kind); 764 return (E_ERROR); 765 } 766 767 if (flags != F_STATS) 768 (void) printf("\n"); 769 770 stats.s_ntypes++; 771 stats.s_types[kind]++; 772 773 tp = (ctf_type_t *)((uintptr_t)tp + increment + vlen); 774 } 775 776 return (E_SUCCESS); 777} 778 779static int 780read_strtab(const ctf_header_t *hp, const ctf_data_t *cd) 781{ 782 size_t n, off, len = hp->cth_strlen; 783 const char *s = cd->cd_ctfdata + hp->cth_stroff; 784 785 if (flags != F_STATS) 786 print_line("- String Table "); 787 788 if (hp->cth_stroff >= cd->cd_ctflen) 789 WARN("file is truncated or cth_stroff is corrupt\n"); 790 if (hp->cth_stroff + hp->cth_strlen > cd->cd_ctflen) 791 WARN("file is truncated or cth_strlen is corrupt\n"); 792 793 for (off = 0; len != 0; off += n) { 794 if (flags != F_STATS) { 795 (void) printf(" [%lu] %s\n", (ulong_t)off, 796 s[0] == '\0' ? "\\0" : s); 797 } 798 n = strlen(s) + 1; 799 len -= n; 800 s += n; 801 802 stats.s_nstr++; 803 stats.s_strlen += n; 804 stats.s_strmax = MAX(stats.s_strmax, n); 805 } 806 807 return (E_SUCCESS); 808} 809 810/* 811 * Remove unwanted symbols from strtab: replace them with "- ". 812 */ 813static int 814clean_strtab(ctf_header_t *hp, ctf_data_t *cd, strtab_t *strtab, 815 char **syms, int nsyms) 816{ 817 size_t n, off, len = hp->cth_strlen; 818 char *s = cd->cd_ctfdata + hp->cth_stroff; 819 int i; 820 821 char buf[1024]; 822 buf[0] = '-'; 823 memset(buf + 1, ' ', 1023); 824 825 if (hp->cth_stroff >= cd->cd_ctflen) 826 WARN("file is truncated or cth_stroff is corrupt\n"); 827 if (hp->cth_stroff + hp->cth_strlen > cd->cd_ctflen) 828 WARN("file is truncated or cth_strlen is corrupt\n"); 829 830 for (off = 0; len != 0; off += n) { 831 for (i = 0; i < nsyms; i++) { 832 /* clean out offending string */ 833 if (!strcmp(s, syms[i])) 834 strncpy(s, buf, strlen(s)); 835 } 836 /* add all strings to fresh strtab */ 837 strtab_insert(strtab, s); 838 n = strlen(s) + 1; 839 len -= n; 840 s += n; 841 } 842 843 return 0; 844} 845 846/* 847 * Convert from one representation to another of the ctf buffer 848 */ 849static void 850ctf_data_to_ctf_buf(ctf_header_t *hp, ctf_data_t *cd, ctf_buf_t *cb) 851{ 852 /* create empty strtab (to be filled in clean_strtab) */ 853 strtab_create(&cb->ctb_strtab); 854 cb->ctb_base = cd->cd_ctfdata; 855 cb->ctb_end = cd->cd_ctfdata + hp->cth_stroff; 856 cb->ctb_ptr = cb->ctb_end; 857 cb->ctb_size = cd->cd_ctflen - hp->cth_strlen; 858 /* not used for our purposes */ 859 cb->nptent = 0; 860 cb->ntholes = 0; 861} 862 863/* 864 * Similar to write_ctf, but we don't have to reconstruct the whole CTF section 865 * from a tdata_t. 866 */ 867static int 868write_ctfdata(int srcfd, Elf *srcelf, const char *srcname, const char *dstname, ctf_header_t *hp, ctf_buf_t *buf) 869{ 870 struct stat st; 871 Elf *dstelf = NULL; 872 caddr_t data = NULL; 873 size_t len = 0; 874 int dstfd; 875 876 /* open + elf_begin destination file */ 877 fstat(srcfd, &st); 878 if ((dstfd = open(dstname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) 879 terminate("Cannot open temp file %s for writing", dstname); 880 if ((dstelf = elf_begin(dstfd, ELF_C_WRITE, NULL)) == NULL) 881 elfterminate(dstname, "Cannot write"); 882 883 /* write out and/or compress header & data buffer */ 884 if (hp->cth_flags & CTF_F_COMPRESS) { 885 data = write_compressed_buffer(hp, buf, &len); 886 } else { 887 data = write_buffer(hp, buf, &len); 888 /* 889 data = (caddr_t) xmalloc(sizeof(ctf_header_t) + cd->cd_ctflen); 890 bcopy(hp, data, sizeof(ctf_header_t)); 891 len += sizeof(ctf_header_t); 892 bcopy(cd->cd_ctfdata, data + len, cd->cd_ctflen); 893 len += cd->cd_ctflen; 894 */ 895 } 896 897 /* send the data to the destination file */ 898 write_file(srcelf, srcname, dstelf, dstname, data, len, 0); 899 900 free(data); 901 elf_end(dstelf); 902 (void) close(dstfd); 903 return 0; 904} 905 906static void 907long_stat(const char *name, ulong_t value) 908{ 909 (void) printf(" %-36s= %lu\n", name, value); 910} 911 912static void 913fp_stat(const char *name, float value) 914{ 915 (void) printf(" %-36s= %.2f\n", name, value); 916} 917 918static int 919print_stats(void) 920{ 921 print_line("- CTF Statistics "); 922 923 long_stat("total number of data objects", stats.s_ndata); 924 (void) printf("\n"); 925 926 long_stat("total number of functions", stats.s_nfunc); 927 long_stat("total number of function arguments", stats.s_nargs); 928 long_stat("maximum argument list length", stats.s_argmax); 929 930 if (stats.s_nfunc != 0) { 931 fp_stat("average argument list length", 932 (float)stats.s_nargs / (float)stats.s_nfunc); 933 } 934 935 (void) printf("\n"); 936 937 long_stat("total number of types", stats.s_ntypes); 938 long_stat("total number of integers", stats.s_types[CTF_K_INTEGER]); 939 long_stat("total number of floats", stats.s_types[CTF_K_FLOAT]); 940 long_stat("total number of pointers", stats.s_types[CTF_K_POINTER]); 941 long_stat("total number of arrays", stats.s_types[CTF_K_ARRAY]); 942 long_stat("total number of func types", stats.s_types[CTF_K_FUNCTION]); 943 long_stat("total number of structs", stats.s_types[CTF_K_STRUCT]); 944 long_stat("total number of unions", stats.s_types[CTF_K_UNION]); 945 long_stat("total number of enums", stats.s_types[CTF_K_ENUM]); 946 long_stat("total number of forward tags", stats.s_types[CTF_K_FORWARD]); 947 long_stat("total number of typedefs", stats.s_types[CTF_K_TYPEDEF]); 948 long_stat("total number of volatile types", 949 stats.s_types[CTF_K_VOLATILE]); 950 long_stat("total number of const types", stats.s_types[CTF_K_CONST]); 951 long_stat("total number of restrict types", 952 stats.s_types[CTF_K_RESTRICT]); 953 long_stat("total number of unknowns (holes)", 954 stats.s_types[CTF_K_UNKNOWN]); 955 956 (void) printf("\n"); 957 958 long_stat("total number of struct members", stats.s_nsmem); 959 long_stat("maximum number of struct members", stats.s_smmax); 960 long_stat("total size of all structs", stats.s_nsbytes); 961 long_stat("maximum size of a struct", stats.s_sbmax); 962 963 if (stats.s_types[CTF_K_STRUCT] != 0) { 964 fp_stat("average number of struct members", 965 (float)stats.s_nsmem / (float)stats.s_types[CTF_K_STRUCT]); 966 fp_stat("average size of a struct", (float)stats.s_nsbytes / 967 (float)stats.s_types[CTF_K_STRUCT]); 968 } 969 970 (void) printf("\n"); 971 972 long_stat("total number of union members", stats.s_numem); 973 long_stat("maximum number of union members", stats.s_ummax); 974 long_stat("total size of all unions", stats.s_nubytes); 975 long_stat("maximum size of a union", stats.s_ubmax); 976 977 if (stats.s_types[CTF_K_UNION] != 0) { 978 fp_stat("average number of union members", 979 (float)stats.s_numem / (float)stats.s_types[CTF_K_UNION]); 980 fp_stat("average size of a union", (float)stats.s_nubytes / 981 (float)stats.s_types[CTF_K_UNION]); 982 } 983 984 (void) printf("\n"); 985 986 long_stat("total number of enum members", stats.s_nemem); 987 long_stat("maximum number of enum members", stats.s_emmax); 988 989 if (stats.s_types[CTF_K_ENUM] != 0) { 990 fp_stat("average number of enum members", 991 (float)stats.s_nemem / (float)stats.s_types[CTF_K_ENUM]); 992 } 993 994 (void) printf("\n"); 995 996 long_stat("total number of unique strings", stats.s_nstr); 997 long_stat("bytes of string data", stats.s_strlen); 998 long_stat("maximum string length", stats.s_strmax); 999 1000 if (stats.s_nstr != 0) { 1001 fp_stat("average string length", 1002 (float)stats.s_strlen / (float)stats.s_nstr); 1003 } 1004 1005 (void) printf("\n"); 1006 return (E_SUCCESS); 1007} 1008 1009static int 1010print_usage(FILE *fp, int verbose) 1011{ 1012#if !defined(__APPLE__) 1013 (void) fprintf(fp, "Usage: %s [-dfhlsSt] [-u file] file\n", getpname()); 1014#else 1015 (void) fprintf(fp, "Usage: %s [-dfhlrsSt] [-u file] file\n", progname); 1016#endif /* __APPLE__ */ 1017 1018 if (verbose) { 1019 (void) fprintf(fp, 1020 "\t-d dump data object section\n" 1021 "\t-f dump function section\n" 1022 "\t-h dump file header\n" 1023 "\t-l dump label table\n" 1024#ifdef __APPLE__ 1025 "\t-r remove listed symbols from CTF data\n" 1026#endif /* __APPLE__ */ 1027 "\t-s dump string table\n" 1028 "\t-S dump statistics\n" 1029 "\t-t dump type section\n" 1030 "\t-u save uncompressed CTF to a file\n"); 1031 } 1032 1033 return (E_USAGE); 1034} 1035 1036static Elf_Scn * 1037findelfscn(Elf *elf, GElf_Ehdr *ehdr, char *secname) 1038{ 1039 GElf_Shdr shdr; 1040 Elf_Scn *scn; 1041 char *name; 1042 1043 for (scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; ) { 1044 if (gelf_getshdr(scn, &shdr) != NULL && (name = 1045 elf_strptr(elf, ehdr->e_shstrndx, shdr.sh_name)) != NULL && 1046 strcmp(name, secname) == 0) 1047 return (scn); 1048 } 1049 1050 return (NULL); 1051} 1052 1053int 1054main(int argc, char *argv[]) 1055{ 1056 const char *filename = NULL; 1057 const char *ufile = NULL; 1058 int error = 0, doclean = 0; 1059 int c, fd, ufd; 1060 1061 ctf_data_t cd; 1062 const ctf_preamble_t *pp; 1063 ctf_header_t *hp; 1064 Elf *elf; 1065 GElf_Ehdr ehdr; 1066 1067 (void) elf_version(EV_CURRENT); 1068 1069 for (opterr = 0; optind < argc; optind++) { 1070 while ((c = getopt(argc, argv, "dfhlrsStu:")) != (int)EOF) { 1071 switch (c) { 1072 case 'd': 1073 flags |= F_DATA; 1074 break; 1075 case 'f': 1076 flags |= F_FUNC; 1077 break; 1078 case 'h': 1079 flags |= F_HDR; 1080 break; 1081 case 'l': 1082 flags |= F_LABEL; 1083 break; 1084 case 'r': 1085 doclean = 1; 1086 goto skiploop; 1087 case 's': 1088 flags |= F_STR; 1089 break; 1090 case 'S': 1091 flags |= F_STATS; 1092 break; 1093 case 't': 1094 flags |= F_TYPES; 1095 break; 1096 case 'u': 1097 ufile = optarg; 1098 break; 1099 default: 1100 if (optopt == '?') 1101 return (print_usage(stdout, 1)); 1102 warn("illegal option -- %c\n", optopt); 1103 return (print_usage(stderr, 0)); 1104 } 1105 } 1106 1107 if (optind < argc) { 1108 if (filename != NULL) 1109 return (print_usage(stderr, 0)); 1110 filename = argv[optind]; 1111 } 1112 } 1113 1114skiploop: 1115 if (doclean) 1116 filename = argv[argc - 1]; 1117 1118 if (filename == NULL) 1119 return (print_usage(stderr, 0)); 1120 1121 if (flags == 0 && ufile == NULL) 1122 flags = F_ALLMSK; 1123 1124 if ((fd = open(filename, O_RDONLY)) == -1) 1125 die("failed to open %s", filename); 1126 1127 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) != NULL && 1128 gelf_getehdr(elf, &ehdr) != NULL) { 1129 1130 Elf_Data *dp; 1131 Elf_Scn *ctfscn = findelfscn(elf, &ehdr, ".SUNW_ctf"); 1132 Elf_Scn *symscn; 1133 GElf_Shdr ctfshdr; 1134 1135 if (ctfscn == NULL || (dp = elf_getdata(ctfscn, NULL)) == NULL) 1136 die("%s does not contain .SUNW_ctf data\n", filename); 1137 1138 cd.cd_ctfdata = dp->d_buf; 1139 cd.cd_ctflen = dp->d_size; 1140 1141 /* 1142 * If the sh_link field of the CTF section header is non-zero 1143 * it indicates which section contains the symbol table that 1144 * should be used. We default to the .symtab section if sh_link 1145 * is zero or if there's an error reading the section header. 1146 */ 1147#if !defined(__APPLE__) 1148 if (gelf_getshdr(ctfscn, &ctfshdr) != NULL && 1149 ctfshdr.sh_link != 0) { 1150 symscn = elf_getscn(elf, ctfshdr.sh_link); 1151 } else { 1152 symscn = findelfscn(elf, &ehdr, ".symtab"); 1153 } 1154#else 1155 if (gelf_getshdr(ctfscn, &ctfshdr) != NULL && 1156 ctfshdr.sh_link != 0 && ctfshdr.sh_link != SHN_MACHO && ctfshdr.sh_link != SHN_MACHO_64) { 1157 symscn = elf_getscn(elf, ctfshdr.sh_link); 1158 } else { 1159 symscn = findelfscn(elf, &ehdr, ".symtab"); 1160 } 1161#endif /* __APPLE__ */ 1162 1163 /* If we found a symbol table, find the corresponding strings */ 1164 if (symscn != NULL) { 1165 GElf_Shdr shdr; 1166 Elf_Scn *symstrscn; 1167 1168 if (gelf_getshdr(symscn, &shdr) != NULL) { 1169#if !defined(__APPLE__) 1170 symstrscn = elf_getscn(elf, shdr.sh_link); 1171 1172 cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; 1173 cd.cd_symdata = elf_getdata(symscn, NULL); 1174 cd.cd_strdata = elf_getdata(symstrscn, NULL); 1175#else 1176 if (SHN_MACHO == shdr.sh_link) { /* Underlying file is Mach-o */ 1177 int dir_idx; 1178 cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; 1179 cd.cd_symdata = elf_getdata(symscn, NULL); 1180 1181 if ((dir_idx = findelfsecidx(elf, filename, ".dir_str_table")) < 0 || 1182 (symstrscn = elf_getscn(elf, dir_idx)) == NULL || 1183 (cd.cd_strdata = elf_getdata(symstrscn, NULL)) == NULL) 1184 terminate("%s: Can't open direct string table\n", filename); 1185 1186 cd.sh_link = SHN_MACHO; /* Mark underlying file as Mach-o */ 1187 } else if (SHN_MACHO_64 == shdr.sh_link) { /* Underlying file is Mach-o 64 */ 1188 int dir_idx; 1189 cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; 1190 cd.cd_symdata = elf_getdata(symscn, NULL); 1191 1192 if ((dir_idx = findelfsecidx(elf, filename, ".dir_str_table")) < 0 || 1193 (symstrscn = elf_getscn(elf, dir_idx)) == NULL || 1194 (cd.cd_strdata = elf_getdata(symstrscn, NULL)) == NULL) 1195 terminate("%s: Can't open direct string table\n", filename); 1196 1197 cd.sh_link = SHN_MACHO_64; /* Mark underlying file as Mach-o 64 */ 1198 } else { 1199 symstrscn = elf_getscn(elf, shdr.sh_link); 1200 1201 cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; 1202 cd.cd_symdata = elf_getdata(symscn, NULL); 1203 cd.cd_strdata = elf_getdata(symstrscn, NULL); 1204 cd.sh_link = shdr.sh_link; 1205 } 1206#endif /* __APPLE__ */ 1207 } 1208 } 1209 } else { 1210 struct stat st; 1211 1212 if (fstat(fd, &st) == -1) 1213 die("failed to fstat %s", filename); 1214 1215 cd.cd_ctflen = st.st_size; 1216 cd.cd_ctfdata = mmap(NULL, cd.cd_ctflen, PROT_READ, 1217 MAP_PRIVATE, fd, 0); 1218 if (cd.cd_ctfdata == MAP_FAILED) 1219 die("failed to mmap %s", filename); 1220 } 1221 1222 /* 1223 * Get a pointer to the CTF data buffer and interpret the first portion 1224 * as a ctf_header_t. Validate the magic number and size. 1225 */ 1226 1227 if (cd.cd_ctflen < sizeof (ctf_preamble_t)) 1228 die("%s does not contain a CTF preamble\n", filename); 1229 1230 /* LINTED - pointer alignment */ 1231 pp = (const ctf_preamble_t *)cd.cd_ctfdata; 1232 1233 if (pp->ctp_magic != CTF_MAGIC) 1234 die("%s does not appear to contain CTF data\n", filename); 1235 1236 if (pp->ctp_version == CTF_VERSION) { 1237 /* LINTED - pointer alignment */ 1238 hp = (ctf_header_t *)cd.cd_ctfdata; 1239 cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t); 1240 1241 if (cd.cd_ctflen < sizeof (ctf_header_t)) { 1242 die("%s does not contain a v%d CTF header\n", filename, 1243 CTF_VERSION); 1244 } 1245 1246 } else { 1247 die("%s contains unsupported CTF version %d\n", filename, 1248 pp->ctp_version); 1249 } 1250 1251 /* 1252 * If the data buffer is compressed, then malloc a buffer large enough 1253 * to hold the decompressed data, and use zlib to decompress it. 1254 */ 1255 if (hp->cth_flags & CTF_F_COMPRESS) { 1256 z_stream zstr; 1257 void *buf; 1258 int rc; 1259 1260 if ((buf = malloc(hp->cth_stroff + hp->cth_strlen)) == NULL) 1261 die("failed to allocate decompression buffer"); 1262 1263 bzero(&zstr, sizeof (z_stream)); 1264 zstr.next_in = (void *)cd.cd_ctfdata; 1265 zstr.avail_in = cd.cd_ctflen; 1266 zstr.next_out = buf; 1267 zstr.avail_out = hp->cth_stroff + hp->cth_strlen; 1268 1269 if ((rc = inflateInit(&zstr)) != Z_OK) 1270 die("failed to initialize zlib: %s\n", zError(rc)); 1271 1272 if ((rc = inflate(&zstr, Z_FINISH)) != Z_STREAM_END) 1273 die("failed to decompress CTF data: %s\n", zError(rc)); 1274 1275 if ((rc = inflateEnd(&zstr)) != Z_OK) 1276 die("failed to finish decompression: %s\n", zError(rc)); 1277 1278 if (zstr.total_out != hp->cth_stroff + hp->cth_strlen) 1279 die("CTF data is corrupt -- short decompression\n"); 1280 1281 cd.cd_ctfdata = buf; 1282 cd.cd_ctflen = hp->cth_stroff + hp->cth_strlen; 1283 } 1284 1285#ifdef __APPLE__ 1286 if (doclean) { 1287 int nsyms = argc - 1 - optind; 1288 char **syms = &argv[optind]; 1289 char *tmpname = (char *)mktmpname(filename, ".ctf"); 1290 ctf_buf_t tmpbuf; 1291 1292 ctf_data_to_ctf_buf(hp, &cd, &tmpbuf); 1293 clean_strtab(hp, &cd, &tmpbuf.ctb_strtab, syms, nsyms); 1294 1295 write_ctfdata(fd, elf, filename, tmpname, hp, &tmpbuf); 1296 if (rename(tmpname, filename) != 0) { 1297 terminate("Couldn't rename temp file %s to %s", tmpname, 1298 filename); 1299 } 1300 free(tmpname); 1301 flags = 0; 1302 } 1303#endif /* __APPLE__ */ 1304 1305 if (flags & F_HDR) 1306 error |= print_header(hp, &cd); 1307 if (flags & (F_LABEL)) 1308 error |= print_labeltable(hp, &cd); 1309 if (flags & (F_DATA | F_STATS)) 1310 error |= read_data(hp, &cd); 1311 if (flags & (F_FUNC | F_STATS)) 1312 error |= read_funcs(hp, &cd); 1313 if (flags & (F_TYPES | F_STATS)) 1314 error |= read_types(hp, &cd); 1315 if (flags & (F_STR | F_STATS)) 1316 error |= read_strtab(hp, &cd); 1317 if (flags & F_STATS) 1318 error |= print_stats(); 1319 1320 /* 1321 * If the -u option is specified, write the uncompressed CTF data to a 1322 * raw CTF file. CTF data can already be extracted compressed by 1323 * applying elfdump -w -N .SUNW_ctf to an ELF file, so we don't bother. 1324 */ 1325 if (ufile != NULL) { 1326 ctf_header_t h; 1327 1328 bcopy(hp, &h, sizeof (h)); 1329 h.cth_flags &= ~CTF_F_COMPRESS; 1330 1331 if ((ufd = open(ufile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 || 1332 write(ufd, &h, sizeof (h)) != sizeof (h) || 1333 write(ufd, cd.cd_ctfdata, cd.cd_ctflen) != cd.cd_ctflen) { 1334 warn("failed to write CTF data to '%s'", ufile); 1335 error |= E_ERROR; 1336 } 1337 1338 (void) close(ufd); 1339 } 1340 1341 if (elf != NULL) 1342 (void) elf_end(elf); 1343 1344 (void) close(fd); 1345 return (error); 1346} 1347