Index: test/tools/llvm-objcopy/binary-no-paddr.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/binary-no-paddr.test @@ -0,0 +1,42 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy -O binary %t %t2 +# RUN: od -t x2 -v %t2 | FileCheck %s +# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x0000000000001000 + Content: "c3c3c3c3" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x1004 + AddressAlign: 0x0000000000000004 + Content: "3232" +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x1000 + PAddr: 0x0000 + Align: 0x1000 + Sections: + - Section: .text + - Type: PT_LOAD + Flags: [ PF_R, PF_W ] + VAddr: 0x1004 + PAddr: 0x0000 + Align: 0x1000 + Sections: + - Section: .data + +# CHECK: 0000000 c3c3 c3c3 3232 +# SIZE: 6 Index: test/tools/llvm-objcopy/binary-paddr.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/binary-paddr.test @@ -0,0 +1,42 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy -O binary %t %t2 +# RUN: od -t x2 -v %t2 | FileCheck %s +# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x0000000000001000 + Content: "c3c3c3c3" + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2000 + AddressAlign: 0x0000000000000004 + Content: "3232" +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x1000 + PAddr: 0x1000 + Align: 0x1000 + Sections: + - Section: .text + - Type: PT_LOAD + Flags: [ PF_R, PF_W ] + VAddr: 0x2000 + PAddr: 0x1004 + Align: 0x1000 + Sections: + - Section: .data + +# CHECK: 0000000 c3c3 c3c3 3232 +# SIZE: 6 Index: test/tools/llvm-objcopy/binary-segment-layout.test =================================================================== --- test/tools/llvm-objcopy/binary-segment-layout.test +++ test/tools/llvm-objcopy/binary-segment-layout.test @@ -14,24 +14,25 @@ Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] AddressAlign: 0x0000000000001000 + Address: 0x00 Content: "c3c3c3c3" - Name: .data Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 0x0000000000001000 + AddressAlign: 0x0000000000000008 + Address: 0x08 Content: "3232" ProgramHeaders: - Type: PT_LOAD Flags: [ PF_X, PF_R ] + VAddr: 0x00 Sections: - Section: .text - Type: PT_LOAD Flags: [ PF_R ] + VAddr: 0x08 Sections: - Section: .data -# CHECK: 0000000 c3c3 c3c3 0000 0000 0000 0000 0000 0000 -# CHECK-NEXT: 0000020 0000 0000 0000 0000 0000 0000 0000 0000 -# CHECK-NEXT: * -# CHECK-NEXT: 0010000 3232 -# SIZE: 4098 +# CHECK: 0000000 c3c3 c3c3 0000 0000 3232 +# SIZE: 10 Index: test/tools/llvm-objcopy/two-seg-remove-end.test =================================================================== --- test/tools/llvm-objcopy/two-seg-remove-end.test +++ test/tools/llvm-objcopy/two-seg-remove-end.test @@ -48,8 +48,8 @@ - Section: .text2 - Type: PT_LOAD Flags: [ PF_R ] - VAddr: 0x1000 - PAddr: 0x1000 + VAddr: 0x3000 + PAddr: 0x3000 Sections: - Section: .text3 - Section: .text4 Index: test/tools/llvm-objcopy/two-seg-remove-first.test =================================================================== --- test/tools/llvm-objcopy/two-seg-remove-first.test +++ test/tools/llvm-objcopy/two-seg-remove-first.test @@ -48,8 +48,8 @@ - Section: .text2 - Type: PT_LOAD Flags: [ PF_R ] - VAddr: 0x1000 - PAddr: 0x1000 + VAddr: 0x3000 + PAddr: 0x3000 Sections: - Section: .text3 - Section: .text4 Index: test/tools/llvm-objcopy/two-seg-remove-third-sec.test =================================================================== --- test/tools/llvm-objcopy/two-seg-remove-third-sec.test +++ test/tools/llvm-objcopy/two-seg-remove-third-sec.test @@ -48,8 +48,8 @@ - Section: .text2 - Type: PT_LOAD Flags: [ PF_R ] - VAddr: 0x1000 - PAddr: 0x1000 + VAddr: 0x3000 + PAddr: 0x3000 Sections: - Section: .text3 - Section: .text4 Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -374,6 +374,14 @@ return A->Index < B->Index; } +static bool compareSegmentsUsingPAddr(const Segment *A, const Segment *B) { + if (A->PAddr < B->PAddr) + return true; + if (A->PAddr > B->PAddr) + return false; + return A->Index < B->Index; +} + template void Object::readProgramHeaders(const ELFFile &ElfFile) { uint32_t Index = 0; @@ -898,7 +906,22 @@ OrderedSegments.push_back(Section->ParentSegment); } } - OrderSegments(OrderedSegments); + + // For binary output, we're going to use physical addresses instead of + // virtual addresses, since a binary output is used for cases like rom + // loading and physical addresses are intended for rom loading. + // However, if no segment has a physical address, we'll fallback to using + // virtual addresses for all. + if (std::all_of(std::begin(OrderedSegments), std::end(OrderedSegments), + [](const Segment *Segment) { + return Segment->PAddr == 0; + })) + for (const auto &Segment: OrderedSegments) + Segment->PAddr = Segment->VAddr; + + std::stable_sort(std::begin(OrderedSegments), std::end(OrderedSegments), + compareSegmentsUsingPAddr); + // Because we add a ParentSegment for each section we might have duplicate // segments in OrderedSegments. If there were duplicates then LayoutSegments // would do very strange things. @@ -906,6 +929,8 @@ std::unique(std::begin(OrderedSegments), std::end(OrderedSegments)); OrderedSegments.erase(End, std::end(OrderedSegments)); + uint64_t Offset = 0; + // Modify the first segment so that there is no gap at the start. This allows // our layout algorithm to proceed as expected while not out writing out the // gap at the start. @@ -917,16 +942,19 @@ // The size needs to be shrunk as well Seg->FileSize -= Diff; Seg->MemSize -= Diff; - // The VAddr needs to be adjusted so that the alignment is correct as well + // The VAddr and PAddr need to be adjusted so that the alignment is correct Seg->VAddr += Diff; - Seg->PAddr = Seg->VAddr; + Seg->PAddr += Diff; // We don't want this to be shifted by alignment so we need to set the // alignment to zero. Seg->Align = 0; + uint64_t LowestPAddr = Seg->PAddr; + for (auto &Segment : OrderedSegments) { + Segment->Offset = Segment->PAddr - LowestPAddr; + Offset = std::max(Offset, Segment->Offset + Segment->FileSize); + } } - uint64_t Offset = LayoutSegments(OrderedSegments, 0); - // TODO: generalize LayoutSections to take a range. Pass a special range // constructed from an iterator that skips values for which a predicate does // not hold. Then pass such a range to LayoutSections instead of constructing