[libunwind] r321445 - [libunwind] Add proper support for DWARF unwind on bare metal.

whitequark via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 25 09:05:07 PST 2017


Author: whitequark
Date: Mon Dec 25 09:05:07 2017
New Revision: 321445

URL: http://llvm.org/viewvc/llvm-project?rev=321445&view=rev
Log:
[libunwind] Add proper support for DWARF unwind on bare metal.

Right now, ARM EHABI unwind on bare metal expects to find the symbols
__exidx_start and __exidx_end defined, and uses those to locate
the EH tables. However, DWARF unwind on bare metal expects to find
dl_iterate_phdr, which, although possible to provide, is inconvenient
and mildly absurd.

This commit provides feature parity with ARM EHABI unwind by looking
for symbols __eh_frame_start, __eh_frame_end, __eh_frame_hdr_start
and __eh_frame_hdr_end, denoting the start and end of the sections
with corresponding names. As far as I know, there is no de jure or
de facto ABI providing any such names, so I chose the obvious ones.

The .eh_frame_hdr support is optional for maximum flexibility and
possible space savings (e.g. if libunwind is only used to provide
backtraces when a device crashes, providing the .eh_frame_hdr, which
is an index for rapid access to EH tables, would be a waste.)

The support for .eh_frame_hdr/DWARF index in the first place is
conditional on defined(_LIBUNWIND_SUPPORT_DWARF_INDEX), although
right now config.h will always define this macro.

The support for DWARF unwind on bare metal has been validated within
the ARTIQ environment[1].

  [1]: https://m-labs.hk/artiq/

Modified:
    libunwind/trunk/src/AddressSpace.hpp

Modified: libunwind/trunk/src/AddressSpace.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/AddressSpace.hpp?rev=321445&r1=321444&r2=321445&view=diff
==============================================================================
--- libunwind/trunk/src/AddressSpace.hpp (original)
+++ libunwind/trunk/src/AddressSpace.hpp Mon Dec 25 09:05:07 2017
@@ -83,6 +83,38 @@ namespace libunwind {
     }
   #endif
 
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
+
+// When statically linked on bare-metal, the symbols for the EH table are looked
+// up without going through the dynamic loader.
+
+// The following linker script may be used to produce the necessary sections and symbols.
+// Unless the --eh-frame-hdr linker option is provided, the section is not generated
+// and does not take space in the output file.
+//
+//   .eh_frame :
+//   {
+//       __eh_frame_start = .;
+//       KEEP(*(.eh_frame))
+//       __eh_frame_end = .;
+//   }
+//
+//   .eh_frame_hdr :
+//   {
+//       KEEP(*(.eh_frame_hdr))
+//   }
+//
+//   __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
+//   __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
+
+extern char __eh_frame_start;
+extern char __eh_frame_end;
+
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+extern char __eh_frame_hdr_start;
+extern char __eh_frame_hdr_end;
+#endif
+
 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
 
 // When statically linked on bare-metal, the symbols for the EH table are looked
@@ -348,6 +380,20 @@ inline bool LocalAddressSpace::findUnwin
     info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
     return true;
   }
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
+  // Bare metal is statically linked, so no need to ask the dynamic loader
+  info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
+  info.dwarf_section =        (uintptr_t)(&__eh_frame_start);
+  _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
+                             info.dwarf_section, info.dwarf_section_length);
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+  info.dwarf_index_section =        (uintptr_t)(&__eh_frame_hdr_start);
+  info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
+  _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %X length %x",
+                             info.dwarf_index_section, info.dwarf_index_section_length);
+#endif
+  if (info.dwarf_section_length)
+    return true;
 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
   // Bare metal is statically linked, so no need to ask the dynamic loader
   info.arm_section =        (uintptr_t)(&__exidx_start);




More information about the cfe-commits mailing list