Print this page
uts: Allow for address space randomisation.
Randomise the base addresses of shared objects, non-fixed mappings, the
stack and the heap. Introduce a service, svc:/system/process-security,
and a tool psecflags(1) to control and observe it
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/dump/common/dump.c
+++ new/usr/src/cmd/sgs/dump/common/dump.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1988 AT&T
24 24 * All Rights Reserved
25 25 *
26 26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 27 */
28 28
29 29 /* Get definitions for the relocation types supported. */
30 30 #define ELF_TARGET_ALL
31 31
32 32 #include <stdio.h>
33 33 #include <stdlib.h>
34 34 #include <locale.h>
35 35 #include <unistd.h>
36 36 #include <libelf.h>
37 37 #include <sys/link.h>
38 38 #include <sys/elf.h>
39 39 #include <sys/machelf.h>
40 40 #include <fcntl.h>
41 41 #include <sys/stat.h>
42 42 #include <errno.h>
43 43 #include <string.h>
44 44 #include "sgs.h"
45 45 #include "conv.h"
46 46 #include "dump.h"
47 47
48 48
49 49 #define OPTSTR "agcd:fhn:oprstvCLT:V?" /* option string for getopt() */
50 50
51 51 const char *UNKNOWN = "<unknown>";
52 52
53 53 static SCNTAB *p_symtab, *p_head_scns, *p_dynsym;
54 54
55 55 static int
56 56 x_flag = 0, /* option requires section header table */
57 57 z_flag = 0, /* process files within an archive */
58 58 rn_flag = 0; /* dump named relocation information */
59 59
60 60 static int
61 61 /* flags: ?_flag corresponds to ? option */
62 62 a_flag = 0, /* dump archive header of each member of archive */
63 63 g_flag = 0, /* dump archive symbol table */
64 64 c_flag = 0, /* dump the string table */
65 65 d_flag = 0, /* dump range of sections */
66 66 f_flag = 0, /* dump each file header */
67 67 h_flag = 0, /* dump section headers */
68 68 n_flag = 0, /* dump named section */
69 69 o_flag = 0, /* dump each program execution header */
70 70 r_flag = 0, /* dump relocation information */
71 71 s_flag = 0, /* dump section contents */
72 72 t_flag = 0, /* dump symbol table entries */
73 73 C_flag = 0, /* dump decoded C++ symbol names */
74 74 L_flag = 0, /* dump dynamic linking information */
75 75 T_flag = 0, /* dump symbol table range */
76 76 V_flag = 0; /* dump version information */
77 77
78 78 int p_flag = 0, /* suppress printing of headings */
79 79 v_flag = 0; /* print information in verbose form */
80 80
81 81 static int
82 82 d_low = 0, /* range for use with -d */
83 83 d_hi = 0,
84 84 d_num = 0;
85 85
86 86 static int
87 87 T_low = 0, /* range for use with -T */
88 88 T_hi = 0,
89 89 T_num = 0;
90 90
91 91 static char *name = NULL; /* for use with -n option */
92 92 char *prog_name;
93 93 static int errflag = 0;
94 94
95 95 static struct stab_list_s {
96 96 struct stab_list_s *next;
97 97 char *strings;
98 98 size_t size;
99 99 } *StringTableList = (void *)0;
100 100
101 101 extern void ar_sym_read();
102 102 extern void dump_exec_header();
103 103
104 104
105 105 /*
106 106 * Get the section descriptor and set the size of the
107 107 * data returned. Data is byte-order converted.
108 108 */
109 109 void *
110 110 get_scndata(Elf_Scn *fd_scn, size_t *size)
111 111 {
112 112 Elf_Data *p_data;
113 113
114 114 p_data = 0;
115 115 if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
116 116 p_data->d_size == 0) {
117 117 return (NULL);
118 118 }
119 119 *size = p_data->d_size;
120 120 return (p_data->d_buf);
121 121 }
122 122
123 123 /*
124 124 * Get the section descriptor and set the size of the
125 125 * data returned. Data is raw (i.e., not byte-order converted).
126 126 */
127 127 static void *
128 128 get_rawscn(Elf_Scn *fd_scn, size_t *size)
129 129 {
130 130 Elf_Data *p_data;
131 131
132 132 p_data = 0;
133 133 if ((p_data = elf_rawdata(fd_scn, p_data)) == 0 ||
134 134 p_data->d_size == 0) {
135 135 return (NULL);
136 136 }
137 137
138 138 *size = p_data->d_size;
139 139 return (p_data->d_buf);
140 140 }
141 141
142 142 /*
143 143 * Print out a usage message in short form when program is invoked
144 144 * with insufficient or no arguments, and in long form when given
145 145 * either a ? or an invalid option.
146 146 */
147 147 static void
148 148 usage()
149 149 {
150 150 (void) fprintf(stderr,
151 151 "Usage: %s [-%s] file(s) ...\n", prog_name, OPTSTR);
152 152 if (errflag) {
153 153 (void) fprintf(stderr,
154 154 "\t\t[-a dump archive header of each member of archive]\n\
155 155 [-g dump archive global symbol table]\n\
156 156 [-c dump the string table]\n\
157 157 [-d dump range of sections]\n\
158 158 [-f dump each file header]\n\
159 159 [-h dump section headers]\n\
160 160 [-n dump named section]\n\
161 161 [-o dump each program execution header]\n\
162 162 [-p suppress printing of headings]\n\
163 163 [-r dump relocation information]\n\
164 164 [-s dump section contents]\n\
165 165 [-t dump symbol table entries]\n\
166 166 [-v print information in verbose form]\n\
167 167 [-C dump decoded C++ symbol names]\n\
168 168 [-L dump the .dynamic structure]\n\
169 169 [-T dump symbol table range]\n\
170 170 [-V dump version information]\n");
171 171 }
172 172 }
173 173
174 174 /*
175 175 * Set a range. Input is a character string, a lower
176 176 * bound and an upper bound. This function converts
177 177 * a character string into its correct integer values,
178 178 * setting the first value as the lower bound, and
179 179 * the second value as the upper bound. If more values
180 180 * are given they are ignored with a warning.
181 181 */
182 182 static void
183 183 set_range(char *s, int *low, int *high)
184 184 {
185 185 char *w;
186 186 char *lasts;
187 187
188 188 while ((w = strtok_r(s, ",", &lasts)) != NULL) {
189 189 if (!(*low))
190 190 /* LINTED */
191 191 *low = (int)atol(w);
192 192 else
193 193 if (!(*high))
194 194 /* LINTED */
195 195 *high = (int)atol(w);
196 196 else {
197 197 (void) fprintf(stderr,
198 198 "%s: too many arguments - %s ignored\n",
199 199 prog_name, w);
200 200 return;
201 201 }
202 202 s = NULL;
203 203 } /* end while */
204 204 }
205 205
206 206
207 207 /*
208 208 * Print static shared library information.
209 209 */
210 210 static void
211 211 print_static(SCNTAB *l_scns, char *filename)
212 212 {
213 213 size_t section_size;
214 214 unsigned char *strtab;
215 215 unsigned char *path, buf[1024];
216 216 unsigned long *temp;
217 217 unsigned long total, topath;
218 218
219 219 (void) printf("\n **** STATIC SHARED LIBRARY INFORMATION ****\n");
220 220 (void) printf("\n%s:\n", filename);
221 221 (void) printf("\t");
222 222 section_size = 0;
223 223 if ((strtab = (unsigned char *)
224 224 get_scndata(l_scns->p_sd, §ion_size)) == NULL) {
225 225 return;
226 226 }
227 227
228 228 while (section_size != 0) {
229 229 /* LINTED */
230 230 temp = (unsigned long *)strtab;
231 231 total = temp[0];
232 232 topath = temp[1];
233 233 path = strtab + (topath*sizeof (long));
234 234 (void) strncpy((char *)buf, (char *)path,
235 235 (total - topath)*sizeof (long));
236 236 (void) fprintf(stdout, "%s\n", buf);
237 237 strtab += total*sizeof (long);
238 238 section_size -= (total*sizeof (long));
239 239 }
240 240 }
241 241
242 242 /*
243 243 * Print raw data in hexidecimal. Input is the section data to
244 244 * be printed out and the size of the data. Output is relative
245 245 * to a table lookup in dumpmap.h.
246 246 */
247 247 static void
248 248 print_rawdata(unsigned char *p_sec, size_t size)
249 249 {
250 250 size_t j;
251 251 size_t count;
252 252
253 253 count = 1;
254 254
255 255 (void) printf("\t");
256 256 for (j = size/sizeof (short); j != 0; --j, ++count) {
257 257 (void) printf("%.2x %.2x ", p_sec[0], p_sec[1]);
258 258 p_sec += 2;
259 259 if (count == 12) {
260 260 (void) printf("\n\t");
261 261 count = 0;
262 262 }
263 263 }
264 264
265 265 /*
266 266 * take care of last byte if odd byte section
267 267 */
268 268 if ((size & 0x1L) == 1L)
269 269 (void) printf("%.2x", *p_sec);
270 270 (void) printf("\n");
271 271 }
272 272
273 273
274 274
275 275 /*
276 276 * Print relocation data of type SHT_RELA
277 277 * If d_flag, print data corresponding only to
278 278 * the section or range of sections specified.
279 279 * If n_flag, print data corresponding only to
280 280 * the named section.
281 281 */
282 282 static void
283 283 print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
284 284 GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
285 285 SCNTAB *reloc_symtab)
286 286 {
287 287 GElf_Rela rela;
288 288 GElf_Sym sym;
289 289 size_t no_entries;
290 290 size_t rel_entsize;
291 291 size_t no_syms;
292 292 int type, symid;
293 293 static int n_title = 0;
294 294 int ndx = 0;
295 295 char *sym_name;
296 296 int adj = 0;
297 297
298 298 if (gelf_getclass(elf_file) == ELFCLASS64)
299 299 adj = 8;
300 300
301 301 rel_entsize = p_scns->p_shdr.sh_entsize;
302 302 if ((rel_entsize == 0) ||
303 303 (rel_entsize > p_scns->p_shdr.sh_size)) {
304 304 rel_entsize = gelf_fsize(elf_file, ELF_T_RELA, 1,
305 305 EV_CURRENT);
306 306 }
307 307 no_entries = reloc_size / rel_entsize;
308 308
309 309 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
310 310 while (no_entries--) {
311 311 (void) gelf_getrela(rdata, ndx, &rela);
312 312 /* LINTED */
313 313 type = (int)GELF_R_TYPE(rela.r_info);
314 314 /* LINTED */
315 315 symid = (int)GELF_R_SYM(rela.r_info);
316 316 /* LINTED */
317 317 if ((symid > (no_syms - 1)) || (symid < 0)) {
318 318 (void) fprintf(stderr, "%s: %s: invalid symbol table "
319 319 "offset - %d - in %s\n", prog_name, filename,
320 320 symid, p_scns->scn_name);
321 321 ndx++;
322 322 continue;
323 323 }
324 324 (void) gelf_getsym(sym_data, symid, &sym);
325 325 sym_name = (char *)elf_strptr(elf_file,
326 326 reloc_symtab->p_shdr.sh_link, sym.st_name);
327 327 if (sym_name == NULL)
328 328 sym_name = (char *)UNKNOWN;
329 329 if (r_flag && rn_flag) {
330 330 if (strcmp(name, p_scns->scn_name) != 0) {
331 331 ndx++;
332 332 continue;
333 333 }
334 334 if (!n_title) {
335 335 (void) printf("\n%s:\n", p_scns->scn_name);
336 336 (void) printf("%-*s%-*s%-*s%s\n\n",
337 337 12 + adj, "Offset", 22, "Symndx",
338 338 16, "Type", "Addend");
339 339 n_title = 1;
340 340 }
341 341 }
342 342 if (d_flag) {
343 343 if (!d_hi)
344 344 d_hi = d_low;
345 345 if ((symid < d_low) || (symid > d_hi)) {
346 346 ndx++;
347 347 continue;
348 348 }
349 349 }
350 350
351 351 (void) printf("%-#*llx", 12 + adj, EC_XWORD(rela.r_offset));
352 352 if (!v_flag) {
353 353 (void) printf("%-22d%-18d", symid, type);
354 354 } else {
355 355 Conv_inv_buf_t inv_buf;
356 356
357 357 if (strlen(sym_name)) {
358 358 size_t len = strlen(sym_name) + 1;
359 359 char tmpstr[10];
360 360 if (len > 22) {
361 361 (void) sprintf(tmpstr, "%%-%ds",
362 362 /* LINTED */
363 363 (int)len);
364 364 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
365 365 (void) printf(tmpstr, sym_name);
366 366 } else
367 367 (void) printf("%-22s", sym_name);
368 368 } else {
369 369 (void) printf("%-22d", symid);
370 370 }
371 371 (void) printf("%-20s",
372 372 conv_reloc_type(p_ehdr->e_machine,
373 373 type, DUMP_CONVFMT, &inv_buf));
374 374 }
375 375 (void) printf("%lld\n", EC_SXWORD(rela.r_addend));
376 376 ndx++;
377 377 }
378 378 }
379 379
380 380 /*
381 381 * Print relocation data of type SHT_REL.
382 382 * If d_flag, print data corresponding only to
383 383 * the section or range of sections specified.
384 384 * If n_flag, print data corresponding only to
385 385 * the named section.
386 386 */
387 387 static void
388 388 print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
389 389 GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
390 390 SCNTAB *reloc_symtab)
391 391 {
392 392 GElf_Rel rel;
393 393 GElf_Sym sym;
394 394 size_t no_entries;
395 395 size_t rel_entsize;
396 396 int type, symid;
397 397 size_t no_syms;
398 398 static int n_title = 0;
399 399 int ndx = 0;
400 400 char *sym_name;
401 401 int adj = 0;
402 402
403 403 if (gelf_getclass(elf_file) == ELFCLASS64)
404 404 adj = 8;
405 405
406 406 rel_entsize = p_scns->p_shdr.sh_entsize;
407 407 if ((rel_entsize == 0) ||
408 408 (rel_entsize > p_scns->p_shdr.sh_size)) {
409 409 rel_entsize = gelf_fsize(elf_file, ELF_T_REL, 1,
410 410 EV_CURRENT);
411 411 }
412 412 no_entries = reloc_size / rel_entsize;
413 413
414 414 no_syms = sym_size / gelf_fsize(elf_file, ELF_T_SYM, 1, EV_CURRENT);
415 415 while (no_entries--) {
416 416 (void) gelf_getrel(rdata, ndx, &rel);
417 417 /* LINTED */
418 418 type = (int)GELF_R_TYPE(rel.r_info);
419 419 /* LINTED */
420 420 symid = (int)GELF_R_SYM(rel.r_info);
421 421 /* LINTED */
422 422 if ((symid > (no_syms - 1)) || (symid < 0)) {
423 423 (void) fprintf(stderr, "%s: %s: invalid symbol table "
424 424 "offset - %d - in %s\n", prog_name, filename,
425 425 symid, p_scns->scn_name);
426 426 ndx++;
427 427 continue;
428 428 }
429 429 (void) gelf_getsym(sym_data, symid, &sym);
430 430 sym_name = (char *)elf_strptr(elf_file,
431 431 reloc_symtab->p_shdr.sh_link, sym.st_name);
432 432 if (sym_name == NULL)
433 433 sym_name = (char *)UNKNOWN;
434 434 if (r_flag && rn_flag) {
435 435 if (strcmp(name, p_scns->scn_name) != 0) {
436 436 ndx++;
437 437 continue;
438 438 }
439 439 if (!n_title) {
440 440 (void) printf("\n%s:\n", p_scns->scn_name);
441 441 (void) printf("%-*s%-*s%s\n\n",
442 442 12 + adj, "Offset", 20, "Symndx", "Type");
443 443 n_title = 1;
444 444 }
445 445 }
446 446 if (d_flag) {
447 447 if (!d_hi)
448 448 d_hi = d_low;
449 449 if ((symid < d_low) || (symid > d_hi)) {
450 450 ndx++;
451 451 continue;
452 452 }
453 453 }
454 454
455 455 (void) printf("%-#*llx", 12 + adj, EC_ADDR(rel.r_offset));
456 456 if (!v_flag) {
457 457 (void) printf("%-20d%-18d", symid, type);
458 458 } else {
459 459 Conv_inv_buf_t inv_buf;
460 460
461 461 if (strlen(sym_name))
462 462 (void) printf("%-20s", sym_name);
463 463 else {
464 464 (void) printf("%-20d", sym.st_name);
465 465 }
466 466 (void) printf("%-20s",
467 467 conv_reloc_type(p_ehdr->e_machine,
468 468 type, DUMP_CONVFMT, &inv_buf));
469 469 }
470 470 (void) printf("\n");
471 471 ndx++;
472 472 }
473 473 }
474 474
475 475 /* demangle C++ names */
476 476 static char *
477 477 demangled_name(char *s)
478 478 {
479 479 static char *buf = NULL;
480 480 const char *dn;
481 481 size_t len;
482 482
483 483 dn = conv_demangle_name(s);
484 484
485 485 /*
486 486 * If not demangled, just return the symbol name
487 487 */
488 488 if (strcmp(s, dn) == 0)
489 489 return (s);
490 490
491 491 /*
492 492 * Demangled. Format it
493 493 */
494 494 if (buf != NULL)
495 495 free(buf);
496 496
497 497 len = strlen(dn) + strlen(s) + 4;
498 498 if ((buf = malloc(len)) == NULL)
499 499 return (s);
500 500
501 501 (void) snprintf(buf, len, "%s\t[%s]", dn, s);
502 502 return (buf);
503 503 }
504 504
505 505 /*
506 506 * Print the symbol table. Input is an ELF file descriptor, a
507 507 * pointer to the symbol table SCNTAB structure,
508 508 * the number of symbols, a range of symbols to print,
509 509 * an index which is the number of the
510 510 * section in the file, and the filename. The number of sections,
511 511 * the range, and the index are set in
512 512 * dump_symbol_table, depending on whether -n or -T were set.
513 513 */
514 514 static void
515 515 print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data,
516 516 long range, int index)
517 517 {
518 518 GElf_Sym sym;
519 519 int adj = 0; /* field adjustment for elf64 */
520 520 Elf32_Word *symshndx = 0;
521 521 unsigned int nosymshndx = 0;
522 522 Conv_inv_buf_t inv_buf;
523 523
524 524
525 525 if (gelf_getclass(elf_file) == ELFCLASS64)
526 526 adj = 8;
527 527
528 528 while (range > 0) {
529 529 char *sym_name = (char *)0;
530 530 int type, bind;
531 531 int specsec;
532 532 unsigned int shndx;
533 533
534 534 (void) gelf_getsym(sym_data, index, &sym);
535 535 type = (int)GELF_ST_TYPE(sym.st_info);
536 536 bind = (int)GELF_ST_BIND(sym.st_info);
537 537
538 538 if ((sym.st_shndx == SHN_XINDEX) &&
539 539 (symshndx == 0) && (nosymshndx == 0)) {
540 540 Elf_Scn *_scn;
541 541 GElf_Shdr _shdr;
542 542 size_t symscnndx;
543 543
544 544 symscnndx = elf_ndxscn(p_symtab->p_sd);
545 545 _scn = 0;
546 546 while ((_scn = elf_nextscn(elf_file, _scn)) != 0) {
547 547 if (gelf_getshdr(_scn, &_shdr) == 0)
548 548 break;
549 549 if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
550 550 /* LINTED */
551 551 (_shdr.sh_link == (GElf_Word)symscnndx)) {
552 552 Elf_Data *_data;
553 553
554 554 if ((_data = elf_getdata(_scn, 0)) == 0)
555 555 continue;
556 556
557 557 symshndx = (Elf32_Word *)_data->d_buf;
558 558 nosymshndx = 0;
559 559 break;
560 560 }
561 561 }
562 562 nosymshndx = 1;
563 563 }
564 564
565 565 if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
566 566 shndx = symshndx[index];
567 567 specsec = 0;
568 568 } else {
569 569 shndx = sym.st_shndx;
570 570 if ((sym.st_shndx == SHN_UNDEF) ||
571 571 (sym.st_shndx >= SHN_LORESERVE))
572 572 specsec = 1;
573 573 else
574 574 specsec = 0;
575 575 }
576 576
577 577
578 578 (void) printf("[%d]\t ", index++);
579 579
580 580 if (v_flag && (type == STT_SPARC_REGISTER)) {
581 581 /*
582 582 * The strings "REG_G1" through "REG_G7" are intended
583 583 * to be consistent with output from elfdump(1).
584 584 */
585 585 (void) printf("%-*s", 12 + adj,
586 586 conv_sym_SPARC_value(sym.st_value,
587 587 DUMP_CONVFMT, &inv_buf));
588 588 } else {
589 589 (void) printf("0x%-*llx", 10 + adj,
590 590 EC_ADDR(sym.st_value));
591 591 }
592 592
593 593 (void) printf("%-*lld", 9 + adj, EC_XWORD(sym.st_size));
594 594
595 595 if (!v_flag) {
596 596 (void) printf("%d\t\t%d\t%d\t%#x\t",
597 597 type, bind, (int)sym.st_other, (int)shndx);
598 598 } else {
599 599 GElf_Ehdr p_ehdr;
600 600 (void) gelf_getehdr(elf_file, &p_ehdr);
601 601 (void) printf("%s\t",
602 602 conv_sym_info_type(p_ehdr.e_machine, type,
603 603 DUMP_CONVFMT, &inv_buf));
604 604 (void) printf("%s",
605 605 conv_sym_info_bind(bind, DUMP_CONVFMT, &inv_buf));
606 606 (void) printf("\t %d\t", EC_WORD(sym.st_other));
607 607
608 608 if (specsec)
609 609 (void) printf("%s",
610 610 conv_sym_shndx(p_ehdr.e_ident[EI_OSABI],
611 611 p_ehdr.e_machine, shndx,
612 612 CONV_FMT_DECIMAL, &inv_buf));
613 613 else
614 614 (void) printf("%d", EC_WORD(shndx));
615 615 (void) printf("\t");
616 616 }
617 617
618 618 /* support machines where NULL-deref causes core dump */
619 619 if (sym.st_name == 0)
620 620 sym_name = (char *)UNKNOWN;
621 621 else
622 622 if (C_flag)
623 623 sym_name = demangled_name(
624 624 (char *)elf_strptr(elf_file,
625 625 p_symtab->p_shdr.sh_link,
626 626 sym.st_name));
627 627 else
628 628 sym_name = (char *)elf_strptr(elf_file,
629 629 p_symtab->p_shdr.sh_link, sym.st_name);
630 630 if (sym_name == NULL)
631 631 sym_name = (char *)UNKNOWN;
632 632 (void) printf("%s\n", sym_name);
633 633
634 634 range--;
635 635 } /* end while */
636 636 }
637 637
638 638 /*
639 639 * Print the section header table. Input is the SCNTAB structure,
640 640 * the number of sections, an index which is the number of the
641 641 * section in the file, and the filename. The values of the SCNTAB
642 642 * structure, the number of sections, and the index are set in
643 643 * dump_shdr depending on whether the -n or -d modifiers were set.
644 644 */
645 645 static void
646 646 print_shdr(Elf *elf_file, SCNTAB *s, int num_scns, int index)
647 647 {
648 648 SCNTAB *p;
649 649 int num;
650 650 int field;
651 651 GElf_Ehdr p_ehdr;
652 652
653 653 if (gelf_getclass(elf_file) == ELFCLASS64)
654 654 field = 21;
655 655 else
656 656 field = 13;
657 657
658 658 p = s;
659 659 (void) gelf_getehdr(elf_file, &p_ehdr);
660 660
661 661 for (num = 0; num < num_scns; num++, p++) {
662 662 (void) printf("[%d]\t", index++);
663 663 if (!v_flag) {
664 664 (void) printf("%u\t%llu\t",
665 665 EC_WORD(p->p_shdr.sh_type),
666 666 EC_XWORD(p->p_shdr.sh_flags));
667 667 } else {
668 668 Conv_inv_buf_t inv_buf;
669 669
670 670 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
671 671 (void) printf(conv_sec_type(
672 672 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
673 673 p->p_shdr.sh_type, DUMP_CONVFMT, &inv_buf));
674 674 (void) printf(" ");
675 675
676 676 if (p->p_shdr.sh_flags & SHF_WRITE)
677 677 (void) printf("W");
678 678 else
679 679 (void) printf("-");
680 680 if (p->p_shdr.sh_flags & SHF_ALLOC)
681 681 (void) printf("A");
682 682 else
683 683 (void) printf("-");
684 684 if (p->p_shdr.sh_flags & SHF_EXECINSTR)
685 685 (void) printf("I");
686 686 else
687 687 (void) printf("-");
688 688
689 689 if (p->p_shdr.sh_flags & SHF_ORDERED)
690 690 (void) printf("O");
691 691 if (p->p_shdr.sh_flags & SHF_EXCLUDE)
692 692 (void) printf("E");
693 693
694 694 (void) printf("\t");
695 695
696 696 }
697 697 (void) printf("%-#*llx%-#*llx%-#*llx%s%s\n",
698 698 field, EC_ADDR(p->p_shdr.sh_addr),
699 699 field, EC_OFF(p->p_shdr.sh_offset),
700 700 field, EC_XWORD(p->p_shdr.sh_size),
701 701 /* compatibility: tab for elf32 */
702 702 (field == 13) ? "\t" : " ", p->scn_name);
703 703
704 704 (void) printf("\t%u\t%u\t%-#*llx%-#*llx\n\n",
705 705 EC_WORD(p->p_shdr.sh_link),
706 706 EC_WORD(p->p_shdr.sh_info),
707 707 field, EC_XWORD(p->p_shdr.sh_addralign),
708 708 field, EC_XWORD(p->p_shdr.sh_entsize));
709 709 }
710 710 }
711 711
712 712 /*
713 713 * Check that a range of numbers is valid. Input is
714 714 * a lower bound, an upper bound, a boundary condition,
715 715 * and the filename. Negative numbers and numbers greater
716 716 * than the bound are invalid. low must be smaller than hi.
717 717 * The returned integer is the number of items in the
718 718 * range if it is valid and -1 otherwise.
719 719 */
720 720 static int
721 721 check_range(int low, int hi, size_t bound, char *filename)
722 722 {
723 723 if (((size_t)low > bound) || (low <= 0)) {
724 724 (void) fprintf(stderr,
725 725 "%s: %s: number out of range, %d\n",
726 726 prog_name, filename, low);
727 727 return (-1);
728 728 }
729 729 if (((size_t)hi > bound) || (hi < 0)) {
730 730 (void) fprintf(stderr,
731 731 "%s: %s: number out of range, %d\n",
732 732 prog_name, filename, hi);
733 733 return (-1);
734 734 }
735 735
736 736 if (hi && (low > hi)) {
737 737 (void) fprintf(stderr,
738 738 "%s: %s: invalid range, %d,%d\n",
739 739 prog_name, filename, low, hi);
740 740 return (-1);
741 741 }
742 742 if (hi)
743 743 return (hi - low + 1);
744 744 else
745 745 return (1);
746 746 }
747 747
748 748 /*
749 749 * Print relocation information. Since this information is
750 750 * machine dependent, new sections must be added for each machine
751 751 * that is supported. Input is an ELF file descriptor, the ELF header,
752 752 * the SCNTAB structure, the number of sections, and a filename.
753 753 * Set up necessary information to print relocation information
754 754 * and call the appropriate print function depending on the
755 755 * type of relocation information. If the symbol table is
756 756 * absent, no relocation data is processed. Input is an
757 757 * ELF file descriptor, the ELF header, the SCNTAB structure,
758 758 * and the filename. Set range of d_flag and name if n_flag.
759 759 */
760 760 static void
761 761 dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr,
762 762 SCNTAB *p_scns, int num_scns, char *filename)
763 763 {
764 764 Elf_Data *rel_data;
765 765 Elf_Data *sym_data;
766 766 size_t sym_size;
767 767 size_t reloc_size;
768 768 SCNTAB *reloc_symtab;
769 769 SCNTAB *head_scns;
770 770 int r_title = 0;
771 771 int adj = 0;
772 772 size_t shnum;
773 773
774 774 if (gelf_getclass(elf_file) == ELFCLASS64)
775 775 adj = 8;
776 776
777 777 if ((!p_flag) && (!r_title)) {
778 778 (void) printf("\n **** RELOCATION INFORMATION ****\n");
779 779 r_title = 1;
780 780 }
781 781
782 782 while (num_scns-- > 0) {
783 783 if ((p_scns->p_shdr.sh_type != SHT_RELA) &&
784 784 (p_scns->p_shdr.sh_type != SHT_REL)) {
785 785 p_scns++;
786 786 continue;
787 787 }
788 788
789 789 head_scns = p_head_scns;
790 790
791 791 if (elf_getshdrnum(elf_file, &shnum) == -1) {
792 792 (void) fprintf(stderr,
793 793 "%s: %s: elf_getshdrnum failed: %s\n",
794 794 prog_name, filename, elf_errmsg(-1));
795 795 return;
796 796 }
797 797
798 798 if ((p_scns->p_shdr.sh_link == 0) ||
799 799 /* LINTED */
800 800 (p_scns->p_shdr.sh_link >= (GElf_Word)shnum)) {
801 801 (void) fprintf(stderr, "%s: %s: invalid sh_link field: "
802 802 "section #: %d sh_link: %d\n",
803 803 /* LINTED */
804 804 prog_name, filename, (int)elf_ndxscn(p_scns->p_sd),
805 805 (int)p_scns->p_shdr.sh_link);
806 806 return;
807 807 }
808 808 head_scns += (p_scns->p_shdr.sh_link -1);
809 809
810 810 if (head_scns->p_shdr.sh_type == SHT_SYMTAB) {
811 811 reloc_symtab = p_symtab;
812 812 } else if (head_scns->p_shdr.sh_type == SHT_DYNSYM) {
813 813 reloc_symtab = p_dynsym;
814 814 } else {
815 815 (void) fprintf(stderr,
816 816 "%s: %s: could not get symbol table\n", prog_name, filename);
817 817 return;
818 818 }
819 819
820 820 sym_data = NULL;
821 821 sym_size = 0;
822 822 reloc_size = 0;
823 823
824 824 if ((sym_data = elf_getdata(reloc_symtab->p_sd, NULL)) == NULL) {
825 825 (void) fprintf(stderr,
826 826 "%s: %s: no symbol table data\n", prog_name, filename);
827 827 return;
828 828 }
829 829 sym_size = sym_data->d_size;
830 830
831 831 if (p_scns == NULL) {
832 832 (void) fprintf(stderr,
833 833 "%s: %s: no section table data\n", prog_name, filename);
834 834 return;
835 835 }
836 836
837 837 if (p_scns->p_shdr.sh_type == SHT_RELA) {
838 838 if (!n_flag && r_flag)
839 839 (void) printf("\n%s:\n", p_scns->scn_name);
840 840 if (!p_flag && (!n_flag && r_flag))
841 841 (void) printf("%-*s%-*s%-*s%s\n\n",
842 842 12 + adj, "Offset", 22, "Symndx",
843 843 18, "Type", "Addend");
844 844 if ((rel_data = elf_getdata(p_scns->p_sd, NULL)) == NULL) {
845 845 (void) fprintf(stderr,
846 846 "%s: %s: no relocation information\n", prog_name, filename);
847 847 return;
848 848 }
849 849 reloc_size = rel_data->d_size;
850 850
851 851 if (n_flag) {
852 852 rn_flag = 1;
853 853 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
854 854 reloc_size, sym_size, filename, reloc_symtab);
855 855 }
856 856 if (d_flag) {
857 857 rn_flag = 0;
858 858 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
859 859 reloc_size, sym_size, filename, reloc_symtab);
860 860 }
861 861 if (!n_flag && !d_flag)
862 862 print_rela(elf_file, p_scns, rel_data, sym_data, p_ehdr,
863 863 reloc_size, sym_size, filename, reloc_symtab);
864 864 } else {
865 865 if (p_scns->p_shdr.sh_type == SHT_REL) {
866 866 if (!n_flag && r_flag)
867 867 (void) printf("\n%s:\n", p_scns->scn_name);
868 868 if (!p_flag && (!n_flag && r_flag)) {
869 869 (void) printf("%-*s%-*s%s\n\n",
870 870 12 + adj, "Offset", 20, "Symndx", "Type");
871 871 }
872 872 if ((rel_data = elf_getdata(p_scns->p_sd, NULL))
873 873 == NULL) {
874 874 (void) fprintf(stderr,
875 875 "%s: %s: no relocation information\n", prog_name, filename);
876 876 return;
877 877 }
878 878 reloc_size = rel_data->d_size;
879 879 if (n_flag) {
880 880 rn_flag = 1;
881 881 print_rel(elf_file, p_scns, rel_data, sym_data,
882 882 p_ehdr, reloc_size, sym_size,
883 883 filename, reloc_symtab);
884 884 }
885 885 if (d_flag) {
886 886 rn_flag = 0;
887 887 print_rel(elf_file, p_scns, rel_data, sym_data,
888 888 p_ehdr, reloc_size, sym_size,
889 889 filename, reloc_symtab);
890 890 }
891 891 if (!n_flag && !d_flag)
892 892 print_rel(elf_file, p_scns, rel_data, sym_data,
893 893 p_ehdr, reloc_size, sym_size,
894 894 filename, reloc_symtab);
895 895 }
896 896 }
897 897 p_scns++;
898 898 }
899 899 }
900 900
901 901 /*
902 902 * Print out the string tables. Input is an opened ELF file,
903 903 * the SCNTAB structure, the number of sections, and the filename.
904 904 * Since there can be more than one string table, all sections are
905 905 * examined and any with the correct type are printed out.
906 906 */
907 907 static void
908 908 dump_string_table(SCNTAB *s, int num_scns)
909 909 {
910 910 size_t section_size;
911 911 unsigned char *strtab;
912 912 int beg_of_string;
913 913 int counter = 0;
914 914 int str_off;
915 915 int i;
916 916
917 917 if (!p_flag) {
918 918 (void) printf("\n **** STRING TABLE INFORMATION ****\n");
919 919 }
920 920
921 921 for (i = 0; i < num_scns; i++, s++) {
922 922 if (s->p_shdr.sh_type != SHT_STRTAB)
923 923 continue;
924 924
925 925 str_off = 0;
926 926
927 927 if (!p_flag) {
928 928 (void) printf("\n%s:\n", s->scn_name);
929 929 (void) printf(" <offset> \tName\n");
930 930 }
931 931 section_size = 0;
932 932 if ((strtab = (unsigned char *)
933 933 get_scndata(s->p_sd, §ion_size)) == NULL) {
934 934 continue;
935 935 }
936 936
937 937 if (section_size != 0) {
938 938 (void) printf(" <%d> \t", str_off);
939 939 beg_of_string = 0;
940 940 while (section_size--) {
941 941 unsigned char c = *strtab++;
942 942
943 943 if (beg_of_string) {
944 944 (void) printf(" <%d> \t", str_off);
945 945 counter++;
946 946 beg_of_string = 0;
947 947 }
948 948 str_off++;
949 949 switch (c) {
950 950 case '\0':
951 951 (void) printf("\n");
952 952 beg_of_string = 1;
953 953 break;
954 954 default:
955 955 (void) putchar(c);
956 956 }
957 957 }
958 958 }
959 959 }
960 960 (void) printf("\n");
961 961 }
962 962
963 963 /*
964 964 * Print the symbol table. This function does not print the contents
965 965 * of the symbol table but sets up the parameters and then calls
966 966 * print_symtab to print the symbols. Calling another function to print
967 967 * the symbols allows both -T and -n to work correctly
968 968 * simultaneously. Input is an opened ELF file, a pointer to the
969 969 * symbol table SCNTAB structure, and the filename.
970 970 * Set the range of symbols to print if T_flag, and set
971 971 * name of symbol to print if n_flag.
972 972 */
973 973 static void
974 974 dump_symbol_table(Elf *elf_file, SCNTAB *p_symtab, char *filename)
975 975 {
976 976 Elf_Data *sym_data;
977 977 GElf_Sym T_range, n_range; /* for use with -T and -n */
978 978 size_t count = 0;
979 979 size_t sym_size;
980 980 int index = 1;
981 981 int found_it = 0;
982 982 int i;
983 983 int adj = 0; /* field adjustment for elf64 */
984 984
985 985 if (gelf_getclass(elf_file) == ELFCLASS64)
986 986 adj = 8;
987 987
988 988 if (p_symtab == NULL) {
989 989 (void) fprintf(stderr,
990 990 "%s: %s: could not get symbol table\n", prog_name, filename);
991 991 return;
992 992 }
993 993
994 994 /* get symbol table data */
995 995 sym_data = NULL;
996 996 sym_size = 0;
997 997 if ((sym_data =
998 998 elf_getdata(p_symtab->p_sd, NULL)) == NULL) {
999 999 (void) printf("\n%s:\n", p_symtab->scn_name);
1000 1000 (void) printf("No symbol table data\n");
1001 1001 return;
1002 1002 }
1003 1003 sym_size = sym_data->d_size;
1004 1004
1005 1005 count = sym_size / p_symtab->p_shdr.sh_entsize;
1006 1006
1007 1007 if (n_flag && t_flag && !T_flag) {
1008 1008 /* LINTED */
1009 1009 for (i = 1; i < count; i++) {
1010 1010 (void) gelf_getsym(sym_data, i, &n_range);
1011 1011 if (strcmp(name, (char *)
1012 1012 elf_strptr(elf_file,
1013 1013 p_symtab->p_shdr.sh_link,
1014 1014 n_range.st_name)) != 0) {
1015 1015 continue;
1016 1016 } else {
1017 1017 found_it = 1;
1018 1018 if (!p_flag) {
1019 1019 (void) printf(
1020 1020 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1021 1021 (void) printf(
1022 1022 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1023 1023 12 + adj, "Value", 9 + adj, "Size");
1024 1024 }
1025 1025 (void) printf("\n%s:\n", p_symtab->scn_name);
1026 1026 print_symtab(elf_file, p_symtab, sym_data,
1027 1027 1, i);
1028 1028 }
1029 1029 } /* end for */
1030 1030 if (!found_it) {
1031 1031 (void) fprintf(stderr, "%s: %s: %s not found\n",
1032 1032 prog_name, filename, name);
1033 1033 }
1034 1034 } else if (T_flag) {
1035 1035 T_num = check_range(T_low, T_hi, count, filename);
1036 1036 if (T_num < 0)
1037 1037 return;
1038 1038
1039 1039 (void) gelf_getsym(sym_data, T_low-1, &T_range);
1040 1040 index = T_low;
1041 1041
1042 1042 if (!p_flag) {
1043 1043 (void) printf(
1044 1044 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1045 1045 (void) printf(
1046 1046 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1047 1047 12 + adj, "Value", 9 + adj, "Size");
1048 1048 }
1049 1049 (void) printf("\n%s:\n", p_symtab->scn_name);
1050 1050 print_symtab(elf_file, p_symtab, sym_data, T_num, index);
1051 1051 } else {
1052 1052 if (!p_flag) {
1053 1053 (void) printf(
1054 1054 "\n ***** SYMBOL TABLE INFORMATION *****\n");
1055 1055 (void) printf(
1056 1056 "[Index] %-*s%-*sType\tBind\tOther\tShndx\tName",
1057 1057 12 + adj, "Value", 9 + adj, "Size");
1058 1058 }
1059 1059 (void) printf("\n%s:\n", p_symtab->scn_name);
1060 1060 print_symtab(elf_file, p_symtab, sym_data, count-1, 1);
1061 1061 }
1062 1062 }
1063 1063
1064 1064
1065 1065 /*
1066 1066 * Print dynamic linking information. Input is an ELF
1067 1067 * file descriptor, the SCNTAB structure, the number of
1068 1068 * sections, and the filename.
1069 1069 */
1070 1070 static void
1071 1071 dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename)
1072 1072 {
1073 1073 #define pdyn_Fmtptr "%#llx"
1074 1074
1075 1075 Elf_Data *dyn_data;
1076 1076 GElf_Dyn p_dyn;
1077 1077 GElf_Phdr p_phdr;
1078 1078 GElf_Ehdr p_ehdr;
1079 1079 int index = 1;
1080 1080 int lib_scns = num_scns;
1081 1081 SCNTAB *l_scns = p_scns;
1082 1082 int header_num = 0;
1083 1083 const char *str;
1084 1084
1085 1085 (void) gelf_getehdr(elf_file, &p_ehdr);
1086 1086
1087 1087 if (!p_flag)
1088 1088 (void) printf("\n **** DYNAMIC SECTION INFORMATION ****\n");
1089 1089
1090 1090 for (; num_scns > 0; num_scns--, p_scns++) {
1091 1091 GElf_Word link;
1092 1092 int ii;
1093 1093
1094 1094
1095 1095 if (p_scns->p_shdr.sh_type != SHT_DYNAMIC)
1096 1096 continue;
1097 1097
1098 1098 if (!p_flag) {
1099 1099 (void) printf("%s:\n", p_scns->scn_name);
1100 1100 (void) printf("[INDEX]\tTag Value\n");
1101 1101 }
1102 1102
1103 1103 if ((dyn_data = elf_getdata(p_scns->p_sd, NULL)) == 0) {
1104 1104 (void) fprintf(stderr, "%s: %s: no data in "
1105 1105 "%s section\n", prog_name, filename,
1106 1106 p_scns->scn_name);
1107 1107 return;
1108 1108 }
1109 1109
1110 1110 link = p_scns->p_shdr.sh_link;
1111 1111 ii = 0;
1112 1112
1113 1113 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1114 1114 while (p_dyn.d_tag != DT_NULL) {
1115 1115 union {
1116 1116 Conv_inv_buf_t inv;
1117 1117 Conv_dyn_flag_buf_t dyn_flag;
1118 1118 Conv_dyn_flag1_buf_t dyn_flag1;
1119 1119 Conv_dyn_feature1_buf_t dyn_feature1;
1120 1120 Conv_dyn_posflag1_buf_t dyn_posflag1;
1121 1121 } conv_buf;
1122 1122
1123 1123 (void) printf("[%d]\t%-15.15s ", index++,
1124 1124 conv_dyn_tag(p_dyn.d_tag,
1125 1125 p_ehdr.e_ident[EI_OSABI], p_ehdr.e_machine,
1126 1126 DUMP_CONVFMT, &conv_buf.inv));
1127 1127
1128 1128 /*
1129 1129 * It would be nice to use a table driven loop
1130 1130 * here, but the address space is too sparse
1131 1131 * and irregular. A switch is simple and robust.
1132 1132 */
1133 1133 switch (p_dyn.d_tag) {
1134 1134 /*
1135 1135 * Items with an address value
1136 1136 */
1137 1137 case DT_PLTGOT:
1138 1138 case DT_HASH:
1139 1139 case DT_STRTAB:
1140 1140 case DT_RELA:
1141 1141 case DT_SYMTAB:
1142 1142 case DT_INIT:
1143 1143 case DT_FINI:
1144 1144 case DT_REL:
1145 1145 case DT_DEBUG:
1146 1146 case DT_TEXTREL:
1147 1147 case DT_JMPREL:
1148 1148 case DT_INIT_ARRAY:
1149 1149 case DT_FINI_ARRAY:
1150 1150 case DT_INIT_ARRAYSZ:
1151 1151 case DT_FINI_ARRAYSZ:
1152 1152 case DT_PREINIT_ARRAY:
1153 1153 case DT_PREINIT_ARRAYSZ:
1154 1154 case DT_SUNW_RTLDINF:
1155 1155 case DT_SUNW_CAP:
1156 1156 case DT_SUNW_CAPINFO:
1157 1157 case DT_SUNW_CAPCHAIN:
1158 1158 case DT_SUNW_SYMTAB:
1159 1159 case DT_SUNW_SYMSORT:
1160 1160 case DT_SUNW_TLSSORT:
1161 1161 case DT_PLTPAD:
1162 1162 case DT_MOVETAB:
1163 1163 case DT_SYMINFO:
1164 1164 case DT_RELACOUNT:
1165 1165 case DT_RELCOUNT:
1166 1166 case DT_VERSYM:
1167 1167 case DT_VERDEF:
1168 1168 case DT_VERDEFNUM:
1169 1169 case DT_VERNEED:
1170 1170 (void) printf(pdyn_Fmtptr,
1171 1171 EC_ADDR(p_dyn.d_un.d_ptr));
1172 1172 break;
1173 1173
1174 1174 /*
1175 1175 * Items with a string value
1176 1176 */
1177 1177 case DT_NEEDED:
1178 1178 case DT_SONAME:
1179 1179 case DT_RPATH:
1180 1180 case DT_RUNPATH:
1181 1181 case DT_SUNW_AUXILIARY:
1182 1182 case DT_SUNW_FILTER:
1183 1183 case DT_CONFIG:
1184 1184 case DT_DEPAUDIT:
1185 1185 case DT_AUDIT:
1186 1186 case DT_AUXILIARY:
1187 1187 case DT_USED:
1188 1188 case DT_FILTER:
1189 1189 if (v_flag) { /* Look up the string */
1190 1190 str = (char *)elf_strptr(elf_file, link,
1191 1191 p_dyn.d_un.d_ptr);
1192 1192 if (!(str && *str))
1193 1193 str = (char *)UNKNOWN;
1194 1194 (void) printf("%s", str);
1195 1195 } else { /* Show the address */
1196 1196 (void) printf(pdyn_Fmtptr,
1197 1197 EC_ADDR(p_dyn.d_un.d_ptr));
1198 1198 }
1199 1199 break;
1200 1200
1201 1201 /*
1202 1202 * Items with a literal value
1203 1203 */
1204 1204 case DT_PLTRELSZ:
1205 1205 case DT_RELASZ:
1206 1206 case DT_RELAENT:
1207 1207 case DT_STRSZ:
1208 1208 case DT_SYMENT:
1209 1209 case DT_RELSZ:
1210 1210 case DT_RELENT:
1211 1211 case DT_PLTREL:
1212 1212 case DT_BIND_NOW:
1213 1213 case DT_CHECKSUM:
1214 1214 case DT_PLTPADSZ:
1215 1215 case DT_MOVEENT:
1216 1216 case DT_MOVESZ:
1217 1217 case DT_SYMINSZ:
↓ open down ↓ |
1217 lines elided |
↑ open up ↑ |
1218 1218 case DT_SYMINENT:
1219 1219 case DT_VERNEEDNUM:
1220 1220 case DT_SPARC_REGISTER:
1221 1221 case DT_SUNW_SYMSZ:
1222 1222 case DT_SUNW_SORTENT:
1223 1223 case DT_SUNW_SYMSORTSZ:
1224 1224 case DT_SUNW_TLSSORTSZ:
1225 1225 case DT_SUNW_STRPAD:
1226 1226 case DT_SUNW_CAPCHAINENT:
1227 1227 case DT_SUNW_CAPCHAINSZ:
1228 + case DT_SUNW_ASLR:
1228 1229 (void) printf(pdyn_Fmtptr,
1229 1230 EC_XWORD(p_dyn.d_un.d_val));
1230 1231 break;
1231 1232
1232 1233 /*
1233 1234 * Integer items that are bitmasks, or which
1234 1235 * can be otherwise formatted in symbolic form.
1235 1236 */
1236 1237 case DT_FLAGS:
1237 1238 case DT_FEATURE_1:
1238 1239 case DT_POSFLAG_1:
1239 1240 case DT_FLAGS_1:
1240 1241 case DT_SUNW_LDMACH:
1241 1242 str = NULL;
1242 1243 if (v_flag) {
1243 1244 switch (p_dyn.d_tag) {
1244 1245 case DT_FLAGS:
1245 1246 str = conv_dyn_flag(
1246 1247 p_dyn.d_un.d_val,
1247 1248 DUMP_CONVFMT,
1248 1249 &conv_buf.dyn_flag);
1249 1250 break;
1250 1251 case DT_FEATURE_1:
1251 1252 str = conv_dyn_feature1(
1252 1253 p_dyn.d_un.d_val,
1253 1254 DUMP_CONVFMT,
1254 1255 &conv_buf.dyn_feature1);
1255 1256 break;
1256 1257 case DT_POSFLAG_1:
1257 1258 str = conv_dyn_posflag1(
1258 1259 p_dyn.d_un.d_val,
1259 1260 DUMP_CONVFMT,
1260 1261 &conv_buf.dyn_posflag1);
1261 1262 break;
1262 1263 case DT_FLAGS_1:
1263 1264 str = conv_dyn_flag1(
1264 1265 p_dyn.d_un.d_val, 0,
1265 1266 &conv_buf.dyn_flag1);
1266 1267 break;
1267 1268 case DT_SUNW_LDMACH:
1268 1269 str = conv_ehdr_mach(
1269 1270 p_dyn.d_un.d_val, 0,
1270 1271 &conv_buf.inv);
1271 1272 break;
1272 1273 }
1273 1274 }
1274 1275 if (str) { /* Show as string */
1275 1276 (void) printf("%s", str);
1276 1277 } else { /* Numeric form */
1277 1278 (void) printf(pdyn_Fmtptr,
1278 1279 EC_ADDR(p_dyn.d_un.d_ptr));
1279 1280 }
1280 1281 break;
1281 1282
1282 1283 /*
1283 1284 * Depreciated items with a literal value
1284 1285 */
1285 1286 case DT_DEPRECATED_SPARC_REGISTER:
1286 1287 (void) printf(pdyn_Fmtptr
1287 1288 " (deprecated value)",
1288 1289 EC_XWORD(p_dyn.d_un.d_val));
1289 1290 break;
1290 1291
1291 1292 /* Ignored items */
1292 1293 case DT_SYMBOLIC:
1293 1294 (void) printf("(ignored)");
1294 1295 break;
1295 1296 }
1296 1297 (void) printf("\n");
1297 1298 (void) gelf_getdyn(dyn_data, ii++, &p_dyn);
1298 1299 }
1299 1300 }
1300 1301
1301 1302 /*
1302 1303 * Check for existence of static shared library information.
1303 1304 */
1304 1305 while (header_num < p_ehdr.e_phnum) {
1305 1306 (void) gelf_getphdr(elf_file, header_num, &p_phdr);
1306 1307 if (p_phdr.p_type == PT_SHLIB) {
1307 1308 while (--lib_scns > 0) {
1308 1309 if (strcmp(l_scns->scn_name, ".lib") == 0) {
1309 1310 print_static(l_scns, filename);
1310 1311 }
1311 1312 l_scns++;
1312 1313 }
1313 1314 }
1314 1315 header_num++;
1315 1316 }
1316 1317 #undef pdyn_Fmtptr
1317 1318 }
1318 1319
1319 1320 /*
1320 1321 * Print the ELF header. Input is an ELF file descriptor
1321 1322 * and the filename. If f_flag is set, the ELF header is
1322 1323 * printed to stdout, otherwise the function returns after
1323 1324 * setting the pointer to the ELF header. Any values which
1324 1325 * are not known are printed in decimal. Fields must be updated
1325 1326 * as new values are added.
1326 1327 */
1327 1328 static GElf_Ehdr *
1328 1329 dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
1329 1330 {
1330 1331 int class;
1331 1332 int field;
1332 1333
1333 1334 if (gelf_getehdr(elf_file, elf_head_p) == NULL) {
1334 1335 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1335 1336 elf_errmsg(-1));
1336 1337 return (NULL);
1337 1338 }
1338 1339
1339 1340 class = (int)elf_head_p->e_ident[4];
1340 1341
1341 1342 if (class == ELFCLASS64)
1342 1343 field = 21;
1343 1344 else
1344 1345 field = 13;
1345 1346
1346 1347 if (!f_flag)
1347 1348 return (elf_head_p);
1348 1349
1349 1350 if (!p_flag) {
1350 1351 (void) printf("\n **** ELF HEADER ****\n");
1351 1352 (void) printf("%-*s%-11s%-*sMachine Version\n",
1352 1353 field, "Class", "Data", field, "Type");
1353 1354 (void) printf("%-*s%-11s%-*sFlags Ehsize\n",
1354 1355 field, "Entry", "Phoff", field, "Shoff");
1355 1356 (void) printf("%-*s%-11s%-*sShnum Shstrndx\n\n",
1356 1357 field, "Phentsize", "Phnum", field, "Shentsz");
1357 1358 }
1358 1359
1359 1360 if (!v_flag) {
1360 1361 (void) printf("%-*d%-11d%-*d%-12d%d\n",
1361 1362 field, elf_head_p->e_ident[4], elf_head_p->e_ident[5],
1362 1363 field, (int)elf_head_p->e_type, (int)elf_head_p->e_machine,
1363 1364 elf_head_p->e_version);
1364 1365 } else {
1365 1366 Conv_inv_buf_t inv_buf;
1366 1367
1367 1368 (void) printf("%-*s", field,
1368 1369 conv_ehdr_class(class, DUMP_CONVFMT, &inv_buf));
1369 1370 (void) printf("%-11s",
1370 1371 conv_ehdr_data(elf_head_p->e_ident[5], DUMP_CONVFMT,
1371 1372 &inv_buf));
1372 1373 (void) printf("%-*s", field,
1373 1374 conv_ehdr_type(elf_head_p->e_ident[EI_OSABI],
1374 1375 elf_head_p->e_type, DUMP_CONVFMT, &inv_buf));
1375 1376 (void) printf("%-12s",
1376 1377 conv_ehdr_mach(elf_head_p->e_machine, DUMP_CONVFMT,
1377 1378 &inv_buf));
1378 1379 (void) printf("%s\n",
1379 1380 conv_ehdr_vers(elf_head_p->e_version, DUMP_CONVFMT,
1380 1381 &inv_buf));
1381 1382 }
1382 1383 (void) printf("%-#*llx%-#11llx%-#*llx%-#12x%#x\n",
1383 1384 field, EC_ADDR(elf_head_p->e_entry), EC_OFF(elf_head_p->e_phoff),
1384 1385 field, EC_OFF(elf_head_p->e_shoff), EC_WORD(elf_head_p->e_flags),
1385 1386 EC_WORD(elf_head_p->e_ehsize));
1386 1387 if (!v_flag || (elf_head_p->e_shstrndx != SHN_XINDEX)) {
1387 1388 (void) printf("%-#*x%-11u%-#*x%-12u%u\n",
1388 1389 field, EC_WORD(elf_head_p->e_phentsize),
1389 1390 EC_WORD(elf_head_p->e_phnum),
1390 1391 field, EC_WORD(elf_head_p->e_shentsize),
1391 1392 EC_WORD(elf_head_p->e_shnum),
1392 1393 EC_WORD(elf_head_p->e_shstrndx));
1393 1394 } else {
1394 1395 (void) printf("%-#*x%-11u%-#*x%-12uXINDEX\n",
1395 1396 field, EC_WORD(elf_head_p->e_phentsize),
1396 1397 EC_WORD(elf_head_p->e_phnum),
1397 1398 field, EC_WORD(elf_head_p->e_shentsize),
1398 1399 EC_WORD(elf_head_p->e_shnum));
1399 1400 }
1400 1401 if ((elf_head_p->e_shnum == 0) && (elf_head_p->e_shoff > 0)) {
1401 1402 Elf_Scn *scn;
1402 1403 GElf_Shdr shdr0;
1403 1404 int field;
1404 1405
1405 1406 if (gelf_getclass(elf_file) == ELFCLASS64)
1406 1407 field = 21;
1407 1408 else
1408 1409 field = 13;
1409 1410 if (!p_flag) {
1410 1411 (void) printf("\n **** SECTION HEADER[0] "
1411 1412 "{Elf Extensions} ****\n");
1412 1413 (void) printf(
1413 1414 "[No]\tType\tFlags\t%-*s %-*s%-*s%sName\n",
1414 1415 field, "Addr", field, "Offset", field,
1415 1416 "Size(shnum)",
1416 1417 /* compatibility: tab for elf32 */
1417 1418 (field == 13) ? "\t" : " ");
1418 1419 (void) printf("\tLn(strndx) Info\t%-*s Entsize\n",
1419 1420 field, "Adralgn");
1420 1421 }
1421 1422 if ((scn = elf_getscn(elf_file, 0)) == NULL) {
1422 1423 (void) fprintf(stderr,
1423 1424 "%s: %s: elf_getscn failed: %s\n",
1424 1425 prog_name, filename, elf_errmsg(-1));
1425 1426 return (NULL);
1426 1427 }
1427 1428 if (gelf_getshdr(scn, &shdr0) == 0) {
1428 1429 (void) fprintf(stderr,
1429 1430 "%s: %s: gelf_getshdr: %s\n",
1430 1431 prog_name, filename, elf_errmsg(-1));
1431 1432 return (NULL);
1432 1433 }
1433 1434 (void) printf("[0]\t%u\t%llu\t", EC_WORD(shdr0.sh_type),
1434 1435 EC_XWORD(shdr0.sh_flags));
1435 1436
1436 1437 (void) printf("%-#*llx %-#*llx%-*llu%s%-*u\n",
1437 1438 field, EC_ADDR(shdr0.sh_addr),
1438 1439 field, EC_OFF(shdr0.sh_offset),
1439 1440 field, EC_XWORD(shdr0.sh_size),
1440 1441 /* compatibility: tab for elf32 */
1441 1442 ((field == 13) ? "\t" : " "),
1442 1443 field, EC_WORD(shdr0.sh_name));
1443 1444
1444 1445 (void) printf("\t%u\t%u\t%-#*llx %-#*llx\n",
1445 1446 EC_WORD(shdr0.sh_link),
1446 1447 EC_WORD(shdr0.sh_info),
1447 1448 field, EC_XWORD(shdr0.sh_addralign),
1448 1449 field, EC_XWORD(shdr0.sh_entsize));
1449 1450 }
1450 1451 (void) printf("\n");
1451 1452
1452 1453 return (elf_head_p);
1453 1454 }
1454 1455
1455 1456 /*
1456 1457 * Print section contents. Input is an ELF file descriptor,
1457 1458 * the ELF header, the SCNTAB structure,
1458 1459 * the number of symbols, and the filename.
1459 1460 * The number of sections,
1460 1461 * and the offset into the SCNTAB structure will be
1461 1462 * set in dump_section if d_flag or n_flag are set.
1462 1463 * If v_flag is set, sections which can be interpreted will
1463 1464 * be interpreted, otherwise raw data will be output in hexidecimal.
1464 1465 */
1465 1466 static void
1466 1467 print_section(Elf *elf_file,
1467 1468 GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
1468 1469 {
1469 1470 unsigned char *p_sec;
1470 1471 int i;
1471 1472 size_t size;
1472 1473
1473 1474 for (i = 0; i < num_scns; i++, p++) {
1474 1475 GElf_Shdr shdr;
1475 1476
1476 1477 size = 0;
1477 1478 if (s_flag && !v_flag)
1478 1479 p_sec = (unsigned char *)get_rawscn(p->p_sd, &size);
1479 1480 else
1480 1481 p_sec = (unsigned char *)get_scndata(p->p_sd, &size);
1481 1482
1482 1483 if ((gelf_getshdr(p->p_sd, &shdr) != NULL) &&
1483 1484 (shdr.sh_type == SHT_NOBITS)) {
1484 1485 continue;
1485 1486 }
1486 1487 if (s_flag && !v_flag) {
1487 1488 (void) printf("\n%s:\n", p->scn_name);
1488 1489 print_rawdata(p_sec, size);
1489 1490 continue;
1490 1491 }
1491 1492 if (shdr.sh_type == SHT_SYMTAB) {
1492 1493 dump_symbol_table(elf_file, p, filename);
1493 1494 continue;
1494 1495 }
1495 1496 if (shdr.sh_type == SHT_DYNSYM) {
1496 1497 dump_symbol_table(elf_file, p, filename);
1497 1498 continue;
1498 1499 }
1499 1500 if (shdr.sh_type == SHT_STRTAB) {
1500 1501 dump_string_table(p, 1);
1501 1502 continue;
1502 1503 }
1503 1504 if (shdr.sh_type == SHT_RELA) {
1504 1505 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1505 1506 continue;
1506 1507 }
1507 1508 if (shdr.sh_type == SHT_REL) {
1508 1509 dump_reloc_table(elf_file, p_ehdr, p, 1, filename);
1509 1510 continue;
1510 1511 }
1511 1512 if (shdr.sh_type == SHT_DYNAMIC) {
1512 1513 dump_dynamic(elf_file, p, 1, filename);
1513 1514 continue;
1514 1515 }
1515 1516
1516 1517 (void) printf("\n%s:\n", p->scn_name);
1517 1518 print_rawdata(p_sec, size);
1518 1519 }
1519 1520 (void) printf("\n");
1520 1521 }
1521 1522
1522 1523 /*
1523 1524 * Print section contents. This function does not print the contents
1524 1525 * of the sections but sets up the parameters and then calls
1525 1526 * print_section to print the contents. Calling another function to print
1526 1527 * the contents allows both -d and -n to work correctly
1527 1528 * simultaneously. Input is an ELF file descriptor, the ELF header,
1528 1529 * the SCNTAB structure, the number of sections, and the filename.
1529 1530 * Set the range of sections if d_flag, and set section name if
1530 1531 * n_flag.
1531 1532 */
1532 1533 static void
1533 1534 dump_section(Elf *elf_file,
1534 1535 GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
1535 1536 {
1536 1537 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1537 1538 int i;
1538 1539 int found_it = 0; /* for use with -n section_name */
1539 1540
1540 1541 if (n_flag) {
1541 1542 n_range = s;
1542 1543
1543 1544 for (i = 0; i < num_scns; i++, n_range++) {
1544 1545 if ((strcmp(name, n_range->scn_name)) != 0)
1545 1546 continue;
1546 1547 else {
1547 1548 found_it = 1;
1548 1549 print_section(elf_file, p_ehdr,
1549 1550 n_range, 1, filename);
1550 1551 }
1551 1552 }
1552 1553
1553 1554 if (!found_it) {
1554 1555 (void) fprintf(stderr, "%s: %s: %s not found\n",
1555 1556 prog_name, filename, name);
1556 1557 }
1557 1558 } /* end n_flag */
1558 1559
1559 1560 if (d_flag) {
1560 1561 d_range = s;
1561 1562 d_num = check_range(d_low, d_hi, num_scns, filename);
1562 1563 if (d_num < 0)
1563 1564 return;
1564 1565 d_range += d_low - 1;
1565 1566
1566 1567 print_section(elf_file, p_ehdr, d_range, d_num, filename);
1567 1568 } /* end d_flag */
1568 1569
1569 1570 if (!n_flag && !d_flag)
1570 1571 print_section(elf_file, p_ehdr, s, num_scns, filename);
1571 1572 }
1572 1573
1573 1574 /*
1574 1575 * Print the section header table. This function does not print the contents
1575 1576 * of the section headers but sets up the parameters and then calls
1576 1577 * print_shdr to print the contents. Calling another function to print
1577 1578 * the contents allows both -d and -n to work correctly
1578 1579 * simultaneously. Input is the SCNTAB structure,
1579 1580 * the number of sections from the ELF header, and the filename.
1580 1581 * Set the range of section headers to print if d_flag, and set
1581 1582 * name of section header to print if n_flag.
1582 1583 */
1583 1584 static void
1584 1585 dump_shdr(Elf *elf_file, SCNTAB *s, int num_scns, char *filename)
1585 1586 {
1586 1587
1587 1588 SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
1588 1589 int field;
1589 1590 int i;
1590 1591 int found_it = 0; /* for use with -n section_name */
1591 1592
1592 1593 if (gelf_getclass(elf_file) == ELFCLASS64)
1593 1594 field = 21;
1594 1595 else
1595 1596 field = 13;
1596 1597
1597 1598 if (!p_flag) {
1598 1599 (void) printf("\n **** SECTION HEADER TABLE ****\n");
1599 1600 (void) printf("[No]\tType\tFlags\t%-*s %-*s %-*s%sName\n",
1600 1601 field, "Addr", field, "Offset", field, "Size",
1601 1602 /* compatibility: tab for elf32 */
1602 1603 (field == 13) ? "\t" : " ");
1603 1604 (void) printf("\tLink\tInfo\t%-*s Entsize\n\n",
1604 1605 field, "Adralgn");
1605 1606 }
1606 1607
1607 1608 if (n_flag) {
1608 1609 n_range = s;
1609 1610
1610 1611 for (i = 1; i <= num_scns; i++, n_range++) {
1611 1612 if ((strcmp(name, n_range->scn_name)) != 0)
1612 1613 continue;
1613 1614 else {
1614 1615 found_it = 1;
1615 1616 print_shdr(elf_file, n_range, 1, i);
1616 1617 }
1617 1618 }
1618 1619
1619 1620 if (!found_it) {
1620 1621 (void) fprintf(stderr, "%s: %s: %s not found\n",
1621 1622 prog_name, filename, name);
1622 1623 }
1623 1624 } /* end n_flag */
1624 1625
1625 1626 if (d_flag) {
1626 1627 d_range = s;
1627 1628 d_num = check_range(d_low, d_hi, num_scns, filename);
1628 1629 if (d_num < 0)
1629 1630 return;
1630 1631 d_range += d_low - 1;
1631 1632
1632 1633 print_shdr(elf_file, d_range, d_num, d_low);
1633 1634 } /* end d_flag */
1634 1635
1635 1636 if (!n_flag && !d_flag)
1636 1637 print_shdr(elf_file, s, num_scns, 1);
1637 1638 }
1638 1639
1639 1640 /*
1640 1641 * Process all of the command line options (except
1641 1642 * for -a, -g, -f, and -o). All of the options processed
1642 1643 * by this function require the presence of the section
1643 1644 * header table and will not be processed if it is not present.
1644 1645 * Set up a buffer containing section name, section header,
1645 1646 * and section descriptor for each section in the file. This
1646 1647 * structure is used to avoid duplicate calls to libelf functions.
1647 1648 * Structure members for the symbol table, the debugging information,
1648 1649 * and the line number information are global. All of the
1649 1650 * rest are local.
1650 1651 */
1651 1652 static void
1652 1653 dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
1653 1654 {
1654 1655
1655 1656 static SCNTAB *buffer, *p_scns;
1656 1657 Elf_Scn *scn = 0;
1657 1658 char *s_name = NULL;
1658 1659 int found = 0;
1659 1660 unsigned int num_scns;
1660 1661 size_t shstrndx;
1661 1662 size_t shnum;
1662 1663
1663 1664
1664 1665 if (elf_getshdrnum(elf_file, &shnum) == -1) {
1665 1666 (void) fprintf(stderr,
1666 1667 "%s: %s: elf_getshdrnum failed: %s\n",
1667 1668 prog_name, filename, elf_errmsg(-1));
1668 1669 return;
1669 1670 }
1670 1671 if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
1671 1672 (void) fprintf(stderr,
1672 1673 "%s: %s: elf_getshdrstrndx failed: %s\n",
1673 1674 prog_name, filename, elf_errmsg(-1));
1674 1675 return;
1675 1676 }
1676 1677
1677 1678 if ((buffer = calloc(shnum, sizeof (SCNTAB))) == NULL) {
1678 1679 (void) fprintf(stderr, "%s: %s: cannot calloc space\n",
1679 1680 prog_name, filename);
1680 1681 return;
1681 1682 }
1682 1683 /* LINTED */
1683 1684 num_scns = (int)shnum - 1;
1684 1685
1685 1686 p_symtab = (SCNTAB *)0;
1686 1687 p_dynsym = (SCNTAB *)0;
1687 1688 p_scns = buffer;
1688 1689 p_head_scns = buffer;
1689 1690
1690 1691 while ((scn = elf_nextscn(elf_file, scn)) != 0) {
1691 1692 if ((gelf_getshdr(scn, &buffer->p_shdr)) == 0) {
1692 1693 (void) fprintf(stderr,
1693 1694 "%s: %s: %s\n", prog_name, filename,
1694 1695 elf_errmsg(-1));
1695 1696 return;
1696 1697 }
1697 1698 s_name = (char *)
1698 1699 elf_strptr(elf_file, shstrndx, buffer->p_shdr.sh_name);
1699 1700 buffer->scn_name = s_name ? s_name : (char *)UNKNOWN;
1700 1701 buffer->p_sd = scn;
1701 1702
1702 1703 if (buffer->p_shdr.sh_type == SHT_SYMTAB) {
1703 1704 found += 1;
1704 1705 p_symtab = buffer;
1705 1706 }
1706 1707 if (buffer->p_shdr.sh_type == SHT_DYNSYM)
1707 1708 p_dynsym = buffer;
1708 1709 buffer++;
1709 1710 }
1710 1711
1711 1712 /*
1712 1713 * These functions depend upon the presence of the section header table
1713 1714 * and will not be invoked in its absence
1714 1715 */
1715 1716 if (h_flag) {
1716 1717 dump_shdr(elf_file, p_scns, num_scns, filename);
1717 1718 }
1718 1719 if (p_symtab && (t_flag || T_flag)) {
1719 1720 dump_symbol_table(elf_file, p_symtab, filename);
1720 1721 }
1721 1722 if (c_flag) {
1722 1723 dump_string_table(p_scns, num_scns);
1723 1724 }
1724 1725 if (r_flag) {
1725 1726 dump_reloc_table(elf_file, elf_head_p,
1726 1727 p_scns, num_scns, filename);
1727 1728 }
1728 1729 if (L_flag) {
1729 1730 dump_dynamic(elf_file, p_scns, num_scns, filename);
1730 1731 }
1731 1732 if (s_flag) {
1732 1733 dump_section(elf_file, elf_head_p, p_scns,
1733 1734 num_scns, filename);
1734 1735 }
1735 1736 }
1736 1737
1737 1738 /*
1738 1739 * Load the archive string table(s) (for extended-length strings)
1739 1740 * into an in-core table/list
1740 1741 */
1741 1742 static struct stab_list_s *
1742 1743 load_arstring_table(struct stab_list_s *STabList,
1743 1744 int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
1744 1745 {
1745 1746 off_t here;
1746 1747 struct stab_list_s *STL_entry, *STL_next;
1747 1748
1748 1749 if (p_ar) {
1749 1750 STL_entry = malloc(sizeof (struct stab_list_s));
1750 1751 STL_entry->next = 0;
1751 1752 STL_entry->strings = 0;
1752 1753 STL_entry->size = 0;
1753 1754
1754 1755 if (!STabList)
1755 1756 STabList = STL_entry;
1756 1757 else {
1757 1758 STL_next = STabList;
1758 1759 while (STL_next->next != (void *)0)
1759 1760 STL_next = STL_next->next;
1760 1761 STL_next->next = STL_entry;
1761 1762 }
1762 1763
1763 1764 STL_entry->size = p_ar->ar_size;
1764 1765 STL_entry->strings = malloc(p_ar->ar_size);
1765 1766 here = elf_getbase(elf_file);
1766 1767 if ((lseek(fd, here, 0)) != here) {
1767 1768 (void) fprintf(stderr,
1768 1769 "%s: %s: could not lseek\n", prog_name, filename);
1769 1770 }
1770 1771
1771 1772 if ((read(fd, STL_entry->strings, p_ar->ar_size)) == -1) {
1772 1773 (void) fprintf(stderr,
1773 1774 "%s: %s: could not read\n", prog_name, filename);
1774 1775 }
1775 1776 }
1776 1777 return (STabList);
1777 1778 }
1778 1779
1779 1780 /*
1780 1781 * Print the archive header for each member of an archive.
1781 1782 * Also call ar_sym_read to print the symbols in the
1782 1783 * archive symbol table if g_flag. Input is a file descriptor,
1783 1784 * an ELF file descriptor, and the filename. Putting the call
1784 1785 * to dump the archive symbol table in this function is more
1785 1786 * efficient since it is necessary to examine the archive member
1786 1787 * name in the archive header to determine which member is the
1787 1788 * symbol table.
1788 1789 */
1789 1790 static void
1790 1791 dump_ar_hdr(int fd, Elf *elf_file, char *filename)
1791 1792 {
1792 1793 extern int v_flag, g_flag, a_flag, p_flag;
1793 1794 Elf_Arhdr *p_ar;
1794 1795 Elf *arf;
1795 1796 Elf_Cmd cmd;
1796 1797 int title = 0;
1797 1798 int err = 0;
1798 1799
1799 1800 char buf[DATESIZE];
1800 1801
1801 1802 cmd = ELF_C_READ;
1802 1803 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1803 1804 p_ar = elf_getarhdr(arf);
1804 1805 if (p_ar == NULL) {
1805 1806 (void) fprintf(stderr,
1806 1807 "%s: %s: %s\n", prog_name, filename,
1807 1808 elf_errmsg(-1));
1808 1809 continue;
1809 1810 }
1810 1811 if ((strcmp(p_ar->ar_name, "/") == 0) ||
1811 1812 (strcmp(p_ar->ar_name, "/SYM64/") == 0)) {
1812 1813 if (g_flag)
1813 1814 ar_sym_read(elf_file, filename);
1814 1815 } else if (strcmp(p_ar->ar_name, "//") == 0) {
1815 1816 StringTableList = load_arstring_table(
1816 1817 StringTableList, fd, arf, p_ar, filename);
1817 1818 cmd = elf_next(arf);
1818 1819 (void) elf_end(arf);
1819 1820 continue;
1820 1821 } else {
1821 1822 if (a_flag) {
1822 1823 (void) printf("%s[%s]:\n", filename,
1823 1824 p_ar->ar_name);
1824 1825 if (!p_flag && title == 0) {
1825 1826 if (!v_flag)
1826 1827 (void) printf(
1827 1828 "\n\n\t\t\t***ARCHIVE HEADER***"
1828 1829 "\n Date Uid Gid Mode Size Member Name\n\n");
1829 1830 else
1830 1831 (void) printf(
1831 1832 "\n\n\t\t\t***ARCHIVE HEADER***"
1832 1833 "\n Date Uid Gid Mode Size Member Name\n\n");
1833 1834 title = 1;
1834 1835 }
1835 1836 if (!v_flag) {
1836 1837 (void) printf(
1837 1838 "\t0x%.8lx %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1838 1839 p_ar->ar_date, (int)p_ar->ar_uid,
1839 1840 (int)p_ar->ar_gid,
1840 1841 (int)p_ar->ar_mode,
1841 1842 p_ar->ar_size, p_ar->ar_name);
1842 1843 } else {
1843 1844 if ((strftime(buf, DATESIZE,
1844 1845 "%b %d %H:%M:%S %Y",
1845 1846 localtime(
1846 1847 &(p_ar->ar_date)))) == 0) {
1847 1848 (void) fprintf(stderr,
1848 1849 "%s: %s: don't have enough space to store the date\n", prog_name, filename);
1849 1850 exit(1);
1850 1851 }
1851 1852 (void) printf(
1852 1853 "\t%s %6d %6d 0%.6ho 0x%.8lx %-s\n\n",
1853 1854 buf, (int)p_ar->ar_uid,
1854 1855 (int)p_ar->ar_gid,
1855 1856 (int)p_ar->ar_mode,
1856 1857 p_ar->ar_size, p_ar->ar_name);
1857 1858 }
1858 1859 }
1859 1860 }
1860 1861 cmd = elf_next(arf);
1861 1862 (void) elf_end(arf);
1862 1863 } /* end while */
1863 1864
1864 1865 err = elf_errno();
1865 1866 if (err != 0) {
1866 1867 (void) fprintf(stderr,
1867 1868 "%s: %s: %s\n", prog_name, filename, elf_errmsg(err));
1868 1869 }
1869 1870 }
1870 1871
1871 1872 /*
1872 1873 * Process member files of an archive. This function provides
1873 1874 * a loop through an archive equivalent the processing of
1874 1875 * each_file for individual object files.
1875 1876 */
1876 1877 static void
1877 1878 dump_ar_files(int fd, Elf *elf_file, char *filename)
1878 1879 {
1879 1880 Elf_Arhdr *p_ar;
1880 1881 Elf *arf;
1881 1882 Elf_Cmd cmd;
1882 1883 Elf_Kind file_type;
1883 1884 GElf_Ehdr elf_head;
1884 1885 char *fullname;
1885 1886
1886 1887 cmd = ELF_C_READ;
1887 1888 while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
1888 1889 size_t len;
1889 1890
1890 1891 p_ar = elf_getarhdr(arf);
1891 1892 if (p_ar == NULL) {
1892 1893 (void) fprintf(stderr, "%s: %s: %s\n",
1893 1894 prog_name, filename, elf_errmsg(-1));
1894 1895 return;
1895 1896 }
1896 1897 if (p_ar->ar_name[0] == '/') {
1897 1898 cmd = elf_next(arf);
1898 1899 (void) elf_end(arf);
1899 1900 continue;
1900 1901 }
1901 1902
1902 1903 len = strlen(filename) + strlen(p_ar->ar_name) + 3;
1903 1904 if ((fullname = malloc(len)) == NULL)
1904 1905 return;
1905 1906 (void) snprintf(fullname, len, "%s[%s]", filename,
1906 1907 p_ar->ar_name);
1907 1908 (void) printf("\n%s:\n", fullname);
1908 1909 file_type = elf_kind(arf);
1909 1910 if (file_type == ELF_K_ELF) {
1910 1911 if (dump_elf_header(arf, fullname, &elf_head) == NULL)
1911 1912 return;
1912 1913 if (o_flag)
1913 1914 dump_exec_header(arf,
1914 1915 (unsigned)elf_head.e_phnum, fullname);
1915 1916 if (x_flag)
1916 1917 dump_section_table(arf, &elf_head, fullname);
1917 1918 } else {
1918 1919 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1919 1920 prog_name, fullname);
1920 1921 cmd = elf_next(arf);
1921 1922 (void) elf_end(arf);
1922 1923 continue;
1923 1924 }
1924 1925
1925 1926 cmd = elf_next(arf);
1926 1927 (void) elf_end(arf);
1927 1928 } /* end while */
1928 1929 }
1929 1930
1930 1931 /*
1931 1932 * Takes a filename as input. Test first for a valid version
1932 1933 * of libelf.a and exit on error. Process each valid file
1933 1934 * or archive given as input on the command line. Check
1934 1935 * for file type. If it is an archive, process the archive-
1935 1936 * specific options first, then files within the archive.
1936 1937 * If it is an ELF object file, process it; otherwise
1937 1938 * warn that it is an invalid file type.
1938 1939 * All options except the archive-specific and program
1939 1940 * execution header are processed in the function, dump_section_table.
1940 1941 */
1941 1942 static void
1942 1943 each_file(char *filename)
1943 1944 {
1944 1945 Elf *elf_file;
1945 1946 GElf_Ehdr elf_head;
1946 1947 int fd;
1947 1948 Elf_Kind file_type;
1948 1949
1949 1950 struct stat buf;
1950 1951
1951 1952 Elf_Cmd cmd;
1952 1953 errno = 0;
1953 1954
1954 1955 if (stat(filename, &buf) == -1) {
1955 1956 int err = errno;
1956 1957 (void) fprintf(stderr, "%s: %s: %s", prog_name, filename,
1957 1958 strerror(err));
1958 1959 return;
1959 1960 }
1960 1961
1961 1962 if ((fd = open((filename), O_RDONLY)) == -1) {
1962 1963 (void) fprintf(stderr, "%s: %s: cannot read\n", prog_name,
1963 1964 filename);
1964 1965 return;
1965 1966 }
1966 1967 cmd = ELF_C_READ;
1967 1968 if ((elf_file = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
1968 1969 (void) fprintf(stderr, "%s: %s: %s\n", prog_name, filename,
1969 1970 elf_errmsg(-1));
1970 1971 return;
1971 1972 }
1972 1973
1973 1974 file_type = elf_kind(elf_file);
1974 1975 if (file_type == ELF_K_AR) {
1975 1976 if (a_flag || g_flag) {
1976 1977 dump_ar_hdr(fd, elf_file, filename);
1977 1978 elf_file = elf_begin(fd, cmd, (Elf *)0);
1978 1979 }
1979 1980 if (z_flag)
1980 1981 dump_ar_files(fd, elf_file, filename);
1981 1982 } else {
1982 1983 if (file_type == ELF_K_ELF) {
1983 1984 (void) printf("\n%s:\n", filename);
1984 1985 if (dump_elf_header(elf_file, filename, &elf_head)) {
1985 1986 if (o_flag)
1986 1987 dump_exec_header(elf_file,
1987 1988 (unsigned)elf_head.e_phnum,
1988 1989 filename);
1989 1990 if (x_flag)
1990 1991 dump_section_table(elf_file,
1991 1992 &elf_head, filename);
1992 1993 }
1993 1994 } else {
1994 1995 (void) fprintf(stderr, "%s: %s: invalid file type\n",
1995 1996 prog_name, filename);
1996 1997 }
1997 1998 }
1998 1999 (void) elf_end(elf_file);
1999 2000 (void) close(fd);
2000 2001 }
2001 2002
2002 2003 /*
2003 2004 * Sets up flags for command line options given and then
2004 2005 * calls each_file() to process each file.
2005 2006 */
2006 2007 int
2007 2008 main(int argc, char *argv[], char *envp[])
2008 2009 {
2009 2010 char *optstr = OPTSTR; /* option string used by getopt() */
2010 2011 int optchar;
2011 2012
2012 2013 /*
2013 2014 * Check for a binary that better fits this architecture.
2014 2015 */
2015 2016 (void) conv_check_native(argv, envp);
2016 2017
2017 2018 prog_name = argv[0];
2018 2019
2019 2020 (void) setlocale(LC_ALL, "");
2020 2021 while ((optchar = getopt(argc, argv, optstr)) != -1) {
2021 2022 switch (optchar) {
2022 2023 case 'a':
2023 2024 a_flag = 1;
2024 2025 x_flag = 1;
2025 2026 break;
2026 2027 case 'g':
2027 2028 g_flag = 1;
2028 2029 x_flag = 1;
2029 2030 break;
2030 2031 case 'v':
2031 2032 v_flag = 1;
2032 2033 break;
2033 2034 case 'p':
2034 2035 p_flag = 1;
2035 2036 break;
2036 2037 case 'f':
2037 2038 f_flag = 1;
2038 2039 z_flag = 1;
2039 2040 break;
2040 2041 case 'o':
2041 2042 o_flag = 1;
2042 2043 z_flag = 1;
2043 2044 break;
2044 2045 case 'h':
2045 2046 h_flag = 1;
2046 2047 x_flag = 1;
2047 2048 z_flag = 1;
2048 2049 break;
2049 2050 case 's':
2050 2051 s_flag = 1;
2051 2052 x_flag = 1;
2052 2053 z_flag = 1;
2053 2054 break;
2054 2055 case 'd':
2055 2056 d_flag = 1;
2056 2057 x_flag = 1;
2057 2058 z_flag = 1;
2058 2059 set_range(optarg, &d_low, &d_hi);
2059 2060 break;
2060 2061 case 'n':
2061 2062 n_flag++;
2062 2063 x_flag = 1;
2063 2064 z_flag = 1;
2064 2065 name = optarg;
2065 2066 break;
2066 2067 case 'r':
2067 2068 r_flag = 1;
2068 2069 x_flag = 1;
2069 2070 z_flag = 1;
2070 2071 break;
2071 2072 case 't':
2072 2073 t_flag = 1;
2073 2074 x_flag = 1;
2074 2075 z_flag = 1;
2075 2076 break;
2076 2077 case 'C':
2077 2078 C_flag = 1;
2078 2079 t_flag = 1;
2079 2080 x_flag = 1;
2080 2081 z_flag = 1;
2081 2082 break;
2082 2083 case 'T':
2083 2084 T_flag = 1;
2084 2085 x_flag = 1;
2085 2086 z_flag = 1;
2086 2087 set_range(optarg, &T_low, &T_hi);
2087 2088 break;
2088 2089 case 'c':
2089 2090 c_flag = 1;
2090 2091 x_flag = 1;
2091 2092 z_flag = 1;
2092 2093 break;
2093 2094 case 'L':
2094 2095 L_flag = 1;
2095 2096 x_flag = 1;
2096 2097 z_flag = 1;
2097 2098 break;
2098 2099 case 'V':
2099 2100 V_flag = 1;
2100 2101 (void) fprintf(stderr, "dump: %s %s\n",
2101 2102 (const char *)SGU_PKG,
2102 2103 (const char *)SGU_REL);
2103 2104 break;
2104 2105 case '?':
2105 2106 errflag += 1;
2106 2107 break;
2107 2108 default:
2108 2109 break;
2109 2110 }
2110 2111 }
2111 2112
2112 2113 if (errflag || (optind >= argc) || (!z_flag && !x_flag)) {
2113 2114 if (!(V_flag && (argc == 2))) {
2114 2115 usage();
2115 2116 exit(269);
2116 2117 }
2117 2118 }
2118 2119
2119 2120 if (elf_version(EV_CURRENT) == EV_NONE) {
2120 2121 (void) fprintf(stderr, "%s: libelf is out of date\n",
2121 2122 prog_name);
2122 2123 exit(101);
2123 2124 }
2124 2125
2125 2126 while (optind < argc) {
2126 2127 each_file(argv[optind]);
2127 2128 optind++;
2128 2129 }
2129 2130 return (0);
2130 2131 }
↓ open down ↓ |
893 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX