llvm.org GIT mirror llvm / 89fd072
[llvm-objcopy] Fix bug in how segment alignment was being handled Just aligning segment offsets to segment alignment is incorrect and also wastes more space than is needed. The requirement is that p_offset == p_addr modulo p_align *not* that p_offset == 0 modulo p_align. Generally speaking we've been using p_addr == 0 modulo p_align. In fact yaml2obj can't even produce a valid situation which causes llvm-objcopy to produce incorrect results because alignment and offset were both inherited from the sections the program header covers. This change fixes this bad behavior in llvm-objcopy. Differential Revision: https://reviews.llvm.org/D39132 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317284 91177308-0d34-0410-b5e6-96231b3b80d8 Jake Ehrlich 1 year, 11 months ago
3 changed file(s) with 124 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
0 # RUN: yaml2obj %s -o %t
1 # RUN: llvm-objcopy -O binary %t %t2
2 # RUN: od -t x1 %t2 | FileCheck %s
3
4 !ELF
5 FileHeader:
6 Class: ELFCLASS64
7 Data: ELFDATA2LSB
8 Type: ET_EXEC
9 Machine: EM_X86_64
10 Sections:
11 - Name: .text
12 Type: SHT_PROGBITS
13 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
14 Address: 0x1000
15 AddressAlign: 0x0000000000001000
16 Content: "c3c3c3c3"
17 - Name: .data
18 Type: SHT_PROGBITS
19 Flags: [ SHF_ALLOC ]
20 Address: 0x1008
21 AddressAlign: 0x0000000000000008
22 Content: "3232"
23 ProgramHeaders:
24 - Type: PT_LOAD
25 Flags: [ PF_X, PF_R ]
26 VAddr: 0x1000
27 PAddr: 0x1000
28 Align: 0x1000
29 Sections:
30 - Section: .text
31 - Type: PT_LOAD
32 Flags: [ PF_R, PF_W ]
33 VAddr: 0x1008
34 PAddr: 0x1008
35 Align: 0x1000
36 Sections:
37 - Section: .data
38
39 # CHECK: 0000000 c3 c3 c3 c3 00 00 00 00 32 32
0 # RUN: yaml2obj %s -o %t
1 # RUN: llvm-objcopy %t %t2
2 # RUN: llvm-readobj -program-headers %t2 | FileCheck %s
3
4 !ELF
5 FileHeader:
6 Class: ELFCLASS64
7 Data: ELFDATA2LSB
8 Type: ET_EXEC
9 Machine: EM_X86_64
10 Sections:
11 - Name: .text
12 Type: SHT_PROGBITS
13 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
14 Address: 0x1000
15 AddressAlign: 0x0000000000001000
16 Content: "c3c3c3c3"
17 - Name: .data
18 Type: SHT_PROGBITS
19 Flags: [ SHF_ALLOC ]
20 Address: 0x1008
21 AddressAlign: 0x0000000000000008
22 Content: "3232"
23 ProgramHeaders:
24 - Type: PT_LOAD
25 Flags: [ PF_X, PF_R ]
26 VAddr: 0x1000
27 PAddr: 0x1000
28 Align: 0x1000
29 Sections:
30 - Section: .text
31 - Type: PT_LOAD
32 Flags: [ PF_R, PF_W ]
33 VAddr: 0x1008
34 PAddr: 0x1008
35 Align: 0x1000
36 Sections:
37 - Section: .data
38
39 #CHECK: ProgramHeaders [
40 #CHECK-NEXT: ProgramHeader {
41 #CHECK-NEXT: Type: PT_LOAD
42 #CHECK-NEXT: Offset: 0x1000
43 #CHECK-NEXT: VirtualAddress: 0x1000
44 #CHECK-NEXT: PhysicalAddress: 0x1000
45 #CHECK-NEXT: FileSize: 4
46 #CHECK-NEXT: MemSize: 4
47 #CHECK-NEXT: Flags [
48 #CHECK-NEXT: PF_R
49 #CHECK-NEXT: PF_X
50 #CHECK-NEXT: ]
51 #CHECK-NEXT: Alignment: 4096
52 #CHECK-NEXT: }
53 #CHECK-NEXT: ProgramHeader {
54 #CHECK-NEXT: Type: PT_LOAD
55 #CHECK-NEXT: Offset: 0x1008
56 #CHECK-NEXT: VirtualAddress: 0x1008
57 #CHECK-NEXT: PhysicalAddress: 0x1008
58 #CHECK-NEXT: FileSize: 2
59 #CHECK-NEXT: MemSize: 2
60 #CHECK-NEXT: Flags [
61 #CHECK-NEXT: PF_R
62 #CHECK-NEXT: PF_W
63 #CHECK-NEXT: ]
64 #CHECK-NEXT: Alignment: 4096
65 #CHECK-NEXT: }
66 #CHECK-NEXT:]
682682 };
683683 std::stable_sort(std::begin(this->Sections), std::end(this->Sections),
684684 CompareSections);
685 }
686
687 static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
688 // Calculate Diff such that (Offset + Diff) & -Align == Addr & -Align.
689 if (Align == 0)
690 Align = 1;
691 auto Diff =
692 static_cast(Addr % Align) - static_cast(Offset % Align);
693 // We only want to add to Offset, however, so if Diff < 0 we can add Align and
694 // (Offset + Diff) & -Align == Addr & -Align will still hold.
695 if (Diff < 0)
696 Diff += Align;
697 return Offset + Diff;
685698 }
686699
687700 template void ELFObject::assignOffsets() {
727740 Segment->Offset =
728741 Parent->Offset + Segment->OriginalOffset - Parent->OriginalOffset;
729742 } else {
730 Offset = alignTo(Offset, Segment->Align == 0 ? 1 : Segment->Align);
743 Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align);
731744 Segment->Offset = Offset;
732745 }
733746 Offset = std::max(Offset, Segment->Offset + Segment->FileSize);
828841
829842 uint64_t Offset = 0;
830843 for (auto &Segment : this->Segments) {
831 if (Segment->Type == PT_LOAD && Segment->firstSection() != nullptr) {
832 Offset = alignTo(Offset, Segment->Align);
844 if (Segment->Type == llvm::ELF::PT_LOAD &&
845 Segment->firstSection() != nullptr) {
846 Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align);
833847 Segment->Offset = Offset;
834848 Offset += Segment->FileSize;
835849 }