diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index e4d825e23b..ddd8cb131b 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -111,6 +111,9 @@ extern bool print_debugger_command_usage(const char* command); extern void _user_debug_output(const char *userString); +extern void debug_set_demangle_hook(const char *(*hook)(const char *)); +extern const char *debug_demangle(const char *); + #ifdef __cplusplus } #endif diff --git a/src/add-ons/kernel/debugger/Jamfile b/src/add-ons/kernel/debugger/Jamfile index 675e619e47..f346ebfddb 100644 --- a/src/add-ons/kernel/debugger/Jamfile +++ b/src/add-ons/kernel/debugger/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel debugger ; SubInclude HAIKU_TOP src add-ons kernel debugger auto_stack_trace ; SubInclude HAIKU_TOP src add-ons kernel debugger bochs ; +SubInclude HAIKU_TOP src add-ons kernel debugger demangle ; SubInclude HAIKU_TOP src add-ons kernel debugger hangman ; SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ; SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ; diff --git a/src/add-ons/kernel/debugger/demangle/Jamfile b/src/add-ons/kernel/debugger/demangle/Jamfile new file mode 100644 index 0000000000..bf95c30a0c --- /dev/null +++ b/src/add-ons/kernel/debugger/demangle/Jamfile @@ -0,0 +1,43 @@ +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 ] ; + + +rule ExtractObject +{ + SetupKernel $(2) ; + Depends $(1) : $(2) ; + Objects $(1) ; + + MakeLocateDebug $(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 ; + +KernelMergeObject demangle_module.o : + demangle.cpp + : + : +; + + + +KernelAddon demangle : + demangle.cpp + #demangle_module.o + cp-demangle.o + ; + +#LINKFLAGS on demangle = -lsupc++ ; + +} diff --git a/src/add-ons/kernel/debugger/demangle/demangle.cpp b/src/add-ons/kernel/debugger/demangle/demangle.cpp new file mode 100644 index 0000000000..b09c25b206 --- /dev/null +++ b/src/add-ons/kernel/debugger/demangle/demangle.cpp @@ -0,0 +1,194 @@ +/* + * Copyright 2008, François Revol, revol@free.fr + * Distributed under the terms of the MIT License. + */ +#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... + * instead we just return it a static buffer. + */ + +void *malloc(size_t len) +{ + if (len < DEMANGLE_BUFFER_SIZE) + return sDemangleBuffer; + return NULL; +} + + +void free(void *ptr) +{ +} + + +void *realloc(void * old_ptr, size_t new_size) +{ + return NULL; +} + + +/* doesn't work, va_list sux... */ +#if 0 +class DemangleDebugOutputFilter : public DebugOutputFilter { +public: + DemangleDebugOutputFilter(); + virtual ~DemangleDebugOutputFilter(); + void SetChain(DebugOutputFilter *chain); + virtual void PrintString(const char* string); + virtual void Print(const char* format, va_list args); +private: + DebugOutputFilter *fChained; +}; + + +DemangleDebugOutputFilter::DemangleDebugOutputFilter() +{ +} + + +DemangleDebugOutputFilter::~DemangleDebugOutputFilter() +{ +} + + +void +DemangleDebugOutputFilter::SetChain(DebugOutputFilter *chain) +{ + fChained = chain; +} + + +void +DemangleDebugOutputFilter::PrintString(const char* string) +{ + fChained->PrintString(string); +} + + +void +DemangleDebugOutputFilter::Print(const char* format, va_list args) +{ + int i; + const char *p = format; + while ((p = strchr(p, '%'))) { + if (p[1] == '%') { + p+=2; + continue; + } + p++; + while (*p && !isalpha(*p)) + p++; + switch (*p) { + case 's': + { + const char **ptr = &va_arg(args, char *); + //char *symbol = va_arg(args, char *); + char *symbol = *ptr; + char *demangled; + size_t length = DEMANGLE_BUFFER_SIZE; + int status; + + demangled = abi::__cxa_demangle(symbol, sDemangleBuffer, &length, &status); + if (status > 0) { + } + break; + } + case 'd': + case 'i': + { + int d; + d = va_arg(args, int); + break; + } + case 'L': + { + long long d; + d = va_arg(args, long long); + break; + } + case 'f': + { + float f; + f = va_arg(args, float); + break; + } + case '\0': + break; + default: + panic("unknown printf format\n"); + break; + } + i++; + } + fChained->Print(format, args); +} +#endif + +static const char *kdebug_demangle(const char *sym) +{ + char *demangled; + size_t length = DEMANGLE_BUFFER_SIZE; + int status; + + demangled = abi::__cxa_demangle(sym, sDemangleBuffer, &length, &status); + if (status == 0) + return demangled; + // something bad happened + 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 = { + { + "debugger/demangle/v1", + B_KEEP_LOADED, + &std_ops + }, + + NULL, + exit_debugger, + NULL, + NULL +}; + +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 04f2305b54..79de3059b7 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -98,6 +98,10 @@ lookup_symbol(struct thread* thread, addr_t address, addr_t *_baseAddress, } } + if (status == B_OK) { + *_symbolName = debug_demangle(*_symbolName); + } + return status; } diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 664ce55d09..a88b4e7c15 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -89,6 +89,8 @@ 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; + #define distance(a, b) ((a) < (b) ? (b) - (a) : (a) - (b)) @@ -1383,3 +1385,20 @@ dump_block(const char *buffer, int size, const char *prefix) dprintf("\n"); } } + + +extern void +debug_set_demangle_hook(const char *(*hook)(const char *)) +{ + sDemangleHook = hook; +} + + +extern const char * +debug_demangle(const char *sym) +{ + if (sDemangleHook) + return sDemangleHook(sym); + return sym; +} +