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 ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 264 NULL) { 265 DWARF_SET_ELF_ERROR(dbg, error); 266 ret = DW_DLE_ELF; 267 goto fail_cleanup; 268 } 269 270 if (!strcmp(name, ".symtab")) { 271 symtab_ndx = elf_ndxscn(scn); 272 if ((symtab_data = elf_getdata(scn, NULL)) == NULL) { 273 elferr = elf_errno(); 274 if (elferr != 0) { 275 _DWARF_SET_ERROR(NULL, error, 276 DW_DLE_ELF, elferr); 277 ret = DW_DLE_ELF; 278 goto fail_cleanup; 279 } 280 } 281 continue; 282 } 283 284 for (i = 0; debug_name[i] != NULL; i++) { 285 if (!strcmp(name, debug_name[i])) 286 n++; 287 } 288 } 289 elferr = elf_errno(); 290 if (elferr != 0) { 291 DWARF_SET_ELF_ERROR(dbg, error); 292 return (DW_DLE_ELF); 293 } 294 295 e->eo_seccnt = n; 296 297 if (n == 0) 298 return (DW_DLE_NONE); 299 300 if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL || 301 (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) { 302 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 303 ret = DW_DLE_MEMORY; 304 goto fail_cleanup; 305 } 306 307 scn = NULL; 308 j = 0; 309 while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) { 310 if (gelf_getshdr(scn, &sh) == NULL) { 311 DWARF_SET_ELF_ERROR(dbg, error); 312 ret = DW_DLE_ELF; 313 goto fail_cleanup; 314 } 315 316 memcpy(&e->eo_shdr[j], &sh, sizeof(sh)); 317 318 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 319 NULL) { 320 DWARF_SET_ELF_ERROR(dbg, error); 321 ret = DW_DLE_ELF; 322 goto fail_cleanup; 323 } 324 325 for (i = 0; debug_name[i] != NULL; i++) { 326 if (strcmp(name, debug_name[i])) 327 continue; 328 329 (void) elf_errno(); 330 if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) == 331 NULL) { 332 elferr = elf_errno(); 333 if (elferr != 0) { 334 _DWARF_SET_ERROR(dbg, error, 335 DW_DLE_ELF, elferr); 336 ret = DW_DLE_ELF; 337 goto fail_cleanup; 338 } 339 } 340 341 if (_libdwarf.applyreloc) { 342 if (_dwarf_elf_relocate(dbg, elf, 343 &e->eo_data[j], elf_ndxscn(scn), symtab_ndx, 344 symtab_data, error) != DW_DLE_NONE) 345 goto fail_cleanup; 346 } 347 348 j++; 349 } 350 } 351 352 assert(j == n); 353 354 return (DW_DLE_NONE); 355 356 fail_cleanup: 357 358 _dwarf_elf_deinit(dbg); 359 360 return (ret); 361 } 362 363 void 364 _dwarf_elf_deinit(Dwarf_Debug dbg) 365 { 366 Dwarf_Obj_Access_Interface *iface; 367 Dwarf_Elf_Object *e; 368 int i; 369 370 iface = dbg->dbg_iface; 371 assert(iface != NULL); 372 373 e = iface->object; 374 assert(e != NULL); 375 376 if (e->eo_data) { 377 for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) { 378 if (e->eo_data[i].ed_alloc) 379 free(e->eo_data[i].ed_alloc); 380 } 381 free(e->eo_data); 382 } 383 if (e->eo_shdr) 384 free(e->eo_shdr); 385 386 free(e); 387 free(iface); 388 389 dbg->dbg_iface = NULL; 390 } 391