Merge "Fix unit tests, and extend for other architectures"
This commit is contained in:
commit
560aacee84
13 changed files with 113 additions and 10 deletions
|
@ -95,3 +95,9 @@ $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so))
|
|||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so))
|
||||
|
|
|
@ -302,13 +302,75 @@ static void AdjustSectionHeadersForHole(Elf* elf,
|
|||
}
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the offsets of any program headers
|
||||
// that have offsets currently beyond the hole start.
|
||||
// Helpers for ResizeSection(). On packing, reduce p_align for LOAD segments
|
||||
// to 4kb if larger. On unpacking, restore p_align for LOAD segments if
|
||||
// packing reduced it to 4kb. Return true if p_align was changed.
|
||||
template <typename ELF>
|
||||
static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
|
||||
static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If large, reduce p_align for a LOAD segment to page size on packing.
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If p_align was reduced on packing, restore it to its previous value
|
||||
// on unpacking. We do this by searching for a different LOAD segment
|
||||
// and setting p_align to that of the other LOAD segment found.
|
||||
//
|
||||
// Relies on the following observations:
|
||||
// - a packable ELF executable has more than one LOAD segment;
|
||||
// - before packing all LOAD segments have the same p_align;
|
||||
// - on packing we reduce only one LOAD segment's p_align.
|
||||
if (program_header->p_align == kPageSize) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* other_header = &program_headers[i];
|
||||
if (other_header->p_type == PT_LOAD && other_header != program_header) {
|
||||
program_header->p_align = other_header->p_align;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
typename ELF::Phdr* program_header,
|
||||
ssize_t hole_size) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
bool status = false;
|
||||
if (hole_size < 0) {
|
||||
status = ClampLoadSegmentAlignment<ELF>(program_header);
|
||||
} else if (hole_size > 0) {
|
||||
status = RestoreLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the offsets of any program headers
|
||||
// that have offsets currently beyond the hole start, and adjust the
|
||||
// virtual and physical addrs (and perhaps alignment) of the others.
|
||||
template <typename ELF>
|
||||
static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
int alignment_changes = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* program_header = &program_headers[i];
|
||||
|
||||
|
@ -327,9 +389,20 @@ static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
|
|||
} else {
|
||||
program_header->p_vaddr -= hole_size;
|
||||
program_header->p_paddr -= hole_size;
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
|
||||
// If packing, clamp LOAD segment alignment to 4kb to prevent strip
|
||||
// from adjusting it unnecessarily if run on a packed file. If
|
||||
// unpacking, attempt to restore a reduced alignment to its previous
|
||||
// value. Ensure that we do this on at most one LOAD segment.
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
alignment_changes += AdjustLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header,
|
||||
hole_size);
|
||||
LOG_IF(FATAL, alignment_changes > 1)
|
||||
<< "Changed p_align on more than one LOAD segment";
|
||||
}
|
||||
|
||||
VLOG(1) << "phdr[" << i
|
||||
<< "] p_vaddr adjusted to "<< program_header->p_vaddr
|
||||
<< "; p_paddr adjusted to "<< program_header->p_paddr
|
||||
|
@ -383,10 +456,10 @@ static void RewriteProgramHeadersForHole(Elf* elf,
|
|||
target_load_header->p_memsz += hole_size;
|
||||
|
||||
// Adjust the offsets and p_vaddrs
|
||||
AdjustProgramHeaderOffsets<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
AdjustProgramHeaderFields<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Locate and return the dynamic section.
|
||||
|
|
|
@ -183,6 +183,18 @@ TEST(ElfFile, PackRelocationsArm64) {
|
|||
RunPackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsMips32) {
|
||||
RunPackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsIa32) {
|
||||
RunPackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsX64) {
|
||||
RunPackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsArm32) {
|
||||
RunUnpackRelocationsTestFor("arm32");
|
||||
}
|
||||
|
@ -191,4 +203,16 @@ TEST(ElfFile, UnpackRelocationsArm64) {
|
|||
RunUnpackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsMips32) {
|
||||
RunUnpackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsIa32) {
|
||||
RunUnpackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsX64) {
|
||||
RunUnpackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
Executable file
Binary file not shown.
Loading…
Reference in a new issue