* Changed the way the demangle functionality works: instead of having a kernel
debugger add-on set a demangle hook, all modules under debugger/demangle/ are now considered demangle modules. * Added another function to the demangle module interface that gives you access to the arguments. * Implemented a demangling module for GCC2. * The older demangling module is now called "gcc3+", but doesn't support getting the arguments yet. * The "call" KDL command is now using demangling to automatically show you the arguments of a call from a stack crawl. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28018 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -66,6 +66,16 @@ struct debugger_module_info {
|
|||||||
// TODO: add hooks for tunnelling gdb ?
|
// 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];
|
extern int dbg_register_file[B_MAX_CPU_COUNT][14];
|
||||||
|
|
||||||
typedef struct debug_page_fault_info {
|
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(struct kernel_args *args);
|
||||||
extern status_t debug_init_post_vm(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 status_t debug_init_post_modules(struct kernel_args *args);
|
||||||
extern void debug_early_boot_message(const char *string);
|
extern void debug_early_boot_message(const char *string);
|
||||||
extern void debug_puts(const char *s, int32 length);
|
extern void debug_puts(const char *s, int32 length);
|
||||||
extern bool debug_debugger_running(void);
|
extern bool debug_debugger_running(void);
|
||||||
extern bool debug_screen_output_enabled(void);
|
extern bool debug_screen_output_enabled(void);
|
||||||
extern void debug_stop_screen_debug_output(void);
|
extern void debug_stop_screen_debug_output(void);
|
||||||
extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc,
|
extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc,
|
||||||
uint32 flags);
|
uint32 flags);
|
||||||
extern debug_page_fault_info* debug_get_page_fault_info();
|
extern debug_page_fault_info* debug_get_page_fault_info();
|
||||||
|
|
||||||
extern void kputs(const char *string);
|
extern void kputs(const char *string);
|
||||||
extern void kputs_unfiltered(const char *string);
|
extern void kputs_unfiltered(const char *string);
|
||||||
extern void kprintf_unfiltered(const char *format, ...)
|
extern void kprintf_unfiltered(const char *format, ...)
|
||||||
__attribute__ ((format (__printf__, 1, 2)));
|
__attribute__ ((format (__printf__, 1, 2)));
|
||||||
extern void dprintf_no_syslog(const char *format, ...)
|
extern void dprintf_no_syslog(const char *format, ...)
|
||||||
__attribute__ ((format (__printf__, 1, 2)));
|
__attribute__ ((format (__printf__, 1, 2)));
|
||||||
|
|
||||||
extern bool is_debug_variable_defined(const char* variableName);
|
extern bool is_debug_variable_defined(const char* variableName);
|
||||||
extern bool set_debug_variable(const char* variableName, uint64 value);
|
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);
|
const char* oldName, const char* description);
|
||||||
extern bool print_debugger_command_usage(const char* command);
|
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_symbol(const char* symbol, char* buffer,
|
||||||
extern const char *debug_demangle(const char *);
|
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_set_debugged_thread(struct thread* thread);
|
||||||
extern struct thread* debug_get_debugged_thread();
|
extern struct thread* debug_get_debugged_thread();
|
||||||
|
|||||||
@@ -1,43 +1,35 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel debugger demangle ;
|
SubDir HAIKU_TOP src add-ons kernel debugger demangle ;
|
||||||
|
|
||||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
|
||||||
|
|
||||||
UsePrivateHeaders kernel ;
|
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
|
MakeLocateDebug $(1) ;
|
||||||
{
|
}
|
||||||
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)"
|
||||||
|
}
|
||||||
|
|
||||||
actions ExtractObject
|
ExtractObject cp-demangle.o : $(TARGET_STATIC_LIBSUPC++) foo ;
|
||||||
{
|
|
||||||
#$(TARGET_AR) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ;
|
|
||||||
pwd
|
|
||||||
echo $(TARGET_AR) -x "$(2)" "$(1)"
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtractObject cp-demangle.o : $(TARGET_STATIC_LIBSUPC++) foo ;
|
KernelAddon <kdebug>gcc3+ :
|
||||||
|
gcc3+.cpp
|
||||||
KernelMergeObject demangle_module.o :
|
cp-demangle.o
|
||||||
demangle.cpp
|
|
||||||
:
|
|
||||||
:
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KernelAddon <kdebug>demangle :
|
|
||||||
demangle.cpp
|
|
||||||
#demangle_module.o
|
|
||||||
cp-demangle.o
|
|
||||||
;
|
;
|
||||||
|
|
||||||
#LINKFLAGS on <kdebug>demangle = -lsupc++ ;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# GCC2 solution
|
||||||
|
|
||||||
|
KernelAddon <kdebug>gcc2 :
|
||||||
|
gcc2.cpp
|
||||||
|
;
|
||||||
|
|||||||
@@ -0,0 +1,394 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected].
|
||||||
|
* This file may be used under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
+19
-39
@@ -2,12 +2,14 @@
|
|||||||
* Copyright 2008, François Revol, revol@free.fr
|
* Copyright 2008, François Revol, revol@free.fr
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <debug.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#define DEMANGLE_BUFFER_SIZE (16*1024)
|
#define DEMANGLE_BUFFER_SIZE (16*1024)
|
||||||
static char sDemangleBuffer[DEMANGLE_BUFFER_SIZE];
|
static char sDemangleBuffer[DEMANGLE_BUFFER_SIZE];
|
||||||
|
|
||||||
@@ -18,7 +20,8 @@ extern "C" void set_debug_demangle_hook(const char *(*demangle_hook)(const char
|
|||||||
* instead we just return it a static buffer.
|
* instead we just return it a static buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *malloc(size_t len)
|
void *
|
||||||
|
malloc(size_t len)
|
||||||
{
|
{
|
||||||
if (len < DEMANGLE_BUFFER_SIZE)
|
if (len < DEMANGLE_BUFFER_SIZE)
|
||||||
return sDemangleBuffer;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -134,7 +139,10 @@ DemangleDebugOutputFilter::Print(const char* format, va_list args)
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
char *demangled;
|
||||||
size_t length = DEMANGLE_BUFFER_SIZE;
|
size_t length = DEMANGLE_BUFFER_SIZE;
|
||||||
@@ -147,44 +155,16 @@ static const char *kdebug_demangle(const char *sym)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
exit_debugger()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static struct debugger_demangle_module_info sModuleInfo = {
|
||||||
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",
|
"debugger/demangle/gcc3+/v1",
|
||||||
B_KEEP_LOADED,
|
0,
|
||||||
&std_ops
|
NULL
|
||||||
},
|
},
|
||||||
|
|
||||||
|
demangle_symbol,
|
||||||
NULL,
|
NULL,
|
||||||
exit_debugger,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
@@ -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;
|
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,
|
status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
|
||||||
&exactMatch);
|
&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);
|
kprintf("%2ld %08lx (+%4ld) %08lx", callIndex, ebp, diff, eip);
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
if (symbol != NULL) {
|
if (name != NULL) {
|
||||||
kprintf(" <%s>:%s + 0x%04lx%s\n", image, symbol,
|
kprintf(" <%s>:%s + 0x%04lx%s\n", image, name,
|
||||||
eip - baseAddress, exactMatch ? "" : " (nearest)");
|
eip - baseAddress, exactMatch ? "" : " (nearest)");
|
||||||
} else {
|
} else {
|
||||||
kprintf(" <%s@%p>:unknown + 0x%04lx\n", image,
|
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
|
static void
|
||||||
print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
|
print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
|
||||||
int32 argCount)
|
int32 argCount)
|
||||||
@@ -444,6 +455,9 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
|
|||||||
addr_t baseAddress;
|
addr_t baseAddress;
|
||||||
bool exactMatch;
|
bool exactMatch;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
char buffer[64];
|
||||||
|
const char* name = NULL;
|
||||||
|
bool isObjectMethod;
|
||||||
|
|
||||||
status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
|
status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
|
||||||
&exactMatch);
|
&exactMatch);
|
||||||
@@ -452,8 +466,16 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
|
|||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
if (symbol != NULL) {
|
if (symbol != NULL) {
|
||||||
kprintf(" <%s>:%s%s", image, symbol,
|
if (exactMatch && argCount <= 0) {
|
||||||
exactMatch ? "" : " (nearest)");
|
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 {
|
} else {
|
||||||
kprintf(" <%s@%p>:unknown + 0x%04lx", image,
|
kprintf(" <%s@%p>:unknown + 0x%04lx", image,
|
||||||
(void *)baseAddress, eip - baseAddress);
|
(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);
|
int32 *arg = (int32 *)(nextEbp + 8);
|
||||||
kprintf("(");
|
|
||||||
|
|
||||||
for (int32 i = 0; i < argCount; i++) {
|
if (name != NULL) {
|
||||||
if (i > 0)
|
if (isObjectMethod) {
|
||||||
kprintf(", ");
|
const char* lastName = strrchr(name, ':') - 1;
|
||||||
kprintf("%#lx", *arg);
|
int namespaceLength = lastName - name;
|
||||||
if (*arg > -0x10000 && *arg < 0x10000)
|
|
||||||
kprintf(" (%ld)", *arg);
|
|
||||||
|
|
||||||
char name[8];
|
kprintf(" <%s> %.*s<%p>%s", image, namespaceLength, name,
|
||||||
snprintf(name, sizeof(name), "_arg%ld", i + 1);
|
*(uint32 **)arg, lastName);
|
||||||
set_debug_variable(name, *(uint32 *)arg);
|
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");
|
kprintf(")\n");
|
||||||
@@ -500,7 +616,8 @@ show_call(int argc, char **argv)
|
|||||||
"the specified thread.\n"
|
"the specified thread.\n"
|
||||||
" <thread id> - The ID of the thread for which to print the call.\n"
|
" <thread id> - The ID of the thread for which to print the call.\n"
|
||||||
" <call index> - The index of the call in the stack trace.\n"
|
" <call index> - The index of the call in the stack trace.\n"
|
||||||
" <arg count> - The number of call arguments to print.\n";
|
" <arg count> - 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) {
|
if (argc == 2 && strcmp(argv[1], "--help") == 0) {
|
||||||
kprintf(usage, argv[0]);
|
kprintf(usage, argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -512,8 +629,11 @@ show_call(int argc, char **argv)
|
|||||||
int32 argCount = 0;
|
int32 argCount = 0;
|
||||||
|
|
||||||
if (argc >= 2 && argv[argc - 1][0] == '-') {
|
if (argc >= 2 && argv[argc - 1][0] == '-') {
|
||||||
argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
|
if (argv[argc - 1][1] != 'c')
|
||||||
if (argCount < 0 || argCount > 16) {
|
argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
|
||||||
|
else
|
||||||
|
argCount = -1;
|
||||||
|
if (argCount < -1 || argCount > 16) {
|
||||||
kprintf("Invalid argument count \"%ld\".\n", argCount);
|
kprintf("Invalid argument count \"%ld\".\n", argCount);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ static int64 sMessageRepeatFirstTime = 0;
|
|||||||
static int64 sMessageRepeatLastTime = 0;
|
static int64 sMessageRepeatLastTime = 0;
|
||||||
static int32 sMessageRepeatCount = 0;
|
static int32 sMessageRepeatCount = 0;
|
||||||
|
|
||||||
static debugger_module_info *sDebuggerModules[8];
|
static debugger_module_info* sDebuggerModules[8];
|
||||||
static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules)
|
static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules)
|
||||||
/ sizeof(sDebuggerModules[0]);
|
/ sizeof(sDebuggerModules[0]);
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ 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;
|
static debugger_demangle_module_info* sDemangleModule;
|
||||||
|
|
||||||
static struct thread* sDebuggedThread;
|
static struct thread* sDebuggedThread;
|
||||||
|
|
||||||
@@ -1105,7 +1105,7 @@ debug_init_post_vm(kernel_args *args)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
debug_init_post_modules(struct kernel_args *args)
|
debug_init_post_modules(struct kernel_args* args)
|
||||||
{
|
{
|
||||||
void *cookie;
|
void *cookie;
|
||||||
|
|
||||||
@@ -1115,6 +1115,9 @@ debug_init_post_modules(struct kernel_args *args)
|
|||||||
syslog_init_post_threads();
|
syslog_init_post_threads();
|
||||||
|
|
||||||
// load kernel debugger addons
|
// load kernel debugger addons
|
||||||
|
|
||||||
|
static const char* kDemanglePrefix = "debugger/demangle/";
|
||||||
|
|
||||||
cookie = open_module_list("debugger");
|
cookie = open_module_list("debugger");
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
while (count < kMaxDebuggerModules) {
|
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)
|
if (read_next_module_name(cookie, name, &nameLength) != B_OK)
|
||||||
break;
|
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);
|
dprintf("kernel debugger extension \"%s\": loaded\n", name);
|
||||||
count++;
|
count++;
|
||||||
} else
|
} else
|
||||||
@@ -1273,9 +1283,10 @@ flush_pending_repeats(void)
|
|||||||
syslog_write(temp, length);
|
syslog_write(temp, length);
|
||||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||||
blue_screen_puts(temp);
|
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)
|
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts)
|
||||||
sDebuggerModules[i]->debugger_puts(temp, length);
|
sDebuggerModules[i]->debugger_puts(temp, length);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// if we only have one repeat just reprint the last buffer
|
// if we only have one repeat just reprint the last buffer
|
||||||
if (sSerialDebugEnabled)
|
if (sSerialDebugEnabled)
|
||||||
@@ -1284,9 +1295,12 @@ flush_pending_repeats(void)
|
|||||||
syslog_write(sLastOutputBuffer, strlen(sLastOutputBuffer));
|
syslog_write(sLastOutputBuffer, strlen(sLastOutputBuffer));
|
||||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||||
blue_screen_puts(sLastOutputBuffer);
|
blue_screen_puts(sLastOutputBuffer);
|
||||||
for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++)
|
for (i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) {
|
||||||
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts)
|
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) {
|
||||||
sDebuggerModules[i]->debugger_puts(sLastOutputBuffer, strlen(sLastOutputBuffer));
|
sDebuggerModules[i]->debugger_puts(sLastOutputBuffer,
|
||||||
|
strlen(sLastOutputBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sMessageRepeatFirstTime = 0;
|
sMessageRepeatFirstTime = 0;
|
||||||
@@ -1348,9 +1362,10 @@ dprintf_args(const char *format, va_list args, bool syslogOutput)
|
|||||||
syslog_write(sOutputBuffer, length);
|
syslog_write(sOutputBuffer, length);
|
||||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||||
blue_screen_puts(sOutputBuffer);
|
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)
|
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts)
|
||||||
sDebuggerModules[i]->debugger_puts(sOutputBuffer, length);
|
sDebuggerModules[i]->debugger_puts(sOutputBuffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(sLastOutputBuffer, sOutputBuffer, length);
|
memcpy(sLastOutputBuffer, sOutputBuffer, length);
|
||||||
sLastOutputBuffer[length] = 0;
|
sLastOutputBuffer[length] = 0;
|
||||||
@@ -1414,19 +1429,29 @@ kprintf_unfiltered(const char *format, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void
|
const char*
|
||||||
debug_set_demangle_hook(const char *(*hook)(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 *
|
status_t
|
||||||
debug_demangle(const char *sym)
|
debug_get_next_demangled_argument(uint32* _cookie, const char* symbol,
|
||||||
|
char* name, size_t nameSize, int32* _type, size_t* _argumentLength)
|
||||||
{
|
{
|
||||||
if (sDemangleHook)
|
if (sDemangleModule != NULL && sDemangleModule->get_next_argument != NULL) {
|
||||||
return sDemangleHook(sym);
|
return sDemangleModule->get_next_argument(_cookie, symbol, name,
|
||||||
return sym;
|
nameSize, _type, _argumentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user