1 /* $NetBSD: libdwarf_elf_init.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 Kai Wang 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 * 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 26 * SUCH DAMAGE. 27 */ 28 29 #include "_libdwarf.h" 30 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 "); 33 34 static const char *debug_name[] = { 35 ".debug_abbrev", 36 ".debug_aranges", 37 ".debug_frame", 38 ".debug_info", 39 ".debug_types", 40 ".debug_line", 41 ".debug_pubnames", 42 ".eh_frame", 43 ".debug_macinfo", 44 ".debug_str", 45 ".debug_loc", 46 ".debug_pubtypes", 47 ".debug_ranges", 48 ".debug_static_func", 49 ".debug_static_vars", 50 ".debug_typenames", 51 ".debug_weaknames", 52 NULL 53 }; 54 55 static void 56 _dwarf_elf_apply_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data, 57 Elf_Data *symtab_data, int endian) 58 { 59 Dwarf_Unsigned type; 60 GElf_Rela rela; 61 GElf_Sym sym; 62 size_t symndx; 63 uint64_t offset; 64 int size, j; 65 66 j = 0; 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); 70 71 if (gelf_getsym(symtab_data, symndx, &sym) == NULL) 72 continue; 73 74 offset = rela.r_offset; 75 size = _dwarf_get_reloc_size(dbg, type); 76 77 if (endian == ELFDATA2MSB) 78 _dwarf_write_msb(buf, &offset, rela.r_addend, size); 79 else 80 _dwarf_write_lsb(buf, &offset, rela.r_addend, size); 81 } 82 } 83 84 static int 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) 87 { 88 GElf_Ehdr eh; 89 GElf_Shdr sh; 90 Elf_Scn *scn; 91 Elf_Data *rel; 92 int elferr; 93 94 if (symtab == 0 || symtab_data == NULL) 95 return (DW_DLE_NONE); 96 97 if (gelf_getehdr(elf, &eh) == NULL) { 98 DWARF_SET_ELF_ERROR(dbg, error); 99 return (DW_DLE_ELF); 100 } 101 102 scn = NULL; 103 (void) elf_errno(); 104 while ((scn = elf_nextscn(elf, scn)) != NULL) { 105 if (gelf_getshdr(scn, &sh) == NULL) { 106 DWARF_SET_ELF_ERROR(dbg, error); 107 return (DW_DLE_ELF); 108 } 109 110 if (sh.sh_type != SHT_RELA || sh.sh_size == 0) 111 continue; 112 113 if (sh.sh_info == shndx && sh.sh_link == symtab) { 114 if ((rel = elf_getdata(scn, NULL)) == NULL) { 115 elferr = elf_errno(); 116 if (elferr != 0) { 117 _DWARF_SET_ERROR(NULL, error, 118 DW_DLE_ELF, elferr); 119 return (DW_DLE_ELF); 120 } else 121 return (DW_DLE_NONE); 122 } 123 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); 128 } 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]); 133 134 return (DW_DLE_NONE); 135 } 136 } 137 elferr = elf_errno(); 138 if (elferr != 0) { 139 DWARF_SET_ELF_ERROR(dbg, error); 140 return (DW_DLE_ELF); 141 } 142 143 return (DW_DLE_NONE); 144 } 145 146 int 147 _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error) 148 { 149 Dwarf_Obj_Access_Interface *iface; 150 Dwarf_Elf_Object *e; 151 const char *name; 152 GElf_Shdr sh; 153 Elf_Scn *scn; 154 Elf_Data *symtab_data; 155 size_t symtab_ndx; 156 int elferr, i, j, n, ret; 157 158 ret = DW_DLE_NONE; 159 160 if ((iface = calloc(1, sizeof(*iface))) == NULL) { 161 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 162 return (DW_DLE_MEMORY); 163 } 164 165 if ((e = calloc(1, sizeof(*e))) == NULL) { 166 free(iface); 167 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 168 return (DW_DLE_MEMORY); 169 } 170 171 e->eo_elf = elf; 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; 178 179 iface->object = e; 180 iface->methods = &e->eo_methods; 181 182 dbg->dbg_iface = iface; 183 184 if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) { 185 DWARF_SET_ELF_ERROR(dbg, error); 186 ret = DW_DLE_ELF; 187 goto fail_cleanup; 188 } 189 190 dbg->dbg_machine = e->eo_ehdr.e_machine; 191 192 if (!elf_getshstrndx(elf, &e->eo_strndx)) { 193 DWARF_SET_ELF_ERROR(dbg, error); 194 ret = DW_DLE_ELF; 195 goto fail_cleanup; 196 } 197 198 n = 0; 199 symtab_ndx = 0; 200 symtab_data = NULL; 201 scn = NULL; 202 (void) elf_errno(); 203 while ((scn = elf_nextscn(elf, scn)) != NULL) { 204 if (gelf_getshdr(scn, &sh) == NULL) { 205 DWARF_SET_ELF_ERROR(dbg, error); 206 ret = DW_DLE_ELF; 207 goto fail_cleanup; 208 } 209 210 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 211 NULL) { 212 DWARF_SET_ELF_ERROR(dbg, error); 213 ret = DW_DLE_ELF; 214 goto fail_cleanup; 215 } 216 217 if (!strcmp(name, ".symtab")) { 218 symtab_ndx = elf_ndxscn(scn); 219 if ((symtab_data = elf_getdata(scn, NULL)) == NULL) { 220 elferr = elf_errno(); 221 if (elferr != 0) { 222 _DWARF_SET_ERROR(NULL, error, 223 DW_DLE_ELF, elferr); 224 ret = DW_DLE_ELF; 225 goto fail_cleanup; 226 } 227 } 228 continue; 229 } 230 231 for (i = 0; debug_name[i] != NULL; i++) { 232 if (!strcmp(name, debug_name[i])) 233 n++; 234 } 235 } 236 elferr = elf_errno(); 237 if (elferr != 0) { 238 DWARF_SET_ELF_ERROR(dbg, error); 239 return (DW_DLE_ELF); 240 } 241 242 e->eo_seccnt = n; 243 244 if (n == 0) 245 return (DW_DLE_NONE); 246 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); 250 ret = DW_DLE_MEMORY; 251 goto fail_cleanup; 252 } 253 254 scn = NULL; 255 j = 0; 256 while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) { 257 if (gelf_getshdr(scn, &sh) == NULL) { 258 DWARF_SET_ELF_ERROR(dbg, error); 259 ret = DW_DLE_ELF; 260 goto fail_cleanup; 261 } 262 263 memcpy(&e->eo_shdr[j], &sh, sizeof(sh)); 264 265 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 266 NULL) { 267 DWARF_SET_ELF_ERROR(dbg, error); 268 ret = DW_DLE_ELF; 269 goto fail_cleanup; 270 } 271 272 for (i = 0; debug_name[i] != NULL; i++) { 273 if (strcmp(name, debug_name[i])) 274 continue; 275 276 (void) elf_errno(); 277 if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) == 278 NULL) { 279 elferr = elf_errno(); 280 if (elferr != 0) { 281 _DWARF_SET_ERROR(dbg, error, 282 DW_DLE_ELF, elferr); 283 ret = DW_DLE_ELF; 284 goto fail_cleanup; 285 } 286 } 287 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) 292 goto fail_cleanup; 293 } 294 295 j++; 296 } 297 } 298 299 assert(j == n); 300 301 return (DW_DLE_NONE); 302 303 fail_cleanup: 304 305 _dwarf_elf_deinit(dbg); 306 307 return (ret); 308 } 309 310 void 311 _dwarf_elf_deinit(Dwarf_Debug dbg) 312 { 313 Dwarf_Obj_Access_Interface *iface; 314 Dwarf_Elf_Object *e; 315 int i; 316 317 iface = dbg->dbg_iface; 318 assert(iface != NULL); 319 320 e = iface->object; 321 assert(e != NULL); 322 323 if (e->eo_data) { 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); 327 } 328 free(e->eo_data); 329 } 330 if (e->eo_shdr) 331 free(e->eo_shdr); 332 333 free(e); 334 free(iface); 335 336 dbg->dbg_iface = NULL; 337 } 338