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
;
65 *phdr
= (Elf_Phdr
*)(exec_hdr
+ (*hdr
)->e_phoff
);
66 if(!elf_ph_sane(*phdr
)) {
70 if((int)((*phdr
) + (*hdr
)->e_phnum
) >= hdr_len
) return ENOEXEC
;
75 #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
76 (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
77 (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
78 (ehdr).e_ident[EI_MAG3] == ELFMAG3)
80 static int check_header(Elf_Ehdr
*hdr
)
83 hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
||
84 hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
||
85 hdr
->e_phentsize
!= sizeof(Elf_Phdr
) ||
86 hdr
->e_version
!= ELF_TARG_VER
)
92 /* Return >0 if there is an ELF interpreter (i.e. it is a dynamically linked
93 * executable) and we could extract it successfully.
94 * Return 0 if there isn't one.
97 int elf_has_interpreter(char *exec_hdr
, /* executable header */
98 int hdr_len
, char *interp
, int maxsz
)
100 Elf_Ehdr
*hdr
= NULL
;
101 Elf_Phdr
*phdr
= NULL
;
104 if((e
=elf_unpack(exec_hdr
, hdr_len
, &hdr
, &phdr
)) != OK
) return 0;
106 for (i
= 0; i
< hdr
->e_phnum
; i
++) {
107 switch (phdr
[i
].p_type
) {
109 if(!interp
) return 1;
110 if(phdr
[i
].p_filesz
>= maxsz
)
112 if(phdr
[i
].p_offset
+ phdr
[i
].p_filesz
>= hdr_len
)
114 memcpy(interp
, exec_hdr
+ phdr
[i
].p_offset
, phdr
[i
].p_filesz
);
115 interp
[phdr
[i
].p_filesz
] = '\0';
124 int libexec_load_elf(struct exec_info
*execi
)
126 Elf_Ehdr
*hdr
= NULL
;
127 Elf_Phdr
*phdr
= NULL
;
130 vir_bytes startv
= 0, stacklow
;
132 assert(execi
!= NULL
);
133 assert(execi
->hdr
!= NULL
);
135 if((e
=elf_unpack(execi
->hdr
, execi
->hdr_len
, &hdr
, &phdr
)) != OK
) {
139 /* this function can load the dynamic linker, but that
140 * shouldn't require an interpreter itself.
142 i
= elf_has_interpreter(execi
->hdr
, execi
->hdr_len
, NULL
, 0);
147 execi
->stack_size
= roundup(execi
->stack_size
, PAGE_SIZE
);
148 execi
->stack_high
= rounddown(execi
->stack_high
, PAGE_SIZE
);
149 stacklow
= execi
->stack_high
- execi
->stack_size
;
151 assert(execi
->copymem
);
152 assert(execi
->clearmem
);
153 assert(execi
->allocmem_prealloc
);
154 assert(execi
->allocmem_ondemand
);
156 for (i
= 0; i
< hdr
->e_phnum
; i
++) {
157 Elf_Phdr
*ph
= &phdr
[i
];
158 off_t file_limit
= ph
->p_offset
+ ph
->p_filesz
;
159 /* sanity check binary before wiping out the target process */
160 if(execi
->filesize
< file_limit
) {
165 if(execi
->clearproc
) execi
->clearproc(execi
);
167 for (i
= 0; i
< hdr
->e_phnum
; i
++) {
168 vir_bytes seg_membytes
, page_offset
, p_vaddr
, vaddr
;
169 vir_bytes chunk
, vfileend
, vmemend
;
170 Elf_Phdr
*ph
= &phdr
[i
];
171 if (ph
->p_type
!= PT_LOAD
|| ph
->p_memsz
== 0) continue;
172 vaddr
= p_vaddr
= ph
->p_vaddr
+ execi
->load_offset
;
173 seg_membytes
= ph
->p_memsz
;
174 page_offset
= vaddr
% PAGE_SIZE
;
175 vaddr
-= page_offset
;
176 seg_membytes
+= page_offset
;
177 seg_membytes
= roundup(seg_membytes
, PAGE_SIZE
);
178 if(first
|| startv
> vaddr
) startv
= vaddr
;
181 /* make us some memory */
182 if(execi
->allocmem_prealloc(execi
, vaddr
, seg_membytes
) != OK
) {
183 if(execi
->clearproc
) execi
->clearproc(execi
);
188 printf("mmapped 0x%lx-0x%lx\n", vaddr
, vaddr
+seg_membytes
);
191 /* Copy executable section into it */
192 if(execi
->copymem(execi
, ph
->p_offset
, p_vaddr
, ph
->p_filesz
) != OK
) {
193 if(execi
->clearproc
) execi
->clearproc(execi
);
198 printf("copied 0x%lx-0x%lx\n", p_vaddr
, p_vaddr
+ph
->p_filesz
);
201 /* Clear remaining bits */
202 vfileend
= p_vaddr
+ ph
->p_filesz
;
203 vmemend
= vaddr
+ seg_membytes
;
204 if((chunk
= p_vaddr
- vaddr
) > 0) {
206 printf("start clearing 0x%lx-0x%lx\n", vaddr
, vaddr
+chunk
);
208 execi
->clearmem(execi
, vaddr
, chunk
);
210 if((chunk
= vmemend
- vfileend
) > 0) {
212 printf("end clearing 0x%lx-0x%lx\n", vfileend
, vaddr
+chunk
);
214 execi
->clearmem(execi
, vfileend
, chunk
);
218 /* Make it a stack */
219 if(execi
->allocmem_ondemand(execi
, stacklow
, execi
->stack_size
) != OK
) {
220 if(execi
->clearproc
) execi
->clearproc(execi
);
225 printf("stack mmapped 0x%lx-0x%lx\n", stacklow
, stacklow
+execi
->stack_size
);
228 /* record entry point and lowest load vaddr for caller */
229 execi
->pc
= hdr
->e_entry
+ execi
->load_offset
;
230 execi
->load_base
= startv
;