Print this page
2940 elfdump should return non-null on invalid file type
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/elfdump/common/main.c
+++ new/usr/src/cmd/sgs/elfdump/common/main.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) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Dump an elf file.
28 28 */
29 29 #include <sys/param.h>
30 30 #include <fcntl.h>
31 31 #include <stdio.h>
32 32 #include <stdlib.h>
33 33 #include <ctype.h>
34 34 #include <_libelf.h>
35 35 #include <link.h>
36 36 #include <stdarg.h>
37 37 #include <unistd.h>
38 38 #include <libgen.h>
39 39 #include <libintl.h>
40 40 #include <locale.h>
41 41 #include <errno.h>
42 42 #include <strings.h>
43 43 #include <debug.h>
44 44 #include <conv.h>
45 45 #include <msg.h>
46 46 #include <_elfdump.h>
47 47 #include <sys/elf_SPARC.h>
48 48 #include <sys/elf_amd64.h>
49 49
50 50
51 51 const Cache cache_init = {NULL, NULL, NULL, NULL, 0};
52 52
53 53
54 54
55 55 /*
56 56 * The -I, -N, and -T options are called "match options", because
57 57 * they allow selecting the items to be displayed based on matching
58 58 * their index, name, or type.
59 59 *
60 60 * The ELF information to which -I, -N, or -T are applied in
61 61 * the current invocation is called the "match item".
62 62 */
63 63 typedef enum {
64 64 MATCH_ITEM_PT, /* Program header (PT_) */
65 65 MATCH_ITEM_SHT /* Section header (SHT_) */
66 66 } match_item_t;
67 67
68 68 /* match_opt_t is used to note which match option was used */
69 69 typedef enum {
70 70 MATCH_OPT_NAME, /* Record contains a name */
71 71 MATCH_OPT_NDX, /* Record contains a single index */
72 72 MATCH_OPT_RANGE, /* Record contains an index range */
73 73 MATCH_OPT_TYPE, /* Record contains a type (shdr or phdr) */
74 74 } match_opt_t;
75 75
76 76 typedef struct _match {
77 77 struct _match *next; /* Pointer to next item in list */
78 78 match_opt_t opt_type;
79 79 union {
80 80 const char *name; /* MATCH_OPT_NAME */
81 81 struct { /* MATCH_OPT_NDX and MATCH_OPT_RANGE */
82 82 int start;
83 83 int end; /* Only for MATCH_OPT_RANGE */
84 84 } ndx;
85 85 uint32_t type; /* MATCH_OPT_TYPE */
86 86 } value;
87 87 } match_rec_t;
88 88
89 89 static struct {
90 90 match_item_t item_type; /* Type of item being matched */
91 91 match_rec_t *list; /* Records for (-I, -N, -T) options */
92 92 } match_state;
93 93
94 94
95 95
96 96 const char *
97 97 _elfdump_msg(Msg mid)
98 98 {
99 99 return (gettext(MSG_ORIG(mid)));
100 100 }
101 101
102 102 /*
103 103 * Determine whether a symbol name should be demangled.
104 104 */
105 105 const char *
106 106 demangle(const char *name, uint_t flags)
107 107 {
108 108 if (flags & FLG_CTL_DEMANGLE)
109 109 return (Elf_demangle_name(name));
110 110 else
111 111 return ((char *)name);
112 112 }
113 113
114 114 /*
115 115 * Define our own standard error routine.
116 116 */
117 117 void
118 118 failure(const char *file, const char *func)
119 119 {
120 120 (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE),
121 121 file, func, elf_errmsg(elf_errno()));
122 122 }
123 123
124 124 /*
125 125 * The full usage message
126 126 */
127 127 static void
128 128 detail_usage()
129 129 {
130 130 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1));
131 131 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2));
132 132 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3));
133 133 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4));
134 134 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5));
135 135 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6));
136 136 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7));
137 137 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8));
138 138 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9));
139 139 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10));
140 140 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11));
141 141 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12));
142 142 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13));
143 143 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14));
144 144 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15));
145 145 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16));
146 146 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17));
147 147 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18));
148 148 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19));
149 149 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20));
150 150 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21));
151 151 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22));
152 152 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23));
153 153 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24));
154 154 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25));
155 155 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26));
156 156 }
157 157
158 158 /*
159 159 * Output a block of raw data as hex bytes. Each row is given
160 160 * the index of the first byte in the row.
161 161 *
162 162 * entry:
163 163 * data - Pointer to first byte of data to be displayed
164 164 * n - # of bytes of data
165 165 * prefix - String to be output before each line. Useful
166 166 * for indenting output.
167 167 * bytes_per_col - # of space separated bytes to output
168 168 * in each column.
169 169 * col_per_row - # of columns to output per row
170 170 *
171 171 * exit:
172 172 * The formatted data has been sent to stdout. Each row of output
173 173 * shows (bytes_per_col * col_per_row) bytes of data.
174 174 */
175 175 void
176 176 dump_hex_bytes(const void *data, size_t n, int indent,
177 177 int bytes_per_col, int col_per_row)
178 178 {
179 179 const uchar_t *ldata = data;
180 180 int bytes_per_row = bytes_per_col * col_per_row;
181 181 int ndx, byte, word;
182 182 char string[128], *str = string;
183 183 char index[MAXNDXSIZE];
184 184 int index_width;
185 185 int sp_prefix = 0;
186 186
187 187
188 188 /*
189 189 * Determine the width to use for the index string. We follow
190 190 * 8-byte tab rules, but don't use an actual \t character so
191 191 * that the output can be arbitrarily shifted without odd
192 192 * tab effects, and so that all the columns line up no matter
193 193 * how many lines of output are produced.
194 194 */
195 195 ndx = n / bytes_per_row;
196 196 (void) snprintf(index, sizeof (index),
197 197 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
198 198 index_width = strlen(index);
199 199 index_width = S_ROUND(index_width, 8);
200 200
201 201 for (ndx = byte = word = 0; n > 0; n--, ldata++) {
202 202 while (sp_prefix-- > 0)
203 203 *str++ = ' ';
204 204
205 205 (void) snprintf(str, sizeof (string),
206 206 MSG_ORIG(MSG_HEXDUMP_TOK), (int)*ldata);
207 207 str += 2;
208 208 sp_prefix = 1;
209 209
210 210 if (++byte == bytes_per_col) {
211 211 sp_prefix += 2;
212 212 word++;
213 213 byte = 0;
214 214 }
215 215 if (word == col_per_row) {
216 216 *str = '\0';
217 217 (void) snprintf(index, sizeof (index),
218 218 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
219 219 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW),
220 220 indent, MSG_ORIG(MSG_STR_EMPTY),
221 221 index_width, index, string);
222 222 sp_prefix = 0;
223 223 word = 0;
224 224 ndx += bytes_per_row;
225 225 str = string;
226 226 }
227 227 }
228 228 if (byte || word) {
229 229 *str = '\0'; /* */
230 230 (void) snprintf(index, sizeof (index),
231 231 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx));
232 232 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW), indent,
233 233 MSG_ORIG(MSG_STR_EMPTY), index_width, index, string);
234 234 }
235 235 }
236 236
237 237 /*
238 238 * Convert the ASCII representation of an index, or index range, into
239 239 * binary form, and store it in rec:
240 240 *
241 241 * index: An positive or 0 valued integer
242 242 * range: Two indexes, separated by a ':' character, denoting
243 243 * a range of allowed values. If the second value is omitted,
244 244 * any values equal to or greater than the first will match.
245 245 *
246 246 * exit:
247 247 * On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE
248 248 * value, and this function returns (1). On failure, the contents
249 249 * of *rec are undefined, and (0) is returned.
250 250 */
251 251 int
252 252 process_index_opt(const char *str, match_rec_t *rec)
253 253 {
254 254 #define SKIP_BLANK for (; *str && isspace(*str); str++)
255 255
256 256 char *endptr;
257 257
258 258 rec->value.ndx.start = strtol(str, &endptr, 10);
259 259 /* Value must use some of the input, and be 0 or positive */
260 260 if ((str == endptr) || (rec->value.ndx.start < 0))
261 261 return (0);
262 262 str = endptr;
263 263
264 264 SKIP_BLANK;
265 265 if (*str != ':') {
266 266 rec->opt_type = MATCH_OPT_NDX;
267 267 } else {
268 268 str++; /* Skip the ':' */
269 269 rec->opt_type = MATCH_OPT_RANGE;
270 270 SKIP_BLANK;
271 271 if (*str == '\0') {
272 272 rec->value.ndx.end = -1; /* Indicates "to end" */
273 273 } else {
274 274 rec->value.ndx.end = strtol(str, &endptr, 10);
275 275 if ((str == endptr) || (rec->value.ndx.end < 0))
276 276 return (0);
277 277 str = endptr;
278 278 SKIP_BLANK;
279 279 }
280 280 }
281 281
282 282 /* Syntax error if anything is left over */
283 283 if (*str != '\0')
284 284 return (0);
285 285
286 286 return (1);
287 287
288 288 #undef SKIP_BLANK
289 289 }
290 290
291 291 /*
292 292 * Convert a string containing a specific type of ELF constant, or an ASCII
293 293 * representation of a number, to an integer. Strings starting with '0'
294 294 * are taken to be octal, those staring with '0x' are hex, and all
295 295 * others are decimal.
296 296 *
297 297 * entry:
298 298 * str - String to be converted
299 299 * ctype - Constant type
300 300 * v - Address of variable to receive resulting value.
301 301 *
302 302 * exit:
303 303 * On success, returns True (1) and *v is set to the value.
304 304 * On failure, returns False (0) and *v is undefined.
305 305 */
306 306 typedef enum {
307 307 ATOUI_PT,
308 308 ATOUI_SHT,
309 309 ATOUI_OSABI
310 310 } atoui_type_t;
311 311
312 312 static int
313 313 atoui(const char *str, atoui_type_t type, uint32_t *v)
314 314 {
315 315 conv_strtol_uvalue_t uvalue;
316 316 char *endptr;
317 317
318 318 if (conv_iter_strtol_init(str, &uvalue) != 0) {
319 319 switch (type) {
320 320 case ATOUI_PT:
321 321 if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF,
322 322 conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
323 323 break;
324 324 (void) conv_iter_phdr_type(CONV_OSABI_ALL,
325 325 CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
326 326 break;
327 327 case ATOUI_SHT:
328 328 if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
329 329 CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) ==
330 330 CONV_ITER_DONE)
331 331 break;
332 332 (void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
333 333 CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
334 334 break;
335 335 case ATOUI_OSABI:
336 336 if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF,
337 337 conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
338 338 break;
339 339 (void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF,
340 340 conv_iter_strtol, &uvalue);
341 341 break;
342 342 }
343 343 if (uvalue.csl_found) {
344 344 *v = uvalue.csl_value;
345 345 return (1);
346 346 }
347 347 }
348 348
349 349 *v = strtoull(str, &endptr, 0);
350 350
351 351 /* If the left over part contains anything but whitespace, fail */
352 352 for (; *endptr; endptr++)
353 353 if (!isspace(*endptr))
354 354 return (0);
355 355 return (1);
356 356 }
357 357
358 358 /*
359 359 * Called after getopt() processing is finished if there is a non-empty
360 360 * match list. Prepares the matching code for use.
361 361 *
362 362 * exit:
363 363 * Returns True (1) if no errors are encountered. Writes an
364 364 * error string to stderr and returns False (0) otherwise.
365 365 */
366 366 static int
367 367 match_prepare(char *argv0, uint_t flags)
368 368 {
369 369 match_rec_t *list;
370 370 const char *str;
371 371 int minus_p = (flags & FLG_SHOW_PHDR) != 0;
372 372 atoui_type_t atoui_type;
373 373
374 374 /*
375 375 * Flag ambiguous attempt to use match option with both -p and
376 376 * and one or more section SHOW options. In this case, we
377 377 * can't tell what type of item we're supposed to match against.
378 378 */
379 379 if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) {
380 380 (void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH),
381 381 basename(argv0));
382 382 return (0);
383 383 }
384 384
385 385 /* Set the match type, based on the presence of the -p option */
386 386 if (minus_p) {
387 387 match_state.item_type = MATCH_ITEM_PT;
388 388 atoui_type = ATOUI_PT;
389 389 } else {
390 390 match_state.item_type = MATCH_ITEM_SHT;
391 391 atoui_type = ATOUI_SHT;
392 392 }
393 393
394 394 /*
395 395 * Scan match list and perform any necessary fixups:
396 396 *
397 397 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N)
398 398 * requests into MATCH_OPT_TYPE (-T).
399 399 *
400 400 * MATCH_OPT_TYPE: Now that we know item type we are matching
401 401 * against, we can convert the string saved in the name
402 402 * field during getopt() processing into an integer and
403 403 * write it into the type field.
404 404 */
405 405 for (list = match_state.list; list; list = list->next) {
406 406 if ((list->opt_type == MATCH_OPT_NAME) && minus_p)
407 407 list->opt_type = MATCH_OPT_TYPE;
408 408
409 409 if (list->opt_type != MATCH_OPT_TYPE)
410 410 continue;
411 411
412 412 str = list->value.name;
413 413 if (atoui(str, atoui_type, &list->value.type) == 0) {
414 414 const char *fmt = minus_p ?
415 415 MSG_INTL(MSG_ERR_BAD_T_PT) :
416 416 MSG_INTL(MSG_ERR_BAD_T_SHT);
417 417
418 418 (void) fprintf(stderr, fmt, basename(argv0), str);
419 419 return (0);
420 420 }
421 421 }
422 422
423 423 return (1);
424 424 }
425 425
426 426
427 427 /*
428 428 * Returns True (1) if the item with the given name or index should
429 429 * be displayed, and False (0) if it should not be.
430 430 *
431 431 * entry:
432 432 * match_flags - Bitmask specifying matching options, as described
433 433 * in _elfdump.h.
434 434 * name - If MATCH_F_NAME flag is set, name of item under
435 435 * consideration. Otherwise ignored.
436 436 * should not be considered.
437 437 * ndx - If MATCH_F_NDX flag is set, index of item under consideration.
438 438 * type - If MATCH_F_TYPE is set, type of item under consideration.
439 439 * If MATCH_F_PHDR is set, this would be a program
440 440 * header type (PT_). Otherwise, a section header type (SHT_).
441 441 *
442 442 * exit:
443 443 * True will be returned if the given name/index matches those given
444 444 * by one of the (-I, -N -T) command line options, or if no such option
445 445 * was used in the command invocation and MATCH_F_STRICT is not
446 446 * set.
447 447 */
448 448 int
449 449 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type)
450 450 {
451 451 match_item_t item_type = (match_flags & MATCH_F_PHDR) ?
452 452 MATCH_ITEM_PT : MATCH_ITEM_SHT;
453 453 match_rec_t *list;
454 454
455 455 /*
456 456 * If there is no match list, then we use the MATCH_F_STRICT
457 457 * flag to decide what to return. In the strict case, we return
458 458 * False (0), in the normal case, True (1).
459 459 */
460 460 if (match_state.list == NULL)
461 461 return ((match_flags & MATCH_F_STRICT) == 0);
462 462
463 463 /*
464 464 * If item being checked is not the current match type,
465 465 * then allow it.
466 466 */
467 467 if (item_type != match_state.item_type)
468 468 return (1);
469 469
470 470 /* Run through the match records and check for a hit */
471 471 for (list = match_state.list; list; list = list->next) {
472 472 switch (list->opt_type) {
473 473 case MATCH_OPT_NAME:
474 474 if (((match_flags & MATCH_F_NAME) == 0) ||
475 475 (name == NULL))
476 476 break;
477 477 if (strcmp(list->value.name, name) == 0)
478 478 return (1);
479 479 break;
480 480 case MATCH_OPT_NDX:
481 481 if ((match_flags & MATCH_F_NDX) &&
482 482 (ndx == list->value.ndx.start))
483 483 return (1);
484 484 break;
485 485 case MATCH_OPT_RANGE:
486 486 /*
487 487 * A range end value less than 0 means that any value
488 488 * above the start is acceptible.
489 489 */
490 490 if ((match_flags & MATCH_F_NDX) &&
491 491 (ndx >= list->value.ndx.start) &&
492 492 ((list->value.ndx.end < 0) ||
493 493 (ndx <= list->value.ndx.end)))
494 494 return (1);
495 495 break;
496 496
497 497 case MATCH_OPT_TYPE:
498 498 if ((match_flags & MATCH_F_TYPE) &&
499 499 (type == list->value.type))
500 500 return (1);
501 501 break;
502 502 }
503 503 }
504 504
505 505 /* Nothing matched */
506 506 return (0);
507 507 }
508 508
509 509 /*
510 510 * Add an entry to match_state.list for use by match(). This routine is for
511 511 * use during getopt() processing. It should not be called once
512 512 * match_prepare() has been called.
513 513 *
514 514 * Return True (1) for success. On failure, an error is written
515 515 * to stderr, and False (0) is returned.
516 516 */
517 517 static int
518 518 add_match_record(char *argv0, match_rec_t *data)
519 519 {
520 520 match_rec_t *rec;
521 521 match_rec_t *list;
522 522
523 523 if ((rec = malloc(sizeof (*rec))) == NULL) {
524 524 int err = errno;
525 525 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
526 526 basename(argv0), strerror(err));
527 527 return (0);
528 528 }
529 529
530 530 *rec = *data;
531 531
532 532 /* Insert at end of match_state.list */
533 533 if (match_state.list == NULL) {
534 534 match_state.list = rec;
535 535 } else {
536 536 for (list = match_state.list; list->next != NULL;
537 537 list = list->next)
538 538 ;
539 539 list->next = rec;
540 540 }
541 541
542 542 rec->next = NULL;
543 543 return (1);
544 544 }
545 545
546 546 static int
547 547 decide(const char *file, int fd, Elf *elf, uint_t flags,
548 548 const char *wname, int wfd, uchar_t osabi)
549 549 {
550 550 int r;
551 551
552 552 if (gelf_getclass(elf) == ELFCLASS64)
553 553 r = regular64(file, fd, elf, flags, wname, wfd, osabi);
554 554 else
555 555 r = regular32(file, fd, elf, flags, wname, wfd, osabi);
556 556
557 557 return (r);
558 558 }
559 559
560 560 static int
561 561 archive(const char *file, int fd, Elf *elf, uint_t flags,
562 562 const char *wname, int wfd, uchar_t osabi)
563 563 {
564 564 Elf_Cmd cmd = ELF_C_READ;
565 565 Elf_Arhdr *arhdr;
566 566 Elf *_elf = NULL;
567 567 size_t ptr;
568 568 Elf_Arsym *arsym = NULL;
569 569
570 570 /*
571 571 * Determine if the archive symbol table itself is required.
572 572 */
573 573 if ((flags & FLG_SHOW_SYMBOLS) &&
574 574 match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
575 575 /*
576 576 * Get the archive symbol table.
577 577 */
578 578 if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
579 579 /*
580 580 * The arsym could be 0 even though there was no error.
581 581 * Print the error message only when there was
582 582 * real error from elf_getarsym().
583 583 */
584 584 failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
585 585 return (0);
586 586 }
587 587 }
588 588
589 589 /*
590 590 * Print the archive symbol table only when the archive symbol
591 591 * table exists and it was requested to print.
592 592 */
593 593 if (arsym) {
594 594 size_t cnt;
595 595 char index[MAXNDXSIZE];
596 596 size_t offset = 0, _offset = 0;
597 597 const char *fmt_arsym1, *fmt_arsym2;
598 598
599 599 /*
600 600 * Print out all the symbol entries. The format width used
601 601 * corresponds to whether the archive symbol table is 32
602 602 * or 64-bit. We see them via Elf_Arhdr as size_t values
603 603 * in either case with no information loss (see the comments
604 604 * in libelf/getarsym.c) so this is done simply to improve
605 605 * the user presentation.
606 606 */
607 607 if (_elf_getarsymwordsize(elf) == 8) {
608 608 dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
609 609 dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));
610 610
611 611 fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
612 612 fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
613 613 } else {
614 614 dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
615 615 dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));
616 616
617 617 fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
618 618 fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
619 619 }
620 620
621 621 for (cnt = 0; cnt < ptr; cnt++, arsym++) {
622 622 /*
623 623 * For each object obtain an elf descriptor so that we
624 624 * can establish the members name. Note, we have had
625 625 * archives where the archive header has not been
626 626 * obtainable so be lenient with errors.
627 627 */
628 628 if ((offset == 0) || ((arsym->as_off != 0) &&
629 629 (arsym->as_off != _offset))) {
630 630
631 631 if (_elf)
632 632 (void) elf_end(_elf);
633 633
634 634 if (elf_rand(elf, arsym->as_off) !=
635 635 arsym->as_off) {
636 636 failure(file, MSG_ORIG(MSG_ELF_RAND));
637 637 arhdr = NULL;
638 638 } else if ((_elf = elf_begin(fd,
639 639 ELF_C_READ, elf)) == 0) {
640 640 failure(file, MSG_ORIG(MSG_ELF_BEGIN));
641 641 arhdr = NULL;
642 642 } else if ((arhdr = elf_getarhdr(_elf)) == 0) {
643 643 failure(file,
644 644 MSG_ORIG(MSG_ELF_GETARHDR));
645 645 arhdr = NULL;
646 646 }
647 647
648 648 _offset = arsym->as_off;
649 649 if (offset == 0)
650 650 offset = _offset;
651 651 }
652 652
653 653 (void) snprintf(index, MAXNDXSIZE,
654 654 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
655 655 if (arsym->as_off)
656 656 dbg_print(0, fmt_arsym1, index,
657 657 EC_XWORD(arsym->as_off),
658 658 arhdr ? arhdr->ar_name :
659 659 MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
660 660 demangle(arsym->as_name, flags) :
661 661 MSG_INTL(MSG_STR_NULL)));
662 662 else
663 663 dbg_print(0, fmt_arsym2, index,
664 664 EC_XWORD(arsym->as_off));
665 665 }
666 666
667 667 if (_elf)
668 668 (void) elf_end(_elf);
669 669
670 670 /*
671 671 * If we only need the archive symbol table return.
672 672 */
673 673 if ((flags & FLG_SHOW_SYMBOLS) &&
674 674 match(MATCH_F_STRICT | MATCH_F_NAME,
675 675 MSG_ORIG(MSG_ELF_ARSYM), -1, -1))
676 676 return (0);
677 677
678 678 /*
679 679 * Reset elf descriptor in preparation for processing each
680 680 * member.
681 681 */
682 682 if (offset)
683 683 (void) elf_rand(elf, offset);
684 684 }
685 685
686 686 /*
687 687 * Process each object within the archive.
688 688 */
689 689 while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
690 690 char name[MAXPATHLEN];
691 691
692 692 if ((arhdr = elf_getarhdr(_elf)) == NULL) {
693 693 failure(file, MSG_ORIG(MSG_ELF_GETARHDR));
694 694 return (0);
695 695 }
696 696 if (*arhdr->ar_name != '/') {
697 697 (void) snprintf(name, MAXPATHLEN,
698 698 MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name);
699 699 dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name);
700 700
701 701 switch (elf_kind(_elf)) {
702 702 case ELF_K_AR:
703 703 if (archive(name, fd, _elf, flags,
704 704 wname, wfd, osabi) == 1)
705 705 return (1);
706 706 break;
707 707 case ELF_K_ELF:
708 708 if (decide(name, fd, _elf, flags,
709 709 wname, wfd, osabi) == 1)
710 710 return (1);
711 711 break;
712 712 default:
713 713 (void) fprintf(stderr,
714 714 MSG_INTL(MSG_ERR_BADFILE), name);
715 715 break;
716 716 }
717 717 }
718 718
719 719 cmd = elf_next(_elf);
720 720 (void) elf_end(_elf);
721 721 }
722 722
723 723 return (0);
724 724 }
725 725
726 726 int
727 727 main(int argc, char **argv, char **envp)
728 728 {
729 729 Elf *elf;
730 730 int var, fd, wfd = 0;
731 731 char *wname = NULL;
732 732 uint_t flags = 0;
733 733 match_rec_t match_data;
734 734 int ret;
735 735 uchar_t osabi;
736 736
737 737 /*
738 738 * If we're on a 64-bit kernel, try to exec a full 64-bit version of
739 739 * the binary. If successful, conv_check_native() won't return.
740 740 */
741 741 (void) conv_check_native(argv, envp);
742 742
743 743 /*
744 744 * Establish locale.
745 745 */
746 746 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
747 747 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
748 748
749 749 (void) setvbuf(stdout, NULL, _IOLBF, 0);
750 750 (void) setvbuf(stderr, NULL, _IOLBF, 0);
751 751
752 752 opterr = 0;
753 753 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) {
754 754 switch (var) {
755 755 case 'C':
756 756 flags |= FLG_CTL_DEMANGLE;
757 757 break;
758 758 case 'c':
759 759 flags |= FLG_SHOW_SHDR;
760 760 break;
761 761 case 'd':
762 762 flags |= FLG_SHOW_DYNAMIC;
763 763 break;
764 764 case 'e':
765 765 flags |= FLG_SHOW_EHDR;
766 766 break;
767 767 case 'G':
768 768 flags |= FLG_SHOW_GOT;
769 769 break;
770 770 case 'g':
771 771 flags |= FLG_SHOW_GROUP;
772 772 break;
773 773 case 'H':
774 774 flags |= FLG_SHOW_CAP;
775 775 break;
776 776 case 'h':
777 777 flags |= FLG_SHOW_HASH;
778 778 break;
779 779 case 'I':
780 780 if (!process_index_opt(optarg, &match_data))
781 781 goto usage_brief;
782 782 if (!add_match_record(argv[0], &match_data))
783 783 return (1);
784 784 flags |= FLG_CTL_MATCH;
785 785 break;
786 786 case 'i':
787 787 flags |= FLG_SHOW_INTERP;
788 788 break;
789 789 case 'k':
790 790 flags |= FLG_CALC_CHECKSUM;
791 791 break;
792 792 case 'l':
793 793 flags |= FLG_CTL_LONGNAME;
794 794 break;
795 795 case 'm':
796 796 flags |= FLG_SHOW_MOVE;
797 797 break;
798 798 case 'N':
799 799 match_data.opt_type = MATCH_OPT_NAME;
800 800 match_data.value.name = optarg;
801 801 if (!add_match_record(argv[0], &match_data))
802 802 return (1);
803 803 flags |= FLG_CTL_MATCH;
804 804 break;
805 805 case 'n':
806 806 flags |= FLG_SHOW_NOTE;
807 807 break;
808 808 case 'O':
809 809 {
810 810 uint32_t val;
811 811
812 812 /*
813 813 * osabi is a uchar_t in the ELF header.
814 814 * Don't accept any value that exceeds
815 815 * that range.
816 816 */
817 817 if ((atoui(optarg, ATOUI_OSABI, &val) == 0) ||
818 818 (val > 255)) {
819 819 (void) fprintf(stderr,
820 820 MSG_INTL(MSG_ERR_BAD_T_OSABI),
821 821 basename(argv[0]), optarg);
822 822 return (1);
823 823 }
824 824 osabi = val;
825 825 }
826 826 flags |= FLG_CTL_OSABI;
827 827 break;
828 828 case 'P':
829 829 flags |= FLG_CTL_FAKESHDR;
830 830 break;
831 831 case 'p':
832 832 flags |= FLG_SHOW_PHDR;
833 833 break;
834 834 case 'r':
835 835 flags |= FLG_SHOW_RELOC;
836 836 break;
837 837 case 'S':
838 838 flags |= FLG_SHOW_SORT;
839 839 break;
840 840 case 's':
841 841 flags |= FLG_SHOW_SYMBOLS;
842 842 break;
843 843 case 'T':
844 844 /*
845 845 * We can't evaluate the value yet, because
846 846 * we need to know if -p is used or not in
847 847 * order to tell if we're seeing section header
848 848 * or program header types. So, we save the
849 849 * string in the name field, and then convert
850 850 * it to a type integer in a following pass.
851 851 */
852 852 match_data.opt_type = MATCH_OPT_TYPE;
853 853 match_data.value.name = optarg;
854 854 if (!add_match_record(argv[0], &match_data))
855 855 return (1);
856 856 flags |= FLG_CTL_MATCH;
857 857 break;
858 858 case 'u':
859 859 flags |= FLG_SHOW_UNWIND;
860 860 break;
861 861 case 'v':
862 862 flags |= FLG_SHOW_VERSIONS;
863 863 break;
864 864 case 'w':
865 865 wname = optarg;
866 866 break;
867 867 case 'y':
868 868 flags |= FLG_SHOW_SYMINFO;
869 869 break;
870 870 case '?':
871 871 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
872 872 basename(argv[0]));
873 873 detail_usage();
874 874 return (1);
875 875 default:
876 876 break;
877 877 }
878 878 }
879 879
880 880 /* -p and -w are mutually exclusive. -w only works with sections */
881 881 if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL))
882 882 goto usage_brief;
883 883
884 884 /* If a match argument is present, prepare the match state */
885 885 if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0))
886 886 return (1);
887 887
888 888 /*
889 889 * Decide what to do if no options specifying something to
890 890 * show or do are present.
891 891 *
892 892 * If there is no -w and no match options, then we will set all
893 893 * the show flags, causing a full display of everything in the
894 894 * file that we know how to handle.
895 895 *
896 896 * Otherwise, if there is no match list, we generate a usage
897 897 * error and quit.
898 898 *
899 899 * In the case where there is a match list, we go ahead and call
900 900 * regular() anyway, leaving it to decide what to do. If -w is
901 901 * present, regular() will use the match list to handle it.
902 902 * In addition, in the absence of explicit show/calc flags, regular()
903 903 * will compare the section headers to the match list and use
904 904 * that to generate the FLG_ bits that will display the information
905 905 * specified by the match list.
906 906 */
907 907 if ((flags & ~FLG_MASK_CTL) == 0) {
908 908 if (!wname && (match_state.list == NULL))
909 909 flags |= FLG_MASK_SHOW;
910 910 else if (match_state.list == NULL)
911 911 goto usage_brief;
912 912 }
913 913
914 914 /* There needs to be at least 1 filename left following the options */
915 915 if ((var = argc - optind) == 0)
916 916 goto usage_brief;
917 917
918 918 /*
919 919 * If the -l/-C option is specified, set up the liblddbg.so.
920 920 */
921 921 if (flags & FLG_CTL_LONGNAME)
922 922 dbg_desc->d_extra |= DBG_E_LONG;
923 923 if (flags & FLG_CTL_DEMANGLE)
924 924 dbg_desc->d_extra |= DBG_E_DEMANGLE;
925 925
926 926 /*
927 927 * If the -w option has indicated an output file open it. It's
928 928 * arguable whether this option has much use when multiple files are
929 929 * being processed.
930 930 *
931 931 * If wname is non-NULL, we know that -p was not specified, due
932 932 * to the test above.
933 933 */
934 934 if (wname) {
935 935 if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC),
936 936 0666)) < 0) {
937 937 int err = errno;
938 938 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
939 939 wname, strerror(err));
940 940 return (1);
941 941 }
942 942 }
943 943
944 944 /*
945 945 * Open the input file, initialize the elf interface, and
946 946 * process it.
947 947 */
948 948 ret = 0;
949 949 for (; (optind < argc) && (ret == 0); optind++) {
950 950 const char *file = argv[optind];
951 951
952 952 if ((fd = open(argv[optind], O_RDONLY)) == -1) {
953 953 int err = errno;
954 954 (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
955 955 file, strerror(err));
956 956 continue;
957 957 }
958 958 (void) elf_version(EV_CURRENT);
959 959 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
960 960 failure(file, MSG_ORIG(MSG_ELF_BEGIN));
961 961 (void) close(fd);
962 962 continue;
963 963 }
964 964
965 965 if (var > 1)
966 966 dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file);
↓ open down ↓ |
966 lines elided |
↑ open up ↑ |
967 967
968 968 switch (elf_kind(elf)) {
969 969 case ELF_K_AR:
970 970 ret = archive(file, fd, elf, flags, wname, wfd, osabi);
971 971 break;
972 972 case ELF_K_ELF:
973 973 ret = decide(file, fd, elf, flags, wname, wfd, osabi);
974 974 break;
975 975 default:
976 976 (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file);
977 + ret = 1;
977 978 break;
978 979 }
979 980
980 981 (void) close(fd);
981 982 (void) elf_end(elf);
982 983 }
983 984
984 985 if (wfd)
985 986 (void) close(wfd);
986 987 return (ret);
987 988
988 989 usage_brief:
989 990 /* Control comes here for a simple usage message and exit */
990 991 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
991 992 basename(argv[0]));
992 993 return (1);
993 994
994 995 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX