# HG changeset patch # User Paul Boddie # Date 1651527937 -7200 # Node ID 8d9befa7772993163ef81e54833125f787802495 # Parent db518b1b88d7922bf08781fb6ab753726f3ca345 Introduced a segment abstraction to handle the different payload segments. diff -r db518b1b88d7 -r 8d9befa77729 tests/dstest_exec.cc --- a/tests/dstest_exec.cc Sun May 01 23:25:09 2022 +0200 +++ b/tests/dstest_exec.cc Mon May 02 23:45:37 2022 +0200 @@ -72,12 +72,104 @@ } }; -typedef std::map Regions; + + +/* Program segment abstraction. */ + +class Segment +{ +protected: + Region _region; + +public: + /* Allocated memory. */ + + char *buf; + l4re_ds_t ds; + + /* Segment base and corresponding region base. */ + + l4_addr_t base, region_base; + + /* Segment size and corresponding region size. */ + + offset_t size, region_size; + + /* Offset of segment content within the region. */ + + offset_t region_offset; + + /* Access flags. */ + + l4re_rm_flags_t flags; + + /* File access details. */ + + offset_t file_offset, file_contents; + + explicit Segment(offset_t base, offset_t size, l4re_rm_flags_t flags, + offset_t file_offset = 0, offset_t file_contents = 0) + : base(base), size(size), flags(flags), file_offset(file_offset), file_contents(file_contents) + { + region_base = trunc(base, L4_PAGESIZE); + region_offset = base - region_base; + region_size = round(size, L4_PAGESIZE); + } + + long allocate(); + + long fill(file_t *file); + + Region ®ion(); + + l4_addr_t region_address(char *address); + + l4_addr_t region_address(l4_addr_t address); +}; + +long Segment::allocate() +{ + return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | flags, + L4_PAGESHIFT, (void **) &buf, &ds); +} + +long Segment::fill(file_t *file) +{ + if (!file_contents) + return L4_EOK; + + memset(buf, 0, region_size); + client_seek(file, file_offset, SEEK_SET); + offset_t nread = client_read(file, buf + region_offset, file_contents); + + if (nread < file_contents) + return -L4_EIO; + else + return L4_EOK; +} + +Region &Segment::region() +{ + _region = Region((l4_addr_t) buf, page_order(region_size), flags, region_base); + return _region; +} + +l4_addr_t Segment::region_address(char *address) +{ + return (l4_addr_t) ((address - buf) + (char *) region_base); +} + +l4_addr_t Segment::region_address(l4_addr_t address) +{ + return (address - (l4_addr_t) buf) + region_base; +} /* A simple system pager also acting as a region mapper. */ +typedef std::map Regions; + class ExecPager : public PagerObject { protected: @@ -405,61 +497,39 @@ /* Copy the payload regions to new dataspaces. NOTE: This should be directed by the ELF metadata. */ - address_t program_region_base = 0x1000000; address_t program_start = 0x1000af3; - char *program_buf; - offset_t nread; - offset_t program_region_contents = 0x282ae; - offset_t program_region_size = round(program_region_contents, L4_PAGESIZE); - l4re_ds_t program_region_ds; + Segment program(0x1000000, 0x282ae, L4_FPAGE_RWX, 0, 0x282ae); + Segment data(0x1029360, 0x8068, L4_FPAGE_RW, 0x28360, 0x2058); + Segment stack(0x80000000, 16 * L4_PAGESIZE, L4_FPAGE_RW); + Segment *segments[] = {&program, &data, &stack, NULL}; + Segment **segment; + + for (segment = segments; *segment != NULL; segment++) + { + err = (*segment)->allocate(); - err = ipc_allocate_align(program_region_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX, - L4_PAGESHIFT, (void **) &program_buf, &program_region_ds); + if (err) + { + printf("Could not reserve memory.\n"); + return 1; + } - if (err) - { - printf("Could not reserve program memory.\n"); - return 1; + err = (*segment)->fill(file); + + if (err) + { + printf("Could not fill segment from file.\n"); + return 1; + } } - nread = client_read(file, program_buf, program_region_contents); - - printf("Read %ld from file into %p.\n", nread, program_buf); - - if (memcmp(program_buf + program_start - program_region_base, "\x31\xed", 2)) + if (memcmp(program.buf + program_start - program.region_base, "\x31\xed", 2)) { printf("Did not find expected instructions at start.\n"); return 1; } - offset_t data_region_start = 0x1029360; - offset_t data_region_size = round(0x8068, L4_PAGESIZE); - offset_t data_region_base = trunc(data_region_start, L4_PAGESIZE); - offset_t data_region_offset = data_region_start - data_region_base; - - char *data_buf; - offset_t data_file_offset = 0x28360; - offset_t data_region_contents = 0x2058; - l4re_ds_t data_region_ds; - - err = ipc_allocate_align(data_region_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, - L4_PAGESHIFT, (void **) &data_buf, &data_region_ds); - - if (err) - { - printf("Could not reserve data memory.\n"); - return 1; - } - - memset(data_buf, 0, data_region_size); - - client_seek(file, data_file_offset, SEEK_SET); - nread = client_read(file, data_buf + data_region_offset, data_region_contents); - - printf("Read %ld from file into %p in region %p with size %ld for %lx.\n", - nread, data_buf + data_region_offset, data_buf, data_region_size, data_region_base); - /* UTCB location and size. */ l4_addr_t utcb_start = Utcb_area_start; @@ -478,25 +548,9 @@ printf("KIP at %lx.\n", kip_start); - /* Stack allocation. */ - - l4_addr_t stack_buf; - offset_t stack_size = 16 * L4_PAGESIZE; - l4_addr_t stack_region_base = 0x8000000 - stack_size; - l4re_ds_t stack_ds; - - err = ipc_allocate_align(stack_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, - L4_PAGESHIFT, (void **) &stack_buf, &stack_ds); - - if (err) - { - printf("Could not reserve stack.\n"); - return 1; - } - /* Populate stack with additional capabilities. */ - l4re_env_cap_entry_t *stack_env_cap = (l4re_env_cap_entry_t *) (stack_buf + stack_size); + l4re_env_cap_entry_t *stack_env_cap = (l4re_env_cap_entry_t *) (stack.buf + stack.size); /* Special invalid/terminating environment capability entry. */ @@ -516,7 +570,7 @@ memset(stack_arg, 0, (char *) stack_element - stack_arg); memcpy(stack_arg, argv[1], strlen(argv[1])); - printf("Stack L4 program argument: %p / %lx\n", stack_arg, ((l4_addr_t) stack_arg - stack_buf) + stack_region_base); + printf("Stack L4 program argument: %p / %lx\n", stack_arg, stack.region_address(stack_arg)); stack_element = (l4_umword_t *) stack_arg; @@ -527,7 +581,7 @@ *(--stack_element) = 0; *(--stack_element) = 0x14 << L4_CAP_SHIFT; - printf("Stack L4 aux elements: %p / %lx\n", stack_element, ((l4_addr_t) stack_element - stack_buf) + stack_region_base); + printf("Stack L4 aux elements: %p / %lx\n", stack_element, stack.region_address((char *) stack_element)); /* Populate stack with standard capabilities. */ @@ -541,7 +595,7 @@ env->rm = 0x11 << L4_CAP_SHIFT; env->mem_alloc = 0x12 << L4_CAP_SHIFT; env->first_free_cap = 0x15; - env->caps = (l4re_env_cap_entry_t *) (caps_start - stack_buf) + stack_region_base; + env->caps = (l4re_env_cap_entry_t *) (stack.region_address(caps_start)); env->utcb_area = utcb_fpage; env->first_free_utcb = utcb_start + L4_UTCB_OFFSET; @@ -556,7 +610,7 @@ /* L4Re global environment pointer. */ - *(--stack_element) = ((l4_addr_t) env - stack_buf) + stack_region_base; + *(--stack_element) = stack.region_address((char *) env); *(--stack_element) = 0xf1; /* Apparently required entries. */ @@ -578,7 +632,7 @@ l4_addr_t stack_data_end = (l4_addr_t) stack_element; - printf("Stack L4 data: %lx / %lx\n", stack_data_end, (stack_data_end - stack_buf) + stack_region_base); + printf("Stack L4 data: %lx / %lx\n", stack_data_end, stack.region_address(stack_data_end)); /* No environment pointers. */ @@ -588,7 +642,7 @@ /* NOTE: Just one argument currently. */ *(--stack_element) = 0; - *(--stack_element) = (l4_umword_t) ((l4_addr_t) stack_arg - stack_buf) + stack_region_base; + *(--stack_element) = (l4_umword_t) (stack.region_address(stack_arg)); *(--stack_element) = 1; char *stack_adjusted = Ldr::adjust_sp((char *) stack_element, NULL); @@ -602,9 +656,9 @@ printf("%ld %lx %lx\n", stack_adjusted_element[0], stack_adjusted_element[1], stack_adjusted_element[2]); - l4_addr_t stack_start = ((l4_addr_t) stack_adjusted - stack_buf) + stack_region_base; + l4_addr_t stack_start = stack.region_address(stack_adjusted); - printf("Stack L4 start: %p / %lx\n", stack_adjusted, ((l4_addr_t) stack_adjusted - stack_buf) + stack_region_base); + printf("Stack L4 start: %p / %lx\n", stack_adjusted, stack.region_address(stack_adjusted)); /* Create a new task and thread. */ @@ -635,9 +689,8 @@ init_pager(&config); - exec_pager.add(Region((l4_addr_t) program_buf, page_order(program_region_size), L4_FPAGE_RX, program_region_base)); - exec_pager.add(Region((l4_addr_t) data_buf, page_order(data_region_size), L4_FPAGE_RW, data_region_base)); - exec_pager.add(Region((l4_addr_t) stack_buf, page_order(stack_size), L4_FPAGE_RW, stack_region_base)); + for (segment = segments; *segment != NULL; segment++) + exec_pager.add((*segment)->region()); err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config); @@ -711,7 +764,7 @@ printf("Schedule thread...\n"); - printf("Stack at 0x%lx mapped to region at 0x%lx.\n", stack_start, stack_region_base); + printf("Stack at 0x%lx mapped to region at 0x%lx.\n", stack_start, stack.region_base); err = l4_error(l4_thread_ex_regs(thread, program_start, stack_start, 0));