2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Copyright 2002, Manuel J. Petit. All rights reserved.
4 ** Distributed under the terms of the NewOS License.
9 #include <newos/errors.h>
10 #include <newos/elf32.h>
11 #include <newos/user_runtime.h>
12 #include <sys/syscalls.h>
18 #define ELF_PREPEND_UNDERSCORE 1
21 #ifndef ELF_PREPEND_UNDERSCORE
22 #define ELF_PREPEND_UNDERSCORE 0
25 #define PAGE_MASK ((PAGE_SIZE)-1)
26 #define PAGE_OFFS(y) ((y)&(PAGE_MASK))
27 #define PAGE_BASE(y) ((y)&~(PAGE_MASK))
29 #define ROUNDOWN(x,y) ((x)&~((y)-1))
30 #define ROUNDUP(x,y) ROUNDOWN(x+y-1,y)
37 RFLAG_SORTED
= 0x0400,
38 RFLAG_SYMBOLIC
= 0x0800,
39 RFLAG_RELOCATED
= 0x1000,
40 RFLAG_PROTECTED
= 0x2000,
41 RFLAG_INITIALIZED
= 0x4000,
42 RFLAG_NEEDAGIRLFRIEND
= 0x8000
63 * image identification
65 char name
[SYS_MAX_OS_NAME_LEN
];
74 addr_t dynamic_ptr
; // pointer to the dynamic section
77 // pointer to symbol participation data structures
78 unsigned int *symhash
;
79 struct Elf32_Sym
*syms
;
81 struct Elf32_Rel
*rel
;
83 struct Elf32_Rela
*rela
;
85 struct Elf32_Rel
*pltrel
;
87 int pltrel_type
; // DT_REL or DT_RELA
90 struct image_t
**needed
;
92 // describes the text and data regions
94 elf_region_t regions
[1];
99 struct image_queue_t
{
105 static image_queue_t loaded_images
= { 0, 0 };
106 static image_queue_t loading_images
= { 0, 0 };
107 static image_queue_t disposable_images
= { 0, 0 };
108 static unsigned loaded_image_count
= 0;
109 static unsigned imageid_count
= 0;
111 static sem_id rld_sem
;
112 static struct uspace_prog_args_t
const *uspa
;
115 #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
116 #define SYMNAME(image, sym) STRING(image, (sym)->st_name)
117 #define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num])
118 #define HASHTABSIZE(image) ((image)->symhash[0])
119 #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2])
120 #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
124 * This macro is non ISO compliant, but a gcc extension
126 #define FATAL(x,y...) \
128 printf("rld.so: " y); \
136 enqueue_image(image_queue_t
*queue
, image_t
*img
)
140 img
->prev
= queue
->tail
;
142 queue
->tail
->next
= img
;
152 dequeue_image(image_queue_t
*queue
, image_t
*img
)
155 img
->next
->prev
= img
->prev
;
157 queue
->tail
= img
->prev
;
161 img
->prev
->next
= img
->next
;
163 queue
->head
= img
->next
;
172 elf_hash(const unsigned char *name
)
174 unsigned long hash
= 0;
178 hash
= (hash
<< 4) + *name
++;
179 if((temp
= hash
& 0xf0000000)) {
189 find_image(char const *name
)
193 iter
= loaded_images
.head
;
195 if(strncmp(iter
->name
, name
, sizeof(iter
->name
)) == 0) {
201 iter
= loading_images
.head
;
203 if(strncmp(iter
->name
, name
, sizeof(iter
->name
)) == 0) {
214 parse_eheader(struct Elf32_Ehdr
*eheader
)
216 if(memcmp(eheader
->e_ident
, ELF_MAGIC
, 4) != 0)
217 return ERR_INVALID_BINARY
;
219 if(eheader
->e_ident
[4] != ELFCLASS32
)
220 return ERR_INVALID_BINARY
;
222 if(eheader
->e_phoff
== 0)
223 return ERR_INVALID_BINARY
;
225 if(eheader
->e_phentsize
< sizeof(struct Elf32_Phdr
))
226 return ERR_INVALID_BINARY
;
228 return eheader
->e_phentsize
*eheader
->e_phnum
;
233 count_regions(char const *buff
, int phnum
, int phentsize
)
237 struct Elf32_Phdr
*pheaders
;
240 for(i
= 0; i
< phnum
; i
++) {
241 pheaders
= (struct Elf32_Phdr
*)(buff
+i
*phentsize
);
243 switch(pheaders
->p_type
) {
249 if(pheaders
->p_memsz
!= pheaders
->p_filesz
) {
250 unsigned A
= pheaders
->p_vaddr
+pheaders
->p_memsz
-1;
251 unsigned B
= pheaders
->p_vaddr
+pheaders
->p_filesz
-1;
262 /* will be handled at some other place */
265 /* should check here for appropiate interpreter */
271 /* undefined semantics */
274 /* we don't use it */
277 FATAL(true, "unhandled pheader type 0x%x\n", pheaders
[i
].p_type
);
288 * create_image() & destroy_image()
290 * Create and destroy image_t structures. The destroyer makes sure that the
291 * memory buffers are full of garbage before freeing.
295 create_image(char const *name
, int num_regions
)
300 alloc_size
= sizeof(image_t
)+(num_regions
-1)*sizeof(elf_region_t
);
302 retval
= rldalloc(alloc_size
);
304 memset(retval
, 0, alloc_size
);
306 strlcpy(retval
->name
, name
, sizeof(retval
->name
));
307 retval
->imageid
= imageid_count
;
309 retval
->num_regions
= num_regions
;
318 destroy_image(image_t
*image
)
322 alloc_size
= sizeof(image_t
)+(image
->num_regions
-1)*sizeof(elf_region_t
);
324 memset(image
->needed
, 0xa5, sizeof(image
->needed
[0])*image
->num_needed
);
325 rldfree(image
->needed
);
327 memset(image
, 0xa5, alloc_size
);
335 parse_program_headers(image_t
*image
, char *buff
, int phnum
, int phentsize
)
339 struct Elf32_Phdr
*pheaders
;
342 for(i
= 0; i
< phnum
; i
++) {
343 pheaders
= (struct Elf32_Phdr
*)(buff
+i
*phentsize
);
345 switch(pheaders
->p_type
) {
350 if(pheaders
->p_memsz
== pheaders
->p_filesz
) {
352 * everything in one area
354 image
->regions
[regcount
].start
= pheaders
->p_vaddr
;
355 image
->regions
[regcount
].size
= pheaders
->p_memsz
;
356 image
->regions
[regcount
].vmstart
= ROUNDOWN(pheaders
->p_vaddr
, PAGE_SIZE
);
357 image
->regions
[regcount
].vmsize
= ROUNDUP (pheaders
->p_memsz
+ (pheaders
->p_vaddr
% PAGE_SIZE
), PAGE_SIZE
);
358 image
->regions
[regcount
].fdstart
= pheaders
->p_offset
;
359 image
->regions
[regcount
].fdsize
= pheaders
->p_filesz
;
360 image
->regions
[regcount
].delta
= 0;
361 image
->regions
[regcount
].flags
= 0;
362 if(pheaders
->p_flags
& PF_W
) {
363 // this is a writable segment
364 image
->regions
[regcount
].flags
|= RFLAG_RW
;
368 * may require splitting
370 unsigned A
= pheaders
->p_vaddr
+pheaders
->p_memsz
-1;
371 unsigned B
= pheaders
->p_vaddr
+pheaders
->p_filesz
-1;
376 image
->regions
[regcount
].start
= pheaders
->p_vaddr
;
377 image
->regions
[regcount
].size
= pheaders
->p_filesz
;
378 image
->regions
[regcount
].vmstart
= ROUNDOWN(pheaders
->p_vaddr
, PAGE_SIZE
);
379 image
->regions
[regcount
].vmsize
= ROUNDUP (pheaders
->p_filesz
+ (pheaders
->p_vaddr
% PAGE_SIZE
), PAGE_SIZE
);
380 image
->regions
[regcount
].fdstart
= pheaders
->p_offset
;
381 image
->regions
[regcount
].fdsize
= pheaders
->p_filesz
;
382 image
->regions
[regcount
].delta
= 0;
383 image
->regions
[regcount
].flags
= 0;
384 if(pheaders
->p_flags
& PF_W
) {
385 // this is a writable segment
386 image
->regions
[regcount
].flags
|= RFLAG_RW
;
391 * yeah, it requires splitting
394 image
->regions
[regcount
].start
= pheaders
->p_vaddr
;
395 image
->regions
[regcount
].size
= pheaders
->p_memsz
- pheaders
->p_filesz
;
396 image
->regions
[regcount
].vmstart
= image
->regions
[regcount
-1].vmstart
+ image
->regions
[regcount
-1].vmsize
;
397 image
->regions
[regcount
].vmsize
= ROUNDUP (pheaders
->p_memsz
+ (pheaders
->p_vaddr
% PAGE_SIZE
), PAGE_SIZE
) - image
->regions
[regcount
-1].vmsize
;
398 image
->regions
[regcount
].fdstart
= 0;
399 image
->regions
[regcount
].fdsize
= 0;
400 image
->regions
[regcount
].delta
= 0;
401 image
->regions
[regcount
].flags
= RFLAG_ANON
;
402 if(pheaders
->p_flags
& PF_W
) {
403 // this is a writable segment
404 image
->regions
[regcount
].flags
|= RFLAG_RW
;
411 image
->dynamic_ptr
= pheaders
->p_vaddr
;
414 /* should check here for appropiate interpreter */
420 /* undefined semantics */
423 /* we don't use it */
426 FATAL(true, "unhandled pheader type 0x%x\n", pheaders
[i
].p_type
);
434 assert_dynamic_loadable(image_t
*image
)
438 if(!image
->dynamic_ptr
) {
442 for(i
= 0; i
< image
->num_regions
; i
++) {
443 if(image
->dynamic_ptr
>= image
->regions
[i
].start
) {
444 if(image
->dynamic_ptr
< image
->regions
[i
].start
+image
->regions
[i
].size
) {
455 map_image(int fd
, char const *path
, image_t
*image
, bool fixed
)
461 for(i
= 0; i
< image
->num_regions
; i
++) {
462 char region_name
[256];
464 unsigned addr_specifier
;
471 (image
->regions
[i
].flags
&RFLAG_RW
)?"RW":"RO"
474 if(image
->dynamic_ptr
&& !fixed
) {
476 * relocatable image... we can afford to place wherever
480 * but only the first segment gets a free ride
483 addr_specifier
= REGION_ADDR_ANY_ADDRESS
;
485 load_address
= image
->regions
[i
].vmstart
+ image
->regions
[i
-1].delta
;
486 addr_specifier
= REGION_ADDR_EXACT_ADDRESS
;
490 * not relocatable, put it where it asks or die trying
492 load_address
= image
->regions
[i
].vmstart
;
493 addr_specifier
= REGION_ADDR_EXACT_ADDRESS
;
496 if(image
->regions
[i
].flags
& RFLAG_ANON
) {
498 printf("rld map_image: creating anon region: name '%s' address 0x%x specifier 0x%x size 0x%x\n",
499 region_name
, load_address
, addr_specifier
, image
->regions
[i
].vmsize
);
501 image
->regions
[i
].id
= _kern_vm_create_anonymous_region(
503 (void **)&load_address
,
505 image
->regions
[i
].vmsize
,
510 if(image
->regions
[i
].id
< 0) {
511 printf("rld map_image: err %d from create_anon_region\n", image
->regions
[i
].id
);
514 image
->regions
[i
].delta
= load_address
- image
->regions
[i
].vmstart
;
515 image
->regions
[i
].vmstart
= load_address
;
518 printf("rld map_image: mapping file: name '%s' address 0x%x specifier 0x%x size 0x%x path '%s' offset 0x%Lx\n",
519 region_name
, load_address
, addr_specifier
, image
->regions
[i
].vmsize
,
520 path
, ROUNDOWN(image
->regions
[i
].fdstart
, PAGE_SIZE
));
522 image
->regions
[i
].id
= _kern_vm_map_file(
524 (void **)&load_address
,
526 image
->regions
[i
].vmsize
,
530 ROUNDOWN(image
->regions
[i
].fdstart
, PAGE_SIZE
)
532 if(image
->regions
[i
].id
< 0) {
533 printf("rld map_image: err %d from map_file (address 0x%x)\n", image
->regions
[i
].id
, load_address
);
536 image
->regions
[i
].delta
= load_address
- image
->regions
[i
].vmstart
;
537 image
->regions
[i
].vmstart
= load_address
;
540 * handle trailer bits in data segment
542 if(image
->regions
[i
].flags
& RFLAG_RW
) {
543 unsigned start_clearing
;
547 image
->regions
[i
].vmstart
548 + PAGE_OFFS(image
->regions
[i
].start
)
549 + image
->regions
[i
].size
;
551 image
->regions
[i
].vmsize
552 - PAGE_OFFS(image
->regions
[i
].start
)
553 - image
->regions
[i
].size
;
554 memset((void*)start_clearing
, 0, to_clear
);
559 if(image
->dynamic_ptr
) {
560 image
->dynamic_ptr
+= image
->regions
[0].delta
;
571 unmap_image(image_t
*image
)
575 for(i
= 0; i
< image
->num_regions
; i
++) {
576 _kern_vm_delete_region(image
->regions
[i
].id
);
578 image
->regions
[i
].id
= -1;
584 parse_dynamic_segment(image_t
*image
)
593 d
= (struct Elf32_Dyn
*)image
->dynamic_ptr
;
598 for(i
=0; d
[i
].d_tag
!= DT_NULL
; i
++) {
601 image
->num_needed
+= 1;
604 image
->symhash
= (unsigned int *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
607 image
->strtab
= (char *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
610 image
->syms
= (struct Elf32_Sym
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
613 image
->rel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
616 image
->rel_len
= d
[i
].d_un
.d_val
;
619 image
->rela
= (struct Elf32_Rela
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
622 image
->rela_len
= d
[i
].d_un
.d_val
;
624 // TK: procedure linkage table
626 image
->pltrel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
629 image
->pltrel_len
= d
[i
].d_un
.d_val
;
632 image
->pltrel_type
= d
[i
].d_un
.d_val
;
639 // lets make sure we found all the required sections
640 if(!image
->symhash
|| !image
->syms
|| !image
->strtab
) {
649 find_symbol_xxx(image_t
*img
, const char *_symbol
)
655 /* some architectures prepend a '_' to symbols, so lets do it here for lookups */
656 #if ELF_PREPEND_UNDERSCORE
657 char new_symbol
[SYS_MAX_NAME_LEN
];
661 strlcat(new_symbol
, _symbol
, SYS_MAX_NAME_LEN
);
667 if(img
->dynamic_ptr
) {
668 hash
= elf_hash(symbol
) % HASHTABSIZE(img
);
669 for(i
= HASHBUCKETS(img
)[hash
]; i
!= STN_UNDEF
; i
= HASHCHAINS(img
)[i
]) {
670 if(img
->syms
[i
].st_shndx
!= SHN_UNDEF
) {
671 if((ELF32_ST_BIND(img
->syms
[i
].st_info
)== STB_GLOBAL
) || (ELF32_ST_BIND(img
->syms
[i
].st_info
)== STB_WEAK
)) {
672 if(!strcmp(SYMNAME(img
, &img
->syms
[i
]), symbol
)) {
673 return &img
->syms
[i
];
685 find_symbol(image_t
**shimg
, const char *name
)
691 iter
= loaded_images
.head
;
693 if(iter
->dynamic_ptr
) {
694 hash
= elf_hash(name
) % HASHTABSIZE(iter
);
695 for(i
= HASHBUCKETS(iter
)[hash
]; i
!= STN_UNDEF
; i
= HASHCHAINS(iter
)[i
]) {
696 if(iter
->syms
[i
].st_shndx
!= SHN_UNDEF
) {
697 if((ELF32_ST_BIND(iter
->syms
[i
].st_info
)== STB_GLOBAL
) || (ELF32_ST_BIND(iter
->syms
[i
].st_info
)== STB_WEAK
)) {
698 if(!strcmp(SYMNAME(iter
, &iter
->syms
[i
]), name
)) {
700 return &iter
->syms
[i
];
715 resolve_symbol(image_t
*image
, struct Elf32_Sym
*sym
, addr_t
*sym_addr
)
717 struct Elf32_Sym
*sym2
;
721 switch(sym
->st_shndx
) {
723 // patch the symbol name
724 symname
= SYMNAME(image
, sym
);
726 // it's undefined, must be outside this image, try the other image
727 sym2
= find_symbol(&shimg
, symname
);
729 printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname
);
730 return ERR_ELF_RESOLVING_SYMBOL
;
733 // make sure they're the same type
734 if(ELF32_ST_TYPE(sym
->st_info
)!= STT_NOTYPE
) {
735 if(ELF32_ST_TYPE(sym
->st_info
) != ELF32_ST_TYPE(sym2
->st_info
)) {
736 printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname
);
737 return ERR_ELF_RESOLVING_SYMBOL
;
741 if(ELF32_ST_BIND(sym2
->st_info
) != STB_GLOBAL
&& ELF32_ST_BIND(sym2
->st_info
) != STB_WEAK
) {
742 printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname
);
743 return ERR_ELF_RESOLVING_SYMBOL
;
746 *sym_addr
= sym2
->st_value
+ shimg
->regions
[0].delta
;
749 *sym_addr
= sym
->st_value
+ image
->regions
[0].delta
;
753 printf("elf_resolve_symbol: COMMON symbol, finish me!\n");
754 return ERR_NOT_IMPLEMENTED
;
757 *sym_addr
= sym
->st_value
+ image
->regions
[0].delta
;
763 #include "arch/rldreloc.inc"
768 load_container(char const *path
, char const *name
, bool fixed
)
776 bool dynamic_success
;
780 struct Elf32_Ehdr eheader
;
782 found
= find_image(name
);
789 printf("rld: load_container: path '%s', name '%s' entry\n", path
, name
);
792 fd
= _kern_open(path
, 0);
793 FATAL((fd
< 0), "cannot open file %s\n", path
);
795 len
= _kern_read(fd
, &eheader
, 0, sizeof(eheader
));
796 FATAL((len
!= sizeof(eheader
)), "troubles reading ELF header\n");
798 ph_len
= parse_eheader(&eheader
);
799 FATAL((ph_len
<= 0), "incorrect ELF header\n");
800 FATAL((ph_len
> (int)sizeof(ph_buff
)), "cannot handle Program headers bigger than %lu\n", (long unsigned)sizeof(ph_buff
));
802 len
= _kern_read(fd
, ph_buff
, eheader
.e_phoff
, ph_len
);
803 FATAL((len
!= ph_len
), "troubles reading Program headers\n");
805 num_regions
= count_regions(ph_buff
, eheader
.e_phnum
, eheader
.e_phentsize
);
806 FATAL((num_regions
<= 0), "troubles parsing Program headers, num_regions= %d\n", num_regions
);
808 image
= create_image(name
, num_regions
);
809 FATAL((!image
), "failed to allocate image_t control block\n");
811 parse_program_headers(image
, ph_buff
, eheader
.e_phnum
, eheader
.e_phentsize
);
812 FATAL(!assert_dynamic_loadable(image
), "dynamic segment must be loadable (implementation restriction)\n");
814 map_success
= map_image(fd
, path
, image
, fixed
);
815 FATAL(!map_success
, "troubles reading image\n");
817 dynamic_success
= parse_dynamic_segment(image
);
818 FATAL(!dynamic_success
, "troubles handling dynamic section\n");
820 image
->entry_point
= eheader
.e_entry
+ image
->regions
[0].delta
;
826 printf("rld: load_container: path '%s', name '%s' loaded:\n", path
, name
);
827 printf("\tregions:\n");
828 for(i
=0; i
<image
->num_regions
; i
++) {
829 printf("\t\tid %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
830 image
->regions
[i
].id
, image
->regions
[i
].start
, image
->regions
[i
].size
,
831 image
->regions
[i
].vmstart
, image
->regions
[i
].vmsize
, image
->regions
[i
].fdstart
,
832 image
->regions
[i
].fdsize
, image
->regions
[i
].delta
, image
->regions
[i
].flags
);
839 enqueue_image(&loaded_images
, image
);
847 load_dependencies(image_t
*img
)
853 addr_t needed_offset
;
856 d
= (struct Elf32_Dyn
*)img
->dynamic_ptr
;
861 img
->needed
= rldalloc(img
->num_needed
*sizeof(image_t
*));
862 FATAL((!img
->needed
), "failed to allocate needed struct\n");
863 memset(img
->needed
, 0, img
->num_needed
*sizeof(image_t
*));
865 for(i
=0, j
= 0; d
[i
].d_tag
!= DT_NULL
; i
++) {
868 needed_offset
= d
[i
].d_un
.d_ptr
;
869 sprintf(path
, "/boot/lib/%s", STRING(img
, needed_offset
));
870 img
->needed
[j
]= load_container(path
, STRING(img
, needed_offset
), false);
876 * ignore any other tag
882 FATAL((j
!= img
->num_needed
), "Internal error at load_dependencies()");
889 topological_sort(image_t
*img
, unsigned slot
, image_t
**init_list
)
893 img
->flags
|= RFLAG_SORTED
; /* make sure we don't visit this one */
894 for(i
= 0; i
< img
->num_needed
; i
++) {
895 if(!(img
->needed
[i
]->flags
& RFLAG_SORTED
)) {
896 slot
= topological_sort(img
->needed
[i
], slot
, init_list
);
900 init_list
[slot
]= img
;
906 init_dependencies(image_t
*img
, bool init_head
)
912 init_list
= rldalloc(loaded_image_count
*sizeof(image_t
*));
913 FATAL((!init_list
), "memory shortage in init_dependencies()");
914 memset(init_list
, 0, loaded_image_count
*sizeof(image_t
*));
916 img
->flags
|= RFLAG_SORTED
; /* make sure we don't visit this one */
918 for(i
= 0; i
< img
->num_needed
; i
++) {
919 if(!(img
->needed
[i
]->flags
& RFLAG_SORTED
)) {
920 slot
= topological_sort(img
->needed
[i
], slot
, init_list
);
925 init_list
[slot
]= img
;
929 for(i
= 0; i
< slot
; i
++) {
930 addr_t _initf
= init_list
[i
]->entry_point
;
931 libinit_f
*initf
= (libinit_f
*)(_initf
);
934 initf(init_list
[i
]->imageid
, uspa
);
944 put_image(image_t
*img
)
947 if(img
->refcount
== 0) {
950 dequeue_image(&loaded_images
, img
);
951 enqueue_image(&disposable_images
, img
);
953 for(i
= 0; i
< img
->num_needed
; i
++) {
954 put_image(img
->needed
[i
]);
961 * exported functions:
972 load_program(char const *path
, void **entry
)
977 image
= load_container(path
, NEWOS_MAGIC_APPNAME
, true);
979 iter
= loaded_images
.head
;
981 load_dependencies(iter
);
986 iter
= loaded_images
.head
;
988 bool relocate_success
;
990 relocate_success
= relocate_image(iter
);
991 FATAL(!relocate_success
, "troubles relocating\n");
996 init_dependencies(loaded_images
.head
, false);
998 *entry
= (void*)(image
->entry_point
);
999 return image
->imageid
;
1003 load_library(char const *path
)
1009 image
= find_image(path
);
1011 image
->refcount
+= 1;
1012 return image
->imageid
;
1015 image
= load_container(path
, path
, false);
1017 iter
= loaded_images
.head
;
1019 load_dependencies(iter
);
1024 iter
= loaded_images
.head
;
1026 bool relocate_success
;
1028 relocate_success
= relocate_image(iter
);
1029 FATAL(!relocate_success
, "troubles relocating\n");
1034 init_dependencies(image
, true);
1036 return image
->imageid
;
1040 unload_library(dynmodule_id imid
)
1046 * we only check images that have been already initialized
1048 iter
= loaded_images
.head
;
1050 if(iter
->imageid
== imid
) {
1068 iter
= disposable_images
.head
;
1070 // call image fini here...
1072 dequeue_image(&disposable_images
, iter
);
1075 destroy_image(iter
);
1076 iter
= disposable_images
.head
;
1084 dynamic_symbol(dynmodule_id imid
, char const *symname
)
1089 * we only check images that have been already initialized
1091 iter
= loaded_images
.head
;
1093 if(iter
->imageid
== imid
) {
1094 struct Elf32_Sym
*sym
= find_symbol_xxx(iter
, symname
);
1097 return (void*)(sym
->st_value
+ iter
->regions
[0].delta
);
1108 * init routine, just get hold of the uspa args
1111 rldelf_init(struct uspace_prog_args_t
const *_uspa
)
1115 rld_sem
= _kern_sem_create(1, "rld_lock\n");