1 |
/* $MidnightBSD$ */ |
2 |
/* |
3 |
* Copyright (c) 2000, Boris Popov |
4 |
* Copyright (c) 1998-2000 Doug Rabson |
5 |
* Copyright (c) 2004 Peter Wemm |
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 |
* 3. All advertising materials mentioning features or use of this software |
17 |
* must display the following acknowledgement: |
18 |
* This product includes software developed by Boris Popov. |
19 |
* 4. Neither the name of the author nor the names of any co-contributors |
20 |
* may be used to endorse or promote products derived from this software |
21 |
* without specific prior written permission. |
22 |
* |
23 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
24 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
27 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 |
* SUCH DAMAGE. |
34 |
* |
35 |
* $FreeBSD: stable/10/usr.sbin/kldxref/ef_obj.c 251440 2013-06-05 21:56:29Z delphij $ |
36 |
*/ |
37 |
|
38 |
#include <sys/param.h> |
39 |
#include <sys/linker.h> |
40 |
#include <string.h> |
41 |
#include <stdio.h> |
42 |
#include <stdlib.h> |
43 |
#include <unistd.h> |
44 |
#include <errno.h> |
45 |
#include <fcntl.h> |
46 |
#include <machine/elf.h> |
47 |
#define FREEBSD_ELF |
48 |
|
49 |
#include <err.h> |
50 |
|
51 |
#include "ef.h" |
52 |
|
53 |
typedef struct { |
54 |
void *addr; |
55 |
Elf_Off size; |
56 |
int flags; |
57 |
int sec; /* Original section */ |
58 |
char *name; |
59 |
} Elf_progent; |
60 |
|
61 |
typedef struct { |
62 |
Elf_Rel *rel; |
63 |
int nrel; |
64 |
int sec; |
65 |
} Elf_relent; |
66 |
|
67 |
typedef struct { |
68 |
Elf_Rela *rela; |
69 |
int nrela; |
70 |
int sec; |
71 |
} Elf_relaent; |
72 |
|
73 |
struct ef_file { |
74 |
char *ef_name; |
75 |
int ef_fd; |
76 |
Elf_Ehdr ef_hdr; |
77 |
struct elf_file *ef_efile; |
78 |
|
79 |
caddr_t address; |
80 |
Elf_Off size; |
81 |
Elf_Shdr *e_shdr; |
82 |
|
83 |
Elf_progent *progtab; |
84 |
int nprogtab; |
85 |
|
86 |
Elf_relaent *relatab; |
87 |
int nrela; |
88 |
|
89 |
Elf_relent *reltab; |
90 |
int nrel; |
91 |
|
92 |
Elf_Sym *ddbsymtab; /* The symbol table we are using */ |
93 |
long ddbsymcnt; /* Number of symbols */ |
94 |
caddr_t ddbstrtab; /* String table */ |
95 |
long ddbstrcnt; /* number of bytes in string table */ |
96 |
|
97 |
caddr_t shstrtab; /* Section name string table */ |
98 |
long shstrcnt; /* number of bytes in string table */ |
99 |
|
100 |
int ef_verbose; |
101 |
}; |
102 |
|
103 |
static int ef_obj_get_type(elf_file_t ef); |
104 |
static int ef_obj_close(elf_file_t ef); |
105 |
static int ef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void* dest); |
106 |
static int ef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, |
107 |
void **ptr); |
108 |
static int ef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, |
109 |
void *dest); |
110 |
static int ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, |
111 |
void *dest); |
112 |
static int ef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, |
113 |
void **ptr); |
114 |
static int ef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, |
115 |
void **ptr); |
116 |
static Elf_Addr ef_obj_symaddr(elf_file_t ef, Elf_Size symidx); |
117 |
static int ef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, |
118 |
long *stopp, long *countp); |
119 |
static int ef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym); |
120 |
|
121 |
static struct elf_file_ops ef_obj_file_ops = { |
122 |
ef_obj_get_type, |
123 |
ef_obj_close, |
124 |
ef_obj_read, |
125 |
ef_obj_read_entry, |
126 |
ef_obj_seg_read, |
127 |
ef_obj_seg_read_rel, |
128 |
ef_obj_seg_read_entry, |
129 |
ef_obj_seg_read_entry_rel, |
130 |
ef_obj_symaddr, |
131 |
ef_obj_lookup_set, |
132 |
ef_obj_lookup_symbol |
133 |
}; |
134 |
|
135 |
static int |
136 |
ef_obj_get_type(elf_file_t __unused ef) |
137 |
{ |
138 |
|
139 |
return (EFT_KLD); |
140 |
} |
141 |
|
142 |
static int |
143 |
ef_obj_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym) |
144 |
{ |
145 |
Elf_Sym *symp; |
146 |
const char *strp; |
147 |
int i; |
148 |
|
149 |
for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { |
150 |
strp = ef->ddbstrtab + symp->st_name; |
151 |
if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) { |
152 |
*sym = symp; |
153 |
return 0; |
154 |
} |
155 |
} |
156 |
return ENOENT; |
157 |
} |
158 |
|
159 |
static int |
160 |
ef_obj_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp, |
161 |
long *countp) |
162 |
{ |
163 |
int i; |
164 |
|
165 |
for (i = 0; i < ef->nprogtab; i++) { |
166 |
if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && |
167 |
strcmp(ef->progtab[i].name + 4, name) == 0) { |
168 |
*startp = (char *)ef->progtab[i].addr - ef->address; |
169 |
*stopp = (char *)ef->progtab[i].addr + |
170 |
ef->progtab[i].size - ef->address; |
171 |
*countp = (*stopp - *startp) / sizeof(void *); |
172 |
return (0); |
173 |
} |
174 |
} |
175 |
return (ESRCH); |
176 |
} |
177 |
|
178 |
static Elf_Addr |
179 |
ef_obj_symaddr(elf_file_t ef, Elf_Size symidx) |
180 |
{ |
181 |
const Elf_Sym *sym; |
182 |
|
183 |
if (symidx >= (size_t) ef->ddbsymcnt) |
184 |
return (0); |
185 |
sym = ef->ddbsymtab + symidx; |
186 |
|
187 |
if (sym->st_shndx != SHN_UNDEF) |
188 |
return (sym->st_value - (Elf_Addr)ef->address); |
189 |
return (0); |
190 |
} |
191 |
|
192 |
static int |
193 |
ef_obj_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) |
194 |
{ |
195 |
ssize_t r; |
196 |
|
197 |
if (offset != (Elf_Off)-1) { |
198 |
if (lseek(ef->ef_fd, offset, SEEK_SET) == -1) |
199 |
return EIO; |
200 |
} |
201 |
|
202 |
r = read(ef->ef_fd, dest, len); |
203 |
if (r != -1 && (size_t)r == len) |
204 |
return 0; |
205 |
else |
206 |
return EIO; |
207 |
} |
208 |
|
209 |
static int |
210 |
ef_obj_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) |
211 |
{ |
212 |
int error; |
213 |
|
214 |
*ptr = malloc(len); |
215 |
if (*ptr == NULL) |
216 |
return ENOMEM; |
217 |
error = ef_obj_read(ef, offset, len, *ptr); |
218 |
if (error) |
219 |
free(*ptr); |
220 |
return error; |
221 |
} |
222 |
|
223 |
static int |
224 |
ef_obj_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest) |
225 |
{ |
226 |
|
227 |
if (offset + len > ef->size) { |
228 |
if (ef->ef_verbose) |
229 |
warnx("ef_seg_read_rel(%s): bad offset/len (%lx:%ld)", |
230 |
ef->ef_name, (long)offset, (long)len); |
231 |
return (EFAULT); |
232 |
} |
233 |
bcopy(ef->address + offset, dest, len); |
234 |
return (0); |
235 |
} |
236 |
|
237 |
static int |
238 |
ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) |
239 |
{ |
240 |
char *memaddr; |
241 |
Elf_Rel *r; |
242 |
Elf_Rela *a; |
243 |
Elf_Off secbase, dataoff; |
244 |
int error, i, sec; |
245 |
|
246 |
if (offset + len > ef->size) { |
247 |
if (ef->ef_verbose) |
248 |
warnx("ef_seg_read_rel(%s): bad offset/len (%lx:%ld)", |
249 |
ef->ef_name, (long)offset, (long)len); |
250 |
return (EFAULT); |
251 |
} |
252 |
bcopy(ef->address + offset, dest, len); |
253 |
|
254 |
/* Find out which section contains the data. */ |
255 |
memaddr = ef->address + offset; |
256 |
sec = -1; |
257 |
secbase = dataoff = 0; |
258 |
for (i = 0; i < ef->nprogtab; i++) { |
259 |
if (ef->progtab[i].addr == NULL) |
260 |
continue; |
261 |
if (memaddr < (char *)ef->progtab[i].addr || memaddr + len > |
262 |
(char *)ef->progtab[i].addr + ef->progtab[i].size) |
263 |
continue; |
264 |
sec = ef->progtab[i].sec; |
265 |
/* We relocate to address 0. */ |
266 |
secbase = (char *)ef->progtab[i].addr - ef->address; |
267 |
dataoff = memaddr - ef->address; |
268 |
break; |
269 |
} |
270 |
|
271 |
if (sec == -1) |
272 |
return (EFAULT); |
273 |
|
274 |
/* Now do the relocations. */ |
275 |
for (i = 0; i < ef->nrel; i++) { |
276 |
if (ef->reltab[i].sec != sec) |
277 |
continue; |
278 |
for (r = ef->reltab[i].rel; |
279 |
r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { |
280 |
error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, secbase, |
281 |
dataoff, len, dest); |
282 |
if (error != 0) |
283 |
return (error); |
284 |
} |
285 |
} |
286 |
for (i = 0; i < ef->nrela; i++) { |
287 |
if (ef->relatab[i].sec != sec) |
288 |
continue; |
289 |
for (a = ef->relatab[i].rela; |
290 |
a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { |
291 |
error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, |
292 |
secbase, dataoff, len, dest); |
293 |
if (error != 0) |
294 |
return (error); |
295 |
} |
296 |
} |
297 |
return (0); |
298 |
} |
299 |
|
300 |
static int |
301 |
ef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr) |
302 |
{ |
303 |
int error; |
304 |
|
305 |
*ptr = malloc(len); |
306 |
if (*ptr == NULL) |
307 |
return ENOMEM; |
308 |
error = ef_obj_seg_read(ef, offset, len, *ptr); |
309 |
if (error) |
310 |
free(*ptr); |
311 |
return error; |
312 |
} |
313 |
|
314 |
static int |
315 |
ef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, |
316 |
void **ptr) |
317 |
{ |
318 |
int error; |
319 |
|
320 |
*ptr = malloc(len); |
321 |
if (*ptr == NULL) |
322 |
return ENOMEM; |
323 |
error = ef_obj_seg_read_rel(ef, offset, len, *ptr); |
324 |
if (error) |
325 |
free(*ptr); |
326 |
return error; |
327 |
} |
328 |
|
329 |
int |
330 |
ef_obj_open(const char *filename, struct elf_file *efile, int verbose) |
331 |
{ |
332 |
elf_file_t ef; |
333 |
Elf_Ehdr *hdr; |
334 |
Elf_Shdr *shdr; |
335 |
Elf_Sym *es; |
336 |
char *mapbase; |
337 |
void *vtmp; |
338 |
size_t mapsize, alignmask, max_addralign; |
339 |
int error, fd, pb, ra, res, rl; |
340 |
int i, j, nbytes, nsym, shstrindex, symstrindex, symtabindex; |
341 |
|
342 |
if (filename == NULL) |
343 |
return EFTYPE; |
344 |
if ((fd = open(filename, O_RDONLY)) == -1) |
345 |
return errno; |
346 |
|
347 |
ef = calloc(1, sizeof(*ef)); |
348 |
if (ef == NULL) { |
349 |
close(fd); |
350 |
return (ENOMEM); |
351 |
} |
352 |
|
353 |
efile->ef_ef = ef; |
354 |
efile->ef_ops = &ef_obj_file_ops; |
355 |
|
356 |
ef->ef_verbose = verbose; |
357 |
ef->ef_fd = fd; |
358 |
ef->ef_name = strdup(filename); |
359 |
ef->ef_efile = efile; |
360 |
hdr = (Elf_Ehdr *)&ef->ef_hdr; |
361 |
|
362 |
res = read(fd, hdr, sizeof(*hdr)); |
363 |
error = EFTYPE; |
364 |
if (res != sizeof(*hdr)) |
365 |
goto out; |
366 |
if (!IS_ELF(*hdr)) |
367 |
goto out; |
368 |
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || |
369 |
hdr->e_ident[EI_DATA] != ELF_TARG_DATA || |
370 |
hdr->e_ident[EI_VERSION] != EV_CURRENT || |
371 |
hdr->e_version != EV_CURRENT || hdr->e_machine != ELF_TARG_MACH || |
372 |
hdr->e_type != ET_REL) |
373 |
goto out; |
374 |
|
375 |
nbytes = hdr->e_shnum * hdr->e_shentsize; |
376 |
if (nbytes == 0 || hdr->e_shoff == 0 || |
377 |
hdr->e_shentsize != sizeof(Elf_Shdr)) |
378 |
goto out; |
379 |
|
380 |
if (ef_obj_read_entry(ef, hdr->e_shoff, nbytes, &vtmp) != 0) { |
381 |
printf("ef_read_entry failed\n"); |
382 |
goto out; |
383 |
} |
384 |
ef->e_shdr = shdr = vtmp; |
385 |
|
386 |
/* Scan the section header for information and table sizing. */ |
387 |
nsym = 0; |
388 |
symtabindex = -1; |
389 |
symstrindex = -1; |
390 |
for (i = 0; i < hdr->e_shnum; i++) { |
391 |
switch (shdr[i].sh_type) { |
392 |
case SHT_PROGBITS: |
393 |
case SHT_NOBITS: |
394 |
ef->nprogtab++; |
395 |
break; |
396 |
case SHT_SYMTAB: |
397 |
nsym++; |
398 |
symtabindex = i; |
399 |
symstrindex = shdr[i].sh_link; |
400 |
break; |
401 |
case SHT_REL: |
402 |
ef->nrel++; |
403 |
break; |
404 |
case SHT_RELA: |
405 |
ef->nrela++; |
406 |
break; |
407 |
case SHT_STRTAB: |
408 |
break; |
409 |
} |
410 |
} |
411 |
|
412 |
if (ef->nprogtab == 0) { |
413 |
warnx("%s: file has no contents", filename); |
414 |
goto out; |
415 |
} |
416 |
if (nsym != 1) { |
417 |
warnx("%s: file has no valid symbol table", filename); |
418 |
goto out; |
419 |
} |
420 |
if (symstrindex < 0 || symstrindex > hdr->e_shnum || |
421 |
shdr[symstrindex].sh_type != SHT_STRTAB) { |
422 |
warnx("%s: file has invalid symbol strings", filename); |
423 |
goto out; |
424 |
} |
425 |
|
426 |
/* Allocate space for tracking the load chunks */ |
427 |
if (ef->nprogtab != 0) |
428 |
ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab)); |
429 |
if (ef->nrel != 0) |
430 |
ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab)); |
431 |
if (ef->nrela != 0) |
432 |
ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab)); |
433 |
if ((ef->nprogtab != 0 && ef->progtab == NULL) || |
434 |
(ef->nrel != 0 && ef->reltab == NULL) || |
435 |
(ef->nrela != 0 && ef->relatab == NULL)) { |
436 |
printf("malloc failed\n"); |
437 |
error = ENOMEM; |
438 |
goto out; |
439 |
} |
440 |
|
441 |
ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); |
442 |
if (ef_obj_read_entry(ef, shdr[symtabindex].sh_offset, |
443 |
shdr[symtabindex].sh_size, (void**)&ef->ddbsymtab) != 0) { |
444 |
printf("ef_read_entry failed\n"); |
445 |
goto out; |
446 |
} |
447 |
|
448 |
ef->ddbstrcnt = shdr[symstrindex].sh_size; |
449 |
if (ef_obj_read_entry(ef, shdr[symstrindex].sh_offset, |
450 |
shdr[symstrindex].sh_size, (void**)&ef->ddbstrtab) != 0) { |
451 |
printf("ef_read_entry failed\n"); |
452 |
goto out; |
453 |
} |
454 |
|
455 |
/* Do we have a string table for the section names? */ |
456 |
shstrindex = -1; |
457 |
if (hdr->e_shstrndx != 0 && |
458 |
shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { |
459 |
shstrindex = hdr->e_shstrndx; |
460 |
ef->shstrcnt = shdr[shstrindex].sh_size; |
461 |
if (ef_obj_read_entry(ef, shdr[shstrindex].sh_offset, |
462 |
shdr[shstrindex].sh_size, (void**)&ef->shstrtab) != 0) { |
463 |
printf("ef_read_entry failed\n"); |
464 |
goto out; |
465 |
} |
466 |
} |
467 |
|
468 |
/* Size up code/data(progbits) and bss(nobits). */ |
469 |
alignmask = 0; |
470 |
max_addralign = 0; |
471 |
mapsize = 0; |
472 |
for (i = 0; i < hdr->e_shnum; i++) { |
473 |
switch (shdr[i].sh_type) { |
474 |
case SHT_PROGBITS: |
475 |
case SHT_NOBITS: |
476 |
alignmask = shdr[i].sh_addralign - 1; |
477 |
if (shdr[i].sh_addralign > max_addralign) |
478 |
max_addralign = shdr[i].sh_addralign; |
479 |
mapsize += alignmask; |
480 |
mapsize &= ~alignmask; |
481 |
mapsize += shdr[i].sh_size; |
482 |
break; |
483 |
} |
484 |
} |
485 |
|
486 |
/* We know how much space we need for the text/data/bss/etc. */ |
487 |
ef->size = mapsize; |
488 |
if (posix_memalign((void **)&ef->address, max_addralign, mapsize)) { |
489 |
printf("posix_memalign failed\n"); |
490 |
goto out; |
491 |
} |
492 |
mapbase = ef->address; |
493 |
|
494 |
/* |
495 |
* Now load code/data(progbits), zero bss(nobits), allocate |
496 |
* space for and load relocs |
497 |
*/ |
498 |
pb = 0; |
499 |
rl = 0; |
500 |
ra = 0; |
501 |
alignmask = 0; |
502 |
for (i = 0; i < hdr->e_shnum; i++) { |
503 |
switch (shdr[i].sh_type) { |
504 |
case SHT_PROGBITS: |
505 |
case SHT_NOBITS: |
506 |
alignmask = shdr[i].sh_addralign - 1; |
507 |
mapbase += alignmask; |
508 |
mapbase = (char *)((uintptr_t)mapbase & ~alignmask); |
509 |
ef->progtab[pb].addr = (void *)(uintptr_t)mapbase; |
510 |
if (shdr[i].sh_type == SHT_PROGBITS) { |
511 |
ef->progtab[pb].name = "<<PROGBITS>>"; |
512 |
if (ef_obj_read(ef, shdr[i].sh_offset, |
513 |
shdr[i].sh_size, |
514 |
ef->progtab[pb].addr) != 0) { |
515 |
printf("failed to read progbits\n"); |
516 |
goto out; |
517 |
} |
518 |
} else { |
519 |
ef->progtab[pb].name = "<<NOBITS>>"; |
520 |
bzero(ef->progtab[pb].addr, shdr[i].sh_size); |
521 |
} |
522 |
ef->progtab[pb].size = shdr[i].sh_size; |
523 |
ef->progtab[pb].sec = i; |
524 |
if (ef->shstrtab && shdr[i].sh_name != 0) |
525 |
ef->progtab[pb].name = |
526 |
ef->shstrtab + shdr[i].sh_name; |
527 |
|
528 |
/* Update all symbol values with the offset. */ |
529 |
for (j = 0; j < ef->ddbsymcnt; j++) { |
530 |
es = &ef->ddbsymtab[j]; |
531 |
if (es->st_shndx != i) |
532 |
continue; |
533 |
es->st_value += (Elf_Addr)ef->progtab[pb].addr; |
534 |
} |
535 |
mapbase += shdr[i].sh_size; |
536 |
pb++; |
537 |
break; |
538 |
case SHT_REL: |
539 |
ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel); |
540 |
ef->reltab[rl].sec = shdr[i].sh_info; |
541 |
if (ef_obj_read_entry(ef, shdr[i].sh_offset, |
542 |
shdr[i].sh_size, (void**)&ef->reltab[rl].rel) != |
543 |
0) { |
544 |
printf("ef_read_entry failed\n"); |
545 |
goto out; |
546 |
} |
547 |
rl++; |
548 |
break; |
549 |
case SHT_RELA: |
550 |
ef->relatab[ra].nrela = |
551 |
shdr[i].sh_size / sizeof(Elf_Rela); |
552 |
ef->relatab[ra].sec = shdr[i].sh_info; |
553 |
if (ef_obj_read_entry(ef, shdr[i].sh_offset, |
554 |
shdr[i].sh_size, (void**)&ef->relatab[ra].rela) != |
555 |
0) { |
556 |
printf("ef_read_entry failed\n"); |
557 |
goto out; |
558 |
} |
559 |
ra++; |
560 |
break; |
561 |
} |
562 |
} |
563 |
error = 0; |
564 |
out: |
565 |
if (error) |
566 |
ef_obj_close(ef); |
567 |
return error; |
568 |
} |
569 |
|
570 |
static int |
571 |
ef_obj_close(elf_file_t ef) |
572 |
{ |
573 |
int i; |
574 |
|
575 |
close(ef->ef_fd); |
576 |
if (ef->ef_name) |
577 |
free(ef->ef_name); |
578 |
if (ef->e_shdr != NULL) |
579 |
free(ef->e_shdr); |
580 |
if (ef->size != 0) |
581 |
free(ef->address); |
582 |
if (ef->nprogtab != 0) |
583 |
free(ef->progtab); |
584 |
if (ef->nrel != 0) { |
585 |
for (i = 0; i < ef->nrel; i++) |
586 |
if (ef->reltab[i].rel != NULL) |
587 |
free(ef->reltab[i].rel); |
588 |
free(ef->reltab); |
589 |
} |
590 |
if (ef->nrela != 0) { |
591 |
for (i = 0; i < ef->nrela; i++) |
592 |
if (ef->relatab[i].rela != NULL) |
593 |
free(ef->relatab[i].rela); |
594 |
free(ef->relatab); |
595 |
} |
596 |
if (ef->ddbsymtab != NULL) |
597 |
free(ef->ddbsymtab); |
598 |
if (ef->ddbstrtab != NULL) |
599 |
free(ef->ddbstrtab); |
600 |
if (ef->shstrtab != NULL) |
601 |
free(ef->shstrtab); |
602 |
ef->ef_efile->ef_ops = NULL; |
603 |
ef->ef_efile->ef_ef = NULL; |
604 |
free(ef); |
605 |
|
606 |
return 0; |
607 |
} |