mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 23:49:22 +08:00
[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/ llvm-svn: 321445
This commit is contained in:
@@ -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::findUnwindSections(pint_t targetAddr,
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user