A module that hooks into the debugger to provide it with a demangle() so at least when using C++ in the kernel stack crawls are meaningful.

It does its job by using part of libsupc++, with fake malloc and friends to make sure it won't double fault.
Works here, but cp-demangle must be extracted by hand from the lib, can't get the rule to work as I want, Ingo ?
Maybe using it directly without malloc hack would be ok with 16KB buffer, but I'm not sure of that.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2008-07-23 16:08:16 +00:00
parent 4e99b4683e
commit 8881176ff3
6 changed files with 264 additions and 0 deletions

View File

@ -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

View File

@ -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 ;

View File

@ -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 <kdebug>demangle :
demangle.cpp
#demangle_module.o
cp-demangle.o
;
#LINKFLAGS on <kdebug>demangle = -lsupc++ ;
}

View File

@ -0,0 +1,194 @@
/*
* Copyright 2008, François Revol, revol@free.fr
* Distributed under the terms of the MIT License.
*/
#include <ctype.h>
#include <cxxabi.h>
#include <debug.h>
#include <malloc.h>
#include <string.h>
#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
};

View File

@ -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;
}

View File

@ -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;
}