summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2015-10-23 05:39:16 +0000
committerLang Hames <lhames@gmail.com>2015-10-23 05:39:16 +0000
commit5e7cfe4e2b078dcda7efbf4314738f768af78ebd (patch)
treef9a6a2535a2c24a6e212beecaea44adf2324b17a
parent81595bd9d255a6c2f88a97c632d08b9742814729 (diff)
downloadbcm5719-llvm-5e7cfe4e2b078dcda7efbf4314738f768af78ebd.tar.gz
bcm5719-llvm-5e7cfe4e2b078dcda7efbf4314738f768af78ebd.zip
[lld][MachO] Prune unused EH frames.
llvm-svn: 251095
-rw-r--r--lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp51
-rw-r--r--lld/test/mach-o/unwind-info-simple-x86_64.yaml21
-rw-r--r--lld/test/mach-o/write-final-sections.yaml23
3 files changed, 92 insertions, 3 deletions
diff --git a/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index c194318f8c9..65bd52c7ce8 100644
--- a/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -310,6 +310,9 @@ private:
std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
mergedFile, unwindLocs, personalities, dwarfFrames);
+ // Remove any unused eh-frame atoms.
+ pruneUnusedEHFrames(mergedFile, unwindInfos, unwindLocs, dwarfFrames);
+
// Finally, we can start creating pages based on these entries.
DEBUG(llvm::dbgs() << " Splitting entries into pages\n");
@@ -470,6 +473,54 @@ private:
return unwindInfos;
}
+ /// Remove unused EH frames.
+ ///
+ /// An EH frame is considered unused if there is a corresponding compact
+ /// unwind atom that doesn't require the EH frame.
+ void pruneUnusedEHFrames(
+ SimpleFile &mergedFile,
+ const std::vector<CompactUnwindEntry> &unwindInfos,
+ const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
+ const std::map<const Atom *, const Atom *> &dwarfFrames) {
+
+ // Worklist of all 'used' FDEs.
+ std::vector<const DefinedAtom *> usedDwarfWorklist;
+
+ // We have to check two conditions when building the worklist:
+ // (1) EH frames used by compact unwind entries.
+ for (auto &entry : unwindInfos)
+ if (entry.ehFrame)
+ usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.ehFrame));
+
+ // (2) EH frames that reference functions with no corresponding compact
+ // unwind info.
+ for (auto &entry : dwarfFrames)
+ if (!unwindLocs.count(entry.first))
+ usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.second));
+
+ // Add all transitively referenced CFI atoms by processing the worklist.
+ std::set<const Atom *> usedDwarfFrames;
+ while (!usedDwarfWorklist.empty()) {
+ const DefinedAtom *cfiAtom = usedDwarfWorklist.back();
+ usedDwarfWorklist.pop_back();
+ usedDwarfFrames.insert(cfiAtom);
+ for (const auto *ref : *cfiAtom) {
+ const DefinedAtom *cfiTarget = dyn_cast<DefinedAtom>(ref->target());
+ if (cfiTarget->contentType() == DefinedAtom::typeCFI)
+ usedDwarfWorklist.push_back(cfiTarget);
+ }
+ }
+
+ // Finally, delete all unreferenced CFI atoms.
+ mergedFile.removeDefinedAtomsIf([&](const DefinedAtom *atom) {
+ if ((atom->contentType() == DefinedAtom::typeCFI) &&
+ !usedDwarfFrames.count(atom))
+ return true;
+ return false;
+ });
+ }
+
+
CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
const DefinedAtom *function,
const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
diff --git a/lld/test/mach-o/unwind-info-simple-x86_64.yaml b/lld/test/mach-o/unwind-info-simple-x86_64.yaml
index eb91c5c9728..1d2294a9967 100644
--- a/lld/test/mach-o/unwind-info-simple-x86_64.yaml
+++ b/lld/test/mach-o/unwind-info-simple-x86_64.yaml
@@ -67,7 +67,8 @@ defined-atoms:
target: _needsDwarfButNoCompactUnwind
# Generic x86_64 CIE:
- - type: unwind-cfi
+ - name: LCIE
+ type: unwind-cfi
content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
@@ -80,6 +81,9 @@ defined-atoms:
- kind: unwindFDEToFunction
offset: 8
target: _needsDwarfButNoCompactUnwind
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
- type: unwind-cfi
content: [ 24, 00, 00, 00, 44, 00, 00, 00, C8, FE, FF, FF,
@@ -90,7 +94,22 @@ defined-atoms:
- kind: unwindFDEToFunction
offset: 8
target: _needsDwarfSaysCompactUnwind
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
+ - type: unwind-cfi
+ content: [ 24, 00, 00, 00, 6C, 00, 00, 00, C8, FE, FF, FF,
+ FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+ 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+ 00, 00, 00, 00 ]
+ references:
+ - kind: unwindFDEToFunction
+ offset: 8
+ target: _main
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
- name: __Z3barv
scope: global
diff --git a/lld/test/mach-o/write-final-sections.yaml b/lld/test/mach-o/write-final-sections.yaml
index 7403cac1d3d..4e94acfa25b 100644
--- a/lld/test/mach-o/write-final-sections.yaml
+++ b/lld/test/mach-o/write-final-sections.yaml
@@ -69,12 +69,31 @@ defined-atoms:
# CHECK-NEXT: )
# For __TEXT, __eh_frame, (with typeCFI)
+ - name: LCIE
+ type: unwind-cfi
+ content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
+ 01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
+
- type: unwind-cfi
- content: [ 07 ]
+ content: [ 24, 00, 00, 00, 1C, 00, 00, 00, C8, FE, FF, FF,
+ FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+ 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+ 00, 00, 00, 00 ]
+ references:
+ - kind: unwindFDEToFunction
+ offset: 8
+ target: _foo
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
+
# CHECK: Name: __eh_frame
# CHECK: Segment: __TEXT
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 07
+# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001
+# CHECK-NEXT: 0010: 100C0708 90010000 24000000 1C000000
+# CHECK-NEXT: 0020: 70FFFFFF FFFFFFFF 01000000 00000000
+# CHECK-NEXT: 0030: 00410E10 8602430D 06000000 00000000
# CHECK-NEXT: )
# For __DATA, __data, (with typeData)
OpenPOWER on IntegriCloud