btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / debug / debug_variables.cpp
blob92ae27c82012c2059f451d6e3e0558dc84478b28
1 /*
2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de
3 * Distributed under the terms of the MIT License.
4 */
7 #include "debug_variables.h"
9 #include <string.h>
11 #include <KernelExport.h>
13 #include <arch/debug.h>
14 #include <debug.h>
15 #include <elf.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 = "_";
27 struct Variable {
28 char name[MAX_DEBUG_VARIABLE_NAME_LEN];
29 uint64 value;
31 inline bool IsUsed() const
33 return name[0] != '\0';
36 void Init(const char* variableName)
38 strlcpy(name, variableName, sizeof(name));
41 void Uninit()
43 name[0] = '\0';
46 inline bool HasName(const char* variableName) const
48 return strncmp(name, variableName, sizeof(name)) == 0;
52 struct TemporaryVariable : Variable,
53 DoublyLinkedListLinkImpl<TemporaryVariable> {
54 bool queued;
57 static Variable sVariables[kVariableCount];
58 static TemporaryVariable sTemporaryVariables[kTemporaryVariableCount];
60 static DoublyLinkedList<TemporaryVariable> sTemporaryVariablesLRUQueue;
63 static inline bool
64 is_temporary_variable(const char* variableName)
66 return variableName[0] == kTemporaryVariablePrefix;
70 static inline bool
71 is_arch_specific_variable(const char* variableName)
73 return variableName[0] == kArchSpecificVariablePrefix;
77 static inline bool
78 is_symbol_variable(const char* variableName)
80 return variableName[0] == kSymbolVariablePrefix;
84 static void
85 dequeue_temporary_variable(TemporaryVariable* variable)
87 // dequeue if queued
88 if (variable->queued) {
89 sTemporaryVariablesLRUQueue.Remove(variable);
90 variable->queued = false;
95 static void
96 unset_variable(Variable* variable)
98 if (is_temporary_variable(variable->name))
99 dequeue_temporary_variable(static_cast<TemporaryVariable*>(variable));
101 variable->Uninit();
105 static void
106 touch_variable(Variable* _variable)
108 if (!is_temporary_variable(_variable->name))
109 return;
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;
120 static Variable*
121 free_temporary_variable_slot()
123 TemporaryVariable* variable = sTemporaryVariablesLRUQueue.RemoveHead();
124 if (variable) {
125 variable->queued = false;
126 variable->Uninit();
129 return variable;
133 static Variable*
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)
147 freeSlot = variable;
148 } else if (variable->HasName(variableName))
149 return variable;
152 if (create && freeSlot == NULL)
153 freeSlot = free_temporary_variable_slot();
154 } else {
155 // persistent variable
156 for (int i = 0; i < kVariableCount; i++) {
157 Variable* variable = sVariables + i;
159 if (!variable->IsUsed()) {
160 if (freeSlot == NULL)
161 freeSlot = variable;
162 } else if (variable->HasName(variableName))
163 return variable;
168 if (create && freeSlot != NULL) {
169 freeSlot->Init(variableName);
170 return freeSlot;
173 return NULL;
177 // #pragma mark - debugger commands
180 static int
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) {
186 kprintf(usage);
187 return 0;
190 const char* variable = argv[1];
192 if (!unset_debug_variable(variable))
193 kprintf("Did not find variable %s.\n", variable);
195 return 0;
199 static int
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]);
206 return 0;
209 unset_all_debug_variables();
211 return 0;
215 static int
216 cmd_variables(int argc, char **argv)
218 static const char* usage = "usage: vars\n"
219 "Unsets the given variable, if it exists.\n";
220 if (argc != 1) {
221 kprintf(usage);
222 return 0;
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);
243 return 0;
247 // #pragma mark - kernel public functions
250 bool
251 is_debug_variable_defined(const char* variableName)
253 if (get_variable(variableName, false) != NULL)
254 return true;
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);
264 bool
265 set_debug_variable(const char* variableName, uint64 value)
267 if (is_symbol_variable(variableName))
268 return false;
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);
276 return true;
279 return false;
283 uint64
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;
291 uint64 value;
292 if (is_arch_specific_variable(variableName)
293 && arch_get_debug_variable(variableName + 1, &value) == B_OK) {
294 return value;
297 if (is_symbol_variable(variableName)) {
298 addr_t value = elf_debug_lookup_symbol(variableName + 1);
299 if (value != 0)
300 return value;
303 return defaultValue;
307 bool
308 unset_debug_variable(const char* variableName)
310 if (Variable* variable = get_variable(variableName, false)) {
311 unset_variable(variable);
312 return true;
315 return false;
319 void
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);
338 void
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");