2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
6 #include <kernel/kernel.h>
7 #include <newos/errors.h>
8 #include <kernel/elf.h>
9 #include <kernel/vfs.h>
10 #include <kernel/vm.h>
11 #include <kernel/thread.h>
12 #include <kernel/debug.h>
13 #include <kernel/heap.h>
14 #include <kernel/arch/cpu.h>
16 #include <newos/elf32.h>
28 struct elf_image_info
{
29 struct elf_image_info
*next
;
33 struct elf_region regions
[2]; // describes the text and data regions
34 addr dynamic_ptr
; // pointer to the dynamic section
35 struct elf_linked_image
*linked_images
;
37 struct Elf32_Ehdr
*eheader
;
39 // pointer to symbol participation data structures
41 unsigned int *symhash
;
42 struct Elf32_Sym
*syms
;
44 struct Elf32_Rel
*rel
;
46 struct Elf32_Rela
*rela
;
48 struct Elf32_Rel
*pltrel
;
52 // XXX TK this shall contain a list of linked images
53 // (don't know enough about ELF how to get this list)
54 typedef struct elf_linked_image
{
55 struct elf_linked_image
*next
;
56 struct elf_image_info
*image
;
59 static struct elf_image_info
*kernel_images
= NULL
;
60 static struct elf_image_info
*kernel_image
= NULL
;
61 static mutex image_lock
;
62 static mutex image_load_lock
;
63 static image_id next_image_id
= 0;
65 #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
66 #define SYMNAME(image, sym) STRING(image, (sym)->st_name)
67 #define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num])
68 #define HASHTABSIZE(image) ((image)->symhash[0])
69 #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2])
70 #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
72 static void insert_image_in_list(struct elf_image_info
*image
)
74 mutex_lock(&image_lock
);
76 image
->next
= kernel_images
;
77 kernel_images
= image
;
79 mutex_unlock(&image_lock
);
82 static void remove_image_from_list(struct elf_image_info
*image
)
84 struct elf_image_info
**ptr
;
86 mutex_lock(&image_lock
);
88 for(ptr
= &kernel_images
; *ptr
; ptr
= &(*ptr
)->next
) {
96 mutex_unlock(&image_lock
);
99 static struct elf_image_info
*find_image(image_id id
)
101 struct elf_image_info
*image
;
103 mutex_lock(&image_lock
);
105 for(image
= kernel_images
; image
; image
= image
->next
) {
109 mutex_unlock(&image_lock
);
114 static struct elf_image_info
*find_image_by_vnode(void *vnode
)
116 struct elf_image_info
*image
;
118 mutex_lock(&image_lock
);
120 for(image
= kernel_images
; image
; image
= image
->next
) {
121 if(image
->vnode
== vnode
)
124 mutex_unlock(&image_lock
);
129 static struct elf_image_info
*create_image_struct()
131 struct elf_image_info
*image
;
133 image
= kmalloc(sizeof(struct elf_image_info
));
136 memset(image
, 0, sizeof(struct elf_image_info
));
137 image
->regions
[0].id
= -1;
138 image
->regions
[1].id
= -1;
139 image
->id
= atomic_add(&next_image_id
, 1);
140 image
->ref_count
= 1;
141 image
->linked_images
= NULL
;
145 static unsigned long elf_hash(const unsigned char *name
)
147 unsigned long hash
= 0;
151 hash
= (hash
<< 4) + *name
++;
152 if((temp
= hash
& 0xf0000000))
159 static void dump_image_info(struct elf_image_info
*image
)
163 dprintf("elf_image_info at %p:\n", image
);
164 dprintf(" next %p\n", image
->next
);
165 dprintf(" id 0x%x\n", image
->id
);
167 dprintf(" regions[%d].id 0x%x\n", i
, image
->regions
[i
].id
);
168 dprintf(" regions[%d].start 0x%lx\n", i
, image
->regions
[i
].start
);
169 dprintf(" regions[%d].size 0x%lx\n", i
, image
->regions
[i
].size
);
170 dprintf(" regions[%d].delta %ld\n", i
, image
->regions
[i
].delta
);
172 dprintf(" dynamic_ptr 0x%lx\n", image
->dynamic_ptr
);
173 dprintf(" needed %p\n", image
->needed
);
174 dprintf(" symhash %p\n", image
->symhash
);
175 dprintf(" syms %p\n", image
->syms
);
176 dprintf(" strtab %p\n", image
->strtab
);
177 dprintf(" rel %p\n", image
->rel
);
178 dprintf(" rel_len 0x%x\n", image
->rel_len
);
179 dprintf(" rela %p\n", image
->rela
);
180 dprintf(" rela_len 0x%x\n", image
->rela_len
);
183 static void dump_symbol(struct elf_image_info
*image
, struct Elf32_Sym
*sym
)
186 dprintf("symbol at %p, in image %p\n", sym
, image
);
188 dprintf(" name index %d, '%s'\n", sym
->st_name
, SYMNAME(image
, sym
));
189 dprintf(" st_value 0x%x\n", sym
->st_value
);
190 dprintf(" st_size %d\n", sym
->st_size
);
191 dprintf(" st_info 0x%x\n", sym
->st_info
);
192 dprintf(" st_other 0x%x\n", sym
->st_other
);
193 dprintf(" st_shndx %d\n", sym
->st_shndx
);
199 #define PRINT(x) dprintf x
205 /* Take an address to symbol. Taken from the OpenBeOS version of the newos kernel. */
206 int elf_reverse_lookup_symbol(addr address
, addr
*base_address
, char *text
, int len
)
208 struct elf_image_info
**ptr
;
209 struct elf_image_info
*image
;
210 struct Elf32_Sym
*sym
;
211 struct elf_image_info
*found_image
;
212 struct Elf32_Sym
*found_sym
;
216 PRINT(("looking up %p\n",(void *)address
));
218 mutex_lock(&image_lock
);
222 found_delta
= 0x7fffffff;
223 for(ptr
= &kernel_images
; *ptr
; ptr
= &(*ptr
)->next
) {
226 PRINT((" image %p, base = %p, size = %p\n", image
, (void *)image
->regions
[0].start
, (void *)image
->regions
[0].size
));
227 if ((address
< image
->regions
[0].start
) || (address
>= (image
->regions
[0].start
+ image
->regions
[0].size
)))
230 PRINT((" searching...\n"));
232 for (i
= 0; i
< HASHTABSIZE(image
); i
++) {
233 for(j
= HASHBUCKETS(image
)[i
]; j
!= STN_UNDEF
; j
= HASHCHAINS(image
)[j
]) {
235 sym
= &image
->syms
[j
];
237 PRINT((" %p looking at %s, type = %d, bind = %d, addr = %p\n",sym
,SYMNAME(image
, sym
),ELF32_ST_TYPE(sym
->st_info
),ELF32_ST_BIND(sym
->st_info
),(void *)sym
->st_value
));
238 PRINT((" symbol: %lx (%x + %lx)\n", sym
->st_value
+ image
->regions
[0].delta
, sym
->st_value
, image
->regions
[0].delta
));
240 if (ELF32_ST_TYPE(sym
->st_info
) != STT_FUNC
)
243 d
= (long)address
- (long)(sym
->st_value
+ image
->regions
[0].delta
);
244 if ((d
>= 0) && (d
< found_delta
)) {
252 if (found_sym
== 0) {
253 PRINT(("symbol not found!\n"));
254 strlcpy(text
, "symbol not found", len
);
257 PRINT(("symbol at %p, in image %p\n", found_sym
, found_image
));
258 PRINT(("name index %d, '%s'\n", found_sym
->st_name
, SYMNAME(found_image
, found_sym
)));
259 PRINT(("addr = %#lx, offset = %#lx\n",(found_sym
->st_value
+ found_image
->regions
[0].delta
),found_delta
));
260 // XXX should honor len here
261 // sprintf(text, "<%#lx:%s + %#lx> %s", (found_sym->st_value + found_image->regions[0].delta), SYMNAME(found_image, found_sym), found_delta, found_image->name);
262 strncpy(text
, SYMNAME(found_image
, found_sym
), len
);
264 *base_address
= found_sym
->st_value
+ found_image
->regions
[0].delta
;
268 mutex_unlock(&image_lock
);
273 static struct Elf32_Sym
*elf_find_symbol(struct elf_image_info
*image
, const char *name
)
278 if(!image
->dynamic_ptr
)
281 hash
= elf_hash(name
) % HASHTABSIZE(image
);
282 for(i
= HASHBUCKETS(image
)[hash
]; i
!= STN_UNDEF
; i
= HASHCHAINS(image
)[i
]) {
283 if(!strcmp(SYMNAME(image
, &image
->syms
[i
]), name
)) {
284 return &image
->syms
[i
];
291 addr
elf_lookup_symbol(image_id id
, const char *symbol
)
293 struct elf_image_info
*image
;
294 struct Elf32_Sym
*sym
;
296 //dprintf( "elf_lookup_symbol: %s\n", symbol );
298 image
= find_image(id
);
302 sym
= elf_find_symbol(image
, symbol
);
306 if(sym
->st_shndx
== SHN_UNDEF
) {
310 /*dprintf( "found: %x (%x + %x)\n", sym->st_value + image->regions[0].delta,
311 sym->st_value, image->regions[0].delta );*/
312 return sym
->st_value
+ image
->regions
[0].delta
;
315 static int elf_parse_dynamic_section(struct elf_image_info
*image
)
319 int needed_offset
= -1;
321 // dprintf("top of elf_parse_dynamic_section\n");
327 d
= (struct Elf32_Dyn
*)image
->dynamic_ptr
;
331 for(i
=0; d
[i
].d_tag
!= DT_NULL
; i
++) {
334 needed_offset
= d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
;
337 image
->symhash
= (unsigned int *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
340 image
->strtab
= (char *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
343 image
->syms
= (struct Elf32_Sym
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
346 image
->rel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
349 image
->rel_len
= d
[i
].d_un
.d_val
;
352 image
->rela
= (struct Elf32_Rela
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
355 image
->rela_len
= d
[i
].d_un
.d_val
;
357 // TK: procedure linkage table
359 image
->pltrel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
362 image
->pltrel_len
= d
[i
].d_un
.d_val
;
369 // lets make sure we found all the required sections
370 if(!image
->symhash
|| !image
->syms
|| !image
->strtab
)
373 // dprintf("needed_offset = %d\n", needed_offset);
375 if(needed_offset
>= 0)
376 image
->needed
= STRING(image
, needed_offset
);
381 // this function first tries to see if the first image and it's already resolved symbol is okay, otherwise
382 // it tries to link against the shared_image
383 // XXX gross hack and needs to be done better
384 static int elf_resolve_symbol(struct elf_image_info
*image
, struct Elf32_Sym
*sym
, struct elf_image_info
*shared_image
, const char *sym_prepend
,addr
*sym_addr
)
386 struct Elf32_Sym
*sym2
;
387 char new_symname
[512];
389 switch(sym
->st_shndx
) {
391 // patch the symbol name
392 strlcpy(new_symname
, sym_prepend
, sizeof(new_symname
));
393 strlcat(new_symname
, SYMNAME(image
, sym
), sizeof(new_symname
));
395 // it's undefined, must be outside this image, try the other image
396 sym2
= elf_find_symbol(shared_image
, new_symname
);
398 dprintf("elf_resolve_symbol: could not resolve symbol '%s'\n", new_symname
);
399 return ERR_ELF_RESOLVING_SYMBOL
;
402 // make sure they're the same type
403 if(ELF32_ST_TYPE(sym
->st_info
) != ELF32_ST_TYPE(sym2
->st_info
)) {
404 dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", new_symname
);
405 return ERR_ELF_RESOLVING_SYMBOL
;
408 if(ELF32_ST_BIND(sym2
->st_info
) != STB_GLOBAL
&& ELF32_ST_BIND(sym2
->st_info
) != STB_WEAK
) {
409 dprintf("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname
);
410 return ERR_ELF_RESOLVING_SYMBOL
;
413 *sym_addr
= sym2
->st_value
+ shared_image
->regions
[0].delta
;
416 *sym_addr
= sym
->st_value
;
420 dprintf("elf_resolve_symbol: COMMON symbol, finish me!\n");
421 return ERR_NOT_IMPLEMENTED_YET
;
424 *sym_addr
= sym
->st_value
+ image
->regions
[0].delta
;
429 static int elf_relocate_rel(struct elf_image_info
*image
, const char *sym_prepend
,
430 struct Elf32_Rel
*rel
, int rel_len
)
433 struct Elf32_Sym
*sym
;
442 for(i
= 0; i
* (int)sizeof(struct Elf32_Rel
) < rel_len
; i
++) {
443 //dprintf("looking at rel type %d, offset 0x%x\n", ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset);
446 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
452 sym
= SYMBOL(image
, ELF32_R_SYM(rel
[i
].r_info
));
454 vlErr
= elf_resolve_symbol(image
, sym
, kernel_image
, sym_prepend
,&S
);
455 if(vlErr
<0) return vlErr
;
456 //dprintf("S 0x%x\n", S);
459 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
467 A
= *(addr
*)(image
->regions
[0].delta
+ rel
[i
].r_offset
);
468 // dprintf("A 0x%x\n", A);
472 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
477 P
= image
->regions
[0].delta
+ rel
[i
].r_offset
;
478 // dprintf("P 0x%x\n", P);
482 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
489 final_val
= S
+ A
- P
;
493 final_val
= image
->regions
[0].delta
+ A
;
497 dprintf( "final=%lx\n", final_val
);
500 dprintf("unhandled relocation type %d\n", ELF32_R_TYPE(rel
[i
].r_info
));
501 return ERR_NOT_ALLOWED
;
503 *(addr
*)(image
->regions
[0].delta
+ rel
[i
].r_offset
) = final_val
;
509 // XXX for now just link against the kernel
510 static int elf_relocate(struct elf_image_info
*image
, const char *sym_prepend
)
514 // dprintf("top of elf_relocate\n");
516 // deal with the rels first
518 //dprintf( "total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel) );
519 res
= elf_relocate_rel( image
, sym_prepend
, image
->rel
, image
->rel_len
);
525 if( image
->pltrel
) {
526 //dprintf( "total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel) );
527 res
= elf_relocate_rel( image
, sym_prepend
, image
->pltrel
, image
->pltrel_len
);
534 dprintf("RELA relocations not supported\n");
535 return ERR_NOT_ALLOWED
;
536 for(i
= 1; i
* (int)sizeof(struct Elf32_Rela
) < image
->rela_len
; i
++) {
537 dprintf("rela: type %d\n", ELF32_R_TYPE(image
->rela
[i
].r_info
));
543 static int verify_eheader(struct Elf32_Ehdr
*eheader
)
545 if(memcmp(eheader
->e_ident
, ELF_MAGIC
, 4) != 0)
546 return ERR_INVALID_BINARY
;
548 if(eheader
->e_ident
[4] != ELFCLASS32
)
549 return ERR_INVALID_BINARY
;
551 if(eheader
->e_phoff
== 0)
552 return ERR_INVALID_BINARY
;
554 if(eheader
->e_phentsize
< sizeof(struct Elf32_Phdr
))
555 return ERR_INVALID_BINARY
;
560 int elf_load_uspace(const char *path
, struct proc
*p
, int flags
, addr
*entry
)
562 struct Elf32_Ehdr eheader
;
563 struct Elf32_Phdr
*pheaders
= NULL
;
569 dprintf("elf_load: entry path '%s', proc %p\n", path
, p
);
571 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
575 len
= sys_read(fd
, &eheader
, 0, sizeof(eheader
));
580 if(len
!= sizeof(eheader
)) {
582 err
= ERR_INVALID_BINARY
;
585 err
= verify_eheader(&eheader
);
589 pheaders
= kmalloc(eheader
.e_phnum
* eheader
.e_phentsize
);
590 if(pheaders
== NULL
) {
591 dprintf("error allocating space for program headers\n");
596 dprintf("reading in program headers at 0x%x, len 0x%x\n", eheader
.e_phoff
, eheader
.e_phnum
* eheader
.e_phentsize
);
597 len
= sys_read(fd
, pheaders
, eheader
.e_phoff
, eheader
.e_phnum
* eheader
.e_phentsize
);
600 dprintf("error reading in program headers\n");
603 if(len
!= eheader
.e_phnum
* eheader
.e_phentsize
) {
604 dprintf("short read while reading in program headers\n");
609 for(i
=0; i
< eheader
.e_phnum
; i
++) {
610 char region_name
[64];
614 sprintf(region_name
, "%s_seg%d", path
, i
);
616 region_addr
= (char *)ROUNDOWN(pheaders
[i
].p_vaddr
, PAGE_SIZE
);
617 if(pheaders
[i
].p_flags
& PF_W
) {
621 unsigned start_clearing
;
623 unsigned A
= pheaders
[i
].p_vaddr
+pheaders
[i
].p_memsz
;
624 unsigned B
= pheaders
[i
].p_vaddr
+pheaders
[i
].p_filesz
;
626 A
= ROUNDOWN(A
, PAGE_SIZE
);
627 B
= ROUNDOWN(B
, PAGE_SIZE
);
632 (void **)®ion_addr
,
633 REGION_ADDR_EXACT_ADDRESS
,
634 ROUNDUP(pheaders
[i
].p_filesz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
),
638 ROUNDOWN(pheaders
[i
].p_offset
, PAGE_SIZE
)
641 dprintf("error allocating region!\n");
642 err
= ERR_INVALID_BINARY
;
648 * clean garbage brought by mmap
651 (unsigned)region_addr
652 + (pheaders
[i
].p_vaddr
% PAGE_SIZE
)
653 + pheaders
[i
].p_filesz
;
655 ROUNDUP(pheaders
[i
].p_filesz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
)
656 - (pheaders
[i
].p_vaddr
% PAGE_SIZE
)
657 - (pheaders
[i
].p_filesz
);
658 memset((void*)start_clearing
, 0, to_clear
);
661 * check if we need extra storage for the bss
667 ROUNDUP(pheaders
[i
].p_memsz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
)
668 - ROUNDUP(pheaders
[i
].p_filesz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
);
670 sprintf(region_name
, "%s_bss%d", path
, 'X');
672 region_addr
+= ROUNDUP(pheaders
[i
].p_filesz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
),
673 id
= vm_create_anonymous_region(
676 (void **)®ion_addr
,
677 REGION_ADDR_EXACT_ADDRESS
,
683 dprintf("error allocating region!\n");
684 err
= ERR_INVALID_BINARY
;
695 (void **)®ion_addr
,
696 REGION_ADDR_EXACT_ADDRESS
,
697 ROUNDUP(pheaders
[i
].p_memsz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
),
701 ROUNDOWN(pheaders
[i
].p_offset
, PAGE_SIZE
)
704 dprintf("error mapping text!\n");
705 err
= ERR_INVALID_BINARY
;
711 dprintf("elf_load: done!\n");
713 *entry
= eheader
.e_entry
;
725 image_id
elf_load_kspace(const char *path
, const char *sym_prepend
)
727 struct Elf32_Ehdr
*eheader
;
728 struct Elf32_Phdr
*pheaders
;
729 struct elf_image_info
*image
;
736 dprintf("elf_load_kspace: entry path '%s'\n", path
);
738 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
742 err
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
746 // XXX awful hack to keep someone else from trying to load this image
747 // probably not a bad thing, shouldn't be too many races
748 mutex_lock(&image_load_lock
);
750 // make sure it's not loaded already. Search by vnode
751 image
= find_image_by_vnode(vnode
);
753 atomic_add( &image
->ref_count
, 1 );
754 //err = ERR_NOT_ALLOWED;
758 eheader
= (struct Elf32_Ehdr
*)kmalloc( sizeof( *eheader
));
764 len
= sys_read(fd
, eheader
, 0, sizeof(*eheader
));
769 if(len
!= sizeof(*eheader
)) {
771 err
= ERR_INVALID_BINARY
;
774 err
= verify_eheader(eheader
);
778 image
= create_image_struct();
783 image
->vnode
= vnode
;
784 image
->eheader
= eheader
;
786 pheaders
= kmalloc(eheader
->e_phnum
* eheader
->e_phentsize
);
787 if(pheaders
== NULL
) {
788 dprintf("error allocating space for program headers\n");
793 // dprintf("reading in program headers at 0x%x, len 0x%x\n", eheader.e_phoff, eheader.e_phnum * eheader.e_phentsize);
794 len
= sys_read(fd
, pheaders
, eheader
->e_phoff
, eheader
->e_phnum
* eheader
->e_phentsize
);
797 dprintf("error reading in program headers\n");
800 if(len
!= eheader
->e_phnum
* eheader
->e_phentsize
) {
801 dprintf("short read while reading in program headers\n");
806 for(i
=0; i
< eheader
->e_phnum
; i
++) {
807 char region_name
[64];
808 bool ro_segment_handled
= false;
809 bool rw_segment_handled
= false;
813 // dprintf("looking at program header %d\n", i);
815 switch(pheaders
[i
].p_type
) {
819 image
->dynamic_ptr
= pheaders
[i
].p_vaddr
;
822 dprintf("unhandled pheader type 0x%x\n", pheaders
[i
].p_type
);
826 // we're here, so it must be a PT_LOAD segment
827 if((pheaders
[i
].p_flags
& (PF_R
| PF_W
| PF_X
)) == (PF_R
| PF_W
)) {
828 // this is the writable segment
829 if(rw_segment_handled
) {
830 // we've already created this segment
833 rw_segment_handled
= true;
835 lock
= LOCK_RW
|LOCK_KERNEL
;
836 sprintf(region_name
, "%s_rw", path
);
837 } else if((pheaders
[i
].p_flags
& (PF_R
| PF_W
| PF_X
)) == (PF_R
| PF_X
)) {
838 // this is the non-writable segment
839 if(ro_segment_handled
) {
840 // we've already created this segment
843 ro_segment_handled
= true;
845 // lock = LOCK_RO|LOCK_KERNEL;
846 lock
= LOCK_RW
|LOCK_KERNEL
;
847 sprintf(region_name
, "%s_ro", path
);
849 dprintf("weird program header flags 0x%x\n", pheaders
[i
].p_flags
);
852 image
->regions
[image_region
].size
= ROUNDUP(pheaders
[i
].p_memsz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
);
853 image
->regions
[image_region
].id
= vm_create_anonymous_region(vm_get_kernel_aspace_id(), region_name
,
854 (void **)&image
->regions
[image_region
].start
, REGION_ADDR_ANY_ADDRESS
,
855 image
->regions
[image_region
].size
, REGION_WIRING_WIRED
, lock
);
856 if(image
->regions
[image_region
].id
< 0) {
857 dprintf("error allocating region!\n");
858 err
= ERR_INVALID_BINARY
;
861 image
->regions
[image_region
].delta
= image
->regions
[image_region
].start
- ROUNDOWN(pheaders
[i
].p_vaddr
, PAGE_SIZE
);
863 // dprintf("elf_load_kspace: created a region at 0x%x\n", image->regions[image_region].start);
865 len
= sys_read(fd
, (void *)(image
->regions
[image_region
].start
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
)),
866 pheaders
[i
].p_offset
, pheaders
[i
].p_filesz
);
869 dprintf("error reading in seg %d\n", i
);
874 if(image
->regions
[1].start
!= 0) {
875 if(image
->regions
[0].delta
!= image
->regions
[1].delta
) {
876 dprintf("could not load binary, fix the region problem!\n");
877 dump_image_info(image
);
883 // modify the dynamic ptr by the delta of the regions
884 image
->dynamic_ptr
+= image
->regions
[0].delta
;
886 err
= elf_parse_dynamic_section(image
);
890 err
= elf_relocate(image
, sym_prepend
);
899 insert_image_in_list(image
);
902 mutex_unlock(&image_load_lock
);
904 dprintf("elf_load_kspace: done!\n");
909 if(image
->regions
[1].id
>= 0)
910 vm_delete_region(vm_get_kernel_aspace_id(), image
->regions
[1].id
);
911 if(image
->regions
[0].id
>= 0)
912 vm_delete_region(vm_get_kernel_aspace_id(), image
->regions
[0].id
);
920 mutex_unlock(&image_load_lock
);
923 vfs_put_vnode_ptr(vnode
);
929 static int elf_unload_image( struct elf_image_info
*image
);
931 static int elf_unlink_relocs( struct elf_image_info
*image
)
933 elf_linked_image
*link
, *next_link
;
935 for( link
= image
->linked_images
; link
; link
= next_link
) {
936 next_link
= link
->next
;
937 elf_unload_image( link
->image
);
944 static void elf_unload_image_final( struct elf_image_info
*image
)
948 for( i
= 0; i
< 2; ++i
) {
949 vm_delete_region( vm_get_kernel_aspace_id(), image
->regions
[i
].id
);
953 vfs_put_vnode_ptr( image
->vnode
);
955 remove_image_from_list(image
);
956 kfree( image
->eheader
);
960 static int elf_unload_image( struct elf_image_info
*image
)
962 if( atomic_add( &image
->ref_count
, -1 ) > 0 )
965 elf_unlink_relocs( image
);
966 elf_unload_image_final( image
);
971 int elf_unload_kspace( const char *path
)
976 struct elf_image_info
*image
;
978 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
982 err
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
986 mutex_lock(&image_load_lock
);
988 image
= find_image_by_vnode(vnode
);
990 dprintf( "Tried to unload image that wasn't loaded (%s)\n", path
);
995 err
= elf_unload_image( image
);
998 mutex_unlock(&image_load_lock
);
1001 vfs_put_vnode_ptr(vnode
);
1007 int elf_init(kernel_args
*ka
)
1009 vm_region_info rinfo
;
1012 mutex_init(&image_lock
, "kimages_lock");
1013 mutex_init(&image_load_lock
, "kimages_load_lock");
1015 // build a image structure for the kernel, which has already been loaded
1016 kernel_image
= create_image_struct();
1019 kernel_image
->regions
[0].id
= vm_find_region_by_name(vm_get_kernel_aspace_id(), "kernel_ro");
1020 if(kernel_image
->regions
[0].id
< 0)
1021 panic("elf_init: could not look up kernel text segment region\n");
1022 vm_get_region_info(kernel_image
->regions
[0].id
, &rinfo
);
1023 kernel_image
->regions
[0].start
= rinfo
.base
;
1024 kernel_image
->regions
[0].size
= rinfo
.size
;
1027 kernel_image
->regions
[1].id
= vm_find_region_by_name(vm_get_kernel_aspace_id(), "kernel_rw");
1028 if(kernel_image
->regions
[1].id
< 0)
1029 panic("elf_init: could not look up kernel data segment region\n");
1030 vm_get_region_info(kernel_image
->regions
[1].id
, &rinfo
);
1031 kernel_image
->regions
[1].start
= rinfo
.base
;
1032 kernel_image
->regions
[1].size
= rinfo
.size
;
1034 // we know where the dynamic section is
1035 kernel_image
->dynamic_ptr
= (addr
)ka
->kernel_dynamic_section_addr
.start
;
1037 // parse the dynamic section
1038 if(elf_parse_dynamic_section(kernel_image
) < 0)
1039 dprintf("elf_init: WARNING elf_parse_dynamic_section couldn't find dynamic section.\n");
1041 // insert it first in the list of kernel images loaded
1042 kernel_images
= NULL
;
1043 insert_image_in_list(kernel_image
);