Added syscall _kern_read_kernel_image_symbols() for reading a kernel

image's symbol and string tables.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27687 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-22 11:13:38 +00:00
parent 8c8b846226
commit 8839d592bc
3 changed files with 110 additions and 0 deletions
+101
View File
@@ -1878,3 +1878,104 @@ elf_init(kernel_args *args)
return B_OK;
}
// #pragma mark -
/*! Reads the symbol and string table for the kernel image with the given ID.
\a _symbolCount and \a _stringTableSize are both in- and output parameters.
When called they call the size of the buffers given by \a symbolTable and
\a stringTable respectively. When the function returns successfully, they
will contain the actual sizes (which can be greater than the original ones).
The function will copy as much as possible into the buffers. For only
getting the required buffer sizes, it can be invoked with \c NULL buffers.
On success \a _imageDelta will contain the offset to be added to the symbol
values in the table to get the actual symbol addresses.
*/
status_t
_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
addr_t* _imageDelta)
{
// check params
if (_symbolCount == NULL || _stringTableSize == NULL)
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
|| _imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta)
|| symbolTable != NULL && !IS_USER_ADDRESS(symbolTable)
|| stringTable != NULL && !IS_USER_ADDRESS(stringTable)) {
return B_BAD_ADDRESS;
}
// get buffer sizes
int32 maxSymbolCount;
size_t maxStringTableSize;
if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
!= B_OK
|| user_memcpy(&maxStringTableSize, _stringTableSize,
sizeof(maxStringTableSize)) != B_OK) {
return B_BAD_ADDRESS;
}
// find the image
MutexLocker _(sImageMutex);
struct elf_image_info* image = find_image(id);
if (image == NULL)
return B_ENTRY_NOT_FOUND;
// get the tables and infos
addr_t imageDelta = image->text_region.delta;
const Elf32_Sym* symbols;
int32 symbolCount;
const char* strings;
if (image->debug_symbols != NULL) {
symbols = image->debug_symbols;
symbolCount = image->num_debug_symbols;
strings = image->debug_string_table;
} else {
symbols = image->syms;
symbolCount = image->symhash[1];
strings = image->strtab;
}
// The string table size isn't stored in the elf_image_info structure. Find
// out by iterating through all symbols.
size_t stringTableSize = 0;
for (int32 i = 0; i < symbolCount; i++) {
size_t index = symbols[i].st_name;
if (index > stringTableSize)
stringTableSize = index;
}
stringTableSize += strlen(strings + stringTableSize) + 1;
// add size of the last string
// copy symbol table
int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
if (symbolTable != NULL && symbolsToCopy > 0) {
if (user_memcpy(symbolTable, symbols, sizeof(Elf32_Sym) * symbolsToCopy)
!= B_OK) {
return B_BAD_ADDRESS;
}
}
// copy string table
size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
if (stringTable != NULL && stringsToCopy > 0) {
if (user_memcpy(stringTable, strings, stringsToCopy)
!= B_OK) {
return B_BAD_ADDRESS;
}
}
// copy sizes
if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
|| user_memcpy(_stringTableSize, &stringTableSize,
sizeof(stringTableSize)) != B_OK
|| _imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
sizeof(imageDelta)) != B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}