diff options
| author | Lang Hames <lhames@gmail.com> | 2015-10-23 05:39:16 +0000 |
|---|---|---|
| committer | Lang Hames <lhames@gmail.com> | 2015-10-23 05:39:16 +0000 |
| commit | 5e7cfe4e2b078dcda7efbf4314738f768af78ebd (patch) | |
| tree | f9a6a2535a2c24a6e212beecaea44adf2324b17a | |
| parent | 81595bd9d255a6c2f88a97c632d08b9742814729 (diff) | |
| download | bcm5719-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.cpp | 51 | ||||
| -rw-r--r-- | lld/test/mach-o/unwind-info-simple-x86_64.yaml | 21 | ||||
| -rw-r--r-- | lld/test/mach-o/write-final-sections.yaml | 23 |
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) |

