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; +}