xref: /netbsd-src/external/bsd/libproc/dist/proc_sym.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*-
2  * Copyright (c) 2010 The FreeBSD Foundation
3  * Copyright (c) 2008 John Birrell (jb@freebsd.org)
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Rui Paulo under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 #ifdef __FBSDID
33 __FBSDID("$FreeBSD: head/lib/libproc/proc_sym.c 279946 2015-03-13 04:26:48Z stas $");
34 #else
35 __RCSID("$NetBSD: proc_sym.c,v 1.4 2017/06/15 23:44:58 kamil Exp $");
36 #endif
37 
38 #include <sys/types.h>
39 #ifndef NO_CTF
40 #include <sys/ctf.h>
41 #include <sys/ctf_api.h>
42 #endif
43 #if defined(__FreeBSD__)
44 #include <sys/user.h>
45 #endif
46 #include <sys/sysctl.h>
47 
48 #include <assert.h>
49 #include <err.h>
50 #include <fcntl.h>
51 #include <libgen.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56 #ifndef NO_CTF
57 #include <libctf.h>
58 #endif
59 #include <util.h>
60 
61 #include "_libproc.h"
62 
63 #define DBG_PATH_FMT "/usr/libdata/debug/%s.debug"
64 
65 #ifdef NO_CTF
66 typedef struct ctf_file ctf_file_t;
67 #endif
68 
69 #ifndef NO_CXA_DEMANGLE
70 extern char *__cxa_demangle(const char *, char *, size_t *, int *);
71 #endif /* NO_CXA_DEMANGLE */
72 
73 static void	proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
74 
75 #ifdef __NetBSD__
76 static char *basename_r(const char *path, char *buf)
77 {
78 	// We "know" this works.
79 	if (path[0])
80 		strlcpy(buf, strrchr(path, '/') + 1, PATH_MAX);
81 	else
82 		buf[0] = '\0';
83 	return buf;
84 }
85 #endif
86 
87 static void
88 demangle(const char *symbol, char *buf, size_t len)
89 {
90 #ifndef NO_CXA_DEMANGLE
91 	char *dembuf;
92 
93 	if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) {
94 		dembuf = __cxa_demangle(symbol, NULL, NULL, NULL);
95 		if (!dembuf)
96 			goto fail;
97 		strlcpy(buf, dembuf, len);
98 		free(dembuf);
99 		return;
100 	}
101 fail:
102 #endif /* NO_CXA_DEMANGLE */
103 	strlcpy(buf, symbol, len);
104 }
105 
106 static int
107 find_dbg_obj(const char *path)
108 {
109 	int fd;
110 	char dbg_path[PATH_MAX];
111 
112 	snprintf(dbg_path, sizeof(dbg_path), DBG_PATH_FMT, path);
113 	fd = open(dbg_path, O_RDONLY);
114 	if (fd >= 0)
115 		return (fd);
116 	else
117 		return (open(path, O_RDONLY));
118 }
119 
120 static void
121 proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
122 {
123 	map->pr_vaddr = rdl->rdl_saddr;
124 	map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
125 	map->pr_offset = rdl->rdl_offset;
126 	map->pr_mflags = 0;
127 	if (rdl->rdl_prot & RD_RDL_R)
128 		map->pr_mflags |= MA_READ;
129 	if (rdl->rdl_prot & RD_RDL_W)
130 		map->pr_mflags |= MA_WRITE;
131 	if (rdl->rdl_prot & RD_RDL_X)
132 		map->pr_mflags |= MA_EXEC;
133 	strlcpy(map->pr_mapname, rdl->rdl_path,
134 	    sizeof(map->pr_mapname));
135 }
136 
137 char *
138 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
139     size_t objnamesz)
140 {
141 	size_t i;
142 	rd_loadobj_t *rdl;
143 
144 	for (i = 0; i < p->nobjs; i++) {
145 		rdl = &p->rdobjs[i];
146 		if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
147 			strlcpy(objname, rdl->rdl_path, objnamesz);
148 			return (objname);
149 		}
150 	}
151 	return (NULL);
152 }
153 
154 prmap_t *
155 proc_obj2map(struct proc_handle *p, const char *objname)
156 {
157 	size_t i;
158 	prmap_t *map;
159 	rd_loadobj_t *rdl;
160 	char path[MAXPATHLEN];
161 
162 	rdl = NULL;
163 	for (i = 0; i < p->nobjs; i++) {
164 		basename_r(p->rdobjs[i].rdl_path, path);
165 		if (strcmp(path, objname) == 0) {
166 			rdl = &p->rdobjs[i];
167 			break;
168 		}
169 	}
170 	if (rdl == NULL) {
171 		if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
172 			rdl = p->rdexec;
173 		else
174 			return (NULL);
175 	}
176 
177 	if ((map = malloc(sizeof(*map))) == NULL)
178 		return (NULL);
179 	proc_rdl2prmap(rdl, map);
180 	return (map);
181 }
182 
183 int
184 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd)
185 {
186 	size_t i;
187 	rd_loadobj_t *rdl;
188 	prmap_t map;
189 	char path[MAXPATHLEN];
190 	char last[MAXPATHLEN];
191 	int error;
192 
193 	if (p->nobjs == 0)
194 		return (-1);
195 
196 	error = 0;
197 	memset(last, 0, sizeof(last));
198 	for (i = 0; i < p->nobjs; i++) {
199 		rdl = &p->rdobjs[i];
200 		proc_rdl2prmap(rdl, &map);
201 		basename_r(rdl->rdl_path, path);
202 		/*
203 		 * We shouldn't call the callback twice with the same object.
204 		 * To do that we are assuming the fact that if there are
205 		 * repeated object names (i.e. different mappings for the
206 		 * same object) they occur next to each other.
207 		 */
208 		if (strcmp(path, last) == 0)
209 			continue;
210 		if ((error = (*func)(cd, &map, path)) != 0)
211 			break;
212 		strlcpy(last, path, sizeof(last));
213 	}
214 	return (error);
215 }
216 
217 prmap_t *
218 proc_addr2map(struct proc_handle *p, uintptr_t addr)
219 {
220 	size_t i, cnt, lastvn = 0;
221 	prmap_t *map;
222 	rd_loadobj_t *rdl;
223 	struct kinfo_vmentry *kves, *kve;
224 
225 	/*
226 	 * If we don't have a cache of listed objects, we need to query
227 	 * it ourselves.
228 	 */
229 	if (p->nobjs == 0) {
230 		if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL)
231 			return (NULL);
232 		for (i = 0; i < (size_t)cnt; i++) {
233 			kve = kves + i;
234 			if (kve->kve_type == KVME_TYPE_VNODE)
235 				lastvn = i;
236 			if (addr >= kve->kve_start && addr < kve->kve_end) {
237 				if ((map = malloc(sizeof(*map))) == NULL) {
238 					free(kves);
239 					return (NULL);
240 				}
241 				map->pr_vaddr = kve->kve_start;
242 				map->pr_size = kve->kve_end - kve->kve_start;
243 				map->pr_offset = kve->kve_offset;
244 				map->pr_mflags = 0;
245 				if (kve->kve_protection & KVME_PROT_READ)
246 					map->pr_mflags |= MA_READ;
247 				if (kve->kve_protection & KVME_PROT_WRITE)
248 					map->pr_mflags |= MA_WRITE;
249 				if (kve->kve_protection & KVME_PROT_EXEC)
250 					map->pr_mflags |= MA_EXEC;
251 				if (kve->kve_flags & KVME_FLAG_COW)
252 					map->pr_mflags |= MA_COW;
253 				if (kve->kve_flags & KVME_FLAG_NEEDS_COPY)
254 					map->pr_mflags |= MA_NEEDS_COPY;
255 				if (kve->kve_flags & KVME_FLAG_NOCOREDUMP)
256 					map->pr_mflags |= MA_NOCOREDUMP;
257 				strlcpy(map->pr_mapname, kves[lastvn].kve_path,
258 				    sizeof(map->pr_mapname));
259 				free(kves);
260 				return (map);
261 			}
262 		}
263 		free(kves);
264 		return (NULL);
265 	}
266 
267 	for (i = 0; i < p->nobjs; i++) {
268 		rdl = &p->rdobjs[i];
269 		if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
270 			if ((map = malloc(sizeof(*map))) == NULL)
271 				return (NULL);
272 			proc_rdl2prmap(rdl, map);
273 			return (map);
274 		}
275 	}
276 	return (NULL);
277 }
278 
279 /*
280  * Look up the symbol at addr, returning a copy of the symbol and its name.
281  */
282 static int
283 lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
284     const char **name, GElf_Sym *symcopy)
285 {
286 	GElf_Sym sym;
287 	Elf_Data *data;
288 	const char *s;
289 	uint64_t rsym;
290 	int i;
291 
292 	if ((data = elf_getdata(scn, NULL)) == NULL) {
293 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
294 		return (1);
295 	}
296 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
297 		rsym = off + sym.st_value;
298 		if (addr >= rsym && addr < rsym + sym.st_size) {
299 			s = elf_strptr(e, stridx, sym.st_name);
300 			if (s != NULL) {
301 				*name = s;
302 				memcpy(symcopy, &sym, sizeof(*symcopy));
303 				/*
304 				 * DTrace expects the st_value to contain
305 				 * only the address relative to the start of
306 				 * the function.
307 				 */
308 				symcopy->st_value = rsym;
309 				return (0);
310 			}
311 		}
312 	}
313 	return (1);
314 }
315 
316 int
317 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
318     size_t namesz, GElf_Sym *symcopy)
319 {
320 	GElf_Ehdr ehdr;
321 	GElf_Shdr shdr;
322 	Elf *e;
323 	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
324 	prmap_t *map;
325 	const char *s;
326 	uintptr_t off;
327 	u_long symtabstridx = 0, dynsymstridx = 0;
328 	int fd, error = -1;
329 
330 	if ((map = proc_addr2map(p, addr)) == NULL)
331 		return (-1);
332 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
333 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
334 		goto err0;
335 	}
336 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
337 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
338 		goto err1;
339 	}
340 	if (gelf_getehdr(e, &ehdr) == NULL) {
341 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
342 		goto err2;
343 	}
344 
345 	/*
346 	 * Find the index of the STRTAB and SYMTAB sections to locate
347 	 * symbol names.
348 	 */
349 	scn = NULL;
350 	while ((scn = elf_nextscn(e, scn)) != NULL) {
351 		gelf_getshdr(scn, &shdr);
352 		switch (shdr.sh_type) {
353 		case SHT_SYMTAB:
354 			symtabscn = scn;
355 			symtabstridx = shdr.sh_link;
356 			break;
357 		case SHT_DYNSYM:
358 			dynsymscn = scn;
359 			dynsymstridx = shdr.sh_link;
360 			break;
361 		}
362 	}
363 
364 	off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
365 
366 	/*
367 	 * First look up the symbol in the dynsymtab, and fall back to the
368 	 * symtab if the lookup fails.
369 	 */
370 	if (dynsymscn) {
371 		error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
372 		if (error == 0)
373 			goto out;
374 	}
375 
376 	error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
377 	if (error != 0)
378 		goto err2;
379 
380 out:
381 	demangle(s, name, namesz);
382 err2:
383 	elf_end(e);
384 err1:
385 	close(fd);
386 err0:
387 	free(map);
388 	return (error);
389 }
390 
391 prmap_t *
392 proc_name2map(struct proc_handle *p, const char *name)
393 {
394 	size_t i, cnt;
395 	prmap_t *map = NULL;
396 	char tmppath[MAXPATHLEN];
397 	struct kinfo_vmentry *kves, *kve;
398 	rd_loadobj_t *rdl;
399 
400 	/*
401 	 * If we haven't iterated over the list of loaded objects,
402 	 * librtld_db isn't yet initialized and it's very likely
403 	 * that librtld_db called us. We need to do the heavy
404 	 * lifting here to find the symbol librtld_db is looking for.
405 	 */
406 	if (p->nobjs == 0) {
407 		if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
408 			return (NULL);
409 		for (i = 0; i < (size_t)cnt; i++) {
410 			kve = kves + i;
411 			basename_r(kve->kve_path, tmppath);
412 			if (strcmp(tmppath, name) == 0) {
413 				map = proc_addr2map(p, kve->kve_start);
414 				break;
415 			}
416 		}
417 		free(kves);
418 	} else
419 		for (i = 0; i < p->nobjs; i++) {
420 			rdl = &p->rdobjs[i];
421 			basename_r(rdl->rdl_path, tmppath);
422 			if (strcmp(tmppath, name) == 0) {
423 				if ((map = malloc(sizeof(*map))) == NULL)
424 					return (NULL);
425 				proc_rdl2prmap(rdl, map);
426 				break;
427 			}
428 		}
429 
430 	if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
431 		map = proc_addr2map(p, p->rdexec->rdl_saddr);
432 
433 	return (map);
434 }
435 
436 /*
437  * Look up the symbol with the given name and return a copy of it.
438  */
439 static int
440 lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
441     GElf_Sym *symcopy, prsyminfo_t *si)
442 {
443 	GElf_Sym sym;
444 	Elf_Data *data;
445 	char *s;
446 	int i;
447 
448 	if ((data = elf_getdata(scn, NULL)) == NULL) {
449 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
450 		return (1);
451 	}
452 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
453 		s = elf_strptr(e, stridx, sym.st_name);
454 		if (s != NULL && strcmp(s, symbol) == 0) {
455 			memcpy(symcopy, &sym, sizeof(*symcopy));
456 			if (si != NULL)
457 				si->prs_id = i;
458 			return (0);
459 		}
460 	}
461 	return (1);
462 }
463 
464 int
465 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
466     GElf_Sym *symcopy, prsyminfo_t *si)
467 {
468 	Elf *e;
469 	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
470 	GElf_Shdr shdr;
471 	GElf_Ehdr ehdr;
472 	prmap_t *map;
473 	uintptr_t off;
474 	u_long symtabstridx = 0, dynsymstridx = 0;
475 	int fd, error = -1;
476 
477 	if ((map = proc_name2map(p, object)) == NULL) {
478 		DPRINTFX("ERROR: couldn't find object %s", object);
479 		goto err0;
480 	}
481 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
482 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
483 		goto err0;
484 	}
485 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
486 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
487 		goto err1;
488 	}
489 	if (gelf_getehdr(e, &ehdr) == NULL) {
490 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
491 		goto err2;
492 	}
493 	/*
494 	 * Find the index of the STRTAB and SYMTAB sections to locate
495 	 * symbol names.
496 	 */
497 	scn = NULL;
498 	while ((scn = elf_nextscn(e, scn)) != NULL) {
499 		gelf_getshdr(scn, &shdr);
500 		switch (shdr.sh_type) {
501 		case SHT_SYMTAB:
502 			symtabscn = scn;
503 			symtabstridx = shdr.sh_link;
504 			break;
505 		case SHT_DYNSYM:
506 			dynsymscn = scn;
507 			dynsymstridx = shdr.sh_link;
508 			break;
509 		}
510 	}
511 
512 	/*
513 	 * First look up the symbol in the dynsymtab, and fall back to the
514 	 * symtab if the lookup fails.
515 	 */
516 	if (dynsymscn) {
517 		error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si);
518 		if (error == 0)
519 			goto out;
520 	}
521 
522 	error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si);
523 	if (error == 0)
524 		goto out;
525 
526 out:
527 	off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
528 	symcopy->st_value += off;
529 
530 err2:
531 	elf_end(e);
532 err1:
533 	close(fd);
534 err0:
535 	free(map);
536 
537 	return (error);
538 }
539 
540 ctf_file_t *
541 proc_name2ctf(struct proc_handle *p, const char *name)
542 {
543 #ifndef NO_CTF
544 	ctf_file_t *ctf;
545 	prmap_t *map;
546 	int error;
547 
548 	if ((map = proc_name2map(p, name)) == NULL)
549 		return (NULL);
550 
551 	ctf = ctf_open(map->pr_mapname, &error);
552 	free(map);
553 	return (ctf);
554 #else
555 	(void)p;
556 	(void)name;
557 	return (NULL);
558 #endif
559 }
560 
561 int
562 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
563     int mask, proc_sym_f *func, void *cd)
564 {
565 	Elf *e;
566 	int i, fd;
567 	prmap_t *map;
568 	Elf_Scn *scn, *foundscn = NULL;
569 	Elf_Data *data;
570 	GElf_Ehdr ehdr;
571 	GElf_Shdr shdr;
572 	GElf_Sym sym;
573 	unsigned long stridx = -1;
574 	char *s;
575 	int error = -1;
576 
577 	if ((map = proc_name2map(p, object)) == NULL)
578 		return (-1);
579 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
580 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
581 		goto err0;
582 	}
583 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
584 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
585 		goto err1;
586 	}
587 	if (gelf_getehdr(e, &ehdr) == NULL) {
588 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
589 		goto err2;
590 	}
591 	/*
592 	 * Find the section we are looking for.
593 	 */
594 	scn = NULL;
595 	while ((scn = elf_nextscn(e, scn)) != NULL) {
596 		gelf_getshdr(scn, &shdr);
597 		if (which == PR_SYMTAB &&
598 		    shdr.sh_type == SHT_SYMTAB) {
599 			foundscn = scn;
600 			break;
601 		} else if (which == PR_DYNSYM &&
602 		    shdr.sh_type == SHT_DYNSYM) {
603 			foundscn = scn;
604 			break;
605 		}
606 	}
607 	if (!foundscn)
608 		return (-1);
609 	stridx = shdr.sh_link;
610 	if ((data = elf_getdata(foundscn, NULL)) == NULL) {
611 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
612 		goto err2;
613 	}
614 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
615 		if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
616 		    (mask & BIND_LOCAL) == 0)
617 			continue;
618 		if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL &&
619 		    (mask & BIND_GLOBAL) == 0)
620 			continue;
621 		if (GELF_ST_BIND(sym.st_info) == STB_WEAK &&
622 		    (mask & BIND_WEAK) == 0)
623 			continue;
624 		if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE &&
625 		    (mask & TYPE_NOTYPE) == 0)
626 			continue;
627 		if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT &&
628 		    (mask & TYPE_OBJECT) == 0)
629 			continue;
630 		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC &&
631 		    (mask & TYPE_FUNC) == 0)
632 			continue;
633 		if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
634 		    (mask & TYPE_SECTION) == 0)
635 			continue;
636 		if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
637 		    (mask & TYPE_FILE) == 0)
638 			continue;
639 		s = elf_strptr(e, stridx, sym.st_name);
640 		if (ehdr.e_type != ET_EXEC)
641 			sym.st_value += map->pr_vaddr;
642 		if ((error = (*func)(cd, &sym, s)) != 0)
643 			goto err2;
644 	}
645 	error = 0;
646 err2:
647 	elf_end(e);
648 err1:
649 	close(fd);
650 err0:
651 	free(map);
652 	return (error);
653 }
654