Incorporated the change 1619 into our tree. Cleaned up the source.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@958 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2002-09-02 14:49:20 +00:00
parent 5813c3dff5
commit 3f8b94d3cd

View File

@ -127,24 +127,22 @@ static struct uspace_prog_args_t const *uspa;
static static void
void
enqueue_image(image_queue_t *queue, image_t *img) enqueue_image(image_queue_t *queue, image_t *img)
{ {
img->next = 0; img->next = 0;
img->prev = queue->tail; img->prev = queue->tail;
if(queue->tail) { if (queue->tail)
queue->tail->next= img; queue->tail->next= img;
}
queue->tail = img; queue->tail = img;
if(!queue->head) { if (!queue->head)
queue->head= img; queue->head= img;
} }
}
static
void static void
dequeue_image(image_queue_t *queue, image_t *img) dequeue_image(image_queue_t *queue, image_t *img)
{ {
if(img->next) { if(img->next) {
@ -163,8 +161,8 @@ dequeue_image(image_queue_t *queue, image_t *img)
img->next= 0; img->next= 0;
} }
static
unsigned long static unsigned long
elf_hash(const unsigned char *name) elf_hash(const unsigned char *name)
{ {
unsigned long hash = 0; unsigned long hash = 0;
@ -180,33 +178,27 @@ elf_hash(const unsigned char *name)
return hash; return hash;
} }
static
image_t * static image_t *
find_image(char const *name) find_image(char const *name)
{ {
image_t *iter; image_t *iter;
iter= loaded_images.head; for (iter = loaded_images.head; iter; iter = iter->next) {
while(iter) { if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
if(strncmp(iter->name, name, sizeof(iter->name)) == 0) {
return iter; return iter;
} }
iter= iter->next;
}
iter= loading_images.head; for (iter = loading_images.head; iter; iter = iter->next) {
while(iter) { if (strncmp(iter->name, name, sizeof(iter->name)) == 0)
if(strncmp(iter->name, name, sizeof(iter->name)) == 0) {
return iter; return iter;
} }
iter= iter->next;
return NULL;
} }
return 0;
}
static static int
int
parse_eheader(struct Elf32_Ehdr *eheader) parse_eheader(struct Elf32_Ehdr *eheader)
{ {
if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
@ -224,15 +216,14 @@ parse_eheader(struct Elf32_Ehdr *eheader)
return eheader->e_phentsize*eheader->e_phnum; return eheader->e_phentsize*eheader->e_phnum;
} }
static
int static int
count_regions(char const *buff, int phnum, int phentsize) count_regions(char const *buff, int phnum, int phentsize)
{ {
int i; int i;
int retval; int retval = 0;
struct Elf32_Phdr *pheaders; struct Elf32_Phdr *pheaders;
retval= 0;
for (i = 0; i < phnum; i++) { for (i = 0; i < phnum; i++) {
pheaders = (struct Elf32_Phdr *)(buff + i * phentsize); pheaders = (struct Elf32_Phdr *)(buff + i * phentsize);
@ -244,15 +235,14 @@ count_regions(char const *buff, int phnum, int phentsize)
retval += 1; retval += 1;
if (pheaders->p_memsz!= pheaders->p_filesz) { if (pheaders->p_memsz!= pheaders->p_filesz) {
unsigned A = pheaders->p_vaddr + pheaders->p_memsz; unsigned A = pheaders->p_vaddr + pheaders->p_memsz;
unsigned B= pheaders->p_vaddr+pheaders->p_filesz; unsigned B = pheaders->p_vaddr + pheaders->p_filesz - 1;
A = PAGE_BASE(A); A = PAGE_BASE(A);
B = PAGE_BASE(B); B = PAGE_BASE(B);
if(A!= B) { if (A != B)
retval += 1; retval += 1;
} }
}
break; break;
case PT_DYNAMIC: case PT_DYNAMIC:
/* will be handled at some other place */ /* will be handled at some other place */
@ -279,15 +269,14 @@ count_regions(char const *buff, int phnum, int phentsize)
} }
/* /*
* create_image() & destroy_image() * create_image() & destroy_image()
* *
* Create and destroy image_t structures. The destroyer makes sure that the * Create and destroy image_t structures. The destroyer makes sure that the
* memory buffers are full of garbage before freeing. * memory buffers are full of garbage before freeing.
*/ */
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; image_t *retval;
@ -309,8 +298,8 @@ create_image(char const *name, int num_regions)
return retval; return retval;
} }
static
void static void
destroy_image(image_t *image) destroy_image(image_t *image)
{ {
size_t alloc_size; size_t alloc_size;
@ -325,9 +314,7 @@ 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; int i;
@ -364,7 +351,7 @@ 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 = pheaders->p_vaddr + pheaders->p_memsz;
unsigned B= pheaders->p_vaddr+pheaders->p_filesz; unsigned B = pheaders->p_vaddr + pheaders->p_filesz - 1;
A = PAGE_BASE(A); A = PAGE_BASE(A);
B = PAGE_BASE(B); B = PAGE_BASE(B);
@ -425,29 +412,26 @@ parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
} }
} }
static
bool static bool
assert_dynamic_loadable(image_t *image) assert_dynamic_loadable(image_t *image)
{ {
unsigned i; unsigned i;
if(!image->dynamic_ptr) { if (!image->dynamic_ptr)
return true; return true;
}
for (i = 0; i < image->num_regions; i++) { for (i = 0; i < image->num_regions; i++) {
if(image->dynamic_ptr>= image->regions[i].start) { if (image->dynamic_ptr >= image->regions[i].start
if(image->dynamic_ptr< image->regions[i].start+image->regions[i].size) { && image->dynamic_ptr < image->regions[i].start + image->regions[i].size)
return true; return true;
} }
}
}
return false; return false;
} }
static
bool static bool
map_image(int fd, char const *path, image_t *image, bool fixed) map_image(int fd, char const *path, image_t *image, bool fixed)
{ {
unsigned i; unsigned i;
@ -459,13 +443,8 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
addr load_address; addr load_address;
unsigned addr_specifier; unsigned addr_specifier;
sprintf( sprintf(region_name, "%s:seg_%d(%s)",
region_name, path, i, (image->regions[i].flags & RFLAG_RW) ? "RW" : "RO");
"%s:seg_%d(%s)",
path,
i,
(image->regions[i].flags&RFLAG_RW)?"RW":"RO"
);
if (image->dynamic_ptr && !fixed) { if (image->dynamic_ptr && !fixed) {
/* /*
@ -499,9 +478,9 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
LOCK_RW LOCK_RW
); );
if(image->regions[i].id < 0) { if (image->regions[i].id < 0)
goto error; goto error;
}
image->regions[i].delta = load_address - image->regions[i].vmstart; image->regions[i].delta = load_address - image->regions[i].vmstart;
image->regions[i].vmstart = load_address; image->regions[i].vmstart = load_address;
} else { } else {
@ -515,9 +494,9 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
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;
}
image->regions[i].delta = load_address - image->regions[i].vmstart; image->regions[i].delta = load_address - image->regions[i].vmstart;
image->regions[i].vmstart = load_address; image->regions[i].vmstart = load_address;
@ -528,12 +507,10 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
unsigned start_clearing; unsigned start_clearing;
unsigned to_clear; unsigned to_clear;
start_clearing= start_clearing = image->regions[i].vmstart
image->regions[i].vmstart
+ PAGE_OFFS(image->regions[i].start) + PAGE_OFFS(image->regions[i].start)
+ image->regions[i].size; + image->regions[i].size;
to_clear= to_clear = image->regions[i].vmsize
image->regions[i].vmsize
- PAGE_OFFS(image->regions[i].start) - PAGE_OFFS(image->regions[i].start)
- image->regions[i].size; - image->regions[i].size;
memset((void*)start_clearing, 0, to_clear); memset((void*)start_clearing, 0, to_clear);
@ -541,9 +518,8 @@ map_image(int fd, char const *path, image_t *image, bool fixed)
} }
} }
if(image->dynamic_ptr) { if (image->dynamic_ptr)
image->dynamic_ptr += image->regions[0].delta; image->dynamic_ptr += image->regions[0].delta;
}
return true; return true;
@ -551,8 +527,8 @@ error:
return false; return false;
} }
static
void static void
unmap_image(image_t *image) unmap_image(image_t *image)
{ {
unsigned i; unsigned i;
@ -564,8 +540,8 @@ unmap_image(image_t *image)
} }
} }
static
bool static bool
parse_dynamic_segment(image_t *image) parse_dynamic_segment(image_t *image)
{ {
struct Elf32_Dyn *d; struct Elf32_Dyn *d;
@ -576,9 +552,8 @@ parse_dynamic_segment(image_t *image)
image->strtab = 0; image->strtab = 0;
d = (struct Elf32_Dyn *)image->dynamic_ptr; d = (struct Elf32_Dyn *)image->dynamic_ptr;
if(!d) { if (!d)
return true; return true;
}
for (i = 0; d[i].d_tag != DT_NULL; i++) { for (i = 0; d[i].d_tag != DT_NULL; i++) {
switch (d[i].d_tag) { switch (d[i].d_tag) {
@ -619,68 +594,63 @@ parse_dynamic_segment(image_t *image)
} }
// lets make sure we found all the required sections // lets make sure we found all the required sections
if(!image->symhash || !image->syms || !image->strtab) { if (!image->symhash || !image->syms || !image->strtab)
return false; return false;
}
return true; return true;
} }
static
struct Elf32_Sym * static struct Elf32_Sym *
find_symbol_xxx(image_t *img, const char *name) find_symbol_xxx(image_t *img, const char *name)
{ {
unsigned int hash; unsigned int hash;
unsigned int i; unsigned int i;
if(img->dynamic_ptr) { if (img->dynamic_ptr == NULL)
return NULL;
hash = elf_hash(name) % HASHTABSIZE(img); hash = elf_hash(name) % HASHTABSIZE(img);
for (i = HASHBUCKETS(img)[hash]; i != STN_UNDEF; i = HASHCHAINS(img)[i]) { for (i = HASHBUCKETS(img)[hash]; i != STN_UNDEF; i = HASHCHAINS(img)[i]) {
if(img->syms[i].st_shndx!= SHN_UNDEF) { if (img->syms[i].st_shndx != SHN_UNDEF
if((ELF32_ST_BIND(img->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(img->syms[i].st_info)== STB_WEAK)) { && ((ELF32_ST_BIND(img->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(img->syms[i].st_info) == STB_WEAK))
if(!strcmp(SYMNAME(img, &img->syms[i]), name)) { && !strcmp(SYMNAME(img, &img->syms[i]), name))
return &img->syms[i]; return &img->syms[i];
} }
}
}
}
}
return NULL; return NULL;
} }
static
struct Elf32_Sym * static struct Elf32_Sym *
find_symbol(image_t **shimg, const char *name) find_symbol(image_t **shimg, const char *name)
{ {
image_t *iter; image_t *iter;
unsigned int hash; unsigned int hash;
unsigned int i; unsigned int i;
iter= loaded_images.head; for (iter = loaded_images.head; iter; iter = iter->next) {
while(iter) { if (iter->dynamic_ptr == NULL)
if(iter->dynamic_ptr) { continue;
hash = elf_hash(name) % HASHTABSIZE(iter); hash = elf_hash(name) % HASHTABSIZE(iter);
for(i = HASHBUCKETS(iter)[hash]; i != STN_UNDEF; i = HASHCHAINS(iter)[i]) { for(i = HASHBUCKETS(iter)[hash]; i != STN_UNDEF; i = HASHCHAINS(iter)[i]) {
if(iter->syms[i].st_shndx!= SHN_UNDEF) { if (iter->syms[i].st_shndx!= SHN_UNDEF
if((ELF32_ST_BIND(iter->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(iter->syms[i].st_info)== STB_WEAK)) { && ((ELF32_ST_BIND(iter->syms[i].st_info)== STB_GLOBAL) || (ELF32_ST_BIND(iter->syms[i].st_info)== STB_WEAK))
if(!strcmp(SYMNAME(iter, &iter->syms[i]), name)) { && !strcmp(SYMNAME(iter, &iter->syms[i]), name)) {
*shimg = iter; *shimg = iter;
return &iter->syms[i]; return &iter->syms[i];
} }
} }
} }
}
}
iter= iter->next;
}
return NULL; return NULL;
} }
static
int static int
resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr) resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr)
{ {
struct Elf32_Sym *sym2; struct Elf32_Sym *sym2;
@ -700,27 +670,30 @@ resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr)
} }
// make sure they're the same type // make sure they're the same type
if(ELF32_ST_TYPE(sym->st_info)!= STT_NOTYPE) { if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE
if(ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) { && ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) {
printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname); printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname);
return ERR_ELF_RESOLVING_SYMBOL; return ERR_ELF_RESOLVING_SYMBOL;
} }
}
if(ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL
&& ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname); printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname);
return ERR_ELF_RESOLVING_SYMBOL; return ERR_ELF_RESOLVING_SYMBOL;
} }
*sym_addr = sym2->st_value + shimg->regions[0].delta; *sym_addr = sym2->st_value + shimg->regions[0].delta;
return B_NO_ERROR; return B_NO_ERROR;
case SHN_ABS: case SHN_ABS:
*sym_addr = sym->st_value + image->regions[0].delta; *sym_addr = sym->st_value + image->regions[0].delta;
return B_NO_ERROR; return B_NO_ERROR;
case SHN_COMMON: case SHN_COMMON:
// XXX finish this // XXX finish this
printf("elf_resolve_symbol: COMMON symbol, finish me!\n"); printf("elf_resolve_symbol: COMMON symbol, finish me!\n");
return ERR_NOT_IMPLEMENTED_YET; return ERR_NOT_IMPLEMENTED_YET;
default: default:
// standard symbol // standard symbol
*sym_addr = sym->st_value + image->regions[0].delta; *sym_addr = sym->st_value + image->regions[0].delta;
@ -732,8 +705,7 @@ resolve_symbol(image_t *image, struct Elf32_Sym *sym, addr *sym_addr)
#include "arch/rldreloc.inc" #include "arch/rldreloc.inc"
static static image_t *
image_t *
load_container(char const *path, char const *name, bool fixed) load_container(char const *path, char const *name, bool fixed)
{ {
int fd; int fd;
@ -792,8 +764,7 @@ load_container(char const *path, char const *name, bool fixed)
} }
static static void
void
load_dependencies(image_t *img) load_dependencies(image_t *img)
{ {
unsigned i; unsigned i;
@ -833,8 +804,8 @@ load_dependencies(image_t *img)
return; return;
} }
static
unsigned static unsigned
topological_sort(image_t *img, unsigned slot, image_t **init_list) topological_sort(image_t *img, unsigned slot, image_t **init_list)
{ {
unsigned i; unsigned i;
@ -850,8 +821,8 @@ topological_sort(image_t *img, unsigned slot, image_t **init_list)
return slot+1; return slot+1;
} }
static
void static void
init_dependencies(image_t *img, bool init_head) init_dependencies(image_t *img, bool init_head)
{ {
unsigned i; unsigned i;
@ -865,10 +836,9 @@ init_dependencies(image_t *img, bool init_head)
img->flags |= RFLAG_SORTED; /* make sure we don't visit this one */ img->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 < img->num_needed; i++) {
if(!(img->needed[i]->flags & RFLAG_SORTED)) { if (!(img->needed[i]->flags & RFLAG_SORTED))
slot = topological_sort(img->needed[i], slot, init_list); slot = topological_sort(img->needed[i], slot, init_list);
} }
}
if (init_head) { if (init_head) {
init_list[slot] = img; init_list[slot] = img;
@ -879,17 +849,15 @@ init_dependencies(image_t *img, bool init_head)
addr _initf = init_list[i]->entry_point; addr _initf = init_list[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(init_list[i]->imageid, uspa);
} }
}
rldfree(init_list); rldfree(init_list);
} }
static static void
void
put_image(image_t *img) put_image(image_t *img)
{ {
img->refcount -= 1; img->refcount -= 1;
@ -917,31 +885,25 @@ put_image(image_t *img)
* + unload_addon() * + unload_addon()
* + dynamic_symbol() * + dynamic_symbol()
*/ */
dynmodule_id dynmodule_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); image = load_container(path, NEWOS_MAGIC_APPNAME, true);
iter= loaded_images.head; for (iter = loaded_images.head; iter; iter = iter->next) {
while(iter) {
load_dependencies(iter); load_dependencies(iter);
}
iter= iter->next; for (iter = loaded_images.head; iter; iter = iter->next) {
};
iter= loaded_images.head;
while(iter) {
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");
}
iter= iter->next;
};
init_dependencies(loaded_images.head, false); init_dependencies(loaded_images.head, false);
@ -949,13 +911,13 @@ load_program(char const *path, void **entry)
return image->imageid; return image->imageid;
} }
dynmodule_id dynmodule_id
load_library(char const *path) load_library(char const *path)
{ {
image_t *image; image_t *image;
image_t *iter; image_t *iter;
image = find_image(path); image = find_image(path);
if (image) { if (image) {
image->refcount += 1; image->refcount += 1;
@ -964,28 +926,23 @@ load_library(char const *path)
image = load_container(path, path, false); image = load_container(path, path, false);
iter= loaded_images.head; for (iter = loaded_images.head; iter; iter = iter->next) {
while(iter) {
load_dependencies(iter); load_dependencies(iter);
}
iter= iter->next; for (iter = loaded_images.head; iter; iter = iter->next) {
};
iter= loaded_images.head;
while(iter) {
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");
}
iter= iter->next;
};
init_dependencies(image, true); init_dependencies(image, true);
return image->imageid; return image->imageid;
} }
dynmodule_id dynmodule_id
unload_library(dynmodule_id imid) unload_library(dynmodule_id imid)
{ {
@ -995,8 +952,8 @@ unload_library(dynmodule_id imid)
/* /*
* we only check images that have been already initialized * we only check images that have been already initialized
*/ */
iter= loaded_images.head;
while(iter) { for (iter = loaded_images.head; iter; iter = iter->next) {
if (iter->imageid == imid) { if (iter->imageid == imid) {
/* /*
* do the unloading * do the unloading
@ -1005,31 +962,23 @@ unload_library(dynmodule_id imid)
break; break;
} }
iter= iter->next;
} }
if(iter) { retval = iter ? 0 : -1;
retval= 0;
} else {
retval= -1;
}
iter= disposable_images.head; while ((iter = disposable_images.head) != NULL) {
while(iter) {
// call image fini here... // call image fini here...
dequeue_image(&disposable_images, iter); dequeue_image(&disposable_images, iter);
unmap_image(iter); unmap_image(iter);
destroy_image(iter); destroy_image(iter);
iter= disposable_images.head;
} }
return retval; return retval;
} }
void * void *
dynamic_symbol(dynmodule_id imid, char const *symname) dynamic_symbol(dynmodule_id imid, char const *symname)
{ {
@ -1038,25 +987,25 @@ dynamic_symbol(dynmodule_id imid, char const *symname)
/* /*
* we only check images that have been already initialized * we only check images that have been already initialized
*/ */
iter= loaded_images.head; for (iter = loaded_images.head; iter; iter = iter->next) {
while(iter) { struct Elf32_Sym *sym;
if(iter->imageid== imid) {
struct Elf32_Sym *sym= find_symbol_xxx(iter, symname);
if(sym) { if (iter->imageid != imid)
continue;
sym = find_symbol_xxx(iter, symname);
if (sym)
return (void*)(sym->st_value + iter->regions[0].delta); return (void*)(sym->st_value + iter->regions[0].delta);
} }
}
iter= iter->next;
}
return NULL; return NULL;
} }
/* /*
* init routine, just get hold of the uspa args * init routine, just get hold of the uspa args
*/ */
void void
rldelf_init(struct uspace_prog_args_t const *_uspa) rldelf_init(struct uspace_prog_args_t const *_uspa)
{ {
@ -1064,3 +1013,4 @@ rldelf_init(struct uspace_prog_args_t const *_uspa)
rld_sem = create_sem(1, "rld_lock\n"); rld_sem = create_sem(1, "rld_lock\n");
} }