OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "elf_file.h" | 5 #include "elf_file.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <sys/types.h> | 8 #include <sys/types.h> |
9 #include <unistd.h> | 9 #include <unistd.h> |
10 #include <string> | 10 #include <string> |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag | 385 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag |
386 << " d_ptr adjusted to " << dynamic->d_un.d_ptr; | 386 << " d_ptr adjusted to " << dynamic->d_un.d_ptr; |
387 } | 387 } |
388 | 388 |
389 // If we are specifically resizing dynamic relocations, we need to make | 389 // If we are specifically resizing dynamic relocations, we need to make |
390 // some added adjustments to tags that indicate the counts of relative | 390 // some added adjustments to tags that indicate the counts of relative |
391 // relocations in the shared object. | 391 // relocations in the shared object. |
392 if (!is_relocations_resize) | 392 if (!is_relocations_resize) |
393 continue; | 393 continue; |
394 | 394 |
395 // DT_RELSZ is the overall size of relocations. Adjust by hole size. | 395 // DT_RELSZ or DT_RELASZ indicate the overall size of relocations. |
396 if (tag == DT_RELSZ) { | 396 // Only one will be present. Adjust by hole size. |
rmcilroy
2014/08/15 16:28:47
Should we assert that only one is present?
| |
397 if (tag == DT_RELSZ || tag == DT_RELASZ) { | |
397 dynamic->d_un.d_val += hole_size; | 398 dynamic->d_un.d_val += hole_size; |
398 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag | 399 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag |
399 << " d_val adjusted to " << dynamic->d_un.d_val; | 400 << " d_val adjusted to " << dynamic->d_un.d_val; |
400 } | 401 } |
401 | 402 |
402 // DT_RELCOUNT is the count of relative relocations. Packing reduces it | 403 // DT_RELCOUNT or DT_RELACOUNT hold the count of relative relocations. |
403 // to the alignment padding, if any; unpacking restores it to its former | 404 // Only one will be present. Packing reduces it to the alignment |
404 // value. The crazy linker does not use it, but we update it anyway. | 405 // padding, if any; unpacking restores it to its former value. The |
405 if (tag == DT_RELCOUNT) { | 406 // crazy linker does not use it, but we update it anyway. |
407 if (tag == DT_RELCOUNT || tag == DT_RELACOUNT) { | |
406 // Cast sizeof to a signed type to avoid the division result being | 408 // Cast sizeof to a signed type to avoid the division result being |
407 // promoted into an unsigned size_t. | 409 // promoted into an unsigned size_t. |
408 const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Rel)); | 410 const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Rel)); |
409 dynamic->d_un.d_val += hole_size / sizeof_rel; | 411 dynamic->d_un.d_val += hole_size / sizeof_rel; |
410 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag | 412 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag |
411 << " d_val adjusted to " << dynamic->d_un.d_val; | 413 << " d_val adjusted to " << dynamic->d_un.d_val; |
412 } | 414 } |
413 | 415 |
414 // DT_RELENT doesn't change, but make sure it is what we expect. | 416 // DT_RELENT and DT_RELAENT don't change, but make sure they are what |
415 if (tag == DT_RELENT) { | 417 // we expect. Only one will be present. |
418 if (tag == DT_RELENT || tag == DT_RELAENT) { | |
416 CHECK(dynamic->d_un.d_val == sizeof(Rel)); | 419 CHECK(dynamic->d_un.d_val == sizeof(Rel)); |
417 } | 420 } |
418 } | 421 } |
419 | 422 |
420 void* section_data = &dynamics[0]; | 423 void* section_data = &dynamics[0]; |
421 size_t bytes = dynamics.size() * sizeof(dynamics[0]); | 424 size_t bytes = dynamics.size() * sizeof(dynamics[0]); |
422 RewriteSectionData(data, section_data, bytes); | 425 RewriteSectionData(data, section_data, bytes); |
423 } | 426 } |
424 | 427 |
425 // Helper for ResizeSection(). Adjust the .dynsym section for the hole. | 428 // Helper for ResizeSection(). Adjust the .dynsym section for the hole. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 // Resize a section. If the new size is larger than the current size, open | 515 // Resize a section. If the new size is larger than the current size, open |
513 // up a hole by increasing file offsets that come after the hole. If smaller | 516 // up a hole by increasing file offsets that come after the hole. If smaller |
514 // than the current size, remove the hole by decreasing those offsets. | 517 // than the current size, remove the hole by decreasing those offsets. |
515 template <typename Rel> | 518 template <typename Rel> |
516 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { | 519 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { |
517 ELF::Shdr* section_header = ELF::getshdr(section); | 520 ELF::Shdr* section_header = ELF::getshdr(section); |
518 if (section_header->sh_size == new_size) | 521 if (section_header->sh_size == new_size) |
519 return; | 522 return; |
520 | 523 |
521 // Note if we are resizing the real dyn relocations. If yes, then we have | 524 // Note if we are resizing the real dyn relocations. If yes, then we have |
522 // to massage d_un.d_val in the dynamic section where d_tag is DT_RELSZ and | 525 // to massage d_un.d_val in the dynamic section where d_tag is DT_RELSZ or |
523 // DT_RELCOUNT. | 526 // DT_RELASZ and DT_RELCOUNT or DT_RELACOUNT. |
524 size_t string_index; | 527 size_t string_index; |
525 elf_getshdrstrndx(elf, &string_index); | 528 elf_getshdrstrndx(elf, &string_index); |
526 const std::string section_name = | 529 const std::string section_name = |
527 elf_strptr(elf, string_index, section_header->sh_name); | 530 elf_strptr(elf, string_index, section_header->sh_name); |
528 const bool is_relocations_resize = | 531 const bool is_relocations_resize = |
529 (section_name == ".rel.dyn" || section_name == ".rela.dyn"); | 532 (section_name == ".rel.dyn" || section_name == ".rela.dyn"); |
530 | 533 |
531 // Require that the section size and the data size are the same. True | 534 // Require that the section size and the data size are the same. True |
532 // in practice for all sections we resize when packing or unpacking. | 535 // in practice for all sections we resize when packing or unpacking. |
533 Elf_Data* data = GetSectionData(section); | 536 Elf_Data* data = GetSectionData(section); |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1075 std::vector<Rel> relative_relocations; | 1078 std::vector<Rel> relative_relocations; |
1076 RelocationPacker packer; | 1079 RelocationPacker packer; |
1077 packer.UnpackRelativeRelocations(packed, &relative_relocations); | 1080 packer.UnpackRelativeRelocations(packed, &relative_relocations); |
1078 const size_t unpacked_bytes = | 1081 const size_t unpacked_bytes = |
1079 relative_relocations.size() * sizeof(relative_relocations[0]); | 1082 relative_relocations.size() * sizeof(relative_relocations[0]); |
1080 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes"; | 1083 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes"; |
1081 | 1084 |
1082 // Retrieve the current dynamic relocations section data. | 1085 // Retrieve the current dynamic relocations section data. |
1083 data = GetSectionData(relocations_section_); | 1086 data = GetSectionData(relocations_section_); |
1084 | 1087 |
1085 // Interpret data as Elf32 relocations. | 1088 // Interpret data as relocations. |
1086 const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf); | 1089 const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf); |
1087 std::vector<Rel> relocations( | 1090 std::vector<Rel> relocations( |
1088 relocations_base, | 1091 relocations_base, |
1089 relocations_base + data->d_size / sizeof(relocations[0])); | 1092 relocations_base + data->d_size / sizeof(relocations[0])); |
1090 | 1093 |
1091 std::vector<Rel> other_relocations; | 1094 std::vector<Rel> other_relocations; |
1092 size_t padding = 0; | 1095 size_t padding = 0; |
1093 | 1096 |
1094 // Filter relocations to locate any that are NONE-type. These will occur | 1097 // Filter relocations to locate any that are NONE-type. These will occur |
1095 // if padding was turned on for packing. | 1098 // if padding was turned on for packing. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1186 | 1189 |
1187 // Clean up libelf, and truncate the output file to the number of bytes | 1190 // Clean up libelf, and truncate the output file to the number of bytes |
1188 // written by elf_update(). | 1191 // written by elf_update(). |
1189 elf_end(elf_); | 1192 elf_end(elf_); |
1190 elf_ = NULL; | 1193 elf_ = NULL; |
1191 const int truncate = ftruncate(fd_, file_bytes); | 1194 const int truncate = ftruncate(fd_, file_bytes); |
1192 CHECK(truncate == 0); | 1195 CHECK(truncate == 0); |
1193 } | 1196 } |
1194 | 1197 |
1195 } // namespace relocation_packer | 1198 } // namespace relocation_packer |
OLD | NEW |