Chromium Code Reviews| 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 |