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