diff --git a/tasks/mm0/src/lib/elf/elf.c b/tasks/mm0/src/lib/elf/elf.c index 1788926..168b97c 100644 --- a/tasks/mm0/src/lib/elf/elf.c +++ b/tasks/mm0/src/lib/elf/elf.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ int elf_test_expand_segment(struct elf_section_header *section, (section->sh_flags & sec_flmask) == sec_flags) { /* Set new section */ if (!*start) { + BUG_ON(*offset || *end); *offset = section->sh_offset; *start = section->sh_addr; *end = section->sh_addr + section->sh_size; @@ -49,13 +51,11 @@ int elf_test_expand_segment(struct elf_section_header *section, return 0; } + /* * Sift through sections and copy their marks to tcb and efd - * if they are recognised and loadable sections. - * - * NOTE: There may be multiple sections of same kind, in - * consecutive address regions. Then we need to increase - * that region's marks. + * if they are recognised and loadable sections. Test the + * assigned segment marks and return an error if they're invalid. */ int elf_mark_segments(struct elf_section_header *sect_header, int nsections, struct tcb *task, struct exec_file_desc *efd) @@ -64,24 +64,45 @@ int elf_mark_segments(struct elf_section_header *sect_header, int nsections, struct elf_section_header *section = §_header[i]; /* Text + read-only data segments */ - elf_test_expand_segment(section, SHT_PROGBITS, SHF_ALLOC, - SHF_ALLOC | SHF_WRITE, &task->text_start, - &task->text_end, &efd->text_offset); + elf_test_expand_segment(section, SHT_PROGBITS, + SHF_ALLOC, SHF_ALLOC | SHF_WRITE, + &task->text_start, &task->text_end, + &efd->text_offset); /* Data segment */ - elf_test_expand_segment(section, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE, - SHF_ALLOC | SHF_WRITE, &task->data_start, - &task->data_end, &efd->data_offset); + elf_test_expand_segment(section, SHT_PROGBITS, SHF_ALLOC | + SHF_WRITE, SHF_ALLOC | SHF_WRITE, + &task->data_start, &task->data_end, + &efd->data_offset); /* Bss segment */ - elf_test_expand_segment(section, SHT_NOBITS, SHF_ALLOC | SHF_WRITE, - SHF_ALLOC | SHF_WRITE, &task->bss_start, - &task->bss_end, &efd->bss_offset); + elf_test_expand_segment(section, SHT_NOBITS, SHF_ALLOC | + SHF_WRITE, SHF_ALLOC | SHF_WRITE, + &task->bss_start, &task->bss_end, + &efd->bss_offset); } - if (!task->text_start || !task->data_start || !task->bss_start) { - printf("%s: NOTE: Could not find one of text, data or " - "bss segments in elf file.\n", __FUNCTION__); + /* Test anomalies with the mappings */ + + /* No text */ + if (!task->text_start) { + printf("%s: Error: Could not find a text " + "segment in ELF file.\n", __FUNCTION__); + return -ENOEXEC; + } + + /* Warn if no data or bss but it's not an error */ + if (!task->data_start || !task->bss_start) { + printf("%s: NOTE: Could not find a data and/or " + "bss segment in ELF file.\n", __FUNCTION__); + } + + /* Data and text are less than page apart */ + if ((task->data_start - task->text_start) < PAGE_SIZE) { + printf("%s: Error: Distance between data and text" + " sections are less than page size (4K)\n", + __FUNCTION__); + return -ENOEXEC; } return 0; @@ -105,7 +126,7 @@ int elf_parse_executable(struct tcb *task, struct vm_file *file, struct elf_section_header *sect_header; unsigned long sect_offset, sect_size; unsigned long prg_offset, prg_size; - int err; + int err = 0; /* Test that it is a valid elf file */ if ((err = elf_probe(elf_headerp)) < 0) @@ -138,7 +159,8 @@ int elf_parse_executable(struct tcb *task, struct vm_file *file, sect_header = (struct elf_section_header *) pager_map_file_range(file, sect_offset, sect_size); - elf_mark_segments(sect_header, elf_header.e_shnum, task, efd); + /* Copy segment marks from ELF file to task + efd. Return errors */ + err = elf_mark_segments(sect_header, elf_header.e_shnum, task, efd); /* Unmap program header table */ pager_unmap_pages(prg_header_start, __pfn(page_align_up(prg_size))); @@ -146,6 +168,6 @@ int elf_parse_executable(struct tcb *task, struct vm_file *file, /* Unmap section header table */ pager_unmap_pages(sect_header, __pfn(page_align_up(sect_size))); - return 0; + return err; } diff --git a/tasks/mm0/src/task.c b/tasks/mm0/src/task.c index a7083e9..71c39c7 100644 --- a/tasks/mm0/src/task.c +++ b/tasks/mm0/src/task.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -342,12 +343,79 @@ struct tcb *task_create(struct tcb *parent, struct task_ids *ids, return task; } +/* + * If bss comes consecutively after the data section, prefault the + * last page of the data section and zero out the bit that contains + * the beginning of bss. If bss spans into more pages, then map those + * pages as anonymous pages which are mapped by the devzero file. + */ +int task_map_bss(struct vm_file *f, struct exec_file_desc *efd, struct tcb *task) +{ + unsigned long bss_mmap_start; + void *mapped; + + /* + * Test if bss starts right from the end of data, + * and not on a new page boundary. + */ + if ((task->data_end == task->bss_start) && + !is_page_aligned(task->bss_start)) { + unsigned long bss_size = task->bss_end - task->bss_start; + struct page *last_data_page; + void *pagebuf, *bss; + + /* Prefault the last data page */ + BUG_ON(prefault_page(task, task->data_end, + VM_READ | VM_WRITE) < 0); + /* Get the page */ + last_data_page = task_virt_to_page(task, task->data_end); + + /* Map the page */ + pagebuf = l4_map_helper((void *)page_to_phys(last_data_page), 1); + + /* Find the bss offset */ + bss = (void *)((unsigned long)pagebuf | + (PAGE_MASK & task->bss_start)); + + /* + * Zero out the part that is bss. This is minimum of either + * end of bss or until the end of page, whichever is met first. + */ + memset((void *)bss, 0, min(TILL_PAGE_ENDS(task->data_end), + (int)bss_size)); + + /* Unmap the page */ + l4_unmap_helper(pagebuf, 1); + + /* Push bss mmap start to next page */ + bss_mmap_start = page_align_up(task->bss_start); + } else /* Otherwise bss mmap start is same as bss_start */ + bss_mmap_start = task->bss_start; + + /* + * Now if there are more pages covering bss, + * map those as anonymous zero pages + */ + if (task->bss_end > bss_mmap_start) { + if (IS_ERR(mapped = do_mmap(0, 0, task, task->bss_start, + VM_READ | VM_WRITE | + VMA_PRIVATE | VMA_ANONYMOUS, + __pfn(page_align_up(task->bss_end) - + page_align(task->bss_start))))) { + printf("do_mmap: Mapping environment failed with %d.\n", + (int)mapped); + return (int)mapped; + } + } + + return 0; +} + int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_desc *efd) { void *mapped; struct vm_file *shm; - - /* Set up heap as one page after bss */ + int err; /* mmap task's text to task's address space. */ if (IS_ERR(mapped = do_mmap(file, efd->text_offset, task, task->text_start, @@ -368,14 +436,12 @@ int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_ } /* mmap task's bss as anonymous memory. */ - if (IS_ERR(mapped = do_mmap(0, 0, task, task->bss_start, - VM_READ | VM_WRITE | - VMA_PRIVATE | VMA_ANONYMOUS, - __pfn(task->bss_end - task->bss_start)))) { - printf("do_mmap: Mapping environment failed with %d.\n", - (int)mapped); - return (int)mapped; + if ((err = task_map_bss(file, efd, task)) < 0) { + printf("%s: Mapping bss has failed.\n", + __FUNCTION__); + return err; } + /* mmap task's environment as anonymous memory. */ if (IS_ERR(mapped = do_mmap(0, 0, task, task->env_start, VM_READ | VM_WRITE | diff --git a/tasks/test0/include/linker.lds b/tasks/test0/include/linker.lds index efa49eb..5870d33 100644 --- a/tasks/test0/include/linker.lds +++ b/tasks/test0/include/linker.lds @@ -30,9 +30,10 @@ SECTIONS /* rodata is needed else your strings will link at physical! */ .rodata : AT (ADDR(.rodata) - offset) { *(.rodata) } .rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) } + + . = ALIGN(4K); .data : AT (ADDR(.data) - offset) { - . = ALIGN(4K); _start_test1 = .; *(.test1) _end_test1 = .; diff --git a/tasks/test1/SConstruct b/tasks/test1/SConstruct deleted file mode 100644 index 5829ada..0000000 --- a/tasks/test1/SConstruct +++ /dev/null @@ -1,78 +0,0 @@ -# -# User space application build script -# -# Copyright (C) 2007 Bahadir Balban -# -import os -import sys -import shutil -from os.path import join -from glob import glob - -task_name = "test1" - -# The root directory of the repository where this file resides: -project_root = "../.." -tools_root = join(project_root, "tools") -prev_image = join(project_root, "tasks/test0/test0.axf") -libs_path = join(project_root, "libs") -ld_script = "include/linker.lds" -physical_base_ld_script = "include/physical_base.lds" - -# Libc situation: -# Libposix has uClibc (and therefore posix) headers. -# NICTA libc implements printf for us for now. -# Libposix implements posix calls for us, e.g. mmap. -# In conclusion nicta libc and libposix complement each other -# they should not clash. In future libposix will be part of uclibc -# and uclibc will be used. - -# libc paths: -libc_variant = "userspace" -libc_libpath = join(libs_path, "c/build/%s" % libc_variant) -libc_incpath = join(libc_libpath, "include") -libc_crt0 = join(libs_path, "c/build/crt/sys-userspace/arch-arm/crt0.o") -libc_name = "c-%s" % libc_variant - -# libposix paths: -libposix_libpath = "../libposix" -libposix_incpath = "../libposix/include/posix" - -# libl4 paths: -libl4_path = "../libl4" -libl4_incpath = join(libl4_path, "include") - -# kernel paths: -kernel_incpath = join(project_root, "include") - -# If crt0 is in its library path, it becomes hard to link with it. -# For instance the linker script must use an absolute path for it. -def copy_crt0(source, target, env): - os.system("cp " + str(source[0]) + " " + str(target[0])) - -def get_physical_base(source, target, env): - os.system(join(tools_root, "pyelf/readelf.py --first-free-page " + \ - prev_image + " >> " + physical_base_ld_script)) - -# The kernel build environment: -env = Environment(CC = 'arm-none-linux-gnueabi-gcc', - # We don't use -nostdinc because sometimes we need standard headers, - # such as stdarg.h e.g. for variable args, as in printk(). - CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror'], - LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path, \ - '-L' + libposix_libpath], - ASFLAGS = ['-D__ASSEMBLY__'], - PROGSUFFIX = '.axf', # The suffix to use for final executable - ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path - LIBS = [libc_name, 'gcc', libc_name, 'libl4', 'libposix'], - CPPFLAGS = "-D__USERSPACE__", - CPPPATH = ['#include', libl4_incpath, libposix_incpath, kernel_incpath]) - -src = [glob("src/*.c"), glob("*.c"), glob("src/arch/arm/*.c")] -objs = env.Object(src) -physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base) -crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0) - -task = env.Program(task_name, objs + [crt0_copied]) -env.Alias(task_name, task) -env.Depends(task, physical_base) diff --git a/tasks/test1/include/.gitignore b/tasks/test1/include/.gitignore deleted file mode 100644 index 2c1b19d..0000000 --- a/tasks/test1/include/.gitignore +++ /dev/null @@ -1 +0,0 @@ -physical_base.lds diff --git a/tasks/test1/include/linker.lds b/tasks/test1/include/linker.lds deleted file mode 100644 index 163e367..0000000 --- a/tasks/test1/include/linker.lds +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Simple linker script for userspace or svc tasks. - * - * Copyright (C) 2007 Bahadir Balban - */ - -/* - * The only catch with this linker script is that everything - * is linked starting at virtual_base, and loaded starting - * at physical_base. virtual_base is the predefined region - * of virtual memory for userland applications. physical_base - * is determined at build-time, it is one of the subsequent pages - * that come after the kernel image's load area. - */ -/* USER_AREA_START, see memlayout.h */ -virtual_base = 0x10000000; -__stack = 0x20000000; -INCLUDE "include/physical_base.lds" - -/* physical_base = 0x228000; */ -offset = virtual_base - physical_base; - -ENTRY(_start) - -SECTIONS -{ - . = virtual_base; - _start_text = .; - .text : AT (ADDR(.text) - offset) { crt0.o(.text) *(.text) } - /* rodata is needed else your strings will link at physical! */ - .rodata : AT (ADDR(.rodata) - offset) { *(.rodata) } - .rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) } - .data : AT (ADDR(.data) - offset) { *(.data) } - .bss : AT (ADDR(.bss) - offset) { *(.bss) } - _end = .; -} diff --git a/tasks/test1/include/tests.h b/tasks/test1/include/tests.h deleted file mode 100644 index 1b9b506..0000000 --- a/tasks/test1/include/tests.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __TEST0_TESTS_H__ -#define __TEST0_TESTS_H__ - -int shmtest(void); -int mmaptest(void); - -#endif /* __TEST0_TESTS_H__ */ diff --git a/tasks/test1/main.c b/tasks/test1/main.c deleted file mode 100644 index ac854c2..0000000 --- a/tasks/test1/main.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Some tests for posix syscalls. - * - * Copyright (C) 2007 Bahadir Balban - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define __TASKNAME__ "test0" - -void wait_pager(l4id_t partner) -{ - u32 tag = L4_IPC_TAG_WAIT; - printf("%s: Syncing with pager.\n", __TASKNAME__); - l4_send(partner, tag); - printf("Pager synced with us.\n"); -} - -void main(void) -{ - /* Sync with pager */ - wait_pager(0); - - /* Check mmap/munmap */ - mmaptest(); - - /* Check shmget/shmat/shmdt */ - shmtest(); -} - diff --git a/tasks/test1/src/mmaptest.c b/tasks/test1/src/mmaptest.c deleted file mode 100644 index c5fa918..0000000 --- a/tasks/test1/src/mmaptest.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Test mmap/munmap posix calls. - * - * Copyright (C) 2007 - 2008 Bahadir Balban - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PAGE_SIZE 0x1000 - -int mmaptest(void) -{ - int fd; - void *base; - int x = 0x1000; - - if ((fd = open("./newfile.txt", O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) < 0) - perror("open:"); - else - printf("open: Success.\n"); - - /* Extend the file */ - if ((int)lseek(fd, PAGE_SIZE*16, SEEK_SET) < 0) - perror("lseek"); - else - printf("lseek: Success.\n"); - - if (write(fd, &x, sizeof(x)) < 0) - perror("write"); - else - printf("write: Success.\n"); - - if ((int)(base = mmap(0, PAGE_SIZE*16, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) - perror("mmap"); - else - printf("mmap: Success: %p\n", base); - - *(unsigned int *)(base + PAGE_SIZE*2) = 0x1000; - if (msync(base + PAGE_SIZE*2, PAGE_SIZE, MS_SYNC) < 0) - perror("msync"); - else - printf("msync: Success: %p\n", base); - - if (munmap(base + PAGE_SIZE*2, PAGE_SIZE) < 0) - perror("munmap"); - else - printf("munmap: Success: %p\n", base); - *(unsigned int *)(base + PAGE_SIZE*3) = 0x1000; - *(unsigned int *)(base + PAGE_SIZE*1) = 0x1000; - - return 0; -} diff --git a/tasks/test1/src/mmaptest.c.orig b/tasks/test1/src/mmaptest.c.orig deleted file mode 100644 index c5fa918..0000000 --- a/tasks/test1/src/mmaptest.c.orig +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Test mmap/munmap posix calls. - * - * Copyright (C) 2007 - 2008 Bahadir Balban - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PAGE_SIZE 0x1000 - -int mmaptest(void) -{ - int fd; - void *base; - int x = 0x1000; - - if ((fd = open("./newfile.txt", O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) < 0) - perror("open:"); - else - printf("open: Success.\n"); - - /* Extend the file */ - if ((int)lseek(fd, PAGE_SIZE*16, SEEK_SET) < 0) - perror("lseek"); - else - printf("lseek: Success.\n"); - - if (write(fd, &x, sizeof(x)) < 0) - perror("write"); - else - printf("write: Success.\n"); - - if ((int)(base = mmap(0, PAGE_SIZE*16, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) - perror("mmap"); - else - printf("mmap: Success: %p\n", base); - - *(unsigned int *)(base + PAGE_SIZE*2) = 0x1000; - if (msync(base + PAGE_SIZE*2, PAGE_SIZE, MS_SYNC) < 0) - perror("msync"); - else - printf("msync: Success: %p\n", base); - - if (munmap(base + PAGE_SIZE*2, PAGE_SIZE) < 0) - perror("munmap"); - else - printf("munmap: Success: %p\n", base); - *(unsigned int *)(base + PAGE_SIZE*3) = 0x1000; - *(unsigned int *)(base + PAGE_SIZE*1) = 0x1000; - - return 0; -} diff --git a/tasks/test1/src/shmtest.c b/tasks/test1/src/shmtest.c deleted file mode 100644 index 2499bbb..0000000 --- a/tasks/test1/src/shmtest.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Test shmget/shmat/shmdt posix calls. - * - * Copyright (C) 2007 - 2008 Bahadir Balban - */ -#include -#include -#include -#include -#include -#include - -int shmtest(void) -{ - //key_t keys[2] = { 5, 10000 }; - key_t keys[2] = { 2, 3 }; - void *bases[2] = { 0 , 0 }; - int shmids[2]; - - printf("Initiating shmget()\n"); - for (int i = 0; i < 2; i++) { - if ((shmids[i] = shmget(keys[i], 27, IPC_CREAT | 0666)) < 0) { - printf("Call failed.\n"); - perror("SHMGET"); - } else - printf("SHMID returned: %d\n", shmids[i]); - } - printf("Now shmat()\n"); - for (int i = 0; i < 2; i++) { - if ((int)(bases[i] = shmat(shmids[i], NULL, 0)) == -1) - perror("SHMAT"); - else - printf("SHM base address returned: %p\n", bases[i]); - } - printf("Now shmdt()\n"); - for (int i = 0; i < 2; i++) { - if (shmdt(bases[i]) < 0) - perror("SHMDT"); - else - printf("SHM detached OK.\n"); - } - printf("Now shmat() again\n"); - for (int i = 0; i < 2; i++) { - if ((int)(bases[i] = shmat(shmids[i], NULL, 0)) == -1) - perror("SHMAT"); - else - printf("SHM base address returned: %p\n", bases[i]); - } - - return 0; -} diff --git a/tasks/test1/tools/generate_bootdesc.py b/tasks/test1/tools/generate_bootdesc.py deleted file mode 100755 index 9761a6d..0000000 --- a/tasks/test1/tools/generate_bootdesc.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python -import os -import sys - -compiler_prefix = "arm-linux-" -objdump = "objdump" -command = "-t" -image_name = "roottask.axf" -linkoutput_file_suffix = "-linkinfo.txt" -linkoutput_file = image_name + linkoutput_file_suffix -def generate_bootdesc(): - command = compiler_prefix + objdump + " -t " + image_name + " > " + linkoutput_file - print command - os.system(command) - f = open(linkoutput_file, "r") - - while True: - line = f.readline() - if len(line) is 0: - break - if "_start" in line or "_end" in line: - print line - f.close() - -if __name__ == "__main__": - generate_bootdesc() -