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