GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#define ELFSIZE 64 |
||
2 |
/* $OpenBSD: elf.c,v 1.34 2015/12/09 19:28:34 mmcc 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_abi.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 |
✓✗ | 28292 |
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
127 |
14146 |
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 |
14146 |
} |
|
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 |
28292 |
elf_fix_header(head); |
|
152 |
|||
153 |
✗✓ | 14146 |
if (head->e_shnum == 0) { |
154 |
warnx("%s: no section header table", name); |
||
155 |
return (NULL); |
||
156 |
} |
||
157 |
|||
158 |
✗✓ | 14146 |
if (head->e_shstrndx >= head->e_shnum) { |
159 |
warnx("%s: inconsistent section header table", name); |
||
160 |
return (NULL); |
||
161 |
} |
||
162 |
|||
163 |
✗✓ | 14146 |
if (head->e_shentsize < sizeof(Elf_Shdr)) { |
164 |
warnx("%s: inconsistent section header size", name); |
||
165 |
return (NULL); |
||
166 |
} |
||
167 |
|||
168 |
✗✓ | 14146 |
if ((shdr = calloc(head->e_shnum, head->e_shentsize)) == NULL) { |
169 |
warn("%s: malloc shdr", name); |
||
170 |
return (NULL); |
||
171 |
} |
||
172 |
|||
173 |
✗✓ | 14146 |
if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) { |
174 |
warn("%s: fseeko", name); |
||
175 |
free(shdr); |
||
176 |
return (NULL); |
||
177 |
} |
||
178 |
|||
179 |
✗✓ | 14146 |
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 |
14146 |
elf_fix_shdrs(head, shdr); |
|
186 |
14146 |
return (shdr); |
|
187 |
14146 |
} |
|
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 |
✓✗ | 28292 |
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
222 |
14146 |
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 |
14146 |
} |
|
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 |
✓✗ | 2017946 |
if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) |
268 |
1008973 |
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 |
1008973 |
} |
|
277 |
|||
278 |
int |
||
279 |
elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn) |
||
280 |
{ |
||
281 |
✗✓✗✗ ✗✓✗✗ ✓ |
1222504 |
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 |
198536 |
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 |
413 |
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 |
✓✓ | 412303 |
if (sn == NULL) |
319 |
123046 |
return (-1); |
|
320 |
✓✓ | 289257 |
else if (!strcmp(sn, ELF_TEXT)) |
321 |
198 |
return (N_TEXT); |
|
322 |
✓✓ | 289059 |
else if (!strcmp(sn, ELF_RODATA)) |
323 |
4242 |
return (N_SIZE); |
|
324 |
✓✓ | 284817 |
else if (!strcmp(sn, ELF_DATA)) |
325 |
7857 |
return (N_DATA); |
|
326 |
✗✓ | 276960 |
else if (!strcmp(sn, ELF_SDATA)) |
327 |
return (N_DATA); |
||
328 |
✗✓ | 276960 |
else if (!strcmp(sn, ELF_TDATA)) |
329 |
return (N_DATA); |
||
330 |
✓✓ | 276960 |
else if (!strcmp(sn, ELF_BSS)) |
331 |
77825 |
return (N_BSS); |
|
332 |
✗✓ | 199135 |
else if (!strcmp(sn, ELF_SBSS)) |
333 |
return (N_BSS); |
||
334 |
✗✓ | 199135 |
else if (!strcmp(sn, ELF_TBSS)) |
335 |
return (N_BSS); |
||
336 |
✗✓ | 199135 |
else if (!strncmp(sn, ELF_GOT, sizeof(ELF_GOT) - 1)) |
337 |
return (N_DATA); |
||
338 |
✗✓ | 199135 |
else if (!strncmp(sn, ELF_PLT, sizeof(ELF_PLT) - 1)) |
339 |
return (N_DATA); |
||
340 |
} |
||
341 |
|||
342 |
199135 |
return (-1); |
|
343 |
611252 |
} |
|
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 |
✓✓ | 1249638 |
if (sym->st_shndx < eh->e_shnum) |
358 |
610839 |
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 |
✗✗✓✓ ✗✓✗✗ |
624819 |
switch (stt = ELF_ST_TYPE(sym->st_info)) { |
371 |
case STT_NOTYPE: |
||
372 |
case STT_OBJECT: |
||
373 |
case STT_TLS: |
||
374 |
488206 |
type = elf_shn2type(eh, sym->st_shndx, sn); |
|
375 |
✓✓ | 488206 |
if (type < 0) { |
376 |
✗✓ | 199135 |
if (sn == NULL) |
377 |
np->nl.n_other = '?'; |
||
378 |
else |
||
379 |
199135 |
np->nl.n_type = stt == STT_NOTYPE ? |
|
380 |
N_COMM : N_DATA; |
||
381 |
} else { |
||
382 |
/* a hack for .rodata check (; */ |
||
383 |
✓✓ | 289071 |
if (type == N_SIZE) { |
384 |
4242 |
np->nl.n_type = N_DATA; |
|
385 |
4242 |
np->nl.n_other = 'r'; |
|
386 |
4242 |
} else |
|
387 |
284829 |
np->nl.n_type = type; |
|
388 |
} |
||
389 |
✓✓ | 488206 |
if (ELF_ST_BIND(sym->st_info) == STB_WEAK) |
390 |
1122 |
np->nl.n_other = 'W'; |
|
391 |
break; |
||
392 |
|||
393 |
case STT_FUNC: |
||
394 |
123046 |
type = elf_shn2type(eh, sym->st_shndx, NULL); |
|
395 |
123046 |
np->nl.n_type = type < 0? N_TEXT : type; |
|
396 |
✓✓ | 123046 |
if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { |
397 |
12541 |
np->nl.n_other = 'W'; |
|
398 |
✓✗✓✗ ✗✗ |
233551 |
} else if (sn != NULL && *sn != 0 && |
399 |
✓✗ | 110505 |
strcmp(sn, ELF_INIT) && |
400 |
✗✓ | 110505 |
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 |
13567 |
np->nl.n_type = N_FN | N_EXT; |
|
415 |
13567 |
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 |
✓✗✓✓ |
1249638 |
if (np->nl.n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) { |
429 |
276338 |
np->nl.n_type |= N_EXT; |
|
430 |
✓✓ | 276338 |
if (np->nl.n_other) |
431 |
15068 |
np->nl.n_other = toupper((unsigned char)np->nl.n_other); |
|
432 |
} |
||
433 |
|||
434 |
624819 |
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 |
28292 |
Elf_Sym sbuf; |
|
469 |
int i; |
||
470 |
|||
471 |
✓✓ | 796640 |
for (i = 0; i < eh->e_shnum; i++) { |
472 |
✗✓ | 384174 |
if (shdr[i].sh_name >= shstrsize) { |
473 |
warnx("%s: corrupt file", name); |
||
474 |
return (1); |
||
475 |
} |
||
476 |
✓✓ | 384174 |
if (!strcmp(shstr + shdr[i].sh_name, strtab)) { |
477 |
14146 |
*pstabsize = shdr[i].sh_size; |
|
478 |
✗✓ | 14146 |
if (*pstabsize > SIZE_MAX) { |
479 |
warnx("%s: corrupt file", name); |
||
480 |
return (1); |
||
481 |
} |
||
482 |
|||
483 |
✓✗✗✓ ✗✗✗✗ ✗✗✗✗ |
42438 |
MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE, |
484 |
fileno(fp), foff + shdr[i].sh_offset); |
||
485 |
✗✓ | 14146 |
if (stab == MAP_FAILED) |
486 |
return (1); |
||
487 |
} |
||
488 |
} |
||
489 |
✓✓ | 796640 |
for (i = 0; i < eh->e_shnum; i++) { |
490 |
✓✓ | 384174 |
if (!strcmp(shstr + shdr[i].sh_name, symtab)) { |
491 |
14146 |
symsize = shdr[i].sh_size; |
|
492 |
✗✓ | 14146 |
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 |
14146 |
*pnrawnames = symsize / sizeof(sbuf); |
|
500 |
✗✓ | 14146 |
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 |
✗✓ | 14146 |
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 |
✓✓ | 2046238 |
for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) { |
518 |
✗✓ | 2017946 |
if (fread(&sbuf, 1, sizeof(sbuf), |
519 |
1008973 |
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 |
1008973 |
elf_fix_sym(eh, &sbuf); |
|
532 |
|||
533 |
✓✓✓✗ |
1633792 |
if (!sbuf.st_name || |
534 |
624819 |
sbuf.st_name > *pstabsize) |
|
535 |
continue; |
||
536 |
|||
537 |
624819 |
elf2nlist(&sbuf, eh, shdr, shstr, np); |
|
538 |
624819 |
np->nl.n_value = sbuf.st_value; |
|
539 |
624819 |
np->nl.n_un.n_strx = sbuf.st_name; |
|
540 |
624819 |
np->n_size = sbuf.st_size; |
|
541 |
624819 |
np++; |
|
542 |
624819 |
} |
|
543 |
14146 |
*pnrawnames = np - *pnames; |
|
544 |
14146 |
} |
|
545 |
} |
||
546 |
14146 |
return (0); |
|
547 |
14146 |
} |
|
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 |
28292 |
shstrsize = shdr[eh->e_shstrndx].sh_size; |
|
558 |
✗✓ | 14146 |
if (shstrsize == 0) { |
559 |
warnx("%s: no name list", name); |
||
560 |
return (1); |
||
561 |
} |
||
562 |
|||
563 |
✗✓ | 14146 |
if ((shstr = malloc(shstrsize)) == NULL) { |
564 |
warn("%s: malloc shsrt", name); |
||
565 |
return (1); |
||
566 |
} |
||
567 |
|||
568 |
✗✓ | 14146 |
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 |
✗✓ | 14146 |
if (fread(shstr, 1, shstrsize, fp) != shstrsize) { |
575 |
warnx("%s: premature EOF", name); |
||
576 |
free(shstr); |
||
577 |
return(1); |
||
578 |
} |
||
579 |
|||
580 |
14146 |
stab = NULL; |
|
581 |
14146 |
*pnames = NULL; *psnames = NULL; *pnrawnames = 0; |
|
582 |
✓✗ | 14146 |
if (!dynamic_only) { |
583 |
14146 |
elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames, |
|
584 |
psnames, pstabsize, pnrawnames, ELF_STRTAB, ELF_SYMTAB); |
||
585 |
14146 |
} |
|
586 |
✗✓ | 14146 |
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 |
14146 |
free(shstr); |
|
592 |
✗✓ | 14146 |
if (stab == NULL) { |
593 |
warnx("%s: no name list", name); |
||
594 |
free(*pnames); |
||
595 |
free(*psnames); |
||
596 |
return (1); |
||
597 |
} |
||
598 |
|||
599 |
14146 |
return (0); |
|
600 |
14146 |
} |
Generated by: GCOVR (Version 3.3) |