From 03aeeb09c53923072d561d004b6f682664a2eb8c Mon Sep 17 00:00:00 2001 From: Jake Ehrlich Date: Wed, 1 Nov 2017 23:14:48 +0000 Subject: [PATCH] [yaml2obj][ELF] Add support for setting alignment in program headers Sometimes program headers have larger alignments than any of the sections they contain. Currently yaml2obj can't produce such files. A bug recently appeared in llvm-objcopy that failed in such a case. I'd like to be able to add tests to llvm-objcopy for such cases. This change adds an optional alignment parameter to program headers that will be used instead of calculating the alignment. Differential Revision: https://reviews.llvm.org/D39130 llvm-svn: 317139 --- llvm/include/llvm/ObjectYAML/ELFYAML.h | 1 + llvm/lib/ObjectYAML/ELFYAML.cpp | 1 + llvm/test/tools/yaml2obj/program-header-align.yaml | 63 ++++++++++++++++++++++ llvm/tools/yaml2obj/yaml2elf.cpp | 20 ++++--- 4 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 llvm/test/tools/yaml2obj/program-header-align.yaml diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index 3468979..e9f9eb9 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -83,6 +83,7 @@ struct ProgramHeader { ELF_PF Flags; llvm::yaml::Hex64 VAddr; llvm::yaml::Hex64 PAddr; + Optional Align; std::vector Sections; }; diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index b19a575..ada9ff8 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -719,6 +719,7 @@ void MappingTraits::mapping( IO.mapOptional("Sections", Phdr.Sections); IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0)); IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0)); + IO.mapOptional("Align", Phdr.Align); } namespace { diff --git a/llvm/test/tools/yaml2obj/program-header-align.yaml b/llvm/test/tools/yaml2obj/program-header-align.yaml new file mode 100644 index 0000000..de51f5d --- /dev/null +++ b/llvm/test/tools/yaml2obj/program-header-align.yaml @@ -0,0 +1,63 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj -program-headers %t | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000008 + Content: "00000000" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + AddressAlign: 0x0000000000000010 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0xAAAA1030 + PAddr: 0xFFFF1030 + Align: 0x1000 + Sections: + - Section: .text + - Type: PT_LOAD + Flags: [ PF_R ] + VAddr: 0xAAAA2040 + PAddr: 0xFFFF2040 + Align: 0x1000 + Sections: + - Section: .data + +#CHECK: ProgramHeaders [ +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_LOAD +#CHECK-NEXT: Offset: 0x230 +#CHECK-NEXT: VirtualAddress: 0xAAAA1030 +#CHECK-NEXT: PhysicalAddress: 0xFFFF1030 +#CHECK-NEXT: FileSize: 4 +#CHECK-NEXT: MemSize: 4 +#CHECK-NEXT: Flags [ +#CHECK-NEXT: PF_R +#CHECK-NEXT: PF_X +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 4096 +#CHECK-NEXT: } +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_LOAD +#CHECK-NEXT: Offset: 0x240 +#CHECK-NEXT: VirtualAddress: 0xAAAA2040 +#CHECK-NEXT: PhysicalAddress: 0xFFFF2040 +#CHECK-NEXT: FileSize: 4 +#CHECK-NEXT: MemSize: 4 +#CHECK-NEXT: Flags [ +#CHECK-NEXT: PF_R +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 4096 +#CHECK-NEXT: } +#CHECK-NEXT:] diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 9328048..913f190 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -378,15 +378,19 @@ void ELFState::setProgramHeaderLayout(std::vector &PHeaders, } // Set the alignment of the segment to be the same as the maximum alignment - // of the the sections with the same offset so that by default the segment + // of the sections with the same offset so that by default the segment // has a valid and sensible alignment. - PHeader.p_align = 1; - for (auto SecName : YamlPhdr.Sections) { - uint32_t Index = 0; - SN2I.lookup(SecName.Section, Index); - const auto &SHeader = SHeaders[Index]; - if (SHeader.sh_offset == PHeader.p_offset) - PHeader.p_align = std::max(PHeader.p_align, SHeader.sh_addralign); + if (YamlPhdr.Align) { + PHeader.p_align = *YamlPhdr.Align; + } else { + PHeader.p_align = 1; + for (auto SecName : YamlPhdr.Sections) { + uint32_t Index = 0; + SN2I.lookup(SecName.Section, Index); + const auto &SHeader = SHeaders[Index]; + if (SHeader.sh_offset == PHeader.p_offset) + PHeader.p_align = std::max(PHeader.p_align, SHeader.sh_addralign); + } } } } -- 2.7.4