diff --git a/headers/private/kernel/elf.h b/headers/private/kernel/elf.h index 8694e3754a..6690b5e6a8 100644 --- a/headers/private/kernel/elf.h +++ b/headers/private/kernel/elf.h @@ -32,6 +32,7 @@ status_t elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, status_t elf_debug_lookup_user_symbol_address(struct team* team, addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch); +addr_t elf_debug_lookup_symbol(const char* searchName); struct elf_image_info* elf_get_kernel_image(); status_t elf_get_image_info_for_address(addr_t address, image_info* info); image_id elf_create_memory_image(const char* imageName, addr_t text, diff --git a/src/system/kernel/debug/debug_parser.cpp b/src/system/kernel/debug/debug_parser.cpp index 14c68b621e..eccbb8f724 100644 --- a/src/system/kernel/debug/debug_parser.cpp +++ b/src/system/kernel/debug/debug_parser.cpp @@ -36,7 +36,7 @@ dereference := "*" [ "{" expression "}" ] unary atom := variable | ( "(" expression ")" ) | ( "[" command "]" ) variable := identifier - identifier := ( "$" | "_" | "a" - "z" | "A" - "Z" ) + identifier := ( "$" | "@" | "_" | "a" - "z" | "A" - "Z" ) ( "_" | "a" - "z" | "A" - "Z" | "0" - "9" )* commandPipe := command ( "|" command )* command := identifier argument* @@ -251,7 +251,7 @@ public: fCurrentToken.value = strtoull(fCurrentToken.string, NULL, 0); } else if (isalpha(*fCurrentChar) || *fCurrentChar == '_' - || *fCurrentChar == '$') { + || *fCurrentChar == '$' || *fCurrentChar == '@') { // identifier const char* begin = fCurrentChar; fCurrentChar++; diff --git a/src/system/kernel/debug/debug_variables.cpp b/src/system/kernel/debug/debug_variables.cpp index b782f1a2ed..b774f41623 100644 --- a/src/system/kernel/debug/debug_variables.cpp +++ b/src/system/kernel/debug/debug_variables.cpp @@ -3,6 +3,7 @@ * Distributed under the terms of the MIT License. */ + #include "debug_variables.h" #include @@ -11,6 +12,7 @@ #include #include +#include #include @@ -18,6 +20,7 @@ static const int kVariableCount = 64; static const int kTemporaryVariableCount = 32; static const char kTemporaryVariablePrefix = '_'; static const char kArchSpecificVariablePrefix = '$'; +static const char kSymbolVariablePrefix = '@'; static const char* const kCommandReturnValueVariable = "_"; @@ -70,6 +73,13 @@ is_arch_specific_variable(const char* variableName) } +static inline bool +is_symbol_variable(const char* variableName) +{ + return variableName[0] == kSymbolVariablePrefix; +} + + static void dequeue_temporary_variable(TemporaryVariable* variable) { @@ -239,6 +249,9 @@ is_debug_variable_defined(const char* variableName) if (get_variable(variableName, false) != NULL) return true; + if (is_symbol_variable(variableName)) + return elf_debug_lookup_symbol(variableName + 1) != 0; + return is_arch_specific_variable(variableName) && arch_is_debug_variable_defined(variableName + 1); } @@ -274,6 +287,12 @@ get_debug_variable(const char* variableName, uint64 defaultValue) return value; } + if (is_symbol_variable(variableName)) { + addr_t value = elf_debug_lookup_symbol(variableName + 1); + if (value != 0) + return value; + } + return defaultValue; } diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 4c4b0f9028..fe95025582 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -1695,6 +1695,47 @@ elf_debug_lookup_user_symbol_address(struct team* team, addr_t address, } +/*! Looks up a symbol in all kernel images. Note, this function is thought to + be used in the kernel debugger, and therefore doesn't perform any locking. +*/ +addr_t +elf_debug_lookup_symbol(const char* searchName) +{ + struct elf_image_info *image = NULL; + struct hash_iterator iterator; + + hash_open(sImagesHash, &iterator); + while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) + != NULL) { + if (image->num_debug_symbols > 0) { + // search extended debug symbol table (contains static symbols) + for (uint32 i = 0; i < image->num_debug_symbols; i++) { + struct Elf32_Sym *symbol = &image->debug_symbols[i]; + const char *name = image->debug_string_table + symbol->st_name; + + if (symbol->st_value > 0 && !strcmp(name, searchName)) + return symbol->st_value + image->text_region.delta; + } + } else { + // search standard symbol lookup table + for (uint32 i = 0; i < HASHTABSIZE(image); i++) { + for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; + j = HASHCHAINS(image)[j]) { + struct Elf32_Sym *symbol = &image->syms[j]; + const char *name = SYMNAME(image, symbol); + + if (symbol->st_value > 0 && !strcmp(name, searchName)) + return symbol->st_value + image->text_region.delta; + } + } + } + } + hash_close(sImagesHash, &iterator, false); + + return 0; +} + + status_t elf_load_user_image(const char *path, struct team *team, int flags, addr_t *entry)