1 /*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 2000, Boris Popov
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Boris Popov.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD$
35 */
36
37 #include <sys/param.h>
38 #include <sys/linker.h>
39
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <machine/elf.h>
48 #define FREEBSD_ELF
49
50 #include "ef.h"
51
52 #define MAXSEGS 16
53 struct ef_file {
54 char *ef_name;
55 struct elf_file *ef_efile;
56 Elf_Phdr *ef_ph;
57 int ef_fd;
58 int ef_type;
59 Elf_Ehdr ef_hdr;
60 void *ef_fpage; /* First block of the file */
61 int ef_fplen; /* length of first block */
62 Elf_Dyn *ef_dyn; /* Symbol table etc. */
63 Elf_Hashelt ef_nbuckets;
64 Elf_Hashelt ef_nchains;
65 Elf_Hashelt *ef_buckets;
66 Elf_Hashelt *ef_chains;
67 Elf_Hashelt *ef_hashtab;
68 Elf_Off ef_stroff;
69 caddr_t ef_strtab;
70 int ef_strsz;
71 Elf_Off ef_symoff;
72 Elf_Sym *ef_symtab;
73 int ef_nsegs;
74 Elf_Phdr *ef_segs[MAXSEGS];
75 int ef_verbose;
76 Elf_Rel *ef_rel; /* relocation table */
77 int ef_relsz; /* number of entries */
78 Elf_Rela *ef_rela; /* relocation table */
79 int ef_relasz; /* number of entries */
80 };
81
82 static void ef_print_phdr(Elf_Phdr *);
83 static Elf_Off ef_get_offset(elf_file_t, Elf_Off);
84 static int ef_parse_dynamic(elf_file_t);
85
86 static int ef_get_type(elf_file_t ef);
87 static int ef_close(elf_file_t ef);
88 static int ef_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest);
89 static int ef_read_entry(elf_file_t ef, Elf_Off offset, size_t len,
90 void **ptr);
91
92 static int ef_seg_read(elf_file_t ef, Elf_Off offset, size_t len,
93 void *dest);
94 static int ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len,
95 void *dest);
96 static int ef_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len,
97 char *dest);
98 static int ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len,
99 void **ptr);
100 static int ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len,
101 void **ptr);
102
103 static Elf_Addr ef_symaddr(elf_file_t ef, Elf_Size symidx);
104 static int ef_lookup_set(elf_file_t ef, const char *name, long *startp,
105 long *stopp, long *countp);
106 static int ef_lookup_symbol(elf_file_t ef, const char *name,
107 Elf_Sym **sym);
108
109 static struct elf_file_ops ef_file_ops = {
110 .get_type = ef_get_type,
111 .close = ef_close,
112 .read = ef_read,
113 .read_entry = ef_read_entry,
114 .seg_read = ef_seg_read,
115 .seg_read_rel = ef_seg_read_rel,
116 .seg_read_string = ef_seg_read_string,
117 .seg_read_entry = ef_seg_read_entry,
118 .seg_read_entry_rel = ef_seg_read_entry_rel,
119 .symaddr = ef_symaddr,
120 .lookup_set = ef_lookup_set,
121 .lookup_symbol = ef_lookup_symbol
122 };
123
124 static void
ef_print_phdr(Elf_Phdr * phdr)125 ef_print_phdr(Elf_Phdr *phdr)
126 {
127
128 if ((phdr->p_flags & PF_W) == 0) {
129 printf("text=0x%jx ", (uintmax_t)phdr->p_filesz);
130 } else {
131 printf("data=0x%jx", (uintmax_t)phdr->p_filesz);
132 if (phdr->p_filesz < phdr->p_memsz)
133 printf("+0x%jx",
134 (uintmax_t)(phdr->p_memsz - phdr->p_filesz));
135 printf(" ");
136 }
137 }
138
139 static Elf_Off
ef_get_offset(elf_file_t ef,Elf_Off off)140 ef_get_offset(elf_file_t ef, Elf_Off off)
141 {
142 Elf_Phdr *ph;
143 int i;
144
145 for (i = 0; i < ef->ef_nsegs; i++) {
146 ph = ef->ef_segs[i];
147 if (off >= ph->p_vaddr && off < ph->p_vaddr + ph->p_memsz) {
148 return (ph->p_offset + (off - ph->p_vaddr));
149 }
150 }
151 return (0);
152 }
153
154 static int
ef_get_type(elf_file_t ef)155 ef_get_type(elf_file_t ef)
156 {
157
158 return (ef->ef_type);
159 }
160
161 /*
162 * next three functions copied from link_elf.c
163 */
164 static unsigned long
elf_hash(const char * name)165 elf_hash(const char *name)
166 {
167 unsigned long h, g;
168 const unsigned char *p;
169
170 h = 0;
171 p = (const unsigned char *)name;
172 while (*p != '\0') {
173 h = (h << 4) + *p++;
174 if ((g = h & 0xf0000000) != 0)
175 h ^= g >> 24;
176 h &= ~g;
177 }
178 return (h);
179 }
180
181 static int
ef_lookup_symbol(elf_file_t ef,const char * name,Elf_Sym ** sym)182 ef_lookup_symbol(elf_file_t ef, const char *name, Elf_Sym **sym)
183 {
184 unsigned long hash, symnum;
185 Elf_Sym *symp;
186 char *strp;
187
188 /* First, search hashed global symbols */
189 hash = elf_hash(name);
190 symnum = ef->ef_buckets[hash % ef->ef_nbuckets];
191
192 while (symnum != STN_UNDEF) {
193 if (symnum >= ef->ef_nchains) {
194 warnx("ef_lookup_symbol: file %s have corrupted symbol table\n",
195 ef->ef_name);
196 return (ENOENT);
197 }
198
199 symp = ef->ef_symtab + symnum;
200 if (symp->st_name == 0) {
201 warnx("ef_lookup_symbol: file %s have corrupted symbol table\n",
202 ef->ef_name);
203 return (ENOENT);
204 }
205
206 strp = ef->ef_strtab + symp->st_name;
207
208 if (strcmp(name, strp) == 0) {
209 if (symp->st_shndx != SHN_UNDEF ||
210 (symp->st_value != 0 &&
211 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
212 *sym = symp;
213 return (0);
214 } else
215 return (ENOENT);
216 }
217
218 symnum = ef->ef_chains[symnum];
219 }
220
221 return (ENOENT);
222 }
223
224 static int
ef_lookup_set(elf_file_t ef,const char * name,long * startp,long * stopp,long * countp)225 ef_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp,
226 long *countp)
227 {
228 Elf_Sym *sym;
229 char *setsym;
230 int error, len;
231
232 len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */
233 setsym = malloc(len);
234 if (setsym == NULL)
235 return (errno);
236
237 /* get address of first entry */
238 snprintf(setsym, len, "%s%s", "__start_set_", name);
239 error = ef_lookup_symbol(ef, setsym, &sym);
240 if (error != 0)
241 goto out;
242 *startp = sym->st_value;
243
244 /* get address of last entry */
245 snprintf(setsym, len, "%s%s", "__stop_set_", name);
246 error = ef_lookup_symbol(ef, setsym, &sym);
247 if (error != 0)
248 goto out;
249 *stopp = sym->st_value;
250
251 /* and the number of entries */
252 *countp = (*stopp - *startp) / sizeof(void *);
253
254 out:
255 free(setsym);
256 return (error);
257 }
258
259 static Elf_Addr
ef_symaddr(elf_file_t ef,Elf_Size symidx)260 ef_symaddr(elf_file_t ef, Elf_Size symidx)
261 {
262 const Elf_Sym *sym;
263
264 if (symidx >= ef->ef_nchains)
265 return (0);
266 sym = ef->ef_symtab + symidx;
267
268 if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
269 sym->st_shndx != SHN_UNDEF && sym->st_value != 0)
270 return (sym->st_value);
271 return (0);
272 }
273
274 static int
ef_parse_dynamic(elf_file_t ef)275 ef_parse_dynamic(elf_file_t ef)
276 {
277 Elf_Dyn *dp;
278 Elf_Hashelt hashhdr[2];
279 int error;
280 Elf_Off rel_off;
281 Elf_Off rela_off;
282 int rel_sz;
283 int rela_sz;
284 int rel_entry;
285 int rela_entry;
286
287 rel_off = rela_off = 0;
288 rel_sz = rela_sz = 0;
289 rel_entry = rela_entry = 0;
290 for (dp = ef->ef_dyn; dp->d_tag != DT_NULL; dp++) {
291 switch (dp->d_tag) {
292 case DT_HASH:
293 error = ef_read(ef, ef_get_offset(ef, dp->d_un.d_ptr),
294 sizeof(hashhdr), hashhdr);
295 if (error != 0) {
296 warnx("can't read hash header (%jx)",
297 (uintmax_t)ef_get_offset(ef, dp->d_un.d_ptr));
298 return (error);
299 }
300 ef->ef_nbuckets = hashhdr[0];
301 ef->ef_nchains = hashhdr[1];
302 error = ef_read_entry(ef, -1,
303 (hashhdr[0] + hashhdr[1]) * sizeof(Elf_Hashelt),
304 (void **)&ef->ef_hashtab);
305 if (error != 0) {
306 warnx("can't read hash table");
307 return (error);
308 }
309 ef->ef_buckets = ef->ef_hashtab;
310 ef->ef_chains = ef->ef_buckets + ef->ef_nbuckets;
311 break;
312 case DT_STRTAB:
313 ef->ef_stroff = dp->d_un.d_ptr;
314 break;
315 case DT_STRSZ:
316 ef->ef_strsz = dp->d_un.d_val;
317 break;
318 case DT_SYMTAB:
319 ef->ef_symoff = dp->d_un.d_ptr;
320 break;
321 case DT_SYMENT:
322 if (dp->d_un.d_val != sizeof(Elf_Sym))
323 return (EFTYPE);
324 break;
325 case DT_REL:
326 if (rel_off != 0)
327 warnx("second DT_REL entry ignored");
328 rel_off = dp->d_un.d_ptr;
329 break;
330 case DT_RELSZ:
331 if (rel_sz != 0)
332 warnx("second DT_RELSZ entry ignored");
333 rel_sz = dp->d_un.d_val;
334 break;
335 case DT_RELENT:
336 if (rel_entry != 0)
337 warnx("second DT_RELENT entry ignored");
338 rel_entry = dp->d_un.d_val;
339 break;
340 case DT_RELA:
341 if (rela_off != 0)
342 warnx("second DT_RELA entry ignored");
343 rela_off = dp->d_un.d_ptr;
344 break;
345 case DT_RELASZ:
346 if (rela_sz != 0)
347 warnx("second DT_RELASZ entry ignored");
348 rela_sz = dp->d_un.d_val;
349 break;
350 case DT_RELAENT:
351 if (rela_entry != 0)
352 warnx("second DT_RELAENT entry ignored");
353 rela_entry = dp->d_un.d_val;
354 break;
355 }
356 }
357 if (ef->ef_symoff == 0) {
358 warnx("%s: no .dynsym section found\n", ef->ef_name);
359 return (EFTYPE);
360 }
361 if (ef->ef_stroff == 0) {
362 warnx("%s: no .dynstr section found\n", ef->ef_name);
363 return (EFTYPE);
364 }
365 if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_symoff),
366 ef->ef_nchains * sizeof(Elf_Sym),
367 (void **)&ef->ef_symtab) != 0) {
368 if (ef->ef_verbose)
369 warnx("%s: can't load .dynsym section (0x%jx)",
370 ef->ef_name, (uintmax_t)ef->ef_symoff);
371 return (EIO);
372 }
373 if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_stroff), ef->ef_strsz,
374 (void **)&ef->ef_strtab) != 0) {
375 warnx("can't load .dynstr section");
376 return (EIO);
377 }
378 if (rel_off != 0) {
379 if (rel_entry == 0) {
380 warnx("%s: no DT_RELENT for DT_REL", ef->ef_name);
381 return (EFTYPE);
382 }
383 if (rel_entry != sizeof(Elf_Rel)) {
384 warnx("%s: inconsistent DT_RELENT value",
385 ef->ef_name);
386 return (EFTYPE);
387 }
388 if (rel_sz % rel_entry != 0) {
389 warnx("%s: inconsistent values for DT_RELSZ and "
390 "DT_RELENT", ef->ef_name);
391 return (EFTYPE);
392 }
393 if (ef_read_entry(ef, ef_get_offset(ef, rel_off), rel_sz,
394 (void **)&ef->ef_rel) != 0) {
395 warnx("%s: cannot load DT_REL section", ef->ef_name);
396 return (EIO);
397 }
398 ef->ef_relsz = rel_sz / rel_entry;
399 if (ef->ef_verbose)
400 warnx("%s: %d REL entries", ef->ef_name,
401 ef->ef_relsz);
402 }
403 if (rela_off != 0) {
404 if (rela_entry == 0) {
405 warnx("%s: no DT_RELAENT for DT_RELA", ef->ef_name);
406 return (EFTYPE);
407 }
408 if (rela_entry != sizeof(Elf_Rela)) {
409 warnx("%s: inconsistent DT_RELAENT value",
410 ef->ef_name);
411 return (EFTYPE);
412 }
413 if (rela_sz % rela_entry != 0) {
414 warnx("%s: inconsistent values for DT_RELASZ and "
415 "DT_RELAENT", ef->ef_name);
416 return (EFTYPE);
417 }
418 if (ef_read_entry(ef, ef_get_offset(ef, rela_off), rela_sz,
419 (void **)&ef->ef_rela) != 0) {
420 warnx("%s: cannot load DT_RELA section", ef->ef_name);
421 return (EIO);
422 }
423 ef->ef_relasz = rela_sz / rela_entry;
424 if (ef->ef_verbose)
425 warnx("%s: %d RELA entries", ef->ef_name,
426 ef->ef_relasz);
427 }
428 return (0);
429 }
430
431 static int
ef_read(elf_file_t ef,Elf_Off offset,size_t len,void * dest)432 ef_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest)
433 {
434 ssize_t r;
435
436 if (offset != (Elf_Off)-1) {
437 if (lseek(ef->ef_fd, offset, SEEK_SET) == -1)
438 return (EIO);
439 }
440
441 r = read(ef->ef_fd, dest, len);
442 if (r != -1 && (size_t)r == len)
443 return (0);
444 else
445 return (EIO);
446 }
447
448 static int
ef_read_entry(elf_file_t ef,Elf_Off offset,size_t len,void ** ptr)449 ef_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr)
450 {
451 int error;
452
453 *ptr = malloc(len);
454 if (*ptr == NULL)
455 return (errno);
456 error = ef_read(ef, offset, len, *ptr);
457 if (error != 0)
458 free(*ptr);
459 return (error);
460 }
461
462 static int
ef_seg_read(elf_file_t ef,Elf_Off offset,size_t len,void * dest)463 ef_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest)
464 {
465 Elf_Off ofs;
466
467 ofs = ef_get_offset(ef, offset);
468 if (ofs == 0) {
469 if (ef->ef_verbose)
470 warnx("ef_seg_read(%s): zero offset (%jx:%ju)",
471 ef->ef_name, (uintmax_t)offset, (uintmax_t)ofs);
472 return (EFAULT);
473 }
474 return (ef_read(ef, ofs, len, dest));
475 }
476
477 static int
ef_seg_read_rel(elf_file_t ef,Elf_Off offset,size_t len,void * dest)478 ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest)
479 {
480 Elf_Off ofs;
481 const Elf_Rela *a;
482 const Elf_Rel *r;
483 int error;
484
485 ofs = ef_get_offset(ef, offset);
486 if (ofs == 0) {
487 if (ef->ef_verbose)
488 warnx("ef_seg_read_rel(%s): zero offset (%jx:%ju)",
489 ef->ef_name, (uintmax_t)offset, (uintmax_t)ofs);
490 return (EFAULT);
491 }
492 if ((error = ef_read(ef, ofs, len, dest)) != 0)
493 return (error);
494
495 for (r = ef->ef_rel; r < &ef->ef_rel[ef->ef_relsz]; r++) {
496 error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, 0, offset, len,
497 dest);
498 if (error != 0)
499 return (error);
500 }
501 for (a = ef->ef_rela; a < &ef->ef_rela[ef->ef_relasz]; a++) {
502 error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, 0, offset, len,
503 dest);
504 if (error != 0)
505 return (error);
506 }
507 return (0);
508 }
509
510 static int
ef_seg_read_string(elf_file_t ef,Elf_Off offset,size_t len,char * dest)511 ef_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len, char *dest)
512 {
513 Elf_Off ofs;
514 ssize_t r;
515
516 ofs = ef_get_offset(ef, offset);
517 if (ofs == 0 || ofs == (Elf_Off)-1) {
518 if (ef->ef_verbose)
519 warnx("ef_seg_read_string(%s): bad offset (%jx:%ju)",
520 ef->ef_name, (uintmax_t)offset, (uintmax_t)ofs);
521 return (EFAULT);
522 }
523
524 r = pread(ef->ef_fd, dest, len, ofs);
525 if (r < 0)
526 return (errno);
527 if (strnlen(dest, len) == len)
528 return (EFAULT);
529
530 return (0);
531 }
532
533 static int
ef_seg_read_entry(elf_file_t ef,Elf_Off offset,size_t len,void ** ptr)534 ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr)
535 {
536 int error;
537
538 *ptr = malloc(len);
539 if (*ptr == NULL)
540 return (errno);
541 error = ef_seg_read(ef, offset, len, *ptr);
542 if (error != 0)
543 free(*ptr);
544 return (error);
545 }
546
547 static int
ef_seg_read_entry_rel(elf_file_t ef,Elf_Off offset,size_t len,void ** ptr)548 ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, void **ptr)
549 {
550 int error;
551
552 *ptr = malloc(len);
553 if (*ptr == NULL)
554 return (errno);
555 error = ef_seg_read_rel(ef, offset, len, *ptr);
556 if (error != 0)
557 free(*ptr);
558 return (error);
559 }
560
561 int
ef_open(const char * filename,struct elf_file * efile,int verbose)562 ef_open(const char *filename, struct elf_file *efile, int verbose)
563 {
564 elf_file_t ef;
565 Elf_Ehdr *hdr;
566 int fd;
567 int error;
568 int phlen, res;
569 int nsegs;
570 Elf_Phdr *phdr, *phdyn, *phlimit;
571
572 if (filename == NULL)
573 return (EINVAL);
574 if ((fd = open(filename, O_RDONLY)) == -1)
575 return (errno);
576
577 ef = malloc(sizeof(*ef));
578 if (ef == NULL) {
579 close(fd);
580 return (errno);
581 }
582
583 efile->ef_ef = ef;
584 efile->ef_ops = &ef_file_ops;
585
586 bzero(ef, sizeof(*ef));
587 ef->ef_verbose = verbose;
588 ef->ef_fd = fd;
589 ef->ef_name = strdup(filename);
590 ef->ef_efile = efile;
591 hdr = (Elf_Ehdr *)&ef->ef_hdr;
592 do {
593 res = read(fd, hdr, sizeof(*hdr));
594 error = EFTYPE;
595 if (res != sizeof(*hdr))
596 break;
597 if (!IS_ELF(*hdr))
598 break;
599 if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
600 hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
601 hdr->e_ident[EI_VERSION] != EV_CURRENT ||
602 hdr->e_version != EV_CURRENT ||
603 hdr->e_machine != ELF_TARG_MACH ||
604 hdr->e_phentsize != sizeof(Elf_Phdr))
605 break;
606 phlen = hdr->e_phnum * sizeof(Elf_Phdr);
607 if (ef_read_entry(ef, hdr->e_phoff, phlen,
608 (void **)&ef->ef_ph) != 0)
609 break;
610 phdr = ef->ef_ph;
611 phlimit = phdr + hdr->e_phnum;
612 nsegs = 0;
613 phdyn = NULL;
614 while (phdr < phlimit) {
615 if (verbose > 1)
616 ef_print_phdr(phdr);
617 switch (phdr->p_type) {
618 case PT_LOAD:
619 if (nsegs < MAXSEGS)
620 ef->ef_segs[nsegs] = phdr;
621 nsegs++;
622 break;
623 case PT_PHDR:
624 break;
625 case PT_DYNAMIC:
626 phdyn = phdr;
627 break;
628 }
629 phdr++;
630 }
631 if (verbose > 1)
632 printf("\n");
633 if (phdyn == NULL) {
634 warnx("Skipping %s: not dynamically-linked",
635 filename);
636 break;
637 } else if (nsegs > MAXSEGS) {
638 warnx("%s: too many segments", filename);
639 break;
640 }
641 ef->ef_nsegs = nsegs;
642 if (ef_read_entry(ef, phdyn->p_offset,
643 phdyn->p_filesz, (void **)&ef->ef_dyn) != 0) {
644 printf("ef_read_entry failed\n");
645 break;
646 }
647 error = ef_parse_dynamic(ef);
648 if (error != 0)
649 break;
650 if (hdr->e_type == ET_DYN) {
651 ef->ef_type = EFT_KLD;
652 error = 0;
653 } else if (hdr->e_type == ET_EXEC) {
654 ef->ef_type = EFT_KERNEL;
655 error = 0;
656 } else
657 break;
658 } while(0);
659 if (error != 0)
660 ef_close(ef);
661 return (error);
662 }
663
664 static int
ef_close(elf_file_t ef)665 ef_close(elf_file_t ef)
666 {
667
668 close(ef->ef_fd);
669 if (ef->ef_name)
670 free(ef->ef_name);
671 ef->ef_efile->ef_ops = NULL;
672 ef->ef_efile->ef_ef = NULL;
673 free(ef);
674 return (0);
675 }
676