[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-07-11 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo abandoned this revision.
mstorsjo added a comment.
Herald added a subscriber: chrib.

FWIW, I'm not going to put any more effort into this one at the moment, I 
managed to fix my use case in a much simpler way by providing a Windows Store 
compatible version of EnumProcessModules, see 
https://sourceforge.net/p/mingw-w64/mingw-w64/ci/0e1f41358845706a1adafcf4f9d27db0319dd3d9/.


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-30 Thread Joerg Sonnenberger via Phabricator via cfe-commits
joerg added a comment.

The "struct object" is an implementation detail of the unwind implementation. 
You are guaranteed historically to get at least 8 longs / 8 pointers for 
internal use statically allocated in each object. What is stored inside is up 
to the unwind implementation.


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-30 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo updated this revision to Diff 140410.
mstorsjo edited the summary of this revision.
mstorsjo added a comment.
Herald added a subscriber: JDevlieghere.

Added and using a helper function `isCIE` to avoid using the error return path 
from `decodeFDE`.

Technically, the decision between a full section and a plain FDE probably 
should be outside of `_unw_add_dynamic_fde`, in `__register_frame` in 
`UnwindLevel1-gcc-ext.c`. That'd require adding a C wrapper for `isCIE` in 
`libunwind.cpp` though.


https://reviews.llvm.org/D44494

Files:
  src/DwarfParser.hpp
  src/UnwindCursor.hpp
  src/libunwind.cpp

Index: src/libunwind.cpp
===
--- src/libunwind.cpp
+++ src/libunwind.cpp
@@ -326,20 +326,27 @@
 
 /// IPI: for __register_frame()
 void _unw_add_dynamic_fde(unw_word_t fde) {
-  CFI_Parser::FDE_Info fdeInfo;
-  CFI_Parser::CIE_Info cieInfo;
-  const char *message = CFI_Parser::decodeFDE(
-   LocalAddressSpace::sThisAddressSpace,
-  (LocalAddressSpace::pint_t) fde, , );
-  if (message == NULL) {
-// dynamically registered FDEs don't have a mach_header group they are in.
-// Use fde as mh_group
-unw_word_t mh_group = fdeInfo.fdeStart;
-DwarfFDECache::add((LocalAddressSpace::pint_t)mh_group,
-  fdeInfo.pcStart, fdeInfo.pcEnd,
-  fdeInfo.fdeStart);
+  if (CFI_Parser::isCIE(LocalAddressSpace::sThisAddressSpace,
+  (LocalAddressSpace::pint_t) fde)) {
+// This wasn't a plain FDE, but it started with a CIE - register a full
+// .eh_frame section.
+DwarfFDECache::addSection((LocalAddressSpace::pint_t)fde);
   } else {
-_LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
+CFI_Parser::FDE_Info fdeInfo;
+CFI_Parser::CIE_Info cieInfo;
+const char *message = CFI_Parser::decodeFDE(
+ LocalAddressSpace::sThisAddressSpace,
+(LocalAddressSpace::pint_t) fde, , );
+if (message == NULL) {
+  // dynamically registered FDEs don't have a mach_header group they are in.
+  // Use fde as mh_group
+  unw_word_t mh_group = fdeInfo.fdeStart;
+  DwarfFDECache::add((LocalAddressSpace::pint_t)mh_group,
+fdeInfo.pcStart, fdeInfo.pcEnd,
+fdeInfo.fdeStart);
+} else {
+  _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
+}
   }
 }
 
Index: src/UnwindCursor.hpp
===
--- src/UnwindCursor.hpp
+++ src/UnwindCursor.hpp
@@ -44,10 +44,12 @@
 public:
   static pint_t findFDE(pint_t mh, pint_t pc);
   static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
+  static void addSection(pint_t section_start);
   static void removeAllIn(pint_t mh);
   static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
unw_word_t ip_end,
unw_word_t fde, unw_word_t mh));
+  template static void iterateSections(Func func);
 
 private:
 
@@ -70,6 +72,11 @@
   static entry *_bufferUsed;
   static entry *_bufferEnd;
   static entry _initialBuffer[64];
+
+  static pint_t *_sections;
+  static pint_t *_sectionsUsed;
+  static pint_t *_sectionsEnd;
+  static pint_t _initialSectionsBuffer[64];
 };
 
 template 
@@ -88,6 +95,21 @@
 typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64];
 
 template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sections = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsUsed = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsEnd = &_initialSectionsBuffer[64];
+
+template 
+typename DwarfFDECache::pint_t DwarfFDECache::_initialSectionsBuffer[64];
+
+template 
 RWMutex DwarfFDECache::_lock;
 
 #ifdef __APPLE__
@@ -144,6 +166,28 @@
 }
 
 template 
+void DwarfFDECache::addSection(pint_t section_start) {
+#if !defined(_LIBUNWIND_NO_HEAP)
+  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
+  if (_sectionsUsed >= _sectionsEnd) {
+size_t oldSize = (size_t)(_sectionsEnd - _sections);
+size_t newSize = oldSize * 4;
+// Can't use operator new (we are below it).
+pint_t *newSections = (pint_t *)malloc(newSize * sizeof(pint_t));
+memcpy(newSections, _sections, oldSize * sizeof(pint_t));
+if (_sections != _initialSectionsBuffer)
+  free(_sections);
+_sections = newSections;
+_sectionsUsed = [oldSize];
+_sectionsEnd = [newSize];
+  }
+  *_sectionsUsed = section_start;
+  ++_sectionsUsed;
+  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
+#endif
+}
+
+template 
 void DwarfFDECache::removeAllIn(pint_t mh) {
   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
   entry *d = _buffer;
@@ -155,6 +199,15 

[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-28 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo added a subscriber: joerg.
mstorsjo added a comment.

Also, relating to this, @joerg mentioned on irc that one should rather use 
`__register_frame_info_bases` instead of `__register_frame`. That function is a 
bit tricky to call though, since it uses a libgcc internal struct `struct 
object`, only available in libgcc headers and in Unwind_AppleExtras.cpp (as 
struct libgcc_object, with the comment "undocumented libgcc struct object").


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-28 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo added a comment.

In https://reviews.llvm.org/D44494#1050803, @mstorsjo wrote:

> In https://reviews.llvm.org/D44494#1050797, @mstorsjo wrote:
>
> > This else clause isn't about `.eh_frame` vs `.eh_frame_hdr`, but about 
> > registering a single FDE (which libunwind's `__register_frame` currently 
> > does) vs registering a full `.eh_frame` section (which libgcc's 
> > `__register_frame` does).
>
>
> However, this function actually just is `_unw_add_dynamic_fde`, while 
> `__register_frame` in `UnwindLevel1-gcc-ext.c` just calls this function. So 
> we should probably check there instead, whether it's an FDE (which libgcc 
> doesn't support via that entry point) or a full `.eh_frame` section.


In this case, it triggers the "FDE is really a CIE" case in decodeFDE, so we 
could do a quick check in `__register_frame` and see if it is a CIE or an FDE, 
and then call the right underlying functions based on that, instead of adding 
it in the error handling else statement like this.


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-28 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo added a comment.

In https://reviews.llvm.org/D44494#1050797, @mstorsjo wrote:

> This else clause isn't about `.eh_frame` vs `.eh_frame_hdr`, but about 
> registering a single FDE (which libunwind's `__register_frame` currently 
> does) vs registering a full `.eh_frame` section (which libgcc's 
> `__register_frame` does).


However, this function actually just is `_unw_add_dynamic_fde`, while 
`__register_frame` in `UnwindLevel1-gcc-ext.c` just calls this function. So we 
should probably check there instead, whether it's an FDE (which libgcc doesn't 
support via that entry point) or a full `.eh_frame` section.


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-28 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo added a comment.

In https://reviews.llvm.org/D44494#1050783, @compnerd wrote:

> I really don't like this approach.  I think that we should introduce a 
> different entry point for this behavior rather than saying that we go through 
> the existing interface.  Having a reference to the `.eh_frame_hdr` seems 
> better, as it would be better to make use of that optimization and we already 
> have handling for that in libunwind.


Well, this is just a plain `.eh_frame`, not an `.eh_frame_hdr`, since nothing 
for MinGW actually produces such a section for COFF (yet), GNU binutils doesn't 
either. Adding support for an indexed `.eh_frame_hdr`, while good from a 
performance PoV, feels like an orthogonal issue from this.

This else clause isn't about `.eh_frame` vs `.eh_frame_hdr`, but about 
registering a single FDE (which libunwind's `__register_frame` currently does) 
vs registering a full `.eh_frame` section (which libgcc's `__register_frame` 
does).


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-28 Thread Saleem Abdulrasool via Phabricator via cfe-commits
compnerd requested changes to this revision.
compnerd added a comment.
This revision now requires changes to proceed.

I really don't like this approach.  I think that we should introduce a 
different entry point for this behavior rather than saying that we go through 
the existing interface.  Having a reference to the `.eh_frame_hdr` seems 
better, as it would be better to make use of that optimization and we already 
have handling for that in libunwind.


https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-14 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo updated this revision to Diff 138451.
mstorsjo added a comment.

Avoid using the C++  header.


https://reviews.llvm.org/D44494

Files:
  src/UnwindCursor.hpp
  src/libunwind.cpp

Index: src/libunwind.cpp
===
--- src/libunwind.cpp
+++ src/libunwind.cpp
@@ -339,7 +339,9 @@
   fdeInfo.pcStart, fdeInfo.pcEnd,
   fdeInfo.fdeStart);
   } else {
+// This wasn't a plain FDE; then it's probably a full .eh_frame section.
 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
+DwarfFDECache::addSection((LocalAddressSpace::pint_t)fde);
   }
 }
 
Index: src/UnwindCursor.hpp
===
--- src/UnwindCursor.hpp
+++ src/UnwindCursor.hpp
@@ -44,10 +44,12 @@
 public:
   static pint_t findFDE(pint_t mh, pint_t pc);
   static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
+  static void addSection(pint_t section_start);
   static void removeAllIn(pint_t mh);
   static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
unw_word_t ip_end,
unw_word_t fde, unw_word_t mh));
+  template static void iterateSections(Func func);
 
 private:
 
@@ -70,6 +72,11 @@
   static entry *_bufferUsed;
   static entry *_bufferEnd;
   static entry _initialBuffer[64];
+
+  static pint_t *_sections;
+  static pint_t *_sectionsUsed;
+  static pint_t *_sectionsEnd;
+  static pint_t _initialSectionsBuffer[64];
 };
 
 template 
@@ -88,6 +95,21 @@
 typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64];
 
 template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sections = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsUsed = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsEnd = &_initialSectionsBuffer[64];
+
+template 
+typename DwarfFDECache::pint_t DwarfFDECache::_initialSectionsBuffer[64];
+
+template 
 RWMutex DwarfFDECache::_lock;
 
 #ifdef __APPLE__
@@ -144,6 +166,28 @@
 }
 
 template 
+void DwarfFDECache::addSection(pint_t section_start) {
+#if !defined(_LIBUNWIND_NO_HEAP)
+  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
+  if (_sectionsUsed >= _sectionsEnd) {
+size_t oldSize = (size_t)(_sectionsEnd - _sections);
+size_t newSize = oldSize * 4;
+// Can't use operator new (we are below it).
+pint_t *newSections = (pint_t *)malloc(newSize * sizeof(pint_t));
+memcpy(newSections, _sections, oldSize * sizeof(pint_t));
+if (_sections != _initialSectionsBuffer)
+  free(_sections);
+_sections = newSections;
+_sectionsUsed = [oldSize];
+_sectionsEnd = [newSize];
+  }
+  *_sectionsUsed = section_start;
+  ++_sectionsUsed;
+  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
+#endif
+}
+
+template 
 void DwarfFDECache::removeAllIn(pint_t mh) {
   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
   entry *d = _buffer;
@@ -155,6 +199,15 @@
 }
   }
   _bufferUsed = d;
+  pint_t *sectionsDest = _sections;
+  for (const pint_t *s = _sections; s < _sectionsUsed; ++s) {
+if (*s != mh) {
+  if (sectionsDest != s)
+*sectionsDest = *s;
+  ++sectionsDest;
+}
+  }
+  _sectionsUsed = sectionsDest;
   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
 }
 
@@ -174,6 +227,16 @@
   }
   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
 }
+
+template 
+template 
+void DwarfFDECache::iterateSections(Func func) {
+  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
+  for (pint_t *p = _sections; p < _sectionsUsed; ++p) {
+func(*p);
+  }
+  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
+}
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
 
 
@@ -1352,6 +1415,28 @@
 }
   }
 
+  bool foundSection = false;
+  DwarfFDECache::iterateSections([&](pint_t section) {
+if (foundSection)
+  return;
+sects.dso_base = section;
+sects.dwarf_section = section;
+sects.dwarf_section_length = ~(pint_t)0 - section;
+if (sects.dwarf_section_length > ~(uint32_t)0)
+sects.dwarf_section_length = ~(uint32_t)0;
+CFI_Parser::FDE_Info fdeInfo;
+CFI_Parser::CIE_Info cieInfo;
+// Only parse and see if it is the right frame here,
+// to avoid recursive self-locking.
+foundSection = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section,
+  (uint32_t)sects.dwarf_section_length, 0,
+  , );
+  });
+  // This call will lock the cache when adding a new match; only do this
+  // outside of the iteration (which also keeps a lock).
+  if (foundSection && this->getInfoFromDwarfSection(pc, sects))
+return;
+
   // Lastly, ask AddressSpace object about platform specific ways to locate
   // other FDEs.
   pint_t fde;
___
cfe-commits mailing list

[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-14 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo added inline comments.



Comment at: src/UnwindCursor.hpp:53
unw_word_t fde, unw_word_t mh));
+  static void iterateSections(std::function func);
 

rnk wrote:
> I'm concerned that std::function might introduce runtime dependencies from 
> libc++abi back to libc++. I think we get away with the  include 
> above because it's templated for the most part. Since this stuff is all 
> in-header anyway, we could just take a non-type template parameter callable 
> and call it directly.
Ok, will change.


Repository:
  rUNW libunwind

https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-14 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added inline comments.



Comment at: src/UnwindCursor.hpp:53
unw_word_t fde, unw_word_t mh));
+  static void iterateSections(std::function func);
 

I'm concerned that std::function might introduce runtime dependencies from 
libc++abi back to libc++. I think we get away with the  include 
above because it's templated for the most part. Since this stuff is all 
in-header anyway, we could just take a non-type template parameter callable and 
call it directly.


Repository:
  rUNW libunwind

https://reviews.llvm.org/D44494



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44494: [libunwind] Support __register_frame with a full .eh_frame section

2018-03-14 Thread Martin Storsjö via Phabricator via cfe-commits
mstorsjo created this revision.
mstorsjo added reviewers: rnk, compnerd.

Previously, the __register_frame function supported registering an FDE for one 
individual function at a time. The function could also be used registering a 
full .eh_frame section of a module (which is how libgcc sets up unwinding).


Repository:
  rUNW libunwind

https://reviews.llvm.org/D44494

Files:
  src/UnwindCursor.hpp
  src/libunwind.cpp

Index: src/libunwind.cpp
===
--- src/libunwind.cpp
+++ src/libunwind.cpp
@@ -347,7 +347,9 @@
   fdeInfo.pcStart, fdeInfo.pcEnd,
   fdeInfo.fdeStart);
   } else {
+// This wasn't a plain FDE; then it's probably a full .eh_frame section.
 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
+DwarfFDECache::addSection((LocalAddressSpace::pint_t)fde);
   }
 }
 
Index: src/UnwindCursor.hpp
===
--- src/UnwindCursor.hpp
+++ src/UnwindCursor.hpp
@@ -13,6 +13,7 @@
 #define __UNWINDCURSOR_HPP__
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,10 +45,12 @@
 public:
   static pint_t findFDE(pint_t mh, pint_t pc);
   static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
+  static void addSection(pint_t section_start);
   static void removeAllIn(pint_t mh);
   static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
unw_word_t ip_end,
unw_word_t fde, unw_word_t mh));
+  static void iterateSections(std::function func);
 
 private:
 
@@ -70,6 +73,11 @@
   static entry *_bufferUsed;
   static entry *_bufferEnd;
   static entry _initialBuffer[64];
+
+  static pint_t *_sections;
+  static pint_t *_sectionsUsed;
+  static pint_t *_sectionsEnd;
+  static pint_t _initialSectionsBuffer[64];
 };
 
 template 
@@ -88,6 +96,21 @@
 typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64];
 
 template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sections = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsUsed = _initialSectionsBuffer;
+
+template 
+typename DwarfFDECache::pint_t *
+DwarfFDECache::_sectionsEnd = &_initialSectionsBuffer[64];
+
+template 
+typename DwarfFDECache::pint_t DwarfFDECache::_initialSectionsBuffer[64];
+
+template 
 RWMutex DwarfFDECache::_lock;
 
 #ifdef __APPLE__
@@ -144,6 +167,28 @@
 }
 
 template 
+void DwarfFDECache::addSection(pint_t section_start) {
+#if !defined(_LIBUNWIND_NO_HEAP)
+  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
+  if (_sectionsUsed >= _sectionsEnd) {
+size_t oldSize = (size_t)(_sectionsEnd - _sections);
+size_t newSize = oldSize * 4;
+// Can't use operator new (we are below it).
+pint_t *newSections = (pint_t *)malloc(newSize * sizeof(pint_t));
+memcpy(newSections, _sections, oldSize * sizeof(pint_t));
+if (_sections != _initialSectionsBuffer)
+  free(_sections);
+_sections = newSections;
+_sectionsUsed = [oldSize];
+_sectionsEnd = [newSize];
+  }
+  *_sectionsUsed = section_start;
+  ++_sectionsUsed;
+  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
+#endif
+}
+
+template 
 void DwarfFDECache::removeAllIn(pint_t mh) {
   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
   entry *d = _buffer;
@@ -155,6 +200,15 @@
 }
   }
   _bufferUsed = d;
+  pint_t *sectionsDest = _sections;
+  for (const pint_t *s = _sections; s < _sectionsUsed; ++s) {
+if (*s != mh) {
+  if (sectionsDest != s)
+*sectionsDest = *s;
+  ++sectionsDest;
+}
+  }
+  _sectionsUsed = sectionsDest;
   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
 }
 
@@ -174,6 +228,15 @@
   }
   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
 }
+
+template 
+void DwarfFDECache::iterateSections(std::function func) {
+  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
+  for (pint_t *p = _sections; p < _sectionsUsed; ++p) {
+func(*p);
+  }
+  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
+}
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
 
 
@@ -1352,6 +1415,28 @@
 }
   }
 
+  bool foundSection = false;
+  DwarfFDECache::iterateSections([&](pint_t section) {
+if (foundSection)
+  return;
+sects.dso_base = section;
+sects.dwarf_section = section;
+sects.dwarf_section_length = ~(pint_t)0 - section;
+if (sects.dwarf_section_length > ~(uint32_t)0)
+sects.dwarf_section_length = ~(uint32_t)0;
+CFI_Parser::FDE_Info fdeInfo;
+CFI_Parser::CIE_Info cieInfo;
+// Only parse and see if it is the right frame here,
+// to avoid recursive self-locking.
+foundSection = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section,
+  (uint32_t)sects.dwarf_section_length, 0,
+  , );
+  });
+  // This call will lock the cache when adding a new match; only do