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: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -720,7 +720,7 @@ // an Offset. It assumes that Segments have been sorted by OrderSegments and // returns an Offset one past the end of the last segment. static uint64_t LayoutSegments(std::vector &Segments, - uint64_t Offset) { + uint64_t Offset, bool UsePAddr = false) { assert(std::is_sorted(std::begin(Segments), std::end(Segments), compareSegments)); // The only way a segment should move is if a section was between two @@ -738,7 +738,10 @@ Segment->Offset = Parent->Offset + Segment->OriginalOffset - Parent->OriginalOffset; } else { - Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align); + if (UsePAddr) + Offset = alignToAddr(Offset, Segment->PAddr, Segment->Align); + else + Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align); Segment->Offset = Offset; } Offset = std::max(Offset, Segment->Offset + Segment->FileSize); @@ -884,6 +887,22 @@ std::unique(std::begin(OrderedSegments), std::end(OrderedSegments)); OrderedSegments.erase(End, std::end(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. + bool HasAnyPAddr = false; + for (const auto &Segment: OrderedSegments) { + if (Segment->PAddr != 0) { + HasAnyPAddr = true; + break; + } + } + if (!HasAnyPAddr) + for (const auto &Segment: OrderedSegments) + Segment->PAddr = Segment->VAddr; + // 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. @@ -897,13 +916,13 @@ Seg->MemSize -= Diff; // The VAddr needs to be adjusted so that the alignment is correct as well 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 Offset = LayoutSegments(OrderedSegments, 0); + uint64_t Offset = LayoutSegments(OrderedSegments, 0, true); // TODO: generalize LayoutSections to take a range. Pass a special range // constructed from an iterator that skips values for which a predicate does