[PATCH] D122459: [ELF] Fix relocations against .eh_frame
Ayrton Muñoz via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 24 22:00:18 PDT 2022
ayrtonm created this revision.
ayrtonm added a reviewer: ruiu.
Herald added subscribers: atanasyan, jrtc27, JDevlieghere, arichardson, emaste.
Herald added a reviewer: MaskRay.
Herald added a project: All.
ayrtonm requested review of this revision.
Herald added subscribers: llvm-commits, StephenFan.
Herald added a project: LLVM.
`SectionBase::getOffset` translates offsets in input sections to offsets in the
output sections, but it previously returned input offsets unchanged for
.eh_frame. This gives incorrect offsets for relocations against .eh_frame when
linking multiple .eh_frame sections. This commit calculates the output offset
the same way as MergeInputSection since both are handled as a vector of section
pieces instead of a single blob. This fixes unwinding in the simplest scenarios
on the rust psp target.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D122459
Files:
lld/ELF/InputSection.cpp
lld/ELF/InputSection.h
lld/test/ELF/mips-eh_frame-offset.s
Index: lld/test/ELF/mips-eh_frame-offset.s
===================================================================
--- /dev/null
+++ lld/test/ELF/mips-eh_frame-offset.s
@@ -0,0 +1,18 @@
+# REQUIRES: mips
+## Check that offsets for emitted relocations are correct when linking multiple
+## .eh_frame sections
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t-1.o
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t-2.o
+# RUN: ld.lld --emit-relocs --entry=0 %t-1.o %t-2.o -o %t.exe
+# RUN: llvm-readobj -r %t.exe | FileCheck %s --check-prefix=RELOCS
+
+# RELOCS: [[OFFSET:0x[0-9,A-F]+]] R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# RELOCS-NOT: [[OFFSET]] R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE .text 0x10
+
+.ent func
+func:
+ .cfi_startproc
+ nop
+ .cfi_endproc
+.end func
Index: lld/ELF/InputSection.h
===================================================================
--- lld/ELF/InputSection.h
+++ lld/ELF/InputSection.h
@@ -325,6 +325,15 @@
SmallVector<EhSectionPiece, 0> pieces;
SyntheticSection *getParent() const;
+ // Translate an offset in the input section to an offset in the parent
+ // MergeSyntheticSection.
+ uint64_t getParentOffset(uint64_t offset) const;
+
+ // Returns the SectionPiece at a given input section offset.
+ EhSectionPiece *getSectionPiece(uint64_t offset);
+ const EhSectionPiece *getSectionPiece(uint64_t offset) const {
+ return const_cast<EhInputSection *>(this)->getSectionPiece(offset);
+ }
};
// This is a section that is added directly to an output section
Index: lld/ELF/InputSection.cpp
===================================================================
--- lld/ELF/InputSection.cpp
+++ lld/ELF/InputSection.cpp
@@ -160,11 +160,15 @@
case Regular:
case Synthetic:
return cast<InputSection>(this)->outSecOff + offset;
- case EHFrame:
+ case EHFrame: {
// The file crtbeginT.o has relocations pointing to the start of an empty
// .eh_frame that is known to be the first in the link. It does that to
// identify the start of the output .eh_frame.
- return offset;
+ const EhInputSection *es = cast<EhInputSection>(this);
+ if (InputSection *isec = es->getParent())
+ return isec->outSecOff + es->getParentOffset(offset);
+ return es->getParentOffset(offset);
+ }
case Merge:
const MergeInputSection *ms = cast<MergeInputSection>(this);
if (InputSection *isec = ms->getParent())
@@ -1334,6 +1338,29 @@
getObjMsg(d.data() - rawData.data()));
}
+EhSectionPiece *EhInputSection::getSectionPiece(uint64_t offset) {
+ if (this->data().size() <= offset)
+ fatal(toString(this) + ": offset is outside the section");
+
+ // If Offset is not at beginning of a section piece, it is not in the map.
+ // In that case we need to do a binary search of the original section piece
+ // vector.
+ auto it = partition_point(
+ pieces, [=](EhSectionPiece p) { return p.inputOff <= offset; });
+ return &it[-1];
+}
+
+// Returns the offset in an output section for a given input offset.
+// Because contents of an eh_frame section is not contiguous in input,
+// it is not just an addition to a base output offset.
+uint64_t EhInputSection::getParentOffset(uint64_t offset) const {
+ // If Offset is not at beginning of a section piece, it is not in the map.
+ // In that case we need to search from the original section piece vector.
+ const EhSectionPiece &piece = *getSectionPiece(offset);
+ uint64_t addend = offset - piece.inputOff;
+ return piece.outputOff + addend;
+}
+
static size_t findNull(StringRef s, size_t entSize) {
for (unsigned i = 0, n = s.size(); i != n; i += entSize) {
const char *b = s.begin() + i;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D122459.418130.patch
Type: text/x-patch
Size: 3711 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220325/02d5e3e8/attachment.bin>
More information about the llvm-commits
mailing list