xref: /haiku/src/add-ons/kernel/debugger/demangle/demangle.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
1 /*
2  * Copyright 2008, François Revol, revol@free.fr
3  * Distributed under the terms of the MIT License.
4  */
5 #include <ctype.h>
6 #include <cxxabi.h>
7 #include <debug.h>
8 #include <malloc.h>
9 #include <string.h>
10 
11 #define DEMANGLE_BUFFER_SIZE (16*1024)
12 static char sDemangleBuffer[DEMANGLE_BUFFER_SIZE];
13 
14 extern "C" void set_debug_demangle_hook(const char *(*demangle_hook)(const char *));
15 
16 /* gcc's __cxa_demangle calls malloc and friends...
17  * we don't want to let it call the real one from inside the kernel debugger...
18  * instead we just return it a static buffer.
19  */
20 
21 void *malloc(size_t len)
22 {
23 	if (len < DEMANGLE_BUFFER_SIZE)
24 		return sDemangleBuffer;
25 	return NULL;
26 }
27 
28 
29 void free(void *ptr)
30 {
31 }
32 
33 
34 void *realloc(void * old_ptr, size_t new_size)
35 {
36 	return NULL;
37 }
38 
39 
40 /* doesn't work, va_list sux... */
41 #if 0
42 class DemangleDebugOutputFilter : public DebugOutputFilter {
43 public:
44         DemangleDebugOutputFilter();
45 	virtual ~DemangleDebugOutputFilter();
46         void SetChain(DebugOutputFilter *chain);
47 	virtual void PrintString(const char* string);
48 	virtual void Print(const char* format, va_list args);
49 private:
50 	DebugOutputFilter *fChained;
51 };
52 
53 
54 DemangleDebugOutputFilter::DemangleDebugOutputFilter()
55 {
56 }
57 
58 
59 DemangleDebugOutputFilter::~DemangleDebugOutputFilter()
60 {
61 }
62 
63 
64 void
65 DemangleDebugOutputFilter::SetChain(DebugOutputFilter *chain)
66 {
67 	fChained = chain;
68 }
69 
70 
71 void
72 DemangleDebugOutputFilter::PrintString(const char* string)
73 {
74 	fChained->PrintString(string);
75 }
76 
77 
78 void
79 DemangleDebugOutputFilter::Print(const char* format, va_list args)
80 {
81 	int i;
82 	const char *p = format;
83 	while ((p = strchr(p, '%'))) {
84 		if (p[1] == '%') {
85 			p+=2;
86 			continue;
87 		}
88 		p++;
89 		while (*p && !isalpha(*p))
90 			p++;
91 		switch (*p) {
92 			case 's':
93 			{
94 				const char **ptr = &va_arg(args, char *);
95 				//char *symbol = va_arg(args, char *);
96 				char *symbol = *ptr;
97 				char *demangled;
98 				size_t length = DEMANGLE_BUFFER_SIZE;
99 				int status;
100 
101 				demangled = abi::__cxa_demangle(symbol, sDemangleBuffer, &length, &status);
102 				if (status > 0)	{
103 				}
104 				break;
105 			}
106 			case 'd':
107 			case 'i':
108 			{
109 				int d;
110 				d = va_arg(args, int);
111 				break;
112 			}
113 			case 'L':
114 			{
115 				long long d;
116 				d = va_arg(args, long long);
117 				break;
118 			}
119 			case 'f':
120 			{
121 				float f;
122 				f = va_arg(args, float);
123 				break;
124 			}
125 			case '\0':
126 				break;
127 			default:
128 				panic("unknown printf format\n");
129 				break;
130 		}
131 		i++;
132 	}
133 	fChained->Print(format, args);
134 }
135 #endif
136 
137 static const char *kdebug_demangle(const char *sym)
138 {
139 	char *demangled;
140 	size_t length = DEMANGLE_BUFFER_SIZE;
141 	int status;
142 
143 	demangled = abi::__cxa_demangle(sym, sDemangleBuffer, &length, &status);
144 	if (status == 0)
145 		return demangled;
146 	// something bad happened
147 	return sym;
148 }
149 
150 static void
151 exit_debugger()
152 {
153 }
154 
155 
156 static status_t
157 std_ops(int32 op, ...)
158 {
159 	if (op == B_MODULE_INIT) {
160 #if 0
161 		DebugOutputFilter *old;
162 		DemangleDebugOutputFilter *filter = new(std::nothrow) DemangleDebugOutputFilter;
163 		old = set_debug_output_filter(filter);
164 		filter->SetChain(old);
165 #endif
166 		debug_set_demangle_hook(kdebug_demangle);
167 
168 		return B_OK;
169 	} else if (op == B_MODULE_UNINIT) {
170 		return B_OK;
171 	}
172 
173 	return B_BAD_VALUE;
174 }
175 
176 
177 static struct debugger_module_info sModuleInfo = {
178 	{
179 		"debugger/demangle/v1",
180 		B_KEEP_LOADED,
181 		&std_ops
182 	},
183 
184 	NULL,
185 	exit_debugger,
186 	NULL,
187 	NULL
188 };
189 
190 module_info *modules[] = {
191 	(module_info *)&sModuleInfo,
192 	NULL
193 };
194 
195