1 /*- 2 * Copyright (c) 2010 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_reloc.c 3741 2019-06-07 06:32:01Z jkoshy $"); 30 31 Dwarf_Unsigned 32 _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64) 33 { 34 35 assert(dbg != NULL); 36 37 switch (dbg->dbgp_isa) { 38 case DW_ISA_AARCH64: 39 return (is64 ? R_AARCH64_ABS64 : R_AARCH64_ABS32); 40 case DW_ISA_X86: 41 return (R_386_32); 42 case DW_ISA_X86_64: 43 return (is64 ? R_X86_64_64 : R_X86_64_32); 44 case DW_ISA_SPARC: 45 return (is64 ? R_SPARC_UA64 : R_SPARC_UA32); 46 case DW_ISA_PPC: 47 return (is64 ? R_PPC64_ADDR64 : R_PPC_ADDR32); 48 case DW_ISA_ARM: 49 return (R_ARM_ABS32); 50 case DW_ISA_MIPS: 51 return (is64 ? R_MIPS_64 : R_MIPS_32); 52 case DW_ISA_RISCV: 53 return (is64 ? R_RISCV_64 : R_RISCV_32); 54 case DW_ISA_IA64: 55 return (is64 ? R_IA_64_DIR64LSB : R_IA_64_DIR32LSB); 56 default: 57 break; 58 } 59 return (0); /* NOT REACHED */ 60 } 61 62 int 63 _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type) 64 { 65 66 switch (dbg->dbg_machine) { 67 case EM_NONE: 68 break; 69 case EM_AARCH64: 70 if (rel_type == R_AARCH64_ABS32) 71 return (4); 72 else if (rel_type == R_AARCH64_ABS64) 73 return (8); 74 break; 75 case EM_ARM: 76 if (rel_type == R_ARM_ABS32) 77 return (4); 78 break; 79 case EM_386: 80 case EM_IAMCU: 81 if (rel_type == R_386_32) 82 return (4); 83 break; 84 case EM_X86_64: 85 if (rel_type == R_X86_64_32) 86 return (4); 87 else if (rel_type == R_X86_64_64) 88 return (8); 89 break; 90 case EM_SPARC: 91 if (rel_type == R_SPARC_UA32) 92 return (4); 93 else if (rel_type == R_SPARC_UA64) 94 return (8); 95 break; 96 case EM_PPC: 97 if (rel_type == R_PPC_ADDR32) 98 return (4); 99 break; 100 case EM_PPC64: 101 if (rel_type == R_PPC_ADDR32) 102 return (4); 103 else if (rel_type == R_PPC64_ADDR64) 104 return (8); 105 break; 106 case EM_MIPS: 107 if (rel_type == R_MIPS_32) 108 return (4); 109 else if (rel_type == R_MIPS_64) 110 return (8); 111 break; 112 case EM_RISCV: 113 if (rel_type == R_RISCV_32) 114 return (4); 115 else if (rel_type == R_RISCV_64) 116 return (8); 117 break; 118 case EM_IA_64: 119 if (rel_type == R_IA_64_SECREL32LSB) 120 return (4); 121 else if (rel_type == R_IA_64_DIR64LSB) 122 return (8); 123 break; 124 default: 125 break; 126 } 127 128 /* unknown relocation. */ 129 return (0); 130 } 131 132 int 133 _dwarf_reloc_section_init(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp, 134 Dwarf_P_Section ref, Dwarf_Error *error) 135 { 136 Dwarf_Rel_Section drs; 137 char name[128]; 138 int pseudo; 139 140 assert(dbg != NULL && drsp != NULL && ref != NULL); 141 142 if ((drs = calloc(1, sizeof(struct _Dwarf_Rel_Section))) == NULL) { 143 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 144 return (DW_DLE_MEMORY); 145 } 146 147 drs->drs_ref = ref; 148 149 /* 150 * FIXME The logic here is most likely wrong. It should 151 * be the ISA that determines relocation type. 152 */ 153 if (dbg->dbgp_flags & DW_DLC_SIZE_64) 154 drs->drs_addend = 1; 155 else 156 drs->drs_addend = 0; 157 158 if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) 159 pseudo = 1; 160 else 161 pseudo = 0; 162 163 snprintf(name, sizeof(name), "%s%s", 164 drs->drs_addend ? ".rela" : ".rel", ref->ds_name); 165 if (_dwarf_section_init(dbg, &drs->drs_ds, name, pseudo, error) != 166 DW_DLE_NONE) { 167 free(drs); 168 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 169 return (DW_DLE_MEMORY); 170 } 171 172 STAILQ_INIT(&drs->drs_dre); 173 STAILQ_INSERT_TAIL(&dbg->dbgp_drslist, drs, drs_next); 174 dbg->dbgp_drscnt++; 175 *drsp = drs; 176 177 return (DW_DLE_NONE); 178 } 179 180 void 181 _dwarf_reloc_section_free(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp) 182 { 183 Dwarf_Rel_Section drs, tdrs; 184 Dwarf_Rel_Entry dre, tdre; 185 186 assert(dbg != NULL && drsp != NULL); 187 188 if (*drsp == NULL) 189 return; 190 191 STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) { 192 if (drs != *drsp) 193 continue; 194 STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section, 195 drs_next); 196 STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) { 197 STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry, 198 dre_next); 199 free(dre); 200 } 201 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) 202 _dwarf_section_free(dbg, &drs->drs_ds); 203 else { 204 if (drs->drs_ds->ds_name) 205 free(drs->drs_ds->ds_name); 206 free(drs->drs_ds); 207 } 208 free(drs); 209 *drsp = NULL; 210 dbg->dbgp_drscnt--; 211 break; 212 } 213 } 214 215 int 216 _dwarf_reloc_entry_add(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs, 217 Dwarf_P_Section ds, unsigned char type, unsigned char length, 218 Dwarf_Unsigned offset, Dwarf_Unsigned symndx, Dwarf_Unsigned addend, 219 const char *secname, Dwarf_Error *error) 220 { 221 Dwarf_Rel_Entry dre; 222 Dwarf_Unsigned reloff; 223 int ret; 224 225 assert(drs != NULL); 226 assert(offset <= ds->ds_size); 227 reloff = offset; 228 229 /* 230 * If the DW_DLC_SYMBOLIC_RELOCATIONS flag is set or ElfXX_Rel 231 * is used instead of ELfXX_Rela, we need to write the addend 232 * in the storage unit to be relocated. Otherwise write 0 in the 233 * storage unit and the addend will be written into relocation 234 * section later. 235 */ 236 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) || 237 drs->drs_addend == 0) 238 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset, 239 addend, length, error); 240 else 241 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset, 242 0, length, error); 243 if (ret != DW_DLE_NONE) 244 return (ret); 245 if (offset > ds->ds_size) 246 ds->ds_size = offset; 247 248 if ((dre = calloc(1, sizeof(struct _Dwarf_Rel_Entry))) == NULL) { 249 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 250 return (DW_DLE_MEMORY); 251 } 252 STAILQ_INSERT_TAIL(&drs->drs_dre, dre, dre_next); 253 dre->dre_type = type; 254 dre->dre_length = length; 255 dre->dre_offset = reloff; 256 dre->dre_symndx = symndx; 257 dre->dre_addend = addend; 258 dre->dre_secname = secname; 259 drs->drs_drecnt++; 260 261 return (DW_DLE_NONE); 262 } 263 264 int 265 _dwarf_reloc_entry_add_pair(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs, 266 Dwarf_P_Section ds, unsigned char length, Dwarf_Unsigned offset, 267 Dwarf_Unsigned symndx, Dwarf_Unsigned esymndx, Dwarf_Unsigned symoff, 268 Dwarf_Unsigned esymoff, Dwarf_Error *error) 269 { 270 Dwarf_Rel_Entry dre; 271 Dwarf_Unsigned reloff; 272 int ret; 273 274 assert(drs != NULL); 275 assert(offset <= ds->ds_size); 276 assert(dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS); 277 reloff = offset; 278 279 /* Write net offset into section stream. */ 280 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset, 281 esymoff - symoff, length, error); 282 if (ret != DW_DLE_NONE) 283 return (ret); 284 if (offset > ds->ds_size) 285 ds->ds_size = offset; 286 287 if ((dre = calloc(2, sizeof(struct _Dwarf_Rel_Entry))) == NULL) { 288 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 289 return (DW_DLE_MEMORY); 290 } 291 STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[0], dre_next); 292 STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[1], dre_next); 293 dre[0].dre_type = dwarf_drt_first_of_length_pair; 294 dre[0].dre_length = length; 295 dre[0].dre_offset = reloff; 296 dre[0].dre_symndx = symndx; 297 dre[0].dre_addend = 0; 298 dre[0].dre_secname = NULL; 299 dre[1].dre_type = dwarf_drt_second_of_length_pair; 300 dre[1].dre_length = length; 301 dre[1].dre_offset = reloff; 302 dre[1].dre_symndx = esymndx; 303 dre[1].dre_addend = 0; 304 dre[1].dre_secname = NULL; 305 drs->drs_drecnt += 2; 306 307 return (DW_DLE_NONE); 308 } 309 310 int 311 _dwarf_reloc_section_finalize(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs, 312 Dwarf_Error *error) 313 { 314 Dwarf_P_Section ds; 315 Dwarf_Unsigned unit; 316 int ret, size; 317 318 assert(dbg != NULL && drs != NULL && drs->drs_ds != NULL && 319 drs->drs_ref != NULL); 320 321 ds = drs->drs_ds; 322 323 /* 324 * Calculate the size (in bytes) of the relocation section. 325 */ 326 if (dbg->dbgp_flags & DW_DLC_SIZE_64) 327 unit = drs->drs_addend ? sizeof(Elf64_Rela) : sizeof(Elf64_Rel); 328 else 329 unit = drs->drs_addend ? sizeof(Elf32_Rela) : sizeof(Elf32_Rel); 330 assert(ds->ds_size == 0); 331 size = drs->drs_drecnt * unit; 332 333 /* 334 * Discard this relocation section if there is no entry in it. 335 */ 336 if (size == 0) { 337 _dwarf_reloc_section_free(dbg, &drs); 338 return (DW_DLE_NONE); 339 } 340 341 /* 342 * If we are under stream mode, realloc the section data block to 343 * this size. 344 */ 345 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) { 346 ds->ds_cap = size; 347 if ((ds->ds_data = realloc(ds->ds_data, (size_t) ds->ds_cap)) == 348 NULL) { 349 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 350 return (DW_DLE_MEMORY); 351 } 352 } 353 354 /* 355 * Notify the application the creation of this relocation section. 356 * Note that the section link here should point to the .symtab 357 * section, we set it to 0 since we have no way to know .symtab 358 * section index. 359 */ 360 ret = _dwarf_pro_callback(dbg, ds->ds_name, size, 361 drs->drs_addend ? SHT_RELA : SHT_REL, 0, 0, drs->drs_ref->ds_ndx, 362 &ds->ds_symndx, NULL); 363 if (ret < 0) { 364 DWARF_SET_ERROR(dbg, error, DW_DLE_ELF_SECT_ERR); 365 return (DW_DLE_ELF_SECT_ERR); 366 } 367 ds->ds_ndx = ret; 368 369 return (DW_DLE_NONE); 370 } 371 372 int 373 _dwarf_reloc_section_gen(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs, 374 Dwarf_Error *error) 375 { 376 Dwarf_Rel_Entry dre; 377 Dwarf_P_Section ds; 378 Dwarf_Unsigned type; 379 int ret; 380 381 assert((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0); 382 assert(drs->drs_ds != NULL && drs->drs_ds->ds_size == 0); 383 assert(!STAILQ_EMPTY(&drs->drs_dre)); 384 ds = drs->drs_ds; 385 386 STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) { 387 assert(dre->dre_length == 4 || dre->dre_length == 8); 388 type = _dwarf_get_reloc_type(dbg, dre->dre_length == 8); 389 if (dbg->dbgp_flags & DW_DLC_SIZE_64) { 390 /* Write r_offset (8 bytes) */ 391 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, 392 &ds->ds_size, dre->dre_offset, 8, error); 393 if (ret != DW_DLE_NONE) 394 return (ret); 395 /* Write r_info (8 bytes) */ 396 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, 397 &ds->ds_size, ELF64_R_INFO(dre->dre_symndx, type), 398 8, error); 399 if (ret != DW_DLE_NONE) 400 return (ret); 401 /* Write r_addend (8 bytes) */ 402 if (drs->drs_addend) { 403 ret = dbg->write_alloc(&ds->ds_data, 404 &ds->ds_cap, &ds->ds_size, dre->dre_addend, 405 8, error); 406 if (ret != DW_DLE_NONE) 407 return (ret); 408 } 409 } else { 410 /* Write r_offset (4 bytes) */ 411 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, 412 &ds->ds_size, dre->dre_offset, 4, error); 413 if (ret != DW_DLE_NONE) 414 return (ret); 415 /* Write r_info (4 bytes) */ 416 ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, 417 &ds->ds_size, ELF32_R_INFO(dre->dre_symndx, type), 418 4, error); 419 if (ret != DW_DLE_NONE) 420 return (ret); 421 /* Write r_addend (4 bytes) */ 422 if (drs->drs_addend) { 423 ret = dbg->write_alloc(&ds->ds_data, 424 &ds->ds_cap, &ds->ds_size, dre->dre_addend, 425 4, error); 426 if (ret != DW_DLE_NONE) 427 return (ret); 428 } 429 } 430 } 431 assert(ds->ds_size == ds->ds_cap); 432 433 return (DW_DLE_NONE); 434 } 435 436 int 437 _dwarf_reloc_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 438 { 439 Dwarf_Rel_Section drs; 440 Dwarf_Rel_Entry dre; 441 Dwarf_P_Section ds; 442 int ret; 443 444 STAILQ_FOREACH(drs, &dbg->dbgp_drslist, drs_next) { 445 /* 446 * Update relocation entries: translate any section name 447 * reference to section symbol index. 448 */ 449 STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) { 450 if (dre->dre_secname == NULL) 451 continue; 452 ds = _dwarf_pro_find_section(dbg, dre->dre_secname); 453 assert(ds != NULL && ds->ds_symndx != 0); 454 dre->dre_symndx = ds->ds_symndx; 455 } 456 457 /* 458 * Generate ELF relocation section if we are under stream 459 * mode. 460 */ 461 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) { 462 ret = _dwarf_reloc_section_gen(dbg, drs, error); 463 if (ret != DW_DLE_NONE) 464 return (ret); 465 } 466 } 467 468 return (DW_DLE_NONE); 469 } 470 471 void 472 _dwarf_reloc_cleanup(Dwarf_P_Debug dbg) 473 { 474 Dwarf_Rel_Section drs, tdrs; 475 Dwarf_Rel_Entry dre, tdre; 476 477 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 478 479 STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) { 480 STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section, 481 drs_next); 482 free(drs->drs_drd); 483 STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) { 484 STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry, 485 dre_next); 486 free(dre); 487 } 488 if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { 489 if (drs->drs_ds) { 490 if (drs->drs_ds->ds_name) 491 free(drs->drs_ds->ds_name); 492 free(drs->drs_ds); 493 } 494 } 495 free(drs); 496 } 497 dbg->dbgp_drscnt = 0; 498 dbg->dbgp_drspos = NULL; 499 } 500