Skip to content

Commit a702552

Browse files
committed
[android] Basic support for backtraces.
Android doesn't support the GNU backtrace call, but unwind.h is there to help. The code is a little bit more complicated than a simple backtrace call, but it is just a callback and the context struct. Sadly, it seems that -funwind-tables is needed in every piece of code that the backtrace needs to traverse, which means that at least the runtime and the stubs need -funwind-tables. However, the flag has been enabled for all targets (only on Android), just in case some other code ends up being in the stack. This might only be necessary for ARM targets, but currently we only build ARM targets in Android. The Swift parts of the stack seems to have unwind information and can be unwind. Another problem at the moment is the symbols from the executable are normally missing. To get symbol names two things need to happen: the symbol has to be public (so it is an exported symbol, and not just a local symbol that dladdr seems to not provide the name), and the linker has to be invoked with -export-dynamic. Without those two pieces, the addresses are returned (and match the binary just fine), but no names are printed.
1 parent a78a298 commit a702552

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

cmake/modules/AddSwift.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ function(_add_variant_c_compile_flags)
303303
"-fcoverage-mapping")
304304
endif()
305305

306+
if((CFLAGS_ARCH STREQUAL "armv7" OR CFLAGS_ARCH STREQUAL "aarch64") AND
307+
(CFLAGS_SDK STREQUAL "LINUX" OR CFLAGS_SDK STREQUAL "ANDROID"))
308+
list(APPEND result -funwind-tables)
309+
endif()
310+
306311
if("${CFLAGS_SDK}" STREQUAL "ANDROID")
307312
swift_android_libcxx_include_paths(CFLAGS_CXX_INCLUDES)
308313
swift_android_include_for_arch("${CFLAGS_ARCH}" "${CFLAGS_ARCH}_INCLUDE")

stdlib/public/runtime/Errors.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#if defined(__CYGWIN__) || defined(__ANDROID__) || defined(__HAIKU__)
17+
#if defined(__CYGWIN__) || defined(__HAIKU__)
1818
#define SWIFT_SUPPORTS_BACKTRACE_REPORTING 0
1919
#else
2020
#define SWIFT_SUPPORTS_BACKTRACE_REPORTING 1
@@ -58,6 +58,10 @@
5858
#include <android/log.h>
5959
#endif
6060

61+
#if defined(__ELF__)
62+
#include <unwind.h>
63+
#endif
64+
6165
namespace FatalErrorFlags {
6266
enum: uint32_t {
6367
ReportBacktrace = 1 << 0
@@ -188,13 +192,46 @@ void swift::dumpStackTraceEntry(unsigned index, void *framePC,
188192
#endif
189193
}
190194

195+
#if defined(__ELF__)
196+
struct UnwindState {
197+
void **current;
198+
void **end;
199+
};
200+
201+
static _Unwind_Reason_Code SwiftUnwindFrame(struct _Unwind_Context *context, void *arg) {
202+
struct UnwindState *state = static_cast<struct UnwindState *>(arg);
203+
if (state->current == state->end) {
204+
return _URC_END_OF_STACK;
205+
}
206+
207+
uintptr_t pc;
208+
#if defined(__arm__)
209+
// ARM r15 is PC. UNW_REG_PC is *not* the same value, and using that will
210+
// result in abnormal behaviour.
211+
_Unwind_VRS_Get(context, _UVRSC_CORE, 15, _UVRSD_UINT32, &pc);
212+
// Clear the ISA bit during the reporting.
213+
pc &= ~(uintptr_t)0x1;
214+
#else
215+
pc = _Unwind_GetIP(context);
216+
#endif
217+
if (pc) {
218+
*state->current++ = reinterpret_cast<void *>(pc);
219+
}
220+
return _URC_NO_REASON;
221+
}
222+
#endif
223+
191224
LLVM_ATTRIBUTE_NOINLINE
192225
void swift::printCurrentBacktrace(unsigned framesToSkip) {
193226
#if SWIFT_SUPPORTS_BACKTRACE_REPORTING
194227
constexpr unsigned maxSupportedStackDepth = 128;
195228
void *addrs[maxSupportedStackDepth];
196229
#if defined(_WIN32)
197230
int symbolCount = CaptureStackBackTrace(0, maxSupportedStackDepth, addrs, NULL);
231+
#elif defined(__ELF__)
232+
struct UnwindState state = {&addrs[0], &addrs[maxSupportedStackDepth]};
233+
_Unwind_Backtrace(SwiftUnwindFrame, &state);
234+
int symbolCount = state.current - addrs;
198235
#else
199236
int symbolCount = backtrace(addrs, maxSupportedStackDepth);
200237
#endif

0 commit comments

Comments
 (0)