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:
@@ -111,6 +111,9 @@ extern bool print_debugger_command_usage(const char* command);
|
|||||||
|
|
||||||
extern void _user_debug_output(const char *userString);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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 auto_stack_trace ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel debugger bochs ;
|
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 hangman ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
||||||
|
|||||||
@@ -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++ ;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, François Revol, [email protected]
|
||||||
|
* 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
|
||||||
|
};
|
||||||
|
|
||||||
@@ -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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules)
|
|||||||
static char sLineBuffer[HISTORY_SIZE][LINE_BUFFER_SIZE] = { "", };
|
static char sLineBuffer[HISTORY_SIZE][LINE_BUFFER_SIZE] = { "", };
|
||||||
static int32 sCurrentLine = 0;
|
static int32 sCurrentLine = 0;
|
||||||
|
|
||||||
|
static const char *(*sDemangleHook)(const char *) = NULL;
|
||||||
|
|
||||||
#define distance(a, b) ((a) < (b) ? (b) - (a) : (a) - (b))
|
#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");
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user