Make it possible to use libunwind without heap.
This patch allows to use libunwind on bare-metal systems that do not
include malloc/free by conditionally turning off nonessential
functionality that requires these functions.
The disabled functionality includes:
* the .cfi_remember_state and .cfi_restore_state instructions;
* the DWARF FDE cache.
The .cfi_{remember,restore}_state instructions don't seem to be used
by contemporary compilers. None of the LLVM backends emit it.
The DWARF FDE cache is bypassed if _LIBUNWIND_NO_HEAP is defined.
Specifically, entries are never added to it, so the search begins
and ends at the statically allocated, empty initial cache.
Such heap-less libunwind on a bare metal system is successfully used
in the ARTIQ project[1], and it is my hope that it will be useful
elsewhere.
[1]: http://m-labs.hk/artiq
Differential Revision: http://reviews.llvm.org/D11897
git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@252452 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/DwarfParser.hpp b/src/DwarfParser.hpp
index 26993c4..a19f051 100644
--- a/src/DwarfParser.hpp
+++ b/src/DwarfParser.hpp
@@ -380,7 +380,9 @@
uint64_t length;
uint8_t opcode = addressSpace.get8(p);
uint8_t operand;
+#if !defined(_LIBUNWIND_NO_HEAP)
PrologInfoStackEntry *entry;
+#endif
++p;
switch (opcode) {
case DW_CFA_nop:
@@ -492,6 +494,7 @@
fprintf(stderr, "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n",
reg, reg2);
break;
+#if !defined(_LIBUNWIND_NO_HEAP)
case DW_CFA_remember_state:
// avoid operator new, because that would be an upward dependency
entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
@@ -517,6 +520,7 @@
if (logDwarf)
fprintf(stderr, "DW_CFA_restore_state\n");
break;
+#endif
case DW_CFA_def_cfa:
reg = addressSpace.getULEB128(p, instructionsEnd);
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index 040d13e..9068316 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -114,6 +114,7 @@
template <typename A>
void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
pint_t fde) {
+#if !defined(_LIBUNWIND_NO_HEAP)
_LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
if (_bufferUsed >= _bufferEnd) {
size_t oldSize = (size_t)(_bufferEnd - _buffer);
@@ -139,6 +140,7 @@
}
#endif
_LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
+#endif
}
template <typename A>