summaryrefslogtreecommitdiff
path: root/libunwind/src/libunwind.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libunwind/src/libunwind.cpp')
-rw-r--r--libunwind/src/libunwind.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index 0faea2b78570..1bd18659b786 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -349,7 +349,87 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
+#ifdef __APPLE__
+namespace libunwind {
+
+static constexpr size_t MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS = 8;
+
+static RWMutex findDynamicUnwindSectionsLock;
+static size_t numDynamicUnwindSectionsFinders = 0;
+static unw_find_dynamic_unwind_sections
+ dynamicUnwindSectionsFinders[MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS] = {0};
+
+bool findDynamicUnwindSections(void *addr, unw_dynamic_unwind_sections *info) {
+ bool found = false;
+ findDynamicUnwindSectionsLock.lock_shared();
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i]((unw_word_t)addr, info)) {
+ found = true;
+ break;
+ }
+ }
+ findDynamicUnwindSectionsLock.unlock_shared();
+ return found;
+}
+
+} // namespace libunwind
+
+int __unw_add_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.lock();
+
+ // Check that we have enough space...
+ if (numDynamicUnwindSectionsFinders == MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_ENOMEM;
+ }
+
+ // Check for value already present...
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_EINVAL;
+ }
+ }
+
+ // Success -- add callback entry.
+ dynamicUnwindSectionsFinders[numDynamicUnwindSectionsFinders++] =
+ find_dynamic_unwind_sections;
+ findDynamicUnwindSectionsLock.unlock();
+
+ return UNW_ESUCCESS;
+}
+
+int __unw_remove_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.lock();
+
+ // Find index to remove.
+ size_t finderIdx = numDynamicUnwindSectionsFinders;
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+ finderIdx = i;
+ break;
+ }
+ }
+
+ // If no such registration is present then error out.
+ if (finderIdx == numDynamicUnwindSectionsFinders) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_EINVAL;
+ }
+
+ // Remove entry.
+ for (size_t i = finderIdx; i != numDynamicUnwindSectionsFinders - 1; ++i)
+ dynamicUnwindSectionsFinders[i] = dynamicUnwindSectionsFinders[i + 1];
+ dynamicUnwindSectionsFinders[--numDynamicUnwindSectionsFinders] = nullptr;
+
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_ESUCCESS;
+}
+
+#endif // __APPLE__
// Add logging hooks in Debug builds only
#ifndef NDEBUG