|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "leaky.h" |
|
6 |
|
7 #ifdef USE_ELF |
|
8 |
|
9 #include "leaky.h" |
|
10 #include <stdio.h> |
|
11 #include <malloc.h> |
|
12 #include <libelf/libelf.h> |
|
13 #include <unistd.h> |
|
14 #include <fcntl.h> |
|
15 #include <string.h> |
|
16 |
|
17 void leaky::readSymbols(const char *fileName) |
|
18 { |
|
19 int fd = ::open(fileName, O_RDONLY); |
|
20 if (fd < 0) { |
|
21 fprintf(stderr, "%s: unable to open \"%s\"\n", applicationName, |
|
22 fileName); |
|
23 exit(-1); |
|
24 } |
|
25 |
|
26 elf_version(EV_CURRENT); |
|
27 Elf *elf = elf_begin(fd, ELF_C_READ, 0); |
|
28 if (!elf) { |
|
29 fprintf(stderr, "%s: \"%s\": has no symbol table\n", applicationName, |
|
30 fileName); |
|
31 exit(-1); |
|
32 } |
|
33 |
|
34 long alloced = 10000; |
|
35 Symbol* syms = (Symbol*) malloc(sizeof(Symbol) * 10000); |
|
36 Symbol* sp = syms; |
|
37 Symbol* last = syms + alloced; |
|
38 |
|
39 // Get each of the relevant sections and add them to the list of |
|
40 // symbols. |
|
41 Elf32_Ehdr *ehdr = elf32_getehdr(elf); |
|
42 if (!ehdr) { |
|
43 fprintf(stderr, "%s: elf library lossage\n", applicationName); |
|
44 exit(-1); |
|
45 } |
|
46 #if 0 |
|
47 Elf32_Half ndx = ehdr->e_shstrndx; |
|
48 #endif |
|
49 |
|
50 Elf_Scn *scn = 0; |
|
51 int strtabndx = -1; |
|
52 for (int i = 1; (scn = elf_nextscn(elf, scn)) != 0; i++) { |
|
53 Elf32_Shdr *shdr = elf32_getshdr(scn); |
|
54 #if 0 |
|
55 char *name = elf_strptr(elf, ndx, (size_t) shdr->sh_name); |
|
56 printf("Section %s (%d 0x%x)\n", name ? name : "(null)", |
|
57 shdr->sh_type, shdr->sh_type); |
|
58 #endif |
|
59 if (shdr->sh_type == SHT_STRTAB) { |
|
60 /* We assume here that string tables preceed symbol tables... */ |
|
61 strtabndx = i; |
|
62 continue; |
|
63 } |
|
64 #if 0 |
|
65 if (shdr->sh_type == SHT_DYNAMIC) { |
|
66 /* Dynamic */ |
|
67 Elf_Data *data = elf_getdata(scn, 0); |
|
68 if (!data || !data->d_size) { |
|
69 printf("No data..."); |
|
70 continue; |
|
71 } |
|
72 |
|
73 Elf32_Dyn *dyn = (Elf32_Dyn*) data->d_buf; |
|
74 Elf32_Dyn *lastdyn = |
|
75 (Elf32_Dyn*) ((char*) data->d_buf + data->d_size); |
|
76 for (; dyn < lastdyn; dyn++) { |
|
77 printf("tag=%d value=0x%x\n", dyn->d_tag, dyn->d_un.d_val); |
|
78 } |
|
79 } else |
|
80 #endif |
|
81 if ((shdr->sh_type == SHT_SYMTAB) || |
|
82 (shdr->sh_type == SHT_DYNSYM)) { |
|
83 /* Symbol table */ |
|
84 Elf_Data *data = elf_getdata(scn, 0); |
|
85 if (!data || !data->d_size) { |
|
86 printf("No data..."); |
|
87 continue; |
|
88 } |
|
89 |
|
90 /* In theory we now have the symbols... */ |
|
91 Elf32_Sym *esym = (Elf32_Sym*) data->d_buf; |
|
92 Elf32_Sym *lastsym = |
|
93 (Elf32_Sym*) ((char*) data->d_buf + data->d_size); |
|
94 for (; esym < lastsym; esym++) { |
|
95 #if 0 |
|
96 char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name); |
|
97 printf("%20s 0x%08x %02x %02x\n", |
|
98 nm, esym->st_value, ELF32_ST_BIND(esym->st_info), |
|
99 ELF32_ST_TYPE(esym->st_info)); |
|
100 #endif |
|
101 if ((esym->st_value == 0) || |
|
102 (ELF32_ST_BIND(esym->st_info) == STB_WEAK) || |
|
103 (ELF32_ST_BIND(esym->st_info) == STB_NUM) || |
|
104 (ELF32_ST_TYPE(esym->st_info) != STT_FUNC)) { |
|
105 continue; |
|
106 } |
|
107 #if 1 |
|
108 char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name); |
|
109 #endif |
|
110 sp->name = nm ? strdup(nm) : "(no name)"; |
|
111 sp->address = esym->st_value; |
|
112 sp++; |
|
113 if (sp >= last) { |
|
114 long n = alloced + 10000; |
|
115 syms = (Symbol*) |
|
116 realloc(syms, (size_t) (sizeof(Symbol) * n)); |
|
117 last = syms + n; |
|
118 sp = syms + alloced; |
|
119 alloced = n; |
|
120 } |
|
121 } |
|
122 } |
|
123 } |
|
124 |
|
125 int interesting = sp - syms; |
|
126 if (!quiet) { |
|
127 printf("Total of %d symbols\n", interesting); |
|
128 } |
|
129 usefulSymbols = interesting; |
|
130 externalSymbols = syms; |
|
131 } |
|
132 |
|
133 #endif /* USE_ELF */ |