First set of changes to have a BeOS compatible runtime loader.
Added a simple locking strategy to the loader (didn't do any locking before), it now uses a global recursive lock for the exported API. Implemented all needed functionality for the BeOS image API. Now registers images with the kernel. Added several ToDo items. Cleanups, and possibly more I've forgotten about. (hope this works since the local diff does not?!) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2436 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+373
-223
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2003, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Copyright 2002, Manuel J. Petit. All rights reserved.
|
** Copyright 2002, Manuel J. Petit. All rights reserved.
|
||||||
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,6 +17,11 @@
|
|||||||
|
|
||||||
#include "rld_priv.h"
|
#include "rld_priv.h"
|
||||||
|
|
||||||
|
// ToDo: implement better locking strategy
|
||||||
|
// ToDo: implement unload_program()
|
||||||
|
// ToDo: implement load_addon()/unload_addon(): at the very least, we will have to make
|
||||||
|
// sure that B_ADD_ON_IMAGE is set correctly
|
||||||
|
// ToDo: implement search paths $LIBRARY_PATH, $ADDON_PATH
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define PAGE_MASK ((PAGE_SIZE)-1)
|
#define PAGE_MASK ((PAGE_SIZE)-1)
|
||||||
@@ -50,29 +56,26 @@ struct elf_region_t {
|
|||||||
addr fdstart;
|
addr fdstart;
|
||||||
addr fdsize;
|
addr fdsize;
|
||||||
long delta;
|
long delta;
|
||||||
unsigned flags;
|
uint32 flags;
|
||||||
} elf_region_t;
|
} elf_region_t;
|
||||||
|
|
||||||
|
|
||||||
typedef
|
typedef struct image_t {
|
||||||
struct image_t {
|
// image identification
|
||||||
/*
|
|
||||||
* image identification
|
|
||||||
*/
|
|
||||||
char name[SYS_MAX_OS_NAME_LEN];
|
char name[SYS_MAX_OS_NAME_LEN];
|
||||||
dynmodule_id imageid;
|
image_id id;
|
||||||
|
image_type type;
|
||||||
|
|
||||||
struct image_t *next;
|
struct image_t *next;
|
||||||
struct image_t *prev;
|
struct image_t *prev;
|
||||||
int refcount;
|
int32 ref_count;
|
||||||
unsigned flags;
|
uint32 flags;
|
||||||
|
|
||||||
addr entry_point;
|
addr entry_point;
|
||||||
addr dynamic_ptr; // pointer to the dynamic section
|
addr dynamic_ptr; // pointer to the dynamic section
|
||||||
|
|
||||||
|
|
||||||
// pointer to symbol participation data structures
|
// pointer to symbol participation data structures
|
||||||
unsigned int *symhash;
|
uint32 *symhash;
|
||||||
struct Elf32_Sym *syms;
|
struct Elf32_Sym *syms;
|
||||||
char *strtab;
|
char *strtab;
|
||||||
struct Elf32_Rel *rel;
|
struct Elf32_Rel *rel;
|
||||||
@@ -82,11 +85,11 @@ struct image_t {
|
|||||||
struct Elf32_Rel *pltrel;
|
struct Elf32_Rel *pltrel;
|
||||||
int pltrel_len;
|
int pltrel_len;
|
||||||
|
|
||||||
unsigned num_needed;
|
uint32 num_needed;
|
||||||
struct image_t **needed;
|
struct image_t **needed;
|
||||||
|
|
||||||
// describes the text and data regions
|
// describes the text and data regions
|
||||||
unsigned num_regions;
|
uint32 num_regions;
|
||||||
elf_region_t regions[1];
|
elf_region_t regions[1];
|
||||||
} image_t;
|
} image_t;
|
||||||
|
|
||||||
@@ -98,14 +101,17 @@ struct image_queue_t {
|
|||||||
} image_queue_t;
|
} image_queue_t;
|
||||||
|
|
||||||
|
|
||||||
static image_queue_t loaded_images = { 0, 0 };
|
static image_queue_t gLoadedImages = {0, 0};
|
||||||
static image_queue_t loading_images = { 0, 0 };
|
static image_queue_t gLoadingImages = {0, 0};
|
||||||
static image_queue_t disposable_images = { 0, 0 };
|
static image_queue_t gDisposableImages = {0, 0};
|
||||||
static unsigned loaded_image_count = 0;
|
static uint32 gLoadedImageCount = 0;
|
||||||
static unsigned imageid_count = 0;
|
|
||||||
|
|
||||||
|
// a recursive lock
|
||||||
static sem_id rld_sem;
|
static sem_id rld_sem;
|
||||||
static struct uspace_prog_args_t const *uspa;
|
static thread_id rld_sem_owner;
|
||||||
|
static int32 rld_sem_count;
|
||||||
|
|
||||||
|
static struct uspace_program_args const *gProgramArgs;
|
||||||
|
|
||||||
|
|
||||||
#define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
|
#define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
|
||||||
@@ -126,47 +132,66 @@ static struct uspace_prog_args_t const *uspa;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
rld_unlock()
|
||||||
|
{
|
||||||
|
if (rld_sem_count-- == 1) {
|
||||||
|
rld_sem_owner = -1;
|
||||||
|
release_sem(rld_sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enqueue_image(image_queue_t *queue, image_t *img)
|
rld_lock()
|
||||||
{
|
{
|
||||||
img->next = 0;
|
thread_id self = sys_get_current_thread_id();
|
||||||
|
if (self != rld_sem_owner) {
|
||||||
|
acquire_sem(rld_sem);
|
||||||
|
rld_sem_owner = self;
|
||||||
|
}
|
||||||
|
rld_sem_count++;
|
||||||
|
}
|
||||||
|
|
||||||
img->prev = queue->tail;
|
|
||||||
|
static void
|
||||||
|
enqueue_image(image_queue_t *queue, image_t *image)
|
||||||
|
{
|
||||||
|
image->next = 0;
|
||||||
|
|
||||||
|
image->prev = queue->tail;
|
||||||
if (queue->tail)
|
if (queue->tail)
|
||||||
queue->tail->next= img;
|
queue->tail->next = image;
|
||||||
|
|
||||||
queue->tail = img;
|
queue->tail = image;
|
||||||
if (!queue->head)
|
if (!queue->head)
|
||||||
queue->head= img;
|
queue->head = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dequeue_image(image_queue_t *queue, image_t *img)
|
dequeue_image(image_queue_t *queue, image_t *image)
|
||||||
{
|
{
|
||||||
if(img->next) {
|
if (image->next)
|
||||||
img->next->prev= img->prev;
|
image->next->prev = image->prev;
|
||||||
} else {
|
else
|
||||||
queue->tail= img->prev;
|
queue->tail = image->prev;
|
||||||
}
|
|
||||||
|
|
||||||
if(img->prev) {
|
if (image->prev)
|
||||||
img->prev->next= img->next;
|
image->prev->next = image->next;
|
||||||
} else {
|
else
|
||||||
queue->head= img->next;
|
queue->head = image->next;
|
||||||
}
|
|
||||||
|
|
||||||
img->prev= 0;
|
image->prev = 0;
|
||||||
img->next= 0;
|
image->next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned long
|
static uint32
|
||||||
elf_hash(const unsigned char *name)
|
elf_hash(const uchar *name)
|
||||||
{
|
{
|
||||||
unsigned long hash = 0;
|
uint32 hash = 0;
|
||||||
unsigned long temp;
|
uint32 temp;
|
||||||
|
|
||||||
while (*name) {
|
while (*name) {
|
||||||
hash = (hash << 4) + *name++;
|
hash = (hash << 4) + *name++;
|
||||||
@@ -184,12 +209,12 @@ find_image(char const *name)
|
|||||||
{
|
{
|
||||||
image_t *iter;
|
image_t *iter;
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
|
if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = loading_images.head; iter; iter = iter->next) {
|
for (iter = gLoadingImages.head; iter; iter = iter->next) {
|
||||||
if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
|
if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
@@ -198,8 +223,22 @@ find_image(char const *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static image_t *
|
||||||
parse_eheader(struct Elf32_Ehdr *eheader)
|
find_loaded_image_by_id(image_id id)
|
||||||
|
{
|
||||||
|
image_t *image;
|
||||||
|
|
||||||
|
for (image = gLoadedImages.head; image; image = image->next) {
|
||||||
|
if (image->id == id)
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize)
|
||||||
{
|
{
|
||||||
if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
|
if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
|
||||||
return ERR_INVALID_BINARY;
|
return ERR_INVALID_BINARY;
|
||||||
@@ -213,7 +252,10 @@ parse_eheader(struct Elf32_Ehdr *eheader)
|
|||||||
if (eheader->e_phentsize < sizeof(struct Elf32_Phdr))
|
if (eheader->e_phentsize < sizeof(struct Elf32_Phdr))
|
||||||
return ERR_INVALID_BINARY;
|
return ERR_INVALID_BINARY;
|
||||||
|
|
||||||
return eheader->e_phentsize*eheader->e_phnum;
|
*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
|
||||||
|
*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
|
||||||
|
|
||||||
|
return *_pheaderSize > 0 && *_sheaderSize > 0 ? B_OK : ERR_INVALID_BINARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -279,37 +321,34 @@ count_regions(char const *buff, int phnum, int phentsize)
|
|||||||
static image_t *
|
static image_t *
|
||||||
create_image(char const *name, int num_regions)
|
create_image(char const *name, int num_regions)
|
||||||
{
|
{
|
||||||
image_t *retval;
|
size_t allocSize;
|
||||||
size_t alloc_size;
|
image_t *image;
|
||||||
|
|
||||||
alloc_size = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t);
|
allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t);
|
||||||
|
|
||||||
retval = rldalloc(alloc_size);
|
image = rldalloc(allocSize);
|
||||||
|
memset(image, 0, allocSize);
|
||||||
|
|
||||||
memset(retval, 0, alloc_size);
|
strlcpy(image->name, name, sizeof(image->name));
|
||||||
|
image->ref_count = 1;
|
||||||
|
image->num_regions = num_regions;
|
||||||
|
|
||||||
strlcpy(retval->name, name, sizeof(retval->name));
|
return image;
|
||||||
retval->imageid = imageid_count;
|
|
||||||
retval->refcount = 1;
|
|
||||||
retval->num_regions = num_regions;
|
|
||||||
|
|
||||||
imageid_count += 1;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_image(image_t *image)
|
delete_image(image_t *image)
|
||||||
{
|
{
|
||||||
size_t alloc_size;
|
size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t);
|
||||||
|
|
||||||
alloc_size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t);
|
sys_unregister_image(image->id);
|
||||||
|
// registered in load_container()
|
||||||
|
|
||||||
memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed);
|
memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed);
|
||||||
rldfree(image->needed);
|
rldfree(image->needed);
|
||||||
|
|
||||||
memset(image, 0xa5, alloc_size);
|
memset(image, 0xa5, size);
|
||||||
rldfree(image);
|
rldfree(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,32 +356,33 @@ destroy_image(image_t *image)
|
|||||||
static void
|
static void
|
||||||
parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
||||||
{
|
{
|
||||||
int i;
|
struct Elf32_Phdr *pheader;
|
||||||
int regcount;
|
int regcount;
|
||||||
struct Elf32_Phdr *pheaders;
|
int i;
|
||||||
|
|
||||||
regcount = 0;
|
regcount = 0;
|
||||||
for (i = 0; i < phnum; i++) {
|
for (i = 0; i < phnum; i++) {
|
||||||
pheaders = (struct Elf32_Phdr *)(buff + i * phentsize);
|
pheader = (struct Elf32_Phdr *)(buff + i * phentsize);
|
||||||
|
|
||||||
switch (pheaders->p_type) {
|
switch (pheader->p_type) {
|
||||||
case PT_NULL:
|
case PT_NULL:
|
||||||
/* NOP header */
|
/* NOP header */
|
||||||
break;
|
break;
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
if (pheaders->p_memsz== pheaders->p_filesz) {
|
if (pheader->p_memsz == pheader->p_filesz) {
|
||||||
/*
|
/*
|
||||||
* everything in one area
|
* everything in one area
|
||||||
*/
|
*/
|
||||||
image->regions[regcount].start = pheaders->p_vaddr;
|
image->regions[regcount].start = pheader->p_vaddr;
|
||||||
image->regions[regcount].size = pheaders->p_memsz;
|
image->regions[regcount].size = pheader->p_memsz;
|
||||||
image->regions[regcount].vmstart= _ROUNDOWN(pheaders->p_vaddr, PAGE_SIZE);
|
image->regions[regcount].vmstart = _ROUNDOWN(pheader->p_vaddr, PAGE_SIZE);
|
||||||
image->regions[regcount].vmsize = _ROUNDUP (pheaders->p_memsz + (pheaders->p_vaddr % PAGE_SIZE), PAGE_SIZE);
|
image->regions[regcount].vmsize = _ROUNDUP(pheader->p_memsz +
|
||||||
image->regions[regcount].fdstart= pheaders->p_offset;
|
(pheader->p_vaddr % PAGE_SIZE), PAGE_SIZE);
|
||||||
image->regions[regcount].fdsize = pheaders->p_filesz;
|
image->regions[regcount].fdstart = pheader->p_offset;
|
||||||
|
image->regions[regcount].fdsize = pheader->p_filesz;
|
||||||
image->regions[regcount].delta = 0;
|
image->regions[regcount].delta = 0;
|
||||||
image->regions[regcount].flags = 0;
|
image->regions[regcount].flags = 0;
|
||||||
if(pheaders->p_flags & PF_W) {
|
if (pheader->p_flags & PF_W) {
|
||||||
// this is a writable segment
|
// this is a writable segment
|
||||||
image->regions[regcount].flags |= RFLAG_RW;
|
image->regions[regcount].flags |= RFLAG_RW;
|
||||||
}
|
}
|
||||||
@@ -350,21 +390,22 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
|||||||
/*
|
/*
|
||||||
* may require splitting
|
* may require splitting
|
||||||
*/
|
*/
|
||||||
unsigned A = pheaders->p_vaddr + pheaders->p_memsz;
|
unsigned A = pheader->p_vaddr + pheader->p_memsz;
|
||||||
unsigned B = pheaders->p_vaddr + pheaders->p_filesz - 1;
|
unsigned B = pheader->p_vaddr + pheader->p_filesz - 1;
|
||||||
|
|
||||||
A = PAGE_BASE(A);
|
A = PAGE_BASE(A);
|
||||||
B = PAGE_BASE(B);
|
B = PAGE_BASE(B);
|
||||||
|
|
||||||
image->regions[regcount].start = pheaders->p_vaddr;
|
image->regions[regcount].start = pheader->p_vaddr;
|
||||||
image->regions[regcount].size = pheaders->p_filesz;
|
image->regions[regcount].size = pheader->p_filesz;
|
||||||
image->regions[regcount].vmstart = _ROUNDOWN(pheaders->p_vaddr, PAGE_SIZE);
|
image->regions[regcount].vmstart = _ROUNDOWN(pheader->p_vaddr, PAGE_SIZE);
|
||||||
image->regions[regcount].vmsize = _ROUNDUP (pheaders->p_filesz + (pheaders->p_vaddr % PAGE_SIZE), PAGE_SIZE);
|
image->regions[regcount].vmsize = _ROUNDUP (pheader->p_filesz +
|
||||||
image->regions[regcount].fdstart = pheaders->p_offset;
|
(pheader->p_vaddr % PAGE_SIZE), PAGE_SIZE);
|
||||||
image->regions[regcount].fdsize = pheaders->p_filesz;
|
image->regions[regcount].fdstart = pheader->p_offset;
|
||||||
|
image->regions[regcount].fdsize = pheader->p_filesz;
|
||||||
image->regions[regcount].delta = 0;
|
image->regions[regcount].delta = 0;
|
||||||
image->regions[regcount].flags = 0;
|
image->regions[regcount].flags = 0;
|
||||||
if (pheaders->p_flags & PF_W) {
|
if (pheader->p_flags & PF_W) {
|
||||||
// this is a writable segment
|
// this is a writable segment
|
||||||
image->regions[regcount].flags |= RFLAG_RW;
|
image->regions[regcount].flags |= RFLAG_RW;
|
||||||
}
|
}
|
||||||
@@ -374,15 +415,15 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
|||||||
* yeah, it requires splitting
|
* yeah, it requires splitting
|
||||||
*/
|
*/
|
||||||
regcount += 1;
|
regcount += 1;
|
||||||
image->regions[regcount].start = pheaders->p_vaddr;
|
image->regions[regcount].start = pheader->p_vaddr;
|
||||||
image->regions[regcount].size = pheaders->p_memsz - pheaders->p_filesz;
|
image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz;
|
||||||
image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize;
|
image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize;
|
||||||
image->regions[regcount].vmsize = _ROUNDUP (pheaders->p_memsz + (pheaders->p_vaddr % PAGE_SIZE), PAGE_SIZE) - image->regions[regcount-1].vmsize;
|
image->regions[regcount].vmsize = _ROUNDUP (pheader->p_memsz + (pheader->p_vaddr % PAGE_SIZE), PAGE_SIZE) - image->regions[regcount-1].vmsize;
|
||||||
image->regions[regcount].fdstart = 0;
|
image->regions[regcount].fdstart = 0;
|
||||||
image->regions[regcount].fdsize = 0;
|
image->regions[regcount].fdsize = 0;
|
||||||
image->regions[regcount].delta = 0;
|
image->regions[regcount].delta = 0;
|
||||||
image->regions[regcount].flags = RFLAG_ANON;
|
image->regions[regcount].flags = RFLAG_ANON;
|
||||||
if (pheaders->p_flags & PF_W) {
|
if (pheader->p_flags & PF_W) {
|
||||||
// this is a writable segment
|
// this is a writable segment
|
||||||
image->regions[regcount].flags |= RFLAG_RW;
|
image->regions[regcount].flags |= RFLAG_RW;
|
||||||
}
|
}
|
||||||
@@ -391,7 +432,7 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
|||||||
regcount += 1;
|
regcount += 1;
|
||||||
break;
|
break;
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
image->dynamic_ptr = pheaders->p_vaddr;
|
image->dynamic_ptr = pheader->p_vaddr;
|
||||||
break;
|
break;
|
||||||
case PT_INTERP:
|
case PT_INTERP:
|
||||||
/* should check here for appropiate interpreter */
|
/* should check here for appropiate interpreter */
|
||||||
@@ -406,7 +447,7 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
|
|||||||
/* we don't use it */
|
/* we don't use it */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FATAL(true, "unhandled pheader type 0x%lx\n", pheaders[i].p_type);
|
FATAL(true, "unhandled pheader type 0x%lx\n", pheader[i].p_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,8 +516,7 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
|
|||||||
addr_specifier,
|
addr_specifier,
|
||||||
image->regions[i].vmsize,
|
image->regions[i].vmsize,
|
||||||
REGION_WIRING_LAZY,
|
REGION_WIRING_LAZY,
|
||||||
LOCK_RW
|
LOCK_RW);
|
||||||
);
|
|
||||||
|
|
||||||
if (image->regions[i].id < 0)
|
if (image->regions[i].id < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -492,8 +532,8 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
|
|||||||
LOCK_RW,
|
LOCK_RW,
|
||||||
REGION_PRIVATE_MAP,
|
REGION_PRIVATE_MAP,
|
||||||
path,
|
path,
|
||||||
_ROUNDOWN(image->regions[i].fdstart, PAGE_SIZE)
|
_ROUNDOWN(image->regions[i].fdstart, PAGE_SIZE));
|
||||||
);
|
|
||||||
if (image->regions[i].id < 0)
|
if (image->regions[i].id < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@@ -561,7 +601,7 @@ parse_dynamic_segment(image_t *image)
|
|||||||
image->num_needed += 1;
|
image->num_needed += 1;
|
||||||
break;
|
break;
|
||||||
case DT_HASH:
|
case DT_HASH:
|
||||||
image->symhash = (unsigned int *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
||||||
break;
|
break;
|
||||||
case DT_STRTAB:
|
case DT_STRTAB:
|
||||||
image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
||||||
@@ -602,21 +642,32 @@ parse_dynamic_segment(image_t *image)
|
|||||||
|
|
||||||
|
|
||||||
static struct Elf32_Sym *
|
static struct Elf32_Sym *
|
||||||
find_symbol_xxx(image_t *img, const char *name)
|
find_symbol(image_t *image, const char *name, int32 type)
|
||||||
{
|
{
|
||||||
unsigned int hash;
|
uint32 hash, i;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (img->dynamic_ptr == NULL)
|
// ToDo: "type" is currently ignored!
|
||||||
|
(void)type;
|
||||||
|
|
||||||
|
if (image->dynamic_ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
hash = elf_hash(name) % HASHTABSIZE(img);
|
hash = elf_hash(name) % HASHTABSIZE(image);
|
||||||
|
|
||||||
for (i = HASHBUCKETS(img)[hash]; i != STN_UNDEF; i = HASHCHAINS(img)[i]) {
|
for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) {
|
||||||
if (img->syms[i].st_shndx != SHN_UNDEF
|
struct Elf32_Sym *symbol = &image->syms[i];
|
||||||
&& ((ELF32_ST_BIND(img->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(img->syms[i].st_info) == STB_WEAK))
|
|
||||||
&& !strcmp(SYMNAME(img, &img->syms[i]), name))
|
if (symbol->st_shndx != SHN_UNDEF
|
||||||
return &img->syms[i];
|
&& ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL)
|
||||||
|
|| (ELF32_ST_BIND(symbol->st_info) == STB_WEAK))
|
||||||
|
&& !strcmp(SYMNAME(image, symbol), name)) {
|
||||||
|
// check if the type matches
|
||||||
|
if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC)
|
||||||
|
|| (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -624,25 +675,20 @@ find_symbol_xxx(image_t *img, const char *name)
|
|||||||
|
|
||||||
|
|
||||||
static struct Elf32_Sym *
|
static struct Elf32_Sym *
|
||||||
find_symbol(image_t **shimg, const char *name)
|
find_symbol_in_loaded_images(image_t **_image, const char *name)
|
||||||
{
|
{
|
||||||
image_t *iter;
|
image_t *image;
|
||||||
unsigned int hash;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (image = gLoadedImages.head; image; image = image->next) {
|
||||||
if (iter->dynamic_ptr == NULL)
|
struct Elf32_Sym *symbol;
|
||||||
|
|
||||||
|
if (image->dynamic_ptr == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hash = elf_hash(name) % HASHTABSIZE(iter);
|
symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY);
|
||||||
|
if (symbol) {
|
||||||
for(i = HASHBUCKETS(iter)[hash]; i != STN_UNDEF; i = HASHCHAINS(iter)[i]) {
|
*_image = image;
|
||||||
if (iter->syms[i].st_shndx!= SHN_UNDEF
|
return symbol;
|
||||||
&& ((ELF32_ST_BIND(iter->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(iter->syms[i].st_info)== STB_WEAK))
|
|
||||||
&& !strcmp(SYMNAME(iter, &iter->syms[i]), name)) {
|
|
||||||
*shimg = iter;
|
|
||||||
return &iter->syms[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,7 +709,7 @@ resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr)
|
|||||||
symname = SYMNAME(image, sym);
|
symname = SYMNAME(image, sym);
|
||||||
|
|
||||||
// it's undefined, must be outside this image, try the other image
|
// it's undefined, must be outside this image, try the other image
|
||||||
sym2 = find_symbol(&shimg, symname);
|
sym2 = find_symbol_in_loaded_images(&shimg, symname);
|
||||||
if (!sym2) {
|
if (!sym2) {
|
||||||
printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname);
|
printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname);
|
||||||
return ERR_ELF_RESOLVING_SYMBOL;
|
return ERR_ELF_RESOLVING_SYMBOL;
|
||||||
@@ -705,12 +751,35 @@ resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr)
|
|||||||
#include "arch/rldreloc.inc"
|
#include "arch/rldreloc.inc"
|
||||||
|
|
||||||
|
|
||||||
static image_t *
|
static void
|
||||||
load_container(char const *path, char const *name, bool fixed)
|
register_image(image_t *image, const char *path)
|
||||||
{
|
{
|
||||||
|
image_info info;
|
||||||
|
|
||||||
|
// ToDo: set these correctly
|
||||||
|
info.id = 0;
|
||||||
|
info.type = image->type;
|
||||||
|
info.sequence = 0;
|
||||||
|
info.init_order = 0;
|
||||||
|
info.init_routine = (void *)image->entry_point;
|
||||||
|
info.term_routine = (void *)image->entry_point;
|
||||||
|
info.device = 0;
|
||||||
|
info.node = 0;
|
||||||
|
strlcpy(info.name, path, sizeof(info.name));
|
||||||
|
info.text = NULL;
|
||||||
|
info.text_size = 0;
|
||||||
|
info.data = NULL;
|
||||||
|
info.data_size = 0;
|
||||||
|
image->id = sys_register_image(&info, sizeof(image_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static image_t *
|
||||||
|
load_container(char const *path, char const *name, image_type type)
|
||||||
|
{
|
||||||
|
int32 pheaderSize, sheaderSize;
|
||||||
int fd;
|
int fd;
|
||||||
int len;
|
int len;
|
||||||
int ph_len;
|
|
||||||
char ph_buff[4096];
|
char ph_buff[4096];
|
||||||
int num_regions;
|
int num_regions;
|
||||||
bool map_success;
|
bool map_success;
|
||||||
@@ -720,9 +789,10 @@ load_container(char const *path, char const *name, bool fixed)
|
|||||||
|
|
||||||
struct Elf32_Ehdr eheader;
|
struct Elf32_Ehdr eheader;
|
||||||
|
|
||||||
|
// have we already loaded that image?
|
||||||
found = find_image(name);
|
found = find_image(name);
|
||||||
if (found) {
|
if (found) {
|
||||||
found->refcount += 1;
|
atomic_add(&found->ref_count, 1);
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,12 +802,14 @@ load_container(char const *path, char const *name, bool fixed)
|
|||||||
len = sys_read(fd, 0, &eheader, sizeof(eheader));
|
len = sys_read(fd, 0, &eheader, sizeof(eheader));
|
||||||
FATAL((len != sizeof(eheader)), "troubles reading ELF header\n");
|
FATAL((len != sizeof(eheader)), "troubles reading ELF header\n");
|
||||||
|
|
||||||
ph_len = parse_eheader(&eheader);
|
if (parse_elf_header(&eheader, &pheaderSize, &sheaderSize) < B_OK) {
|
||||||
FATAL((ph_len <= 0), "incorrect ELF header\n");
|
FATAL(1, "incorrect ELF header\n");
|
||||||
FATAL((ph_len > (int)sizeof(ph_buff)), "cannot handle Program headers bigger than %lu\n", (long unsigned)sizeof(ph_buff));
|
}
|
||||||
|
// ToDo: what to do about this restriction??
|
||||||
|
FATAL((pheaderSize > (int)sizeof(ph_buff)), "cannot handle Program headers bigger than %lu\n", (long unsigned)sizeof(ph_buff));
|
||||||
|
|
||||||
len = sys_read(fd, eheader.e_phoff, ph_buff, ph_len);
|
len = sys_read(fd, eheader.e_phoff, ph_buff, pheaderSize);
|
||||||
FATAL((len != ph_len), "troubles reading Program headers\n");
|
FATAL((len != pheaderSize), "troubles reading Program headers\n");
|
||||||
|
|
||||||
num_regions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize);
|
num_regions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize);
|
||||||
FATAL((num_regions <= 0), "troubles parsing Program headers, num_regions= %d\n", num_regions);
|
FATAL((num_regions <= 0), "troubles parsing Program headers, num_regions= %d\n", num_regions);
|
||||||
@@ -748,46 +820,45 @@ load_container(char const *path, char const *name, bool fixed)
|
|||||||
parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize);
|
parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize);
|
||||||
FATAL(!assert_dynamic_loadable(image), "dynamic segment must be loadable (implementation restriction)\n");
|
FATAL(!assert_dynamic_loadable(image), "dynamic segment must be loadable (implementation restriction)\n");
|
||||||
|
|
||||||
map_success = map_image(fd, path, image, fixed);
|
map_success = map_image(fd, path, image, type == B_APP_IMAGE);
|
||||||
FATAL(!map_success, "troubles reading image\n");
|
FATAL(!map_success, "troubles reading image\n");
|
||||||
|
|
||||||
dynamic_success = parse_dynamic_segment(image);
|
dynamic_success = parse_dynamic_segment(image);
|
||||||
FATAL(!dynamic_success, "troubles handling dynamic section\n");
|
FATAL(!dynamic_success, "troubles handling dynamic section\n");
|
||||||
|
|
||||||
image->entry_point = eheader.e_entry + image->regions[0].delta;
|
image->entry_point = eheader.e_entry + image->regions[0].delta;
|
||||||
|
image->type = type;
|
||||||
|
register_image(image, path);
|
||||||
|
|
||||||
sys_close(fd);
|
sys_close(fd);
|
||||||
|
|
||||||
enqueue_image(&loaded_images, image);
|
enqueue_image(&gLoadedImages, image);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_dependencies(image_t *img)
|
load_dependencies(image_t *image)
|
||||||
{
|
{
|
||||||
unsigned i;
|
struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
|
||||||
unsigned j;
|
|
||||||
|
|
||||||
struct Elf32_Dyn *d;
|
|
||||||
addr needed_offset;
|
addr needed_offset;
|
||||||
char path[256];
|
char path[256];
|
||||||
|
uint32 i, j;
|
||||||
|
|
||||||
d = (struct Elf32_Dyn *)img->dynamic_ptr;
|
|
||||||
if (!d)
|
if (!d)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
img->needed = rldalloc(img->num_needed*sizeof(image_t*));
|
image->needed = rldalloc(image->num_needed * sizeof(image_t *));
|
||||||
FATAL((!img->needed), "failed to allocate needed struct\n");
|
FATAL((!image->needed), "failed to allocate needed struct\n");
|
||||||
memset(img->needed, 0, img->num_needed*sizeof(image_t*));
|
memset(image->needed, 0, image->num_needed * sizeof(image_t *));
|
||||||
|
|
||||||
for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
|
for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
|
||||||
switch (d[i].d_tag) {
|
switch (d[i].d_tag) {
|
||||||
case DT_NEEDED:
|
case DT_NEEDED:
|
||||||
needed_offset = d[i].d_un.d_ptr;
|
needed_offset = d[i].d_un.d_ptr;
|
||||||
sprintf(path, "/boot/lib/%s", STRING(img, needed_offset));
|
sprintf(path, "/boot/lib/%s", STRING(image, needed_offset));
|
||||||
img->needed[j]= load_container(path, STRING(img, needed_offset), false);
|
image->needed[j] = load_container(path, STRING(image, needed_offset), B_LIBRARY_IMAGE);
|
||||||
j += 1;
|
j += 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -799,81 +870,84 @@ load_dependencies(image_t *img)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FATAL((j!= img->num_needed), "Internal error at load_dependencies()");
|
FATAL((j != image->num_needed), "Internal error at load_dependencies()");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned
|
static uint32
|
||||||
topological_sort(image_t *img, unsigned slot, image_t **init_list)
|
topological_sort(image_t *image, uint32 slot, image_t **initList)
|
||||||
{
|
{
|
||||||
unsigned i;
|
uint32 i;
|
||||||
|
|
||||||
img->flags|= RFLAG_SORTED; /* make sure we don't visit this one */
|
image->flags |= RFLAG_SORTED; /* make sure we don't visit this one */
|
||||||
for(i= 0; i< img->num_needed; i++) {
|
for (i = 0; i < image->num_needed; i++) {
|
||||||
if(!(img->needed[i]->flags & RFLAG_SORTED)) {
|
if (!(image->needed[i]->flags & RFLAG_SORTED))
|
||||||
slot= topological_sort(img->needed[i], slot, init_list);
|
slot = topological_sort(image->needed[i], slot, initList);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_list[slot]= img;
|
initList[slot] = image;
|
||||||
return slot + 1;
|
return slot + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_dependencies(image_t *img, bool init_head)
|
init_dependencies(image_t *image, bool initHead)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
unsigned slot;
|
unsigned slot;
|
||||||
image_t **init_list;
|
image_t **initList;
|
||||||
|
|
||||||
init_list = rldalloc(loaded_image_count*sizeof(image_t*));
|
initList = rldalloc(gLoadedImageCount * sizeof(image_t *));
|
||||||
FATAL((!init_list), "memory shortage in init_dependencies()");
|
FATAL((!initList), "memory shortage in init_dependencies()");
|
||||||
memset(init_list, 0, loaded_image_count*sizeof(image_t*));
|
memset(initList, 0, gLoadedImageCount * sizeof(image_t *));
|
||||||
|
|
||||||
img->flags |= RFLAG_SORTED; /* make sure we don't visit this one */
|
image->flags |= RFLAG_SORTED; /* make sure we don't visit this one */
|
||||||
slot = 0;
|
slot = 0;
|
||||||
for (i = 0; i < img->num_needed; i++) {
|
for (i = 0; i < image->num_needed; i++) {
|
||||||
if (!(img->needed[i]->flags & RFLAG_SORTED))
|
if (!(image->needed[i]->flags & RFLAG_SORTED))
|
||||||
slot = topological_sort(img->needed[i], slot, init_list);
|
slot = topological_sort(image->needed[i], slot, initList);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_head) {
|
if (initHead) {
|
||||||
init_list[slot] = img;
|
initList[slot] = image;
|
||||||
slot += 1;
|
slot += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < slot; i++) {
|
for (i = 0; i < slot; i++) {
|
||||||
addr _initf = init_list[i]->entry_point;
|
addr _initf = initList[i]->entry_point;
|
||||||
libinit_f *initf = (libinit_f *)(_initf);
|
libinit_f *initf = (libinit_f *)(_initf);
|
||||||
|
|
||||||
if (initf)
|
if (initf)
|
||||||
initf(init_list[i]->imageid, uspa);
|
initf(initList[i]->id, gProgramArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
rldfree(init_list);
|
rldfree(initList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
put_image(image_t *img)
|
put_image(image_t *image)
|
||||||
{
|
{
|
||||||
img->refcount -= 1;
|
// If all references to the image are gone, add it to the disposable list
|
||||||
if (img->refcount == 0) {
|
// and remove all dependencies
|
||||||
|
|
||||||
|
if (atomic_add(&image->ref_count, -1) == 1) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
dequeue_image(&loaded_images, img);
|
dequeue_image(&gLoadedImages, image);
|
||||||
enqueue_image(&disposable_images, img);
|
enqueue_image(&gDisposableImages, image);
|
||||||
|
|
||||||
for(i = 0; i < img->num_needed; i++) {
|
for (i = 0; i < image->num_needed; i++) {
|
||||||
put_image(img->needed[i]);
|
put_image(image->needed[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exported functions:
|
* exported functions:
|
||||||
*
|
*
|
||||||
@@ -886,131 +960,207 @@ put_image(image_t *img)
|
|||||||
* + dynamic_symbol()
|
* + dynamic_symbol()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dynmodule_id
|
image_id
|
||||||
load_program(char const *path, void **entry)
|
load_program(char const *path, void **_entry)
|
||||||
{
|
{
|
||||||
image_t *image;
|
image_t *image;
|
||||||
image_t *iter;
|
image_t *iter;
|
||||||
|
|
||||||
image = load_container(path, NEWOS_MAGIC_APPNAME, true);
|
rld_lock();
|
||||||
|
// for now, just do stupid simple global locking
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
image = load_container(path, MAGIC_APP_NAME, B_APP_IMAGE);
|
||||||
|
|
||||||
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
load_dependencies(iter);
|
load_dependencies(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
bool relocate_success;
|
bool relocate_success;
|
||||||
|
|
||||||
relocate_success = relocate_image(iter);
|
relocate_success = relocate_image(iter);
|
||||||
FATAL(!relocate_success, "troubles relocating\n");
|
FATAL(!relocate_success, "troubles relocating\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
init_dependencies(loaded_images.head, false);
|
init_dependencies(gLoadedImages.head, false);
|
||||||
|
|
||||||
*entry = (void*)(image->entry_point);
|
*_entry = (void *)(image->entry_point);
|
||||||
return image->imageid;
|
|
||||||
|
rld_unlock();
|
||||||
|
return image->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dynmodule_id
|
image_id
|
||||||
load_library(char const *path)
|
load_library(char const *path, uint32 flags)
|
||||||
{
|
{
|
||||||
image_t *image;
|
image_t *image;
|
||||||
image_t *iter;
|
image_t *iter;
|
||||||
|
|
||||||
|
// ToDo: implement flags
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
|
rld_lock();
|
||||||
|
// for now, just do stupid simple global locking
|
||||||
|
|
||||||
|
// have we already loaded this library?
|
||||||
|
// Checking it at this stage saves loading its dependencies again
|
||||||
|
// ToDo: don't we have to increment the reference counter of the dependencies??
|
||||||
image = find_image(path);
|
image = find_image(path);
|
||||||
if (image) {
|
if (image) {
|
||||||
image->refcount += 1;
|
atomic_add(&image->ref_count, 1);
|
||||||
return image->imageid;
|
rld_unlock();
|
||||||
|
return image->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
image = load_container(path, path, false);
|
image = load_container(path, path, B_LIBRARY_IMAGE);
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
load_dependencies(iter);
|
load_dependencies(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
bool relocate_success;
|
bool relocateSuccess;
|
||||||
|
|
||||||
relocate_success = relocate_image(iter);
|
relocateSuccess = relocate_image(iter);
|
||||||
FATAL(!relocate_success, "troubles relocating\n");
|
FATAL(!relocateSuccess, "troubles relocating\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
init_dependencies(image, true);
|
init_dependencies(image, true);
|
||||||
|
|
||||||
return image->imageid;
|
rld_unlock();
|
||||||
|
return image->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dynmodule_id
|
status_t
|
||||||
unload_library(dynmodule_id imid)
|
unload_library(image_id imageID)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
image_t *iter;
|
image_t *iter;
|
||||||
|
|
||||||
|
rld_lock();
|
||||||
|
// for now, just do stupid simple global locking
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we only check images that have been already initialized
|
* we only check images that have been already initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
for (iter = gLoadedImages.head; iter; iter = iter->next) {
|
||||||
if (iter->imageid == imid) {
|
if (iter->id == imageID) {
|
||||||
/*
|
/*
|
||||||
* do the unloading
|
* do the unloading
|
||||||
*/
|
*/
|
||||||
put_image(iter);
|
put_image(iter);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = iter ? 0 : -1;
|
retval = iter ? B_OK : -1;
|
||||||
|
|
||||||
while ((iter = disposable_images.head) != NULL) {
|
while ((iter = gDisposableImages.head) != NULL) {
|
||||||
// call image fini here...
|
// call image fini here...
|
||||||
|
|
||||||
dequeue_image(&disposable_images, iter);
|
dequeue_image(&gDisposableImages, iter);
|
||||||
unmap_image(iter);
|
unmap_image(iter);
|
||||||
|
|
||||||
destroy_image(iter);
|
delete_image(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rld_unlock();
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
status_t
|
||||||
dynamic_symbol(dynmodule_id imid, char const *symname)
|
get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength,
|
||||||
|
int32 *_type, void **_location)
|
||||||
{
|
{
|
||||||
image_t *iter;
|
int32 count = 0, i, j;
|
||||||
|
image_t *image;
|
||||||
|
|
||||||
/*
|
rld_lock();
|
||||||
* we only check images that have been already initialized
|
|
||||||
*/
|
|
||||||
for (iter = loaded_images.head; iter; iter = iter->next) {
|
|
||||||
struct Elf32_Sym *sym;
|
|
||||||
|
|
||||||
if (iter->imageid != imid)
|
// get the image from those who have been already initialized
|
||||||
continue;
|
image = find_loaded_image_by_id(imageID);
|
||||||
|
if (image == NULL) {
|
||||||
sym = find_symbol_xxx(iter, symname);
|
rld_unlock();
|
||||||
if (sym)
|
return B_BAD_IMAGE_ID;
|
||||||
return (void*)(sym->st_value + iter->regions[0].delta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
// iterate through all the hash buckets until we've found the one
|
||||||
|
for (i = 0; i < HASHTABSIZE(image); i++) {
|
||||||
|
for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
|
||||||
|
struct Elf32_Sym *symbol = &image->syms[i];
|
||||||
|
|
||||||
|
if (count == num) {
|
||||||
|
strlcpy(nameBuffer, SYMNAME(image, symbol), *_nameLength);
|
||||||
|
*_nameLength = strlen(SYMNAME(image, symbol));
|
||||||
|
|
||||||
|
// ToDo: check with the return types of that BeOS function
|
||||||
|
if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
|
||||||
|
*_type = B_SYMBOL_TYPE_TEXT;
|
||||||
|
else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
|
||||||
|
*_type = B_SYMBOL_TYPE_DATA;
|
||||||
|
else
|
||||||
|
*_type = B_SYMBOL_TYPE_ANY;
|
||||||
|
|
||||||
|
*_location = (void *)(symbol->st_value + image->regions[0].delta);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
rld_unlock();
|
||||||
|
|
||||||
|
if (num != count)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location)
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
image_t *image;
|
||||||
|
|
||||||
|
rld_lock();
|
||||||
|
// for now, just do stupid simple global locking
|
||||||
|
|
||||||
|
// get the image from those who have been already initialized
|
||||||
|
image = find_loaded_image_by_id(imageID);
|
||||||
|
if (image != NULL) {
|
||||||
|
struct Elf32_Sym *symbol;
|
||||||
|
|
||||||
|
// get the symbol in the image
|
||||||
|
symbol = find_symbol(image, symbolName, symbolType);
|
||||||
|
if (symbol)
|
||||||
|
*_location = (void *)(symbol->st_value + image->regions[0].delta);
|
||||||
|
else
|
||||||
|
status = B_ENTRY_NOT_FOUND;
|
||||||
|
} else
|
||||||
|
status = B_BAD_IMAGE_ID;
|
||||||
|
|
||||||
|
rld_unlock();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* init routine, just get hold of the uspa args
|
* init routine, just get hold of the user-space program args
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
rldelf_init(struct uspace_prog_args_t const *_uspa)
|
rldelf_init(struct uspace_program_args const *_args)
|
||||||
{
|
{
|
||||||
uspa = _uspa;
|
gProgramArgs = _args;
|
||||||
|
|
||||||
rld_sem = create_sem(1, "rld_lock\n");
|
rld_sem = create_sem(1, "rld_lock\n");
|
||||||
|
rld_sem_owner = -1;
|
||||||
|
rld_sem_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user