Extended image_info by fields for the Haiku version and ABI. The runtime loader
and the kernel read those values from the shared object (if available). In the runtime loader this should eventually replace the gcc version guessing method currently used (at least for shared objects built for Haiku). The optional packages need to be rebuilt first, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30729 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
51c706f70c
commit
593ee7bbc3
@ -33,6 +33,10 @@ typedef struct {
|
||||
void *data;
|
||||
int32 text_size;
|
||||
int32 data_size;
|
||||
|
||||
// Haiku R1 extensions
|
||||
int32 api_version; // the Haiku API version used by the image
|
||||
int32 abi; // the Haiku ABI used by the image
|
||||
} image_info;
|
||||
|
||||
// flags for clear_caches()
|
||||
|
@ -85,6 +85,9 @@ typedef struct image_t {
|
||||
bool haiku;
|
||||
} gcc_version;
|
||||
|
||||
uint32 api_version;
|
||||
uint32 abi;
|
||||
|
||||
addr_t entry_point;
|
||||
addr_t init_routine;
|
||||
addr_t term_routine;
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <debug.h>
|
||||
#include <image_defs.h>
|
||||
#include <kernel.h>
|
||||
#include <kimage.h>
|
||||
#include <syscalls.h>
|
||||
@ -59,6 +60,10 @@ static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
|
||||
static bool sInitialized = false;
|
||||
|
||||
|
||||
static struct Elf32_Sym *elf_find_symbol(struct elf_image_info *image,
|
||||
const char *name);
|
||||
|
||||
|
||||
/*! Calculates hash for an image using its ID */
|
||||
static uint32
|
||||
image_hash(void *_image, const void *_key, uint32 range)
|
||||
@ -107,6 +112,46 @@ register_elf_image(struct elf_image_info *image)
|
||||
imageInfo.data = (void *)image->data_region.start;
|
||||
imageInfo.data_size = image->data_region.size;
|
||||
|
||||
if (image->text_region.id >= 0) {
|
||||
// evaluate the API/ABI version symbols
|
||||
|
||||
// Haiku API version
|
||||
imageInfo.api_version = 0;
|
||||
struct Elf32_Sym* symbol = elf_find_symbol(image,
|
||||
B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME);
|
||||
if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
|
||||
&& symbol->st_value > 0
|
||||
&& ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT
|
||||
&& symbol->st_size >= sizeof(uint32)) {
|
||||
addr_t symbolAddress = symbol->st_value + image->text_region.delta;
|
||||
if (symbolAddress >= image->text_region.start
|
||||
&& symbolAddress - image->text_region.start + sizeof(uint32)
|
||||
<= image->text_region.size) {
|
||||
imageInfo.api_version = *(uint32*)symbolAddress;
|
||||
}
|
||||
}
|
||||
|
||||
// Haiku ABI
|
||||
imageInfo.abi = 0;
|
||||
symbol = elf_find_symbol(image,
|
||||
B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME);
|
||||
if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
|
||||
&& symbol->st_value > 0
|
||||
&& ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT
|
||||
&& symbol->st_size >= sizeof(uint32)) {
|
||||
addr_t symbolAddress = symbol->st_value + image->text_region.delta;
|
||||
if (symbolAddress >= image->text_region.start
|
||||
&& symbolAddress - image->text_region.start + sizeof(uint32)
|
||||
<= image->text_region.size) {
|
||||
imageInfo.api_version = *(uint32*)symbolAddress;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// in-memory image -- use the current values
|
||||
imageInfo.api_version = B_HAIKU_VERSION;
|
||||
imageInfo.abi = B_HAIKU_ABI;
|
||||
}
|
||||
|
||||
image->id = register_image(team_get_kernel_team(), &imageInfo,
|
||||
sizeof(image_info));
|
||||
hash_insert(sImagesHash, image);
|
||||
@ -1529,6 +1574,12 @@ elf_load_user_image(const char *path, struct team *team, int flags,
|
||||
imageInfo.node = st.st_ino;
|
||||
strlcpy(imageInfo.name, path, sizeof(imageInfo.name));
|
||||
|
||||
imageInfo.api_version = B_HAIKU_VERSION;
|
||||
imageInfo.abi = B_HAIKU_ABI;
|
||||
// TODO: Get the actual values for the shared object. Currently only
|
||||
// the runtime loader is loaded, so this is good enough for the time
|
||||
// being.
|
||||
|
||||
imageInfo.id = register_image(team, &imageInfo, sizeof(image_info));
|
||||
if (imageInfo.id >= 0 && team_get_current_team_id() == team->id)
|
||||
user_debug_image_created(&imageInfo);
|
||||
|
@ -189,6 +189,9 @@ remove_images(struct team *team)
|
||||
status_t
|
||||
_get_image_info(image_id id, image_info *info, size_t size)
|
||||
{
|
||||
if (size > sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
|
||||
mutex_lock(&sImageMutex);
|
||||
@ -209,6 +212,9 @@ status_t
|
||||
_get_next_image_info(team_id teamID, int32 *cookie, image_info *info,
|
||||
size_t size)
|
||||
{
|
||||
if (size > sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
struct team *team;
|
||||
cpu_status state;
|
||||
@ -468,13 +474,13 @@ _user_get_image_info(image_id id, image_info *userInfo, size_t size)
|
||||
image_info info;
|
||||
status_t status;
|
||||
|
||||
if (size != sizeof(image_info))
|
||||
if (size > sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!IS_USER_ADDRESS(userInfo))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = _get_image_info(id, &info, size);
|
||||
status = _get_image_info(id, &info, sizeof(image_info));
|
||||
|
||||
if (user_memcpy(userInfo, &info, size) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
@ -484,18 +490,19 @@ _user_get_image_info(image_id id, image_info *userInfo, size_t size)
|
||||
|
||||
|
||||
status_t
|
||||
_user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo, size_t size)
|
||||
_user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo,
|
||||
size_t size)
|
||||
{
|
||||
image_info info;
|
||||
status_t status;
|
||||
|
||||
if (size != sizeof(image_info))
|
||||
if (size > sizeof(image_info))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!IS_USER_ADDRESS(userInfo) || !IS_USER_ADDRESS(_cookie))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = _get_next_image_info(team, _cookie, &info, size);
|
||||
status = _get_next_image_info(team, _cookie, &info, sizeof(image_info));
|
||||
|
||||
if (user_memcpy(userInfo, &info, size) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
@ -19,6 +19,7 @@
|
||||
#include <OS.h>
|
||||
|
||||
#include <elf32.h>
|
||||
#include <image_defs.h>
|
||||
#include <runtime_loader.h>
|
||||
#include <syscalls.h>
|
||||
#include <user_runtime.h>
|
||||
@ -144,6 +145,10 @@ static int32 sSemCount;
|
||||
extern runtime_loader_add_on_export gRuntimeLoaderAddOnExport;
|
||||
|
||||
|
||||
static struct Elf32_Sym* find_symbol(image_t* image, const char* name,
|
||||
int32 type);
|
||||
|
||||
|
||||
void
|
||||
dprintf(const char *format, ...)
|
||||
{
|
||||
@ -694,6 +699,34 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
analyze_image_haiku_version_and_abi(image_t* image)
|
||||
{
|
||||
// Haiku API version
|
||||
struct Elf32_Sym* symbol = find_symbol(image,
|
||||
B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, B_SYMBOL_TYPE_DATA);
|
||||
if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
|
||||
&& symbol->st_value > 0
|
||||
&& ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT
|
||||
&& symbol->st_size >= sizeof(uint32)) {
|
||||
image->api_version
|
||||
= *(uint32*)(symbol->st_value + image->regions[0].delta);
|
||||
} else
|
||||
image->api_version = 0;
|
||||
|
||||
// Haiku ABI
|
||||
symbol = find_symbol(image, B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME,
|
||||
B_SYMBOL_TYPE_DATA);
|
||||
if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
|
||||
&& symbol->st_value > 0
|
||||
&& ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT
|
||||
&& symbol->st_size >= sizeof(uint32)) {
|
||||
image->abi = *(uint32*)(symbol->st_value + image->regions[0].delta);
|
||||
} else
|
||||
image->abi = 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
||||
int32 sheaderSize, char* buffer, size_t bufferSize)
|
||||
@ -831,9 +864,9 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
||||
// well as cases where e.g. in a gcc 2 program a single C file has
|
||||
// been compiled with gcc 4.
|
||||
if (gccMajor == 0 || gccMajor > version[0]
|
||||
|| gccMajor == version[0]
|
||||
|| (gccMajor == version[0]
|
||||
&& (gccMiddle < version[1]
|
||||
|| gccMiddle == version[1] && gccMinor < version[2])) {
|
||||
|| (gccMiddle == version[1] && gccMinor < version[2])))) {
|
||||
gccMajor = version[0];
|
||||
gccMiddle = version[1];
|
||||
gccMinor = version[2];
|
||||
@ -1311,9 +1344,9 @@ find_undefined_symbol_global(image_t* rootImage, image_t* image,
|
||||
image_t* otherImage = sLoadedImages.head;
|
||||
while (otherImage != NULL) {
|
||||
if (otherImage == rootImage
|
||||
|| otherImage->type != B_ADD_ON_IMAGE
|
||||
|| (otherImage->type != B_ADD_ON_IMAGE
|
||||
&& (otherImage->flags
|
||||
& (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) != 0) {
|
||||
& (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) != 0)) {
|
||||
struct Elf32_Sym *symbol = find_symbol(otherImage, name,
|
||||
B_SYMBOL_TYPE_ANY);
|
||||
if (symbol) {
|
||||
@ -1542,6 +1575,8 @@ register_image(image_t *image, int fd, const char *path)
|
||||
info.text_size = image->regions[0].vmsize;
|
||||
info.data = (void *)image->regions[1].vmstart;
|
||||
info.data_size = image->regions[1].vmsize;
|
||||
info.api_version = image->api_version;
|
||||
info.abi = image->abi;
|
||||
image->id = _kern_register_image(&info, sizeof(image_info));
|
||||
}
|
||||
|
||||
@ -1687,6 +1722,24 @@ load_container(char const *name, image_type type, const char *rpath,
|
||||
goto err2;
|
||||
}
|
||||
|
||||
status = map_image(fd, path, image, type == B_APP_IMAGE);
|
||||
if (status < B_OK) {
|
||||
FATAL("Could not map image: %s\n", strerror(status));
|
||||
status = B_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
if (!parse_dynamic_segment(image)) {
|
||||
FATAL("Troubles handling dynamic section\n");
|
||||
status = B_BAD_DATA;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
if (eheader.e_entry != 0)
|
||||
image->entry_point = eheader.e_entry + image->regions[0].delta;
|
||||
|
||||
analyze_image_haiku_version_and_abi(image);
|
||||
|
||||
if (analyze_object_gcc_version(fd, image, eheader, sheaderSize, ph_buff,
|
||||
sizeof(ph_buff))) {
|
||||
// If this is the executable image, we init the search path
|
||||
@ -1709,26 +1762,10 @@ load_container(char const *name, image_type type, const char *rpath,
|
||||
// symbol resolution strategy (fallback is R5-style, if version is
|
||||
// unavailable)
|
||||
if (image->gcc_version.major == 0
|
||||
|| image->gcc_version.major == 2 && image->gcc_version.middle < 95) {
|
||||
|| (image->gcc_version.major == 2 && image->gcc_version.middle < 95)) {
|
||||
image->find_undefined_symbol = find_undefined_symbol_beos;
|
||||
}
|
||||
|
||||
status = map_image(fd, path, image, type == B_APP_IMAGE);
|
||||
if (status < B_OK) {
|
||||
FATAL("Could not map image: %s\n", strerror(status));
|
||||
status = B_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
if (!parse_dynamic_segment(image)) {
|
||||
FATAL("Troubles handling dynamic section\n");
|
||||
status = B_BAD_DATA;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
if (eheader.e_entry != 0)
|
||||
image->entry_point = eheader.e_entry + image->regions[0].delta;
|
||||
|
||||
image->type = type;
|
||||
register_image(image, fd, path);
|
||||
image_event(image, IMAGE_EVENT_LOADED);
|
||||
|
Loading…
Reference in New Issue
Block a user