From fec47a570239d9505c56b680fb3c2564c9988c14 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 24 Sep 2008 14:40:24 +0000 Subject: [PATCH] Added functions elf_create_memory_image() and elf_add_memory_image_symbol(). The former creates and registers a new image that has not been loaded from a file. The latter adds a symbol to its symbol table. This is mainly a debug feature, allowing to name code or data in memory regions that aren't associated with loaded ELF objects. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27721 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/elf.h | 5 ++ src/system/kernel/elf.cpp | 120 +++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/headers/private/kernel/elf.h b/headers/private/kernel/elf.h index 9adf6cbbe1..da11badbd1 100644 --- a/headers/private/kernel/elf.h +++ b/headers/private/kernel/elf.h @@ -12,6 +12,7 @@ #include #include + struct kernel_args; @@ -32,6 +33,10 @@ 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); 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, + size_t textSize, addr_t data, size_t dataSize); +status_t elf_add_memory_image_symbol(image_id id, const char* name, + addr_t address, size_t size, int32 type); status_t elf_init(struct kernel_args *args); status_t _user_read_kernel_image_symbols(image_id id, diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index e0e7ba6229..552d00054a 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -1872,6 +1873,125 @@ elf_get_image_info_for_address(addr_t address, image_info* info) } +image_id +elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, + addr_t data, size_t dataSize) +{ + // allocate the image + elf_image_info* image = create_image_struct(); + if (image == NULL) + return B_NO_MEMORY; + MemoryDeleter imageDeleter(image); + + // allocate symbol and string tables -- we allocate an empty symbol table, + // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol + // table, which we don't have. + Elf32_Sym* symbolTable = (Elf32_Sym*)malloc(0); + char* stringTable = (char*)malloc(1); + MemoryDeleter symbolTableDeleter(symbolTable); + MemoryDeleter stringTableDeleter(stringTable); + if (symbolTable == NULL || stringTable == NULL) + return B_NO_MEMORY; + + // the string table always contains the empty string + stringTable[0] = '\0'; + + image->debug_symbols = symbolTable; + image->num_debug_symbols = 0; + image->debug_string_table = stringTable; + + // dup image name + image->name = strdup(imageName); + if (image->name == NULL) + return B_NO_MEMORY; + + // data and text region + image->text_region.id = -1; + image->text_region.start = text; + image->text_region.size = textSize; + image->text_region.delta = 0; + + image->data_region.id = -1; + image->data_region.start = data; + image->data_region.size = dataSize; + image->data_region.delta = 0; + + mutex_lock(&sImageMutex); + register_elf_image(image); + image_id imageID = image->id; + mutex_unlock(&sImageMutex); + + // keep the allocated memory + imageDeleter.Detach(); + symbolTableDeleter.Detach(); + stringTableDeleter.Detach(); + + return imageID; +} + + +status_t +elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, + size_t size, int32 type) +{ + MutexLocker _(sImageMutex); + + // get the image + struct elf_image_info* image = find_image(id); + if (image == NULL) + return B_ENTRY_NOT_FOUND; + + // get the current string table size + size_t stringTableSize = 1; + if (image->num_debug_symbols > 0) { + for (uint32 i = image->num_debug_symbols - 1; i >= 0; i--) { + int32 nameIndex = image->debug_symbols[i].st_name; + if (nameIndex != 0) { + stringTableSize = nameIndex + + strlen(image->debug_string_table + nameIndex) + 1; + break; + } + } + } + + // enter the name in the string table + char* stringTable = (char*)image->debug_string_table; + size_t stringIndex = 0; + if (name != NULL) { + size_t nameSize = strlen(name) + 1; + stringIndex = stringTableSize; + stringTableSize += nameSize; + stringTable = (char*)realloc((char*)image->debug_string_table, + stringTableSize); + if (stringTable == NULL) + return B_NO_MEMORY; + image->debug_string_table = stringTable; + memcpy(stringTable + stringIndex, name, nameSize); + } + + // resize the symbol table + int32 symbolCount = image->num_debug_symbols + 1; + Elf32_Sym* symbolTable = (Elf32_Sym*)realloc( + (Elf32_Sym*)image->debug_symbols, sizeof(Elf32_Sym) * symbolCount); + if (symbolTable == NULL) + return B_NO_MEMORY; + image->debug_symbols = symbolTable; + + // enter the symbol + Elf32_Sym& symbol = symbolTable[symbolCount - 1]; + uint32 symbolType = type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC; + symbol.st_name = stringIndex; + symbol.st_value = address; + symbol.st_size = size; + symbol.st_info = ELF32_ST_INFO(STB_GLOBAL, symbolType); + symbol.st_other = 0; + symbol.st_shndx = 0; + image->num_debug_symbols++; + + return B_OK; +} + + status_t elf_init(kernel_args *args) {