From b959d46dbd2f9087ae860dbced40440c28596a6e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 10 Apr 2015 15:44:58 +0200 Subject: [PATCH] syscalls: Add get_stack_trace and lookup_symbol syscalls. The get_stack_trace syscall generates a stack trace using the kernel debugging facilities and copies the resulting return address array to the preallocated buffer from userland. It is only possible to get a stack trace of the current thread. The lookup_symbol syscall can be used to look up the symbol and image name corresponding to an address. It can be used to resolve symbols from a stack trace generated by the get_stack_trace syscall. Only symbols of the current team can be looked up. Note that this uses the symbol lookup of the kernel debugger which does not support lookup of all symbols (static functions are missing for example). This is meant to be used in situations where more elaborate stack trace generation, like done in the userland debugging helpers, is not possible due to constraints. --- headers/private/kernel/elf.h | 5 +++ headers/private/kernel/user_debugger.h | 1 + headers/private/system/syscalls.h | 7 +++++ src/system/kernel/debug/user_debugger.cpp | 18 +++++++++++ src/system/kernel/elf.cpp | 38 +++++++++++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/headers/private/kernel/elf.h b/headers/private/kernel/elf.h index 3851504db4..b8c6a426e9 100644 --- a/headers/private/kernel/elf.h +++ b/headers/private/kernel/elf.h @@ -54,6 +54,11 @@ status_t _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable, int32* _symbolCount, char* stringTable, size_t* _stringTableSize, addr_t* _imageDelta); +status_t _user_lookup_symbol(addr_t address, addr_t* baseAddress, + char* symbolNameBuffer, size_t symbolNameBufferSize, + char* imageNameBuffer, size_t imageNameBufferSize, + bool* exactMatch); + #ifdef __cplusplus } #endif diff --git a/headers/private/kernel/user_debugger.h b/headers/private/kernel/user_debugger.h index 809289c445..27824a4830 100644 --- a/headers/private/kernel/user_debugger.h +++ b/headers/private/kernel/user_debugger.h @@ -289,6 +289,7 @@ status_t _user_set_debugger_breakpoint(void *address, uint32 type, int32 length, bool watchpoint); status_t _user_clear_debugger_breakpoint(void *address, bool watchpoint); +ssize_t _user_get_stack_trace(size_t addressCount, addr_t* returnAddresses); #ifdef __cplusplus } // extern "C" diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 51a52138c1..f55639b115 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -492,6 +492,13 @@ extern status_t _kern_system_profiler_stop(); extern status_t _kern_system_profiler_recorded( struct system_profiler_parameters* parameters); +extern ssize_t _kern_get_stack_trace(size_t addressCount, + addr_t* adresses); +extern status_t _kern_lookup_symbol(addr_t address, addr_t* baseAddress, + char* symbolNameBuffer, size_t symbolNameBufferSize, + char* imageNameBuffer, size_t imageNameBufferSize, + bool* exactMatch); + /* atomic_* ops (needed for CPUs that don't support them directly) */ #ifdef ATOMIC_FUNCS_ARE_SYSCALLS extern void _kern_atomic_set(int32 *value, int32 newValue); diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index a4eb75ebc3..bbc30fb496 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -3000,3 +3000,21 @@ _user_clear_debugger_breakpoint(void *address, bool watchpoint) return result; } + + +ssize_t +_user_get_stack_trace(size_t addressCount, addr_t* userReturnAddresses) +{ + addr_t returnAddresses[addressCount]; + int32 readCount = arch_debug_get_stack_trace(returnAddresses, addressCount, + 1, 0, STACK_TRACE_KERNEL | STACK_TRACE_USER); + if (readCount < 0) + return readCount; + + status_t copyResult = user_memcpy(userReturnAddresses, returnAddresses, + readCount * sizeof(addr_t)); + if (copyResult != B_OK) + return copyResult; + + return readCount; +} diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 8a2ba78e05..16775532d2 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -2686,3 +2686,41 @@ _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable, return B_OK; } + + +status_t +_user_lookup_symbol(addr_t address, addr_t* userBaseAddress, + char* userSymbolNameBuffer, size_t symbolNameBufferSize, + char* userImageNameBuffer, size_t imageNameBufferSize, bool* userExactMatch) +{ + MutexLocker locker(&sImageMutex); + + addr_t baseAddress; + const char *symbolName; + const char *imageName; + bool exactMatch; + status_t status; + + if (IS_KERNEL_ADDRESS(address)) { + status = elf_debug_lookup_symbol_address(address, &baseAddress, + &symbolName, &imageName, &exactMatch); + } else { + status = elf_debug_lookup_user_symbol_address( + thread_get_current_thread()->team, address, &baseAddress, + &symbolName, &imageName, &exactMatch); + } + + if (status != B_OK) + return status; + + if (user_memcpy(userBaseAddress, &baseAddress, sizeof(addr_t)) != B_OK + || user_memcpy(userExactMatch, &exactMatch, sizeof(bool)) != B_OK + || user_strlcpy(userSymbolNameBuffer, symbolName, symbolNameBufferSize) + < 0 + || user_strlcpy(userImageNameBuffer, imageName, imageNameBufferSize) + < 0) { + return B_BAD_ADDRESS; + } + + return B_OK; +}