2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de
3 * Distributed under the terms of the MIT License.
7 #include "debug_variables.h"
11 #include <KernelExport.h>
13 #include <arch/debug.h>
16 #include <util/DoublyLinkedList.h>
19 static const int kVariableCount
= 64;
20 static const int kTemporaryVariableCount
= 32;
21 static const char kTemporaryVariablePrefix
= '_';
22 static const char kArchSpecificVariablePrefix
= '$';
23 static const char kSymbolVariablePrefix
= '@';
24 static const char* const kCommandReturnValueVariable
= "_";
28 char name
[MAX_DEBUG_VARIABLE_NAME_LEN
];
31 inline bool IsUsed() const
33 return name
[0] != '\0';
36 void Init(const char* variableName
)
38 strlcpy(name
, variableName
, sizeof(name
));
46 inline bool HasName(const char* variableName
) const
48 return strncmp(name
, variableName
, sizeof(name
)) == 0;
52 struct TemporaryVariable
: Variable
,
53 DoublyLinkedListLinkImpl
<TemporaryVariable
> {
57 static Variable sVariables
[kVariableCount
];
58 static TemporaryVariable sTemporaryVariables
[kTemporaryVariableCount
];
60 static DoublyLinkedList
<TemporaryVariable
> sTemporaryVariablesLRUQueue
;
64 is_temporary_variable(const char* variableName
)
66 return variableName
[0] == kTemporaryVariablePrefix
;
71 is_arch_specific_variable(const char* variableName
)
73 return variableName
[0] == kArchSpecificVariablePrefix
;
78 is_symbol_variable(const char* variableName
)
80 return variableName
[0] == kSymbolVariablePrefix
;
85 dequeue_temporary_variable(TemporaryVariable
* variable
)
88 if (variable
->queued
) {
89 sTemporaryVariablesLRUQueue
.Remove(variable
);
90 variable
->queued
= false;
96 unset_variable(Variable
* variable
)
98 if (is_temporary_variable(variable
->name
))
99 dequeue_temporary_variable(static_cast<TemporaryVariable
*>(variable
));
106 touch_variable(Variable
* _variable
)
108 if (!is_temporary_variable(_variable
->name
))
111 TemporaryVariable
* variable
= static_cast<TemporaryVariable
*>(_variable
);
113 // move to the end of the queue
114 dequeue_temporary_variable(variable
);
115 sTemporaryVariablesLRUQueue
.Add(variable
);
116 variable
->queued
= true;
121 free_temporary_variable_slot()
123 TemporaryVariable
* variable
= sTemporaryVariablesLRUQueue
.RemoveHead();
125 variable
->queued
= false;
134 get_variable(const char* variableName
, bool create
)
136 // find the variable in the respective array and a free slot, we can
137 // use, if it doesn't exist yet
138 Variable
* freeSlot
= NULL
;
140 if (is_temporary_variable(variableName
)) {
141 // temporary variable
142 for (int i
= 0; i
< kTemporaryVariableCount
; i
++) {
143 TemporaryVariable
* variable
= sTemporaryVariables
+ i
;
145 if (!variable
->IsUsed()) {
146 if (freeSlot
== NULL
)
148 } else if (variable
->HasName(variableName
))
152 if (create
&& freeSlot
== NULL
)
153 freeSlot
= free_temporary_variable_slot();
155 // persistent variable
156 for (int i
= 0; i
< kVariableCount
; i
++) {
157 Variable
* variable
= sVariables
+ i
;
159 if (!variable
->IsUsed()) {
160 if (freeSlot
== NULL
)
162 } else if (variable
->HasName(variableName
))
168 if (create
&& freeSlot
!= NULL
) {
169 freeSlot
->Init(variableName
);
177 // #pragma mark - debugger commands
181 cmd_unset_variable(int argc
, char **argv
)
183 static const char* usage
= "usage: unset <variable>\n"
184 "Unsets the given variable, if it exists.\n";
185 if (argc
!= 2 || strcmp(argv
[1], "--help") == 0) {
190 const char* variable
= argv
[1];
192 if (!unset_debug_variable(variable
))
193 kprintf("Did not find variable %s.\n", variable
);
200 cmd_unset_all_variables(int argc
, char **argv
)
202 static const char* usage
= "usage: %s\n"
203 "Unsets all variables.\n";
204 if (argc
== 2 && strcmp(argv
[1], "--help") == 0) {
205 kprintf(usage
, argv
[0]);
209 unset_all_debug_variables();
216 cmd_variables(int argc
, char **argv
)
218 static const char* usage
= "usage: vars\n"
219 "Unsets the given variable, if it exists.\n";
225 // persistent variables
226 for (int i
= 0; i
< kVariableCount
; i
++) {
227 Variable
& variable
= sVariables
[i
];
228 if (variable
.IsUsed()) {
229 kprintf("%16s: %" B_PRIu64
" (0x%" B_PRIx64
")\n", variable
.name
,
230 variable
.value
, variable
.value
);
234 // temporary variables
235 for (int i
= 0; i
< kTemporaryVariableCount
; i
++) {
236 Variable
& variable
= sTemporaryVariables
[i
];
237 if (variable
.IsUsed()) {
238 kprintf("%16s: %" B_PRIu64
" (0x%" B_PRIx64
")\n", variable
.name
,
239 variable
.value
, variable
.value
);
247 // #pragma mark - kernel public functions
251 is_debug_variable_defined(const char* variableName
)
253 if (get_variable(variableName
, false) != NULL
)
256 if (is_symbol_variable(variableName
))
257 return elf_debug_lookup_symbol(variableName
+ 1) != 0;
259 return is_arch_specific_variable(variableName
)
260 && arch_is_debug_variable_defined(variableName
+ 1);
265 set_debug_variable(const char* variableName
, uint64 value
)
267 if (is_symbol_variable(variableName
))
270 if (is_arch_specific_variable(variableName
))
271 return arch_set_debug_variable(variableName
+ 1, value
) == B_OK
;
273 if (Variable
* variable
= get_variable(variableName
, true)) {
274 variable
->value
= value
;
275 touch_variable(variable
);
284 get_debug_variable(const char* variableName
, uint64 defaultValue
)
286 if (Variable
* variable
= get_variable(variableName
, false)) {
287 touch_variable(variable
);
288 return variable
->value
;
292 if (is_arch_specific_variable(variableName
)
293 && arch_get_debug_variable(variableName
+ 1, &value
) == B_OK
) {
297 if (is_symbol_variable(variableName
)) {
298 addr_t value
= elf_debug_lookup_symbol(variableName
+ 1);
308 unset_debug_variable(const char* variableName
)
310 if (Variable
* variable
= get_variable(variableName
, false)) {
311 unset_variable(variable
);
320 unset_all_debug_variables()
322 // persistent variables
323 for (int i
= 0; i
< kVariableCount
; i
++) {
324 Variable
& variable
= sVariables
[i
];
325 if (variable
.IsUsed())
326 unset_variable(&variable
);
329 // temporary variables
330 for (int i
= 0; i
< kTemporaryVariableCount
; i
++) {
331 Variable
& variable
= sTemporaryVariables
[i
];
332 if (variable
.IsUsed())
333 unset_variable(&variable
);
339 debug_variables_init()
341 add_debugger_command("unset", &cmd_unset_variable
,
342 "Unsets the given variable");
343 add_debugger_command("unset_all", &cmd_unset_all_variables
,
344 "Unsets all variables");
345 add_debugger_command("vars", &cmd_variables
,
346 "Lists all defined variables with their values");