* Got rid of sLoadingImages. It was always empty.
* The previous symbol resolution code was incorrect. It would search all loaded images in the order they had been loaded. Thus an add-on would possibly see a symbol of an earlier loaded add-on. Now we search recursively starting with the respective root image (executable or add-on). * Added BeOS style symbol resolution and made it the default. A symbol undefined in an image is only searched in its direct dependencies. Fixes bug #889 (BeOS apps crashing under Haiku when opening a file panel). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21290 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
b31d4c4373
commit
46f4d84912
@ -8,6 +8,9 @@ UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
|
||||
SubDirCcFlags -fno-builtin ;
|
||||
SubDirC++Flags -fno-builtin -fno-exceptions ;
|
||||
|
||||
# default to BeOS style symbol resolution
|
||||
DEFINES += BEOS_STYLE_SYMBOLS_RESOLUTION ;
|
||||
|
||||
# needed for "runtime_loader" only
|
||||
StaticLibrary libruntime_loader.a :
|
||||
kernel_vsprintf.c
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
|
||||
static int
|
||||
relocate_rel(image_t *image, struct Elf32_Rel *rel, int rel_len)
|
||||
relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
|
||||
int rel_len)
|
||||
{
|
||||
// ToDo: implement me!
|
||||
|
||||
@ -30,19 +31,20 @@ relocate_rel(image_t *image, struct Elf32_Rel *rel, int rel_len)
|
||||
|
||||
|
||||
status_t
|
||||
arch_relocate_image(image_t *image)
|
||||
arch_relocate_image(image_t *rootImage, image_t *image)
|
||||
{
|
||||
status_t status = B_NO_ERROR;
|
||||
|
||||
// deal with the rels first
|
||||
if (image->rel) {
|
||||
status = relocate_rel(image, image->rel, image->rel_len);
|
||||
status = relocate_rel(rootImage, image, image->rel, image->rel_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (image->pltrel) {
|
||||
status = relocate_rel(image, image->pltrel, image->pltrel_len);
|
||||
status = relocate_rel(rootImage, image, image->pltrel,
|
||||
image->pltrel_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
@ -26,7 +26,8 @@
|
||||
|
||||
|
||||
static int
|
||||
relocate_rel(image_t *image, struct Elf32_Rel *rel, int rel_len)
|
||||
relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
|
||||
int rel_len)
|
||||
{
|
||||
int i;
|
||||
addr_t S;
|
||||
@ -50,7 +51,7 @@ relocate_rel(image_t *image, struct Elf32_Rel *rel, int rel_len)
|
||||
status_t status;
|
||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
||||
|
||||
status = resolve_symbol(image, sym, &S);
|
||||
status = resolve_symbol(rootImage, image, sym, &S);
|
||||
if (status < B_OK) {
|
||||
TRACE(("resolve symbol \"%s\" returned: %ld\n",
|
||||
SYMNAME(image, sym), status));
|
||||
@ -114,19 +115,20 @@ relocate_rel(image_t *image, struct Elf32_Rel *rel, int rel_len)
|
||||
|
||||
|
||||
status_t
|
||||
arch_relocate_image(image_t *image)
|
||||
arch_relocate_image(image_t *rootImage, image_t *image)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
// deal with the rels first
|
||||
if (image->rel) {
|
||||
status = relocate_rel(image, image->rel, image->rel_len);
|
||||
status = relocate_rel(rootImage, image, image->rel, image->rel_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (image->pltrel) {
|
||||
status = relocate_rel(image, image->pltrel, image->pltrel_len);
|
||||
status = relocate_rel(rootImage, image, image->pltrel,
|
||||
image->pltrel_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
@ -55,7 +55,10 @@ enum {
|
||||
RFLAG_RELOCATED = 0x1000,
|
||||
RFLAG_PROTECTED = 0x2000,
|
||||
RFLAG_DEPENDENCIES_LOADED = 0x4000,
|
||||
RFLAG_REMAPPED = 0x8000
|
||||
RFLAG_REMAPPED = 0x8000,
|
||||
|
||||
RFLAG_VISITED = 0x10000
|
||||
// temporarily set in the symbol resolution code
|
||||
};
|
||||
|
||||
|
||||
@ -70,11 +73,16 @@ enum {
|
||||
typedef void (*init_term_function)(image_id);
|
||||
|
||||
static image_queue_t sLoadedImages = {0, 0};
|
||||
static image_queue_t sLoadingImages = {0, 0};
|
||||
static image_queue_t sDisposableImages = {0, 0};
|
||||
static uint32 sLoadedImageCount = 0;
|
||||
static image_t *sProgramImage;
|
||||
|
||||
#ifdef BEOS_STYLE_SYMBOLS_RESOLUTION
|
||||
static bool sResolveSymbolsBeOSStyle = true;
|
||||
#else
|
||||
static bool sResolveSymbolsBeOSStyle = false;
|
||||
#endif
|
||||
|
||||
// a recursive lock
|
||||
static sem_id rld_sem;
|
||||
static thread_id rld_sem_owner;
|
||||
@ -198,13 +206,7 @@ static image_t *
|
||||
find_image(char const *name, uint32 typeMask)
|
||||
{
|
||||
bool isPath = (strchr(name, '/') != NULL);
|
||||
image_t *image;
|
||||
|
||||
image = find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
|
||||
if (image == NULL)
|
||||
image = find_image_in_queue(&sLoadingImages, name, isPath, typeMask);
|
||||
|
||||
return image;
|
||||
return find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
|
||||
}
|
||||
|
||||
|
||||
@ -729,30 +731,98 @@ find_symbol(image_t *image, const char *name, int32 type)
|
||||
}
|
||||
|
||||
|
||||
static struct Elf32_Sym *
|
||||
find_symbol_in_loaded_images(image_t **_image, const char *name)
|
||||
static struct Elf32_Sym*
|
||||
find_symbol_recursively_impl(image_t* image, const char* name,
|
||||
image_t** foundInImage)
|
||||
{
|
||||
image_t *image;
|
||||
image->flags |= RFLAG_VISITED;
|
||||
|
||||
for (image = sLoadedImages.head; image; image = image->next) {
|
||||
struct Elf32_Sym *symbol;
|
||||
|
||||
if (image->dynamic_ptr == NULL)
|
||||
continue;
|
||||
struct Elf32_Sym *symbol;
|
||||
|
||||
// look up the symbol in this image
|
||||
if (image->dynamic_ptr) {
|
||||
symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY);
|
||||
if (symbol) {
|
||||
*_image = image;
|
||||
*foundInImage = image;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
// recursively search dependencies
|
||||
for (uint32 i = 0; i < image->num_needed; i++) {
|
||||
if (!(image->needed[i]->flags & RFLAG_VISITED)) {
|
||||
symbol = find_symbol_recursively_impl(image->needed[i], name,
|
||||
foundInImage);
|
||||
if (symbol)
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clear_image_flag_recursively(image_t* image, uint32 flag)
|
||||
{
|
||||
image->flags &= ~flag;
|
||||
|
||||
for (uint32 i = 0; i < image->num_needed; i++) {
|
||||
if (image->needed[i]->flags & flag)
|
||||
clear_image_flag_recursively(image->needed[i], flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct Elf32_Sym*
|
||||
find_symbol_recursively(image_t* image, const char* name,
|
||||
image_t** foundInImage)
|
||||
{
|
||||
struct Elf32_Sym* symbol = find_symbol_recursively_impl(image, name,
|
||||
foundInImage);
|
||||
clear_image_flag_recursively(image, RFLAG_VISITED);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
static struct Elf32_Sym*
|
||||
find_symbol_in_loaded_images(const char* name, image_t** foundInImage)
|
||||
{
|
||||
return find_symbol_recursively(sLoadedImages.head, name, foundInImage);
|
||||
}
|
||||
|
||||
|
||||
static struct Elf32_Sym*
|
||||
find_undefined_symbol(image_t* rootImage, image_t* image, const char* name,
|
||||
image_t** foundInImage)
|
||||
{
|
||||
// If not simulating BeOS style symbol resolution, undefined symbols are
|
||||
// search recursively starting from the root image. (Note, breadth first
|
||||
// might be better than the depth first use here.)
|
||||
if (!sResolveSymbolsBeOSStyle)
|
||||
return find_symbol_recursively(rootImage, name, foundInImage);
|
||||
|
||||
// BeOS style symbol resolution: It is sufficient to check the direct
|
||||
// dependencies. The linker would have complained, if the symbol wasn't
|
||||
// there.
|
||||
for (uint32 i = 0; i < image->num_needed; i++) {
|
||||
if (image->needed[i]->dynamic_ptr) {
|
||||
struct Elf32_Sym *symbol = find_symbol(image->needed[i], name,
|
||||
B_SYMBOL_TYPE_ANY);
|
||||
if (symbol) {
|
||||
*foundInImage = image->needed[i];
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr_t *sym_addr)
|
||||
resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
||||
addr_t *sym_addr)
|
||||
{
|
||||
struct Elf32_Sym *sym2;
|
||||
char *symname;
|
||||
@ -763,8 +833,8 @@ resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr_t *sym_addr)
|
||||
// patch the symbol name
|
||||
symname = SYMNAME(image, sym);
|
||||
|
||||
// it's undefined, must be outside this image, try the other image
|
||||
sym2 = find_symbol_in_loaded_images(&shimg, symname);
|
||||
// it's undefined, must be outside this image, try the other images
|
||||
sym2 = find_undefined_symbol(rootImage, image, symname, &shimg);
|
||||
if (!sym2) {
|
||||
printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname);
|
||||
return B_MISSING_SYMBOL;
|
||||
@ -835,11 +905,11 @@ register_image(image_t *image, int fd, const char *path)
|
||||
|
||||
|
||||
static status_t
|
||||
relocate_image(image_t *image)
|
||||
relocate_image(image_t *rootImage, image_t *image)
|
||||
{
|
||||
status_t status = arch_relocate_image(image);
|
||||
status_t status = arch_relocate_image(rootImage, image);
|
||||
if (status < B_OK) {
|
||||
FATAL("troubles relocating: 0x%lx\n", status);
|
||||
FATAL("troubles relocating: 0x%lx (image: %s)\n", status, image->name);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1124,7 +1194,7 @@ relocate_dependencies(image_t *image)
|
||||
return count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
status_t status = relocate_image(list[i]);
|
||||
status_t status = relocate_image(image, list[i]);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
@ -1219,7 +1289,8 @@ load_program(char const *path, void **_entry)
|
||||
|
||||
// We patch any exported __gRuntimeLoader symbols to point to our private API
|
||||
{
|
||||
struct Elf32_Sym *symbol = find_symbol_in_loaded_images(&image, "__gRuntimeLoader");
|
||||
struct Elf32_Sym *symbol = find_symbol_in_loaded_images(
|
||||
"__gRuntimeLoader", &image);
|
||||
if (symbol != NULL) {
|
||||
void **_export = (void **)(symbol->st_value + image->regions[0].delta);
|
||||
*_export = &gRuntimeLoader;
|
||||
@ -1233,7 +1304,8 @@ load_program(char const *path, void **_entry)
|
||||
// Since the images are initialized now, we no longer should use our
|
||||
// getenv(), but use the one from libroot.so
|
||||
{
|
||||
struct Elf32_Sym *symbol = find_symbol_in_loaded_images(&image, "getenv");
|
||||
struct Elf32_Sym *symbol = find_symbol_in_loaded_images("getenv",
|
||||
&image);
|
||||
if (symbol != NULL)
|
||||
gGetEnv = (char* (*)(const char*))
|
||||
(symbol->st_value + image->regions[0].delta);
|
||||
|
@ -24,18 +24,21 @@ extern "C" {
|
||||
|
||||
int runtime_loader(void *arg);
|
||||
int open_executable(char *name, image_type type, const char *rpath);
|
||||
status_t test_executable(const char *path, uid_t user, gid_t group, char *starter);
|
||||
status_t test_executable(const char *path, uid_t user, gid_t group,
|
||||
char *starter);
|
||||
|
||||
void terminate_program(void);
|
||||
image_id load_program(char const *path, void **entry);
|
||||
status_t unload_library(image_id imageID, bool addOn);
|
||||
image_id load_library(char const *path, uint32 flags, bool addOn);
|
||||
status_t get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength,
|
||||
int32 *_type, void **_location);
|
||||
status_t get_nth_symbol(image_id imageID, int32 num, char *nameBuffer,
|
||||
int32 *_nameLength, int32 *_type, void **_location);
|
||||
status_t get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
|
||||
void **_location);
|
||||
status_t get_next_image_dependency(image_id id, uint32 *cookie, const char **_name);
|
||||
int resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr_t *sym_addr);
|
||||
status_t get_next_image_dependency(image_id id, uint32 *cookie,
|
||||
const char **_name);
|
||||
int resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
||||
addr_t *sym_addr);
|
||||
|
||||
|
||||
status_t elf_verify_header(void *header, int32 length);
|
||||
@ -45,7 +48,7 @@ void rldexport_init(void);
|
||||
status_t heap_init(void);
|
||||
|
||||
// arch dependent prototypes
|
||||
status_t arch_relocate_image(image_t *image);
|
||||
status_t arch_relocate_image(image_t *rootImage, image_t *image);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user