1 /*- 2 * Copyright (c) 2009 Kai Wang 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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: libdwarf_elf_init.c 3475 2016-05-18 18:11:26Z emaste $"); 30 31 static const char *debug_name[] = { 32 ".debug_abbrev", 33 ".debug_aranges", 34 ".debug_frame", 35 ".debug_info", 36 ".debug_types", 37 ".debug_line", 38 ".debug_pubnames", 39 ".eh_frame", 40 ".debug_macinfo", 41 ".debug_str", 42 ".debug_loc", 43 ".debug_pubtypes", 44 ".debug_ranges", 45 ".debug_static_func", 46 ".debug_static_vars", 47 ".debug_typenames", 48 ".debug_weaknames", 49 NULL 50 }; 51 52 static void 53 _dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize, 54 Elf_Data *rel_data, Elf_Data *symtab_data, int endian) 55 { 56 Dwarf_Unsigned type; 57 GElf_Rel rel; 58 GElf_Sym sym; 59 size_t symndx; 60 uint64_t offset; 61 uint64_t addend; 62 int size, j; 63 64 j = 0; 65 while (gelf_getrel(rel_data, j++, &rel) != NULL) { 66 symndx = GELF_R_SYM(rel.r_info); 67 type = GELF_R_TYPE(rel.r_info); 68 69 if (gelf_getsym(symtab_data, symndx, &sym) == NULL) 70 continue; 71 72 size = _dwarf_get_reloc_size(dbg, type); 73 if (size == 0) 74 continue; /* Unknown or non-absolute relocation. */ 75 76 offset = rel.r_offset; 77 if (offset + size >= bufsize) 78 continue; 79 80 if (endian == ELFDATA2MSB) 81 addend = _dwarf_read_msb(buf, &offset, size); 82 else 83 addend = _dwarf_read_lsb(buf, &offset, size); 84 85 offset = rel.r_offset; 86 if (endian == ELFDATA2MSB) 87 _dwarf_write_msb(buf, &offset, sym.st_value + addend, 88 size); 89 else 90 _dwarf_write_lsb(buf, &offset, sym.st_value + addend, 91 size); 92 } 93 } 94 95 static void 96 _dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize, 97 Elf_Data *rel_data, Elf_Data *symtab_data, int endian) 98 { 99 Dwarf_Unsigned type; 100 GElf_Rela rela; 101 GElf_Sym sym; 102 size_t symndx; 103 uint64_t offset; 104 int size, j; 105 106 j = 0; 107 while (gelf_getrela(rel_data, j++, &rela) != NULL) { 108 symndx = GELF_R_SYM(rela.r_info); 109 type = GELF_R_TYPE(rela.r_info); 110 111 if (gelf_getsym(symtab_data, symndx, &sym) == NULL) 112 continue; 113 114 offset = rela.r_offset; 115 size = _dwarf_get_reloc_size(dbg, type); 116 if (size == 0) 117 continue; /* Unknown or non-absolute relocation. */ 118 if (offset + size >= bufsize) 119 continue; 120 121 if (endian == ELFDATA2MSB) 122 _dwarf_write_msb(buf, &offset, 123 sym.st_value + rela.r_addend, size); 124 else 125 _dwarf_write_lsb(buf, &offset, 126 sym.st_value + rela.r_addend, size); 127 } 128 } 129 130 static int 131 _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx, 132 size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error) 133 { 134 GElf_Ehdr eh; 135 GElf_Shdr sh; 136 Elf_Scn *scn; 137 Elf_Data *rel; 138 int elferr; 139 140 if (symtab == 0 || symtab_data == NULL) 141 return (DW_DLE_NONE); 142 143 if (gelf_getehdr(elf, &eh) == NULL) { 144 DWARF_SET_ELF_ERROR(dbg, error); 145 return (DW_DLE_ELF); 146 } 147 148 scn = NULL; 149 (void) elf_errno(); 150 while ((scn = elf_nextscn(elf, scn)) != NULL) { 151 if (gelf_getshdr(scn, &sh) == NULL) { 152 DWARF_SET_ELF_ERROR(dbg, error); 153 return (DW_DLE_ELF); 154 } 155 156 if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) || 157 sh.sh_size == 0) 158 continue; 159 160 if (sh.sh_info == shndx && sh.sh_link == symtab) { 161 if ((rel = elf_getdata(scn, NULL)) == NULL) { 162 elferr = elf_errno(); 163 if (elferr != 0) { 164 _DWARF_SET_ERROR(NULL, error, 165 DW_DLE_ELF, elferr); 166 return (DW_DLE_ELF); 167 } else 168 return (DW_DLE_NONE); 169 } 170 171 ed->ed_alloc = malloc(ed->ed_data->d_size); 172 if (ed->ed_alloc == NULL) { 173 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 174 return (DW_DLE_MEMORY); 175 } 176 memcpy(ed->ed_alloc, ed->ed_data->d_buf, 177 ed->ed_data->d_size); 178 if (sh.sh_type == SHT_REL) 179 _dwarf_elf_apply_rel_reloc(dbg, 180 ed->ed_alloc, ed->ed_data->d_size, 181 rel, symtab_data, eh.e_ident[EI_DATA]); 182 else 183 _dwarf_elf_apply_rela_reloc(dbg, 184 ed->ed_alloc, ed->ed_data->d_size, 185 rel, symtab_data, eh.e_ident[EI_DATA]); 186 187 return (DW_DLE_NONE); 188 } 189 } 190 elferr = elf_errno(); 191 if (elferr != 0) { 192 DWARF_SET_ELF_ERROR(dbg, error); 193 return (DW_DLE_ELF); 194 } 195 196 return (DW_DLE_NONE); 197 } 198 199 int 200 _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error) 201 { 202 Dwarf_Obj_Access_Interface *iface; 203 Dwarf_Elf_Object *e; 204 const char *name; 205 GElf_Shdr sh; 206 Elf_Scn *scn; 207 Elf_Data *symtab_data; 208 size_t symtab_ndx; 209 int elferr, i, j, n, ret; 210 211 ret = DW_DLE_NONE; 212 213 if ((iface = calloc(1, sizeof(*iface))) == NULL) { 214 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 215 return (DW_DLE_MEMORY); 216 } 217 218 if ((e = calloc(1, sizeof(*e))) == NULL) { 219 free(iface); 220 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 221 return (DW_DLE_MEMORY); 222 } 223 224 e->eo_elf = elf; 225 e->eo_methods.get_section_info = _dwarf_elf_get_section_info; 226 e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order; 227 e->eo_methods.get_length_size = _dwarf_elf_get_length_size; 228 e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size; 229 e->eo_methods.get_section_count = _dwarf_elf_get_section_count; 230 e->eo_methods.load_section = _dwarf_elf_load_section; 231 232 iface->object = e; 233 iface->methods = &e->eo_methods; 234 235 dbg->dbg_iface = iface; 236 237 if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) { 238 DWARF_SET_ELF_ERROR(dbg, error); 239 ret = DW_DLE_ELF; 240 goto fail_cleanup; 241 } 242 243 dbg->dbg_machine = e->eo_ehdr.e_machine; 244 245 if (!elf_getshstrndx(elf, &e->eo_strndx)) { 246 DWARF_SET_ELF_ERROR(dbg, error); 247 ret = DW_DLE_ELF; 248 goto fail_cleanup; 249 } 250 251 n = 0; 252 symtab_ndx = 0; 253 symtab_data = NULL; 254 scn = NULL; 255 (void) elf_errno(); 256 while ((scn = elf_nextscn(elf, scn)) != NULL) { 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 if (sh.sh_type == SHT_NOBITS) 264 continue; 265 266 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 267 NULL) { 268 DWARF_SET_ELF_ERROR(dbg, error); 269 ret = DW_DLE_ELF; 270 goto fail_cleanup; 271 } 272 273 if (!strcmp(name, ".symtab")) { 274 symtab_ndx = elf_ndxscn(scn); 275 if ((symtab_data = elf_getdata(scn, NULL)) == NULL) { 276 elferr = elf_errno(); 277 if (elferr != 0) { 278 _DWARF_SET_ERROR(NULL, error, 279 DW_DLE_ELF, elferr); 280 ret = DW_DLE_ELF; 281 goto fail_cleanup; 282 } 283 } 284 continue; 285 } 286 287 for (i = 0; debug_name[i] != NULL; i++) { 288 if (!strcmp(name, debug_name[i])) 289 n++; 290 } 291 } 292 elferr = elf_errno(); 293 if (elferr != 0) { 294 DWARF_SET_ELF_ERROR(dbg, error); 295 return (DW_DLE_ELF); 296 } 297 298 e->eo_seccnt = n; 299 300 if (n == 0) 301 return (DW_DLE_NONE); 302 303 if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL || 304 (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) { 305 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 306 ret = DW_DLE_MEMORY; 307 goto fail_cleanup; 308 } 309 310 scn = NULL; 311 j = 0; 312 while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) { 313 if (gelf_getshdr(scn, &sh) == NULL) { 314 DWARF_SET_ELF_ERROR(dbg, error); 315 ret = DW_DLE_ELF; 316 goto fail_cleanup; 317 } 318 319 if (sh.sh_type == SHT_NOBITS) 320 continue; 321 322 memcpy(&e->eo_shdr[j], &sh, sizeof(sh)); 323 324 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 325 NULL) { 326 DWARF_SET_ELF_ERROR(dbg, error); 327 ret = DW_DLE_ELF; 328 goto fail_cleanup; 329 } 330 331 for (i = 0; debug_name[i] != NULL; i++) { 332 if (strcmp(name, debug_name[i])) 333 continue; 334 335 (void) elf_errno(); 336 if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) == 337 NULL) { 338 elferr = elf_errno(); 339 if (elferr != 0) { 340 _DWARF_SET_ERROR(dbg, error, 341 DW_DLE_ELF, elferr); 342 ret = DW_DLE_ELF; 343 goto fail_cleanup; 344 } 345 } 346 347 if (_libdwarf.applyreloc) { 348 if (_dwarf_elf_relocate(dbg, elf, 349 &e->eo_data[j], elf_ndxscn(scn), symtab_ndx, 350 symtab_data, error) != DW_DLE_NONE) 351 goto fail_cleanup; 352 } 353 354 j++; 355 } 356 } 357 358 assert(j == n); 359 360 return (DW_DLE_NONE); 361 362 fail_cleanup: 363 364 _dwarf_elf_deinit(dbg); 365 366 return (ret); 367 } 368 369 void 370 _dwarf_elf_deinit(Dwarf_Debug dbg) 371 { 372 Dwarf_Obj_Access_Interface *iface; 373 Dwarf_Elf_Object *e; 374 int i; 375 376 iface = dbg->dbg_iface; 377 assert(iface != NULL); 378 379 e = iface->object; 380 assert(e != NULL); 381 382 if (e->eo_data) { 383 for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) { 384 if (e->eo_data[i].ed_alloc) 385 free(e->eo_data[i].ed_alloc); 386 } 387 free(e->eo_data); 388 } 389 if (e->eo_shdr) 390 free(e->eo_shdr); 391 392 free(e); 393 free(iface); 394 395 dbg->dbg_iface = NULL; 396 } 397