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