#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <List.h>
#include <debug/debug_support.h>
#include "ElfImage.h"
static status_t
get_static_image_symbol(image_id image, const char* name, int32 symbolType,
void** _address)
{
status_t error = get_image_symbol(image, name, symbolType, _address);
if (error == B_OK)
return B_OK;
image_info imageInfo;
error = get_image_info(image, &imageInfo);
if (error != B_OK)
return error;
debug_symbol_iterator* iterator;
error = debug_create_file_symbol_iterator(imageInfo.name, &iterator);
if (error != B_OK)
return error;
image_info unrelocatedImageInfo;
error = debug_get_symbol_iterator_image_info(iterator,
&unrelocatedImageInfo);
if (error != B_OK) {
debug_delete_symbol_iterator(iterator);
return error;
}
int32 nameLength = strlen(name);
while (true) {
char foundName[nameLength + 1];
int32 foundType;
void* foundAddress;
size_t foundSize;
if (debug_next_image_symbol(iterator, foundName, nameLength + 1,
&foundType, &foundAddress, &foundSize) != B_OK) {
debug_delete_symbol_iterator(iterator);
return B_ENTRY_NOT_FOUND;
}
if (strcmp(foundName, name) == 0
&& (symbolType == B_SYMBOL_TYPE_ANY || foundType == symbolType)) {
*_address = (void*)((addr_t)foundAddress + (addr_t)imageInfo.text
- (addr_t)unrelocatedImageInfo.text);
debug_delete_symbol_iterator(iterator);
return B_OK;
}
}
}
ElfImage::ElfImage()
: fImage(-1),
fFile(),
fTextAddress(NULL),
fDataAddress(NULL),
fGotAddress(NULL)
{
}
ElfImage::~ElfImage()
{
Unset();
}
status_t
ElfImage::SetTo(image_id image)
{
Unset();
status_t error = _SetTo(image);
if (error)
Unset();
return error;
}
void
ElfImage::Unset()
{
fFile.Unset();
fImage = -1;
fTextAddress = NULL;
fDataAddress = NULL;
fGotAddress = NULL;
}
void
ElfImage::Unload()
{
fFile.Unload();
}
status_t
ElfImage::FindSymbol(const char* symbolName, void** address)
{
return get_image_symbol(fImage, symbolName, B_SYMBOL_TYPE_ANY, address);
}
status_t
ElfImage::GetSymbolRelocations(const char* symbolName, BList* relocations)
{
status_t error = B_OK;
ElfRelocation relocation;
for (ElfRelocationIterator it(&fFile); it.GetNext(&relocation); ) {
uint32 type = relocation.GetType();
ElfSymbol symbol;
if ((type == R_GLOB_DAT || type == R_JUMP_SLOT)
&& relocation.GetSymbol(&symbol) == B_OK
&& symbol.GetName()) {
if ((symbol.GetBinding() == STB_GLOBAL
|| symbol.GetBinding() == STB_WEAK)
&& (symbol.GetTargetSectionIndex() == SHN_UNDEF
|| symbol.GetTargetSectionIndex()
>= (uint32)fFile.CountSections())
&& !strcmp(symbol.GetName(), symbolName)) {
void** gotEntry
= (void**)(fTextAddress + relocation.GetOffset());
if (!relocations->AddItem(gotEntry)) {
error = B_NO_MEMORY;
break;
}
}
}
}
return error;
}
status_t
ElfImage::_SetTo(image_id image)
{
image_info imageInfo;
status_t error = get_image_info(image, &imageInfo);
if (error != B_OK)
return error;
fImage = imageInfo.id;
error = get_static_image_symbol(image, "_GLOBAL_OFFSET_TABLE_",
B_SYMBOL_TYPE_ANY, (void**)&fGotAddress);
if (error != B_OK)
return error;
fTextAddress = (uint8*)imageInfo.text;
fDataAddress = (uint8*)imageInfo.data;
error = fFile.SetTo(imageInfo.name);
if (error != B_OK)
return error;
return B_OK;
}