diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index 1755ca6c2e..2250c94e33 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -66,6 +66,16 @@ struct debugger_module_info { // TODO: add hooks for tunnelling gdb ? }; +struct debugger_demangle_module_info { + module_info info; + + const char* (*demangle_symbol)(const char* name, char* buffer, + size_t bufferSize, bool* _isObjectMethod); + status_t (*get_next_argument)(uint32* _cookie, const char* symbol, + char* name, size_t nameSize, int32* _type, size_t* _argumentLength); +}; + + extern int dbg_register_file[B_MAX_CPU_COUNT][14]; typedef struct debug_page_fault_info { @@ -89,21 +99,21 @@ struct kernel_args; extern status_t debug_init(struct kernel_args *args); extern status_t debug_init_post_vm(struct kernel_args *args); extern status_t debug_init_post_modules(struct kernel_args *args); -extern void debug_early_boot_message(const char *string); -extern void debug_puts(const char *s, int32 length); -extern bool debug_debugger_running(void); -extern bool debug_screen_output_enabled(void); -extern void debug_stop_screen_debug_output(void); -extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc, - uint32 flags); +extern void debug_early_boot_message(const char *string); +extern void debug_puts(const char *s, int32 length); +extern bool debug_debugger_running(void); +extern bool debug_screen_output_enabled(void); +extern void debug_stop_screen_debug_output(void); +extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc, + uint32 flags); extern debug_page_fault_info* debug_get_page_fault_info(); -extern void kputs(const char *string); -extern void kputs_unfiltered(const char *string); -extern void kprintf_unfiltered(const char *format, ...) - __attribute__ ((format (__printf__, 1, 2))); -extern void dprintf_no_syslog(const char *format, ...) - __attribute__ ((format (__printf__, 1, 2))); +extern void kputs(const char *string); +extern void kputs_unfiltered(const char *string); +extern void kprintf_unfiltered(const char *format, ...) + __attribute__ ((format (__printf__, 1, 2))); +extern void dprintf_no_syslog(const char *format, ...) + __attribute__ ((format (__printf__, 1, 2))); extern bool is_debug_variable_defined(const char* variableName); extern bool set_debug_variable(const char* variableName, uint64 value); @@ -125,8 +135,11 @@ extern status_t add_debugger_command_alias(const char* newName, const char* oldName, const char* description); extern bool print_debugger_command_usage(const char* command); -extern void debug_set_demangle_hook(const char *(*hook)(const char *)); -extern const char *debug_demangle(const char *); +extern const char *debug_demangle_symbol(const char* symbol, char* buffer, + size_t bufferSize, bool* _isObjectMethod); +extern status_t debug_get_next_demangled_argument(uint32* _cookie, + const char* symbol, char* name, size_t nameSize, + int32* _type, size_t* _argumentLength); extern struct thread* debug_set_debugged_thread(struct thread* thread); extern struct thread* debug_get_debugged_thread(); diff --git a/src/add-ons/kernel/debugger/demangle/Jamfile b/src/add-ons/kernel/debugger/demangle/Jamfile index bf95c30a0c..48149b6610 100644 --- a/src/add-ons/kernel/debugger/demangle/Jamfile +++ b/src/add-ons/kernel/debugger/demangle/Jamfile @@ -1,43 +1,35 @@ SubDir HAIKU_TOP src add-ons kernel debugger demangle ; -if $(HAIKU_GCC_VERSION[1]) >= 4 { - UsePrivateHeaders kernel ; -UseHeaders [ FDirName $(HAIKU_TOP) src system kernel debug ] ; +# GCC3/4 only solution (using parts of libsubc++) +if $(HAIKU_GCC_VERSION[1]) >= 3 { + rule ExtractObject + { + SetupKernel $(2) ; + Depends $(1) : $(2) ; + Objects $(1) ; -rule ExtractObject -{ - SetupKernel $(2) ; - Depends $(1) : $(2) ; - Objects $(1) ; + MakeLocateDebug $(1) ; + } - MakeLocateDebug $(1) ; -} + actions ExtractObject + { + #$(TARGET_AR) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ; + pwd + echo $(TARGET_AR) -x "$(2)" "$(1)" + } -actions ExtractObject -{ - #$(TARGET_AR) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ; - pwd - echo $(TARGET_AR) -x "$(2)" "$(1)" -} + ExtractObject cp-demangle.o : $(TARGET_STATIC_LIBSUPC++) foo ; -ExtractObject cp-demangle.o : $(TARGET_STATIC_LIBSUPC++) foo ; - -KernelMergeObject demangle_module.o : - demangle.cpp - : - : -; - - - -KernelAddon demangle : - demangle.cpp - #demangle_module.o - cp-demangle.o + KernelAddon gcc3+ : + gcc3+.cpp + cp-demangle.o ; - -#LINKFLAGS on demangle = -lsupc++ ; - } + +# GCC2 solution + +KernelAddon gcc2 : + gcc2.cpp +; diff --git a/src/add-ons/kernel/debugger/demangle/gcc2.cpp b/src/add-ons/kernel/debugger/demangle/gcc2.cpp new file mode 100644 index 0000000000..3b25b6c729 --- /dev/null +++ b/src/add-ons/kernel/debugger/demangle/gcc2.cpp @@ -0,0 +1,394 @@ +/* + * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. + * This file may be used under the terms of the MIT License. + */ + + +#include +#include +#include + +#include + +#include + + +enum { + TYPE_FUNCTION, + TYPE_METHOD, +}; + + +static void +ignore_qualifiers(const char** _arg) +{ + while (isupper(**_arg)) + (*_arg)++; +} + + +static uint32 +argument_type(const char* arg, size_t& length) +{ + length = sizeof(int); + + switch (char type = arg[0]) { + case 'P': // pointer + case 'R': // reference + length = sizeof(void*); + ignore_qualifiers(&arg); + if (arg[0] == 'c') + return B_STRING_TYPE; + + return type == 'P' ? B_POINTER_TYPE : B_REF_TYPE; + case 'x': + length = sizeof(long long); + return B_INT64_TYPE; + case 'l': + if (sizeof(long) == 4) + return B_INT32_TYPE; + return B_INT64_TYPE; + case 'i': + return B_INT32_TYPE; + case 's': + return B_INT16_TYPE; + case 'c': + return B_INT8_TYPE; + case 'b': + return B_BOOL_TYPE; + case 'U': + switch (arg[1]) { + case 'x': + length = sizeof(long long); + return B_UINT64_TYPE; + case 'l': + if (sizeof(long) == 4) + return B_UINT32_TYPE; + return B_UINT64_TYPE; + case 'i': + return B_UINT32_TYPE; + case 's': + return B_UINT16_TYPE; + case 'c': + return B_UINT8_TYPE; + default: + return B_UINT32_TYPE; + } + break; + + default: + return B_ANY_TYPE; + } +} + + +static uint32 +parse_number(const char** _arg, bool numberLeft) +{ + const char* arg = *_arg; + + while (isdigit(arg[0])) + arg++; + + uint32 value; + + if (arg[0] == '_' && (!numberLeft || isdigit(arg[1]))) { + // long value + value = strtoul(*_arg, (char**)_arg, 10); + if (**_arg == '_') + (*_arg)++; + } else { + value = **_arg - '0'; + (*_arg)++; + } + + return value; +} + + +static uint32 +parse_repeats(const char** _arg, uint32& index) +{ + if (**_arg != 'N') + return 0; + + (*_arg)++; + + uint32 count = parse_number(_arg, true); + index = parse_number(_arg, false); + + return count; +} + + +static void +skip_numbers(const char** _arg, int32 count) +{ + // skip leading character + (*_arg)++; + + while (count-- > 0) { + parse_number(_arg, count != 0); + } +} + + +static uint32 +argument_name_length(const char** _arg) +{ + if (**_arg == 'N') + return 0; + + ignore_qualifiers(_arg); + + // See if it's a built-in type + if (isalpha(**_arg)) + return 0; + + return strtoul(*_arg, (char**)_arg, 10); +} + + +static uint32 +argument_length(const char** _arg) +{ + if (**_arg == 'N') { + // skip repeats + skip_numbers(_arg, 2); + return 0; + } else if (**_arg == 'T') { + // skip reference + skip_numbers(_arg, 1); + return 0; + } + + ignore_qualifiers(_arg); + + // See if it's a built-in type + if (isalpha(**_arg)) + return 1; + + return strtoul(*_arg, (char**)_arg, 10); +} + + +static const char* +next_argument(const char* arg) +{ + if (arg == NULL) + return NULL; + + uint32 length = argument_length(&arg); + arg += length; + + if (!arg[0]) + return NULL; + + return arg; +} + + +static uint32 +count_namespaces(const char** _mangled) +{ + const char* mangled = *_mangled; + + int32 namespaces = 0; + if (mangled[0] == 'Q') { + // more than one namespace + if (mangled[1] == '_') { + // more than 9 namespaces + namespaces = strtoul(mangled + 1, (char**)&mangled, 10); + if (mangled[0] != '_') + namespaces = 0; + } else + namespaces = mangled[1] - '0'; + + mangled++; + } else if (isdigit(mangled[0])) + namespaces = 1; + + *_mangled = mangled; + return namespaces; +} + + +static const char* +first_argument(const char* mangled) +{ + int32 namespaces = count_namespaces(&mangled); + + while (namespaces-- > 0) { + if (!isdigit(mangled[0])) + break; + + mangled += strtoul(mangled, (char**)&mangled, 10); + } + + return mangled; +} + + +static const char* +mangled_start(const char* name, size_t* _symbolLength, int32* _symbolType) +{ + if (name == NULL) + return NULL; + + const char* mangled = strstr(name, "__"); + if (mangled == NULL) + return NULL; + + if (_symbolLength != NULL) + *_symbolLength = mangled - name; + + if (mangled[2] == 'F') { + if (_symbolType != NULL) + *_symbolType = TYPE_FUNCTION; + return mangled + 3; + } + + if (_symbolType != NULL) + *_symbolType = TYPE_METHOD; + return mangled + 2; +} + + + +// #pragma mark - + + +const char* +demangle_symbol(const char* name, char* buffer, size_t bufferSize, + bool* _isObjectMethod) +{ + size_t nameLength; + int32 type; + const char* mangled = mangled_start(name, &nameLength, &type); + if (mangled == NULL) + return NULL; + + if (_isObjectMethod != NULL) { + // we can only guess with GCC2 mangling + *_isObjectMethod = type == TYPE_METHOD; + } + + const char* namespaceStart = mangled; + int32 namespaces = count_namespaces(&namespaceStart); + + buffer[0] = '\0'; + + while (namespaces-- > 0) { + if (!isdigit(namespaceStart[0])) + break; + + uint32 length = strtoul(namespaceStart, (char**)&namespaceStart, 10); + uint32 max = strlen(buffer) + length + 1; + strlcat(buffer, namespaceStart, min_c(max, bufferSize)); + strlcat(buffer, "::", bufferSize); + namespaceStart += length; + } + + size_t max = strlen(buffer) + nameLength + 1; + strlcat(buffer, name, min_c(max, bufferSize)); + return buffer; +} + + +status_t +get_next_argument(uint32* _cookie, const char* symbol, char* name, + size_t nameSize, int32* _type, size_t* _argumentLength) +{ + const char* mangled = mangled_start(symbol, NULL, NULL); + if (mangled == NULL) + return B_BAD_VALUE; + + const char* arg = first_argument(mangled); + + // (void) is not an argument + if (arg != NULL && arg[0] == 'v') + return B_ENTRY_NOT_FOUND; + + uint32 current = *_cookie; + for (uint32 i = 0; i < current; i++) { + arg = next_argument(arg); + if (arg != NULL && arg[0] == 'N') { + // repeat argument 'count' times + uint32 index; + uint32 count = parse_repeats(&arg, index); + if (current <= i + count) { + // it's a repeat case + status_t status = get_next_argument(&index, symbol, name, + nameSize, _type, _argumentLength); + if (status == B_OK) + (*_cookie)++; + return status; + } + + i += count - 1; + } + } + + if (arg == NULL) + return B_ENTRY_NOT_FOUND; + + if (arg[0] == 'T') { + // duplicate argument + arg++; + uint32 index = parse_number(&arg, false); + status_t status = get_next_argument(&index, symbol, name, + nameSize, _type, _argumentLength); + if (status == B_OK) + (*_cookie)++; + return status; + } + + (*_cookie)++; + + size_t argumentLength; + int32 type = argument_type(arg, argumentLength); + if (_type != NULL) + *_type = type; + if (_argumentLength != NULL) + *_argumentLength = argumentLength; + + uint32 length = argument_name_length(&arg); + strlcpy(name, arg, min_c(length + 1, nameSize)); + + return B_OK; +} + + +static status_t +std_ops(int32 op, ...) +{ +#if __GNUC__ != 2 + return B_NOT_SUPPORTED; +#else + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + } + + return B_BAD_VALUE; +#endif +} + + +static struct debugger_demangle_module_info sModuleInfo = { + { + "debugger/demangle/gcc2/v1", + 0, + std_ops + }, + + demangle_symbol, + get_next_argument, +}; + +module_info *modules[] = { + (module_info *)&sModuleInfo, + NULL +}; + diff --git a/src/add-ons/kernel/debugger/demangle/demangle.cpp b/src/add-ons/kernel/debugger/demangle/gcc3+.cpp similarity index 77% rename from src/add-ons/kernel/debugger/demangle/demangle.cpp rename to src/add-ons/kernel/debugger/demangle/gcc3+.cpp index b09c25b206..238867ee0d 100644 --- a/src/add-ons/kernel/debugger/demangle/demangle.cpp +++ b/src/add-ons/kernel/debugger/demangle/gcc3+.cpp @@ -2,23 +2,26 @@ * Copyright 2008, François Revol, revol@free.fr * Distributed under the terms of the MIT License. */ + #include #include -#include -#include +#include #include +#include + #define DEMANGLE_BUFFER_SIZE (16*1024) static char sDemangleBuffer[DEMANGLE_BUFFER_SIZE]; extern "C" void set_debug_demangle_hook(const char *(*demangle_hook)(const char *)); /* gcc's __cxa_demangle calls malloc and friends... - * we don't want to let it call the real one from inside the kernel debugger... + * we don't want to let it call the real one from inside the kernel debugger... * instead we just return it a static buffer. */ -void *malloc(size_t len) +void * +malloc(size_t len) { if (len < DEMANGLE_BUFFER_SIZE) return sDemangleBuffer; @@ -26,12 +29,14 @@ void *malloc(size_t len) } -void free(void *ptr) +void +free(void *ptr) { } -void *realloc(void * old_ptr, size_t new_size) +void * +realloc(void * oldPtr, size_t newSize) { return NULL; } @@ -134,7 +139,10 @@ DemangleDebugOutputFilter::Print(const char* format, va_list args) } #endif -static const char *kdebug_demangle(const char *sym) + +static const char * +demangle_symbol(const char *sym, char* buffer, size_t bufferSize, + bool* _isObjectMethod) { char *demangled; size_t length = DEMANGLE_BUFFER_SIZE; @@ -147,47 +155,19 @@ static const char *kdebug_demangle(const char *sym) return sym; } -static void -exit_debugger() -{ -} - -static status_t -std_ops(int32 op, ...) -{ - if (op == B_MODULE_INIT) { -#if 0 - DebugOutputFilter *old; - DemangleDebugOutputFilter *filter = new(std::nothrow) DemangleDebugOutputFilter; - old = set_debug_output_filter(filter); - filter->SetChain(old); -#endif - debug_set_demangle_hook(kdebug_demangle); - - return B_OK; - } else if (op == B_MODULE_UNINIT) { - return B_OK; - } - - return B_BAD_VALUE; -} - - -static struct debugger_module_info sModuleInfo = { +static struct debugger_demangle_module_info sModuleInfo = { { - "debugger/demangle/v1", - B_KEEP_LOADED, - &std_ops + "debugger/demangle/gcc3+/v1", + 0, + NULL }, + demangle_symbol, NULL, - exit_debugger, - NULL, - NULL }; -module_info *modules[] = { +module_info *modules[] = { (module_info *)&sModuleInfo, NULL }; diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index ac62bd264d..dd1e630047 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -99,10 +99,6 @@ lookup_symbol(struct thread* thread, addr_t address, addr_t *_baseAddress, } } - if (status == B_OK) { - *_symbolName = debug_demangle(*_symbolName); - } - return status; } @@ -126,11 +122,17 @@ print_stack_frame(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, &exactMatch); + char buffer[64]; + const char* name = debug_demangle_symbol(symbol, buffer, sizeof(buffer), + NULL); + if (name == NULL) + name = symbol; + kprintf("%2ld %08lx (+%4ld) %08lx", callIndex, ebp, diff, eip); if (status == B_OK) { - if (symbol != NULL) { - kprintf(" <%s>:%s + 0x%04lx%s\n", image, symbol, + if (name != NULL) { + kprintf(" <%s>:%s + 0x%04lx%s\n", image, name, eip - baseAddress, exactMatch ? "" : " (nearest)"); } else { kprintf(" <%s@%p>:unknown + 0x%04lx\n", image, @@ -436,6 +438,15 @@ stack_trace(int argc, char **argv) } +static void +set_debug_argument_variable(int32 index, uint64 value) +{ + char name[8]; + snprintf(name, sizeof(name), "_arg%ld", index); + set_debug_variable(name, value); +} + + static void print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, int32 argCount) @@ -444,6 +455,9 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, addr_t baseAddress; bool exactMatch; status_t status; + char buffer[64]; + const char* name = NULL; + bool isObjectMethod; status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, &exactMatch); @@ -452,8 +466,16 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, if (status == B_OK) { if (symbol != NULL) { - kprintf(" <%s>:%s%s", image, symbol, - exactMatch ? "" : " (nearest)"); + if (exactMatch && argCount <= 0) { + name = debug_demangle_symbol(symbol, buffer, sizeof(buffer), + &isObjectMethod); + if (argCount < 0) + isObjectMethod = false; + } + if (name == NULL) { + kprintf(" <%s>:%s%s", image, symbol, + exactMatch ? "" : " (nearest)"); + } } else { kprintf(" <%s@%p>:unknown + 0x%04lx", image, (void *)baseAddress, eip - baseAddress); @@ -469,20 +491,114 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, } int32 *arg = (int32 *)(nextEbp + 8); - kprintf("("); - for (int32 i = 0; i < argCount; i++) { - if (i > 0) - kprintf(", "); - kprintf("%#lx", *arg); - if (*arg > -0x10000 && *arg < 0x10000) - kprintf(" (%ld)", *arg); + if (name != NULL) { + if (isObjectMethod) { + const char* lastName = strrchr(name, ':') - 1; + int namespaceLength = lastName - name; - char name[8]; - snprintf(name, sizeof(name), "_arg%ld", i + 1); - set_debug_variable(name, *(uint32 *)arg); + kprintf(" <%s> %.*s<%p>%s", image, namespaceLength, name, + *(uint32 **)arg, lastName); + set_debug_variable("_this", *(uint32 *)arg); + arg++; + } else + kprintf(" <%s> %s", image, name); - arg++; + kprintf("("); + + char buffer[64]; + size_t length; + int32 type, i = 0; + uint32 cookie = 0; + while (debug_get_next_demangled_argument(&cookie, symbol, buffer, + sizeof(buffer), &type, &length) == B_OK) { + if (i++ > 0) + kprintf(", "); + + // retrieve value and type identifier + + uint64 value; + + switch (type) { + case B_INT64_TYPE: + value = *(int64*)arg; + kprintf("int64: %Ld", value); + break; + case B_INT32_TYPE: + value = *(int32*)arg; + kprintf("int32: %ld", (int32)value); + break; + case B_INT16_TYPE: + value = *(int16*)arg; + kprintf("int16: %d", (int16)value); + break; + case B_INT8_TYPE: + value = *(int8*)arg; + kprintf("int8: %d", (int8)value); + break; + case B_UINT64_TYPE: + value = *(uint64*)arg; + kprintf("uint64: %Lx", value); + if (value < 0x100000) + kprintf(" (%Lu)", value); + break; + case B_UINT32_TYPE: + value = *(uint32*)arg; + kprintf("uint32: %lx", (uint32)value); + if (value < 0x100000) + kprintf(" (%lu)", (uint32)value); + break; + case B_UINT16_TYPE: + value = *(uint16*)arg; + kprintf("uint16: %#x (%u)", (uint16)value, (uint16)value); + break; + case B_UINT8_TYPE: + value = *(uint8*)arg; + kprintf("uint8: %#x (%u)", (uint8)value, (uint8)value); + break; + case B_BOOL_TYPE: + value = *(uint8*)arg; + kprintf(value ? "true" : "false"); + break; + default: + if (buffer[0]) { + kprintf("%s%s: ", buffer, type == B_POINTER_TYPE ? "*" + : type == B_REF_TYPE ? "&" : ""); + } + + if (length == 4) { + value = *(uint32*)arg; + kprintf("%#lx", (uint32)value); + break; + } + + if (length == 8) + value = *(uint64*)arg; + else + value = (uint64)arg; + kprintf("%#Lx", value); + break; + } + + if (type == B_STRING_TYPE && value != 0) + kprintf(" \"%s\"", (char*)value); + + set_debug_argument_variable(i, value); + arg = (int32*)((uint8*)arg + length); + } + } else { + kprintf("("); + + for (int32 i = 0; i < argCount; i++) { + if (i > 0) + kprintf(", "); + kprintf("%#lx", *arg); + if (*arg > -0x10000 && *arg < 0x10000) + kprintf(" (%ld)", *arg); + + set_debug_argument_variable(i + 1, *(uint32 *)arg); + arg++; + } } kprintf(")\n"); @@ -500,7 +616,8 @@ show_call(int argc, char **argv) "the specified thread.\n" " - The ID of the thread for which to print the call.\n" " - The index of the call in the stack trace.\n" - " - The number of call arguments to print.\n"; + " - The number of call arguments to print (use 'c' to\n" + " force the C++ demangler to use class methods).\n"; if (argc == 2 && strcmp(argv[1], "--help") == 0) { kprintf(usage, argv[0]); return 0; @@ -512,8 +629,11 @@ show_call(int argc, char **argv) int32 argCount = 0; if (argc >= 2 && argv[argc - 1][0] == '-') { - argCount = strtoul(argv[argc - 1] + 1, NULL, 0); - if (argCount < 0 || argCount > 16) { + if (argv[argc - 1][1] != 'c') + argCount = strtoul(argv[argc - 1] + 1, NULL, 0); + else + argCount = -1; + if (argCount < -1 || argCount > 16) { kprintf("Invalid argument count \"%ld\".\n", argCount); return 0; } diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 889a3842ed..58bda07af2 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -81,7 +81,7 @@ static int64 sMessageRepeatFirstTime = 0; static int64 sMessageRepeatLastTime = 0; static int32 sMessageRepeatCount = 0; -static debugger_module_info *sDebuggerModules[8]; +static debugger_module_info* sDebuggerModules[8]; static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules) / sizeof(sDebuggerModules[0]); @@ -91,7 +91,7 @@ static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules) static char sLineBuffer[HISTORY_SIZE][LINE_BUFFER_SIZE] = { "", }; static int32 sCurrentLine = 0; -static const char *(*sDemangleHook)(const char *) = NULL; +static debugger_demangle_module_info* sDemangleModule; static struct thread* sDebuggedThread; @@ -1105,7 +1105,7 @@ debug_init_post_vm(kernel_args *args) status_t -debug_init_post_modules(struct kernel_args *args) +debug_init_post_modules(struct kernel_args* args) { void *cookie; @@ -1115,6 +1115,9 @@ debug_init_post_modules(struct kernel_args *args) syslog_init_post_threads(); // load kernel debugger addons + + static const char* kDemanglePrefix = "debugger/demangle/"; + cookie = open_module_list("debugger"); uint32 count = 0; while (count < kMaxDebuggerModules) { @@ -1124,7 +1127,14 @@ debug_init_post_modules(struct kernel_args *args) if (read_next_module_name(cookie, name, &nameLength) != B_OK) break; - if (get_module(name, (module_info **)&sDebuggerModules[count]) == B_OK) { + // get demangle module, if any + if (!strncmp(name, kDemanglePrefix, strlen(kDemanglePrefix))) { + if (sDemangleModule == NULL) + get_module(name, (module_info**)&sDemangleModule); + continue; + } + + if (get_module(name, (module_info**)&sDebuggerModules[count]) == B_OK) { dprintf("kernel debugger extension \"%s\": loaded\n", name); count++; } else @@ -1273,9 +1283,10 @@ flush_pending_repeats(void) syslog_write(temp, length); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(temp); - for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) + for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) { if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) sDebuggerModules[i]->debugger_puts(temp, length); + } } else { // if we only have one repeat just reprint the last buffer if (sSerialDebugEnabled) @@ -1284,9 +1295,12 @@ flush_pending_repeats(void) syslog_write(sLastOutputBuffer, strlen(sLastOutputBuffer)); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(sLastOutputBuffer); - for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) - if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) - sDebuggerModules[i]->debugger_puts(sLastOutputBuffer, strlen(sLastOutputBuffer)); + for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) { + if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) { + sDebuggerModules[i]->debugger_puts(sLastOutputBuffer, + strlen(sLastOutputBuffer)); + } + } } sMessageRepeatFirstTime = 0; @@ -1348,9 +1362,10 @@ dprintf_args(const char *format, va_list args, bool syslogOutput) syslog_write(sOutputBuffer, length); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(sOutputBuffer); - for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) + for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) { if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) sDebuggerModules[i]->debugger_puts(sOutputBuffer, length); + } memcpy(sLastOutputBuffer, sOutputBuffer, length); sLastOutputBuffer[length] = 0; @@ -1414,19 +1429,29 @@ kprintf_unfiltered(const char *format, ...) } -extern void -debug_set_demangle_hook(const char *(*hook)(const char *)) +const char* +debug_demangle_symbol(const char* symbol, char* buffer, size_t bufferSize, + bool* _isObjectMethod) { - sDemangleHook = hook; + if (sDemangleModule != NULL && sDemangleModule->demangle_symbol != NULL) { + return sDemangleModule->demangle_symbol(symbol, buffer, bufferSize, + _isObjectMethod); + } + + return symbol; } -extern const char * -debug_demangle(const char *sym) +status_t +debug_get_next_demangled_argument(uint32* _cookie, const char* symbol, + char* name, size_t nameSize, int32* _type, size_t* _argumentLength) { - if (sDemangleHook) - return sDemangleHook(sym); - return sym; + if (sDemangleModule != NULL && sDemangleModule->get_next_argument != NULL) { + return sDemangleModule->get_next_argument(_cookie, symbol, name, + nameSize, _type, _argumentLength); + } + + return B_NOT_SUPPORTED; }