[lld] 86ab98b - [ELF] -r: rewrite SHT_GROUP content if some members are combined or discarded
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 21 08:49:54 PDT 2020
Author: Fangrui Song
Date: 2020-07-21T08:49:45-07:00
New Revision: 86ab98b0014662f489dbee97f7d3b8d2569e37cc
URL: https://github.com/llvm/llvm-project/commit/86ab98b0014662f489dbee97f7d3b8d2569e37cc
DIFF: https://github.com/llvm/llvm-project/commit/86ab98b0014662f489dbee97f7d3b8d2569e37cc.diff
LOG: [ELF] -r: rewrite SHT_GROUP content if some members are combined or discarded
* If two group members are combined, we should leave just one index in the SHT_GROUP content.
* If a group member is discarded (/DISCARD/ or upcoming -r --gc-sections combination),
we should drop its index in the SHT_GROUP content. LLD currently crashes (`getOutputSection()` is null).
Reviewed By: psmith
Differential Revision: https://reviews.llvm.org/D84129
Added:
Modified:
lld/ELF/InputSection.cpp
lld/ELF/OutputSections.cpp
lld/test/ELF/relocatable-comdat.s
Removed:
################################################################################
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 7a7ebd974909..0a97b6aa2f50 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -28,6 +28,7 @@
#include <algorithm>
#include <mutex>
#include <set>
+#include <unordered_set>
#include <vector>
using namespace llvm;
@@ -389,11 +390,16 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *buf) {
// The first entry is not a section number but a flag.
*to++ = from[0];
- // Adjust section numbers because section numbers in an input object
- // files are
diff erent in the output.
+ // Adjust section numbers because section numbers in an input object files are
+ //
diff erent in the output. We also need to handle combined or discarded
+ // members.
ArrayRef<InputSectionBase *> sections = file->getSections();
- for (uint32_t idx : from.slice(1))
- *to++ = sections[idx]->getOutputSection()->sectionIndex;
+ std::unordered_set<uint32_t> seen;
+ for (uint32_t idx : from.slice(1)) {
+ OutputSection *osec = sections[idx]->getOutputSection();
+ if (osec && seen.insert(osec->sectionIndex).second)
+ *to++ = osec->sectionIndex;
+ }
}
InputSectionBase *InputSection::getRelocatedSection() const {
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 7e9e76b070ec..3864a4143d2b 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -21,6 +21,7 @@
#include "llvm/Support/Parallel.h"
#include "llvm/Support/SHA1.h"
#include <regex>
+#include <unordered_set>
using namespace llvm;
using namespace llvm::dwarf;
@@ -376,6 +377,15 @@ static void finalizeShtGroup(OutputSection *os,
// provides signature of the section group.
ArrayRef<Symbol *> symbols = section->file->getSymbols();
os->info = in.symTab->getSymbolIndex(symbols[section->info]);
+
+ // Some group members may be combined or discarded, so we need to compute the
+ // new size. The content will be rewritten in InputSection::copyShtGroup.
+ std::unordered_set<uint32_t> seen;
+ ArrayRef<InputSectionBase *> sections = section->file->getSections();
+ for (const uint32_t &idx : section->getDataAs<uint32_t>().slice(1))
+ if (OutputSection *osec = sections[read32(&idx)]->getOutputSection())
+ seen.insert(osec->sectionIndex);
+ os->size = (1 + seen.size()) * sizeof(uint32_t);
}
void OutputSection::finalize() {
diff --git a/lld/test/ELF/relocatable-comdat.s b/lld/test/ELF/relocatable-comdat.s
index 213d14bd2cc6..b290bae4ee32 100644
--- a/lld/test/ELF/relocatable-comdat.s
+++ b/lld/test/ELF/relocatable-comdat.s
@@ -1,45 +1,52 @@
# REQUIRES: x86
+## Test that SHT_GROUP sections are retained in relocatable output. The content
+## may be rewritten because group members may change their indices. Additionally,
+## group member may be combined or discarded (e.g. /DISCARD/ or --gc-sections).
+
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: ld.lld -r %t.o %t.o -o %t
-# RUN: llvm-readobj --elf-section-groups --sections %t | FileCheck %s
-
-# CHECK: Name: .text.bar
-# CHECK-NEXT: Type: SHT_PROGBITS
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: SHF_ALLOC
-# CHECK-NEXT: SHF_EXECINSTR
-# CHECK-NEXT: SHF_GROUP
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset:
-# CHECK-NEXT: Size: 8
-# CHECK: Section {
-# CHECK-NEXT: Index: 4
-# CHECK-NEXT: Name: .text.foo
-# CHECK-NEXT: Type: SHT_PROGBITS
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: SHF_ALLOC
-# CHECK-NEXT: SHF_EXECINSTR
-# CHECK-NEXT: SHF_GROUP
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset:
-# CHECK-NEXT: Size: 4
-
-# CHECK: Groups {
-# CHECK-NEXT: Group {
-# CHECK-NEXT: Name: .group
-# CHECK-NEXT: Index: 2
-# CHECK-NEXT: Link: 6
-# CHECK-NEXT: Info: 1
-# CHECK-NEXT: Type: COMDAT
-# CHECK-NEXT: Signature: abc
-# CHECK-NEXT: Section(s) in group [
-# CHECK-NEXT: .text.bar
-# CHECK-NEXT: .text.foo
-# CHECK-NEXT: ]
-# CHECK-NEXT: }
-# CHECK-NEXT: }
+# RUN: ld.lld -r %t.o %t.o -o %t.ro
+# RUN: llvm-readelf -g -S %t.ro | FileCheck %s
+
+# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
+# CHECK: .group GROUP 0000000000000000 {{.*}} 000014 04 {{[1-9]}} 1 4
+
+# CHECK: COMDAT group section [{{.*}}] `.group' [abc] contains 4 sections:
+# CHECK-NEXT: Name
+# CHECK-NEXT: .rodata.bar
+# CHECK-NEXT: .rodata.foo
+# CHECK-NEXT: .text.bar
+# CHECK-NEXT: .text.foo
+
+## Rewrite SHT_GROUP content if some members are combined.
+# RUN: echo 'SECTIONS { .rodata : {*(.rodata.*)} .text : {*(.text.*)} }' > %t1.lds
+# RUN: ld.lld -r -T %t1.lds %t.o %t.o -o %t1.ro
+# RUN: llvm-readelf -g -S %t1.ro | FileCheck %s --check-prefix=SCRIPT1
+
+# SCRIPT1: Name Type Address Off Size ES Flg Lk Inf Al
+# SCRIPT1: .group GROUP 0000000000000000 {{.*}} 00000c 04 {{[1-9]}} 1 4
+
+# SCRIPT1: COMDAT group section [{{.*}}] `.group' [abc] contains 2 sections:
+# SCRIPT1-NEXT: Name
+# SCRIPT1-NEXT: .rodata
+# SCRIPT1-NEXT: .text
+
+# RUN: echo 'SECTIONS { /DISCARD/ : {*(.rodata.*)} }' > %t2.lds
+# RUN: ld.lld -r -T %t2.lds %t.o %t.o -o %t2.ro
+# RUN: llvm-readelf -g -S %t2.ro | FileCheck %s --check-prefix=SCRIPT2
+
+## Handle discarded group members.
+# SCRIPT2: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# SCRIPT2: [ 2] .group GROUP 0000000000000000 {{.*}} 00000c 04 {{[1-9]}} 1 4
+
+# SCRIPT2: COMDAT group section [{{.*}}] `.group' [abc] contains 2 sections:
+# SCRIPT2-NEXT: Name
+# SCRIPT2-NEXT: .text.bar
+# SCRIPT2-NEXT: .text.foo
+
+.section .rodata.bar,"aG", at progbits,abc,comdat
+.byte 42
+.section .rodata.foo,"aG", at progbits,abc,comdat
+.byte 42
.section .text.bar,"axG", at progbits,abc,comdat
.quad 42
More information about the llvm-commits
mailing list