llvm.org GIT mirror llvm / 7cc02fd
[llvm-objcopy] Fix SHT_GROUP ordering. Summary: When llvm-objcopy sorts sections during finalization, it only sorts based on the offset, which can cause the group section to come after the sections it contains. This causes link failures when using gold to link objects created by llvm-objcopy. Fix this for now by copying GNU objcopy's behavior of placing SHT_GROUP sections first. In the future, we may want to remove this sorting entirely to more closely preserve the input file layout. This fixes https://bugs.llvm.org/show_bug.cgi?id=42052. Reviewers: jakehehrlich, jhenderson, MaskRay, espindola, alexshap Reviewed By: MaskRay Subscribers: phuongtrang148993, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62620 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362973 91177308-0d34-0410-b5e6-96231b3b80d8 Jordan Rupprecht 4 months ago
5 changed file(s) with 82 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
1313 # CHECK: .debug_foo:
1414 # CHECK-NEXT: 0000 00000000 00000000
1515
16 # CHECK-HEADER: Index: 1
17 # CHECK-HEADER-NEXT: Name: .debug_foo
16 # CHECK-HEADER: Name: .debug_foo
1817 # CHECK-HEADER-NEXT: Type: SHT_PROGBITS
1918 # CHECK-HEADER-NEXT: Flags [
2019 # CHECK-HEADER-NEXT: ]
2625 # CHECK-COMPRESSED: ZLIB
2726 # CHECK-COMPRESSED: .notdebug_foo:
2827
29 # CHECK-FLAGS-NOT: Name: .debug_foo
30 # CHECK-FLAGS: Index: 1
31 # CHECK-FLAGS-NEXT: Name: .zdebug_foo
28 # CHECK-FLAGS-NOT: Name: .debug_foo
29 # CHECK-FLAGS: Name: .zdebug_foo
3230 # CHECK-FLAGS-NEXT: Type: SHT_PROGBITS
3331 # CHECK-FLAGS-NEXT: Flags [
3432 # CHECK-FLAGS-NEXT: ]
4846 # CHECK-FLAGS-NEXT: Type: SHT_RELA
4947 # CHECK-FLAGS-NEXT: Flags [
5048 # CHECK-FLAGS-NEXT: ]
51 # CHECK-FLAGS-NEXT: Address:
52 # CHECK-FLAGS-NEXT: Offset:
53 # CHECK-FLAGS-NEXT: Size:
54 # CHECK-FLAGS-NEXT: Link:
55 # CHECK-FLAGS-NEXT: Info: 1
5649
5750 # CHECK-FLAGS: Relocations [
5851 # CHECK-FLAGS-NEXT: .rela.debug_foo {
1313 # CHECK: .debug_foo:
1414 # CHECK-NEXT: 0000 00000000 00000000
1515
16 # CHECK-HEADER: Index: 1
17 # CHECK-HEADER-NEXT: Name: .debug_foo
16 # CHECK-HEADER: Name: .debug_foo
1817 # CHECK-HEADER-NEXT: Type: SHT_PROGBITS
1918 # CHECK-HEADER-NEXT: Flags [
2019 # CHECK-HEADER-NEXT: ]
2524 # CHECK-COMPRESSED: .debug_foo:
2625 # CHECK-COMPRESSED: .notdebug_foo:
2726
28 # CHECK-FLAGS: Index: 1
29 # CHECK-FLAGS-NEXT: Name: .debug_foo
27 # CHECK-FLAGS: Name: .debug_foo
3028 # CHECK-FLAGS-NEXT: Type: SHT_PROGBITS
3129 # CHECK-FLAGS-NEXT: Flags [
3230 # CHECK-FLAGS-NEXT: SHF_COMPRESSED
5250 # CHECK-FLAGS-NEXT: Offset:
5351 # CHECK-FLAGS-NEXT: Size:
5452 # CHECK-FLAGS-NEXT: Link:
55 # CHECK-FLAGS-NEXT: Info: 1
5653
5754 # CHECK-FLAGS: Relocations [
5855 # CHECK-FLAGS-NEXT: .rela.debug_foo {
0 # RUN: yaml2obj %s > %t.o
1 # RUN: llvm-objcopy %t.o %t.2.o
2 # RUN: llvm-readelf --elf-section-groups --sections %t.o | FileCheck %s --check-prefix=IN
3 # RUN: llvm-readelf --elf-section-groups --sections %t.2.o | FileCheck %s --check-prefix=OUT
4
5 # In this test, .group gets moved to the beginning. Run readelf -gS on input as
6 # well as output to make sure it really moved, as well as to verify that we
7 # aren't purely sorting based on offsets (it gets moved to the beginning
8 # despite having a larger offset).
9
10 # IN: There are 7 section headers, starting at offset 0x40:
11 # IN: [Nr] Name Type Address Off Size
12 # IN-NEXT: [ 0] NULL 0000000000000000 000000 000000
13 # IN-NEXT: [ 1] .foo PROGBITS 0000000000000000 000200 000040
14 # IN-NEXT: [ 2] .group GROUP 0000000000000000 000240 000008
15 # IN-NEXT: [ 3] .bar PROGBITS 0000000000000000 000248 000040
16
17 # IN: COMDAT group section [ 2] `.group' [bar] contains 1 sections:
18 # IN-NEXT: [Index] Name
19 # IN-NEXT: [ 3] .bar
20
21 # OUT: There are 7 section headers, starting at offset 0x160:
22 # OUT: [Nr] Name Type Address Off Size
23 # OUT-NEXT: [ 0] NULL 0000000000000000 000000 000000
24 # OUT-NEXT: [ 1] .group GROUP 0000000000000000 000040 000008
25 # OUT-NEXT: [ 2] .foo PROGBITS 0000000000000000 000048 000040
26 # OUT-NEXT: [ 3] .bar PROGBITS 0000000000000000 000088 000040
27
28 # OUT: COMDAT group section [ 1] `.group' [bar] contains 1 sections:
29 # OUT-NEXT: [Index] Name
30 # OUT-NEXT: [ 3] .bar
31
32 --- !ELF
33 FileHeader:
34 Class: ELFCLASS64
35 Data: ELFDATA2LSB
36 Type: ET_REL
37 Machine: EM_X86_64
38 Sections:
39 - Name: .foo
40 Type: SHT_PROGBITS
41 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
42 Size: 64
43 - Name: .group
44 Type: SHT_GROUP
45 Link: .symtab
46 Info: bar
47 Members:
48 - SectionOrType: GRP_COMDAT
49 - SectionOrType: .bar
50 - Name: .bar
51 Type: SHT_PROGBITS
52 Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
53 Size: 64
54 Symbols:
55 - Name: .foo
56 Type: STT_SECTION
57 Section: .foo
58 - Name: .bar
59 Type: STT_SECTION
60 Section: .bar
61 - Name: bar
62 Type: STT_FUNC
63 Section: .foo
2626 // Link, Info and the content of this section.
2727
2828 CHECK: Name: .group (179)
29 CHECK-NEXT: Index: 17
29 CHECK-NEXT: Index: 1{{$}}
3030 CHECK-NEXT: Link: 19
3131 CHECK-NEXT: Info: 14
32 CHECK: .text._ZN1SIiE4getXEv (2)
32 CHECK: .text._ZN1SIiE4getXEv
3333
3434 CHECK: Name: .group (179)
35 CHECK-NEXT: Index: 18
35 CHECK-NEXT: Index: 2{{$}}
3636 CHECK-NEXT: Link: 19
3737 CHECK-NEXT: Info: 13
38 CHECK: .text._ZN1SIdE4getXEv (4)
39 CHECK-NEXT: .rela.text._ZN1SIdE4getXEv (21)
38 CHECK: .text._ZN1SIdE4getXEv
39 CHECK-NEXT: .rela.text._ZN1SIdE4getXEv
16671667 }
16681668
16691669 void Object::sortSections() {
1670 // Put all sections in offset order. Maintain the ordering as closely as
1671 // possible while meeting that demand however.
1670 // Use stable_sort to maintain the original ordering as closely as possible.
16721671 llvm::stable_sort(Sections, [](const SecPtr &A, const SecPtr &B) {
1672 // Put SHT_GROUP sections first, since group section headers must come
1673 // before the sections they contain. This also matches what GNU objcopy
1674 // does.
1675 if (A->Type != B->Type &&
1676 (A->Type == ELF::SHT_GROUP || B->Type == ELF::SHT_GROUP))
1677 return A->Type == ELF::SHT_GROUP;
1678 // For all other sections, sort by offset order.
16731679 return A->OriginalOffset < B->OriginalOffset;
16741680 });
16751681 }