1 2 #include <stdio.h> 3 #include <common.h> 4 #include <debug.h> 5 #include <hash.h> 6 #include <libelf.h> 7 #include <libebl.h> 8 #include <libebl_arm.h> 9 #include <elf.h> 10 #include <gelf.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <fcntl.h> 17 #include <unistd.h> 18 #ifdef DEBUG 19 #include <rangesort.h> 20 #endif 21 22 /* static void print_shdr_array(shdr_info_t *, int); */ 23 24 #include <elfcopy.h> 25 26 #define COPY_SECTION_DATA_BUFFER (0) 27 28 /* When this macro is set to a nonzero value, we replace calls to elf_strptr() 29 on the target ELF handle with code that extracts the strings directly from 30 the data buffers of that ELF handle. In this case, elf_strptr() does not 31 work as expected, as it tries to read the data buffer of the associated 32 string section directly from the file, and that buffer does not exist yet 33 in the file, since we haven't committed our changes yet. 34 */ 35 #define ELF_STRPTR_IS_BROKEN (1) 36 37 static void update_relocations_section_symbol_references(Elf *newelf, Elf *elf, 38 shdr_info_t *info, int info_len, 39 shdr_info_t *relsect_info, 40 Elf32_Word *newsymidx); 41 42 static void update_relocations_section_offsets(Elf *newelf, Elf *elf, Ebl *ebl, 43 shdr_info_t *info, 44 int info_len, 45 shdr_info_t *relsect_info, 46 Elf_Data *data, 47 range_list_t *old_section_ranges); 48 49 static void update_hash_table(Elf *newelf, Elf *elf, 50 Elf32_Word hash_scn_idx, 51 shdr_info_t *symtab_info); 52 53 static inline 54 Elf_Data *create_section_data(shdr_info_t *, Elf_Scn *); 55 56 static Elf64_Off section_to_header_mapping(Elf *elf, 57 int phdr_idx, 58 shdr_info_t *shdr_info, 59 int num_shdr_info, 60 Elf64_Off *file_end, 61 Elf64_Off *mem_end); 62 63 static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl, 64 int dynidx, /* index of .dynamic section */ 65 int symtabidx, /* index of symbol table section */ 66 shdr_info_t *shdr_info, 67 int shdr_info_len); 68 69 #ifdef DEBUG 70 static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl, 71 int dynidx, /* index of .dynamic section */ 72 int symtabidx, /* index of symbol table section */ 73 shdr_info_t *shdr_info, 74 int shdr_info_len); 75 #endif 76 77 static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl, 78 Elf *newelf, 79 int idx, /* index of .dynamic section */ 80 shdr_info_t *shdr_info, 81 int shdr_info_len); 82 83 static void update_symbol_values(Elf *elf, GElf_Ehdr *ehdr, 84 Elf *newelf, 85 shdr_info_t *shdr_info, 86 int num_shdr_info, 87 int shady, 88 int dynamic_idx); 89 90 static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr); 91 92 static range_list_t * 93 update_section_offsets(Elf *elf, 94 Elf *newelf, 95 GElf_Phdr *phdr_info, 96 shdr_info_t *shdr_info, 97 int num_shdr_info, 98 range_list_t *section_ranges, 99 bool adjust_alloc_section_offsets); 100 101 void handle_range_error(range_error_t err, range_t *left, range_t *right); 102 103 #ifdef DEBUG 104 static void 105 verify_elf(GElf_Ehdr *ehdr, struct shdr_info_t *shdr_info, int shdr_info_len, 106 GElf_Phdr *phdr_info); 107 #endif 108 109 void adjust_elf(Elf *elf, const char *elf_name, 110 Elf *newelf, const char *newelf_name __attribute__((unused)), 111 Ebl *ebl, 112 GElf_Ehdr *ehdr, /* store ELF header of original library */ 113 bool *sym_filter, int num_symbols, 114 struct shdr_info_t *shdr_info, int shdr_info_len, 115 GElf_Phdr *phdr_info, 116 size_t highest_scn_num, 117 size_t shnum, 118 size_t shstrndx, 119 struct Ebl_Strtab *shst, 120 bool sections_dropped_or_rearranged, 121 int dynamic_idx, /* index in shdr_info[] of .dynamic section */ 122 int dynsym_idx, /* index in shdr_info[] of dynamic symbol table */ 123 int shady, 124 Elf_Data **shstrtab_data, 125 bool adjust_alloc_section_offsets, 126 bool rebuild_shstrtab) 127 { 128 int cnt; /* general-purpose counter */ 129 Elf_Scn *scn; /* general-purpose section */ 130 131 *shstrtab_data = NULL; 132 133 /* When this flag is true, we have dropped some symbols, which caused 134 a change in the order of symbols in the symbol table (all symbols after 135 the removed symbol have shifted forward), and a change in its size as 136 well. When the symbol table changes this way, we need to modify the 137 relocation entries that relocate symbols in this symbol table, and we 138 also need to rebuild the hash table (the hash is outdated). 139 140 Note that it is possible to change the symbols in the symbol table 141 without changing their position (that is, without cutting any symbols 142 out). If a section that a symbol refers to changes (i.e., moves), we 143 need to update that section's index in the symbol entry in the symbol 144 table. Therefore, there are symbol-table changes that can be made and 145 still have symtab_size_changed == false! 146 */ 147 bool symtab_size_changed = false; 148 149 /* We allow adjusting of offsets only for files that are shared libraries. 150 We cannot mess with the relative positions of sections for executable 151 files, because we do not have enough information to adjust them. The 152 text section is already linked to fixed addresses. 153 */ 154 ASSERT(!adjust_alloc_section_offsets || ehdr->e_type == ET_DYN); 155 156 if (!sections_dropped_or_rearranged) 157 INFO("Note: we aren't dropping or rearranging any sections.\n"); 158 159 /* Index of the section header table in the shdr_info array. This is 160 an important variable because it denotes the last section of the old 161 file, as well as the location of the section-strings section of the 162 new one. 163 164 Note: we use this variable only when we are re-creating the section- 165 header-strings table. Otherwise, we keep it as zero. 166 */ 167 168 size_t shdridx = shstrndx; 169 if (rebuild_shstrtab) { 170 INFO("Creating new section-strings section...\n"); 171 172 shdridx = shnum; 173 174 /* Create the new section-name-strings section */ 175 { 176 INFO("\tNew index will be %d (was %d).\n", highest_scn_num, shstrndx); 177 178 /* Add the section header string table section name. */ 179 shdr_info[shdridx] = shdr_info[shstrndx]; 180 ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab")); 181 shdr_info[shdridx].se = ebl_strtabadd (shst, ".shstrtab", 10); 182 ASSERT(shdr_info[shdridx].se != NULL); 183 shdr_info[shdridx].idx = highest_scn_num; 184 185 /* Create the section header. */ 186 shdr_info[shdridx].shdr.sh_type = SHT_STRTAB; 187 shdr_info[shdridx].shdr.sh_flags = 0; 188 shdr_info[shdridx].shdr.sh_addr = 0; 189 shdr_info[shdridx].shdr.sh_link = SHN_UNDEF; 190 shdr_info[shdridx].shdr.sh_info = SHN_UNDEF; 191 shdr_info[shdridx].shdr.sh_entsize = 0; 192 193 shdr_info[shdridx].shdr.sh_offset = shdr_info[shdridx].old_shdr.sh_offset; 194 shdr_info[shdridx].shdr.sh_addralign = 1; 195 196 /* Create the section. */ 197 FAILIF_LIBELF((shdr_info[shdridx].newscn = elf_newscn(newelf)) == NULL, 198 elf_newscn); 199 ASSERT(elf_ndxscn (shdr_info[shdridx].newscn) == highest_scn_num); 200 201 { 202 /* Finalize the string table and fill in the correct indices in 203 the section headers. */ 204 FAILIF_LIBELF((*shstrtab_data = 205 elf_newdata (shdr_info[shdridx].newscn)) == NULL, 206 elf_newdata); 207 ebl_strtabfinalize (shst, *shstrtab_data); 208 /* We have to set the section size. */ 209 INFO("\tNew size will be %d.\n", (*shstrtab_data)->d_size); 210 shdr_info[shdridx].shdr.sh_size = (*shstrtab_data)->d_size; 211 /* Setting the data pointer tells the update loop below not to 212 copy the information from the original section. */ 213 214 shdr_info[shdridx].data = *shstrtab_data; 215 #if COPY_SECTION_DATA_BUFFER 216 shdr_info[shdridx].data->d_buf = MALLOC(shdr_info[shdridx].data->d_size); 217 ASSERT((*shstrtab_data)->d_buf); 218 memcpy(shdr_info[shdridx].data->d_buf, (*shstrtab_data)->d_buf, (*shstrtab_data)->d_size); 219 #endif 220 } 221 } 222 } /* if (rebuild_shstrtab) */ 223 else { 224 /* When we are not rebuilding shstrtab, we expect the input parameter 225 shstrndx to be the index of .shstrtab BOTH in shdr_info[] and in 226 as a section index in the ELF file. 227 */ 228 ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab")); 229 } 230 231 INFO("Updating section information...\n"); 232 /* Update the section information. */ 233 234 #ifdef DEBUG 235 /* We use this flag to ASSERT that the symbol tables comes 236 before the .dynamic section in the file. See comments 237 further below. 238 */ 239 bool visited_dynsym = false; 240 #endif 241 242 for (cnt = 1; cnt < shdr_info_len; ++cnt) { 243 if (shdr_info[cnt].idx > 0) { 244 Elf_Data *newdata; 245 246 INFO("\t%03d: Updating section %s (index %d, address %lld offset %lld, size %lld, alignment %d)...\n", 247 cnt, 248 (shdr_info[cnt].name ?: "(no name)"), 249 shdr_info[cnt].idx, 250 shdr_info[cnt].shdr.sh_addr, 251 shdr_info[cnt].shdr.sh_offset, 252 shdr_info[cnt].shdr.sh_size, 253 shdr_info[cnt].shdr.sh_addralign); 254 255 scn = shdr_info[cnt].newscn; 256 ASSERT(scn != NULL); 257 ASSERT(scn == elf_getscn(newelf, shdr_info[cnt].idx)); 258 259 /* Update the name. */ 260 if (rebuild_shstrtab) { 261 Elf64_Word new_sh_name = ebl_strtaboffset(shdr_info[cnt].se); 262 INFO("\t\tname offset %d (was %d).\n", 263 new_sh_name, 264 shdr_info[cnt].shdr.sh_name); 265 shdr_info[cnt].shdr.sh_name = new_sh_name; 266 } 267 268 /* Update the section header from the input file. Some fields 269 might be section indices which now have to be adjusted. */ 270 if (shdr_info[cnt].shdr.sh_link != 0) { 271 INFO("\t\tsh_link %d (was %d).\n", 272 shdr_info[shdr_info[cnt].shdr.sh_link].idx, 273 shdr_info[cnt].shdr.sh_link); 274 275 shdr_info[cnt].shdr.sh_link = 276 shdr_info[shdr_info[cnt].shdr.sh_link].idx; 277 } 278 279 /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */ 280 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)) { 281 INFO("\t\tsh_info %d (was %d).\n", 282 shdr_info[shdr_info[cnt].shdr.sh_info].idx, 283 shdr_info[cnt].shdr.sh_info); 284 285 shdr_info[cnt].shdr.sh_info = 286 shdr_info[shdr_info[cnt].shdr.sh_info].idx; 287 } 288 289 /* Get the data from the old file if necessary. We already 290 created the data for the section header string table, which 291 has a section number equal to shnum--hence the ASSERT(). 292 */ 293 ASSERT(!rebuild_shstrtab || shdr_info[cnt].data || cnt < shnum); 294 newdata = create_section_data(shdr_info + cnt, scn); 295 296 /* We know the size. */ 297 shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size; 298 299 /* We have to adjust symbol tables. Each symbol contains 300 a reference to the section it belongs to. Since we have 301 renumbered the sections (and dropped some), we need to adjust 302 the symbols' section indices as well. Also, if we do not want 303 to keep a symbol, we drop it from the symbol table in this loop. 304 305 When we drop symbols from the dynamic-symbol table, we need to 306 remove the names of the sybmols from the dynamic-symbol-strings 307 table. Changing the dynamic-symbol-strings table means that we 308 also have to rebuild the strings that go into the .dynamic 309 section (such as the DT_NEEDED strings, which lists the libraries 310 that the file depends on), since those strings are kept in the 311 same dynamic-symbol-strings table. That latter statement 312 is an assumption (which we ASSERT against, read on below). 313 314 Note: we process the symbol-table sections only when the user 315 specifies a symbol filter AND that leads to a change in the 316 symbol table, or when section indices change. 317 */ 318 319 /* The .dynamic section's strings need not be contained in the 320 same section as the strings of the dynamic symbol table, 321 but we assume that they are (I haven't seen it be otherwise). 322 We assert the validity of our assumption here. 323 324 If this assertion fails, then we *may* need to reorganize 325 this code as follows: we will need to call function 326 build_dynamic_segment_strings() even when sections numbers 327 don't change and there is no filter. Also, if string section 328 containing the .dynamic section strings changes, then we'd 329 need to update the sh_link of the .dynamic section to point 330 to the new section. 331 */ 332 333 ASSERT(shdr_info[dynamic_idx].shdr.sh_link == 334 shdr_info[dynsym_idx].shdr.sh_link); 335 336 if (sections_dropped_or_rearranged || (sym_filter != NULL)) 337 { 338 if(shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) 339 { 340 INFO("\t\tupdating a symbol table.\n"); 341 342 /* Calculate the size of the external representation of a 343 symbol. */ 344 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version); 345 346 /* Check the length of the dynamic-symbol filter. (This is the 347 second of two identical checks, the first one being in 348 the loop that checks for exceptions.) 349 350 NOTE: We narrow this assertion down to the dynamic-symbol 351 table only. Since we expect the symbol filter to 352 be parallel to .dynsym, and .dynsym in general 353 contains fewer symbols than .strtab, we cannot 354 make this assertion for .strtab. 355 */ 356 FAILIF(sym_filter != NULL && 357 num_symbols != shdr_info[cnt].data->d_size / elsize, 358 "Length of dynsym filter (%d) must equal the number" 359 " of dynamic symbols (%d) in section [%s]!\n", 360 num_symbols, 361 shdr_info[cnt].data->d_size / elsize, 362 shdr_info[cnt].name); 363 364 shdr_info[cnt].symse = 365 (struct Ebl_Strent **)MALLOC( 366 (shdr_info[cnt].data->d_size/elsize) * 367 sizeof(struct Ebl_Strent *)); 368 shdr_info[cnt].dynsymst = ebl_strtabinit(1); 369 FAILIF_LIBELF(NULL == shdr_info[cnt].dynsymst, ebl_strtabinit); 370 371 /* Allocate an array of Elf32_Word, one for each symbol. This 372 array will hold the new symbol indices. 373 */ 374 shdr_info[cnt].newsymidx = 375 (Elf32_Word *)CALLOC(shdr_info[cnt].data->d_size / elsize, 376 sizeof (Elf32_Word)); 377 378 bool last_was_local = true; 379 size_t destidx, // index of the symbol in the new symbol table 380 inner, // index of the symbol in the old table 381 last_local_idx = 0; 382 int num_kept_undefined_and_special = 0; 383 int num_kept_global_or_weak = 0; 384 int num_thrown_away = 0; 385 386 unsigned long num_symbols = shdr_info[cnt].data->d_size / elsize; 387 INFO("\t\tsymbol table has %ld symbols.\n", num_symbols); 388 389 /* In the loop below, determine whether to remove or not each 390 symbol. 391 */ 392 for (destidx = inner = 1; inner < num_symbols; ++inner) 393 { 394 Elf32_Word sec; /* index of section a symbol refers to */ 395 Elf32_Word xshndx; /* extended-section index of symbol */ 396 /* Retrieve symbol information and separate section index 397 from the symbol table at the given index. */ 398 GElf_Sym sym_mem; /* holds the symbol */ 399 400 /* Retrieve symbol information and separate section index 401 from the symbol table at the given index. */ 402 GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data, 403 NULL, inner, 404 &sym_mem, &xshndx); 405 ASSERT(sym != NULL); 406 407 FAILIF(sym->st_shndx == SHN_XINDEX, 408 "Can't handle symbol's st_shndx == SHN_XINDEX!\n"); 409 410 /* Do not automatically strip the symbol if: 411 -- the symbol filter is NULL or 412 -- the symbol is marked to keep or 413 -- the symbol is neither of: 414 -- imported or refers to a nonstandard section 415 -- global 416 -- weak 417 418 We do not want to strip imported symbols, because then 419 we won't be able to link against them. We do not want 420 to strip global or weak symbols, because then someone 421 else will fail to link against them. Finally, we do 422 not want to strip nonstandard symbols, because we're 423 not sure what they are doing there. 424 */ 425 426 char *symname = elf_strptr(elf, 427 shdr_info[cnt].old_shdr.sh_link, 428 sym->st_name); 429 430 if (NULL == sym_filter || /* no symfilter */ 431 sym_filter[inner] || /* keep the symbol! */ 432 /* don't keep the symbol, but the symbol is undefined 433 or refers to a specific section */ 434 sym->st_shndx == SHN_UNDEF || sym->st_shndx >= shnum || 435 /* don't keep the symbol, which defined and refers to 436 a normal section, but the symbol is neither global 437 nor weak. */ 438 (ELF32_ST_BIND(sym->st_info) != STB_GLOBAL && 439 ELF32_ST_BIND(sym->st_info) != STB_WEAK)) 440 { 441 /* Do not remove the symbol. */ 442 if (sym->st_shndx == SHN_UNDEF || 443 sym->st_shndx >= shnum) 444 { 445 /* This symbol has no section index (it is 446 absolute). Leave the symbol alone unless it is 447 moved. */ 448 FAILIF_LIBELF(!(destidx == inner || 449 gelf_update_symshndx( 450 shdr_info[cnt].data, 451 NULL, 452 destidx, 453 sym, 454 xshndx)), 455 gelf_update_symshndx); 456 457 shdr_info[cnt].newsymidx[inner] = destidx; 458 INFO("\t\t\tkeeping %s symbol %d (new index %d), name [%s]\n", 459 (sym->st_shndx == SHN_UNDEF ? "undefined" : "special"), 460 inner, 461 destidx, 462 symname); 463 /* mark the symbol as kept */ 464 if (sym_filter) sym_filter[inner] = 1; 465 shdr_info[cnt].symse[destidx] = 466 ebl_strtabadd (shdr_info[cnt].dynsymst, 467 symname, 0); 468 ASSERT(shdr_info[cnt].symse[destidx] != NULL); 469 num_kept_undefined_and_special++; 470 if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) 471 last_local_idx = destidx; 472 destidx++; 473 } else { 474 /* Get the full section index. */ 475 sec = shdr_info[sym->st_shndx].idx; 476 477 if (sec) { 478 Elf32_Word nxshndx; 479 480 ASSERT (sec < SHN_LORESERVE); 481 nxshndx = 0; 482 483 /* Update the symbol only if something changed, 484 that is, if either the symbol's position in 485 the symbol table changed (because we deleted 486 some symbols), or because its section moved! 487 488 NOTE: We don't update the symbol's section 489 index, sym->st_shndx here, but in function 490 update_symbol_values() instead. The reason 491 is that if we update the symbol-section index, 492 now, it won't refer anymore to the shdr_info[] 493 entry, which we will need in 494 update_symbol_values(). 495 */ 496 if (inner != destidx) 497 { 498 FAILIF_LIBELF(0 == 499 gelf_update_symshndx( 500 shdr_info[cnt].data, 501 NULL, 502 destidx, sym, 503 nxshndx), 504 gelf_update_symshndx); 505 } 506 507 shdr_info[cnt].newsymidx[inner] = destidx; 508 509 /* If we are not filtering out some symbols, 510 there's no point to printing this message 511 for every single symbol. */ 512 if (sym_filter) { 513 INFO("\t\t\tkeeping symbol %d (new index %d), name (index %d) [%s]\n", 514 inner, 515 destidx, 516 sym->st_name, 517 symname); 518 /* mark the symbol as kept */ 519 sym_filter[inner] = 1; 520 } 521 shdr_info[cnt].symse[destidx] = 522 ebl_strtabadd(shdr_info[cnt].dynsymst, 523 symname, 0); 524 ASSERT(shdr_info[cnt].symse[destidx] != NULL); 525 num_kept_global_or_weak++; 526 if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) 527 last_local_idx = destidx; 528 destidx++; 529 } else { 530 /* I am not sure, there might be other types of 531 symbols that do not refer to any section, but 532 I will handle them case by case when this 533 assertion fails--I want to know if each of them 534 is safe to remove! 535 */ 536 ASSERT(GELF_ST_TYPE (sym->st_info) == STT_SECTION || 537 GELF_ST_TYPE (sym->st_info) == STT_NOTYPE); 538 INFO("\t\t\tignoring %s symbol [%s]" 539 " at index %d refering to section %d\n", 540 (GELF_ST_TYPE(sym->st_info) == STT_SECTION 541 ? "STT_SECTION" : "STT_NOTYPE"), 542 symname, 543 inner, 544 sym->st_shndx); 545 num_thrown_away++; 546 /* mark the symbol as thrown away */ 547 if (sym_filter) sym_filter[inner] = 0; 548 } 549 } 550 } /* to strip or not to strip? */ 551 else { 552 INFO("\t\t\tremoving symbol [%s]\n", symname); 553 shdr_info[cnt].newsymidx[inner] = (Elf32_Word)-1; 554 num_thrown_away++; 555 /* mark the symbol as thrown away */ 556 if (sym_filter) sym_filter[inner] = 0; 557 } 558 559 /* For symbol-table sections, sh_info is one greater than the 560 symbol table index of the last local symbol. This is why, 561 when we find the last local symbol, we update the sh_info 562 field. 563 */ 564 565 if (last_was_local) { 566 if (GELF_ST_BIND (sym->st_info) != STB_LOCAL) { 567 last_was_local = false; 568 if (last_local_idx) { 569 INFO("\t\t\tMARKING ONE PAST LAST LOCAL INDEX %d\n", 570 last_local_idx + 1); 571 shdr_info[cnt].shdr.sh_info = 572 last_local_idx + 1; 573 } 574 else shdr_info[cnt].shdr.sh_info = 0; 575 576 } 577 } else FAILIF(0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL, 578 "Internal error in ELF file: symbol table has" 579 " local symbols after first global" 580 " symbol!\n"); 581 } /* for each symbol */ 582 583 INFO("\t\t%d undefined or special symbols were kept.\n", 584 num_kept_undefined_and_special); 585 INFO("\t\t%d global or weak symbols were kept.\n", 586 num_kept_global_or_weak); 587 INFO("\t\t%d symbols were thrown away.\n", 588 num_thrown_away); 589 590 if (destidx != inner) { 591 /* The symbol table changed. */ 592 INFO("\t\t\tthe symbol table has changed.\n"); 593 INFO("\t\t\tdestidx = %d, inner = %d.\n", destidx, inner); 594 INFO("\t\t\tnew size %d (was %lld).\n", 595 destidx * elsize, 596 shdr_info[cnt].shdr.sh_size); 597 shdr_info[cnt].shdr.sh_size = newdata->d_size = destidx * elsize; 598 symtab_size_changed = true; 599 } else { 600 /* The symbol table didn't really change. */ 601 INFO("\t\t\tthe symbol table did not change.\n"); 602 FREE (shdr_info[cnt].newsymidx); 603 shdr_info[cnt].newsymidx = NULL; 604 } 605 #ifdef DEBUG 606 visited_dynsym = shdr_info[cnt].shdr.sh_type == SHT_DYNSYM; 607 #endif 608 } /* if it's a symbol table... */ 609 else if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) { 610 /* We get here either when we drop some sections, or 611 when we are dropping symbols. If we are not dropping 612 symbols, then the dynamic-symbol-table and its strings 613 section won't change, so we won't need to rebuild the 614 symbols for the SHT_DYNAMIC section either. 615 616 NOTE: If ever in the future we add the ability in 617 adjust_elf() to change the strings in the SHT_DYNAMIC 618 section, then we would need to find a way to rebuild 619 the dynamic-symbol-table-strings section. 620 */ 621 622 /* symtab_size_changed has a meaningful value only after 623 we've processed the symbol table. If this assertion 624 is ever violated, it will be because the .dynamic section 625 came before the symbol table in the list of section in 626 a file. If that happens, then we have to break up the 627 loop into two: one that finds and processes the symbol 628 tables, and another, after the first one, that finds 629 and handles the .dynamic sectio. 630 */ 631 ASSERT(visited_dynsym == true); 632 if (sym_filter != NULL && symtab_size_changed) { 633 /* Walk the old dynamic segment. For each tag that represents 634 a string, build an entry into the dynamic-symbol-table's 635 strings table. */ 636 INFO("\t\tbuilding strings for the dynamic section.\n"); 637 ASSERT(cnt == dynamic_idx); 638 639 /* NOTE: By passing the the index (in shdr_info[]) of the 640 dynamic-symbol table to build_dynamic_segment_strings(), 641 we are making the assumption that those strings will be 642 kept in that table. While this does not seem to be 643 mandated by the ELF spec, it seems to be always the case. 644 Where else would you put these strings? You already have 645 the dynamic-symbol table and its strings table, and that's 646 guaranteed to be in the file, so why not put it there? 647 */ 648 build_dynamic_segment_strings(elf, ebl, 649 dynamic_idx, 650 dynsym_idx, 651 shdr_info, 652 shdr_info_len); 653 } 654 else { 655 INFO("\t\tThe dynamic-symbol table is not changing, so no " 656 "need to rebuild strings for the dynamic section.\n"); 657 #ifdef DEBUG 658 print_dynamic_segment_strings(elf, ebl, 659 dynamic_idx, 660 dynsym_idx, 661 shdr_info, 662 shdr_info_len); 663 #endif 664 } 665 } 666 } 667 668 /* Set the section header in the new file. There cannot be any 669 overflows. */ 670 INFO("\t\tupdating section header (size %lld)\n", 671 shdr_info[cnt].shdr.sh_size); 672 673 FAILIF(!gelf_update_shdr (scn, &shdr_info[cnt].shdr), 674 "Could not update section header for section %s!\n", 675 shdr_info[cnt].name); 676 } /* if (shdr_info[cnt].idx > 0) */ 677 else INFO("\t%03d: not updating section %s, it will be discarded.\n", 678 cnt, 679 shdr_info[cnt].name); 680 } /* for (cnt = 1; cnt < shdr_info_len; ++cnt) */ 681 682 /* Now, if we removed some symbols and thus modified the symbol table, 683 we need to update the hash table, the relocation sections that use these 684 symbols, and the symbol-strings table to cut out the unused symbols. 685 */ 686 if (symtab_size_changed) { 687 for (cnt = 1; cnt < shnum; ++cnt) { 688 if (shdr_info[cnt].idx == 0) { 689 /* Ignore sections which are discarded, unless these sections 690 are relocation sections. This case is for use by the 691 prelinker. */ 692 if (shdr_info[cnt].shdr.sh_type != SHT_REL && 693 shdr_info[cnt].shdr.sh_type != SHT_RELA) { 694 continue; 695 } 696 } 697 698 if (shdr_info[cnt].shdr.sh_type == SHT_REL || 699 shdr_info[cnt].shdr.sh_type == SHT_RELA) { 700 /* shdr_info[cnt].old_shdr.sh_link is index of old symbol-table 701 section that this relocation-table section was relative to. 702 We can access shdr_info[] at that index to get to the 703 symbol-table section. 704 */ 705 Elf32_Word *newsymidx = 706 shdr_info[shdr_info[cnt].old_shdr.sh_link].newsymidx; 707 708 /* The referred-to-section must be a symbol table! Note that 709 alrhough shdr_info[cnt].shdr refers to the updated section 710 header, this assertion is still valid, since when updating 711 the section header we never modify the sh_type field. 712 */ 713 { 714 Elf64_Word sh_type = 715 shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type; 716 FAILIF(sh_type != SHT_DYNSYM, 717 "Section refered to from relocation section is not" 718 " a dynamic symbol table (sh_type=%d)!\n", 719 sh_type); 720 } 721 722 /* If that symbol table hasn't changed, then its newsymidx 723 field is NULL (see comments to shdr_info_t), so we 724 don't have to update this relocation-table section 725 */ 726 if (newsymidx == NULL) continue; 727 728 update_relocations_section_symbol_references(newelf, elf, 729 shdr_info, shnum, 730 shdr_info + cnt, 731 newsymidx); 732 733 } else if (shdr_info[cnt].shdr.sh_type == SHT_HASH) { 734 /* We have to recompute the hash table. A hash table's 735 sh_link field refers to the symbol table for which the hash 736 table is generated. 737 */ 738 Elf32_Word symtabidx = shdr_info[cnt].old_shdr.sh_link; 739 740 /* We do not have to recompute the hash table if the symbol 741 table was not changed. */ 742 if (shdr_info[symtabidx].newsymidx == NULL) 743 continue; 744 745 FAILIF(shdr_info[cnt].shdr.sh_entsize != sizeof (Elf32_Word), 746 "Can't handle 64-bit ELF files!\n"); 747 748 update_hash_table(newelf, /* new ELF */ 749 elf, /* old ELF */ 750 shdr_info[cnt].idx, /* hash table index */ 751 shdr_info + symtabidx); 752 } /* if SHT_REL else if SHT_HASH ... */ 753 else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) 754 { 755 /* The symbol table's sh_link field contains the index of the 756 strings table for this symbol table. We want to find the 757 index of the section in the shdr_info[] array. That index 758 corresponds to the index of the section in the original ELF file, 759 which is why we look at shdr_info[cnt].old_shdr and not 760 shdr_info[cnt].shdr. 761 */ 762 763 int symstrndx = shdr_info[cnt].old_shdr.sh_link; 764 INFO("Updating [%s] (symbol-strings-section data for [%s]).\n", 765 shdr_info[symstrndx].name, 766 shdr_info[cnt].name); 767 ASSERT(shdr_info[symstrndx].newscn); 768 size_t new_symstrndx = elf_ndxscn(shdr_info[symstrndx].newscn); 769 Elf_Data *newdata = elf_getdata(shdr_info[symstrndx].newscn, NULL); 770 ASSERT(NULL != newdata); 771 INFO("\tbefore update:\n" 772 "\t\tbuffer: %p\n" 773 "\t\tsize: %d\n", 774 newdata->d_buf, 775 newdata->d_size); 776 ASSERT(shdr_info[cnt].dynsymst); 777 ebl_strtabfinalize (shdr_info[cnt].dynsymst, newdata); 778 INFO("\tafter update:\n" 779 "\t\tbuffer: %p\n" 780 "\t\tsize: %d\n", 781 newdata->d_buf, 782 newdata->d_size); 783 FAILIF(new_symstrndx != shdr_info[cnt].shdr.sh_link, 784 "The index of the symbol-strings table according to elf_ndxscn() is %d, " 785 "according to shdr_info[] is %d!\n", 786 new_symstrndx, 787 shdr_info[cnt].shdr.sh_link); 788 789 INFO("%d nonprintable\n", 790 dump_hex_buffer(stdout, newdata->d_buf, newdata->d_size, 0)); 791 792 shdr_info[symstrndx].shdr.sh_size = newdata->d_size; 793 FAILIF(!gelf_update_shdr(shdr_info[symstrndx].newscn, 794 &shdr_info[symstrndx].shdr), 795 "Could not update section header for section %s!\n", 796 shdr_info[symstrndx].name); 797 798 /* Now, update the symbol-name offsets. */ 799 { 800 size_t i; 801 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version); 802 for (i = 1; i < shdr_info[cnt].shdr.sh_size / elsize; ++i) { 803 Elf32_Word xshndx; 804 GElf_Sym sym_mem; 805 /* retrieve the symbol information; */ 806 GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data, 807 NULL, i, 808 &sym_mem, &xshndx); 809 ASSERT(sym != NULL); 810 ASSERT(NULL != shdr_info[cnt].symse[i]); 811 /* calculate the new name offset; */ 812 size_t new_st_name = 813 ebl_strtaboffset(shdr_info[cnt].symse[i]); 814 #if 1 815 ASSERT(!strcmp(newdata->d_buf + new_st_name, 816 elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link, 817 sym->st_name))); 818 #endif 819 if (sym_filter && (sym->st_name != new_st_name)) { 820 /* FIXME: For some reason, elf_strptr() does not return the updated 821 string value here. It looks like ebl_strtabfinalize() doesn't 822 update libelf's internal structures well enough for elf_strptr() 823 to work on an ELF file that's being compose. 824 */ 825 INFO("Symbol [%s]'s name (index %d, old value %llx) changes offset: %d -> %d\n", 826 #if 0 827 newdata->d_buf + new_st_name, 828 #else 829 elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link, 830 sym->st_name), 831 #endif 832 i, 833 sym->st_value, 834 sym->st_name, 835 new_st_name); 836 } 837 sym->st_name = new_st_name; 838 /* update the symbol info; */ 839 FAILIF_LIBELF(0 == 840 gelf_update_symshndx( 841 shdr_info[cnt].data, 842 NULL, 843 i, sym, 844 xshndx), 845 gelf_update_symshndx); 846 } /* for each symbol... */ 847 } 848 } 849 850 FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym, 851 "Can't handle SHT_GNU_versym!\n"); 852 FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP, 853 "Can't handle section groups!\n"); 854 } /* for (cnt = 1; cnt < shnum; ++cnt) */ 855 } /* if (symtab_size_changed) */ 856 857 858 range_list_t *old_section_ranges = init_range_list(); 859 range_list_t *section_ranges = NULL; 860 /* Analyze gaps in the ranges before we compact the sections. */ 861 INFO("Analyzing gaps in ranges before compacting sections...\n"); 862 { 863 size_t scnidx; 864 /* Gather the ranges */ 865 for (scnidx = 1; scnidx < shdr_info_len; scnidx++) { 866 if (shdr_info[scnidx].idx > 0) { 867 if (/*shdr_info[scnidx].old_shdr.sh_type != SHT_NOBITS &&*/ 868 shdr_info[scnidx].old_shdr.sh_flags & SHF_ALLOC) { 869 add_unique_range_nosort( 870 old_section_ranges, 871 shdr_info[scnidx].old_shdr.sh_addr, 872 shdr_info[scnidx].old_shdr.sh_size, 873 shdr_info + scnidx, 874 handle_range_error, 875 NULL); 876 } 877 } 878 } 879 sort_ranges(old_section_ranges); 880 #ifdef DEBUG 881 int num_ranges; 882 /* Analyze gaps in the ranges before we compact the sections. */ 883 range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges); 884 if (ranges) { 885 GElf_Off last_end = ranges->start; 886 int i; 887 for (i = 0; i < num_ranges; i++) { 888 shdr_info_t *curr = (shdr_info_t *)ranges[i].user; 889 ASSERT(ranges[i].start >= last_end); 890 int col_before, col_after; 891 INFO("[%016lld, %016lld] %n[%s]%n", 892 ranges[i].start, 893 ranges[i].start + ranges[i].length, 894 &col_before, 895 curr->name, 896 &col_after); 897 if (ranges[i].start > last_end) { 898 shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user; 899 ASSERT(prev && curr); 900 while (col_after++ - col_before < 20) INFO(" "); 901 INFO(" [GAP: %lld bytes with %s]\n", 902 (ranges[i].start - last_end), 903 prev->name); 904 } 905 else INFO("\n"); 906 last_end = ranges[i].start + ranges[i].length; 907 } 908 } 909 #endif/*DEBUG*/ 910 } 911 912 /* Calculate the final section offsets */ 913 INFO("Calculating new section offsets...\n"); 914 section_ranges = update_section_offsets(elf, 915 newelf, 916 phdr_info, 917 shdr_info, 918 shdr_info_len, 919 init_range_list(), 920 adjust_alloc_section_offsets); 921 922 #ifdef DEBUG 923 { 924 /* Analyze gaps in the ranges after we've compacted the sections. */ 925 int num_ranges; 926 range_t *ranges = get_sorted_ranges(section_ranges, &num_ranges); 927 if (ranges) { 928 int last_end = ranges->start; 929 int i; 930 for (i = 0; i < num_ranges; i++) { 931 shdr_info_t *curr = (shdr_info_t *)ranges[i].user; 932 ASSERT(ranges[i].start >= last_end); 933 int col_before, col_after; 934 INFO("[%016lld, %016lld] %n[%s]%n", 935 ranges[i].start, 936 ranges[i].start + ranges[i].length, 937 &col_before, 938 curr->name, 939 &col_after); 940 if (ranges[i].start > last_end) { 941 shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user; 942 ASSERT(prev && curr); 943 while (col_after++ - col_before < 20) INFO(" "); 944 INFO(" [GAP: %lld bytes with %s]\n", 945 (ranges[i].start - last_end), 946 prev->name); 947 } 948 else INFO("\n"); 949 last_end = ranges[i].start + ranges[i].length; 950 } 951 } 952 } 953 #endif 954 955 { 956 /* Now that we have modified the section offsets, we need to scan the 957 symbol tables once again and update their st_value fields. A symbol's 958 st_value field (in a shared library) contains the virtual address of the 959 symbol. For each symbol we encounter, we look up the section it was in. 960 If that section's virtual address has changed, then we calculate the 961 delta and update the symbol. 962 */ 963 964 #if 0 965 { 966 /* for debugging: Print out all sections and their data pointers and 967 sizes. */ 968 int i = 1; 969 for (; i < shdr_info_len; i++) { 970 PRINT("%8d: %-15s: %2lld %8lld %08lx (%08lx:%8d) %08lx (%08lx:%8d)\n", 971 i, 972 shdr_info[i].name, 973 shdr_info[i].shdr.sh_entsize, 974 shdr_info[i].shdr.sh_addralign, 975 (long)shdr_info[i].data, 976 (long)(shdr_info[i].data ? shdr_info[i].data->d_buf : 0), 977 (shdr_info[i].data ? shdr_info[i].data->d_size : 0), 978 (long)shdr_info[i].newdata, 979 (long)(shdr_info[i].newdata ? shdr_info[i].newdata->d_buf : 0), 980 (shdr_info[i].newdata ? shdr_info[i].newdata->d_size : 0)); 981 if (!strcmp(shdr_info[i].name, ".got") /* || 982 !strcmp(shdr_info[i].name, ".plt") */) { 983 dump_hex_buffer(stdout, 984 shdr_info[i].newdata->d_buf, 985 shdr_info[i].newdata->d_size, 986 shdr_info[i].shdr.sh_entsize); 987 } 988 } 989 } 990 #endif 991 992 INFO("Updating symbol values...\n"); 993 update_symbol_values(elf, ehdr, newelf, shdr_info, shdr_info_len, 994 shady, 995 dynamic_idx); 996 997 /* If we are not stripping the debug sections, then we need to adjust 998 * them accordingly, so that the new ELF file is actually debuggable. 999 * For that glorios reason, we call update_dwarf(). Note that 1000 * update_dwarf() won't do anything if there, in fact, no debug 1001 * sections to speak of. 1002 */ 1003 1004 INFO("Updating DWARF records...\n"); 1005 int num_total_dwarf_patches = 0, num_failed_dwarf_patches = 0; 1006 update_dwarf_if_necessary( 1007 elf, ehdr, newelf, 1008 shdr_info, shdr_info_len, 1009 &num_total_dwarf_patches, &num_failed_dwarf_patches); 1010 INFO("DWARF: %-15s: total %8d failed %8d.\n", elf_name, num_total_dwarf_patches, num_failed_dwarf_patches); 1011 1012 /* Adjust the program-header table. Since the file offsets of the various 1013 sections may have changed, the file offsets of their containing segments 1014 must change as well. We update those offsets in the loop below. 1015 */ 1016 { 1017 INFO("Adjusting program-header table...\n"); 1018 int pi; /* program-header index */ 1019 for (pi = 0; pi < ehdr->e_phnum; ++pi) { 1020 /* Print the segment number. */ 1021 INFO("\t%2.2zu\t", pi); 1022 INFO("PT_ header type: %d", phdr_info[pi].p_type); 1023 if (phdr_info[pi].p_type == PT_NULL) { 1024 INFO(" PT_NULL (skip)\n"); 1025 } 1026 else if (phdr_info[pi].p_type == PT_PHDR) { 1027 INFO(" PT_PHDR\n"); 1028 ASSERT(phdr_info[pi].p_memsz == phdr_info[pi].p_filesz); 1029 /* Although adjust_elf() does not remove program-header entries, 1030 we perform this update here because I've seen object files 1031 whose PHDR table is bigger by one element than it should be. 1032 Here we check and correct the size, if necessary. 1033 */ 1034 if (phdr_info[pi].p_memsz != ehdr->e_phentsize * ehdr->e_phnum) { 1035 ASSERT(phdr_info[pi].p_memsz > ehdr->e_phentsize * ehdr->e_phnum); 1036 INFO("WARNING: PT_PHDR file and memory sizes are incorrect (%ld instead of %ld). Correcting.\n", 1037 (long)phdr_info[pi].p_memsz, 1038 (long)(ehdr->e_phentsize * ehdr->e_phnum)); 1039 phdr_info[pi].p_memsz = ehdr->e_phentsize * ehdr->e_phnum; 1040 phdr_info[pi].p_filesz = phdr_info[pi].p_memsz; 1041 } 1042 } 1043 else { 1044 1045 /* Go over the section array and find which section's offset 1046 field matches this program header's, and update the program 1047 header's offset to reflect the new value. 1048 */ 1049 Elf64_Off file_end, mem_end; 1050 Elf64_Off new_phdr_offset = 1051 section_to_header_mapping(elf, pi, 1052 shdr_info, shdr_info_len, 1053 &file_end, 1054 &mem_end); 1055 1056 if (new_phdr_offset == (Elf64_Off)-1) { 1057 INFO("PT_ header type: %d does not contain any sections.\n", 1058 phdr_info[pi].p_type); 1059 /* Move to the next program header. */ 1060 FAILIF_LIBELF(gelf_update_phdr (newelf, pi, &phdr_info[pi]) == 0, 1061 gelf_update_phdr); 1062 continue; 1063 } 1064 1065 /* Alignments of 0 and 1 mean nothing. Higher alignments are 1066 interpreted as powers of 2. */ 1067 if (phdr_info[pi].p_align > 1) { 1068 INFO("\t\tapplying alignment of 0x%llx to new offset %lld\n", 1069 phdr_info[pi].p_align, 1070 new_phdr_offset); 1071 new_phdr_offset &= ~(phdr_info[pi].p_align - 1); 1072 } 1073 1074 Elf32_Sxword delta = new_phdr_offset - phdr_info[pi].p_offset; 1075 1076 INFO("\t\tnew offset %lld (was %lld)\n", 1077 new_phdr_offset, 1078 phdr_info[pi].p_offset); 1079 1080 phdr_info[pi].p_offset = new_phdr_offset; 1081 1082 INFO("\t\tnew vaddr 0x%llx (was 0x%llx)\n", 1083 phdr_info[pi].p_vaddr + delta, 1084 phdr_info[pi].p_vaddr); 1085 phdr_info[pi].p_vaddr += delta; 1086 1087 INFO("\t\tnew paddr 0x%llx (was 0x%llx)\n", 1088 phdr_info[pi].p_paddr + delta, 1089 phdr_info[pi].p_paddr); 1090 phdr_info[pi].p_paddr += delta; 1091 1092 INFO("\t\tnew mem size %lld (was %lld)\n", 1093 mem_end - new_phdr_offset, 1094 phdr_info[pi].p_memsz); 1095 //phdr_info[pi].p_memsz = mem_end - new_phdr_offset; 1096 phdr_info[pi].p_memsz = mem_end - phdr_info[pi].p_vaddr; 1097 1098 INFO("\t\tnew file size %lld (was %lld)\n", 1099 file_end - new_phdr_offset, 1100 phdr_info[pi].p_filesz); 1101 //phdr_info[pi].p_filesz = file_end - new_phdr_offset; 1102 phdr_info[pi].p_filesz = file_end - phdr_info[pi].p_offset; 1103 } 1104 1105 FAILIF_LIBELF(gelf_update_phdr (newelf, pi, &phdr_info[pi]) == 0, 1106 gelf_update_phdr); 1107 } 1108 } 1109 1110 if (dynamic_idx >= 0) { 1111 /* NOTE: dynamic_idx is the index of .dynamic section in the shdr_info[] array, NOT the 1112 index of the section in the ELF file! 1113 */ 1114 adjust_dynamic_segment_offsets(elf, ebl, 1115 newelf, 1116 dynamic_idx, 1117 shdr_info, 1118 shdr_info_len); 1119 } 1120 else INFO("There is no dynamic section in this file.\n"); 1121 1122 /* Walk the relocation sections (again). This time, update offsets of the 1123 relocation entries. Note that there is an implication here that the 1124 offsets are virual addresses, because we are handling a shared library! 1125 */ 1126 for (cnt = 1; cnt < shdr_info_len; cnt++) { 1127 /* Note here that we process even those relocation sections that are 1128 * marked for removal. Normally, we wouldn't need to do this, but 1129 * in the case where we run adjust_elf() after a dry run of 1130 * prelink() (see apriori), we still want to update the relocation 1131 * offsets because those will be picked up by the second run of 1132 * prelink(). If this all seems too cryptic, go yell at Iliyan 1133 * Malchev. 1134 */ 1135 if (/* shdr_info[cnt].idx > 0 && */ 1136 (shdr_info[cnt].shdr.sh_type == SHT_REL || 1137 shdr_info[cnt].shdr.sh_type == SHT_RELA)) 1138 { 1139 int hacked = shdr_info[cnt].idx == 0; 1140 Elf_Data *data; 1141 if (hacked) { 1142 /* This doesn't work! elf_ndxscn(shdr_info[cnt].scn) will return the section number 1143 of the new sectin that has moved into this slot. */ 1144 shdr_info[cnt].idx = elf_ndxscn(shdr_info[cnt].scn); 1145 data = elf_getdata (elf_getscn (elf, shdr_info[cnt].idx), NULL); 1146 INFO("PRELINKER HACK: Temporarily restoring index of to-be-removed section [%s] to %d.\n", 1147 shdr_info[cnt].name, 1148 shdr_info[cnt].idx); 1149 } 1150 else 1151 data = elf_getdata (elf_getscn (newelf, shdr_info[cnt].idx), NULL); 1152 1153 update_relocations_section_offsets(newelf, elf, ebl, 1154 shdr_info, shdr_info_len, 1155 shdr_info + cnt, 1156 data, 1157 old_section_ranges); 1158 if (hacked) { 1159 INFO("PRELINKER HACK: Done with hack, marking section [%s] for removal again.\n", 1160 shdr_info[cnt].name); 1161 shdr_info[cnt].idx = 0; 1162 } 1163 } 1164 } 1165 } 1166 1167 /* Finally finish the ELF header. Fill in the fields not handled by 1168 libelf from the old file. */ 1169 { 1170 GElf_Ehdr *newehdr, newehdr_mem; 1171 newehdr = gelf_getehdr (newelf, &newehdr_mem); 1172 FAILIF_LIBELF(newehdr == NULL, gelf_getehdr); 1173 1174 INFO("Updating ELF header.\n"); 1175 1176 memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT); 1177 newehdr->e_type = ehdr->e_type; 1178 newehdr->e_machine = ehdr->e_machine; 1179 newehdr->e_version = ehdr->e_version; 1180 newehdr->e_entry = ehdr->e_entry; 1181 newehdr->e_flags = ehdr->e_flags; 1182 newehdr->e_phoff = ehdr->e_phoff; 1183 1184 /* We need to position the section header table. */ 1185 { 1186 const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT); 1187 newehdr->e_shoff = get_last_address(section_ranges); 1188 newehdr->e_shoff += offsize - 1; 1189 newehdr->e_shoff &= ~((GElf_Off) (offsize - 1)); 1190 newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT); 1191 INFO("\tsetting section-header-table offset to %lld\n", 1192 newehdr->e_shoff); 1193 } 1194 1195 if (rebuild_shstrtab) { 1196 /* If we are rebuilding the section-headers string table, then 1197 the new index must not be zero. This is to guard against 1198 code breakage resulting from rebuild_shstrtab and shdridx 1199 somehow getting out of sync. */ 1200 ASSERT(shdridx); 1201 /* The new section header string table index. */ 1202 FAILIF(!(shdr_info[shdridx].idx < SHN_HIRESERVE) && 1203 likely (shdr_info[shdridx].idx != SHN_XINDEX), 1204 "Can't handle extended section indices!\n"); 1205 } 1206 1207 INFO("Index of shstrtab is now %d (was %d).\n", 1208 shdr_info[shdridx].idx, 1209 ehdr->e_shstrndx); 1210 newehdr->e_shstrndx = shdr_info[shdridx].idx; 1211 1212 FAILIF_LIBELF(gelf_update_ehdr(newelf, newehdr) == 0, gelf_update_ehdr); 1213 } 1214 if (section_ranges != NULL) destroy_range_list(section_ranges); 1215 destroy_range_list(old_section_ranges); 1216 1217 #ifdef DEBUG 1218 verify_elf (ehdr, shdr_info, shdr_info_len, phdr_info); 1219 #endif 1220 1221 } 1222 1223 static void update_hash_table(Elf *newelf, Elf *elf, 1224 Elf32_Word hash_scn_idx, 1225 shdr_info_t *symtab_info) { 1226 GElf_Shdr shdr_mem, *shdr = NULL; 1227 Elf32_Word *chain; 1228 Elf32_Word nbucket; 1229 1230 /* The hash table section and data in the new file. */ 1231 Elf_Scn *hashscn = elf_getscn (newelf, hash_scn_idx); 1232 ASSERT(hashscn != NULL); 1233 Elf_Data *hashd = elf_getdata (hashscn, NULL); 1234 ASSERT (hashd != NULL); 1235 Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf; /* Sane arches first. */ 1236 1237 /* The symbol table data. */ 1238 Elf_Data *symd = elf_getdata (elf_getscn (newelf, symtab_info->idx), NULL); 1239 ASSERT (symd != NULL); 1240 1241 GElf_Ehdr ehdr_mem; 1242 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 1243 FAILIF_LIBELF(NULL == ehdr, gelf_getehdr); 1244 size_t strshndx = symtab_info->old_shdr.sh_link; 1245 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, 1246 ehdr->e_version); 1247 1248 /* Convert to the correct byte order. */ 1249 FAILIF_LIBELF(gelf_xlatetom (newelf, hashd, hashd, 1250 BYTE_ORDER == LITTLE_ENDIAN 1251 ? ELFDATA2LSB : ELFDATA2MSB) == NULL, 1252 gelf_xlatetom); 1253 1254 /* Adjust the nchain value. The symbol table size changed. We keep the 1255 same size for the bucket array. */ 1256 INFO("hash table: buckets: %d (no change).\n", bucket[0]); 1257 INFO("hash table: chains: %d (was %d).\n", 1258 symd->d_size / elsize, 1259 bucket[1]); 1260 bucket[1] = symd->d_size / elsize; 1261 nbucket = bucket[0]; 1262 bucket += 2; 1263 chain = bucket + nbucket; 1264 1265 /* New size of the section. */ 1266 shdr = gelf_getshdr (hashscn, &shdr_mem); 1267 ASSERT(shdr->sh_type == SHT_HASH); 1268 shdr->sh_size = (2 + symd->d_size / elsize + nbucket) * sizeof (Elf32_Word); 1269 INFO("hash table: size %lld (was %d) bytes.\n", 1270 shdr->sh_size, 1271 hashd->d_size); 1272 hashd->d_size = shdr->sh_size; 1273 (void)gelf_update_shdr (hashscn, shdr); 1274 1275 /* Clear the arrays. */ 1276 memset (bucket, '\0', 1277 (symd->d_size / elsize + nbucket) 1278 * sizeof (Elf32_Word)); 1279 1280 size_t inner; 1281 for (inner = symtab_info->shdr.sh_info; 1282 inner < symd->d_size / elsize; 1283 ++inner) { 1284 const char *name; 1285 GElf_Sym sym_mem; 1286 GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem); 1287 ASSERT (sym != NULL); 1288 1289 name = elf_strptr (elf, strshndx, sym->st_name); 1290 ASSERT (name != NULL); 1291 size_t hidx = elf_hash (name) % nbucket; 1292 1293 if (bucket[hidx] == 0) 1294 bucket[hidx] = inner; 1295 else { 1296 hidx = bucket[hidx]; 1297 while (chain[hidx] != 0) 1298 hidx = chain[hidx]; 1299 chain[hidx] = inner; 1300 } 1301 } 1302 1303 /* Convert back to the file byte order. */ 1304 FAILIF_LIBELF(gelf_xlatetof (newelf, hashd, hashd, 1305 BYTE_ORDER == LITTLE_ENDIAN 1306 ? ELFDATA2LSB : ELFDATA2MSB) == NULL, 1307 gelf_xlatetof); 1308 } 1309 1310 /* This function updates the symbol indices of relocation entries. It does not 1311 update the section offsets of those entries. 1312 */ 1313 static void update_relocations_section_symbol_references( 1314 Elf *newelf, Elf *elf __attribute__((unused)), 1315 shdr_info_t *info, 1316 int info_len __attribute__((unused)), 1317 shdr_info_t *relsect_info, 1318 Elf32_Word *newsymidx) 1319 { 1320 /* Get this relocation section's data */ 1321 Elf_Data *d = elf_getdata (elf_getscn (newelf, relsect_info->idx), NULL); 1322 ASSERT (d != NULL); 1323 ASSERT (d->d_size == relsect_info->shdr.sh_size); 1324 1325 size_t old_nrels = 1326 relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize; 1327 size_t new_nrels = 1328 relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize; 1329 1330 size_t nrels = new_nrels; 1331 if (relsect_info->use_old_shdr_for_relocation_calculations) { 1332 nrels = old_nrels; 1333 /* Now, we update d->d_size to point to the old size in order to 1334 prevent gelf_update_rel() and gelf_update_rela() from returning 1335 an error. We restore the value at the end of the function. 1336 */ 1337 d->d_size = old_nrels * relsect_info->shdr.sh_entsize; 1338 } 1339 1340 /* Now, walk the relocations one by one. For each relocation, 1341 check to see whether the symbol it refers to has a new 1342 index in the symbol table, and if so--update it. We know 1343 if a symbol's index has changed when we look up that 1344 the newsymidx[] array at the old index. If the value at that 1345 location is different from the array index, then the 1346 symbol's index has changed; otherwise, it remained the same. 1347 */ 1348 INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n", 1349 nrels, 1350 relsect_info->name, 1351 (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"), 1352 old_nrels, new_nrels); 1353 1354 size_t relidx, newidx; 1355 if (relsect_info->shdr.sh_type == SHT_REL) { 1356 for (newidx = relidx = 0; relidx < nrels; ++relidx) { 1357 GElf_Rel rel_mem; 1358 FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL, 1359 gelf_getrel); 1360 size_t symidx = GELF_R_SYM (rel_mem.r_info); 1361 if (newsymidx[symidx] != (Elf32_Word)-1) 1362 { 1363 rel_mem.r_info = GELF_R_INFO (newsymidx[symidx], 1364 GELF_R_TYPE (rel_mem.r_info)); 1365 FAILIF_LIBELF(gelf_update_rel (d, newidx, &rel_mem) == 0, 1366 gelf_update_rel); 1367 newidx++; 1368 } 1369 else { 1370 INFO("Discarding REL entry for symbol [%d], section [%d]\n", 1371 symidx, 1372 relsect_info->shdr.sh_info); 1373 } 1374 } /* for each rel entry... */ 1375 } else { 1376 for (newidx = relidx = 0; relidx < nrels; ++relidx) { 1377 GElf_Rela rel_mem; 1378 FAILIF_LIBELF(gelf_getrela (d, relidx, &rel_mem) == NULL, 1379 gelf_getrela); 1380 size_t symidx = GELF_R_SYM (rel_mem.r_info); 1381 if (newsymidx[symidx] != (Elf32_Word)-1) 1382 { 1383 rel_mem.r_info 1384 = GELF_R_INFO (newsymidx[symidx], 1385 GELF_R_TYPE (rel_mem.r_info)); 1386 1387 FAILIF_LIBELF(gelf_update_rela (d, newidx, &rel_mem) == 0, 1388 gelf_update_rela); 1389 newidx++; 1390 } 1391 else { 1392 INFO("Discarding RELA entry for symbol [%d], section [%d]\n", 1393 symidx, 1394 relsect_info->shdr.sh_info); 1395 } 1396 } /* for each rela entry... */ 1397 } /* if rel else rela */ 1398 1399 if (newidx != relidx) 1400 { 1401 INFO("Shrinking relocation section from %lld to %lld bytes (%d -> %d " 1402 "entries).\n", 1403 relsect_info->shdr.sh_size, 1404 relsect_info->shdr.sh_entsize * newidx, 1405 relidx, 1406 newidx); 1407 1408 d->d_size = relsect_info->shdr.sh_size = 1409 relsect_info->shdr.sh_entsize * newidx; 1410 } else INFO("Relocation section [%s]'s size (relocates: %s(%d), " 1411 "symab: %s(%d)) does not change.\n", 1412 relsect_info->name, 1413 info[relsect_info->shdr.sh_info].name, 1414 relsect_info->shdr.sh_info, 1415 info[relsect_info->shdr.sh_link].name, 1416 relsect_info->shdr.sh_link); 1417 1418 /* Restore d->d_size if necessary. */ 1419 if (relsect_info->use_old_shdr_for_relocation_calculations) 1420 d->d_size = new_nrels * relsect_info->shdr.sh_entsize; 1421 } 1422 1423 static void update_relocations_section_offsets(Elf *newelf __attribute((unused)), Elf *elf, 1424 Ebl *ebl __attribute__((unused)), 1425 shdr_info_t *info, 1426 int info_len __attribute__((unused)), 1427 shdr_info_t *relsect_info, 1428 Elf_Data *d, 1429 range_list_t *old_section_ranges) 1430 { 1431 /* Get this relocation section's data */ 1432 ASSERT (d != NULL); 1433 if (d->d_size != relsect_info->shdr.sh_size) { 1434 /* This is not necessarily a fatal error. In the case where we call adjust_elf() from apriori 1435 (the prelinker), we may call this function for a relocation section that is marked for 1436 removal. We still want to process this relocation section because, even though it is marked 1437 for removal, its relocatin entries will be used by the prelinker to know what to prelink. 1438 Once the prelinker is done, it will call adjust_elf() one more time to actually eliminate the 1439 relocation section. */ 1440 PRINT("WARNING: section size according to section [%s]'s header is %lld, but according to data buffer is %ld.\n", 1441 relsect_info->name, 1442 relsect_info->shdr.sh_size, 1443 d->d_size); 1444 ASSERT((relsect_info->shdr.sh_type == SHT_REL || relsect_info->shdr.sh_type == SHT_RELA) && 1445 relsect_info->use_old_shdr_for_relocation_calculations); 1446 } 1447 1448 size_t old_nrels = 1449 relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize; 1450 size_t new_nrels = 1451 relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize; 1452 1453 size_t nrels = new_nrels; 1454 if (relsect_info->use_old_shdr_for_relocation_calculations) { 1455 nrels = old_nrels; 1456 /* Now, we update d->d_size to point to the old size in order to 1457 prevent gelf_update_rel() and gelf_update_rela() from returning 1458 an error. We restore the value at the end of the function. 1459 */ 1460 d->d_size = old_nrels * relsect_info->shdr.sh_entsize; 1461 } 1462 1463 /* Now, walk the relocations one by one. For each relocation, 1464 check to see whether the symbol it refers to has a new 1465 index in the symbol table, and if so--update it. We know 1466 if a symbol's index has changed when we look up that 1467 the newsymidx[] array at the old index. If the value at that 1468 location is different from the array index, then the 1469 symbol's index has changed; otherwise, it remained the same. 1470 */ 1471 INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n", 1472 nrels, 1473 relsect_info->name, 1474 (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"), 1475 old_nrels, new_nrels); 1476 1477 if (relsect_info->old_shdr.sh_info == 0) { 1478 PRINT("WARNING: Relocation section [%s] relocates the NULL section.\n", 1479 relsect_info->name); 1480 } 1481 else { 1482 FAILIF(info[relsect_info->old_shdr.sh_info].idx == 0, 1483 "Section [%s] relocates section [%s] (index %d), which is being " 1484 "removed!\n", 1485 relsect_info->name, 1486 info[relsect_info->old_shdr.sh_info].name, 1487 relsect_info->old_shdr.sh_info); 1488 } 1489 1490 size_t relidx; 1491 FAILIF(relsect_info->shdr.sh_type == SHT_RELA, 1492 "Can't handle SHT_RELA relocation entries.\n"); 1493 1494 if (relsect_info->shdr.sh_type == SHT_REL) { 1495 for (relidx = 0; relidx < nrels; ++relidx) { 1496 GElf_Rel rel_mem; 1497 FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL, 1498 gelf_getrel); 1499 1500 if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_NONE) 1501 continue; 1502 1503 range_t *old_range = find_range(old_section_ranges, 1504 rel_mem.r_offset); 1505 #if 1 1506 if (NULL == old_range) { 1507 GElf_Sym *sym, sym_mem; 1508 unsigned sym_idx = GELF_R_SYM(rel_mem.r_info); 1509 /* relsect_info->shdr.sh_link is the index of the associated 1510 symbol table. */ 1511 sym = gelf_getsymshndx(info[relsect_info->shdr.sh_link].data, 1512 NULL, 1513 sym_idx, 1514 &sym_mem, 1515 NULL); 1516 /* info[relsect_info->shdr.sh_link].shdr.sh_link is the index 1517 of the string table associated with the symbol table 1518 associated with the relocation section rel_sect. */ 1519 const char *symname = elf_strptr(elf, 1520 info[relsect_info->shdr.sh_link].shdr.sh_link, 1521 sym->st_name); 1522 1523 { 1524 int i = 0; 1525 INFO("ABOUT TO FAIL for symbol [%s]: old section ranges:\n", symname); 1526 1527 int num_ranges; 1528 range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges); 1529 1530 for (; i < num_ranges; i++) { 1531 shdr_info_t *inf = (shdr_info_t *)ranges[i].user; 1532 INFO("\t[%8lld, %8lld] (%8lld bytes) [%8lld, %8lld] (%8lld bytes) [%-15s]\n", 1533 ranges[i].start, 1534 ranges[i].start + ranges[i].length, 1535 ranges[i].length, 1536 inf->old_shdr.sh_addr, 1537 inf->old_shdr.sh_addr + inf->old_shdr.sh_size, 1538 inf->old_shdr.sh_size, 1539 inf->name); 1540 } 1541 INFO("\n"); 1542 } 1543 1544 FAILIF(1, 1545 "No range matches relocation entry value 0x%llx (%d) [%s]!\n", 1546 rel_mem.r_offset, 1547 rel_mem.r_offset, 1548 symname); 1549 } 1550 #else 1551 FAILIF(NULL == old_range, 1552 "No range matches relocation entry value 0x%llx!\n", 1553 rel_mem.r_offset); 1554 #endif 1555 ASSERT(old_range->start <= rel_mem.r_offset && 1556 rel_mem.r_offset < old_range->start + old_range->length); 1557 ASSERT(old_range->user); 1558 shdr_info_t *old_range_info = (shdr_info_t *)old_range->user; 1559 ASSERT(old_range_info->idx > 0); 1560 if (relsect_info->old_shdr.sh_info && 1561 old_range_info->idx != relsect_info->old_shdr.sh_info) { 1562 PRINT("Relocation offset 0x%llx does not match section [%s] " 1563 "but section [%s]!\n", 1564 rel_mem.r_offset, 1565 info[relsect_info->old_shdr.sh_info].name, 1566 old_range_info->name); 1567 } 1568 1569 #if 0 /* This is true only for shared libraries, but not for executables */ 1570 ASSERT(old_range_info->shdr.sh_addr == old_range_info->shdr.sh_offset); 1571 ASSERT(old_range_info->old_shdr.sh_addr == old_range_info->old_shdr.sh_offset); 1572 #endif 1573 Elf64_Sxword delta = 1574 old_range_info->shdr.sh_addr - old_range_info->old_shdr.sh_addr; 1575 1576 if (delta) { 1577 extern int verbose_flag; 1578 /* Print out some info about the relocation entry we are 1579 modifying. */ 1580 if (unlikely(verbose_flag)) { 1581 /* Get associated (new) symbol table. */ 1582 Elf64_Word symtab = relsect_info->shdr.sh_link; 1583 /* Get the symbol that is being relocated. */ 1584 size_t symidx = GELF_R_SYM (rel_mem.r_info); 1585 GElf_Sym sym_mem, *sym; 1586 /* Since by now we've already updated the symbol index, 1587 we need to retrieve the symbol from the new symbol table. 1588 */ 1589 sym = gelf_getsymshndx (elf_getdata(info[symtab].newscn, NULL), 1590 NULL, 1591 symidx, &sym_mem, NULL); 1592 FAILIF_LIBELF(NULL == sym, gelf_getsymshndx); 1593 char buf[64]; 1594 INFO("\t%02d (%-15s) off 0x%llx -> 0x%llx (%lld) (relocates [%s:(%d)%s])\n", 1595 (unsigned)GELF_R_TYPE(rel_mem.r_info), 1596 ebl_reloc_type_name(ebl, 1597 GELF_R_TYPE(rel_mem.r_info), 1598 buf, 1599 sizeof(buf)), 1600 rel_mem.r_offset, rel_mem.r_offset + delta, delta, 1601 old_range_info->name, 1602 symidx, 1603 #if ELF_STRPTR_IS_BROKEN 1604 /* libelf does not keep track of changes very well. 1605 Looks like, if you use elf_strptr() on a file that 1606 has not been updated yet, you get bogus results. */ 1607 ((char *)info[info[symtab].old_shdr.sh_link]. 1608 newdata->d_buf) + sym->st_name 1609 #else 1610 elf_strptr(newelf, 1611 info[symtab].shdr.sh_link, 1612 sym->st_name) 1613 #endif 1614 ); 1615 } /* if (verbose_flag) */ 1616 1617 rel_mem.r_offset += delta; 1618 FAILIF_LIBELF(gelf_update_rel (d, relidx, &rel_mem) == 0, 1619 gelf_update_rel); 1620 1621 #ifdef ARM_SPECIFIC_HACKS 1622 if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_RELATIVE) { 1623 FAILIF(GELF_R_SYM(rel_mem.r_info) != 0, 1624 "Can't handle relocation!\n"); 1625 /* From the ARM documentation: "when the symbol is zero, 1626 the R_ARM_RELATIVE entry resolves to the difference 1627 between the address at which the segment being 1628 relocated was loaded and the address at which it 1629 was linked." 1630 */ 1631 1632 int *ptr = 1633 (int *)(((char *)old_range_info->newdata->d_buf) + 1634 (rel_mem.r_offset - 1635 old_range_info->shdr.sh_addr)); 1636 *ptr += (int)delta; 1637 1638 } 1639 #endif 1640 } /* if (delta) */ 1641 } /* for each rel entry... */ 1642 } 1643 1644 /* Restore d->d_size if necessary. */ 1645 if (relsect_info->use_old_shdr_for_relocation_calculations) 1646 d->d_size = new_nrels * relsect_info->shdr.sh_entsize; 1647 } 1648 1649 static inline 1650 Elf_Data *create_section_data(shdr_info_t *info, Elf_Scn *scn) 1651 { 1652 Elf_Data *newdata = NULL; 1653 1654 if (info->data == NULL) { 1655 info->data = elf_getdata (info->scn, NULL); 1656 FAILIF_LIBELF(NULL == info->data, elf_getdata); 1657 INFO("\t\tcopying data from original section (%d bytes).\n", 1658 info->data->d_size); 1659 /* Set the data. This is done by copying from the old file. */ 1660 newdata = elf_newdata (scn); 1661 FAILIF_LIBELF(newdata == NULL, elf_newdata); 1662 /* Copy the structure. Note that the data buffer pointer gets 1663 copied, but the buffer itself does not. */ 1664 *newdata = *info->data; 1665 #if COPY_SECTION_DATA_BUFFER 1666 if (info->data->d_buf != NULL) { 1667 newdata->d_buf = MALLOC(newdata->d_size); 1668 memcpy(newdata->d_buf, info->data->d_buf, newdata->d_size); 1669 } 1670 #endif 1671 } else { 1672 INFO("\t\tassigning new data to section (%d bytes).\n", 1673 info->data->d_size); 1674 newdata = info->data; 1675 } 1676 1677 info->newdata = newdata; 1678 return newdata; 1679 } 1680 1681 #if 0 1682 static void print_shdr_array(shdr_info_t *info, int num_entries) { 1683 extern int verbose_flag; 1684 if (verbose_flag) { 1685 int i; 1686 for (i = 0; i < num_entries; i++) { 1687 INFO("%03d:" 1688 "\tname [%s]\n" 1689 "\tidx [%d]\n", 1690 i, info[i].name, info[i].idx); 1691 } 1692 } /* if (verbose_flag) */ 1693 } 1694 #endif 1695 1696 static size_t do_update_dyn_entry_address(Elf *elf, 1697 GElf_Dyn *dyn, 1698 shdr_info_t *shdr_info, 1699 int shdr_info_len, 1700 int newline) 1701 { 1702 size_t scnidx = 0; 1703 INFO("%#0*llx", 1704 gelf_getclass (elf) == ELFCLASS32 ? 10 : 18, 1705 dyn->d_un.d_val); 1706 for (scnidx = 1; scnidx < shdr_info_len; scnidx++) { 1707 if (shdr_info[scnidx].old_shdr.sh_addr == dyn->d_un.d_ptr) { 1708 if (shdr_info[scnidx].idx > 0) { 1709 INFO(" (updating to 0x%08llx per section %d (shdr_info[] index %d): [%s])", 1710 shdr_info[scnidx].shdr.sh_addr, 1711 shdr_info[scnidx].idx, 1712 scnidx, 1713 shdr_info[scnidx].name); 1714 dyn->d_un.d_ptr = shdr_info[scnidx].shdr.sh_addr; 1715 break; 1716 } 1717 else { 1718 /* FIXME: This should be more intelligent. What if there is more than one section that fits the 1719 dynamic entry, and just the first such is being removed? We should keep on searching here. 1720 */ 1721 INFO(" (Setting to ZERO per section (shdr_info[] index %d) [%s], which is being removed)", 1722 scnidx, 1723 shdr_info[scnidx].name); 1724 dyn->d_un.d_ptr = 0; 1725 break; 1726 } 1727 } 1728 } 1729 if (newline) INFO("\n"); 1730 return scnidx == shdr_info_len ? 0 : scnidx; 1731 } 1732 1733 static inline size_t update_dyn_entry_address(Elf *elf, 1734 GElf_Dyn *dyn, 1735 shdr_info_t *shdr_info, 1736 int shdr_info_len) 1737 { 1738 return do_update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len, 1); 1739 } 1740 1741 static void update_dyn_entry_address_and_size(Elf *elf, Ebl *oldebl, 1742 GElf_Dyn *dyn, 1743 shdr_info_t *shdr_info, 1744 int shdr_info_len, 1745 Elf_Data *dyn_data, 1746 size_t *dyn_size_entries, 1747 int dyn_entry_idx) 1748 { 1749 size_t scnidx = do_update_dyn_entry_address(elf, dyn, 1750 shdr_info, shdr_info_len, 1751 0); 1752 if (scnidx) { 1753 char buf[64]; 1754 INFO(" (affects tag %s)", 1755 ebl_dynamic_tag_name(oldebl, dyn_entry_idx, 1756 buf, sizeof (buf))); 1757 if (dyn_size_entries[dyn_entry_idx]) { 1758 /* We previously encountered this size entry, and because 1759 we did not know which section would affect it, we saved its 1760 index in the dyn_size_entries[] array so that we can update 1761 the entry when we do know. Now we know that the field 1762 shdr_info[scnidx].shdr.sh_size contains that new value. 1763 */ 1764 GElf_Dyn *szdyn, szdyn_mem; 1765 1766 szdyn = gelf_getdyn (dyn_data, 1767 dyn_size_entries[dyn_entry_idx], 1768 &szdyn_mem); 1769 FAILIF_LIBELF(NULL == szdyn, gelf_getdyn); 1770 ASSERT(szdyn->d_tag == dyn_entry_idx); 1771 1772 INFO("\n (!)\t%-17s completing deferred update (%lld -> %lld bytes)" 1773 " per section %d [%s]", 1774 ebl_dynamic_tag_name (oldebl, szdyn->d_tag, 1775 buf, sizeof (buf)), 1776 szdyn->d_un.d_val, 1777 shdr_info[scnidx].shdr.sh_size, 1778 shdr_info[scnidx].idx, 1779 shdr_info[scnidx].name); 1780 1781 szdyn->d_un.d_val = shdr_info[scnidx].shdr.sh_size; 1782 FAILIF_LIBELF(0 == gelf_update_dyn(dyn_data, 1783 dyn_size_entries[dyn_entry_idx], 1784 szdyn), 1785 gelf_update_dyn); 1786 #ifdef DEBUG 1787 dyn_size_entries[dyn_entry_idx] = -1; 1788 #endif 1789 } 1790 else dyn_size_entries[dyn_entry_idx] = scnidx; 1791 } /* if (scnidx) */ 1792 1793 INFO("\n"); 1794 } 1795 1796 static void do_build_dynamic_segment_strings(Elf *elf, Ebl *oldebl, 1797 int dynidx, /* index of .dynamic section */ 1798 int symtabidx, /* index of symbol table section */ 1799 shdr_info_t *shdr_info, 1800 int shdr_info_len __attribute__((unused)), 1801 bool print_strings_only) 1802 { 1803 Elf_Scn *dynscn = elf_getscn(elf, dynidx); 1804 FAILIF_LIBELF(NULL == dynscn, elf_getscn); 1805 Elf_Data *data = elf_getdata (dynscn, NULL); 1806 ASSERT(data != NULL); 1807 1808 size_t cnt; 1809 1810 if (!print_strings_only) { 1811 /* Allocate an array of string-offset structures. */ 1812 shdr_info[dynidx].symse = 1813 (struct Ebl_Strent **)CALLOC( 1814 shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize, 1815 sizeof(struct Ebl_Strent *)); 1816 } 1817 1818 for (cnt = 0; 1819 cnt < shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize; 1820 ++cnt) 1821 { 1822 char buf[64]; 1823 GElf_Dyn dynmem; 1824 GElf_Dyn *dyn; 1825 1826 dyn = gelf_getdyn (data, cnt, &dynmem); 1827 FAILIF_LIBELF(NULL == dyn, gelf_getdyn); 1828 1829 switch (dyn->d_tag) { 1830 case DT_NEEDED: 1831 case DT_SONAME: 1832 case DT_RPATH: 1833 case DT_RUNPATH: 1834 { 1835 const char *str = 1836 elf_strptr (elf, 1837 shdr_info[dynidx].shdr.sh_link, 1838 dyn->d_un.d_val); 1839 ASSERT(str != NULL); 1840 INFO("\t\t\t%-17s: ", 1841 ebl_dynamic_tag_name (oldebl, 1842 dyn->d_tag, 1843 buf, sizeof (buf))); 1844 INFO("[%s] (offset %ld)\n", str, dyn->d_un.d_val); 1845 if (!print_strings_only) { 1846 /* We append the strings to the string table belonging to the 1847 dynamic-symbol-table section. We keep the dynsymst handle 1848 for the strings section in the shdr_info[] entry for the 1849 dynamic-sybmol table. Confusing, I know. 1850 */ 1851 ASSERT(shdr_info[symtabidx].dynsymst); 1852 /* The string tables for the symbol table and the .dynamic 1853 section must be the same. 1854 */ 1855 ASSERT(shdr_info[symtabidx].shdr.sh_link == 1856 shdr_info[dynidx].shdr.sh_link); 1857 shdr_info[dynidx].symse[cnt] = 1858 ebl_strtabadd(shdr_info[symtabidx].dynsymst, str?:"", 0); 1859 ASSERT(shdr_info[dynidx].symse[cnt] != NULL); 1860 } 1861 } 1862 break; 1863 default: 1864 break; 1865 } 1866 } /* for (...) */ 1867 } /* build_dynamic_segment_strings() */ 1868 1869 static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl, 1870 int dynidx, /* index of .dynamic section */ 1871 int symtabidx, /* index of symbol table section */ 1872 shdr_info_t *shdr_info, 1873 int shdr_info_len __attribute__((unused))) 1874 { 1875 INFO("\t\tbuilding string offsets for dynamic section [%s], index %d\n", 1876 shdr_info[dynidx].name, 1877 dynidx); 1878 do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx, 1879 shdr_info, shdr_info_len, false); 1880 } 1881 1882 #ifdef DEBUG 1883 static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl, 1884 int dynidx, /* index of .dynamic section */ 1885 int symtabidx, /* index of symbol table section */ 1886 shdr_info_t *shdr_info, 1887 int shdr_info_len __attribute__((unused))) 1888 { 1889 INFO("\t\tprinting string offsets for dynamic section [%s], index %d\n", 1890 shdr_info[dynidx].name, 1891 dynidx); 1892 do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx, 1893 shdr_info, shdr_info_len, true); 1894 } 1895 #endif 1896 1897 static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl, 1898 Elf *newelf __attribute__((unused)), 1899 int dynidx, /* index of .dynamic section in shdr_info[] */ 1900 shdr_info_t *shdr_info, 1901 int shdr_info_len) 1902 { 1903 Elf_Scn *scn = shdr_info[dynidx].newscn; 1904 FAILIF_LIBELF(NULL == scn, elf_getscn); 1905 Elf_Data *data = elf_getdata (scn, NULL); 1906 ASSERT(data != NULL); 1907 1908 size_t cnt; 1909 INFO("Updating dynamic section [%s], index %d\n", 1910 shdr_info[dynidx].name, 1911 dynidx); 1912 1913 size_t *dyn_size_entries = (size_t *)CALLOC(DT_NUM, sizeof(size_t)); 1914 1915 ASSERT(data->d_type == ELF_T_DYN); 1916 1917 for (cnt = 0; cnt < shdr_info[dynidx].shdr.sh_size / shdr_info[dynidx].shdr.sh_entsize; ++cnt) { 1918 char buf[64]; 1919 GElf_Dyn dynmem; 1920 GElf_Dyn *dyn; 1921 1922 dyn = gelf_getdyn (data, cnt, &dynmem); 1923 FAILIF_LIBELF(NULL == dyn, gelf_getdyn); 1924 1925 INFO("\t%-17s ", 1926 ebl_dynamic_tag_name (oldebl, dyn->d_tag, buf, sizeof (buf))); 1927 1928 switch (dyn->d_tag) { 1929 /* Updates to addresses */ 1930 1931 /* We assume that the address entries come before the size entries. 1932 */ 1933 1934 case DT_PLTGOT: 1935 case DT_HASH: 1936 case DT_SYMTAB: 1937 (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len); 1938 break; 1939 case DT_STRTAB: 1940 /* Defer-update DT_STRSZ as well, if not already updated. */ 1941 update_dyn_entry_address_and_size(elf, oldebl, dyn, 1942 shdr_info, shdr_info_len, 1943 data, 1944 dyn_size_entries, 1945 DT_STRSZ); 1946 break; 1947 case DT_RELA: 1948 /* Defer-update DT_RELASZ as well, if not already updated. */ 1949 update_dyn_entry_address_and_size(elf, oldebl, dyn, 1950 shdr_info, shdr_info_len, 1951 data, 1952 dyn_size_entries, 1953 DT_RELASZ); 1954 break; 1955 case DT_REL: 1956 /* Defer-update DT_RELSZ as well, if not already updated. */ 1957 update_dyn_entry_address_and_size(elf, oldebl, dyn, 1958 shdr_info, shdr_info_len, 1959 data, 1960 dyn_size_entries, 1961 DT_RELSZ); 1962 break; 1963 case DT_JMPREL: 1964 /* Defer-update DT_PLTRELSZ as well, if not already updated. */ 1965 update_dyn_entry_address_and_size(elf, oldebl, dyn, 1966 shdr_info, shdr_info_len, 1967 data, 1968 dyn_size_entries, 1969 DT_PLTRELSZ); 1970 break; 1971 case DT_INIT_ARRAY: 1972 case DT_FINI_ARRAY: 1973 case DT_PREINIT_ARRAY: 1974 case DT_INIT: 1975 case DT_FINI: 1976 (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len); 1977 break; 1978 1979 /* Updates to sizes */ 1980 case DT_PLTRELSZ: /* DT_JMPREL or DT_PLTGOT */ 1981 case DT_STRSZ: /* DT_STRTAB */ 1982 case DT_RELSZ: /* DT_REL */ 1983 case DT_RELASZ: /* DR_RELA */ 1984 if (dyn_size_entries[dyn->d_tag] == 0) { 1985 /* We have not yet found the new size for this entry, so we 1986 save the index of the dynamic entry in the dyn_size_entries[] 1987 array. When we find the section affecting this field (in 1988 code above), we will update the entry. 1989 */ 1990 INFO("(!) (deferring update: new value not known yet)\n"); 1991 dyn_size_entries[dyn->d_tag] = cnt; 1992 } 1993 else { 1994 ASSERT(dyn_size_entries[dyn->d_tag] < shdr_info_len); 1995 INFO("%lld (bytes) (updating to %lld bytes " 1996 "per section %d [%s])\n", 1997 dyn->d_un.d_val, 1998 shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size, 1999 shdr_info[dyn_size_entries[dyn->d_tag]].idx, 2000 shdr_info[dyn_size_entries[dyn->d_tag]].name); 2001 dyn->d_un.d_val = 2002 shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size; 2003 #ifdef DEBUG 2004 /* Clear the array so that we know we are done with it. */ 2005 dyn_size_entries[dyn->d_tag] = (size_t)-1; 2006 #endif 2007 } 2008 break; 2009 /* End of updates. */ 2010 2011 case DT_NULL: 2012 case DT_DEBUG: 2013 case DT_BIND_NOW: 2014 case DT_TEXTREL: 2015 /* No further output. */ 2016 INFO("\n"); 2017 break; 2018 2019 /* String-entry updates. */ 2020 case DT_NEEDED: 2021 case DT_SONAME: 2022 case DT_RPATH: 2023 case DT_RUNPATH: 2024 if (shdr_info[dynidx].symse != NULL) 2025 { 2026 Elf64_Xword new_offset = 2027 ebl_strtaboffset(shdr_info[dynidx].symse[cnt]); 2028 INFO("string [%s] offset changes: %lld -> %lld\n", 2029 elf_strptr (elf, 2030 shdr_info[dynidx].shdr.sh_link, 2031 dyn->d_un.d_val), 2032 dyn->d_un.d_val, 2033 new_offset); 2034 dyn->d_un.d_val = new_offset; 2035 FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn), 2036 gelf_update_dyn); 2037 } 2038 else 2039 INFO("string [%s] offset has not changed from %lld, not updating\n", 2040 elf_strptr (elf, 2041 shdr_info[dynidx].shdr.sh_link, 2042 dyn->d_un.d_val), 2043 dyn->d_un.d_val); 2044 break; 2045 2046 case DT_RELAENT: 2047 case DT_SYMENT: 2048 case DT_RELENT: 2049 case DT_PLTPADSZ: 2050 case DT_MOVEENT: 2051 case DT_MOVESZ: 2052 case DT_INIT_ARRAYSZ: 2053 case DT_FINI_ARRAYSZ: 2054 case DT_SYMINSZ: 2055 case DT_SYMINENT: 2056 case DT_GNU_CONFLICTSZ: 2057 case DT_GNU_LIBLISTSZ: 2058 INFO("%lld (bytes)\n", dyn->d_un.d_val); 2059 break; 2060 2061 case DT_VERDEFNUM: 2062 case DT_VERNEEDNUM: 2063 case DT_RELACOUNT: 2064 case DT_RELCOUNT: 2065 INFO("%lld\n", dyn->d_un.d_val); 2066 break; 2067 2068 case DT_PLTREL: /* Specifies whether PLTREL (same as JMPREL) has REL or RELA entries */ 2069 INFO("%s (%d)\n", ebl_dynamic_tag_name (oldebl, dyn->d_un.d_val, NULL, 0), dyn->d_un.d_val); 2070 break; 2071 2072 default: 2073 INFO("%#0*llx\n", 2074 gelf_getclass (elf) == ELFCLASS32 ? 10 : 18, 2075 dyn->d_un.d_val); 2076 break; 2077 } 2078 2079 FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn), 2080 gelf_update_dyn); 2081 } /* for (...) */ 2082 2083 #ifdef DEBUG 2084 if (1) { 2085 int i; 2086 for (i = 0; i < DT_NUM; i++) 2087 ASSERT((ssize_t)dyn_size_entries[i] <= 0); 2088 } 2089 #endif 2090 2091 FREE(dyn_size_entries); 2092 } /* adjust_dynamic_segment_offsets() */ 2093 2094 static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr) 2095 { 2096 if (shdr->sh_size) { 2097 /* Compare allocated sections by VMA, unallocated 2098 sections by file offset. */ 2099 if(shdr->sh_flags & SHF_ALLOC) { 2100 if(shdr->sh_addr >= phdr->p_vaddr 2101 && (shdr->sh_addr + shdr->sh_size 2102 <= phdr->p_vaddr + phdr->p_memsz)) 2103 { 2104 return true; 2105 } 2106 } 2107 else { 2108 if (shdr->sh_offset >= phdr->p_offset 2109 && (shdr->sh_offset + shdr->sh_size 2110 <= phdr->p_offset + phdr->p_filesz)) 2111 { 2112 return true; 2113 } 2114 } 2115 } 2116 2117 return false; 2118 } 2119 2120 static Elf64_Off section_to_header_mapping(Elf *elf, 2121 int phdr_idx, 2122 shdr_info_t *shdr_info, 2123 int num_shdr_info, 2124 Elf64_Off *file_end, 2125 Elf64_Off *mem_end) 2126 { 2127 Elf64_Off start; 2128 GElf_Phdr phdr_mem; 2129 GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_mem); 2130 FAILIF_LIBELF(NULL == phdr, gelf_getphdr); 2131 size_t inner; 2132 2133 FAILIF(phdr->p_type == PT_GNU_RELRO, 2134 "Can't handle segments of type PT_GNU_RELRO!\n"); 2135 2136 /* Iterate over the sections. */ 2137 start = (Elf64_Off)-1; 2138 *file_end = *mem_end = 0; 2139 INFO("\n\t\t"); 2140 for (inner = 1; inner < num_shdr_info; ++inner) 2141 { 2142 if (shdr_info[inner].idx > 0) { 2143 /* Check to see the section is in the segment. We use the old 2144 header because that header contains the old offset and length 2145 information about a section. 2146 */ 2147 if (section_belongs_to_header(&shdr_info[inner].old_shdr, phdr)) 2148 { 2149 INFO("%-17s", shdr_info[inner].name); 2150 #define SECT_MEM_END(s) ((s).sh_addr + (s).sh_size) 2151 if ((shdr_info[inner].shdr.sh_flags & SHF_ALLOC)) { 2152 if (SECT_MEM_END(shdr_info[inner].shdr) > *mem_end) { 2153 INFO("(mem_end 0x%llx --> 0x%llx) ", *mem_end, SECT_MEM_END(shdr_info[inner].shdr)); 2154 *mem_end = SECT_MEM_END(shdr_info[inner].shdr); 2155 } 2156 #undef SECT_MEM_END 2157 #define SECT_FILE_END(s) ((s).sh_offset + (s).sh_size) 2158 if (shdr_info[inner].shdr.sh_type != SHT_NOBITS) { 2159 if (SECT_FILE_END(shdr_info[inner].shdr) > *file_end) { 2160 INFO("(file_end 0x%llx --> 0x%llx) ", *file_end, SECT_FILE_END(shdr_info[inner].shdr)); 2161 *file_end = SECT_FILE_END(shdr_info[inner].shdr); 2162 } 2163 } 2164 #undef SECT_FILE_END 2165 if (shdr_info[inner].shdr.sh_offset < start) { 2166 start = shdr_info[inner].shdr.sh_offset; 2167 } 2168 } /* if section takes space */ 2169 INFO("\n\t\t"); 2170 } 2171 else 2172 INFO("(!) %-17s does not belong\n\t\t", shdr_info[inner].name); 2173 } 2174 else 2175 INFO("(!) %-17s is not considered, it is being removed\n\t\t", shdr_info[inner].name); 2176 } 2177 2178 /* Finish the line. */ 2179 INFO("start: %lld\n", start); 2180 INFO("\t\tends: %lld file, %lld mem\n", *file_end, *mem_end); 2181 2182 return start; 2183 } 2184 2185 static void 2186 update_symbol_values(Elf *elf, GElf_Ehdr *ehdr, 2187 Elf *newelf __attribute__((unused)), 2188 shdr_info_t *shdr_info, 2189 int num_shdr_info, 2190 int shady, 2191 int dynamic_idx) 2192 { 2193 /* Scan the sections, looking for the symbol table. */ 2194 size_t i; 2195 for (i = 1; i < num_shdr_info; i++) { 2196 if (shdr_info[i].idx > 0 && 2197 (shdr_info[i].shdr.sh_type == SHT_SYMTAB || 2198 shdr_info[i].shdr.sh_type == SHT_DYNSYM)) 2199 { 2200 size_t inner; 2201 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version); 2202 Elf_Data *symdata = shdr_info[i].newdata; 2203 /* shdr_info[i].old_shdr.sh_link is the index of the strings table 2204 in the old ELF file. This index still points to the same section 2205 in the shdr_info[] array. The idx field of that entry is that 2206 section's new index. That index must, therefore, be equal to 2207 the new value of sh_link. */ 2208 ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].idx == 2209 shdr_info[i].shdr.sh_link); 2210 ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].data); 2211 2212 INFO("\tupdating symbol values for section [%s]...\n", 2213 shdr_info[i].name); 2214 2215 #if 1 /* DEBUG */ 2216 { 2217 Elf_Scn *symstrscn = elf_getscn(newelf, shdr_info[i].shdr.sh_link); 2218 ASSERT(symstrscn); 2219 Elf_Data *symstrdata = elf_getdata(symstrscn, NULL); 2220 ASSERT(symstrdata); 2221 INFO("%d nonprintable\n", 2222 dump_hex_buffer(stdout, symstrdata->d_buf, symstrdata->d_size, 0)); 2223 } 2224 #endif 2225 2226 INFO("\tnumber of symbols to update: %d (%d bytes)\n", 2227 symdata->d_size / elsize, symdata->d_size); 2228 for (inner = 0; inner < symdata->d_size / elsize; ++inner) 2229 { 2230 GElf_Sym sym_mem; 2231 GElf_Sym *sym; 2232 size_t shnum; 2233 FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum); 2234 2235 sym = gelf_getsymshndx (symdata, NULL, 2236 inner, &sym_mem, NULL); 2237 FAILIF_LIBELF(sym == NULL, gelf_getsymshndx); 2238 2239 #if 0 /* DEBUG */ 2240 if (shdr_info[i].shdr.sh_type == SHT_SYMTAB) { 2241 PRINT("%8d: name %d info %02x other %02x shndx %d size %lld value %lld\n", 2242 inner, 2243 sym->st_info, 2244 sym->st_name, 2245 sym->st_other, 2246 sym->st_shndx, 2247 sym->st_size, 2248 sym->st_value); 2249 } 2250 #endif 2251 2252 size_t scnidx = sym->st_shndx; 2253 FAILIF(scnidx == SHN_XINDEX, 2254 "Can't handle SHN_XINDEX!\n"); 2255 2256 char *symname = NULL; 2257 { 2258 #if ELF_STRPTR_IS_BROKEN 2259 Elf_Scn *symstrscn = elf_getscn(newelf, shdr_info[i].shdr.sh_link); 2260 ASSERT(symstrscn); 2261 Elf_Data *symstrdata = elf_getdata(symstrscn, NULL); 2262 ASSERT(symstrdata); 2263 symname = symstrdata->d_buf + sym->st_name; 2264 #else 2265 symname = elf_strptr(newelf, 2266 shdr_info[i].shdr.sh_link, 2267 sym->st_name); 2268 #endif 2269 } 2270 2271 extern int verbose_flag; 2272 if (unlikely(verbose_flag)) 2273 { 2274 int c, max = 40; 2275 INFO("%-8d [", inner); 2276 for (c=0; c<max-1; c++) { 2277 if (symname[c]) { 2278 INFO("%c", symname[c]); 2279 } 2280 else break; 2281 } 2282 if (c < max-1) { 2283 while (c++ < max) INFO(" "); 2284 } 2285 else INFO("<"); 2286 INFO("]"); 2287 } /* if (unlikely(verbose_flag)) */ 2288 2289 /* Notice that shdr_info[] is an array whose indices correspond 2290 to the section indices in the original ELF file. Of those 2291 sections, some have been discarded, and one is moved to the 2292 end of the file--this is section .shstrtab. Of course, no 2293 symbol refers to this section, so it is safe for us to 2294 address sections by their original indices in the 2295 shdr_info[] array directly. 2296 */ 2297 2298 /* Note that we do not skip over the STT_SECTION symbols. Since 2299 they contain the addresses of sections, we update their 2300 values as well. 2301 */ 2302 if (scnidx == SHN_UNDEF) { 2303 INFO(" undefined\n"); 2304 continue; 2305 } 2306 if (scnidx >= shnum || 2307 (scnidx >= SHN_LORESERVE && 2308 scnidx <= SHN_HIRESERVE)) 2309 { 2310 INFO(" special (scn %d, value 0x%llx, size %lld)\n", 2311 scnidx, 2312 sym->st_value, 2313 sym->st_size); 2314 2315 /* We shouldn't be messing with these symbols, but they are 2316 often absolute symbols that encode the starting address 2317 or the ending address of some section. As a heuristic, 2318 we will check to see if the value of the symbol matches 2319 the start or the end of any section, and if so, we will 2320 update it, but only if --shady is enabled. 2321 */ 2322 2323 if (shady && sym->st_value) { 2324 size_t scnidx; 2325 /* Is it the special symbol _DYNAMIC? */ 2326 if (!strcmp(symname, "_DYNAMIC")) { 2327 /* The _DYNAMIC symbol points to the DYNAMIC 2328 segment. It is used by linker to bootstrap 2329 itself. */ 2330 ASSERT(dynamic_idx >= 0); 2331 PRINT("*** SHADY *** symbol %s: " 2332 "new st_value = %lld (was %lld), " 2333 "st_size = %lld (was %lld)\n", 2334 symname, 2335 shdr_info[dynamic_idx].shdr.sh_addr, 2336 sym->st_value, 2337 shdr_info[dynamic_idx].shdr.sh_size, 2338 sym->st_size); 2339 sym->st_value = 2340 shdr_info[dynamic_idx].shdr.sh_addr; 2341 sym->st_size = 2342 shdr_info[dynamic_idx].shdr.sh_size; 2343 /* NOTE: We don't update st_shndx, because this is a special 2344 symbol. I am not sure if it's necessary though. 2345 */ 2346 FAILIF_LIBELF(gelf_update_symshndx(symdata, 2347 NULL, 2348 inner, 2349 sym, 2350 0) == 0, 2351 gelf_update_symshndx); 2352 } 2353 else { 2354 for (scnidx = 1; scnidx < num_shdr_info; scnidx++) { 2355 if (sym->st_value == 2356 shdr_info[scnidx].old_shdr.sh_addr) { 2357 if (shdr_info[scnidx].shdr.sh_addr != 2358 sym->st_value) { 2359 PRINT("*** SHADY *** symbol %s matches old " 2360 "start %lld of section %s, updating " 2361 "to %lld.\n", 2362 symname, 2363 shdr_info[scnidx].old_shdr.sh_addr, 2364 shdr_info[scnidx].name, 2365 shdr_info[scnidx].shdr.sh_addr); 2366 sym->st_value = shdr_info[scnidx].shdr.sh_addr; 2367 } 2368 break; 2369 } 2370 else { 2371 Elf64_Addr oldaddr = 2372 shdr_info[scnidx].old_shdr.sh_addr + 2373 shdr_info[scnidx].old_shdr.sh_size; 2374 if (sym->st_value == oldaddr) { 2375 Elf64_Addr newaddr = 2376 shdr_info[scnidx].shdr.sh_addr + 2377 shdr_info[scnidx].shdr.sh_size; 2378 if (newaddr != sym->st_value) { 2379 PRINT("*** SHADY *** symbol %s matches old " 2380 "end %lld of section %s, updating " 2381 "to %lld.\n", 2382 symname, 2383 oldaddr, 2384 shdr_info[scnidx].name, 2385 newaddr); 2386 sym->st_value = newaddr; 2387 } 2388 break; 2389 } 2390 } 2391 } /* for each section... */ 2392 /* NOTE: We don't update st_shndx, because this is a special 2393 symbol. I am not sure if it's necessary though. 2394 */ 2395 if (scnidx < num_shdr_info) { 2396 FAILIF_LIBELF(gelf_update_symshndx(symdata, 2397 NULL, 2398 inner, 2399 sym, 2400 0) == 0, 2401 gelf_update_symshndx); 2402 } 2403 } /* if symbol is _DYNAMIC else */ 2404 } 2405 2406 continue; 2407 } /* handle special-section symbols */ 2408 2409 /* The symbol must refer to a section which is not being 2410 removed. */ 2411 if(shdr_info[scnidx].idx == 0) 2412 { 2413 FAILIF(GELF_ST_TYPE (sym->st_info) != STT_SECTION, 2414 "Non-STT_SECTION symbol [%s] refers to section [%s]," 2415 " which is being removed.\n", 2416 symname, 2417 shdr_info[scnidx].name); 2418 INFO("STT_SECTION symbol [%s] refers to section [%s], " 2419 "which is being removed. Skipping...\n", 2420 symname, 2421 shdr_info[scnidx].name); 2422 continue; 2423 } 2424 2425 INFO(" %8d %-17s ", 2426 sym->st_shndx, 2427 shdr_info[sym->st_shndx].name); 2428 2429 /* Has the section's offset (hence its virtual address, 2430 because we set that to the same value as the offset) changed? 2431 If so, calculate the delta and update the symbol entry. 2432 */ 2433 Elf64_Sxword delta; 2434 delta = 2435 shdr_info[scnidx].shdr.sh_offset - 2436 shdr_info[scnidx].old_shdr.sh_offset; 2437 2438 Elf64_Sxword vaddr_delta; 2439 vaddr_delta = 2440 shdr_info[scnidx].shdr.sh_addr - 2441 shdr_info[scnidx].old_shdr.sh_addr; 2442 2443 if (vaddr_delta || shdr_info[scnidx].idx != scnidx) { 2444 2445 if (sym->st_value) 2446 INFO("0x%llx -> 0x%llx (delta %lld)", 2447 sym->st_value, 2448 sym->st_value + vaddr_delta, 2449 vaddr_delta); 2450 else { 2451 INFO("(value is zero, not adjusting it)"); 2452 /* This might be a bit too paranoid, but symbols with values of 2453 zero for which we are not adjusting the value must be in the 2454 static-symbol section and refer to a section which is 2455 not loaded at run time. If this assertion ever fails, figure 2456 out why and also figure out whether the zero value should have 2457 been adjusted, after all. 2458 */ 2459 ASSERT(!(shdr_info[sym->st_shndx].shdr.sh_flags & SHF_ALLOC)); 2460 ASSERT(shdr_info[i].shdr.sh_type == SHT_SYMTAB); 2461 } 2462 2463 /* The section index of the symbol must coincide with 2464 the shdr_info[] index of the section that the 2465 symbol refers to. Since that section may have been 2466 moved, its new setion index, which is stored in 2467 the idx field, may have changed. However the index 2468 of the original section must match. 2469 */ 2470 ASSERT(scnidx == elf_ndxscn(shdr_info[scnidx].scn)); 2471 2472 if(unlikely(verbose_flag)) { 2473 if (shdr_info[scnidx].idx != scnidx) { 2474 INFO(" (updating sym->st_shndx = %lld --> %lld)\n", 2475 sym->st_shndx, 2476 shdr_info[scnidx].idx); 2477 } 2478 else INFO("(sym->st_shndx remains %lld)\n", sym->st_shndx); 2479 } 2480 2481 sym->st_shndx = shdr_info[scnidx].idx; 2482 if (sym->st_value) 2483 sym->st_value += vaddr_delta; 2484 FAILIF_LIBELF(gelf_update_symshndx(symdata, 2485 NULL, 2486 inner, 2487 sym, 2488 0) == 0, 2489 gelf_update_symshndx); 2490 } 2491 else { 2492 INFO(" (no change)\n"); 2493 } 2494 } /* for each symbol */ 2495 } /* if it's a symbol table... */ 2496 } /* for each section... */ 2497 } 2498 2499 static void adjust_section_offset(Elf *newelf, 2500 shdr_info_t *shdr_info, 2501 Elf64_Sxword delta) 2502 { 2503 Elf_Scn *scn = elf_getscn (newelf, shdr_info->idx); 2504 ASSERT(scn != NULL); 2505 2506 ASSERT(((Elf64_Sxword)shdr_info->shdr.sh_offset) + delta >= 0); 2507 shdr_info->shdr.sh_offset += delta; 2508 ASSERT(shdr_info->shdr.sh_addralign); 2509 #ifdef DEBUG 2510 /* The assumption is that the delta is calculated so that it will preserve 2511 the alignment. Of course, we don't trust ourselves so we verify. 2512 2513 NOTE: The assertion below need not hold about NOBITS sections (such as 2514 the .bss section), for which the offset in the file and the address at 2515 which the section is to be loaded may differ. 2516 */ 2517 if (shdr_info->shdr.sh_type != SHT_NOBITS) 2518 { 2519 Elf64_Off new_offset = shdr_info->shdr.sh_offset; 2520 new_offset += shdr_info->shdr.sh_addralign - 1; 2521 new_offset &= ~((GElf_Off)(shdr_info->shdr.sh_addralign - 1)); 2522 2523 ASSERT(shdr_info->shdr.sh_offset == new_offset); 2524 } 2525 #endif 2526 INFO("\t\t\t\tsection offset %lld -> %lld%s\n", 2527 shdr_info->old_shdr.sh_offset, 2528 shdr_info->shdr.sh_offset, 2529 (shdr_info->old_shdr.sh_offset == 2530 shdr_info->shdr.sh_offset ? " (SAME)" : "")); 2531 2532 /* If there is a delta for an ALLOC section, then the sections address must match the sections's offset in 2533 the file, if that section is not marked SHT_NOBITS. For SHT_NOBITS sections, the two may differ. 2534 Note that we compare against the old_shdr.sh_offset because we just modified shdr.sh_offset! 2535 */ 2536 2537 ASSERT(!delta || 2538 !(shdr_info->shdr.sh_flags & SHF_ALLOC) || 2539 shdr_info->shdr.sh_type == SHT_NOBITS || 2540 shdr_info->shdr.sh_addr == shdr_info->old_shdr.sh_offset); 2541 2542 if ((shdr_info->shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC) 2543 { 2544 ASSERT(shdr_info->shdr.sh_addr); 2545 shdr_info->shdr.sh_addr += delta; 2546 INFO("\t\t\t\tsection address %lld -> %lld%s\n", 2547 shdr_info->old_shdr.sh_addr, 2548 shdr_info->shdr.sh_addr, 2549 (shdr_info->old_shdr.sh_addr == 2550 shdr_info->shdr.sh_addr ? " (SAME)" : "")); 2551 } 2552 2553 /* Set the section header in the new file. There cannot be any 2554 overflows. */ 2555 INFO("\t\t\t\tupdating section header (size %lld)\n", 2556 shdr_info->shdr.sh_size); 2557 FAILIF(!gelf_update_shdr (scn, &shdr_info->shdr), 2558 "Could not update section header for section %s!\n", 2559 shdr_info->name); 2560 } 2561 2562 #ifdef MOVE_SECTIONS_IN_RANGES 2563 static int get_end_of_range(shdr_info_t *shdr_info, 2564 int num_shdr_info, 2565 int start, 2566 Elf64_Xword *alignment, 2567 Elf32_Word *real_align) 2568 { 2569 int end = start; 2570 ASSERT(start < num_shdr_info); 2571 2572 /* Note that in the loop below we do not check to see if a section is 2573 being thrown away. If a section in the middle of a range is thrown 2574 away, that will cause the section to be removed, but it will not cause 2575 the relative offsets of the sections in the block to be modified. 2576 */ 2577 2578 *alignment = real_align[start]; 2579 while (end < num_shdr_info && 2580 ((shdr_info[end].shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC) && 2581 ((shdr_info[end].shdr.sh_type == SHT_PROGBITS) || 2582 (shdr_info[end].shdr.sh_type == SHT_INIT_ARRAY) || 2583 (shdr_info[end].shdr.sh_type == SHT_FINI_ARRAY) || 2584 (shdr_info[end].shdr.sh_type == SHT_PREINIT_ARRAY) || 2585 /* (shdr_info[end].shdr.sh_type == SHT_NOBITS) || */ 2586 #ifdef ARM_SPECIFIC_HACKS 2587 /* SHF_ALLOC sections with with names starting with ".ARM." are 2588 part of the ARM EABI extensions to ELF. 2589 */ 2590 !strncmp(shdr_info[end].name, ".ARM.", 5) || 2591 #endif 2592 (shdr_info[end].shdr.sh_type == SHT_DYNAMIC))) 2593 { 2594 if (real_align[end] > *alignment) { 2595 *alignment = real_align[end]; 2596 } 2597 end++; 2598 } 2599 2600 return end == start ? end + 1 : end; 2601 } 2602 #endif/*MOVE_SECTIONS_IN_RANGES*/ 2603 2604 static GElf_Off update_last_offset(shdr_info_t *shdr_info, 2605 range_list_t *section_ranges, 2606 GElf_Off offset) 2607 { 2608 GElf_Off filesz = 0; 2609 if (shdr_info->shdr.sh_type != SHT_NOBITS) { 2610 /* This function is used as an assertion: if the range we are 2611 adding conflicts with another range already in the list, 2612 then add_unique_range() will call FAILIF(). 2613 */ 2614 add_unique_range_nosort(section_ranges, 2615 shdr_info->shdr.sh_offset, 2616 shdr_info->shdr.sh_size, 2617 shdr_info, 2618 handle_range_error, 2619 NULL); 2620 2621 filesz = shdr_info->shdr.sh_size; 2622 } 2623 2624 /* Remember the last section written so far. */ 2625 if (offset < shdr_info->shdr.sh_offset + filesz) { 2626 offset = shdr_info->shdr.sh_offset + filesz; 2627 INFO("\t\t\t\tupdated lastoffset to %lld\n", offset); 2628 } 2629 2630 return offset; 2631 } 2632 2633 static GElf_Off move_sections(Elf *newelf, 2634 shdr_info_t *shdr_info, 2635 int num_shdr_info, 2636 int start, 2637 int end, 2638 GElf_Off offset, 2639 Elf64_Xword alignment, 2640 range_list_t *section_ranges, 2641 bool adjust_alloc_section_offsets) 2642 { 2643 /* The alignment parameter is expected to contain the largest alignment of 2644 all sections in the block. Thus, when we iterate over all sections in 2645 the block and apply the same offset to them, we are guaranteed to 2646 preserve (a) the relative offsets between the sections in the block and 2647 (b) the alignment requirements of each individual section. 2648 */ 2649 2650 ASSERT(start < num_shdr_info); 2651 ASSERT(end <= num_shdr_info); 2652 2653 Elf64_Sxword delta = offset - shdr_info[start].shdr.sh_offset; 2654 delta += (alignment - 1); 2655 delta &= ~(alignment - 1); 2656 while (start < end) { 2657 if (shdr_info[start].idx > 0) { 2658 if (adjust_alloc_section_offsets || (shdr_info[start].shdr.sh_flags & SHF_ALLOC) != SHF_ALLOC) { 2659 INFO("\t\t\t%03d:\tAdjusting offset of section %s " 2660 "(index %d) from 0x%llx (%lld) to 0x%llx (%lld) (DELTA %lld)...\n", 2661 start, 2662 (shdr_info[start].name ?: "(no name)"), 2663 shdr_info[start].idx, 2664 shdr_info[start].old_shdr.sh_offset, shdr_info[start].old_shdr.sh_offset, 2665 offset, offset, 2666 delta); 2667 2668 /* Compute the new offset of the section. */ 2669 adjust_section_offset(newelf, shdr_info + start, delta); 2670 } 2671 else { 2672 INFO("\t\t\t%03d: NOT adjusting offset of section %s (index %d)" 2673 ": (not moving SHF_ALLOC sections)...\n", 2674 start, 2675 (shdr_info[start].name ?: "(no name)"), 2676 shdr_info[start].idx); 2677 } 2678 offset = update_last_offset(shdr_info + start, 2679 section_ranges, 2680 offset); 2681 } /* if (shdr_info[start].idx > 0) */ 2682 else { 2683 INFO("\t\t\t%03d: NOT adjusting offset of section %s (index %d)" 2684 " (ignored)...\n", 2685 start, 2686 (shdr_info[start].name ?: "(no name)"), 2687 shdr_info[start].idx); 2688 } 2689 start++; 2690 } 2691 2692 sort_ranges(section_ranges); 2693 return offset; 2694 } 2695 2696 /* Compute the alignments of sections with consideration of segment 2697 alignments. Returns an array of Elf32_Word containing the alignment 2698 of sections. Callee is responsible to deallocate the array after use. */ 2699 Elf32_Word * 2700 get_section_real_align (GElf_Ehdr *ehdr, GElf_Phdr *phdr_info, 2701 struct shdr_info_t *shdr_info, int shdr_info_len) 2702 { 2703 size_t max_align_array_size; 2704 Elf32_Word *max_align; 2705 size_t first_section; 2706 bool propagate_p; 2707 int si, pi; 2708 2709 max_align_array_size = sizeof(Elf32_Word) * shdr_info_len; 2710 max_align = (Elf32_Word*) malloc (max_align_array_size); 2711 FAILIF(!max_align, "malloc(%zu) failed.\n", max_align_array_size); 2712 2713 /* Initialize alignment array. */ 2714 max_align[0] = 0; 2715 for (si = 1; si < shdr_info_len; si++) 2716 max_align[si] = shdr_info[si].shdr.sh_addralign; 2717 2718 /* Determine which sections need to be aligned with the alignment of 2719 containing segments. Becasue the first section in a segment may 2720 be deleted, we need to look at all sections and compare their offsets. 2721 */ 2722 for (pi = 0; pi < ehdr->e_phnum; ++pi) { 2723 /* Skip null segment. */ 2724 if (phdr_info[pi].p_type == PT_NULL) 2725 continue; 2726 2727 /* Look for the first non-deleted section of a segment in output. 2728 We assume asections are sorted by offsets. Also check to see if 2729 a segment starts with a section. We only want to propagate 2730 alignment if the segment starts with a section. */ 2731 propagate_p = false; 2732 first_section = 0; 2733 for (si = 1; si < shdr_info_len && first_section == 0; si++) { 2734 if (shdr_info[si].old_shdr.sh_offset == phdr_info[pi].p_offset) 2735 propagate_p = true; 2736 2737 if (shdr_info[si].idx > 0 2738 && section_belongs_to_header(&shdr_info[si].old_shdr, 2739 &phdr_info[pi])) 2740 first_section = si; 2741 } 2742 2743 if (!propagate_p || first_section == 0) 2744 continue; 2745 2746 /* Adjust alignment of first section. Note that a section can appear 2747 in multiple segments. We only need the extra alignment if the 2748 section's alignment is smaller than that of the segment. */ 2749 if (first_section != 0 && 2750 max_align[first_section] < phdr_info[pi].p_align) { 2751 max_align[first_section] = phdr_info[pi].p_align; 2752 } 2753 } 2754 2755 return max_align; 2756 } 2757 2758 static range_list_t * 2759 update_section_offsets(Elf *elf, 2760 Elf *newelf, 2761 GElf_Phdr *phdr_info, 2762 shdr_info_t *shdr_info, 2763 int num_shdr_info, 2764 range_list_t *section_ranges, 2765 bool adjust_alloc_section_offsets) 2766 { 2767 Elf32_Word *real_align; 2768 2769 ASSERT(section_ranges); 2770 INFO("Updating section addresses and offsets...\n"); 2771 /* The initial value of lastoffset is set to the size of the ELF header 2772 plus the size of the program-header table. libelf seems to always 2773 place the program-header table for a new file immediately after the 2774 ELF header itself... or I could not find any other way to change it 2775 otherwise. 2776 */ 2777 GElf_Ehdr ehdr_mem, *ehdr; 2778 ehdr = gelf_getehdr (elf, &ehdr_mem); 2779 FAILIF_LIBELF(NULL == ehdr, gelf_getehdr); 2780 const size_t ehdr_size = gelf_fsize (elf, ELF_T_EHDR, 1, EV_CURRENT); 2781 FAILIF(ehdr->e_phoff != ehdr_size, 2782 "Expecting the program-header table to follow the ELF header" 2783 " immediately!\n"); 2784 2785 GElf_Off lastoffset = 0; 2786 lastoffset += ehdr_size; 2787 lastoffset += ehdr->e_phnum * ehdr->e_phentsize; 2788 INFO("Section offsets will start from %lld.\n", lastoffset); 2789 2790 int start = 1, end = 1; 2791 ASSERT(num_shdr_info > 0); 2792 real_align = get_section_real_align (ehdr, phdr_info, shdr_info, 2793 num_shdr_info); 2794 while (end < num_shdr_info) { 2795 Elf64_Xword alignment; 2796 /* end is the index one past the last section of the block. */ 2797 #ifdef MOVE_SECTIONS_IN_RANGES 2798 end = get_end_of_range(shdr_info, num_shdr_info, 2799 start, &alignment, real_align); 2800 #else 2801 end = start + 1; 2802 alignment = real_align[start]; 2803 #endif 2804 2805 INFO("\tAdjusting sections [%d - %d) as a group (start offset %lld, alignment %lld)\n", 2806 start, end, lastoffset, alignment); 2807 lastoffset = move_sections(newelf, 2808 shdr_info, 2809 num_shdr_info, 2810 start, end, 2811 lastoffset, 2812 alignment, 2813 section_ranges, 2814 adjust_alloc_section_offsets); 2815 2816 start = end; 2817 } 2818 2819 ASSERT(lastoffset == get_last_address(section_ranges)); 2820 free (real_align); 2821 return section_ranges; 2822 } 2823 2824 void handle_range_error(range_error_t err, range_t *left, range_t *right) 2825 { 2826 shdr_info_t *info_l = (shdr_info_t *)left->user; 2827 shdr_info_t *info_r = (shdr_info_t *)right->user; 2828 ASSERT(info_l); 2829 ASSERT(info_r); 2830 2831 switch (err) { 2832 case ERROR_CONTAINS: 2833 ERROR("ERROR: section [%s] (%lld, %lld bytes) contains " 2834 "section [%s] (%lld, %lld bytes)\n", 2835 info_l->name, 2836 left->start, left->length, 2837 info_r->name, 2838 right->start, right->length); 2839 break; 2840 case ERROR_OVERLAPS: 2841 ERROR("ERROR: Section [%s] (%lld, %lld bytes) intersects " 2842 "section [%s] (%lld, %lld bytes)\n", 2843 info_l->name, 2844 left->start, left->length, 2845 info_r->name, 2846 right->start, right->length); 2847 break; 2848 default: 2849 ASSERT(!"Unknown range error code!"); 2850 } 2851 2852 FAILIF(1, "Range error.\n"); 2853 } 2854 2855 #ifdef DEBUG 2856 2857 /* Functions to ELF file is still sane after adjustment. */ 2858 2859 static bool 2860 sections_overlap_p (GElf_Shdr *s1, GElf_Shdr *s2) 2861 { 2862 GElf_Addr a1, a2; 2863 GElf_Off o1, o2; 2864 2865 if ((s1->sh_flags & s2->sh_flags & SHF_ALLOC) != 0) { 2866 a1 = (s1->sh_addr > s2->sh_addr)? s1->sh_addr : s2->sh_addr; 2867 a2 = ((s1->sh_addr + s1->sh_size < s2->sh_addr + s2->sh_size)? 2868 (s1->sh_addr + s1->sh_size) : (s2->sh_addr + s2->sh_size)); 2869 if (a1 < a2) 2870 return true; 2871 } 2872 2873 if (s1->sh_type != SHT_NOBITS && s2->sh_type != SHT_NOBITS) { 2874 o1 = (s1->sh_offset > s2->sh_offset)? s1->sh_offset : s2->sh_offset; 2875 o2 = ((s1->sh_offset + s1->sh_size < s2->sh_offset + s2->sh_size)? 2876 (s1->sh_offset + s1->sh_size) : (s2->sh_offset + s2->sh_size)); 2877 if (o1 < o2) 2878 return true; 2879 } 2880 2881 return false; 2882 } 2883 2884 /* Return size of the overlapping portion of section S and segment P 2885 in memory. */ 2886 2887 static GElf_Word 2888 mem_overlap_size (GElf_Shdr *s, GElf_Phdr *p) 2889 { 2890 GElf_Addr a1, a2; 2891 2892 if (s->sh_flags & SHF_ALLOC) { 2893 a1 = p->p_vaddr > s->sh_addr ? p->p_vaddr : s->sh_addr; 2894 a2 = ((p->p_vaddr + p->p_memsz < s->sh_addr + s->sh_size) ? 2895 (p->p_vaddr + p->p_memsz) : (s->sh_addr + s->sh_size)); 2896 if (a1 < a2) { 2897 return a2 - a1; 2898 } 2899 } 2900 return 0; 2901 } 2902 2903 /* Return size of the overlapping portion of section S and segment P 2904 in file. */ 2905 2906 static GElf_Word 2907 file_overlap_size (GElf_Shdr *s, GElf_Phdr *p) 2908 { 2909 GElf_Off o1, o2; 2910 2911 if (s->sh_type != SHT_NOBITS) { 2912 o1 = p->p_offset > s->sh_offset ? p->p_offset : s->sh_offset; 2913 o2 = ((p->p_offset + p->p_filesz < s->sh_offset + s->sh_size) ? 2914 (p->p_offset + p->p_filesz) : (s->sh_offset + s->sh_size)); 2915 if (o1 < o2) { 2916 return o2 - o1; 2917 } 2918 } 2919 return 0; 2920 } 2921 2922 /* Verify the ELF file is sane. */ 2923 static void 2924 verify_elf(GElf_Ehdr *ehdr, struct shdr_info_t *shdr_info, int shdr_info_len, 2925 GElf_Phdr *phdr_info) 2926 { 2927 int si, sj, pi; 2928 GElf_Word addralign; 2929 GElf_Word m_size, f_size; 2930 2931 /* Check all sections */ 2932 for (si = 1; si < shdr_info_len; si++) { 2933 if (shdr_info[si].idx <= 0) 2934 continue; 2935 2936 /* Check alignment */ 2937 addralign = shdr_info[si].shdr.sh_addralign; 2938 if (addralign != 0) { 2939 if (shdr_info[si].shdr.sh_flags & SHF_ALLOC) { 2940 FAILIF ((addralign - 1) & shdr_info[si].shdr.sh_addr, 2941 "Load address %llx of section %s is not " 2942 "aligned to multiples of %u\n", 2943 (long long unsigned) shdr_info[si].shdr.sh_addr, 2944 shdr_info[si].name, 2945 addralign); 2946 } 2947 2948 if (shdr_info[si].shdr.sh_type != SHT_NOBITS) { 2949 FAILIF ((addralign - 1) & shdr_info[si].shdr.sh_offset, 2950 "Offset %lx of section %s is not " 2951 "aligned to multiples of %u\n", 2952 shdr_info[si].shdr.sh_offset, 2953 shdr_info[si].name, 2954 addralign); 2955 } 2956 } 2957 2958 /* Verify that sections do not overlap. */ 2959 for (sj = si + 1; sj < shdr_info_len; sj++) { 2960 if (shdr_info[sj].idx <= 0) 2961 continue; 2962 2963 FAILIF (sections_overlap_p (&shdr_info[si].shdr, 2964 &shdr_info[sj].shdr), 2965 "sections %s and %s overlap.\n", shdr_info[si].name, 2966 shdr_info[sj].name); 2967 } 2968 2969 /* Verify that section is properly contained in segments. */ 2970 for (pi = 0; pi < ehdr->e_phnum; pi++) { 2971 if (phdr_info[pi].p_type == PT_NULL) 2972 continue; 2973 2974 f_size = file_overlap_size (&shdr_info[si].shdr, &phdr_info[pi]); 2975 m_size = mem_overlap_size (&shdr_info[si].shdr, &phdr_info[pi]); 2976 2977 if (f_size) { 2978 FAILIF (shdr_info[si].shdr.sh_size > phdr_info[pi].p_filesz, 2979 "Section %s is larger than segment %d\n", 2980 shdr_info[si].name, pi); 2981 FAILIF (f_size != shdr_info[si].shdr.sh_size, 2982 "Section %s partially overlaps segment %d in file.\n", 2983 shdr_info[si].name, pi); 2984 } 2985 2986 if (m_size) { 2987 FAILIF (shdr_info[si].shdr.sh_size > phdr_info[pi].p_memsz, 2988 "Section %s is larger than segment %d\n", 2989 shdr_info[si].name, pi); 2990 FAILIF (m_size != shdr_info[si].shdr.sh_size, 2991 "Section %s partially overlaps segment %d in memory.\n", 2992 shdr_info[si].name, pi); 2993 } 2994 2995 } 2996 } 2997 } 2998 #endif /* DEBUG */ 2999