3 #include <minix/type.h>
4 #include <minix/const.h>
6 #include <minix/syslib.h>
14 #include <machine/elf.h>
15 #include <machine/vmparam.h>
16 #include <machine/memory.h>
17 #include <minix/syslib.h>
19 /* For verbose logging */
22 /* Support only 32-bit ELF objects */
23 #define __ELF_WORD_SIZE 32
25 #define SECTOR_SIZE 512
27 static int check_header(Elf_Ehdr
*hdr
);
29 static int elf_sane(Elf_Ehdr
*hdr
)
31 if (check_header(hdr
) != OK
) {
35 if((hdr
->e_type
!= ET_EXEC
) && (hdr
->e_type
!= ET_DYN
)) {
39 if ((hdr
->e_phoff
> SECTOR_SIZE
) ||
40 (hdr
->e_phoff
+ hdr
->e_phentsize
* hdr
->e_phnum
) > SECTOR_SIZE
) {
42 printf("peculiar phoff\n");
50 static int elf_ph_sane(Elf_Phdr
*phdr
)
52 if (rounddown((uintptr_t)phdr
, sizeof(Elf_Addr
)) != (uintptr_t)phdr
) {
58 static int elf_unpack(char *exec_hdr
,
59 int hdr_len
, Elf_Ehdr
**hdr
, Elf_Phdr
**phdr
)
61 *hdr
= (Elf_Ehdr
*) exec_hdr
;
63 printf("elf_unpack: elf_sane failed\n");
66 *phdr
= (Elf_Phdr
*)(exec_hdr
+ (*hdr
)->e_phoff
);
67 if(!elf_ph_sane(*phdr
)) {
68 printf("elf_unpack: elf_ph_sane failed\n");
72 if((int)((*phdr
) + (*hdr
)->e_phnum
) >= hdr_len
) return ENOEXEC
;
77 #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
78 (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
79 (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
80 (ehdr).e_ident[EI_MAG3] == ELFMAG3)
82 static int check_header(Elf_Ehdr
*hdr
)
85 hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
||
86 hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
||
87 hdr
->e_phentsize
!= sizeof(Elf_Phdr
) ||
88 hdr
->e_version
!= ELF_TARG_VER
)
94 /* Return >0 if there is an ELF interpreter (i.e. it is a dynamically linked
95 * executable) and we could extract it successfully.
96 * Return 0 if there isn't one.
99 int elf_has_interpreter(char *exec_hdr
, /* executable header */
100 int hdr_len
, char *interp
, int maxsz
)
102 Elf_Ehdr
*hdr
= NULL
;
103 Elf_Phdr
*phdr
= NULL
;
106 if((e
=elf_unpack(exec_hdr
, hdr_len
, &hdr
, &phdr
)) != OK
) return 0;
108 for (i
= 0; i
< hdr
->e_phnum
; i
++) {
109 switch (phdr
[i
].p_type
) {
111 if(!interp
) return 1;
112 if(phdr
[i
].p_filesz
>= maxsz
)
114 if(phdr
[i
].p_offset
+ phdr
[i
].p_filesz
>= hdr_len
)
116 memcpy(interp
, exec_hdr
+ phdr
[i
].p_offset
, phdr
[i
].p_filesz
);
117 interp
[phdr
[i
].p_filesz
] = '\0';
126 int libexec_load_elf(struct exec_info
*execi
)
128 Elf_Ehdr
*hdr
= NULL
;
129 Elf_Phdr
*phdr
= NULL
;
132 vir_bytes startv
, stacklow
;
134 assert(execi
!= NULL
);
135 assert(execi
->hdr
!= NULL
);
137 if((e
=elf_unpack(execi
->hdr
, execi
->hdr_len
, &hdr
, &phdr
)) != OK
) {
138 printf("libexec_load_elf: elf_unpack failed\n");
142 /* this function can load the dynamic linker, but that
143 * shouldn't require an interpreter itself.
145 i
= elf_has_interpreter(execi
->hdr
, execi
->hdr_len
, NULL
, 0);
150 execi
->stack_size
= roundup(execi
->stack_size
, PAGE_SIZE
);
151 execi
->stack_high
= rounddown(execi
->stack_high
, PAGE_SIZE
);
152 stacklow
= execi
->stack_high
- execi
->stack_size
;
154 assert(execi
->copymem
);
155 assert(execi
->clearmem
);
156 assert(execi
->allocmem_prealloc
);
157 assert(execi
->allocmem_ondemand
);
159 if(execi
->clearproc
) execi
->clearproc(execi
);
161 for (i
= 0; i
< hdr
->e_phnum
; i
++) {
162 vir_bytes seg_membytes
, page_offset
, p_vaddr
, vaddr
;
163 vir_bytes chunk
, vfileend
, vmemend
;
164 Elf_Phdr
*ph
= &phdr
[i
];
165 if (ph
->p_type
!= PT_LOAD
|| ph
->p_memsz
== 0) continue;
166 vaddr
= p_vaddr
= ph
->p_vaddr
+ execi
->load_offset
;
167 seg_membytes
= ph
->p_memsz
;
168 page_offset
= vaddr
% PAGE_SIZE
;
169 vaddr
-= page_offset
;
170 seg_membytes
+= page_offset
;
171 seg_membytes
= roundup(seg_membytes
, PAGE_SIZE
);
172 if(first
|| startv
> vaddr
) startv
= vaddr
;
175 /* make us some memory */
176 if(execi
->allocmem_prealloc(execi
, vaddr
, seg_membytes
) != OK
) {
177 if(execi
->clearproc
) execi
->clearproc(execi
);
182 printf("mmapped 0x%lx-0x%lx\n", vaddr
, vaddr
+seg_membytes
);
185 /* Copy executable section into it */
186 if(execi
->copymem(execi
, ph
->p_offset
, p_vaddr
, ph
->p_filesz
) != OK
) {
187 if(execi
->clearproc
) execi
->clearproc(execi
);
192 printf("copied 0x%lx-0x%lx\n", p_vaddr
, p_vaddr
+ph
->p_filesz
);
195 /* Clear remaining bits */
196 vfileend
= p_vaddr
+ ph
->p_filesz
;
197 vmemend
= vaddr
+ seg_membytes
;
198 if((chunk
= p_vaddr
- vaddr
) > 0) {
200 printf("start clearing 0x%lx-0x%lx\n", vaddr
, vaddr
+chunk
);
202 execi
->clearmem(execi
, vaddr
, chunk
);
204 if((chunk
= vmemend
- vfileend
) > 0) {
206 printf("end clearing 0x%lx-0x%lx\n", vfileend
, vaddr
+chunk
);
208 execi
->clearmem(execi
, vfileend
, chunk
);
212 /* Make it a stack */
213 if(execi
->allocmem_ondemand(execi
, stacklow
, execi
->stack_size
) != OK
) {
214 if(execi
->clearproc
) execi
->clearproc(execi
);
219 printf("stack mmapped 0x%lx-0x%lx\n", stacklow
, stacklow
+execi
->stack_size
);
222 /* record entry point and lowest load vaddr for caller */
223 execi
->pc
= hdr
->e_entry
+ execi
->load_offset
;
224 execi
->load_base
= startv
;