Index: libunwind/src/DwarfInstructions.hpp =================================================================== --- libunwind/src/DwarfInstructions.hpp +++ libunwind/src/DwarfInstructions.hpp @@ -93,7 +93,8 @@ case CFI_Parser::kRegisterInRegister: return registers.getRegister((int)savedReg.value); - + case CFI_Parser::kRegisterUndefined: + return 0; case CFI_Parser::kRegisterUnused: case CFI_Parser::kRegisterOffsetFromCFA: // FIX ME @@ -117,6 +118,7 @@ case CFI_Parser::kRegisterIsExpression: case CFI_Parser::kRegisterUnused: + case CFI_Parser::kRegisterUndefined: case CFI_Parser::kRegisterOffsetFromCFA: case CFI_Parser::kRegisterInRegister: // FIX ME @@ -140,6 +142,7 @@ case CFI_Parser::kRegisterIsExpression: case CFI_Parser::kRegisterUnused: + case CFI_Parser::kRegisterUndefined: case CFI_Parser::kRegisterOffsetFromCFA: case CFI_Parser::kRegisterInRegister: // FIX ME @@ -190,6 +193,10 @@ prolog.savedRegisters[i])); else return UNW_EBADREG; + } else if (i == (int)cieInfo.returnAddressRegister) { + // Leaf function keeps the return address in register and there is no + // explicit intructions how to restore it. + returnAddress = registers.getRegister(cieInfo.returnAddressRegister); } } Index: libunwind/src/DwarfParser.hpp =================================================================== --- libunwind/src/DwarfParser.hpp +++ libunwind/src/DwarfParser.hpp @@ -69,6 +69,7 @@ }; enum RegisterSavedWhere { kRegisterUnused, + kRegisterUndefined, kRegisterInCFA, kRegisterOffsetFromCFA, kRegisterInRegister, @@ -503,7 +504,7 @@ "malformed DW_CFA_undefined DWARF unwind, reg too big"); return false; } - results->setRegisterLocation(reg, kRegisterUnused, initialState); + results->setRegisterLocation(reg, kRegisterUndefined, initialState); _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_same_value: Index: libunwind/test/lit.site.cfg.in =================================================================== --- libunwind/test/lit.site.cfg.in +++ libunwind/test/lit.site.cfg.in @@ -44,6 +44,10 @@ # Allow expanding substitutions that are based on other substitutions config.recursiveExpansionLimit = 10 +# Make symbols available in the tests. +config.test_compiler_flags += " -funwind-tables " +config.test_linker_flags += " -Wl,--export-dynamic " + # Infer the test_exec_root from the build directory. config.test_exec_root = os.path.join(config.libunwind_obj_root, 'test') Index: libunwind/test/signal_unwind.pass.cpp =================================================================== --- /dev/null +++ libunwind/test/signal_unwind.pass.cpp @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Ensure that the unwinder can cope with the signal handler. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) { + (void)arg; + Dl_info info = { 0, 0, 0, 0 }; + assert(dladdr((void*)_Unwind_GetIP(ctx), &info)); + + // Unwind util the main is reached, above frames deeped on the platfrom and architecture. + if(info.dli_sname && !strcmp("main", info.dli_sname)) { + _Exit(0); + } + return _URC_NO_REASON; +} + +void signal_handler(int signum) { + (void)signum; + _Unwind_Backtrace(frame_handler, NULL); + _Exit(-1); +} + +int main() { + signal(SIGUSR1, signal_handler); + kill(getpid(), SIGUSR1); + return -2; +} Index: libunwind/test/unwind_leaffunction.pass.cpp =================================================================== --- /dev/null +++ libunwind/test/unwind_leaffunction.pass.cpp @@ -0,0 +1,50 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Ensure that leaf function can be unwund. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) { + (void)arg; + Dl_info info = { 0, 0, 0, 0 }; + assert(dladdr((void*)_Unwind_GetIP(ctx), &info)); + + // Unwind util the main is reached, above frames deeped on the platfrom and architecture. + if(info.dli_sname && !strcmp("main", info.dli_sname)) { + _Exit(0); + } + return _URC_NO_REASON; +} + +void signal_handler(int signum) { + (void)signum; + _Unwind_Backtrace(frame_handler, NULL); + _Exit(-1); +} + +int* faultyPointer = NULL; + +__attribute__((noinline)) void crashing_leaf_func(void) { + *faultyPointer = 0; +} + +int main() { + signal(SIGSEGV, signal_handler); + crashing_leaf_func(); + return -2; +} \ No newline at end of file