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.
This commit is contained in:
parent
e01de52283
commit
b959d46dbd
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user