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
+4
View File
@@ -34,6 +34,10 @@ status_t elf_debug_lookup_user_symbol_address(struct team* team, addr_t address,
status_t elf_get_image_info_for_address(addr_t address, image_info* info);
status_t elf_init(struct kernel_args *args);
status_t _user_read_kernel_image_symbols(image_id id,
struct Elf32_Sym* symbolTable, int32* _symbolCount,
char* stringTable, size_t* _stringTableSize, addr_t* _imageDelta);
#ifdef __cplusplus
}
#endif
+5
View File
@@ -20,6 +20,7 @@ extern "C" {
#endif
struct dirent;
struct Elf32_Sym;
struct fd_info;
struct fd_set;
struct fs_info;
@@ -188,6 +189,10 @@ extern void _kern_image_relocated(image_id id);
extern void _kern_loading_app_failed(status_t error);
extern status_t _kern_get_image_info(image_id id, image_info *info, size_t size);
extern status_t _kern_get_next_image_info(team_id team, int32 *cookie, image_info *info, size_t size);
extern status_t _kern_read_kernel_image_symbols(image_id id,
struct Elf32_Sym* symbolTable, int32* _symbolCount,
char* stringTable, size_t* _stringTableSize,
addr_t* _imageDelta);
// VFS functions
extern dev_t _kern_mount(const char *path, const char *device,
+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;
}