Skip to content

Commit f8f9d65

Browse files
committed
[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 llvm-svn: 362973
1 parent b0f98d3 commit f8f9d65

File tree

5 files changed

+82
-22
lines changed

5 files changed

+82
-22
lines changed

llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
# CHECK: .debug_foo:
1515
# CHECK-NEXT: 0000 00000000 00000000
1616

17-
# CHECK-HEADER: Index: 1
18-
# CHECK-HEADER-NEXT: Name: .debug_foo
17+
# CHECK-HEADER: Name: .debug_foo
1918
# CHECK-HEADER-NEXT: Type: SHT_PROGBITS
2019
# CHECK-HEADER-NEXT: Flags [
2120
# CHECK-HEADER-NEXT: ]
@@ -27,9 +26,8 @@
2726
# CHECK-COMPRESSED: ZLIB
2827
# CHECK-COMPRESSED: .notdebug_foo:
2928

30-
# CHECK-FLAGS-NOT: Name: .debug_foo
31-
# CHECK-FLAGS: Index: 1
32-
# CHECK-FLAGS-NEXT: Name: .zdebug_foo
29+
# CHECK-FLAGS-NOT: Name: .debug_foo
30+
# CHECK-FLAGS: Name: .zdebug_foo
3331
# CHECK-FLAGS-NEXT: Type: SHT_PROGBITS
3432
# CHECK-FLAGS-NEXT: Flags [
3533
# CHECK-FLAGS-NEXT: ]
@@ -49,11 +47,6 @@
4947
# CHECK-FLAGS-NEXT: Type: SHT_RELA
5048
# CHECK-FLAGS-NEXT: Flags [
5149
# CHECK-FLAGS-NEXT: ]
52-
# CHECK-FLAGS-NEXT: Address:
53-
# CHECK-FLAGS-NEXT: Offset:
54-
# CHECK-FLAGS-NEXT: Size:
55-
# CHECK-FLAGS-NEXT: Link:
56-
# CHECK-FLAGS-NEXT: Info: 1
5750

5851
# CHECK-FLAGS: Relocations [
5952
# CHECK-FLAGS-NEXT: .rela.debug_foo {

llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
# CHECK: .debug_foo:
1515
# CHECK-NEXT: 0000 00000000 00000000
1616

17-
# CHECK-HEADER: Index: 1
18-
# CHECK-HEADER-NEXT: Name: .debug_foo
17+
# CHECK-HEADER: Name: .debug_foo
1918
# CHECK-HEADER-NEXT: Type: SHT_PROGBITS
2019
# CHECK-HEADER-NEXT: Flags [
2120
# CHECK-HEADER-NEXT: ]
@@ -26,8 +25,7 @@
2625
# CHECK-COMPRESSED: .debug_foo:
2726
# CHECK-COMPRESSED: .notdebug_foo:
2827

29-
# CHECK-FLAGS: Index: 1
30-
# CHECK-FLAGS-NEXT: Name: .debug_foo
28+
# CHECK-FLAGS: Name: .debug_foo
3129
# CHECK-FLAGS-NEXT: Type: SHT_PROGBITS
3230
# CHECK-FLAGS-NEXT: Flags [
3331
# CHECK-FLAGS-NEXT: SHF_COMPRESSED
@@ -53,7 +51,6 @@
5351
# CHECK-FLAGS-NEXT: Offset:
5452
# CHECK-FLAGS-NEXT: Size:
5553
# CHECK-FLAGS-NEXT: Link:
56-
# CHECK-FLAGS-NEXT: Info: 1
5754

5855
# CHECK-FLAGS: Relocations [
5956
# CHECK-FLAGS-NEXT: .rela.debug_foo {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# RUN: yaml2obj %s > %t.o
2+
# RUN: llvm-objcopy %t.o %t.2.o
3+
# RUN: llvm-readelf --elf-section-groups --sections %t.o | FileCheck %s --check-prefix=IN
4+
# RUN: llvm-readelf --elf-section-groups --sections %t.2.o | FileCheck %s --check-prefix=OUT
5+
6+
# In this test, .group gets moved to the beginning. Run readelf -gS on input as
7+
# well as output to make sure it really moved, as well as to verify that we
8+
# aren't purely sorting based on offsets (it gets moved to the beginning
9+
# despite having a larger offset).
10+
11+
# IN: There are 7 section headers, starting at offset 0x40:
12+
# IN: [Nr] Name Type Address Off Size
13+
# IN-NEXT: [ 0] NULL 0000000000000000 000000 000000
14+
# IN-NEXT: [ 1] .foo PROGBITS 0000000000000000 000200 000040
15+
# IN-NEXT: [ 2] .group GROUP 0000000000000000 000240 000008
16+
# IN-NEXT: [ 3] .bar PROGBITS 0000000000000000 000248 000040
17+
18+
# IN: COMDAT group section [ 2] `.group' [bar] contains 1 sections:
19+
# IN-NEXT: [Index] Name
20+
# IN-NEXT: [ 3] .bar
21+
22+
# OUT: There are 7 section headers, starting at offset 0x160:
23+
# OUT: [Nr] Name Type Address Off Size
24+
# OUT-NEXT: [ 0] NULL 0000000000000000 000000 000000
25+
# OUT-NEXT: [ 1] .group GROUP 0000000000000000 000040 000008
26+
# OUT-NEXT: [ 2] .foo PROGBITS 0000000000000000 000048 000040
27+
# OUT-NEXT: [ 3] .bar PROGBITS 0000000000000000 000088 000040
28+
29+
# OUT: COMDAT group section [ 1] `.group' [bar] contains 1 sections:
30+
# OUT-NEXT: [Index] Name
31+
# OUT-NEXT: [ 3] .bar
32+
33+
--- !ELF
34+
FileHeader:
35+
Class: ELFCLASS64
36+
Data: ELFDATA2LSB
37+
Type: ET_REL
38+
Machine: EM_X86_64
39+
Sections:
40+
- Name: .foo
41+
Type: SHT_PROGBITS
42+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
43+
Size: 64
44+
- Name: .group
45+
Type: SHT_GROUP
46+
Link: .symtab
47+
Info: bar
48+
Members:
49+
- SectionOrType: GRP_COMDAT
50+
- SectionOrType: .bar
51+
- Name: .bar
52+
Type: SHT_PROGBITS
53+
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
54+
Size: 64
55+
Symbols:
56+
- Name: .foo
57+
Type: STT_SECTION
58+
Section: .foo
59+
- Name: .bar
60+
Type: STT_SECTION
61+
Section: .bar
62+
- Name: bar
63+
Type: STT_FUNC
64+
Section: .foo

llvm/test/tools/llvm-objcopy/ELF/strip-dwo-groups.test

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
// Link, Info and the content of this section.
2828

2929
CHECK: Name: .group (179)
30-
CHECK-NEXT: Index: 17
30+
CHECK-NEXT: Index: 1{{$}}
3131
CHECK-NEXT: Link: 19
3232
CHECK-NEXT: Info: 14
33-
CHECK: .text._ZN1SIiE4getXEv (2)
33+
CHECK: .text._ZN1SIiE4getXEv
3434

3535
CHECK: Name: .group (179)
36-
CHECK-NEXT: Index: 18
36+
CHECK-NEXT: Index: 2{{$}}
3737
CHECK-NEXT: Link: 19
3838
CHECK-NEXT: Info: 13
39-
CHECK: .text._ZN1SIdE4getXEv (4)
40-
CHECK-NEXT: .rela.text._ZN1SIdE4getXEv (21)
39+
CHECK: .text._ZN1SIdE4getXEv
40+
CHECK-NEXT: .rela.text._ZN1SIdE4getXEv

llvm/tools/llvm-objcopy/ELF/Object.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,9 +1668,15 @@ Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
16681668
}
16691669

16701670
void Object::sortSections() {
1671-
// Put all sections in offset order. Maintain the ordering as closely as
1672-
// possible while meeting that demand however.
1671+
// Use stable_sort to maintain the original ordering as closely as possible.
16731672
llvm::stable_sort(Sections, [](const SecPtr &A, const SecPtr &B) {
1673+
// Put SHT_GROUP sections first, since group section headers must come
1674+
// before the sections they contain. This also matches what GNU objcopy
1675+
// does.
1676+
if (A->Type != B->Type &&
1677+
(A->Type == ELF::SHT_GROUP || B->Type == ELF::SHT_GROUP))
1678+
return A->Type == ELF::SHT_GROUP;
1679+
// For all other sections, sort by offset order.
16741680
return A->OriginalOffset < B->OriginalOffset;
16751681
});
16761682
}

0 commit comments

Comments
 (0)