kernel/elf: Use extended_image_info instead of reading runtime_loader structures.

This solves some TODOs and allows image_debug_lookup_user_symbol_address
to be dropped entirely. It should also fix reading symbols from binaries
that have multiple TEXT regions, and most functions are not in the first.
This commit is contained in:
Augustin Cavalier 2025-01-14 15:23:34 -05:00
parent 802fb5b90f
commit 9792c51694
9 changed files with 34 additions and 111 deletions

View File

@ -56,9 +56,6 @@ struct image* image_iterate_through_images(image_iterator_callback callback,
struct image* image_iterate_through_team_images(team_id teamID, struct image* image_iterate_through_team_images(team_id teamID,
image_iterator_callback callback, void* cookie); image_iterator_callback callback, void* cookie);
extern status_t image_debug_lookup_user_symbol_address(Team *team,
addr_t address, addr_t *_baseAddress, const char **_symbolName,
const char **_imageName, bool *_exactMatch);
extern status_t image_init(void); extern status_t image_init(void);
// user-space exported calls // user-space exported calls

View File

@ -78,15 +78,9 @@ lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
status = elf_debug_lookup_symbol_address(address, _baseAddress, status = elf_debug_lookup_symbol_address(address, _baseAddress,
_symbolName, _imageName, _exactMatch); _symbolName, _imageName, _exactMatch);
} else if (thread != NULL && thread->team != NULL) { } else if (thread != NULL && thread->team != NULL) {
// try a lookup using the userland runtime loader structures // try to locate the image in the images loaded into user space
status = elf_debug_lookup_user_symbol_address(thread->team, address, status = elf_debug_lookup_user_symbol_address(thread->team, address,
_baseAddress, _symbolName, _imageName, _exactMatch); _baseAddress, _symbolName, _imageName, _exactMatch);
if (status != B_OK) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team,
address, _baseAddress, _symbolName, _imageName, _exactMatch);
}
} }
return status; return status;

View File

@ -70,15 +70,9 @@ lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
status = elf_debug_lookup_symbol_address(address, _baseAddress, status = elf_debug_lookup_symbol_address(address, _baseAddress,
_symbolName, _imageName, _exactMatch); _symbolName, _imageName, _exactMatch);
} else if (thread != NULL && thread->team != NULL) { } else if (thread != NULL && thread->team != NULL) {
// try a lookup using the userland runtime loader structures // try to locate the image in the images loaded into user space
status = elf_debug_lookup_user_symbol_address(thread->team, address, status = elf_debug_lookup_user_symbol_address(thread->team, address,
_baseAddress, _symbolName, _imageName, _exactMatch); _baseAddress, _symbolName, _imageName, _exactMatch);
if (status != B_OK) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team,
address, _baseAddress, _symbolName, _imageName, _exactMatch);
}
} }
return status; return status;

View File

@ -96,7 +96,7 @@ print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
&image, &exactMatch); &image, &exactMatch);
if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) { if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) {
// try to locate the image in the images loaded into user space // try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team, ip, status = elf_debug_lookup_user_symbol_address(thread->team, ip,
&baseAddress, &symbol, &image, &exactMatch); &baseAddress, &symbol, &image, &exactMatch);
} }
if (status == B_OK) { if (status == B_OK) {

View File

@ -95,7 +95,7 @@ print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
&image, &exactMatch); &image, &exactMatch);
if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) { if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) {
// try to locate the image in the images loaded into user space // try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team, ip, status = elf_debug_lookup_user_symbol_address(thread->team, ip,
&baseAddress, &symbol, &image, &exactMatch); &baseAddress, &symbol, &image, &exactMatch);
} }
if (status == B_OK) { if (status == B_OK) {

View File

@ -143,15 +143,9 @@ lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
status = elf_debug_lookup_symbol_address(address, _baseAddress, status = elf_debug_lookup_symbol_address(address, _baseAddress,
_symbolName, _imageName, _exactMatch); _symbolName, _imageName, _exactMatch);
} else if (thread != NULL && thread->team != NULL) { } else if (thread != NULL && thread->team != NULL) {
// try a lookup using the userland runtime loader structures // try to locate the image in the images loaded into user space
status = elf_debug_lookup_user_symbol_address(thread->team, address, status = elf_debug_lookup_user_symbol_address(thread->team, address,
_baseAddress, _symbolName, _imageName, _exactMatch); _baseAddress, _symbolName, _imageName, _exactMatch);
if (status != B_OK) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team,
address, _baseAddress, _symbolName, _imageName, _exactMatch);
}
} }
return status; return status;

View File

@ -116,12 +116,6 @@ lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
// try a lookup using the userland runtime loader structures // try a lookup using the userland runtime loader structures
status = elf_debug_lookup_user_symbol_address(thread->team, address, status = elf_debug_lookup_user_symbol_address(thread->team, address,
_baseAddress, _symbolName, _imageName, _exactMatch); _baseAddress, _symbolName, _imageName, _exactMatch);
if (status != B_OK) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team,
address, _baseAddress, _symbolName, _imageName, _exactMatch);
}
} }
return status; return status;

View File

@ -1357,22 +1357,6 @@ public:
status_t Init(Team* team) status_t Init(Team* team)
{ {
// find the runtime loader debug area
VMArea* area;
for (VMAddressSpace::AreaIterator it
= team->address_space->GetAreaIterator();
(area = it.Next()) != NULL;) {
if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
break;
}
if (area == NULL)
return B_ERROR;
// copy the runtime loader data structure
if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
return B_BAD_ADDRESS;
fTeam = team; fTeam = team;
return B_OK; return B_OK;
} }
@ -1390,7 +1374,7 @@ public:
// from the shared object. // from the shared object.
// get the image for the address // get the image for the address
image_t image; struct image *image;
status_t error = _FindImageAtAddress(address, image); status_t error = _FindImageAtAddress(address, image);
if (error != B_OK) { if (error != B_OK) {
// commpage requires special treatment since kernel stores symbol // commpage requires special treatment since kernel stores symbol
@ -1409,20 +1393,22 @@ public:
return error; return error;
} }
strlcpy(fImageName, image.name, sizeof(fImageName)); const extended_image_info& info = image->info;
const uint32 *symhash = (uint32 *)info.symbol_hash;
elf_sym *syms = (elf_sym *)info.symbol_table;
strlcpy(fImageName, info.basic_info.name, sizeof(fImageName));
// symbol hash table size // symbol hash table size
uint32 hashTabSize; uint32 hashTabSize;
if (!_Read(image.symhash, hashTabSize)) if (!_Read(symhash, hashTabSize))
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
// remote pointers to hash buckets and chains // remote pointers to hash buckets and chains
const uint32* hashBuckets = image.symhash + 2; const uint32* hashBuckets = symhash + 2;
const uint32* hashChains = image.symhash + 2 + hashTabSize; const uint32* hashChains = symhash + 2 + hashTabSize;
const addr_t loadDelta = image.regions[0].delta; const addr_t loadDelta = (addr_t)info.basic_info.text;
// TODO: add a way to get other text regions' size!
size_t regionsSize = image.regions[0].size;
// search the image for the symbol // search the image for the symbol
elf_sym symbolFound; elf_sym symbolFound;
@ -1442,7 +1428,7 @@ public:
_Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) { _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
elf_sym symbol; elf_sym symbol;
if (!_Read(image.syms + j, symbol)) if (!_Read(syms + j, symbol))
continue; continue;
// The symbol table contains not only symbols referring to // The symbol table contains not only symbols referring to
@ -1454,7 +1440,7 @@ public:
// -- couldn't verify that in the specs though). // -- couldn't verify that in the specs though).
if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT) if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
|| symbol.st_value == 0 || symbol.st_value == 0
|| (symbol.st_value + symbol.st_size) > regionsSize) { || (symbol.st_value + symbol.st_size) > (elf_addr)info.basic_info.text_size) {
continue; continue;
} }
@ -1484,7 +1470,7 @@ public:
*_symbolName = NULL; *_symbolName = NULL;
if (deltaFound < INT_MAX) { if (deltaFound < INT_MAX) {
if (_ReadString(image, symbolFound.st_name, fSymbolName, if (_ReadString(info, symbolFound.st_name, fSymbolName,
sizeof(fSymbolName))) { sizeof(fSymbolName))) {
*_symbolName = fSymbolName; *_symbolName = fSymbolName;
} else { } else {
@ -1498,7 +1484,7 @@ public:
if (deltaFound < INT_MAX) if (deltaFound < INT_MAX)
*_baseAddress = symbolFound.st_value + loadDelta; *_baseAddress = symbolFound.st_value + loadDelta;
else else
*_baseAddress = image.regions[0].vmstart; *_baseAddress = loadDelta;
} }
if (_exactMatch) if (_exactMatch)
@ -1507,33 +1493,31 @@ public:
return B_OK; return B_OK;
} }
status_t _FindImageAtAddress(addr_t address, image_t& image) status_t _FindImageAtAddress(addr_t address, struct image*& _image)
{ {
image_queue_t imageQueue; struct image* image = NULL;
if (!_Read(fDebugArea.loaded_images, imageQueue)) while ((image = (struct image*)list_get_next_item(&fTeam->image_list,
return B_BAD_ADDRESS; image)) != NULL) {
image_info *info = &image->info.basic_info;
image_t* imageAddress = imageQueue.head; if ((address < (addr_t)info->text
while (imageAddress != NULL) { || address >= (addr_t)info->text + info->text_size)
if (!_Read(imageAddress, image)) && (address < (addr_t)info->data
return B_BAD_ADDRESS; || address >= (addr_t)info->data + info->data_size))
continue;
// TODO: text may be more than just the first region. // found image
if (image.regions[0].vmstart <= address _image = image;
&& address < image.regions[0].vmstart + image.regions[0].size) { return B_OK;
return B_OK;
}
imageAddress = image.next;
} }
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
bool _ReadString(const image_t& image, uint32 offset, char* buffer, bool _ReadString(const extended_image_info& info, uint32 offset, char* buffer,
size_t bufferSize) size_t bufferSize)
{ {
const char* address = image.strtab + offset; const char* address = (char *)info.string_table + offset;
if (!IS_USER_ADDRESS(address)) if (!IS_USER_ADDRESS(address))
return false; return false;
@ -1550,7 +1534,6 @@ public:
private: private:
Team* fTeam; Team* fTeam;
runtime_loader_debug_area fDebugArea;
char fImageName[B_OS_NAME_LENGTH]; char fImageName[B_OS_NAME_LENGTH];
char fSymbolName[256]; char fSymbolName[256];
static UserSymbolLookup sLookup; static UserSymbolLookup sLookup;

View File

@ -365,39 +365,6 @@ image_iterate_through_team_images(team_id teamID,
} }
status_t
image_debug_lookup_user_symbol_address(Team *team, addr_t address,
addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
bool *_exactMatch)
{
// TODO: Work together with ELF reader and runtime_loader. For regular user
// images we have the symbol and string table addresses.
struct image *image = NULL;
while ((image = (struct image*)list_get_next_item(&team->image_list, image))
!= NULL) {
image_info *info = &image->info.basic_info;
if ((address < (addr_t)info->text
|| address >= (addr_t)info->text + info->text_size)
&& (address < (addr_t)info->data
|| address >= (addr_t)info->data + info->data_size))
continue;
// found image
*_symbolName = NULL;
*_imageName = info->name;
*_baseAddress = (addr_t)info->text;
*_exactMatch = false;
return B_OK;
}
return B_ENTRY_NOT_FOUND;
}
status_t status_t
image_init(void) image_init(void)
{ {