xref: /freebsd-src/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c (revision c983ec6428ecfa362903cbdba1dc9f4303e2f28c)
12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2009 Kai Wang
32de3b87aSKai Wang  * All rights reserved.
42de3b87aSKai Wang  *
52de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
62de3b87aSKai Wang  * modification, are permitted provided that the following conditions
72de3b87aSKai Wang  * are met:
82de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
92de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
102de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
112de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
122de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
132de3b87aSKai Wang  *
142de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242de3b87aSKai Wang  * SUCH DAMAGE.
252de3b87aSKai Wang  */
262de3b87aSKai Wang 
272de3b87aSKai Wang #include "_libdwarf.h"
28dbf05458SMark Johnston #include <zlib.h>
292de3b87aSKai Wang 
30b6b6f9ccSEd Maste ELFTC_VCSID("$Id: libdwarf_elf_init.c 3475 2016-05-18 18:11:26Z emaste $");
312de3b87aSKai Wang 
322de3b87aSKai Wang static const char *debug_name[] = {
332de3b87aSKai Wang 	".debug_abbrev",
342de3b87aSKai Wang 	".debug_aranges",
352de3b87aSKai Wang 	".debug_frame",
362de3b87aSKai Wang 	".debug_info",
372de3b87aSKai Wang 	".debug_types",
382de3b87aSKai Wang 	".debug_line",
392de3b87aSKai Wang 	".debug_pubnames",
402de3b87aSKai Wang 	".eh_frame",
412de3b87aSKai Wang 	".debug_macinfo",
422de3b87aSKai Wang 	".debug_str",
432de3b87aSKai Wang 	".debug_loc",
442de3b87aSKai Wang 	".debug_pubtypes",
452de3b87aSKai Wang 	".debug_ranges",
462de3b87aSKai Wang 	".debug_static_func",
472de3b87aSKai Wang 	".debug_static_vars",
482de3b87aSKai Wang 	".debug_typenames",
492de3b87aSKai Wang 	".debug_weaknames",
502de3b87aSKai Wang 	NULL
512de3b87aSKai Wang };
522de3b87aSKai Wang 
532de3b87aSKai Wang static void
_dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg,void * buf,uint64_t bufsize,Elf_Data * rel_data,Elf_Data * symtab_data,int endian)54b6b6f9ccSEd Maste _dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize,
55b6b6f9ccSEd Maste     Elf_Data *rel_data, Elf_Data *symtab_data, int endian)
56d133198bSEd Maste {
57b6b6f9ccSEd Maste 	Dwarf_Unsigned type;
58d133198bSEd Maste 	GElf_Rel rel;
59b6b6f9ccSEd Maste 	GElf_Sym sym;
60b6b6f9ccSEd Maste 	size_t symndx;
61b6b6f9ccSEd Maste 	uint64_t offset;
62b6b6f9ccSEd Maste 	uint64_t addend;
63b6b6f9ccSEd Maste 	int size, j;
642de3b87aSKai Wang 
652de3b87aSKai Wang 	j = 0;
66b6b6f9ccSEd Maste 	while (gelf_getrel(rel_data, j++, &rel) != NULL) {
67b6b6f9ccSEd Maste 		symndx = GELF_R_SYM(rel.r_info);
68b6b6f9ccSEd Maste 		type = GELF_R_TYPE(rel.r_info);
69b6b6f9ccSEd Maste 
70b6b6f9ccSEd Maste 		if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
71b6b6f9ccSEd Maste 			continue;
72b6b6f9ccSEd Maste 
73b6b6f9ccSEd Maste 		size = _dwarf_get_reloc_size(dbg, type);
74b6b6f9ccSEd Maste 		if (size == 0)
75b6b6f9ccSEd Maste 			continue; /* Unknown or non-absolute relocation. */
76b6b6f9ccSEd Maste 
77b6b6f9ccSEd Maste 		offset = rel.r_offset;
78b6b6f9ccSEd Maste 		if (offset + size >= bufsize)
79b6b6f9ccSEd Maste 			continue;
80b6b6f9ccSEd Maste 
81b6b6f9ccSEd Maste 		if (endian == ELFDATA2MSB)
82b6b6f9ccSEd Maste 			addend = _dwarf_read_msb(buf, &offset, size);
83b6b6f9ccSEd Maste 		else
84b6b6f9ccSEd Maste 			addend = _dwarf_read_lsb(buf, &offset, size);
85b6b6f9ccSEd Maste 
86b6b6f9ccSEd Maste 		offset = rel.r_offset;
87b6b6f9ccSEd Maste 		if (endian == ELFDATA2MSB)
88b6b6f9ccSEd Maste 			_dwarf_write_msb(buf, &offset, sym.st_value + addend,
89b6b6f9ccSEd Maste 			    size);
90b6b6f9ccSEd Maste 		else
91b6b6f9ccSEd Maste 			_dwarf_write_lsb(buf, &offset, sym.st_value + addend,
92b6b6f9ccSEd Maste 			    size);
93b6b6f9ccSEd Maste 	}
942de3b87aSKai Wang }
95d133198bSEd Maste 
96d133198bSEd Maste static void
_dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg,void * buf,uint64_t bufsize,Elf_Data * rel_data,Elf_Data * symtab_data,int endian)97b6b6f9ccSEd Maste _dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize,
98b6b6f9ccSEd Maste     Elf_Data *rel_data, Elf_Data *symtab_data, int endian)
99d133198bSEd Maste {
100b6b6f9ccSEd Maste 	Dwarf_Unsigned type;
101d133198bSEd Maste 	GElf_Rela rela;
102b6b6f9ccSEd Maste 	GElf_Sym sym;
103b6b6f9ccSEd Maste 	size_t symndx;
104b6b6f9ccSEd Maste 	uint64_t offset;
105b6b6f9ccSEd Maste 	int size, j;
106d133198bSEd Maste 
107d133198bSEd Maste 	j = 0;
108b6b6f9ccSEd Maste 	while (gelf_getrela(rel_data, j++, &rela) != NULL) {
109b6b6f9ccSEd Maste 		symndx = GELF_R_SYM(rela.r_info);
110b6b6f9ccSEd Maste 		type = GELF_R_TYPE(rela.r_info);
111b6b6f9ccSEd Maste 
112b6b6f9ccSEd Maste 		if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
113b6b6f9ccSEd Maste 			continue;
114b6b6f9ccSEd Maste 
115b6b6f9ccSEd Maste 		offset = rela.r_offset;
116b6b6f9ccSEd Maste 		size = _dwarf_get_reloc_size(dbg, type);
117b6b6f9ccSEd Maste 		if (size == 0)
118b6b6f9ccSEd Maste 			continue; /* Unknown or non-absolute relocation. */
119b6b6f9ccSEd Maste 		if (offset + size >= bufsize)
120b6b6f9ccSEd Maste 			continue;
121b6b6f9ccSEd Maste 
122b6b6f9ccSEd Maste 		if (endian == ELFDATA2MSB)
123b6b6f9ccSEd Maste 			_dwarf_write_msb(buf, &offset,
124b6b6f9ccSEd Maste 			    sym.st_value + rela.r_addend, size);
125b6b6f9ccSEd Maste 		else
126b6b6f9ccSEd Maste 			_dwarf_write_lsb(buf, &offset,
127b6b6f9ccSEd Maste 			    sym.st_value + rela.r_addend, size);
128b6b6f9ccSEd Maste 	}
1292de3b87aSKai Wang }
1302de3b87aSKai Wang 
1312de3b87aSKai Wang static int
_dwarf_elf_relocate(Dwarf_Debug dbg,Elf * elf,Dwarf_Elf_Data * ed,size_t shndx,size_t symtab,Elf_Data * symtab_data,Dwarf_Error * error)1322de3b87aSKai Wang _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx,
1332de3b87aSKai Wang     size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error)
1342de3b87aSKai Wang {
1352de3b87aSKai Wang 	GElf_Ehdr eh;
1362de3b87aSKai Wang 	GElf_Shdr sh;
1372de3b87aSKai Wang 	Elf_Scn *scn;
1382de3b87aSKai Wang 	Elf_Data *rel;
1392de3b87aSKai Wang 	int elferr;
1402de3b87aSKai Wang 
1412de3b87aSKai Wang 	if (symtab == 0 || symtab_data == NULL)
1422de3b87aSKai Wang 		return (DW_DLE_NONE);
1432de3b87aSKai Wang 
1442de3b87aSKai Wang 	if (gelf_getehdr(elf, &eh) == NULL) {
1452de3b87aSKai Wang 		DWARF_SET_ELF_ERROR(dbg, error);
1462de3b87aSKai Wang 		return (DW_DLE_ELF);
1472de3b87aSKai Wang 	}
1482de3b87aSKai Wang 
1492de3b87aSKai Wang 	scn = NULL;
1502de3b87aSKai Wang 	(void) elf_errno();
1512de3b87aSKai Wang 	while ((scn = elf_nextscn(elf, scn)) != NULL) {
1522de3b87aSKai Wang 		if (gelf_getshdr(scn, &sh) == NULL) {
1532de3b87aSKai Wang 			DWARF_SET_ELF_ERROR(dbg, error);
1542de3b87aSKai Wang 			return (DW_DLE_ELF);
1552de3b87aSKai Wang 		}
1562de3b87aSKai Wang 
157d133198bSEd Maste 		if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) ||
158d133198bSEd Maste 		     sh.sh_size == 0)
1592de3b87aSKai Wang 			continue;
1602de3b87aSKai Wang 
1612de3b87aSKai Wang 		if (sh.sh_info == shndx && sh.sh_link == symtab) {
1622de3b87aSKai Wang 			if ((rel = elf_getdata(scn, NULL)) == NULL) {
1632de3b87aSKai Wang 				elferr = elf_errno();
1642de3b87aSKai Wang 				if (elferr != 0) {
1652de3b87aSKai Wang 					_DWARF_SET_ERROR(NULL, error,
1662de3b87aSKai Wang 					    DW_DLE_ELF, elferr);
1672de3b87aSKai Wang 					return (DW_DLE_ELF);
1682de3b87aSKai Wang 				} else
1692de3b87aSKai Wang 					return (DW_DLE_NONE);
1702de3b87aSKai Wang 			}
1712de3b87aSKai Wang 
172dbf05458SMark Johnston 			/*
173dbf05458SMark Johnston 			 * A copy may already have been created if the section
174dbf05458SMark Johnston 			 * is compressed.
175dbf05458SMark Johnston 			 */
1762de3b87aSKai Wang 			if (ed->ed_alloc == NULL) {
177dbf05458SMark Johnston 				ed->ed_alloc = malloc(ed->ed_size);
178dbf05458SMark Johnston 				if (ed->ed_alloc == NULL) {
179dbf05458SMark Johnston 					DWARF_SET_ERROR(dbg, error,
180dbf05458SMark Johnston 					    DW_DLE_MEMORY);
1812de3b87aSKai Wang 					return (DW_DLE_MEMORY);
1822de3b87aSKai Wang 				}
1832de3b87aSKai Wang 				memcpy(ed->ed_alloc, ed->ed_data->d_buf,
184dbf05458SMark Johnston 				    ed->ed_size);
185dbf05458SMark Johnston 			}
186d133198bSEd Maste 			if (sh.sh_type == SHT_REL)
187b6b6f9ccSEd Maste 				_dwarf_elf_apply_rel_reloc(dbg,
188dbf05458SMark Johnston 				    ed->ed_alloc, ed->ed_size,
189d133198bSEd Maste 				    rel, symtab_data, eh.e_ident[EI_DATA]);
190d133198bSEd Maste 			else
191b6b6f9ccSEd Maste 				_dwarf_elf_apply_rela_reloc(dbg,
192dbf05458SMark Johnston 				    ed->ed_alloc, ed->ed_size, rel, symtab_data,
193dbf05458SMark Johnston 				    eh.e_ident[EI_DATA]);
1942de3b87aSKai Wang 
1952de3b87aSKai Wang 			return (DW_DLE_NONE);
1962de3b87aSKai Wang 		}
1972de3b87aSKai Wang 	}
1982de3b87aSKai Wang 	elferr = elf_errno();
1992de3b87aSKai Wang 	if (elferr != 0) {
2002de3b87aSKai Wang 		DWARF_SET_ELF_ERROR(dbg, error);
2012de3b87aSKai Wang 		return (DW_DLE_ELF);
2022de3b87aSKai Wang 	}
2032de3b87aSKai Wang 
2042de3b87aSKai Wang 	return (DW_DLE_NONE);
2052de3b87aSKai Wang }
2062de3b87aSKai Wang 
207dbf05458SMark Johnston static int
_dwarf_elf_decompress(Dwarf_Debug dbg,Dwarf_Elf_Object * e,Elf_Scn * scn,Dwarf_Elf_Data * ed,GElf_Shdr * shdr,Dwarf_Error * error)208dbf05458SMark Johnston _dwarf_elf_decompress(Dwarf_Debug dbg, Dwarf_Elf_Object *e, Elf_Scn *scn,
209dbf05458SMark Johnston     Dwarf_Elf_Data *ed, GElf_Shdr *shdr, Dwarf_Error *error)
210dbf05458SMark Johnston {
211dbf05458SMark Johnston 	GElf_Chdr chdr;
212dbf05458SMark Johnston 	size_t hsize;
213dbf05458SMark Johnston 	unsigned long csize;
214dbf05458SMark Johnston 
215dbf05458SMark Johnston 	if (gelf_getchdr(scn, &chdr) == NULL) {
216dbf05458SMark Johnston 		DWARF_SET_ELF_ERROR(dbg, error);
217dbf05458SMark Johnston 		return (DW_DLE_ELF);
218dbf05458SMark Johnston 	}
219dbf05458SMark Johnston 
220dbf05458SMark Johnston 	if (chdr.ch_type != ELFCOMPRESS_ZLIB) {
221dbf05458SMark Johnston 		DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
222dbf05458SMark Johnston 		return (DW_DLE_COMPRESSION);
223dbf05458SMark Johnston 	}
224dbf05458SMark Johnston 
225dbf05458SMark Johnston 	if ((ed->ed_alloc = malloc(chdr.ch_size)) == NULL) {
226dbf05458SMark Johnston 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
227dbf05458SMark Johnston 		return (DW_DLE_MEMORY);
228dbf05458SMark Johnston 	}
229dbf05458SMark Johnston 
230dbf05458SMark Johnston 	csize = chdr.ch_size;
231dbf05458SMark Johnston 	hsize = e->eo_ehdr.e_ident[EI_CLASS] == ELFCLASS64 ?
232dbf05458SMark Johnston 	    sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
233dbf05458SMark Johnston 	if (uncompress(ed->ed_alloc, &csize, (char *)ed->ed_data->d_buf + hsize,
234dbf05458SMark Johnston 	    ed->ed_data->d_size - hsize) != Z_OK) {
235dbf05458SMark Johnston 		DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
236dbf05458SMark Johnston 		return (DW_DLE_COMPRESSION);
237dbf05458SMark Johnston 	}
238dbf05458SMark Johnston 	/* Sanity check. */
239dbf05458SMark Johnston 	if (csize != chdr.ch_size) {
240dbf05458SMark Johnston 		DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
241dbf05458SMark Johnston 		return (DW_DLE_COMPRESSION);
242dbf05458SMark Johnston 	}
243dbf05458SMark Johnston 
244dbf05458SMark Johnston 	ed->ed_size = chdr.ch_size;
245dbf05458SMark Johnston 	shdr->sh_size = chdr.ch_size;
246dbf05458SMark Johnston 	shdr->sh_addralign = chdr.ch_addralign;
247dbf05458SMark Johnston 
248dbf05458SMark Johnston 	return (DW_DLE_NONE);
249dbf05458SMark Johnston }
250dbf05458SMark Johnston 
2512de3b87aSKai Wang int
_dwarf_elf_init(Dwarf_Debug dbg,Elf * elf,Dwarf_Error * error)2522de3b87aSKai Wang _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
2532de3b87aSKai Wang {
2542de3b87aSKai Wang 	Dwarf_Obj_Access_Interface *iface;
255dbf05458SMark Johnston 	Dwarf_Elf_Data *ed;
2562de3b87aSKai Wang 	Dwarf_Elf_Object *e;
2572de3b87aSKai Wang 	const char *name;
258dbf05458SMark Johnston 	GElf_Shdr *es, sh;
2592de3b87aSKai Wang 	Elf_Scn *scn;
2602de3b87aSKai Wang 	Elf_Data *symtab_data;
2612de3b87aSKai Wang 	size_t symtab_ndx;
2622de3b87aSKai Wang 	int elferr, i, j, n, ret;
2632de3b87aSKai Wang 
2642de3b87aSKai Wang 	ret = DW_DLE_NONE;
2652de3b87aSKai Wang 
2662de3b87aSKai Wang 	if ((iface = calloc(1, sizeof(*iface))) == NULL) {
2672de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
2682de3b87aSKai Wang 		return (DW_DLE_MEMORY);
2692de3b87aSKai Wang 	}
2702de3b87aSKai Wang 
2712de3b87aSKai Wang 	if ((e = calloc(1, sizeof(*e))) == NULL) {
2722de3b87aSKai Wang 		free(iface);
2732de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
2742de3b87aSKai Wang 		return (DW_DLE_MEMORY);
2752de3b87aSKai Wang 	}
2762de3b87aSKai Wang 
2772de3b87aSKai Wang 	e->eo_elf = elf;
2782de3b87aSKai Wang 	e->eo_methods.get_section_info = _dwarf_elf_get_section_info;
2792de3b87aSKai Wang 	e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order;
2802de3b87aSKai Wang 	e->eo_methods.get_length_size = _dwarf_elf_get_length_size;
2812de3b87aSKai Wang 	e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size;
2822de3b87aSKai Wang 	e->eo_methods.get_section_count = _dwarf_elf_get_section_count;
2832de3b87aSKai Wang 	e->eo_methods.load_section = _dwarf_elf_load_section;
2842de3b87aSKai Wang 
2852de3b87aSKai Wang 	iface->object = e;
2862de3b87aSKai Wang 	iface->methods = &e->eo_methods;
2872de3b87aSKai Wang 
2882de3b87aSKai Wang 	dbg->dbg_iface = iface;
2892de3b87aSKai Wang 
2902de3b87aSKai Wang 	if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) {
2912de3b87aSKai Wang 		DWARF_SET_ELF_ERROR(dbg, error);
2922de3b87aSKai Wang 		ret = DW_DLE_ELF;
2932de3b87aSKai Wang 		goto fail_cleanup;
2942de3b87aSKai Wang 	}
2952de3b87aSKai Wang 
2962de3b87aSKai Wang 	dbg->dbg_machine = e->eo_ehdr.e_machine;
2972de3b87aSKai Wang 
2982de3b87aSKai Wang 	if (!elf_getshstrndx(elf, &e->eo_strndx)) {
2992de3b87aSKai Wang 		DWARF_SET_ELF_ERROR(dbg, error);
3002de3b87aSKai Wang 		ret = DW_DLE_ELF;
3012de3b87aSKai Wang 		goto fail_cleanup;
3022de3b87aSKai Wang 	}
3032de3b87aSKai Wang 
3042de3b87aSKai Wang 	n = 0;
3052de3b87aSKai Wang 	symtab_ndx = 0;
3062de3b87aSKai Wang 	symtab_data = NULL;
3072de3b87aSKai Wang 	scn = NULL;
3082de3b87aSKai Wang 	(void) elf_errno();
3092de3b87aSKai Wang 	while ((scn = elf_nextscn(elf, scn)) != NULL) {
3102de3b87aSKai Wang 		if (gelf_getshdr(scn, &sh) == NULL) {
3112de3b87aSKai Wang 			DWARF_SET_ELF_ERROR(dbg, error);
3122de3b87aSKai Wang 			ret = DW_DLE_ELF;
3132de3b87aSKai Wang 			goto fail_cleanup;
3142de3b87aSKai Wang 		}
3152de3b87aSKai Wang 
316f690eff9SMark Johnston 		if (sh.sh_type == SHT_NOBITS)
317f690eff9SMark Johnston 			continue;
318f690eff9SMark Johnston 
3192de3b87aSKai Wang 		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
3202de3b87aSKai Wang 		    NULL) {
3212de3b87aSKai Wang 			DWARF_SET_ELF_ERROR(dbg, error);
3222de3b87aSKai Wang 			ret = DW_DLE_ELF;
3232de3b87aSKai Wang 			goto fail_cleanup;
3242de3b87aSKai Wang 		}
3252de3b87aSKai Wang 
3262de3b87aSKai Wang 		if (!strcmp(name, ".symtab")) {
3272de3b87aSKai Wang 			symtab_ndx = elf_ndxscn(scn);
3282de3b87aSKai Wang 			if ((symtab_data = elf_getdata(scn, NULL)) == NULL) {
3292de3b87aSKai Wang 				elferr = elf_errno();
3302de3b87aSKai Wang 				if (elferr != 0) {
3312de3b87aSKai Wang 					_DWARF_SET_ERROR(NULL, error,
3322de3b87aSKai Wang 					    DW_DLE_ELF, elferr);
3332de3b87aSKai Wang 					ret = DW_DLE_ELF;
3342de3b87aSKai Wang 					goto fail_cleanup;
3352de3b87aSKai Wang 				}
3362de3b87aSKai Wang 			}
3372de3b87aSKai Wang 			continue;
3382de3b87aSKai Wang 		}
3392de3b87aSKai Wang 
3402de3b87aSKai Wang 		for (i = 0; debug_name[i] != NULL; i++) {
3412de3b87aSKai Wang 			if (!strcmp(name, debug_name[i]))
3422de3b87aSKai Wang 				n++;
3432de3b87aSKai Wang 		}
3442de3b87aSKai Wang 	}
3452de3b87aSKai Wang 	elferr = elf_errno();
3462de3b87aSKai Wang 	if (elferr != 0) {
3472de3b87aSKai Wang 		DWARF_SET_ELF_ERROR(dbg, error);
3482de3b87aSKai Wang 		return (DW_DLE_ELF);
3492de3b87aSKai Wang 	}
3502de3b87aSKai Wang 
3512de3b87aSKai Wang 	e->eo_seccnt = n;
3522de3b87aSKai Wang 
3532de3b87aSKai Wang 	if (n == 0)
3542de3b87aSKai Wang 		return (DW_DLE_NONE);
3552de3b87aSKai Wang 
3562de3b87aSKai Wang 	if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL ||
3572de3b87aSKai Wang 	    (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) {
3582de3b87aSKai Wang 		DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
3592de3b87aSKai Wang 		ret = DW_DLE_MEMORY;
3602de3b87aSKai Wang 		goto fail_cleanup;
3612de3b87aSKai Wang 	}
3622de3b87aSKai Wang 
3632de3b87aSKai Wang 	scn = NULL;
3642de3b87aSKai Wang 	j = 0;
3652de3b87aSKai Wang 	while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) {
3662de3b87aSKai Wang 		if (gelf_getshdr(scn, &sh) == NULL) {
3672de3b87aSKai Wang 			DWARF_SET_ELF_ERROR(dbg, error);
3682de3b87aSKai Wang 			ret = DW_DLE_ELF;
3692de3b87aSKai Wang 			goto fail_cleanup;
3702de3b87aSKai Wang 		}
3712de3b87aSKai Wang 
372f690eff9SMark Johnston 		if (sh.sh_type == SHT_NOBITS)
373f690eff9SMark Johnston 			continue;
374f690eff9SMark Johnston 
3752de3b87aSKai Wang 		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
3762de3b87aSKai Wang 		    NULL) {
3772de3b87aSKai Wang 			DWARF_SET_ELF_ERROR(dbg, error);
3782de3b87aSKai Wang 			ret = DW_DLE_ELF;
3792de3b87aSKai Wang 			goto fail_cleanup;
3802de3b87aSKai Wang 		}
3812de3b87aSKai Wang 
382dbf05458SMark Johnston 		ed = &e->eo_data[j];
383dbf05458SMark Johnston 		es = &e->eo_shdr[j];
384dbf05458SMark Johnston 		memcpy(es, &sh, sizeof(sh));
3852de3b87aSKai Wang 		for (i = 0; debug_name[i] != NULL; i++) {
3862de3b87aSKai Wang 			if (strcmp(name, debug_name[i]))
3872de3b87aSKai Wang 				continue;
3882de3b87aSKai Wang 
3892de3b87aSKai Wang 			(void) elf_errno();
390dbf05458SMark Johnston 			if ((ed->ed_data = elf_getdata(scn, NULL)) == NULL) {
3912de3b87aSKai Wang 				elferr = elf_errno();
3922de3b87aSKai Wang 				if (elferr != 0) {
3932de3b87aSKai Wang 					_DWARF_SET_ERROR(dbg, error,
3942de3b87aSKai Wang 					    DW_DLE_ELF, elferr);
3952de3b87aSKai Wang 					ret = DW_DLE_ELF;
3962de3b87aSKai Wang 					goto fail_cleanup;
3972de3b87aSKai Wang 				}
3982de3b87aSKai Wang 			}
3992de3b87aSKai Wang 
400dbf05458SMark Johnston 			if ((sh.sh_flags & SHF_COMPRESSED) != 0) {
401*c983ec64SMark Johnston 				if ((ret = _dwarf_elf_decompress(dbg, e, scn,
402*c983ec64SMark Johnston 				    ed, es, error)) != DW_DLE_NONE)
403dbf05458SMark Johnston 					goto fail_cleanup;
404dbf05458SMark Johnston 			} else {
405dbf05458SMark Johnston 				ed->ed_size = ed->ed_data->d_size;
406dbf05458SMark Johnston 			}
407dbf05458SMark Johnston 
408d133198bSEd Maste 			if (_libdwarf.applyreloc) {
409*c983ec64SMark Johnston 				if ((ret = _dwarf_elf_relocate(dbg, elf,
4102de3b87aSKai Wang 				    &e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
411*c983ec64SMark Johnston 				    symtab_data, error)) != DW_DLE_NONE)
4122de3b87aSKai Wang 					goto fail_cleanup;
4132de3b87aSKai Wang 			}
4142de3b87aSKai Wang 
4152de3b87aSKai Wang 			j++;
4162de3b87aSKai Wang 		}
4172de3b87aSKai Wang 	}
4182de3b87aSKai Wang 
4192de3b87aSKai Wang 	assert(j == n);
4202de3b87aSKai Wang 
4212de3b87aSKai Wang 	return (DW_DLE_NONE);
4222de3b87aSKai Wang 
4232de3b87aSKai Wang fail_cleanup:
4242de3b87aSKai Wang 
4252de3b87aSKai Wang 	_dwarf_elf_deinit(dbg);
4262de3b87aSKai Wang 
4272de3b87aSKai Wang 	return (ret);
4282de3b87aSKai Wang }
4292de3b87aSKai Wang 
4302de3b87aSKai Wang void
_dwarf_elf_deinit(Dwarf_Debug dbg)4312de3b87aSKai Wang _dwarf_elf_deinit(Dwarf_Debug dbg)
4322de3b87aSKai Wang {
4332de3b87aSKai Wang 	Dwarf_Obj_Access_Interface *iface;
4342de3b87aSKai Wang 	Dwarf_Elf_Object *e;
4352de3b87aSKai Wang 	int i;
4362de3b87aSKai Wang 
4372de3b87aSKai Wang 	iface = dbg->dbg_iface;
4382de3b87aSKai Wang 	assert(iface != NULL);
4392de3b87aSKai Wang 
4402de3b87aSKai Wang 	e = iface->object;
4412de3b87aSKai Wang 	assert(e != NULL);
4422de3b87aSKai Wang 
4432de3b87aSKai Wang 	if (e->eo_data) {
4442de3b87aSKai Wang 		for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) {
4452de3b87aSKai Wang 			if (e->eo_data[i].ed_alloc)
4462de3b87aSKai Wang 				free(e->eo_data[i].ed_alloc);
4472de3b87aSKai Wang 		}
4482de3b87aSKai Wang 		free(e->eo_data);
4492de3b87aSKai Wang 	}
4502de3b87aSKai Wang 	if (e->eo_shdr)
4512de3b87aSKai Wang 		free(e->eo_shdr);
4522de3b87aSKai Wang 
4532de3b87aSKai Wang 	free(e);
4542de3b87aSKai Wang 	free(iface);
4552de3b87aSKai Wang 
4562de3b87aSKai Wang 	dbg->dbg_iface = NULL;
4572de3b87aSKai Wang }
458