Print this page
4054 dis sometimes decides random symbols are functions
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/dis/dis_target.c
+++ new/usr/src/cmd/dis/dis_target.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 * Copyright 2011 Jason King. All rights reserved.
26 26 */
27 27
28 28 #include <assert.h>
29 29 #include <errno.h>
30 30 #include <fcntl.h>
31 31 #include <gelf.h>
32 32 #include <libelf.h>
33 33 #include <stdlib.h>
34 34 #include <string.h>
35 35 #include <unistd.h>
36 36
37 37 #include <sys/fcntl.h>
38 38 #include <sys/stat.h>
39 39 #include <sys/sysmacros.h>
40 40 #include <sys/types.h>
41 41
42 42 #include "dis_target.h"
43 43 #include "dis_util.h"
44 44
45 45 /*
46 46 * Standard ELF disassembler target.
47 47 *
48 48 * We only support disassembly of ELF files, though this target interface could
49 49 * be extended in the future. Each basic type (target, func, section) contains
50 50 * enough information to uniquely identify the location within the file. The
51 51 * interfaces use libelf(3LIB) to do the actual processing of the file.
52 52 */
53 53
54 54 /*
55 55 * Symbol table entry type. We maintain our own symbol table sorted by address,
56 56 * with the symbol name already resolved against the ELF symbol table.
57 57 */
58 58 typedef struct sym_entry {
59 59 GElf_Sym se_sym; /* value of symbol */
60 60 char *se_name; /* name of symbol */
61 61 int se_shndx; /* section where symbol is located */
62 62 } sym_entry_t;
63 63
64 64 /*
65 65 * Create a map of the virtual address ranges of every section. This will
66 66 * allow us to create dummpy mappings for unassigned addresses. Otherwise
67 67 * multiple sections with unassigned addresses will appear to overlap and
68 68 * mess up symbol resolution (which uses the virtual address).
69 69 */
70 70 typedef struct dis_shnmap {
71 71 const char *dm_name; /* name of section */
72 72 uint64_t dm_start; /* virtual address of section */
73 73 size_t dm_length; /* address length */
74 74 boolean_t dm_mapped; /* did we assign the mapping */
75 75 } dis_shnmap_t;
76 76
77 77 /*
78 78 * Target data structure. This structure keeps track of the ELF file
79 79 * information, a few bits of pre-processed section index information, and
80 80 * sorted versions of the symbol table. We also keep track of the last symbol
81 81 * looked up, as the majority of lookups remain within the same symbol.
82 82 */
83 83 struct dis_tgt {
84 84 Elf *dt_elf; /* libelf handle */
85 85 Elf *dt_elf_root; /* main libelf handle (for archives) */
86 86 const char *dt_filename; /* name of file */
87 87 int dt_fd; /* underlying file descriptor */
88 88 size_t dt_shstrndx; /* section index of .shstrtab */
89 89 size_t dt_symidx; /* section index of symbol table */
90 90 sym_entry_t *dt_symcache; /* last symbol looked up */
91 91 sym_entry_t *dt_symtab; /* sorted symbol table */
92 92 int dt_symcount; /* # of symbol table entries */
93 93 struct dis_tgt *dt_next; /* next target (for archives) */
94 94 Elf_Arhdr *dt_arhdr; /* archive header (for archives) */
95 95 dis_shnmap_t *dt_shnmap; /* section address map */
96 96 size_t dt_shncount; /* # of sections in target */
97 97 };
98 98
99 99 /*
100 100 * Function data structure. We resolve the symbol and lookup the associated ELF
101 101 * data when building this structure. The offset is calculated based on the
102 102 * section's starting address.
103 103 */
104 104 struct dis_func {
105 105 sym_entry_t *df_sym; /* symbol table reference */
106 106 Elf_Data *df_data; /* associated ELF data */
107 107 size_t df_offset; /* offset within data */
108 108 };
109 109
110 110 /*
111 111 * Section data structure. We store the entire section header so that we can
112 112 * determine some properties (such as whether or not it contains text) after
113 113 * building the structure.
114 114 */
115 115 struct dis_scn {
116 116 GElf_Shdr ds_shdr;
117 117 const char *ds_name;
118 118 Elf_Data *ds_data;
119 119 };
120 120
121 121 /* Lifted from Psymtab.c, omitting STT_TLS */
122 122 #define DATA_TYPES \
123 123 ((1 << STT_OBJECT) | (1 << STT_FUNC) | (1 << STT_COMMON))
124 124 #define IS_DATA_TYPE(tp) (((1 << (tp)) & DATA_TYPES) != 0)
125 125
126 126 /*
127 127 * Save the virtual address range for this section and select the
128 128 * best section to use as the symbol table. We prefer SHT_SYMTAB
129 129 * over SHT_DYNSYM.
130 130 */
131 131 /* ARGSUSED */
132 132 static void
133 133 tgt_scn_init(dis_tgt_t *tgt, dis_scn_t *scn, void *data)
134 134 {
135 135 int *index = data;
136 136
137 137 *index += 1;
138 138
139 139 tgt->dt_shnmap[*index].dm_name = scn->ds_name;
140 140 tgt->dt_shnmap[*index].dm_start = scn->ds_shdr.sh_addr;
141 141 tgt->dt_shnmap[*index].dm_length = scn->ds_shdr.sh_size;
142 142 tgt->dt_shnmap[*index].dm_mapped = B_FALSE;
143 143
144 144 /*
145 145 * Prefer SHT_SYMTAB over SHT_DYNSYM
146 146 */
147 147 if (scn->ds_shdr.sh_type == SHT_DYNSYM && tgt->dt_symidx == 0)
148 148 tgt->dt_symidx = *index;
149 149 else if (scn->ds_shdr.sh_type == SHT_SYMTAB)
150 150 tgt->dt_symidx = *index;
151 151 }
152 152
153 153 static int
154 154 sym_compare(const void *a, const void *b)
155 155 {
156 156 const sym_entry_t *syma = a;
157 157 const sym_entry_t *symb = b;
158 158 const char *aname = syma->se_name;
159 159 const char *bname = symb->se_name;
160 160
161 161 if (syma->se_sym.st_value < symb->se_sym.st_value)
162 162 return (-1);
163 163
164 164 if (syma->se_sym.st_value > symb->se_sym.st_value)
165 165 return (1);
166 166
167 167 /*
168 168 * Prefer functions over non-functions
169 169 */
170 170 if (GELF_ST_TYPE(syma->se_sym.st_info) !=
171 171 GELF_ST_TYPE(symb->se_sym.st_info)) {
172 172 if (GELF_ST_TYPE(syma->se_sym.st_info) == STT_FUNC)
173 173 return (-1);
174 174 if (GELF_ST_TYPE(symb->se_sym.st_info) == STT_FUNC)
175 175 return (1);
176 176 }
177 177
178 178 /*
179 179 * For symbols with the same address and type, we sort them according to
180 180 * a hierarchy:
181 181 *
182 182 * 1. weak symbols (common name)
183 183 * 2. global symbols (external name)
184 184 * 3. local symbols
185 185 */
186 186 if (GELF_ST_BIND(syma->se_sym.st_info) !=
187 187 GELF_ST_BIND(symb->se_sym.st_info)) {
188 188 if (GELF_ST_BIND(syma->se_sym.st_info) == STB_WEAK)
189 189 return (-1);
190 190 if (GELF_ST_BIND(symb->se_sym.st_info) == STB_WEAK)
191 191 return (1);
192 192
193 193 if (GELF_ST_BIND(syma->se_sym.st_info) == STB_GLOBAL)
194 194 return (-1);
195 195 if (GELF_ST_BIND(symb->se_sym.st_info) == STB_GLOBAL)
196 196 return (1);
197 197 }
198 198
199 199 /*
200 200 * As a last resort, if we have multiple symbols of the same type at the
201 201 * same address, prefer the version with the fewest leading underscores.
202 202 */
203 203 if (aname == NULL)
204 204 return (-1);
205 205 if (bname == NULL)
206 206 return (1);
207 207
208 208 while (*aname == '_' && *bname == '_') {
209 209 aname++;
210 210 bname++;
211 211 }
212 212
213 213 if (*bname == '_')
214 214 return (-1);
215 215 if (*aname == '_')
216 216 return (1);
217 217
218 218 /*
219 219 * Prefer the symbol with the smaller size.
220 220 */
221 221 if (syma->se_sym.st_size < symb->se_sym.st_size)
222 222 return (-1);
223 223 if (syma->se_sym.st_size > symb->se_sym.st_size)
224 224 return (1);
225 225
226 226 /*
227 227 * We really do have two identical symbols for some reason. Just report
228 228 * them as equal, and to the lucky one go the spoils.
229 229 */
230 230 return (0);
231 231 }
232 232
233 233 /*
234 234 * Construct an optimized symbol table sorted by starting address.
235 235 */
236 236 static void
237 237 construct_symtab(dis_tgt_t *tgt)
238 238 {
239 239 Elf_Scn *scn;
240 240 GElf_Shdr shdr;
241 241 Elf_Data *symdata;
242 242 int i;
243 243 GElf_Word *symshndx = NULL;
244 244 int symshndx_size;
245 245 sym_entry_t *sym;
246 246 sym_entry_t *p_symtab = NULL;
247 247 int nsym = 0; /* count of symbols we're not interested in */
248 248
249 249 /*
250 250 * Find the symshndx section, if any
251 251 */
252 252 for (scn = elf_nextscn(tgt->dt_elf, NULL); scn != NULL;
253 253 scn = elf_nextscn(tgt->dt_elf, scn)) {
254 254 if (gelf_getshdr(scn, &shdr) == NULL)
255 255 break;
256 256 if (shdr.sh_type == SHT_SYMTAB_SHNDX &&
257 257 shdr.sh_link == tgt->dt_symidx) {
258 258 Elf_Data *data;
259 259
260 260 if ((data = elf_getdata(scn, NULL)) != NULL) {
261 261 symshndx = (GElf_Word *)data->d_buf;
262 262 symshndx_size = data->d_size /
263 263 sizeof (GElf_Word);
264 264 break;
265 265 }
266 266 }
267 267 }
268 268
269 269 if ((scn = elf_getscn(tgt->dt_elf, tgt->dt_symidx)) == NULL)
270 270 die("%s: failed to get section information", tgt->dt_filename);
271 271 if (gelf_getshdr(scn, &shdr) == NULL)
272 272 die("%s: failed to get section header", tgt->dt_filename);
273 273 if (shdr.sh_entsize == 0)
274 274 die("%s: symbol table has zero size", tgt->dt_filename);
275 275
276 276 if ((symdata = elf_getdata(scn, NULL)) == NULL)
277 277 die("%s: failed to get symbol table", tgt->dt_filename);
278 278
279 279 tgt->dt_symcount = symdata->d_size / gelf_fsize(tgt->dt_elf, ELF_T_SYM,
280 280 1, EV_CURRENT);
281 281
282 282 p_symtab = safe_malloc(tgt->dt_symcount * sizeof (sym_entry_t));
283 283
284 284 for (i = 0, sym = p_symtab; i < tgt->dt_symcount; i++) {
285 285 if (gelf_getsym(symdata, i, &(sym->se_sym)) == NULL) {
286 286 warn("%s: gelf_getsym returned NULL for %d",
287 287 tgt->dt_filename, i);
288 288 nsym++;
289 289 continue;
290 290 }
291 291
292 292 /*
293 293 * We're only interested in data symbols.
294 294 */
295 295 if (!IS_DATA_TYPE(GELF_ST_TYPE(sym->se_sym.st_info))) {
296 296 nsym++;
297 297 continue;
298 298 }
299 299
300 300 if (sym->se_sym.st_shndx == SHN_XINDEX && symshndx != NULL) {
301 301 if (i > symshndx_size) {
302 302 warn("%s: bad SHNX_XINDEX %d",
303 303 tgt->dt_filename, i);
304 304 sym->se_shndx = -1;
305 305 } else {
306 306 sym->se_shndx = symshndx[i];
307 307 }
308 308 } else {
309 309 sym->se_shndx = sym->se_sym.st_shndx;
310 310 }
311 311
312 312 /* Deal with symbols with special section indicies */
313 313 if (sym->se_shndx == SHN_ABS) {
314 314 /*
315 315 * If st_value == 0, references to these
316 316 * symbols in code are modified in situ
317 317 * thus we will never attempt to look
318 318 * them up.
319 319 */
320 320 if (sym->se_sym.st_value == 0) {
321 321 /*
322 322 * References to these symbols in code
323 323 * are modified in situ by the runtime
324 324 * linker and no code on disk will ever
325 325 * attempt to look them up.
326 326 */
327 327 nsym++;
328 328 continue;
329 329 } else {
330 330 /*
331 331 * If st_value != 0, (such as examining
332 332 * something in /system/object/.../object)
333 333 * the values should resolve to a value
334 334 * within an existing section (such as
335 335 * .data). This also means it never needs
336 336 * to have st_value mapped.
337 337 */
338 338 sym++;
339 339 continue;
340 340 }
341 341 }
342 342
343 343 /*
344 344 * Ignore the symbol if it has some other special
345 345 * section index
346 346 */
347 347 if (sym->se_shndx == SHN_UNDEF ||
348 348 sym->se_shndx >= SHN_LORESERVE) {
349 349 nsym++;
350 350 continue;
351 351 }
352 352
353 353 if ((sym->se_name = elf_strptr(tgt->dt_elf, shdr.sh_link,
354 354 (size_t)sym->se_sym.st_name)) == NULL) {
355 355 warn("%s: failed to lookup symbol %d name",
356 356 tgt->dt_filename, i);
357 357 nsym++;
358 358 continue;
359 359 }
360 360
361 361 /*
362 362 * If we had to map this section, its symbol value
363 363 * also needs to be mapped.
364 364 */
365 365 if (tgt->dt_shnmap[sym->se_shndx].dm_mapped)
366 366 sym->se_sym.st_value +=
367 367 tgt->dt_shnmap[sym->se_shndx].dm_start;
368 368
369 369 sym++;
370 370 }
371 371
372 372 tgt->dt_symcount -= nsym;
373 373 tgt->dt_symtab = realloc(p_symtab, tgt->dt_symcount *
374 374 sizeof (sym_entry_t));
375 375
376 376 qsort(tgt->dt_symtab, tgt->dt_symcount, sizeof (sym_entry_t),
377 377 sym_compare);
378 378 }
379 379
380 380 /*
381 381 * Assign virtual address ranges for sections that need it
382 382 */
383 383 static void
384 384 create_addrmap(dis_tgt_t *tgt)
385 385 {
386 386 uint64_t addr;
387 387 int i;
388 388
389 389 if (tgt->dt_shnmap == NULL)
390 390 return;
391 391
392 392 /* find the greatest used address */
393 393 for (addr = 0, i = 1; i < tgt->dt_shncount; i++)
394 394 if (tgt->dt_shnmap[i].dm_start > addr)
395 395 addr = tgt->dt_shnmap[i].dm_start +
396 396 tgt->dt_shnmap[i].dm_length;
397 397
398 398 addr = P2ROUNDUP(addr, 0x1000);
399 399
400 400 /*
401 401 * Assign section a starting address beyond the largest mapped section
402 402 * if no address was given.
403 403 */
404 404 for (i = 1; i < tgt->dt_shncount; i++) {
405 405 if (tgt->dt_shnmap[i].dm_start != 0)
406 406 continue;
407 407
408 408 tgt->dt_shnmap[i].dm_start = addr;
409 409 tgt->dt_shnmap[i].dm_mapped = B_TRUE;
410 410 addr = P2ROUNDUP(addr + tgt->dt_shnmap[i].dm_length, 0x1000);
411 411 }
412 412 }
413 413
414 414 /*
415 415 * Create a target backed by an ELF file.
416 416 */
417 417 dis_tgt_t *
418 418 dis_tgt_create(const char *file)
419 419 {
420 420 dis_tgt_t *tgt, *current;
421 421 int idx;
422 422 Elf *elf;
423 423 GElf_Ehdr ehdr;
424 424 Elf_Arhdr *arhdr = NULL;
425 425 int cmd;
426 426
427 427 if (elf_version(EV_CURRENT) == EV_NONE)
428 428 die("libelf(3ELF) out of date");
429 429
430 430 tgt = safe_malloc(sizeof (dis_tgt_t));
431 431
432 432 if ((tgt->dt_fd = open(file, O_RDONLY)) < 0) {
433 433 warn("%s: failed opening file, reason: %s", file,
434 434 strerror(errno));
435 435 free(tgt);
436 436 return (NULL);
437 437 }
438 438
439 439 if ((tgt->dt_elf_root =
440 440 elf_begin(tgt->dt_fd, ELF_C_READ, NULL)) == NULL) {
441 441 warn("%s: invalid or corrupt ELF file", file);
442 442 dis_tgt_destroy(tgt);
443 443 return (NULL);
444 444 }
445 445
446 446 current = tgt;
447 447 cmd = ELF_C_READ;
448 448 while ((elf = elf_begin(tgt->dt_fd, cmd, tgt->dt_elf_root)) != NULL) {
449 449
450 450 if (elf_kind(tgt->dt_elf_root) == ELF_K_AR &&
451 451 (arhdr = elf_getarhdr(elf)) == NULL) {
452 452 warn("%s: malformed archive", file);
453 453 dis_tgt_destroy(tgt);
454 454 return (NULL);
455 455 }
456 456
457 457 /*
458 458 * Make sure that this Elf file is sane
459 459 */
460 460 if (gelf_getehdr(elf, &ehdr) == NULL) {
461 461 if (arhdr != NULL) {
462 462 /*
463 463 * For archives, we drive on in the face of bad
464 464 * members. The "/" and "//" members are
465 465 * special, and should be silently ignored.
466 466 */
467 467 if (strcmp(arhdr->ar_name, "/") != 0 &&
468 468 strcmp(arhdr->ar_name, "//") != 0)
469 469 warn("%s[%s]: invalid file type",
470 470 file, arhdr->ar_name);
471 471 cmd = elf_next(elf);
472 472 (void) elf_end(elf);
473 473 continue;
474 474 }
475 475
476 476 warn("%s: invalid file type", file);
477 477 dis_tgt_destroy(tgt);
478 478 return (NULL);
479 479 }
480 480
481 481 /*
482 482 * If we're seeing a new Elf object, then we have an
483 483 * archive. In this case, we create a new target, and chain it
484 484 * off the master target. We can later iterate over these
485 485 * targets using dis_tgt_next().
486 486 */
487 487 if (current->dt_elf != NULL) {
488 488 dis_tgt_t *next = safe_malloc(sizeof (dis_tgt_t));
489 489 next->dt_elf_root = tgt->dt_elf_root;
490 490 next->dt_fd = -1;
491 491 current->dt_next = next;
492 492 current = next;
493 493 }
494 494 current->dt_elf = elf;
495 495 current->dt_arhdr = arhdr;
496 496
497 497 if (elf_getshdrstrndx(elf, ¤t->dt_shstrndx) == -1) {
498 498 warn("%s: failed to get section string table for "
499 499 "file", file);
500 500 dis_tgt_destroy(tgt);
501 501 return (NULL);
502 502 }
503 503
504 504 current->dt_shnmap = safe_malloc(sizeof (dis_shnmap_t) *
505 505 ehdr.e_shnum);
506 506 current->dt_shncount = ehdr.e_shnum;
507 507
508 508 idx = 0;
509 509 dis_tgt_section_iter(current, tgt_scn_init, &idx);
510 510 current->dt_filename = file;
511 511
512 512 create_addrmap(current);
513 513 if (current->dt_symidx != 0)
514 514 construct_symtab(current);
515 515
516 516 cmd = elf_next(elf);
517 517 }
518 518
519 519 /*
520 520 * Final sanity check. If we had an archive with no members, then bail
521 521 * out with a nice message.
522 522 */
523 523 if (tgt->dt_elf == NULL) {
524 524 warn("%s: empty archive\n", file);
525 525 dis_tgt_destroy(tgt);
526 526 return (NULL);
527 527 }
528 528
529 529 return (tgt);
530 530 }
531 531
532 532 /*
533 533 * Return the filename associated with the target.
534 534 */
535 535 const char *
536 536 dis_tgt_name(dis_tgt_t *tgt)
537 537 {
538 538 return (tgt->dt_filename);
539 539 }
540 540
541 541 /*
542 542 * Return the archive member name, if any.
543 543 */
544 544 const char *
545 545 dis_tgt_member(dis_tgt_t *tgt)
546 546 {
547 547 if (tgt->dt_arhdr)
548 548 return (tgt->dt_arhdr->ar_name);
549 549 else
550 550 return (NULL);
551 551 }
552 552
553 553 /*
554 554 * Return the Elf_Ehdr associated with this target. Needed to determine which
555 555 * disassembler to use.
556 556 */
557 557 void
558 558 dis_tgt_ehdr(dis_tgt_t *tgt, GElf_Ehdr *ehdr)
559 559 {
560 560 (void) gelf_getehdr(tgt->dt_elf, ehdr);
561 561 }
562 562
563 563 /*
564 564 * Return the next target in the list, if this is an archive.
565 565 */
566 566 dis_tgt_t *
567 567 dis_tgt_next(dis_tgt_t *tgt)
568 568 {
569 569 return (tgt->dt_next);
570 570 }
571 571
572 572 /*
573 573 * Destroy a target and free up any associated memory.
574 574 */
575 575 void
576 576 dis_tgt_destroy(dis_tgt_t *tgt)
577 577 {
578 578 dis_tgt_t *current, *next;
579 579
580 580 current = tgt->dt_next;
581 581 while (current != NULL) {
582 582 next = current->dt_next;
583 583 if (current->dt_elf)
584 584 (void) elf_end(current->dt_elf);
585 585 if (current->dt_symtab)
586 586 free(current->dt_symtab);
587 587 free(current);
588 588 current = next;
589 589 }
590 590
591 591 if (tgt->dt_elf)
592 592 (void) elf_end(tgt->dt_elf);
593 593 if (tgt->dt_elf_root)
594 594 (void) elf_end(tgt->dt_elf_root);
595 595
596 596 if (tgt->dt_symtab)
597 597 free(tgt->dt_symtab);
598 598
599 599 free(tgt);
600 600 }
601 601
602 602 /*
603 603 * Given an address, return the section it is in and set the offset within
604 604 * the section.
605 605 */
606 606 const char *
607 607 dis_find_section(dis_tgt_t *tgt, uint64_t addr, off_t *offset)
608 608 {
609 609 int i;
610 610
611 611 for (i = 1; i < tgt->dt_shncount; i++) {
612 612 if ((addr >= tgt->dt_shnmap[i].dm_start) &&
613 613 (addr < tgt->dt_shnmap[i].dm_start +
614 614 tgt->dt_shnmap[i].dm_length)) {
615 615 *offset = addr - tgt->dt_shnmap[i].dm_start;
616 616 return (tgt->dt_shnmap[i].dm_name);
617 617 }
618 618 }
619 619
620 620 *offset = 0;
621 621 return (NULL);
622 622 }
623 623
624 624 /*
625 625 * Given an address, returns the name of the corresponding symbol, as well as
626 626 * the offset within that symbol. If no matching symbol is found, then NULL is
627 627 * returned.
628 628 *
629 629 * If 'cache_result' is specified, then we keep track of the resulting symbol.
630 630 * This cached result is consulted first on subsequent lookups in order to avoid
631 631 * unecessary lookups. This flag should be used for resolving the current PC,
632 632 * as the majority of addresses stay within the current function.
633 633 */
634 634 const char *
635 635 dis_tgt_lookup(dis_tgt_t *tgt, uint64_t addr, off_t *offset, int cache_result,
↓ open down ↓ |
635 lines elided |
↑ open up ↑ |
636 636 size_t *size, int *isfunc)
637 637 {
638 638 int lo, hi, mid;
639 639 sym_entry_t *sym, *osym, *match;
640 640 int found;
641 641
642 642 if (tgt->dt_symcache != NULL &&
643 643 addr >= tgt->dt_symcache->se_sym.st_value &&
644 644 addr < tgt->dt_symcache->se_sym.st_value +
645 645 tgt->dt_symcache->se_sym.st_size) {
646 - *offset = addr - tgt->dt_symcache->se_sym.st_value;
647 - *size = tgt->dt_symcache->se_sym.st_size;
648 - return (tgt->dt_symcache->se_name);
646 + sym = tgt->dt_symcache;
647 + *offset = addr - sym->se_sym.st_value;
648 + *size = sym->se_sym.st_size;
649 + if (isfunc != NULL)
650 + *isfunc = (GELF_ST_TYPE(sym->se_sym.st_info) ==
651 + STT_FUNC);
652 + return (sym->se_name);
649 653 }
650 654
651 655 lo = 0;
652 656 hi = (tgt->dt_symcount - 1);
653 657 found = 0;
654 658 match = osym = NULL;
655 659 while (lo <= hi) {
656 660 mid = (lo + hi) / 2;
657 661
658 662 sym = &tgt->dt_symtab[mid];
659 663
660 664 if (addr >= sym->se_sym.st_value &&
661 665 addr < sym->se_sym.st_value + sym->se_sym.st_size &&
662 666 (!found || sym->se_sym.st_value > osym->se_sym.st_value)) {
663 667 osym = sym;
664 668 found = 1;
665 669 } else if (addr == sym->se_sym.st_value) {
666 670 /*
667 671 * Particularly for .plt objects, it's possible to have
668 672 * a zero sized object. We want to return this, but we
669 673 * want it to be a last resort.
670 674 */
671 675 match = sym;
672 676 }
673 677
674 678 if (addr < sym->se_sym.st_value)
675 679 hi = mid - 1;
676 680 else
677 681 lo = mid + 1;
678 682 }
679 683
680 684 if (!found) {
681 685 if (match)
682 686 osym = match;
683 687 else
684 688 return (NULL);
685 689 }
686 690
687 691 /*
688 692 * Walk backwards to find the best match.
689 693 */
690 694 do {
691 695 sym = osym;
692 696
693 697 if (osym == tgt->dt_symtab)
694 698 break;
695 699
696 700 osym = osym - 1;
697 701 } while ((sym->se_sym.st_value == osym->se_sym.st_value) &&
698 702 (addr >= osym->se_sym.st_value) &&
699 703 (addr < osym->se_sym.st_value + osym->se_sym.st_size));
700 704
701 705 if (cache_result)
702 706 tgt->dt_symcache = sym;
703 707
704 708 *offset = addr - sym->se_sym.st_value;
705 709 *size = sym->se_sym.st_size;
706 710 if (isfunc)
707 711 *isfunc = (GELF_ST_TYPE(sym->se_sym.st_info) == STT_FUNC);
708 712
709 713 return (sym->se_name);
710 714 }
711 715
712 716 #if !defined(__sparc)
713 717 /*
714 718 * Given an address, return the starting offset of the next symbol in the file.
715 719 * Only needed on variable length instruction architectures.
716 720 */
717 721 off_t
718 722 dis_tgt_next_symbol(dis_tgt_t *tgt, uint64_t addr)
719 723 {
720 724 sym_entry_t *sym;
721 725
722 726 sym = (tgt->dt_symcache != NULL) ? tgt->dt_symcache : tgt->dt_symtab;
723 727
724 728 while (sym != (tgt->dt_symtab + tgt->dt_symcount)) {
725 729 if (sym->se_sym.st_value >= addr)
726 730 return (sym->se_sym.st_value - addr);
727 731 sym++;
728 732 }
729 733
730 734 return (0);
731 735 }
732 736 #endif
733 737
734 738 /*
735 739 * Iterate over all sections in the target, executing the given callback for
736 740 * each.
737 741 */
738 742 void
739 743 dis_tgt_section_iter(dis_tgt_t *tgt, section_iter_f func, void *data)
740 744 {
741 745 dis_scn_t sdata;
742 746 Elf_Scn *scn;
743 747 int idx;
744 748
745 749 for (scn = elf_nextscn(tgt->dt_elf, NULL), idx = 1; scn != NULL;
746 750 scn = elf_nextscn(tgt->dt_elf, scn), idx++) {
747 751
748 752 if (gelf_getshdr(scn, &sdata.ds_shdr) == NULL) {
749 753 warn("%s: failed to get section %d header",
750 754 tgt->dt_filename, idx);
751 755 continue;
752 756 }
753 757
754 758 if ((sdata.ds_name = elf_strptr(tgt->dt_elf, tgt->dt_shstrndx,
755 759 sdata.ds_shdr.sh_name)) == NULL) {
756 760 warn("%s: failed to get section %d name",
757 761 tgt->dt_filename, idx);
758 762 continue;
759 763 }
760 764
761 765 if ((sdata.ds_data = elf_getdata(scn, NULL)) == NULL) {
762 766 warn("%s: failed to get data for section '%s'",
763 767 tgt->dt_filename, sdata.ds_name);
764 768 continue;
765 769 }
766 770
767 771 /*
768 772 * dis_tgt_section_iter is also used before the section map
769 773 * is initialized, so only check when we need to. If the
770 774 * section map is uninitialized, it will return 0 and have
771 775 * no net effect.
772 776 */
773 777 if (sdata.ds_shdr.sh_addr == 0)
774 778 sdata.ds_shdr.sh_addr = tgt->dt_shnmap[idx].dm_start;
775 779
776 780 func(tgt, &sdata, data);
777 781 }
778 782 }
779 783
780 784 /*
781 785 * Return 1 if the given section contains text, 0 otherwise.
782 786 */
783 787 int
784 788 dis_section_istext(dis_scn_t *scn)
785 789 {
786 790 return ((scn->ds_shdr.sh_type == SHT_PROGBITS) &&
787 791 (scn->ds_shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR)));
788 792 }
789 793
790 794 /*
791 795 * Return a pointer to the section data.
792 796 */
793 797 void *
794 798 dis_section_data(dis_scn_t *scn)
795 799 {
796 800 return (scn->ds_data->d_buf);
797 801 }
798 802
799 803 /*
800 804 * Return the size of the section data.
801 805 */
802 806 size_t
803 807 dis_section_size(dis_scn_t *scn)
804 808 {
805 809 return (scn->ds_data->d_size);
806 810 }
807 811
808 812 /*
809 813 * Return the address for the given section.
810 814 */
811 815 uint64_t
812 816 dis_section_addr(dis_scn_t *scn)
813 817 {
814 818 return (scn->ds_shdr.sh_addr);
815 819 }
816 820
817 821 /*
818 822 * Return the name of the current section.
819 823 */
820 824 const char *
821 825 dis_section_name(dis_scn_t *scn)
822 826 {
823 827 return (scn->ds_name);
824 828 }
825 829
826 830 /*
827 831 * Create an allocated copy of the given section
828 832 */
829 833 dis_scn_t *
830 834 dis_section_copy(dis_scn_t *scn)
831 835 {
832 836 dis_scn_t *new;
833 837
834 838 new = safe_malloc(sizeof (dis_scn_t));
835 839 (void) memcpy(new, scn, sizeof (dis_scn_t));
836 840
837 841 return (new);
838 842 }
839 843
840 844 /*
841 845 * Free section memory
842 846 */
843 847 void
844 848 dis_section_free(dis_scn_t *scn)
845 849 {
846 850 free(scn);
847 851 }
848 852
849 853 /*
850 854 * Iterate over all functions in the target, executing the given callback for
851 855 * each one.
852 856 */
853 857 void
854 858 dis_tgt_function_iter(dis_tgt_t *tgt, function_iter_f func, void *data)
855 859 {
856 860 int i;
857 861 sym_entry_t *sym;
858 862 dis_func_t df;
859 863 Elf_Scn *scn;
860 864 GElf_Shdr shdr;
861 865
862 866 for (i = 0, sym = tgt->dt_symtab; i < tgt->dt_symcount; i++, sym++) {
863 867
864 868 /* ignore non-functions */
865 869 if ((GELF_ST_TYPE(sym->se_sym.st_info) != STT_FUNC) ||
866 870 (sym->se_name == NULL) ||
867 871 (sym->se_sym.st_size == 0) ||
868 872 (sym->se_shndx >= SHN_LORESERVE))
869 873 continue;
870 874
871 875 /* get the ELF data associated with this function */
872 876 if ((scn = elf_getscn(tgt->dt_elf, sym->se_shndx)) == NULL ||
873 877 gelf_getshdr(scn, &shdr) == NULL ||
874 878 (df.df_data = elf_getdata(scn, NULL)) == NULL ||
875 879 df.df_data->d_size == 0) {
876 880 warn("%s: failed to read section %d",
877 881 tgt->dt_filename, sym->se_shndx);
878 882 continue;
879 883 }
880 884
881 885 if (tgt->dt_shnmap[sym->se_shndx].dm_mapped)
882 886 shdr.sh_addr = tgt->dt_shnmap[sym->se_shndx].dm_start;
883 887
884 888 /*
885 889 * Verify that the address lies within the section that we think
886 890 * it does.
887 891 */
888 892 if (sym->se_sym.st_value < shdr.sh_addr ||
889 893 (sym->se_sym.st_value + sym->se_sym.st_size) >
890 894 (shdr.sh_addr + shdr.sh_size)) {
891 895 warn("%s: bad section %d for address %p",
892 896 tgt->dt_filename, sym->se_sym.st_shndx,
893 897 sym->se_sym.st_value);
894 898 continue;
895 899 }
896 900
897 901 df.df_sym = sym;
898 902 df.df_offset = sym->se_sym.st_value - shdr.sh_addr;
899 903
900 904 func(tgt, &df, data);
901 905 }
902 906 }
903 907
904 908 /*
905 909 * Return the data associated with a given function.
906 910 */
907 911 void *
908 912 dis_function_data(dis_func_t *func)
909 913 {
910 914 return ((char *)func->df_data->d_buf + func->df_offset);
911 915 }
912 916
913 917 /*
914 918 * Return the size of a function.
915 919 */
916 920 size_t
917 921 dis_function_size(dis_func_t *func)
918 922 {
919 923 return (func->df_sym->se_sym.st_size);
920 924 }
921 925
922 926 /*
923 927 * Return the address of a function.
924 928 */
925 929 uint64_t
926 930 dis_function_addr(dis_func_t *func)
927 931 {
928 932 return (func->df_sym->se_sym.st_value);
929 933 }
930 934
931 935 /*
932 936 * Return the name of the function
933 937 */
934 938 const char *
935 939 dis_function_name(dis_func_t *func)
936 940 {
937 941 return (func->df_sym->se_name);
938 942 }
939 943
940 944 /*
941 945 * Return a copy of a function.
942 946 */
943 947 dis_func_t *
944 948 dis_function_copy(dis_func_t *func)
945 949 {
946 950 dis_func_t *new;
947 951
948 952 new = safe_malloc(sizeof (dis_func_t));
949 953 (void) memcpy(new, func, sizeof (dis_func_t));
950 954
951 955 return (new);
952 956 }
953 957
954 958 /*
955 959 * Free function memory
956 960 */
957 961 void
958 962 dis_function_free(dis_func_t *func)
959 963 {
960 964 free(func);
961 965 }
↓ open down ↓ |
303 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX