Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 0b964a1

Browse files
committed
[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/ git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@321445 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 5d8a75e commit 0b964a1

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

src/AddressSpace.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,38 @@ namespace libunwind {
8383
}
8484
#endif
8585

86+
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
87+
88+
// When statically linked on bare-metal, the symbols for the EH table are looked
89+
// up without going through the dynamic loader.
90+
91+
// The following linker script may be used to produce the necessary sections and symbols.
92+
// Unless the --eh-frame-hdr linker option is provided, the section is not generated
93+
// and does not take space in the output file.
94+
//
95+
// .eh_frame :
96+
// {
97+
// __eh_frame_start = .;
98+
// KEEP(*(.eh_frame))
99+
// __eh_frame_end = .;
100+
// }
101+
//
102+
// .eh_frame_hdr :
103+
// {
104+
// KEEP(*(.eh_frame_hdr))
105+
// }
106+
//
107+
// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
108+
// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
109+
110+
extern char __eh_frame_start;
111+
extern char __eh_frame_end;
112+
113+
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
114+
extern char __eh_frame_hdr_start;
115+
extern char __eh_frame_hdr_end;
116+
#endif
117+
86118
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
87119

88120
// When statically linked on bare-metal, the symbols for the EH table are looked
@@ -348,6 +380,20 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
348380
info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
349381
return true;
350382
}
383+
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
384+
// Bare metal is statically linked, so no need to ask the dynamic loader
385+
info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
386+
info.dwarf_section = (uintptr_t)(&__eh_frame_start);
387+
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
388+
info.dwarf_section, info.dwarf_section_length);
389+
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
390+
info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
391+
info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
392+
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %X length %x",
393+
info.dwarf_index_section, info.dwarf_index_section_length);
394+
#endif
395+
if (info.dwarf_section_length)
396+
return true;
351397
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
352398
// Bare metal is statically linked, so no need to ask the dynamic loader
353399
info.arm_section = (uintptr_t)(&__exidx_start);

0 commit comments

Comments
 (0)