]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/kldxref/ef.c
Remove spurious newline
[FreeBSD/FreeBSD.git] / usr.sbin / kldxref / ef.c
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 3
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }