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 3161 2015-02-15 21:43:36Z 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_write_reloc(Dwarf_Debug dbg, Elf_Data *symtab_data, int endian, 54 void *buf, uint64_t offset, GElf_Xword r_info, GElf_Sxword r_addend, 55 int is_rel) 56 { 57 GElf_Sym sym; 58 int size; 59 60 if (gelf_getsym(symtab_data, GELF_R_SYM(r_info), &sym) == NULL) 61 return; 62 if ((size = _dwarf_get_reloc_size(dbg, GELF_R_TYPE(r_info))) == 0) 63 return; /* Unknown or non-absolute relocation. */ 64 if (is_rel) { 65 uint64_t roffset = offset; 66 67 if (endian == ELFDATA2MSB) 68 r_addend = _dwarf_read_msb(buf, &roffset, size); 69 else 70 r_addend = _dwarf_read_lsb(buf, &roffset, size); 71 } 72 if (endian == ELFDATA2MSB) 73 _dwarf_write_msb(buf, &offset, sym.st_value + r_addend, size); 74 else 75 _dwarf_write_lsb(buf, &offset, sym.st_value + r_addend, size); 76 } 77 78 static void 79 _dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data, 80 Elf_Data *symtab_data, int endian) 81 { 82 GElf_Rel rel; 83 int j; 84 85 j = 0; 86 while (gelf_getrel(rel_data, j++, &rel) != NULL) 87 _dwarf_elf_write_reloc(dbg, symtab_data, endian, buf, 88 rel.r_offset, rel.r_info, 0, 1); 89 } 90 91 static void 92 _dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data, 93 Elf_Data *symtab_data, int endian) 94 { 95 GElf_Rela rela; 96 int j; 97 98 j = 0; 99 while (gelf_getrela(rel_data, j++, &rela) != NULL) 100 _dwarf_elf_write_reloc(dbg, symtab_data, endian, buf, 101 rela.r_offset, rela.r_info, rela.r_addend, 0); 102 } 103 104 static int 105 _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx, 106 size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error) 107 { 108 GElf_Ehdr eh; 109 GElf_Shdr sh; 110 Elf_Scn *scn; 111 Elf_Data *rel; 112 int elferr; 113 114 if (symtab == 0 || symtab_data == NULL) 115 return (DW_DLE_NONE); 116 117 if (gelf_getehdr(elf, &eh) == NULL) { 118 DWARF_SET_ELF_ERROR(dbg, error); 119 return (DW_DLE_ELF); 120 } 121 122 scn = NULL; 123 (void) elf_errno(); 124 while ((scn = elf_nextscn(elf, scn)) != NULL) { 125 if (gelf_getshdr(scn, &sh) == NULL) { 126 DWARF_SET_ELF_ERROR(dbg, error); 127 return (DW_DLE_ELF); 128 } 129 130 if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) || 131 sh.sh_size == 0) 132 continue; 133 134 if (sh.sh_info == shndx && sh.sh_link == symtab) { 135 if ((rel = elf_getdata(scn, NULL)) == NULL) { 136 elferr = elf_errno(); 137 if (elferr != 0) { 138 _DWARF_SET_ERROR(NULL, error, 139 DW_DLE_ELF, elferr); 140 return (DW_DLE_ELF); 141 } else 142 return (DW_DLE_NONE); 143 } 144 145 ed->ed_alloc = malloc(ed->ed_data->d_size); 146 if (ed->ed_alloc == NULL) { 147 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 148 return (DW_DLE_MEMORY); 149 } 150 memcpy(ed->ed_alloc, ed->ed_data->d_buf, 151 ed->ed_data->d_size); 152 if (sh.sh_type == SHT_REL) 153 _dwarf_elf_apply_rel_reloc(dbg, ed->ed_alloc, 154 rel, symtab_data, eh.e_ident[EI_DATA]); 155 else 156 _dwarf_elf_apply_rela_reloc(dbg, ed->ed_alloc, 157 rel, symtab_data, eh.e_ident[EI_DATA]); 158 159 return (DW_DLE_NONE); 160 } 161 } 162 elferr = elf_errno(); 163 if (elferr != 0) { 164 DWARF_SET_ELF_ERROR(dbg, error); 165 return (DW_DLE_ELF); 166 } 167 168 return (DW_DLE_NONE); 169 } 170 171 int 172 _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error) 173 { 174 Dwarf_Obj_Access_Interface *iface; 175 Dwarf_Elf_Object *e; 176 const char *name; 177 GElf_Shdr sh; 178 Elf_Scn *scn; 179 Elf_Data *symtab_data; 180 size_t symtab_ndx; 181 int elferr, i, j, n, ret; 182 183 ret = DW_DLE_NONE; 184 185 if ((iface = calloc(1, sizeof(*iface))) == NULL) { 186 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 187 return (DW_DLE_MEMORY); 188 } 189 190 if ((e = calloc(1, sizeof(*e))) == NULL) { 191 free(iface); 192 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 193 return (DW_DLE_MEMORY); 194 } 195 196 e->eo_elf = elf; 197 e->eo_methods.get_section_info = _dwarf_elf_get_section_info; 198 e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order; 199 e->eo_methods.get_length_size = _dwarf_elf_get_length_size; 200 e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size; 201 e->eo_methods.get_section_count = _dwarf_elf_get_section_count; 202 e->eo_methods.load_section = _dwarf_elf_load_section; 203 204 iface->object = e; 205 iface->methods = &e->eo_methods; 206 207 dbg->dbg_iface = iface; 208 209 if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) { 210 DWARF_SET_ELF_ERROR(dbg, error); 211 ret = DW_DLE_ELF; 212 goto fail_cleanup; 213 } 214 215 dbg->dbg_machine = e->eo_ehdr.e_machine; 216 217 if (!elf_getshstrndx(elf, &e->eo_strndx)) { 218 DWARF_SET_ELF_ERROR(dbg, error); 219 ret = DW_DLE_ELF; 220 goto fail_cleanup; 221 } 222 223 n = 0; 224 symtab_ndx = 0; 225 symtab_data = NULL; 226 scn = NULL; 227 (void) elf_errno(); 228 while ((scn = elf_nextscn(elf, scn)) != NULL) { 229 if (gelf_getshdr(scn, &sh) == NULL) { 230 DWARF_SET_ELF_ERROR(dbg, error); 231 ret = DW_DLE_ELF; 232 goto fail_cleanup; 233 } 234 235 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 236 NULL) { 237 DWARF_SET_ELF_ERROR(dbg, error); 238 ret = DW_DLE_ELF; 239 goto fail_cleanup; 240 } 241 242 if (!strcmp(name, ".symtab")) { 243 symtab_ndx = elf_ndxscn(scn); 244 if ((symtab_data = elf_getdata(scn, NULL)) == NULL) { 245 elferr = elf_errno(); 246 if (elferr != 0) { 247 _DWARF_SET_ERROR(NULL, error, 248 DW_DLE_ELF, elferr); 249 ret = DW_DLE_ELF; 250 goto fail_cleanup; 251 } 252 } 253 continue; 254 } 255 256 for (i = 0; debug_name[i] != NULL; i++) { 257 if (!strcmp(name, debug_name[i])) 258 n++; 259 } 260 } 261 elferr = elf_errno(); 262 if (elferr != 0) { 263 DWARF_SET_ELF_ERROR(dbg, error); 264 return (DW_DLE_ELF); 265 } 266 267 e->eo_seccnt = n; 268 269 if (n == 0) 270 return (DW_DLE_NONE); 271 272 if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL || 273 (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) { 274 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 275 ret = DW_DLE_MEMORY; 276 goto fail_cleanup; 277 } 278 279 scn = NULL; 280 j = 0; 281 while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) { 282 if (gelf_getshdr(scn, &sh) == NULL) { 283 DWARF_SET_ELF_ERROR(dbg, error); 284 ret = DW_DLE_ELF; 285 goto fail_cleanup; 286 } 287 288 memcpy(&e->eo_shdr[j], &sh, sizeof(sh)); 289 290 if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) == 291 NULL) { 292 DWARF_SET_ELF_ERROR(dbg, error); 293 ret = DW_DLE_ELF; 294 goto fail_cleanup; 295 } 296 297 for (i = 0; debug_name[i] != NULL; i++) { 298 if (strcmp(name, debug_name[i])) 299 continue; 300 301 (void) elf_errno(); 302 if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) == 303 NULL) { 304 elferr = elf_errno(); 305 if (elferr != 0) { 306 _DWARF_SET_ERROR(dbg, error, 307 DW_DLE_ELF, elferr); 308 ret = DW_DLE_ELF; 309 goto fail_cleanup; 310 } 311 } 312 313 if (_libdwarf.applyreloc) { 314 if (_dwarf_elf_relocate(dbg, elf, 315 &e->eo_data[j], elf_ndxscn(scn), symtab_ndx, 316 symtab_data, error) != DW_DLE_NONE) 317 goto fail_cleanup; 318 } 319 320 j++; 321 } 322 } 323 324 assert(j == n); 325 326 return (DW_DLE_NONE); 327 328 fail_cleanup: 329 330 _dwarf_elf_deinit(dbg); 331 332 return (ret); 333 } 334 335 void 336 _dwarf_elf_deinit(Dwarf_Debug dbg) 337 { 338 Dwarf_Obj_Access_Interface *iface; 339 Dwarf_Elf_Object *e; 340 int i; 341 342 iface = dbg->dbg_iface; 343 assert(iface != NULL); 344 345 e = iface->object; 346 assert(e != NULL); 347 348 if (e->eo_data) { 349 for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) { 350 if (e->eo_data[i].ed_alloc) 351 free(e->eo_data[i].ed_alloc); 352 } 353 free(e->eo_data); 354 } 355 if (e->eo_shdr) 356 free(e->eo_shdr); 357 358 free(e); 359 free(iface); 360 361 dbg->dbg_iface = NULL; 362 } 363