[lld] r237491 - [LLD] Make sure MachO FDEs read their augmentation data strings from the right
Lang Hames
lhames at gmail.com
Fri May 15 17:08:02 PDT 2015
Author: lhames
Date: Fri May 15 19:08:02 2015
New Revision: 237491
URL: http://llvm.org/viewvc/llvm-project?rev=237491&view=rev
Log:
[LLD] Make sure MachO FDEs read their augmentation data strings from the right
CIE, not just the most recently encountered one.
Modified:
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
lld/trunk/test/mach-o/parse-eh-frame-relocs-x86_64.yaml
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=237491&r1=237490&r2=237491&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Fri May 15 19:08:02 2015
@@ -647,13 +647,15 @@ static int64_t readSPtr(bool is64, bool
/// --- Augmentation String Processing ---
-struct AugmentationDataInfo {
- bool _present = false;
+struct CIEInfo {
+ bool _augmentationDataPresent = false;
bool _mayHaveLSDA = false;
};
+typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
+
static std::error_code processAugmentationString(const uint8_t *augStr,
- AugmentationDataInfo &adi,
+ CIEInfo &cieInfo,
unsigned *len = nullptr) {
if (augStr[0] == '\0') {
@@ -666,12 +668,12 @@ static std::error_code processAugmentati
return make_dynamic_error_code("expected 'z' at start of augmentation "
"string");
- adi._present = true;
+ cieInfo._augmentationDataPresent = true;
uint64_t idx = 1;
while (augStr[idx] != '\0') {
if (augStr[idx] == 'L') {
- adi._mayHaveLSDA = true;
+ cieInfo._mayHaveLSDA = true;
++idx;
} else
++idx;
@@ -684,10 +686,12 @@ static std::error_code processAugmentati
static std::error_code processCIE(const NormalizedFile &normalizedFile,
MachODefinedAtom *atom,
- AugmentationDataInfo &adi) {
+ CIEInfoMap &cieInfos) {
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-
const uint8_t *frameData = atom->rawContent().data();
+
+ CIEInfo cieInfo;
+
uint32_t size = read32(frameData, isBig);
uint64_t cieIDField = size == 0xffffffffU
? sizeof(uint32_t) + sizeof(uint64_t)
@@ -696,9 +700,11 @@ static std::error_code processCIE(const
uint64_t augmentationStringField = versionField + sizeof(uint8_t);
if (auto err = processAugmentationString(frameData + augmentationStringField,
- adi))
+ cieInfo))
return err;
+ cieInfos[atom] = std::move(cieInfo);
+
return std::error_code();
}
@@ -708,7 +714,7 @@ static std::error_code processFDE(const
const Section *ehFrameSection,
MachODefinedAtom *atom,
uint64_t offset,
- const AugmentationDataInfo &adi) {
+ const CIEInfoMap &cieInfos) {
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
@@ -730,11 +736,16 @@ static std::error_code processFDE(const
cieAddress -= cieDelta;
Reference::Addend addend;
- const Atom *cie =
+ const MachODefinedAtom *cie =
findAtomCoveringAddress(normalizedFile, file, cieAddress, &addend);
atom->addReference(cieFieldInFDE, handler.unwindRefToCIEKind(), cie,
addend, handler.kindArch());
+ assert(cie && cie->contentType() == DefinedAtom::typeCFI && !addend &&
+ "FDE's CIE field does not point at the start of a CIE.");
+
+ const CIEInfo &cieInfo = cieInfos.find(cie)->second;
+
// Linker needs to fixup reference from the FDE to the function it's
// describing. FIXME: there are actually different ways to do this, and the
// particular method used is specified in the CIE's augmentation fields
@@ -752,7 +763,7 @@ static std::error_code processFDE(const
func, addend, handler.kindArch());
// Handle the augmentation data if there is any.
- if (adi._present) {
+ if (cieInfo._augmentationDataPresent) {
// First process the augmentation data length field.
uint64_t augmentationDataLengthFieldInFDE =
rangeFieldInFDE + 2 * (is64 ? sizeof(uint64_t) : sizeof(uint32_t));
@@ -761,7 +772,7 @@ static std::error_code processFDE(const
llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
&lengthFieldSize);
- if (adi._mayHaveLSDA && augmentationDataLength > 0) {
+ if (cieInfo._mayHaveLSDA && augmentationDataLength > 0) {
// Look at the augmentation data field.
uint64_t augmentationDataFieldInFDE =
@@ -800,7 +811,7 @@ std::error_code addEHFrameReferences(con
return std::error_code();
std::error_code ehFrameErr;
- AugmentationDataInfo adi;
+ CIEInfoMap cieInfos;
file.eachAtomInSection(*ehFrameSection,
[&](MachODefinedAtom *atom, uint64_t offset) -> void {
@@ -811,12 +822,11 @@ std::error_code addEHFrameReferences(con
return;
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- if (ArchHandler::isDwarfCIE(isBig, atom)) {
- adi = AugmentationDataInfo();
- ehFrameErr = processCIE(normalizedFile, atom, adi);
- } else
+ if (ArchHandler::isDwarfCIE(isBig, atom))
+ ehFrameErr = processCIE(normalizedFile, atom, cieInfos);
+ else
ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
- atom, offset, adi);
+ atom, offset, cieInfos);
});
return ehFrameErr;
Modified: lld/trunk/test/mach-o/parse-eh-frame-relocs-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-eh-frame-relocs-x86_64.yaml?rev=237491&r1=237490&r2=237491&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-eh-frame-relocs-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/parse-eh-frame-relocs-x86_64.yaml Fri May 15 19:08:02 2015
@@ -1,83 +1,110 @@
# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
#
# Test parsing of x86_64 __eh_frame (dwarf unwind) relocations.
-#
-#_catchMyException:
-# pushq %rbp
-# movq %rsp, %rbp
-# callq _foo
-# popq %rbp
-# retq
-# movq %rax, %rdi
-# callq ___cxa_begin_catch
-# popq %rbp
-# jmp ___cxa_end_catch
--- !mach-o
arch: x86_64
file-type: MH_OBJECT
-flags: [ ]
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 16
address: 0x0000000000000000
- content: [0x55, 0x48, 0x89, 0xe5, 0xe8, 0x00, 0x00, 0x00,
- 0x00, 0x5d, 0xc3, 0x48, 0x89, 0xc7, 0xe8, 0x00,
- 0x00, 0x00, 0x00, 0x5d, 0xe9, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000015
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000000f
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000005
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 0
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
+ 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
+ 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x66, 0x2E,
+ 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
+ 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
+ 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
+ 0x00 ]
- segment: __TEXT
section: __gcc_except_tab
type: S_REGULAR
attributes: [ ]
- address: 0x000000000000001c
- content: [ 0x00, 0x00, 0x00, 0x00 ]
+ alignment: 4
+ address: 0x000000000000004C
+ content: [ 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- segment: __TEXT
section: __eh_frame
type: S_COALESCED
attributes: [ ]
- address: 0x0000000000000020
- content: [ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7a, 0x50, 0x4c, 0x52, 0x00, 0x01, 0x78,
- 0x10, 0x07, 0x9b, 0x04, 0x00, 0x00, 0x00, 0x10,
- 0x10, 0x0c, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0xB8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ alignment: 8
+ address: 0x0000000000000100
+ content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
+ 0x10, 0x07, 0x9B, 0x04, 0x00, 0x00, 0x00, 0x10,
+ 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
+ 0x2C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0xD8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
+ 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
+ 0xB0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2C, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x98, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x41, 0x0e, 0x10, 0x86, 0x02, 0x43, 0x0d,
+ 0x08, 0xCB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000068
- content: [ 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000013
+ type: X86_64_RELOC_GOT
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 8
local-symbols:
- - name: _catchMyException
+ - name: GCC_except_table0
+ type: N_SECT
+ sect: 2
+ value: 0x000000000000004C
+ - name: GCC_except_table2
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000074
+global-symbols:
+ - name: _catchMyException1
type: N_SECT
+ scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
+ - name: _catchMyException2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000030
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000020
undefined-symbols:
- name: _foo
type: N_UNDF
@@ -91,17 +118,59 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
+ - name: ___gxx_personality_v0
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
...
+# Check that LSDA fields are fixed up correctly, even when there are multiple
+# CIEs involved.
+#
+# (1) Check that we can relocate an LSDA at all. Requires correct interpretation
+# of augmentation data strings in CIEs and augmentation data fields of FDEs.
+#
# CHECK: - type: unwind-cfi
# CHECK-NOT: - type:
# CHECK: references:
# CHECK-NEXT: - kind: negDelta32
# CHECK-NEXT: offset: 4
-# CHECK-NEXT: target: L000
+# CHECK-NEXT: target: L002
# CHECK-NEXT: - kind: unwindFDEToFunction
# CHECK-NEXT: offset: 8
-# CHECK-NEXT: target: _catchMyException
+# CHECK-NEXT: target: _catchMyException1
# CHECK-NEXT: - kind: unwindFDEToFunction
# CHECK-NEXT: offset: 25
+# CHECK-NEXT: target: GCC_except_table0
+#
+# (2) Check that we have an intervening FDE with a different CIE.
+# If the test fails here then test (3) probably isn't testing what it
+# should, and this test-case should be updated.
+#
+# CHECK: - type: unwind-cfi
+# CHECK-NOT: - type:
+# CHECK: references:
+# CHECK-NEXT: - kind: negDelta32
+# CHECK-NEXT: offset: 4
# CHECK-NEXT: target: L001
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 8
+# CHECK-NEXT: target: _bar
+#
+# (3) Check that we can relocate the LSDA on a second FDE that references the
+# original CIE from (1). Requires us to match this FDE up with the correct
+# CIE.
+#
+# CHECK-NEXT: - type: unwind-cfi
+# CHECK-NOT: - type:
+# CHECK: references:
+# CHECK-NEXT: - kind: negDelta32
+# CHECK-NEXT: offset: 4
+# CHECK-NEXT: target: L002
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 8
+# CHECK-NEXT: target: _catchMyException2
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 25
+# CHECK-NEXT: target: GCC_except_table2
More information about the llvm-commits
mailing list