|
|
|
@@ -6,6 +6,8 @@
|
|
|
|
|
* Axel Dörfler <[email protected]>
|
|
|
|
|
* Ingo Weinhold <[email protected]>
|
|
|
|
|
* François Revol <[email protected]>
|
|
|
|
|
* Ithamar R. Adema <[email protected]>
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -13,25 +15,22 @@
|
|
|
|
|
|
|
|
|
|
#include <arch_cpu.h>
|
|
|
|
|
#include <debug.h>
|
|
|
|
|
#include <debug_heap.h>
|
|
|
|
|
#include <elf.h>
|
|
|
|
|
#include <kernel.h>
|
|
|
|
|
#include <kimage.h>
|
|
|
|
|
#include <thread.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct stack_frame {
|
|
|
|
|
struct stack_frame *previous;
|
|
|
|
|
addr_t return_address;
|
|
|
|
|
};
|
|
|
|
|
#include <vm/vm_types.h>
|
|
|
|
|
#include <vm/VMAddressSpace.h>
|
|
|
|
|
#include <vm/VMArea.h>
|
|
|
|
|
|
|
|
|
|
#define NUM_PREVIOUS_LOCATIONS 32
|
|
|
|
|
|
|
|
|
|
extern struct iframe_stack gBootFrameStack;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
static bool
|
|
|
|
|
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
|
|
|
|
|
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 fp)
|
|
|
|
|
{
|
|
|
|
|
int32 last = *_last;
|
|
|
|
|
int32 num = *_num;
|
|
|
|
@@ -39,13 +38,13 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
|
if (visited[(NUM_PREVIOUS_LOCATIONS + last - i)
|
|
|
|
|
% NUM_PREVIOUS_LOCATIONS] == framePointer) {
|
|
|
|
|
% NUM_PREVIOUS_LOCATIONS] == fp) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
|
|
|
|
|
visited[last] = framePointer;
|
|
|
|
|
visited[last] = fp;
|
|
|
|
|
|
|
|
|
|
if (num < NUM_PREVIOUS_LOCATIONS)
|
|
|
|
|
*_num = num + 1;
|
|
|
|
@@ -54,99 +53,327 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline stack_frame *
|
|
|
|
|
get_current_stack_frame()
|
|
|
|
|
static status_t
|
|
|
|
|
get_next_frame(addr_t fp, addr_t *next, addr_t *ip)
|
|
|
|
|
{
|
|
|
|
|
stack_frame *frame;
|
|
|
|
|
asm volatile("move.l %%fp,%0" : "=r"(frame));
|
|
|
|
|
return frame;
|
|
|
|
|
if (fp != 0) {
|
|
|
|
|
addr_t _fp = *(((addr_t*)fp) -3);
|
|
|
|
|
addr_t _sp = *(((addr_t*)fp) -2);
|
|
|
|
|
addr_t _lr = *(((addr_t*)fp) -1);
|
|
|
|
|
addr_t _pc = *(((addr_t*)fp) -0);
|
|
|
|
|
|
|
|
|
|
*ip = (_fp != 0) ? _lr : _pc;
|
|
|
|
|
*next = _fp;
|
|
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static status_t
|
|
|
|
|
get_next_frame(addr_t framePointer, addr_t *next, addr_t *ip)
|
|
|
|
|
lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
|
|
|
|
|
const char** _symbolName, const char** _imageName, bool* _exactMatch)
|
|
|
|
|
{
|
|
|
|
|
Thread *thread = thread_get_current_thread();
|
|
|
|
|
addr_t oldFaultHandler = thread->fault_handler;
|
|
|
|
|
status_t status = B_ENTRY_NOT_FOUND;
|
|
|
|
|
|
|
|
|
|
// set fault handler, so that we can safely access user stacks
|
|
|
|
|
if (thread) {
|
|
|
|
|
if (m68k_set_fault_handler(&thread->fault_handler, (addr_t)&&error))
|
|
|
|
|
goto error;
|
|
|
|
|
if (IS_KERNEL_ADDRESS(address)) {
|
|
|
|
|
// a kernel symbol
|
|
|
|
|
status = elf_debug_lookup_symbol_address(address, _baseAddress,
|
|
|
|
|
_symbolName, _imageName, _exactMatch);
|
|
|
|
|
} else if (thread != NULL && thread->team != NULL) {
|
|
|
|
|
// try a lookup using the userland runtime loader structures
|
|
|
|
|
status = elf_debug_lookup_user_symbol_address(thread->team, address,
|
|
|
|
|
_baseAddress, _symbolName, _imageName, _exactMatch);
|
|
|
|
|
|
|
|
|
|
if (status != B_OK) {
|
|
|
|
|
// try to locate the image in the images loaded into user space
|
|
|
|
|
status = image_debug_lookup_user_symbol_address(thread->team,
|
|
|
|
|
address, _baseAddress, _symbolName, _imageName, _exactMatch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ip = ((struct stack_frame *)framePointer)->return_address;
|
|
|
|
|
*next = (addr_t)((struct stack_frame *)framePointer)->previous;
|
|
|
|
|
|
|
|
|
|
if (thread)
|
|
|
|
|
thread->fault_handler = oldFaultHandler;
|
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
thread->fault_handler = oldFaultHandler;
|
|
|
|
|
return B_BAD_ADDRESS;
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
|
|
|
|
|
addr_t nextFramePointer)
|
|
|
|
|
set_debug_argument_variable(int32 index, uint64 value)
|
|
|
|
|
{
|
|
|
|
|
addr_t diff = nextFramePointer - framePointer;
|
|
|
|
|
|
|
|
|
|
// kernel space/user space switch
|
|
|
|
|
if (diff & 0x80000000)
|
|
|
|
|
diff = 0;
|
|
|
|
|
|
|
|
|
|
// lookup symbol
|
|
|
|
|
const char *symbol, *image;
|
|
|
|
|
addr_t baseAddress;
|
|
|
|
|
bool exactMatch;
|
|
|
|
|
status_t status = elf_debug_lookup_symbol_address(ip, &baseAddress, &symbol,
|
|
|
|
|
&image, &exactMatch);
|
|
|
|
|
if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) {
|
|
|
|
|
// try to locate the image in the images loaded into user space
|
|
|
|
|
status = image_debug_lookup_user_symbol_address(thread->team, ip,
|
|
|
|
|
&baseAddress, &symbol, &image, &exactMatch);
|
|
|
|
|
}
|
|
|
|
|
if (status == B_OK) {
|
|
|
|
|
if (symbol != NULL) {
|
|
|
|
|
kprintf("%08lx (+%4ld) %08lx <%s>:%s + 0x%04lx%s\n", framePointer,
|
|
|
|
|
diff, ip, image, symbol, ip - baseAddress,
|
|
|
|
|
(exactMatch ? "" : " (nearest)"));
|
|
|
|
|
} else {
|
|
|
|
|
kprintf("%08lx (+%4ld) %08lx <%s@%p>:unknown + 0x%04lx\n",
|
|
|
|
|
framePointer, diff, ip, image, (void *)baseAddress,
|
|
|
|
|
ip - baseAddress);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
kprintf("%08lx (+%4ld) %08lx\n", framePointer, diff, ip);
|
|
|
|
|
char name[8];
|
|
|
|
|
snprintf(name, sizeof(name), "_arg%ld", index);
|
|
|
|
|
set_debug_variable(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename Type>
|
|
|
|
|
static Type
|
|
|
|
|
read_function_argument_value(void* argument, bool& _valueKnown)
|
|
|
|
|
{
|
|
|
|
|
Type value;
|
|
|
|
|
if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) {
|
|
|
|
|
_valueKnown = true;
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_valueKnown = false;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static status_t
|
|
|
|
|
print_demangled_call(const char* image, const char* symbol, addr_t args,
|
|
|
|
|
bool noObjectMethod, bool addDebugVariables)
|
|
|
|
|
{
|
|
|
|
|
static const size_t kBufferSize = 256;
|
|
|
|
|
char* buffer = (char*)debug_malloc(kBufferSize);
|
|
|
|
|
if (buffer == NULL)
|
|
|
|
|
return B_NO_MEMORY;
|
|
|
|
|
|
|
|
|
|
bool isObjectMethod;
|
|
|
|
|
const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
|
|
|
|
|
&isObjectMethod);
|
|
|
|
|
if (name == NULL) {
|
|
|
|
|
debug_free(buffer);
|
|
|
|
|
return B_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32* arg = (uint32*)args;
|
|
|
|
|
|
|
|
|
|
if (noObjectMethod)
|
|
|
|
|
isObjectMethod = false;
|
|
|
|
|
if (isObjectMethod) {
|
|
|
|
|
const char* lastName = strrchr(name, ':') - 1;
|
|
|
|
|
int namespaceLength = lastName - name;
|
|
|
|
|
|
|
|
|
|
uint32 argValue = 0;
|
|
|
|
|
if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) {
|
|
|
|
|
kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image,
|
|
|
|
|
namespaceLength, name, argValue, lastName);
|
|
|
|
|
} else
|
|
|
|
|
kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName);
|
|
|
|
|
|
|
|
|
|
if (addDebugVariables)
|
|
|
|
|
set_debug_variable("_this", argValue);
|
|
|
|
|
arg++;
|
|
|
|
|
} else
|
|
|
|
|
kprintf("<%s> %s", image, name);
|
|
|
|
|
|
|
|
|
|
kprintf("(");
|
|
|
|
|
|
|
|
|
|
size_t length;
|
|
|
|
|
int32 type, i = 0;
|
|
|
|
|
uint32 cookie = 0;
|
|
|
|
|
while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
|
|
|
|
|
kBufferSize, &type, &length) == B_OK) {
|
|
|
|
|
if (i++ > 0)
|
|
|
|
|
kprintf(", ");
|
|
|
|
|
|
|
|
|
|
// retrieve value and type identifier
|
|
|
|
|
|
|
|
|
|
uint64 value;
|
|
|
|
|
bool valueKnown = false;
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case B_INT64_TYPE:
|
|
|
|
|
value = read_function_argument_value<int64>(arg, valueKnown);
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("int64: \33[34m%Ld\33[0m", value);
|
|
|
|
|
break;
|
|
|
|
|
case B_INT32_TYPE:
|
|
|
|
|
value = read_function_argument_value<int32>(arg, valueKnown);
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("int32: \33[34m%ld\33[0m", (int32)value);
|
|
|
|
|
break;
|
|
|
|
|
case B_INT16_TYPE:
|
|
|
|
|
value = read_function_argument_value<int16>(arg, valueKnown);
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("int16: \33[34m%d\33[0m", (int16)value);
|
|
|
|
|
break;
|
|
|
|
|
case B_INT8_TYPE:
|
|
|
|
|
value = read_function_argument_value<int8>(arg, valueKnown);
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("int8: \33[34m%d\33[0m", (int8)value);
|
|
|
|
|
break;
|
|
|
|
|
case B_UINT64_TYPE:
|
|
|
|
|
value = read_function_argument_value<uint64>(arg, valueKnown);
|
|
|
|
|
if (valueKnown) {
|
|
|
|
|
kprintf("uint64: \33[34m%#Lx\33[0m", value);
|
|
|
|
|
if (value < 0x100000)
|
|
|
|
|
kprintf(" (\33[34m%Lu\33[0m)", value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case B_UINT32_TYPE:
|
|
|
|
|
value = read_function_argument_value<uint32>(arg, valueKnown);
|
|
|
|
|
if (valueKnown) {
|
|
|
|
|
kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value);
|
|
|
|
|
if (value < 0x100000)
|
|
|
|
|
kprintf(" (\33[34m%lu\33[0m)", (uint32)value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case B_UINT16_TYPE:
|
|
|
|
|
value = read_function_argument_value<uint16>(arg, valueKnown);
|
|
|
|
|
if (valueKnown) {
|
|
|
|
|
kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
|
|
|
|
|
(uint16)value, (uint16)value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case B_UINT8_TYPE:
|
|
|
|
|
value = read_function_argument_value<uint8>(arg, valueKnown);
|
|
|
|
|
if (valueKnown) {
|
|
|
|
|
kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
|
|
|
|
|
(uint8)value, (uint8)value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case B_BOOL_TYPE:
|
|
|
|
|
value = read_function_argument_value<uint8>(arg, valueKnown);
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("\33[34m%s\33[0m", value ? "true" : "false");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (buffer[0])
|
|
|
|
|
kprintf("%s: ", buffer);
|
|
|
|
|
|
|
|
|
|
if (length == 4) {
|
|
|
|
|
value = read_function_argument_value<uint32>(arg,
|
|
|
|
|
valueKnown);
|
|
|
|
|
if (valueKnown) {
|
|
|
|
|
if (value == 0
|
|
|
|
|
&& (type == B_POINTER_TYPE || type == B_REF_TYPE))
|
|
|
|
|
kprintf("NULL");
|
|
|
|
|
else
|
|
|
|
|
kprintf("\33[34m%#lx\33[0m", (uint32)value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (length == 8) {
|
|
|
|
|
value = read_function_argument_value<uint64>(arg,
|
|
|
|
|
valueKnown);
|
|
|
|
|
} else
|
|
|
|
|
value = (uint64)arg;
|
|
|
|
|
|
|
|
|
|
if (valueKnown)
|
|
|
|
|
kprintf("\33[34m%#Lx\33[0m", value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!valueKnown)
|
|
|
|
|
kprintf("???");
|
|
|
|
|
|
|
|
|
|
if (valueKnown && type == B_STRING_TYPE) {
|
|
|
|
|
if (value == 0)
|
|
|
|
|
kprintf(" \33[31m\"<NULL>\"\33[0m");
|
|
|
|
|
else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value,
|
|
|
|
|
kBufferSize) < B_OK) {
|
|
|
|
|
kprintf(" \33[31m\"<???>\"\33[0m");
|
|
|
|
|
} else
|
|
|
|
|
kprintf(" \33[36m\"%s\"\33[0m", buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (addDebugVariables)
|
|
|
|
|
set_debug_argument_variable(i, value);
|
|
|
|
|
arg = (uint32*)((uint8*)arg + length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_free(buffer);
|
|
|
|
|
|
|
|
|
|
kprintf(")");
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_stack_frame(Thread *thread, addr_t ip, addr_t fp, addr_t next,
|
|
|
|
|
int32 callIndex, bool demangle)
|
|
|
|
|
{
|
|
|
|
|
const char* symbol;
|
|
|
|
|
const char* image;
|
|
|
|
|
addr_t baseAddress;
|
|
|
|
|
bool exactMatch;
|
|
|
|
|
status_t status;
|
|
|
|
|
addr_t diff;
|
|
|
|
|
|
|
|
|
|
diff = next - fp;
|
|
|
|
|
|
|
|
|
|
// MSB set = kernel space/user space switch
|
|
|
|
|
if (diff & ~((addr_t)-1 >> 1))
|
|
|
|
|
diff = 0;
|
|
|
|
|
|
|
|
|
|
status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
|
|
|
|
|
&exactMatch);
|
|
|
|
|
|
|
|
|
|
kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex,
|
|
|
|
|
B_PRINTF_POINTER_WIDTH, fp, diff, B_PRINTF_POINTER_WIDTH, ip);
|
|
|
|
|
|
|
|
|
|
if (status == B_OK) {
|
|
|
|
|
if (exactMatch && demangle) {
|
|
|
|
|
status = print_demangled_call(image, symbol,
|
|
|
|
|
next, false, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!exactMatch || !demangle || status != B_OK) {
|
|
|
|
|
if (symbol != NULL) {
|
|
|
|
|
kprintf("<%s> %s%s", image, symbol,
|
|
|
|
|
exactMatch ? "" : " (nearest)");
|
|
|
|
|
} else
|
|
|
|
|
kprintf("<%s@%p> <unknown>", image, (void*)baseAddress);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kprintf(" + %#04lx\n", ip - baseAddress);
|
|
|
|
|
} else {
|
|
|
|
|
VMArea *area = NULL;
|
|
|
|
|
if (thread != NULL && thread->team != NULL
|
|
|
|
|
&& thread->team->address_space != NULL) {
|
|
|
|
|
area = thread->team->address_space->LookupArea(ip);
|
|
|
|
|
}
|
|
|
|
|
if (area != NULL) {
|
|
|
|
|
kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
|
|
|
|
|
(void*)area->Base(), ip - area->Base());
|
|
|
|
|
} else
|
|
|
|
|
kprintf("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
stack_trace(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
|
|
|
|
|
struct iframe_stack *frameStack;
|
|
|
|
|
Thread *thread;
|
|
|
|
|
addr_t framePointer;
|
|
|
|
|
int32 i, num = 0, last = 0;
|
|
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
|
thread = thread_get_current_thread();
|
|
|
|
|
framePointer = (addr_t)get_current_stack_frame();
|
|
|
|
|
} else {
|
|
|
|
|
kprintf("Stack traces of other threads not supported yet!\n");
|
|
|
|
|
return 0;
|
|
|
|
|
static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
|
|
|
|
|
"Prints a stack trace for the current, respectively the specified\n"
|
|
|
|
|
"thread.\n"
|
|
|
|
|
" -d - Disables the demangling of the symbols.\n"
|
|
|
|
|
" <thread id> - The ID of the thread for which to print the stack\n"
|
|
|
|
|
" trace.\n";
|
|
|
|
|
bool demangle = true;
|
|
|
|
|
int32 threadIndex = 1;
|
|
|
|
|
if (argc > 1 && !strcmp(argv[1], "-d")) {
|
|
|
|
|
demangle = false;
|
|
|
|
|
threadIndex++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc > threadIndex + 1
|
|
|
|
|
|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
|
|
|
|
|
kprintf(usage, argv[0]);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
|
|
|
|
|
Thread* thread = NULL;
|
|
|
|
|
phys_addr_t oldPageDirectory = 0;
|
|
|
|
|
addr_t fp = arm_get_fp();
|
|
|
|
|
int32 num = 0, last = 0;
|
|
|
|
|
struct iframe_stack *frameStack;
|
|
|
|
|
|
|
|
|
|
// We don't have a thread pointer early in the boot process
|
|
|
|
|
if (thread != NULL)
|
|
|
|
|
frameStack = &thread->arch_info.iframes;
|
|
|
|
|
else
|
|
|
|
|
frameStack = &gBootFrameStack;
|
|
|
|
|
|
|
|
|
|
int32 i;
|
|
|
|
|
for (i = 0; i < frameStack->index; i++) {
|
|
|
|
|
kprintf("iframe %p (end = %p)\n",
|
|
|
|
|
frameStack->frames[i], frameStack->frames[i] + 1);
|
|
|
|
@@ -168,11 +395,11 @@ return 0;
|
|
|
|
|
|
|
|
|
|
kprintf("frame caller <image>:function + offset\n");
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
for (int32 callIndex = 0;; callIndex++) {
|
|
|
|
|
// see if the frame pointer matches the iframe
|
|
|
|
|
struct iframe *frame = NULL;
|
|
|
|
|
for (i = 0; i < frameStack->index; i++) {
|
|
|
|
|
if (framePointer == (addr_t)frameStack->frames[i]) {
|
|
|
|
|
if (fp == (addr_t)frameStack->frames[i]) {
|
|
|
|
|
// it's an iframe
|
|
|
|
|
frame = frameStack->frames[i];
|
|
|
|
|
break;
|
|
|
|
@@ -181,49 +408,43 @@ return 0;
|
|
|
|
|
|
|
|
|
|
if (frame) {
|
|
|
|
|
kprintf("iframe at %p\n", frame);
|
|
|
|
|
kprintf(" d0 0x%08lx d1 0x%08lx d2 0x%08lx d3 0x%08lx\n",
|
|
|
|
|
frame->d[0], frame->d[1], frame->d[2], frame->d[3]);
|
|
|
|
|
kprintf(" d4 0x%08lx d5 0x%08lx d6 0x%08lx d7 0x%08lx\n",
|
|
|
|
|
frame->d[4], frame->d[5], frame->d[6], frame->d[7]);
|
|
|
|
|
kprintf(" a0 0x%08lx a1 0x%08lx a2 0x%08lx a3 0x%08lx\n",
|
|
|
|
|
frame->a[0], frame->a[1], frame->a[2], frame->a[3]);
|
|
|
|
|
kprintf(" a4 0x%08lx a5 0x%08lx a6 0x%08lx a7 0x%08lx (sp)\n",
|
|
|
|
|
#warning M68K: a7 in iframe ??
|
|
|
|
|
frame->a[4], frame->a[5], frame->a[6], -1L);
|
|
|
|
|
kprintf(" pc 0x%08lx sr 0x%04x\n",
|
|
|
|
|
frame->cpu.pc, frame->cpu.sr);
|
|
|
|
|
#warning M68K: missing regs
|
|
|
|
|
kprintf(" r0 0x%08lx r1 0x%08lx r2 0x%08lx r3 0x%08lx\n",
|
|
|
|
|
frame->r0, frame->r1, frame->r2, frame->r3);
|
|
|
|
|
kprintf(" r4 0x%08lx r5 0x%08lx r6 0x%08lx r7 0x%08lx\n",
|
|
|
|
|
frame->r4, frame->r5, frame->r6, frame->r7);
|
|
|
|
|
kprintf(" r8 0x%08lx r9 0x%08lx r10 0x%08lx r11 0x%08lx\n",
|
|
|
|
|
frame->r8, frame->r9, frame->r10, frame->r11);
|
|
|
|
|
kprintf(" r12 0x%08lx sp 0x%08lx lr 0x%08lx pc 0x%08lx\n",
|
|
|
|
|
frame->r12, frame->svc_sp, frame->svc_lr, frame->pc);
|
|
|
|
|
|
|
|
|
|
print_stack_frame(thread, frame->cpu.pc, framePointer, frame->a[6]);
|
|
|
|
|
framePointer = frame->a[6];
|
|
|
|
|
fp = frame->svc_sp;
|
|
|
|
|
print_stack_frame(thread, frame->pc, frame->svc_sp, frame->svc_lr, callIndex, demangle);
|
|
|
|
|
} else {
|
|
|
|
|
addr_t ip, nextFramePointer;
|
|
|
|
|
addr_t ip, next;
|
|
|
|
|
|
|
|
|
|
if (get_next_frame(framePointer, &nextFramePointer, &ip) != B_OK) {
|
|
|
|
|
kprintf("%08lx -- read fault\n", framePointer);
|
|
|
|
|
if (get_next_frame(fp, &next, &ip) != B_OK) {
|
|
|
|
|
kprintf("%08lx -- read fault\n", fp);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ip == 0 || framePointer == 0)
|
|
|
|
|
if (ip == 0 || fp == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
print_stack_frame(thread, ip, framePointer, nextFramePointer);
|
|
|
|
|
framePointer = nextFramePointer;
|
|
|
|
|
print_stack_frame(thread, ip, fp, next, callIndex, demangle);
|
|
|
|
|
fp = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (already_visited(previousLocations, &last, &num, framePointer)) {
|
|
|
|
|
kprintf("circular stack frame: %p!\n", (void *)framePointer);
|
|
|
|
|
if (already_visited(previousLocations, &last, &num, fp)) {
|
|
|
|
|
kprintf("circular stack frame: %p!\n", (void *)fp);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (framePointer == 0)
|
|
|
|
|
if (fp == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
@@ -245,6 +466,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
|
|
|
|
|
void
|
|
|
|
|
arch_debug_stack_trace(void)
|
|
|
|
|
{
|
|
|
|
|
stack_trace(0, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -261,8 +483,7 @@ int32
|
|
|
|
|
arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
|
|
|
|
|
int32 skipIframes, int32 skipFrames, uint32 flags)
|
|
|
|
|
{
|
|
|
|
|
#warning ARM:IMPLEMENT
|
|
|
|
|
|
|
|
|
|
// TODO: Implement!
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -302,10 +523,9 @@ arch_get_debug_variable(const char* variableName, uint64* value)
|
|
|
|
|
status_t
|
|
|
|
|
arch_debug_init(kernel_args *args)
|
|
|
|
|
{
|
|
|
|
|
// add_debugger_command("where", &stack_trace, "Same as \"sc\"");
|
|
|
|
|
// add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
|
|
|
|
|
// add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
|
|
|
|
|
#warning ARM:IMPLEMENT
|
|
|
|
|
add_debugger_command("where", &stack_trace, "Same as \"sc\"");
|
|
|
|
|
add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
|
|
|
|
|
add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
|
|
|
|
|
|
|
|
|
|
return B_NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|