ARM: kernel: Make KDL more useful on ARM
This adds the -mapcs-frame compiler flag for ARM to have "stable" stack frames, adds support to the kernel for dumping stack crawls, and initial support for iframes. There' much more functionality to unlock in KDL, but this makes debugging already a lot more comfortable.....
This commit is contained in:
@@ -242,6 +242,8 @@ switch $(HAIKU_CPU) {
|
|||||||
case arm :
|
case arm :
|
||||||
{
|
{
|
||||||
HAIKU_DEFINES += __ARM__ ;
|
HAIKU_DEFINES += __ARM__ ;
|
||||||
|
HAIKU_CCFLAGS += -mapcs-frame ; # For stackcrawls
|
||||||
|
HAIKU_C++FLAGS += -mapcs-frame ;
|
||||||
HAIKU_BOOT_PLATFORM ?= u-boot ;
|
HAIKU_BOOT_PLATFORM ?= u-boot ;
|
||||||
HAIKU_BOOT_BOARD ?= verdex ;
|
HAIKU_BOOT_BOARD ?= verdex ;
|
||||||
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ;
|
HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ;
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ extern "C" {
|
|||||||
|
|
||||||
extern addr_t arm_get_far(void);
|
extern addr_t arm_get_far(void);
|
||||||
extern int32 arm_get_fsr(void);
|
extern int32 arm_get_fsr(void);
|
||||||
|
extern addr_t arm_get_fp(void);
|
||||||
|
|
||||||
extern int mmu_read_c1(void);
|
extern int mmu_read_c1(void);
|
||||||
extern int mmu_write_c1(int val);
|
extern int mmu_write_c1(int val);
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ FUNCTION(arm_get_far):
|
|||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_get_far)
|
FUNCTION_END(arm_get_far)
|
||||||
|
|
||||||
|
/* addr_t arm_get_fp(void); */
|
||||||
|
FUNCTION(arm_get_fp):
|
||||||
|
mov r0, fp @ get framepointer
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(arm_get_fp);
|
||||||
|
|
||||||
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
||||||
FUNCTION(arch_cpu_user_memcpy):
|
FUNCTION(arch_cpu_user_memcpy):
|
||||||
stmfd sp!, { r4-r6 }
|
stmfd sp!, { r4-r6 }
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
* Axel Dörfler <[email protected]>
|
* Axel Dörfler <[email protected]>
|
||||||
* Ingo Weinhold <[email protected]>
|
* Ingo Weinhold <[email protected]>
|
||||||
* François Revol <[email protected]>
|
* François Revol <[email protected]>
|
||||||
|
* Ithamar R. Adema <[email protected]>
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -13,25 +15,22 @@
|
|||||||
|
|
||||||
#include <arch_cpu.h>
|
#include <arch_cpu.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <debug_heap.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <kimage.h>
|
#include <kimage.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
|
#include <vm/vm_types.h>
|
||||||
|
#include <vm/VMAddressSpace.h>
|
||||||
struct stack_frame {
|
#include <vm/VMArea.h>
|
||||||
struct stack_frame *previous;
|
|
||||||
addr_t return_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NUM_PREVIOUS_LOCATIONS 32
|
#define NUM_PREVIOUS_LOCATIONS 32
|
||||||
|
|
||||||
extern struct iframe_stack gBootFrameStack;
|
extern struct iframe_stack gBootFrameStack;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
static bool
|
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 last = *_last;
|
||||||
int32 num = *_num;
|
int32 num = *_num;
|
||||||
@@ -39,13 +38,13 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
|
|||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
if (visited[(NUM_PREVIOUS_LOCATIONS + last - i)
|
if (visited[(NUM_PREVIOUS_LOCATIONS + last - i)
|
||||||
% NUM_PREVIOUS_LOCATIONS] == framePointer) {
|
% NUM_PREVIOUS_LOCATIONS] == fp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
|
*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
|
||||||
visited[last] = framePointer;
|
visited[last] = fp;
|
||||||
|
|
||||||
if (num < NUM_PREVIOUS_LOCATIONS)
|
if (num < NUM_PREVIOUS_LOCATIONS)
|
||||||
*_num = num + 1;
|
*_num = num + 1;
|
||||||
@@ -54,99 +53,327 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline stack_frame *
|
static status_t
|
||||||
get_current_stack_frame()
|
get_next_frame(addr_t fp, addr_t *next, addr_t *ip)
|
||||||
{
|
{
|
||||||
stack_frame *frame;
|
if (fp != 0) {
|
||||||
asm volatile("move.l %%fp,%0" : "=r"(frame));
|
addr_t _fp = *(((addr_t*)fp) -3);
|
||||||
return frame;
|
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
|
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();
|
status_t status = B_ENTRY_NOT_FOUND;
|
||||||
addr_t oldFaultHandler = thread->fault_handler;
|
|
||||||
|
|
||||||
// set fault handler, so that we can safely access user stacks
|
if (IS_KERNEL_ADDRESS(address)) {
|
||||||
if (thread) {
|
// a kernel symbol
|
||||||
if (m68k_set_fault_handler(&thread->fault_handler, (addr_t)&&error))
|
status = elf_debug_lookup_symbol_address(address, _baseAddress,
|
||||||
goto error;
|
_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;
|
return status;
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
|
set_debug_argument_variable(int32 index, uint64 value)
|
||||||
addr_t nextFramePointer)
|
|
||||||
{
|
{
|
||||||
addr_t diff = nextFramePointer - framePointer;
|
char name[8];
|
||||||
|
snprintf(name, sizeof(name), "_arg%ld", index);
|
||||||
// kernel space/user space switch
|
set_debug_variable(name, value);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
static int
|
||||||
stack_trace(int argc, char **argv)
|
stack_trace(int argc, char **argv)
|
||||||
{
|
{
|
||||||
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
|
static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
|
||||||
struct iframe_stack *frameStack;
|
"Prints a stack trace for the current, respectively the specified\n"
|
||||||
Thread *thread;
|
"thread.\n"
|
||||||
addr_t framePointer;
|
" -d - Disables the demangling of the symbols.\n"
|
||||||
int32 i, num = 0, last = 0;
|
" <thread id> - The ID of the thread for which to print the stack\n"
|
||||||
|
" trace.\n";
|
||||||
if (argc < 2) {
|
bool demangle = true;
|
||||||
thread = thread_get_current_thread();
|
int32 threadIndex = 1;
|
||||||
framePointer = (addr_t)get_current_stack_frame();
|
if (argc > 1 && !strcmp(argv[1], "-d")) {
|
||||||
} else {
|
demangle = false;
|
||||||
kprintf("Stack traces of other threads not supported yet!\n");
|
threadIndex++;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// We don't have a thread pointer early in the boot process
|
||||||
if (thread != NULL)
|
if (thread != NULL)
|
||||||
frameStack = &thread->arch_info.iframes;
|
frameStack = &thread->arch_info.iframes;
|
||||||
else
|
else
|
||||||
frameStack = &gBootFrameStack;
|
frameStack = &gBootFrameStack;
|
||||||
|
|
||||||
|
int32 i;
|
||||||
for (i = 0; i < frameStack->index; i++) {
|
for (i = 0; i < frameStack->index; i++) {
|
||||||
kprintf("iframe %p (end = %p)\n",
|
kprintf("iframe %p (end = %p)\n",
|
||||||
frameStack->frames[i], frameStack->frames[i] + 1);
|
frameStack->frames[i], frameStack->frames[i] + 1);
|
||||||
@@ -168,11 +395,11 @@ return 0;
|
|||||||
|
|
||||||
kprintf("frame caller <image>:function + offset\n");
|
kprintf("frame caller <image>:function + offset\n");
|
||||||
|
|
||||||
for (;;) {
|
for (int32 callIndex = 0;; callIndex++) {
|
||||||
// see if the frame pointer matches the iframe
|
// see if the frame pointer matches the iframe
|
||||||
struct iframe *frame = NULL;
|
struct iframe *frame = NULL;
|
||||||
for (i = 0; i < frameStack->index; i++) {
|
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
|
// it's an iframe
|
||||||
frame = frameStack->frames[i];
|
frame = frameStack->frames[i];
|
||||||
break;
|
break;
|
||||||
@@ -181,49 +408,43 @@ return 0;
|
|||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
kprintf("iframe at %p\n", frame);
|
kprintf("iframe at %p\n", frame);
|
||||||
kprintf(" d0 0x%08lx d1 0x%08lx d2 0x%08lx d3 0x%08lx\n",
|
kprintf(" r0 0x%08lx r1 0x%08lx r2 0x%08lx r3 0x%08lx\n",
|
||||||
frame->d[0], frame->d[1], frame->d[2], frame->d[3]);
|
frame->r0, frame->r1, frame->r2, frame->r3);
|
||||||
kprintf(" d4 0x%08lx d5 0x%08lx d6 0x%08lx d7 0x%08lx\n",
|
kprintf(" r4 0x%08lx r5 0x%08lx r6 0x%08lx r7 0x%08lx\n",
|
||||||
frame->d[4], frame->d[5], frame->d[6], frame->d[7]);
|
frame->r4, frame->r5, frame->r6, frame->r7);
|
||||||
kprintf(" a0 0x%08lx a1 0x%08lx a2 0x%08lx a3 0x%08lx\n",
|
kprintf(" r8 0x%08lx r9 0x%08lx r10 0x%08lx r11 0x%08lx\n",
|
||||||
frame->a[0], frame->a[1], frame->a[2], frame->a[3]);
|
frame->r8, frame->r9, frame->r10, frame->r11);
|
||||||
kprintf(" a4 0x%08lx a5 0x%08lx a6 0x%08lx a7 0x%08lx (sp)\n",
|
kprintf(" r12 0x%08lx sp 0x%08lx lr 0x%08lx pc 0x%08lx\n",
|
||||||
#warning M68K: a7 in iframe ??
|
frame->r12, frame->svc_sp, frame->svc_lr, frame->pc);
|
||||||
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
|
|
||||||
|
|
||||||
print_stack_frame(thread, frame->cpu.pc, framePointer, frame->a[6]);
|
fp = frame->svc_sp;
|
||||||
framePointer = frame->a[6];
|
print_stack_frame(thread, frame->pc, frame->svc_sp, frame->svc_lr, callIndex, demangle);
|
||||||
} else {
|
} else {
|
||||||
addr_t ip, nextFramePointer;
|
addr_t ip, next;
|
||||||
|
|
||||||
if (get_next_frame(framePointer, &nextFramePointer, &ip) != B_OK) {
|
if (get_next_frame(fp, &next, &ip) != B_OK) {
|
||||||
kprintf("%08lx -- read fault\n", framePointer);
|
kprintf("%08lx -- read fault\n", fp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip == 0 || framePointer == 0)
|
if (ip == 0 || fp == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
print_stack_frame(thread, ip, framePointer, nextFramePointer);
|
print_stack_frame(thread, ip, fp, next, callIndex, demangle);
|
||||||
framePointer = nextFramePointer;
|
fp = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (already_visited(previousLocations, &last, &num, framePointer)) {
|
if (already_visited(previousLocations, &last, &num, fp)) {
|
||||||
kprintf("circular stack frame: %p!\n", (void *)framePointer);
|
kprintf("circular stack frame: %p!\n", (void *)fp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (framePointer == 0)
|
if (fp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
@@ -245,6 +466,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
|
|||||||
void
|
void
|
||||||
arch_debug_stack_trace(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,
|
arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
|
||||||
int32 skipIframes, int32 skipFrames, uint32 flags)
|
int32 skipIframes, int32 skipFrames, uint32 flags)
|
||||||
{
|
{
|
||||||
#warning ARM:IMPLEMENT
|
// TODO: Implement!
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,10 +523,9 @@ arch_get_debug_variable(const char* variableName, uint64* value)
|
|||||||
status_t
|
status_t
|
||||||
arch_debug_init(kernel_args *args)
|
arch_debug_init(kernel_args *args)
|
||||||
{
|
{
|
||||||
// add_debugger_command("where", &stack_trace, "Same as \"sc\"");
|
add_debugger_command("where", &stack_trace, "Same as \"sc\"");
|
||||||
// add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
|
add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
|
||||||
// add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
|
add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
|
||||||
#warning ARM:IMPLEMENT
|
|
||||||
|
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,9 +188,35 @@ arch_int_init_post_device_manager(struct kernel_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Little helper class for handling the
|
||||||
|
// iframe stack as used by KDL.
|
||||||
|
class IFrameScope {
|
||||||
|
public:
|
||||||
|
IFrameScope(struct iframe *iframe) {
|
||||||
|
fThread = thread_get_current_thread();
|
||||||
|
if (fThread)
|
||||||
|
arm_push_iframe(&fThread->arch_info.iframes, iframe);
|
||||||
|
else
|
||||||
|
arm_push_iframe(&gBootFrameStack, iframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~IFrameScope() {
|
||||||
|
// pop iframe
|
||||||
|
if (fThread)
|
||||||
|
arm_pop_iframe(&fThread->arch_info.iframes);
|
||||||
|
else
|
||||||
|
arm_pop_iframe(&gBootFrameStack);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Thread* fThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_undefined(struct iframe *iframe)
|
arch_arm_undefined(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe); // push/pop iframe
|
||||||
|
|
||||||
print_iframe("Undefined Instruction", iframe);
|
print_iframe("Undefined Instruction", iframe);
|
||||||
panic("not handled!");
|
panic("not handled!");
|
||||||
}
|
}
|
||||||
@@ -199,6 +225,8 @@ arch_arm_undefined(struct iframe *iframe)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_syscall(struct iframe *iframe)
|
arch_arm_syscall(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe); // push/pop iframe
|
||||||
|
|
||||||
print_iframe("Software interrupt", iframe);
|
print_iframe("Software interrupt", iframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +234,8 @@ arch_arm_syscall(struct iframe *iframe)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_data_abort(struct iframe *frame)
|
arch_arm_data_abort(struct iframe *frame)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe);
|
||||||
|
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread *thread = thread_get_current_thread();
|
||||||
bool isUser = (frame->spsr & 0x1f) == 0x10;
|
bool isUser = (frame->spsr & 0x1f) == 0x10;
|
||||||
addr_t far = arm_get_far();
|
addr_t far = arm_get_far();
|
||||||
@@ -290,6 +320,8 @@ arch_arm_data_abort(struct iframe *frame)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_prefetch_abort(struct iframe *iframe)
|
arch_arm_prefetch_abort(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe);
|
||||||
|
|
||||||
print_iframe("Prefetch Abort", iframe);
|
print_iframe("Prefetch Abort", iframe);
|
||||||
panic("not handled!");
|
panic("not handled!");
|
||||||
}
|
}
|
||||||
@@ -298,6 +330,8 @@ arch_arm_prefetch_abort(struct iframe *iframe)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_irq(struct iframe *iframe)
|
arch_arm_irq(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe);
|
||||||
|
|
||||||
for (int i=0; i < 32; i++) {
|
for (int i=0; i < 32; i++) {
|
||||||
if (sPxaInterruptBase[PXA_ICIP] & (1 << i))
|
if (sPxaInterruptBase[PXA_ICIP] & (1 << i))
|
||||||
int_io_interrupt_handler(i, true);
|
int_io_interrupt_handler(i, true);
|
||||||
@@ -308,6 +342,8 @@ arch_arm_irq(struct iframe *iframe)
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
arch_arm_fiq(struct iframe *iframe)
|
arch_arm_fiq(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
|
IFrameScope scope(iframe);
|
||||||
|
|
||||||
for (int i=0; i < 32; i++) {
|
for (int i=0; i < 32; i++) {
|
||||||
if (sPxaInterruptBase[PXA_ICIP] & (1 << i)) {
|
if (sPxaInterruptBase[PXA_ICIP] & (1 << i)) {
|
||||||
dprintf("arch_arm_fiq: help me, FIQ %d was triggered but no "
|
dprintf("arch_arm_fiq: help me, FIQ %d was triggered but no "
|
||||||
|
|||||||
@@ -42,6 +42,23 @@ static struct arch_thread sInitialState;
|
|||||||
Thread *gCurrentThread;
|
Thread *gCurrentThread;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arm_push_iframe(struct iframe_stack *stack, struct iframe *frame)
|
||||||
|
{
|
||||||
|
ASSERT(stack->index < IFRAME_TRACE_DEPTH);
|
||||||
|
stack->frames[stack->index++] = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arm_pop_iframe(struct iframe_stack *stack)
|
||||||
|
{
|
||||||
|
ASSERT(stack->index > 0);
|
||||||
|
stack->index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_thread_init(struct kernel_args *args)
|
arch_thread_init(struct kernel_args *args)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user