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