1 |
|
|
#define ELFSIZE 32 |
2 |
|
|
/* $OpenBSD: elf.c,v 1.35 2017/10/27 16:47:08 mpi Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 2003 Michael Shalayeff |
6 |
|
|
* All rights reserved. |
7 |
|
|
* |
8 |
|
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
|
* modification, are permitted provided that the following conditions |
10 |
|
|
* are met: |
11 |
|
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
|
* documentation and/or other materials provided with the distribution. |
16 |
|
|
* |
17 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 |
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 |
|
|
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
21 |
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 |
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
23 |
|
|
* SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
25 |
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
26 |
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
27 |
|
|
* THE POSSIBILITY OF SUCH DAMAGE. |
28 |
|
|
*/ |
29 |
|
|
|
30 |
|
|
#include <sys/mman.h> |
31 |
|
|
#include <unistd.h> |
32 |
|
|
#include <a.out.h> |
33 |
|
|
#include <elf.h> |
34 |
|
|
#include <errno.h> |
35 |
|
|
#include <err.h> |
36 |
|
|
#include <stdint.h> |
37 |
|
|
#include <stdio.h> |
38 |
|
|
#include <stdlib.h> |
39 |
|
|
#include <string.h> |
40 |
|
|
#include <ctype.h> |
41 |
|
|
#include "util.h" |
42 |
|
|
#include "elfuncs.h" |
43 |
|
|
|
44 |
|
|
#if ELFSIZE == 32 |
45 |
|
|
#define swap_addr swap32 |
46 |
|
|
#define swap_off swap32 |
47 |
|
|
#define swap_sword swap32 |
48 |
|
|
#define swap_word swap32 |
49 |
|
|
#define swap_sxword swap32 |
50 |
|
|
#define swap_xword swap32 |
51 |
|
|
#define swap_half swap16 |
52 |
|
|
#define swap_quarter swap16 |
53 |
|
|
#define elf_fix_header elf32_fix_header |
54 |
|
|
#define elf_load_shdrs elf32_load_shdrs |
55 |
|
|
#define elf_load_phdrs elf32_load_phdrs |
56 |
|
|
#define elf_fix_shdrs elf32_fix_shdrs |
57 |
|
|
#define elf_fix_phdrs elf32_fix_phdrs |
58 |
|
|
#define elf_fix_sym elf32_fix_sym |
59 |
|
|
#define elf_size elf32_size |
60 |
|
|
#define elf_symloadx elf32_symloadx |
61 |
|
|
#define elf_symload elf32_symload |
62 |
|
|
#define elf2nlist elf32_2nlist |
63 |
|
|
#define elf_shn2type elf32_shn2type |
64 |
|
|
#elif ELFSIZE == 64 |
65 |
|
|
#define swap_addr swap64 |
66 |
|
|
#define swap_off swap64 |
67 |
|
|
#ifdef __alpha__ |
68 |
|
|
#define swap_sword swap64 |
69 |
|
|
#define swap_word swap64 |
70 |
|
|
#else |
71 |
|
|
#define swap_sword swap32 |
72 |
|
|
#define swap_word swap32 |
73 |
|
|
#endif |
74 |
|
|
#define swap_sxword swap64 |
75 |
|
|
#define swap_xword swap64 |
76 |
|
|
#define swap_half swap64 |
77 |
|
|
#define swap_quarter swap16 |
78 |
|
|
#define elf_fix_header elf64_fix_header |
79 |
|
|
#define elf_load_shdrs elf64_load_shdrs |
80 |
|
|
#define elf_load_phdrs elf64_load_phdrs |
81 |
|
|
#define elf_fix_shdrs elf64_fix_shdrs |
82 |
|
|
#define elf_fix_phdrs elf64_fix_phdrs |
83 |
|
|
#define elf_fix_sym elf64_fix_sym |
84 |
|
|
#define elf_size elf64_size |
85 |
|
|
#define elf_symloadx elf64_symloadx |
86 |
|
|
#define elf_symload elf64_symload |
87 |
|
|
#define elf2nlist elf64_2nlist |
88 |
|
|
#define elf_shn2type elf64_shn2type |
89 |
|
|
#else |
90 |
|
|
#error "Unsupported ELF class" |
91 |
|
|
#endif |
92 |
|
|
|
93 |
|
|
#define ELF_SDATA ".sdata" |
94 |
|
|
#define ELF_TDATA ".tdata" |
95 |
|
|
#define ELF_SBSS ".sbss" |
96 |
|
|
#define ELF_TBSS ".tbss" |
97 |
|
|
#define ELF_PLT ".plt" |
98 |
|
|
|
99 |
|
|
#ifndef SHN_MIPS_ACOMMON |
100 |
|
|
#define SHN_MIPS_ACOMMON SHN_LOPROC + 0 |
101 |
|
|
#endif |
102 |
|
|
#ifndef SHN_MIPS_TEXT |
103 |
|
|
#define SHN_MIPS_TEXT SHN_LOPROC + 1 |
104 |
|
|
#endif |
105 |
|
|
#ifndef SHN_MIPS_DATA |
106 |
|
|
#define SHN_MIPS_DATA SHN_LOPROC + 2 |
107 |
|
|
#endif |
108 |
|
|
#ifndef SHN_MIPS_SUNDEFINED |
109 |
|
|
#define SHN_MIPS_SUNDEFINED SHN_LOPROC + 4 |
110 |
|
|
#endif |
111 |
|
|
#ifndef SHN_MIPS_SCOMMON |
112 |
|
|
#define SHN_MIPS_SCOMMON SHN_LOPROC + 3 |
113 |
|
|
#endif |
114 |
|
|
|
115 |
|
|
#ifndef STT_PARISC_MILLI |
116 |
|
|
#define STT_PARISC_MILLI STT_LOPROC + 0 |
117 |
|
|
#endif |
118 |
|
|
|
119 |
|
|
int elf_shn2type(Elf_Ehdr *, u_int, const char *); |
120 |
|
|
int elf2nlist(Elf_Sym *, Elf_Ehdr *, Elf_Shdr *, char *, struct xnlist *); |
121 |
|
|
|
122 |
|
|
int |
123 |
|
|
elf_fix_header(Elf_Ehdr *eh) |
124 |
|
|
{ |
125 |
|
|
/* nothing to do */ |
126 |
|
|
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
127 |
|
|
return (0); |
128 |
|
|
|
129 |
|
|
eh->e_type = swap16(eh->e_type); |
130 |
|
|
eh->e_machine = swap16(eh->e_machine); |
131 |
|
|
eh->e_version = swap32(eh->e_version); |
132 |
|
|
eh->e_entry = swap_addr(eh->e_entry); |
133 |
|
|
eh->e_phoff = swap_off(eh->e_phoff); |
134 |
|
|
eh->e_shoff = swap_off(eh->e_shoff); |
135 |
|
|
eh->e_flags = swap32(eh->e_flags); |
136 |
|
|
eh->e_ehsize = swap16(eh->e_ehsize); |
137 |
|
|
eh->e_phentsize = swap16(eh->e_phentsize); |
138 |
|
|
eh->e_phnum = swap16(eh->e_phnum); |
139 |
|
|
eh->e_shentsize = swap16(eh->e_shentsize); |
140 |
|
|
eh->e_shnum = swap16(eh->e_shnum); |
141 |
|
|
eh->e_shstrndx = swap16(eh->e_shstrndx); |
142 |
|
|
|
143 |
|
|
return (1); |
144 |
|
|
} |
145 |
|
|
|
146 |
|
|
Elf_Shdr * |
147 |
|
|
elf_load_shdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head) |
148 |
|
|
{ |
149 |
|
|
Elf_Shdr *shdr; |
150 |
|
|
|
151 |
|
|
elf_fix_header(head); |
152 |
|
|
|
153 |
|
|
if (head->e_shnum == 0) { |
154 |
|
|
warnx("%s: no section header table", name); |
155 |
|
|
return (NULL); |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
if (head->e_shstrndx >= head->e_shnum) { |
159 |
|
|
warnx("%s: inconsistent section header table", name); |
160 |
|
|
return (NULL); |
161 |
|
|
} |
162 |
|
|
|
163 |
|
|
if (head->e_shentsize < sizeof(Elf_Shdr)) { |
164 |
|
|
warnx("%s: inconsistent section header size", name); |
165 |
|
|
return (NULL); |
166 |
|
|
} |
167 |
|
|
|
168 |
|
|
if ((shdr = calloc(head->e_shnum, head->e_shentsize)) == NULL) { |
169 |
|
|
warn("%s: malloc shdr", name); |
170 |
|
|
return (NULL); |
171 |
|
|
} |
172 |
|
|
|
173 |
|
|
if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) { |
174 |
|
|
warn("%s: fseeko", name); |
175 |
|
|
free(shdr); |
176 |
|
|
return (NULL); |
177 |
|
|
} |
178 |
|
|
|
179 |
|
|
if (fread(shdr, head->e_shentsize, head->e_shnum, fp) != head->e_shnum) { |
180 |
|
|
warnx("%s: premature EOF", name); |
181 |
|
|
free(shdr); |
182 |
|
|
return (NULL); |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
elf_fix_shdrs(head, shdr); |
186 |
|
|
return (shdr); |
187 |
|
|
} |
188 |
|
|
|
189 |
|
|
Elf_Phdr * |
190 |
|
|
elf_load_phdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head) |
191 |
|
|
{ |
192 |
|
|
Elf_Phdr *phdr; |
193 |
|
|
|
194 |
|
|
if ((phdr = calloc(head->e_phentsize, head->e_phnum)) == NULL) { |
195 |
|
|
warn("%s: malloc phdr", name); |
196 |
|
|
return (NULL); |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
if (fseeko(fp, foff + head->e_phoff, SEEK_SET)) { |
200 |
|
|
warn("%s: fseeko", name); |
201 |
|
|
free(phdr); |
202 |
|
|
return (NULL); |
203 |
|
|
} |
204 |
|
|
|
205 |
|
|
if (fread(phdr, head->e_phentsize, head->e_phnum, fp) != head->e_phnum) { |
206 |
|
|
warnx("%s: premature EOF", name); |
207 |
|
|
free(phdr); |
208 |
|
|
return (NULL); |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
elf_fix_phdrs(head, phdr); |
212 |
|
|
return (phdr); |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
int |
216 |
|
|
elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr) |
217 |
|
|
{ |
218 |
|
|
int i; |
219 |
|
|
|
220 |
|
|
/* nothing to do */ |
221 |
|
|
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
222 |
|
|
return (0); |
223 |
|
|
|
224 |
|
|
for (i = eh->e_shnum; i--; shdr++) { |
225 |
|
|
shdr->sh_name = swap32(shdr->sh_name); |
226 |
|
|
shdr->sh_type = swap32(shdr->sh_type); |
227 |
|
|
shdr->sh_flags = swap_xword(shdr->sh_flags); |
228 |
|
|
shdr->sh_addr = swap_addr(shdr->sh_addr); |
229 |
|
|
shdr->sh_offset = swap_off(shdr->sh_offset); |
230 |
|
|
shdr->sh_size = swap_xword(shdr->sh_size); |
231 |
|
|
shdr->sh_link = swap32(shdr->sh_link); |
232 |
|
|
shdr->sh_info = swap32(shdr->sh_info); |
233 |
|
|
shdr->sh_addralign = swap_xword(shdr->sh_addralign); |
234 |
|
|
shdr->sh_entsize = swap_xword(shdr->sh_entsize); |
235 |
|
|
} |
236 |
|
|
|
237 |
|
|
return (1); |
238 |
|
|
} |
239 |
|
|
|
240 |
|
|
int |
241 |
|
|
elf_fix_phdrs(Elf_Ehdr *eh, Elf_Phdr *phdr) |
242 |
|
|
{ |
243 |
|
|
int i; |
244 |
|
|
|
245 |
|
|
/* nothing to do */ |
246 |
|
|
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
247 |
|
|
return (0); |
248 |
|
|
|
249 |
|
|
for (i = eh->e_phnum; i--; phdr++) { |
250 |
|
|
phdr->p_type = swap32(phdr->p_type); |
251 |
|
|
phdr->p_flags = swap32(phdr->p_flags); |
252 |
|
|
phdr->p_offset = swap_off(phdr->p_offset); |
253 |
|
|
phdr->p_vaddr = swap_addr(phdr->p_vaddr); |
254 |
|
|
phdr->p_paddr = swap_addr(phdr->p_paddr); |
255 |
|
|
phdr->p_filesz = swap_xword(phdr->p_filesz); |
256 |
|
|
phdr->p_memsz = swap_xword(phdr->p_memsz); |
257 |
|
|
phdr->p_align = swap_xword(phdr->p_align); |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
return (1); |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
int |
264 |
|
|
elf_fix_sym(Elf_Ehdr *eh, Elf_Sym *sym) |
265 |
|
|
{ |
266 |
|
|
/* nothing to do */ |
267 |
|
|
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
268 |
|
|
return (0); |
269 |
|
|
|
270 |
|
|
sym->st_name = swap32(sym->st_name); |
271 |
|
|
sym->st_shndx = swap16(sym->st_shndx); |
272 |
|
|
sym->st_value = swap_addr(sym->st_value); |
273 |
|
|
sym->st_size = swap_xword(sym->st_size); |
274 |
|
|
|
275 |
|
|
return (1); |
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
int |
279 |
|
|
elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn) |
280 |
|
|
{ |
281 |
|
|
switch (shn) { |
282 |
|
|
case SHN_MIPS_SUNDEFINED: |
283 |
|
|
if (eh->e_machine == EM_MIPS) |
284 |
|
|
return (N_UNDF | N_EXT); |
285 |
|
|
break; |
286 |
|
|
|
287 |
|
|
case SHN_UNDEF: |
288 |
|
|
return (N_UNDF | N_EXT); |
289 |
|
|
|
290 |
|
|
case SHN_ABS: |
291 |
|
|
return (N_ABS); |
292 |
|
|
|
293 |
|
|
case SHN_MIPS_ACOMMON: |
294 |
|
|
if (eh->e_machine == EM_MIPS) |
295 |
|
|
return (N_COMM); |
296 |
|
|
break; |
297 |
|
|
|
298 |
|
|
case SHN_MIPS_SCOMMON: |
299 |
|
|
if (eh->e_machine == EM_MIPS) |
300 |
|
|
return (N_COMM); |
301 |
|
|
break; |
302 |
|
|
|
303 |
|
|
case SHN_COMMON: |
304 |
|
|
return (N_COMM); |
305 |
|
|
|
306 |
|
|
case SHN_MIPS_TEXT: |
307 |
|
|
if (eh->e_machine == EM_MIPS) |
308 |
|
|
return (N_TEXT); |
309 |
|
|
break; |
310 |
|
|
|
311 |
|
|
case SHN_MIPS_DATA: |
312 |
|
|
if (eh->e_machine == EM_MIPS) |
313 |
|
|
return (N_DATA); |
314 |
|
|
break; |
315 |
|
|
|
316 |
|
|
default: |
317 |
|
|
/* TODO: beyond 8 a table-driven binsearch should be used */ |
318 |
|
|
if (sn == NULL) |
319 |
|
|
return (-1); |
320 |
|
|
else if (!strcmp(sn, ELF_TEXT)) |
321 |
|
|
return (N_TEXT); |
322 |
|
|
else if (!strcmp(sn, ELF_RODATA)) |
323 |
|
|
return (N_SIZE); |
324 |
|
|
else if (!strcmp(sn, ELF_DATA)) |
325 |
|
|
return (N_DATA); |
326 |
|
|
else if (!strcmp(sn, ELF_SDATA)) |
327 |
|
|
return (N_DATA); |
328 |
|
|
else if (!strcmp(sn, ELF_TDATA)) |
329 |
|
|
return (N_DATA); |
330 |
|
|
else if (!strcmp(sn, ELF_BSS)) |
331 |
|
|
return (N_BSS); |
332 |
|
|
else if (!strcmp(sn, ELF_SBSS)) |
333 |
|
|
return (N_BSS); |
334 |
|
|
else if (!strcmp(sn, ELF_TBSS)) |
335 |
|
|
return (N_BSS); |
336 |
|
|
else if (!strncmp(sn, ELF_GOT, sizeof(ELF_GOT) - 1)) |
337 |
|
|
return (N_DATA); |
338 |
|
|
else if (!strncmp(sn, ELF_PLT, sizeof(ELF_PLT) - 1)) |
339 |
|
|
return (N_DATA); |
340 |
|
|
} |
341 |
|
|
|
342 |
|
|
return (-1); |
343 |
|
|
} |
344 |
|
|
|
345 |
|
|
/* |
346 |
|
|
* Devise xnlist's type from Elf_Sym. |
347 |
|
|
* XXX this task is done as well in libc and kvm_mkdb. |
348 |
|
|
*/ |
349 |
|
|
int |
350 |
|
|
elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, |
351 |
|
|
struct xnlist *np) |
352 |
|
|
{ |
353 |
|
|
u_char stt; |
354 |
|
|
const char *sn; |
355 |
|
|
int type; |
356 |
|
|
|
357 |
|
|
if (sym->st_shndx < eh->e_shnum) |
358 |
|
|
sn = shstr + shdr[sym->st_shndx].sh_name; |
359 |
|
|
else |
360 |
|
|
sn = NULL; |
361 |
|
|
#if 0 |
362 |
|
|
{ |
363 |
|
|
extern char *stab; |
364 |
|
|
printf("%d:%s %d %d %s\n", sym->st_shndx, sn? sn : "", |
365 |
|
|
ELF_ST_TYPE(sym->st_info), ELF_ST_BIND(sym->st_info), |
366 |
|
|
stab + sym->st_name); |
367 |
|
|
} |
368 |
|
|
#endif |
369 |
|
|
|
370 |
|
|
switch (stt = ELF_ST_TYPE(sym->st_info)) { |
371 |
|
|
case STT_NOTYPE: |
372 |
|
|
case STT_OBJECT: |
373 |
|
|
case STT_TLS: |
374 |
|
|
type = elf_shn2type(eh, sym->st_shndx, sn); |
375 |
|
|
if (type < 0) { |
376 |
|
|
if (sn == NULL) |
377 |
|
|
np->nl.n_other = '?'; |
378 |
|
|
else |
379 |
|
|
np->nl.n_type = stt == STT_NOTYPE ? |
380 |
|
|
N_COMM : N_DATA; |
381 |
|
|
} else { |
382 |
|
|
/* a hack for .rodata check (; */ |
383 |
|
|
if (type == N_SIZE) { |
384 |
|
|
np->nl.n_type = N_DATA; |
385 |
|
|
np->nl.n_other = 'r'; |
386 |
|
|
} else |
387 |
|
|
np->nl.n_type = type; |
388 |
|
|
} |
389 |
|
|
if (ELF_ST_BIND(sym->st_info) == STB_WEAK) |
390 |
|
|
np->nl.n_other = 'W'; |
391 |
|
|
break; |
392 |
|
|
|
393 |
|
|
case STT_FUNC: |
394 |
|
|
type = elf_shn2type(eh, sym->st_shndx, NULL); |
395 |
|
|
np->nl.n_type = type < 0? N_TEXT : type; |
396 |
|
|
if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { |
397 |
|
|
np->nl.n_other = 'W'; |
398 |
|
|
} else if (sn != NULL && *sn != 0 && |
399 |
|
|
strcmp(sn, ELF_INIT) && |
400 |
|
|
strcmp(sn, ELF_TEXT) && |
401 |
|
|
strcmp(sn, ELF_FINI)) /* XXX GNU compat */ |
402 |
|
|
np->nl.n_other = '?'; |
403 |
|
|
break; |
404 |
|
|
|
405 |
|
|
case STT_SECTION: |
406 |
|
|
type = elf_shn2type(eh, sym->st_shndx, NULL); |
407 |
|
|
if (type < 0) |
408 |
|
|
np->nl.n_other = '?'; |
409 |
|
|
else |
410 |
|
|
np->nl.n_type = type; |
411 |
|
|
break; |
412 |
|
|
|
413 |
|
|
case STT_FILE: |
414 |
|
|
np->nl.n_type = N_FN | N_EXT; |
415 |
|
|
break; |
416 |
|
|
|
417 |
|
|
case STT_PARISC_MILLI: |
418 |
|
|
if (eh->e_machine == EM_PARISC) |
419 |
|
|
np->nl.n_type = N_TEXT; |
420 |
|
|
else |
421 |
|
|
np->nl.n_other = '?'; |
422 |
|
|
break; |
423 |
|
|
|
424 |
|
|
default: |
425 |
|
|
np->nl.n_other = '?'; |
426 |
|
|
break; |
427 |
|
|
} |
428 |
|
|
if (np->nl.n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) { |
429 |
|
|
np->nl.n_type |= N_EXT; |
430 |
|
|
if (np->nl.n_other) |
431 |
|
|
np->nl.n_other = toupper((unsigned char)np->nl.n_other); |
432 |
|
|
} |
433 |
|
|
|
434 |
|
|
return (0); |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
int |
438 |
|
|
elf_size(Elf_Ehdr *head, Elf_Shdr *shdr, |
439 |
|
|
u_long *ptext, u_long *pdata, u_long *pbss) |
440 |
|
|
{ |
441 |
|
|
int i; |
442 |
|
|
|
443 |
|
|
*ptext = *pdata = *pbss = 0; |
444 |
|
|
|
445 |
|
|
for (i = 0; i < head->e_shnum; i++) { |
446 |
|
|
if (!(shdr[i].sh_flags & SHF_ALLOC)) |
447 |
|
|
; |
448 |
|
|
else if (shdr[i].sh_flags & SHF_EXECINSTR || |
449 |
|
|
!(shdr[i].sh_flags & SHF_WRITE)) |
450 |
|
|
*ptext += shdr[i].sh_size; |
451 |
|
|
else if (shdr[i].sh_type == SHT_NOBITS) |
452 |
|
|
*pbss += shdr[i].sh_size; |
453 |
|
|
else |
454 |
|
|
*pdata += shdr[i].sh_size; |
455 |
|
|
} |
456 |
|
|
|
457 |
|
|
return (0); |
458 |
|
|
} |
459 |
|
|
|
460 |
|
|
int |
461 |
|
|
elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, |
462 |
|
|
Elf_Shdr *shdr, char *shstr, long shstrsize, struct xnlist **pnames, |
463 |
|
|
struct xnlist ***psnames, size_t *pstabsize, int *pnrawnames, |
464 |
|
|
const char *strtab, const char *symtab) |
465 |
|
|
{ |
466 |
|
|
long symsize; |
467 |
|
|
struct xnlist *np; |
468 |
|
|
Elf_Sym sbuf; |
469 |
|
|
int i; |
470 |
|
|
|
471 |
|
|
for (i = 0; i < eh->e_shnum; i++) { |
472 |
|
|
if (shdr[i].sh_name >= shstrsize) { |
473 |
|
|
warnx("%s: corrupt file", name); |
474 |
|
|
return (1); |
475 |
|
|
} |
476 |
|
|
if (!strcmp(shstr + shdr[i].sh_name, strtab)) { |
477 |
|
|
*pstabsize = shdr[i].sh_size; |
478 |
|
|
if (*pstabsize > SIZE_MAX) { |
479 |
|
|
warnx("%s: corrupt file", name); |
480 |
|
|
return (1); |
481 |
|
|
} |
482 |
|
|
|
483 |
|
|
MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE, |
484 |
|
|
fileno(fp), foff + shdr[i].sh_offset); |
485 |
|
|
if (stab == MAP_FAILED) |
486 |
|
|
return (1); |
487 |
|
|
} |
488 |
|
|
} |
489 |
|
|
for (i = 0; i < eh->e_shnum; i++) { |
490 |
|
|
if (!strcmp(shstr + shdr[i].sh_name, symtab)) { |
491 |
|
|
symsize = shdr[i].sh_size; |
492 |
|
|
if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) { |
493 |
|
|
warn("%s: fseeko", name); |
494 |
|
|
if (stab) |
495 |
|
|
MUNMAP(stab, *pstabsize); |
496 |
|
|
return (1); |
497 |
|
|
} |
498 |
|
|
|
499 |
|
|
*pnrawnames = symsize / sizeof(sbuf); |
500 |
|
|
if ((*pnames = calloc(*pnrawnames, sizeof(*np))) == NULL) { |
501 |
|
|
warn("%s: malloc names", name); |
502 |
|
|
if (stab) |
503 |
|
|
MUNMAP(stab, *pstabsize); |
504 |
|
|
*pnrawnames = 0; |
505 |
|
|
return (1); |
506 |
|
|
} |
507 |
|
|
if ((*psnames = calloc(*pnrawnames, sizeof(np))) == NULL) { |
508 |
|
|
warn("%s: malloc snames", name); |
509 |
|
|
if (stab) |
510 |
|
|
MUNMAP(stab, *pstabsize); |
511 |
|
|
free(*pnames); |
512 |
|
|
*pnames = NULL; |
513 |
|
|
*pnrawnames = 0; |
514 |
|
|
return (1); |
515 |
|
|
} |
516 |
|
|
|
517 |
|
|
for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) { |
518 |
|
|
if (fread(&sbuf, 1, sizeof(sbuf), |
519 |
|
|
fp) != sizeof(sbuf)) { |
520 |
|
|
warn("%s: read symbol", name); |
521 |
|
|
if (stab) |
522 |
|
|
MUNMAP(stab, *pstabsize); |
523 |
|
|
free(*pnames); |
524 |
|
|
free(*psnames); |
525 |
|
|
*pnames = NULL; |
526 |
|
|
*psnames = NULL; |
527 |
|
|
*pnrawnames = 0; |
528 |
|
|
return (1); |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
elf_fix_sym(eh, &sbuf); |
532 |
|
|
|
533 |
|
|
if (!sbuf.st_name || |
534 |
|
|
sbuf.st_name > *pstabsize) |
535 |
|
|
continue; |
536 |
|
|
|
537 |
|
|
elf2nlist(&sbuf, eh, shdr, shstr, np); |
538 |
|
|
np->nl.n_value = sbuf.st_value; |
539 |
|
|
np->nl.n_un.n_strx = sbuf.st_name; |
540 |
|
|
np->n_size = sbuf.st_size; |
541 |
|
|
np++; |
542 |
|
|
} |
543 |
|
|
*pnrawnames = np - *pnames; |
544 |
|
|
} |
545 |
|
|
} |
546 |
|
|
return (0); |
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
int |
550 |
|
|
elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, |
551 |
|
|
Elf_Shdr *shdr, struct xnlist **pnames, struct xnlist ***psnames, |
552 |
|
|
size_t *pstabsize, int *pnrawnames) |
553 |
|
|
{ |
554 |
|
|
long shstrsize; |
555 |
|
|
char *shstr; |
556 |
|
|
|
557 |
|
|
shstrsize = shdr[eh->e_shstrndx].sh_size; |
558 |
|
|
if (shstrsize == 0) { |
559 |
|
|
warnx("%s: no name list", name); |
560 |
|
|
return (1); |
561 |
|
|
} |
562 |
|
|
|
563 |
|
|
if ((shstr = malloc(shstrsize)) == NULL) { |
564 |
|
|
warn("%s: malloc shsrt", name); |
565 |
|
|
return (1); |
566 |
|
|
} |
567 |
|
|
|
568 |
|
|
if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) { |
569 |
|
|
warn("%s: fseeko", name); |
570 |
|
|
free(shstr); |
571 |
|
|
return (1); |
572 |
|
|
} |
573 |
|
|
|
574 |
|
|
if (fread(shstr, 1, shstrsize, fp) != shstrsize) { |
575 |
|
|
warnx("%s: premature EOF", name); |
576 |
|
|
free(shstr); |
577 |
|
|
return(1); |
578 |
|
|
} |
579 |
|
|
|
580 |
|
|
stab = NULL; |
581 |
|
|
*pnames = NULL; *psnames = NULL; *pnrawnames = 0; |
582 |
|
|
if (!dynamic_only) { |
583 |
|
|
elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames, |
584 |
|
|
psnames, pstabsize, pnrawnames, ELF_STRTAB, ELF_SYMTAB); |
585 |
|
|
} |
586 |
|
|
if (stab == NULL) { |
587 |
|
|
elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames, |
588 |
|
|
psnames, pstabsize, pnrawnames, ELF_DYNSTR, ELF_DYNSYM); |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
free(shstr); |
592 |
|
|
if (stab == NULL) { |
593 |
|
|
warnx("%s: no name list", name); |
594 |
|
|
free(*pnames); |
595 |
|
|
free(*psnames); |
596 |
|
|
return (1); |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
return (0); |
600 |
|
|
} |