* Resolved TODO added by Ingo: the runtime loader now lazily updates its
image IDs when needed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27611 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
3534ce57f0
commit
9a6072a35f
@ -82,6 +82,7 @@ static image_t *sProgramImage;
|
|||||||
static KMessage sErrorMessage;
|
static KMessage sErrorMessage;
|
||||||
static bool sProgramLoaded = false;
|
static bool sProgramLoaded = false;
|
||||||
static const char *sSearchPathSubDir = NULL;
|
static const char *sSearchPathSubDir = NULL;
|
||||||
|
static bool sInvalidImageIDs;
|
||||||
|
|
||||||
// a recursive lock
|
// a recursive lock
|
||||||
static sem_id rld_sem;
|
static sem_id rld_sem;
|
||||||
@ -227,13 +228,52 @@ report_errors()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Remaps the image ID of \a image after fork.
|
||||||
|
static status_t
|
||||||
|
update_image_id(image_t *image)
|
||||||
|
{
|
||||||
|
int32 cookie = 0;
|
||||||
|
image_info info;
|
||||||
|
while (_kern_get_next_image_info(B_CURRENT_TEAM, &cookie, &info,
|
||||||
|
sizeof(image_info)) == B_OK) {
|
||||||
|
for (uint32 i = 0; i < image->num_regions; i++) {
|
||||||
|
if (image->regions[i].vmstart == (addr_t)info.text) {
|
||||||
|
image->id = info.id;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FATAL("Could not update image ID %ld after fork()!\n", image->id);
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! After fork, we lazily rebuild the image IDs of all loaded images.
|
||||||
|
static status_t
|
||||||
|
update_image_ids(void)
|
||||||
|
{
|
||||||
|
for (image_t *image = sLoadedImages.head; image; image = image->next) {
|
||||||
|
status_t status = update_image_id(image);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
for (image_t *image = sDisposableImages.head; image; image = image->next) {
|
||||||
|
status_t status = update_image_id(image);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
sInvalidImageIDs = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static image_t *
|
static image_t *
|
||||||
find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
|
find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
|
||||||
uint32 typeMask)
|
uint32 typeMask)
|
||||||
{
|
{
|
||||||
image_t *image;
|
for (image_t *image = queue->head; image; image = image->next) {
|
||||||
|
|
||||||
for (image = queue->head; image; image = image->next) {
|
|
||||||
const char *imageName = isPath ? image->path : image->name;
|
const char *imageName = isPath ? image->path : image->name;
|
||||||
int length = isPath ? sizeof(image->path) : sizeof(image->name);
|
int length = isPath ? sizeof(image->path) : sizeof(image->name);
|
||||||
|
|
||||||
@ -250,7 +290,7 @@ find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
|
|||||||
static image_t *
|
static image_t *
|
||||||
find_image(char const *name, uint32 typeMask)
|
find_image(char const *name, uint32 typeMask)
|
||||||
{
|
{
|
||||||
bool isPath = (strchr(name, '/') != NULL);
|
bool isPath = strchr(name, '/') != NULL;
|
||||||
return find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
|
return find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,16 +298,19 @@ find_image(char const *name, uint32 typeMask)
|
|||||||
static image_t *
|
static image_t *
|
||||||
find_loaded_image_by_id(image_id id)
|
find_loaded_image_by_id(image_id id)
|
||||||
{
|
{
|
||||||
image_t *image;
|
if (sInvalidImageIDs) {
|
||||||
|
// After fork, we lazily rebuild the image IDs of all loaded images
|
||||||
|
update_image_ids();
|
||||||
|
}
|
||||||
|
|
||||||
for (image = sLoadedImages.head; image; image = image->next) {
|
for (image_t *image = sLoadedImages.head; image; image = image->next) {
|
||||||
if (image->id == id)
|
if (image->id == id)
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the termination routine, we need to look into the list of
|
// For the termination routine, we need to look into the list of
|
||||||
// disposable images as well
|
// disposable images as well
|
||||||
for (image = sDisposableImages.head; image; image = image->next) {
|
for (image_t *image = sDisposableImages.head; image; image = image->next) {
|
||||||
if (image->id == id)
|
if (image->id == id)
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@ -373,13 +416,6 @@ count_regions(char const *buff, int phnum, int phentsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create_image() & destroy_image()
|
|
||||||
*
|
|
||||||
* Create and destroy image_t structures. The destroyer makes sure that the
|
|
||||||
* memory buffers are full of garbage before freeing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static image_t *
|
static image_t *
|
||||||
create_image(const char *name, const char *path, int num_regions)
|
create_image(const char *name, const char *path, int num_regions)
|
||||||
{
|
{
|
||||||
@ -420,6 +456,7 @@ delete_image_struct(image_t *image)
|
|||||||
free(image->needed);
|
free(image->needed);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
// overwrite images to make sure they aren't accidently reused anywhere
|
||||||
memset(image, 0xa5, size);
|
memset(image, 0xa5, size);
|
||||||
#endif
|
#endif
|
||||||
free(image);
|
free(image);
|
||||||
@ -1736,6 +1773,11 @@ unload_library(image_id imageID, bool addOn)
|
|||||||
rld_lock();
|
rld_lock();
|
||||||
// for now, just do stupid simple global locking
|
// for now, just do stupid simple global locking
|
||||||
|
|
||||||
|
if (sInvalidImageIDs) {
|
||||||
|
// After fork, we lazily rebuild the image IDs of all loaded images
|
||||||
|
update_image_ids();
|
||||||
|
}
|
||||||
|
|
||||||
// we only check images that have been already initialized
|
// we only check images that have been already initialized
|
||||||
|
|
||||||
for (image = sLoadedImages.head; image; image = image->next) {
|
for (image = sLoadedImages.head; image; image = image->next) {
|
||||||
@ -1774,8 +1816,8 @@ unload_library(image_id imageID, bool addOn)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength,
|
get_nth_symbol(image_id imageID, int32 num, char *nameBuffer,
|
||||||
int32 *_type, void **_location)
|
int32 *_nameLength, int32 *_type, void **_location)
|
||||||
{
|
{
|
||||||
int32 count = 0, j;
|
int32 count = 0, j;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
@ -1827,7 +1869,8 @@ out:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location)
|
get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
|
||||||
|
void **_location)
|
||||||
{
|
{
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
image_t *image;
|
image_t *image;
|
||||||
@ -1906,8 +1949,7 @@ get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
|
|||||||
// #pragma mark - runtime_loader private exports
|
// #pragma mark - runtime_loader private exports
|
||||||
|
|
||||||
|
|
||||||
/** Read and verify the ELF header */
|
/*! Read and verify the ELF header */
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
elf_verify_header(void *header, int32 length)
|
elf_verify_header(void *header, int32 length)
|
||||||
{
|
{
|
||||||
@ -1916,7 +1958,8 @@ elf_verify_header(void *header, int32 length)
|
|||||||
if (length < (int32)sizeof(struct Elf32_Ehdr))
|
if (length < (int32)sizeof(struct Elf32_Ehdr))
|
||||||
return B_NOT_AN_EXECUTABLE;
|
return B_NOT_AN_EXECUTABLE;
|
||||||
|
|
||||||
return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, §ionSize);
|
return parse_elf_header((struct Elf32_Ehdr *)header, &programSize,
|
||||||
|
§ionSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1930,6 +1973,11 @@ terminate_program(void)
|
|||||||
if (count < B_OK)
|
if (count < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (sInvalidImageIDs) {
|
||||||
|
// After fork, we lazily rebuild the image IDs of all loaded images
|
||||||
|
update_image_ids();
|
||||||
|
}
|
||||||
|
|
||||||
TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
|
TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
|
||||||
for (i = count; i-- > 0;) {
|
for (i = count; i-- > 0;) {
|
||||||
image_t *image = termList[i];
|
image_t *image = termList[i];
|
||||||
@ -1980,16 +2028,17 @@ rldelf_init(void)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
elf_reinit_after_fork()
|
elf_reinit_after_fork(void)
|
||||||
{
|
{
|
||||||
rld_sem = create_sem(1, "rld_lock");
|
rld_sem = create_sem(1, "rld_lock");
|
||||||
if (rld_sem < 0)
|
if (rld_sem < 0)
|
||||||
return rld_sem;
|
return rld_sem;
|
||||||
|
|
||||||
// TODO: We should also update the IDs of our images. We are the child and
|
// We also need to update the IDs of our images. We are the child and
|
||||||
// and have cloned images with different IDs. Since in most cases (fork()
|
// and have cloned images with different IDs. Since in most cases (fork()
|
||||||
// + exec*()) this would just increase the fork() overhead with no one
|
// + exec*()) this would just increase the fork() overhead with no one
|
||||||
// caring, we could do that lazily, when first doing something different.
|
// caring, we do that lazily, when first doing something different.
|
||||||
|
sInvalidImageIDs = true;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ int resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
|||||||
status_t elf_verify_header(void *header, int32 length);
|
status_t elf_verify_header(void *header, int32 length);
|
||||||
void rldelf_init(void);
|
void rldelf_init(void);
|
||||||
void rldexport_init(void);
|
void rldexport_init(void);
|
||||||
status_t elf_reinit_after_fork();
|
status_t elf_reinit_after_fork(void);
|
||||||
|
|
||||||
status_t heap_init(void);
|
status_t heap_init(void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user