1 /* $NetBSD: libdwarf_elf_init.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2009 Kai Wang
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include "_libdwarf.h"
31 __RCSID("$NetBSD: libdwarf_elf_init.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
32 ELFTC_VCSID("Id: libdwarf_elf_init.c 2972 2013-12-23 06:46:04Z kaiwang27 ");
34 static const char *debug_name
[] = {
56 _dwarf_elf_apply_reloc(Dwarf_Debug dbg
, void *buf
, Elf_Data
*rel_data
,
57 Elf_Data
*symtab_data
, int endian
)
67 while (gelf_getrela(rel_data
, j
++, &rela
) != NULL
) {
68 symndx
= GELF_R_SYM(rela
.r_info
);
69 type
= GELF_R_TYPE(rela
.r_info
);
71 if (gelf_getsym(symtab_data
, symndx
, &sym
) == NULL
)
74 offset
= rela
.r_offset
;
75 size
= _dwarf_get_reloc_size(dbg
, type
);
77 if (endian
== ELFDATA2MSB
)
78 _dwarf_write_msb(buf
, &offset
, rela
.r_addend
, size
);
80 _dwarf_write_lsb(buf
, &offset
, rela
.r_addend
, size
);
85 _dwarf_elf_relocate(Dwarf_Debug dbg
, Elf
*elf
, Dwarf_Elf_Data
*ed
, size_t shndx
,
86 size_t symtab
, Elf_Data
*symtab_data
, Dwarf_Error
*error
)
94 if (symtab
== 0 || symtab_data
== NULL
)
97 if (gelf_getehdr(elf
, &eh
) == NULL
) {
98 DWARF_SET_ELF_ERROR(dbg
, error
);
104 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
105 if (gelf_getshdr(scn
, &sh
) == NULL
) {
106 DWARF_SET_ELF_ERROR(dbg
, error
);
110 if (sh
.sh_type
!= SHT_RELA
|| sh
.sh_size
== 0)
113 if (sh
.sh_info
== shndx
&& sh
.sh_link
== symtab
) {
114 if ((rel
= elf_getdata(scn
, NULL
)) == NULL
) {
115 elferr
= elf_errno();
117 _DWARF_SET_ERROR(NULL
, error
,
121 return (DW_DLE_NONE
);
124 ed
->ed_alloc
= malloc(ed
->ed_data
->d_size
);
125 if (ed
->ed_alloc
== NULL
) {
126 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
127 return (DW_DLE_MEMORY
);
129 memcpy(ed
->ed_alloc
, ed
->ed_data
->d_buf
,
130 ed
->ed_data
->d_size
);
131 _dwarf_elf_apply_reloc(dbg
, ed
->ed_alloc
, rel
,
132 symtab_data
, eh
.e_ident
[EI_DATA
]);
134 return (DW_DLE_NONE
);
137 elferr
= elf_errno();
139 DWARF_SET_ELF_ERROR(dbg
, error
);
143 return (DW_DLE_NONE
);
147 _dwarf_elf_init(Dwarf_Debug dbg
, Elf
*elf
, Dwarf_Error
*error
)
149 Dwarf_Obj_Access_Interface
*iface
;
154 Elf_Data
*symtab_data
;
156 int elferr
, i
, j
, n
, ret
;
160 if ((iface
= calloc(1, sizeof(*iface
))) == NULL
) {
161 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
162 return (DW_DLE_MEMORY
);
165 if ((e
= calloc(1, sizeof(*e
))) == NULL
) {
167 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
168 return (DW_DLE_MEMORY
);
172 e
->eo_methods
.get_section_info
= _dwarf_elf_get_section_info
;
173 e
->eo_methods
.get_byte_order
= _dwarf_elf_get_byte_order
;
174 e
->eo_methods
.get_length_size
= _dwarf_elf_get_length_size
;
175 e
->eo_methods
.get_pointer_size
= _dwarf_elf_get_pointer_size
;
176 e
->eo_methods
.get_section_count
= _dwarf_elf_get_section_count
;
177 e
->eo_methods
.load_section
= _dwarf_elf_load_section
;
180 iface
->methods
= &e
->eo_methods
;
182 dbg
->dbg_iface
= iface
;
184 if (gelf_getehdr(elf
, &e
->eo_ehdr
) == NULL
) {
185 DWARF_SET_ELF_ERROR(dbg
, error
);
190 dbg
->dbg_machine
= e
->eo_ehdr
.e_machine
;
192 if (!elf_getshstrndx(elf
, &e
->eo_strndx
)) {
193 DWARF_SET_ELF_ERROR(dbg
, error
);
203 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
204 if (gelf_getshdr(scn
, &sh
) == NULL
) {
205 DWARF_SET_ELF_ERROR(dbg
, error
);
210 if ((name
= elf_strptr(elf
, e
->eo_strndx
, sh
.sh_name
)) ==
212 DWARF_SET_ELF_ERROR(dbg
, error
);
217 if (!strcmp(name
, ".symtab")) {
218 symtab_ndx
= elf_ndxscn(scn
);
219 if ((symtab_data
= elf_getdata(scn
, NULL
)) == NULL
) {
220 elferr
= elf_errno();
222 _DWARF_SET_ERROR(NULL
, error
,
231 for (i
= 0; debug_name
[i
] != NULL
; i
++) {
232 if (!strcmp(name
, debug_name
[i
]))
236 elferr
= elf_errno();
238 DWARF_SET_ELF_ERROR(dbg
, error
);
245 return (DW_DLE_NONE
);
247 if ((e
->eo_data
= calloc(n
, sizeof(Dwarf_Elf_Data
))) == NULL
||
248 (e
->eo_shdr
= calloc(n
, sizeof(GElf_Shdr
))) == NULL
) {
249 DWARF_SET_ERROR(NULL
, error
, DW_DLE_MEMORY
);
256 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
&& j
< n
) {
257 if (gelf_getshdr(scn
, &sh
) == NULL
) {
258 DWARF_SET_ELF_ERROR(dbg
, error
);
263 memcpy(&e
->eo_shdr
[j
], &sh
, sizeof(sh
));
265 if ((name
= elf_strptr(elf
, e
->eo_strndx
, sh
.sh_name
)) ==
267 DWARF_SET_ELF_ERROR(dbg
, error
);
272 for (i
= 0; debug_name
[i
] != NULL
; i
++) {
273 if (strcmp(name
, debug_name
[i
]))
277 if ((e
->eo_data
[j
].ed_data
= elf_getdata(scn
, NULL
)) ==
279 elferr
= elf_errno();
281 _DWARF_SET_ERROR(dbg
, error
,
288 if (_libdwarf
.applyrela
) {
289 if (_dwarf_elf_relocate(dbg
, elf
,
290 &e
->eo_data
[j
], elf_ndxscn(scn
), symtab_ndx
,
291 symtab_data
, error
) != DW_DLE_NONE
)
301 return (DW_DLE_NONE
);
305 _dwarf_elf_deinit(dbg
);
311 _dwarf_elf_deinit(Dwarf_Debug dbg
)
313 Dwarf_Obj_Access_Interface
*iface
;
317 iface
= dbg
->dbg_iface
;
318 assert(iface
!= NULL
);
324 for (i
= 0; (Dwarf_Unsigned
) i
< e
->eo_seccnt
; i
++) {
325 if (e
->eo_data
[i
].ed_alloc
)
326 free(e
->eo_data
[i
].ed_alloc
);
336 dbg
->dbg_iface
= NULL
;