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 #include <zlib.h> 29 30 ELFTC_VCSID("$Id: libdwarf_elf_init.c 3475 2016-05-18 18:11:26Z emaste $"); 31 32 static const char *debug_name[] = { 33 ".debug_abbrev", 34 ".debug_aranges", 35 ".debug_frame", 36 ".debug_info", 37 ".debug_types", 38 ".debug_line", 39 ".debug_pubnames", 40 ".eh_frame", 41 ".debug_macinfo", 42 ".debug_str", 43 ".debug_loc", 44 ".debug_pubtypes", 45 ".debug_ranges", 46 ".debug_static_func", 47 ".debug_static_vars", 48 ".debug_typenames", 49 ".debug_weaknames", 50 NULL 51 }; 52 53 static void 54 _dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize, 55 Elf_Data *rel_data, Elf_Data *symtab_data, int endian) 56 { 57 Dwarf_Unsigned type; 58 GElf_Rel rel; 59 GElf_Sym sym; 60 size_t symndx; 61 uint64_t offset; 62 uint64_t addend; 63 int size, j; 64 65 j = 0; 66 while (gelf_getrel(rel_data, j++, &rel) != NULL) { 67 symndx = GELF_R_SYM(rel.r_info); 68 type = GELF_R_TYPE(rel.r_info); 69 70 if (gelf_getsym(symtab_data, symndx, &sym) == NULL) 71 continue; 72 73 size = _dwarf_get_reloc_size(dbg, type); 74 if (size == 0) 75 continue; /* Unknown or non-absolute relocation. */ 76 77 offset = rel.r_offset; 78 if (offset + size >= bufsize) 79 continue; 80 81 if (endian == ELFDATA2MSB) 82 addend = _dwarf_read_msb(buf, &offset, size); 83 else 84 addend = _dwarf_read_lsb(buf, &offset, size); 85 86 offset = rel.r_offset; 87 if (endian == ELFDATA2MSB) 88 _dwarf_write_msb(buf, &offset, sym.st_value + addend, 89 size); 90 else 91 _dwarf_write_lsb(buf, &offset, sym.st_value + addend, 92 size); 93 } 94 } 95 96 static void 97 _dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize, 98 Elf_Data *rel_data, Elf_Data *symtab_data, int endian) 99 { 100 Dwarf_Unsigned type; 101 GElf_Rela rela; 102 GElf_Sym sym; 103 size_t symndx; 104 uint64_t offset; 105 int size, j; 106 107 j = 0; 108 while (gelf_getrela(rel_data, j++, &rela) != NULL) { 109 symndx = GELF_R_SYM(rela.r_info); 110 type = GELF_R_TYPE(rela.r_info); 111 112 if (gelf_getsym(symtab_data, symndx, &sym) == NULL) 113 continue; 114 115 offset = rela.r_offset; 116 size = _dwarf_get_reloc_size(dbg, type); 117 if (size == 0) 118 continue; /* Unknown or non-absolute relocation. */ 119 if (offset + size >= bufsize) 120 continue; 121 122 if (endian == ELFDATA2MSB) 123 _dwarf_write_msb(buf, &offset, 124 sym.st_value + rela.r_addend, size); 125 else 126 _dwarf_write_lsb(buf, &offset, 127 sym.st_value + rela.r_addend, size); 128 } 129 } 130 131 static int 132 _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx, 133 size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error) 134 { 135 GElf_Ehdr eh; 136 GElf_Shdr sh; 137 Elf_Scn *scn; 138 Elf_Data *rel; 139 int elferr; 140 141 if (symtab == 0 || symtab_data == NULL) 142 return (DW_DLE_NONE); 143 144 if (gelf_getehdr(elf, &eh) == NULL) { 145 DWARF_SET_ELF_ERROR(dbg, error); 146 return (DW_DLE_ELF); 147 } 148 149 scn = NULL; 150 (void) elf_errno(); 151 while ((scn = elf_nextscn(elf, scn)) != NULL) { 152 if (gelf_getshdr(scn, &sh) == NULL) { 153 DWARF_SET_ELF_ERROR(dbg, error); 154 return (DW_DLE_ELF); 155 } 156 157 if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) || 158 sh.sh_size == 0) 159 continue; 160 161 if (sh.sh_info == shndx && sh.sh_link == symtab) { 162 if ((rel = elf_getdata(scn, NULL)) == NULL) { 163 elferr = elf_errno(); 164 if (elferr != 0) { 165 _DWARF_SET_ERROR(NULL, error, 166 DW_DLE_ELF, elferr); 167 return (DW_DLE_ELF); 168 } else 169 return (DW_DLE_NONE); 170 } 171 172 /* 173 * A copy may already have been created if the section 174 * is compressed. 175 */ 176 if (ed->ed_alloc == NULL) { 177 ed->ed_alloc = malloc(ed->ed_size); 178 if (ed->ed_alloc == NULL) { 179 DWARF_SET_ERROR(dbg, error, 180 DW_DLE_MEMORY); 181 return (DW_DLE_MEMORY); 182 } 183 memcpy(ed->ed_alloc, ed->ed_data->d_buf, 184 ed->ed_size); 185 } 186 if (sh.sh_type == SHT_REL) 187 _dwarf_elf_apply_rel_reloc(dbg, 188 ed->ed_alloc, ed->ed_size, 189 rel, symtab_data, eh.e_ident[EI_DATA]); 190 else 191 _dwarf_elf_apply_rela_reloc(dbg, 192 ed->ed_alloc, ed->ed_size, rel, symtab_data, 193 eh.e_ident[EI_DATA]); 194 195 return (DW_DLE_NONE); 196 } 197 } 198 elferr = elf_errno(); 199 if (elferr != 0) { 200 DWARF_SET_ELF_ERROR(dbg, error); 201 return (DW_DLE_ELF); 202 } 203 204 return (DW_DLE_NONE); 205 } 206 207 static int 208 _dwarf_elf_decompress(Dwarf_Debug dbg, Dwarf_Elf_Object *e, Elf_Scn *scn, 209 Dwarf_Elf_Data *ed, GElf_Shdr *shdr, Dwarf_Error *error) 210 { 211 GElf_Chdr chdr; 212 size_t hsize; 213 unsigned long csize; 214 215 if (gelf_getchdr(scn, &chdr) == NULL) { 216 DWARF_SET_ELF_ERROR(dbg, error); 217 return (DW_DLE_ELF); 218 } 219 220 if (chdr.ch_type != ELFCOMPRESS_ZLIB) { 221 DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION); 222 return (DW_DLE_COMPRESSION); 223 } 224 225 if ((ed->ed_alloc = malloc(chdr.ch_size)) == NULL) { 226 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 227 return (DW_DLE_MEMORY); 228 } 229 230 csize = chdr.ch_size; 231 hsize = e->eo_ehdr.e_ident[EI_CLASS] == ELFCLASS64 ? 232 sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); 233 if (uncompress(ed->ed_alloc, &csize, (char *)ed->ed_data->d_buf + hsize, 234 ed->ed_data->d_size - hsize) != Z_OK) { 235 DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION); 236 return (DW_DLE_COMPRESSION); 237 } 238 /* Sanity check. */ 239 if (csize != chdr.ch_size) { 240 DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION); 241 return (DW_DLE_COMPRESSION); 242 } 243 244 ed->ed_size = chdr.ch_size; 245 shdr->sh_size = chdr.ch_size; 246 shdr->sh_addralign = chdr.ch_addralign; 247 248 return (DW_DLE_NONE); 249 } 250 251 int 252 _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error) 253 { 254 Dwarf_Obj_Access_Interface *iface; 255 Dwarf_Elf_Data *ed; 256 Dwarf_Elf_Object *e; 257 const char *name; 258 GElf_Shdr *es, sh; 259 Elf_Scn *scn; 260 Elf_Data *symtab_data; 261 size_t symtab_ndx; 262 int elferr, i, j, n, ret; 263 264 ret = DW_DLE_NONE; 265 266 if ((iface = calloc(1, sizeof(*iface))) == NULL) { 267 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 268 return (DW_DLE_MEMORY); 269 } 270 271 if ((e = calloc(1, sizeof(*e))) == NULL) { 272 free(iface); 273 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 274 return (DW_DLE_MEMORY); 275 } 276 277 e->eo_elf = elf; 278 e->eo_methods.get_section_info = _dwarf_elf_get_section_info; 279 e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order; 280 e->eo_methods.get_length_size = _dwarf_elf_get_length_size; 281 e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size; 282 e->eo_methods.get_section_count = _dwarf_elf_get_section_count; 283 e->eo_methods.load_section = _dwarf_elf_load_section; 284 285 iface->object = e; 286 iface->methods = &e->eo_methods; 287 288 dbg->dbg_iface = iface; 289 290 if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) { 291 DWARF_SET_ELF_ERROR(dbg, error); 292 ret = DW_DLE_ELF; 293 goto fail_cleanup; 294 } 295 296 dbg->dbg_machine = e->eo_ehdr.e_machine; 297 298 if (!elf_getshstrndx(elf, &e->eo_strndx)) { 299 DWARF_SET_ELF_ERROR(dbg, error); 300 ret = DW_DLE_ELF; 301 goto fail_cleanup; 302 } 303 304 n = 0; 305 symtab_ndx = 0; 306 symtab_data = NULL; 307 scn = NULL; 308 (void) elf_errno(); 309 while ((scn = elf_nextscn(elf, scn)) != NULL) { 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 if (sh.sh_type == SHT_NOBITS) 317 continue; 318 319 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 320 NULL) { 321 DWARF_SET_ELF_ERROR(dbg, error); 322 ret = DW_DLE_ELF; 323 goto fail_cleanup; 324 } 325 326 if (!strcmp(name, ".symtab")) { 327 symtab_ndx = elf_ndxscn(scn); 328 if ((symtab_data = elf_getdata(scn, NULL)) == NULL) { 329 elferr = elf_errno(); 330 if (elferr != 0) { 331 _DWARF_SET_ERROR(NULL, error, 332 DW_DLE_ELF, elferr); 333 ret = DW_DLE_ELF; 334 goto fail_cleanup; 335 } 336 } 337 continue; 338 } 339 340 for (i = 0; debug_name[i] != NULL; i++) { 341 if (!strcmp(name, debug_name[i])) 342 n++; 343 } 344 } 345 elferr = elf_errno(); 346 if (elferr != 0) { 347 DWARF_SET_ELF_ERROR(dbg, error); 348 return (DW_DLE_ELF); 349 } 350 351 e->eo_seccnt = n; 352 353 if (n == 0) 354 return (DW_DLE_NONE); 355 356 if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL || 357 (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) { 358 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 359 ret = DW_DLE_MEMORY; 360 goto fail_cleanup; 361 } 362 363 scn = NULL; 364 j = 0; 365 while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) { 366 if (gelf_getshdr(scn, &sh) == NULL) { 367 DWARF_SET_ELF_ERROR(dbg, error); 368 ret = DW_DLE_ELF; 369 goto fail_cleanup; 370 } 371 372 if (sh.sh_type == SHT_NOBITS) 373 continue; 374 375 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 376 NULL) { 377 DWARF_SET_ELF_ERROR(dbg, error); 378 ret = DW_DLE_ELF; 379 goto fail_cleanup; 380 } 381 382 ed = &e->eo_data[j]; 383 es = &e->eo_shdr[j]; 384 memcpy(es, &sh, sizeof(sh)); 385 for (i = 0; debug_name[i] != NULL; i++) { 386 if (strcmp(name, debug_name[i])) 387 continue; 388 389 (void) elf_errno(); 390 if ((ed->ed_data = elf_getdata(scn, NULL)) == NULL) { 391 elferr = elf_errno(); 392 if (elferr != 0) { 393 _DWARF_SET_ERROR(dbg, error, 394 DW_DLE_ELF, elferr); 395 ret = DW_DLE_ELF; 396 goto fail_cleanup; 397 } 398 } 399 400 if ((sh.sh_flags & SHF_COMPRESSED) != 0) { 401 if ((ret = _dwarf_elf_decompress(dbg, e, scn, 402 ed, es, error)) != DW_DLE_NONE) 403 goto fail_cleanup; 404 } else { 405 ed->ed_size = ed->ed_data->d_size; 406 } 407 408 if (_libdwarf.applyreloc) { 409 if ((ret = _dwarf_elf_relocate(dbg, elf, 410 &e->eo_data[j], elf_ndxscn(scn), symtab_ndx, 411 symtab_data, error)) != DW_DLE_NONE) 412 goto fail_cleanup; 413 } 414 415 j++; 416 } 417 } 418 419 assert(j == n); 420 421 return (DW_DLE_NONE); 422 423 fail_cleanup: 424 425 _dwarf_elf_deinit(dbg); 426 427 return (ret); 428 } 429 430 void 431 _dwarf_elf_deinit(Dwarf_Debug dbg) 432 { 433 Dwarf_Obj_Access_Interface *iface; 434 Dwarf_Elf_Object *e; 435 int i; 436 437 iface = dbg->dbg_iface; 438 assert(iface != NULL); 439 440 e = iface->object; 441 assert(e != NULL); 442 443 if (e->eo_data) { 444 for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) { 445 if (e->eo_data[i].ed_alloc) 446 free(e->eo_data[i].ed_alloc); 447 } 448 free(e->eo_data); 449 } 450 if (e->eo_shdr) 451 free(e->eo_shdr); 452 453 free(e); 454 free(iface); 455 456 dbg->dbg_iface = NULL; 457 } 458