[libcxx-commits] [PATCH] D111863: [libunwind] Add an interface for dynamic .eh_frame registration
Peter S. Housel via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 14 20:56:21 PDT 2021
housel created this revision.
housel added a reviewer: cfe-commits.
Herald added a project: libunwind.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libunwind.
housel requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
The libgcc runtime library provides __register_frame and __deregister_frame functions, which can be used by dynamic code generators to register an .eh_frame section, which contains one or more Call Frame Information records, each consisting of a Common Information Entry record followed by one or more Frame Description Entry records. This libunwind library also provides __register_frame
and __deregister_frame functions, but they are effectively aliases for __unw_add_dynamic_fde and __unw_remove_dynamic_fde and thus can only take a single FDE.
This patch adds __unw_add_dynamic_eh_frame_section and __unw_remove_dynamic_eh_frame_section functions which explicitly use the .eh_frame format. Clients such as the ORCv2 platform and runtime can check for these functions and use them if unwinding is being
provided by libunwind, or fall back to __register_frame and __deregister_frame if unwinding is provided by libgcc.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D111863
Files:
libunwind/src/DwarfParser.hpp
libunwind/src/libunwind.cpp
libunwind/src/libunwind_ext.h
Index: libunwind/src/libunwind_ext.h
===================================================================
--- libunwind/src/libunwind_ext.h
+++ libunwind/src/libunwind_ext.h
@@ -51,6 +51,9 @@
extern void __unw_add_dynamic_fde(unw_word_t fde);
extern void __unw_remove_dynamic_fde(unw_word_t fde);
+extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start);
+extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start);
+
#if defined(_LIBUNWIND_ARM_EHABI)
extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
Index: libunwind/src/libunwind.cpp
===================================================================
--- libunwind/src/libunwind.cpp
+++ libunwind/src/libunwind.cpp
@@ -292,6 +292,35 @@
// fde is own mh_group
DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
}
+
+void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
+ // The eh_frame section start serves as the mh_group
+ unw_word_t mh_group = eh_frame_start;
+ CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
+ CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
+ auto p = (LocalAddressSpace::pint_t)eh_frame_start;
+ while (true) {
+ if (CFI_Parser<LocalAddressSpace>::decodeFDE(
+ LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
+ true) == NULL) {
+ DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
+ fdeInfo.pcStart, fdeInfo.pcEnd,
+ fdeInfo.fdeStart);
+ p += fdeInfo.fdeLength;
+ } else if (CFI_Parser<LocalAddressSpace>::parseCIE(
+ LocalAddressSpace::sThisAddressSpace, p, &cieInfo) == NULL) {
+ p += cieInfo.cieLength;
+ } else
+ return;
+ }
+}
+
+void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
+ // The eh_frame section start serves as the mh_group
+ DwarfFDECache<LocalAddressSpace>::removeAllIn(
+ (LocalAddressSpace::pint_t)eh_frame_start);
+}
+
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
Index: libunwind/src/DwarfParser.hpp
===================================================================
--- libunwind/src/DwarfParser.hpp
+++ libunwind/src/DwarfParser.hpp
@@ -154,7 +154,8 @@
uintptr_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
CIE_Info *cieInfo);
static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
- FDE_Info *fdeInfo, CIE_Info *cieInfo);
+ FDE_Info *fdeInfo, CIE_Info *cieInfo,
+ bool useCIEInfo = false);
static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
const CIE_Info &cieInfo, pint_t upToPC,
int arch, PrologInfo *results);
@@ -165,7 +166,8 @@
/// Parse a FDE into a CIE_Info and an FDE_Info
template <typename A>
const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
- FDE_Info *fdeInfo, CIE_Info *cieInfo) {
+ FDE_Info *fdeInfo, CIE_Info *cieInfo,
+ bool useCIEInfo) {
pint_t p = fdeStart;
pint_t cfiLength = (pint_t)addressSpace.get32(p);
p += 4;
@@ -181,9 +183,14 @@
return "FDE is really a CIE"; // this is a CIE not an FDE
pint_t nextCFI = p + cfiLength;
pint_t cieStart = p - ciePointer;
- const char *err = parseCIE(addressSpace, cieStart, cieInfo);
- if (err != NULL)
- return err;
+ if (useCIEInfo) {
+ if (cieInfo->cieStart != cieStart)
+ return "CIE start does not match";
+ } else {
+ const char *err = parseCIE(addressSpace, cieStart, cieInfo);
+ if (err != NULL)
+ return err;
+ }
p += 4;
// Parse pc begin and range.
pint_t pcStart =
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D111863.379910.patch
Type: text/x-patch
Size: 4058 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20211015/46fcd71d/attachment.bin>
More information about the libcxx-commits
mailing list