1 #include "userprog/addrspace.h"
7 #include "userprog/pagedir.h"
8 #include "userprog/tss.h"
9 #include "filesys/directory.h"
10 #include "filesys/file.h"
11 #include "filesys/filesys.h"
12 #include "threads/init.h"
13 #include "threads/mmu.h"
14 #include "threads/palloc.h"
15 #include "threads/thread.h"
17 /* We load ELF binaries. The following definitions are taken
18 from the ELF specification, [ELF1], more-or-less verbatim. */
20 /* ELF types. See [ELF1] 1-2. */
21 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
22 typedef uint16_t Elf32_Half;
24 /* For use with ELF types in printf(). */
25 #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
26 #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
27 #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
28 #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
30 /* Executable header. See [ELF1] 1-4 to 1-8.
31 This appears at the very beginning of an ELF binary. */
34 unsigned char e_ident[16];
43 Elf32_Half e_phentsize;
45 Elf32_Half e_shentsize;
47 Elf32_Half e_shstrndx;
50 /* Program header. See [ELF1] 2-2 to 2-4.
51 There are e_phnum of these, starting at file offset e_phoff
65 /* Values for p_type. See [ELF1] 2-3. */
66 #define PT_NULL 0 /* Ignore. */
67 #define PT_LOAD 1 /* Loadable segment. */
68 #define PT_DYNAMIC 2 /* Dynamic linking info. */
69 #define PT_INTERP 3 /* Name of dynamic loader. */
70 #define PT_NOTE 4 /* Auxiliary info. */
71 #define PT_SHLIB 5 /* Reserved. */
72 #define PT_PHDR 6 /* Program header table. */
73 #define PT_STACK 0x6474e551 /* Stack segment. */
75 /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */
76 #define PF_X 1 /* Executable. */
77 #define PF_W 2 /* Writable. */
78 #define PF_R 4 /* Readable. */
80 static bool load_segment (struct thread *, struct file *,
81 const struct Elf32_Phdr *);
82 static bool setup_stack (struct thread *, void **esp);
84 /* Aborts loading an executable, with an error message. */
85 #define LOAD_ERROR(MSG) \
87 printf ("addrspace_load: %s: ", filename); \
93 /* Loads an ELF executable from FILENAME into T,
94 Stores the executable's entry point into *EIP
95 and its initial stack pointer into *ESP.
96 Returns true if successful, false otherwise. */
98 addrspace_load (struct thread *t, const char *filename,
99 void (**eip) (void), void **esp)
101 struct Elf32_Ehdr ehdr;
102 struct file *file = NULL;
104 bool success = false;
107 /* Allocate page directory. */
108 t->pagedir = pagedir_create ();
109 if (t->pagedir == NULL)
110 LOAD_ERROR (("page directory allocation failed"));
112 /* Open executable file. */
113 file = filesys_open (filename);
115 LOAD_ERROR (("open failed"));
117 /* Read and verify executable header. */
118 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr)
119 LOAD_ERROR (("error reading executable header"));
120 if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
121 LOAD_ERROR (("file is not ELF"));
122 if (ehdr.e_type != 2)
123 LOAD_ERROR (("ELF file is not an executable"));
124 if (ehdr.e_machine != 3)
125 LOAD_ERROR (("ELF executable is not x86"));
126 if (ehdr.e_version != 1)
127 LOAD_ERROR (("ELF executable hasunknown version %d",
128 (int) ehdr.e_version));
129 if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
130 LOAD_ERROR (("bad ELF program header size"));
131 if (ehdr.e_phnum > 1024)
132 LOAD_ERROR (("too many ELF program headers"));
134 /* Read program headers. */
135 file_ofs = ehdr.e_phoff;
136 for (i = 0; i < ehdr.e_phnum; i++)
138 struct Elf32_Phdr phdr;
140 file_seek (file, file_ofs);
141 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
142 LOAD_ERROR (("error reading program header"));
143 file_ofs += sizeof phdr;
150 /* Ignore this segment. */
155 /* Reject the executable. */
156 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
159 printf ("unknown ELF segment type %08x\n", phdr.p_type);
162 if (!load_segment (t, file, &phdr))
169 if (!setup_stack (t, esp))
173 *eip = (void (*) (void)) ehdr.e_entry;
178 /* We arrive here whether the load is successful or not.
179 We can distinguish based on `success'. */
182 addrspace_destroy (t);
186 /* Destroys the user address space in T and frees all of its
189 addrspace_destroy (struct thread *t)
191 if (t->pagedir != NULL)
193 pagedir_destroy (t->pagedir);
198 /* Sets up the CPU for running user code in thread T, if any. */
200 addrspace_activate (struct thread *t)
204 /* Activate T's page tables. */
205 pagedir_activate (t->pagedir);
207 /* Set T's kernel stack for use in processing interrupts. */
208 tss_set_esp0 ((uint8_t *) t + PGSIZE);
211 /* addrspace_load() helpers. */
213 static bool install_page (struct thread *, void *upage, void *kpage);
215 /* Loads the segment described by PHDR from FILE into thread T's
216 user address space. Return true if successful, false
219 load_segment (struct thread *t, struct file *file,
220 const struct Elf32_Phdr *phdr)
222 void *start, *end; /* Page-rounded segment start and end. */
223 uint8_t *upage; /* Iterator from start to end. */
224 off_t filesz_left; /* Bytes left of file data (as opposed to
225 zero-initialized bytes). */
227 /* Is this a read-only segment? Not currently used, so it's
228 commented out. You'll want to use it when implementing VM
229 to decide whether to page the segment from its executable or
231 //bool read_only = (phdr->p_flags & PF_W) == 0;
234 ASSERT (file != NULL);
235 ASSERT (phdr != NULL);
236 ASSERT (phdr->p_type == PT_LOAD);
238 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
240 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
242 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
243 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
247 /* [ELF1] 2-3 says that p_memsz must be at least as big as
249 if (phdr->p_memsz < phdr->p_filesz)
251 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
252 phdr->p_memsz, phdr->p_filesz);
256 /* Validate virtual memory region to be mapped.
257 The region must both start and end within the user address
258 space range starting at 0 and ending at PHYS_BASE (typically
259 3 GB == 0xc0000000). */
260 start = pg_round_down ((void *) phdr->p_vaddr);
261 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
262 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
264 printf ("bad virtual region %08lx...%08lx\n",
265 (unsigned long) start, (unsigned long) end);
269 /* Load the segment page-by-page into memory. */
270 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
271 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
272 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
274 /* We want to read min(PGSIZE, filesz_left) bytes from the
275 file into the page and zero the rest. */
276 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
277 size_t zero_bytes = PGSIZE - read_bytes;
278 uint8_t *kpage = palloc_get (PAL_USER);
282 /* Do the reading and zeroing. */
283 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
288 memset (kpage + read_bytes, 0, zero_bytes);
289 filesz_left -= read_bytes;
291 /* Add the page to the process's address space. */
292 if (!install_page (t, upage, kpage))
302 /* Create a minimal stack for T by mapping a zeroed page at the
303 top of user virtual memory. */
305 setup_stack (struct thread *t, void **esp)
308 bool success = false;
310 kpage = palloc_get (PAL_USER | PAL_ZERO);
313 success = install_page (t, ((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
320 printf ("failed to allocate process stack\n");
325 /* Adds a mapping from user virtual address UPAGE to kernel
326 virtual address KPAGE to T's page tables. Fails if UPAGE is
327 already mapped or if memory allocation fails. */
329 install_page (struct thread *t, void *upage, void *kpage)
331 /* Verify that there's not already a page at that virtual
332 address, then map our page there. */
333 return (pagedir_get_page (t->pagedir, upage) == NULL
334 && pagedir_set_page (t->pagedir, upage, kpage, true));