1.1 --- a/libexec/include/exec/segment.h Tue May 10 22:39:15 2022 +0200
1.2 +++ b/libexec/include/exec/segment.h Wed May 11 01:23:28 2022 +0200
1.3 @@ -63,7 +63,7 @@
1.4
1.5 offset_t file_offset, file_contents;
1.6
1.7 - explicit Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
1.8 + explicit Segment(l4_addr_t base, offset_t size, l4re_rm_flags_t flags,
1.9 offset_t file_offset = 0, offset_t file_contents = 0);
1.10
1.11 long allocate();
2.1 --- a/libexec/lib/src/segment.cc Tue May 10 22:39:15 2022 +0200
2.2 +++ b/libexec/lib/src/segment.cc Wed May 11 01:23:28 2022 +0200
2.3 @@ -33,7 +33,7 @@
2.4
2.5 /* Initialise a memory segment. */
2.6
2.7 -Segment::Segment(offset_t base, offset_t size, l4re_rm_flags_t flags,
2.8 +Segment::Segment(l4_addr_t base, offset_t size, l4re_rm_flags_t flags,
2.9 offset_t file_offset, offset_t file_contents)
2.10 : base(base), size(size), flags(flags), file_offset(file_offset),
2.11 file_contents(file_contents)
2.12 @@ -47,7 +47,14 @@
2.13
2.14 long Segment::allocate()
2.15 {
2.16 - return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | flags,
2.17 + /* Make regions writable if they need to be filled. */
2.18 +
2.19 + l4re_rm_flags_t allocation_flags = flags;
2.20 +
2.21 + if (file_contents)
2.22 + allocation_flags |= L4RE_RM_F_W;
2.23 +
2.24 + return ipc_allocate_align(size, L4RE_RM_F_SEARCH_ADDR | allocation_flags,
2.25 L4_PAGESHIFT, (void **) &buf, &ds);
2.26 }
2.27
3.1 --- a/tests/dstest_exec.cc Tue May 10 22:39:15 2022 +0200
3.2 +++ b/tests/dstest_exec.cc Wed May 11 01:23:28 2022 +0200
3.3 @@ -275,21 +275,103 @@
3.4
3.5
3.6
3.7 -class PayloadBase
3.8 +/* Generic program segment interface. */
3.9 +
3.10 +class ProgramSegment
3.11 +{
3.12 +public:
3.13 + virtual bool loadable() = 0;
3.14 + virtual offset_t file_contents() = 0;
3.15 + virtual offset_t file_offset() = 0;
3.16 + virtual l4_addr_t region_address() = 0;
3.17 + virtual offset_t region_size() = 0;
3.18 + virtual l4re_rm_flags_t region_flags() = 0;
3.19 +
3.20 + Segment *segment()
3.21 + {
3.22 + return new Segment(
3.23 + region_address(),
3.24 + region_size(),
3.25 + region_flags(),
3.26 + file_offset(),
3.27 + file_contents());
3.28 + }
3.29 +};
3.30 +
3.31 +template <typename PROGRAM_HEADER>
3.32 +class ProgramSegmentVariant : public ProgramSegment
3.33 +{
3.34 +protected:
3.35 + PROGRAM_HEADER *_header;
3.36 +
3.37 +public:
3.38 + explicit ProgramSegmentVariant(PROGRAM_HEADER *header)
3.39 + : _header(header)
3.40 + {
3.41 + }
3.42 +
3.43 + bool loadable()
3.44 + {
3.45 + return _header->p_type == PT_LOAD;
3.46 + }
3.47 +
3.48 + offset_t file_contents()
3.49 + {
3.50 + return _header->p_filesz;
3.51 + }
3.52 +
3.53 + offset_t file_offset()
3.54 + {
3.55 + return _header->p_offset;
3.56 + }
3.57 +
3.58 + l4_addr_t region_address()
3.59 + {
3.60 + return _header->p_vaddr;
3.61 + }
3.62 +
3.63 + offset_t region_size()
3.64 + {
3.65 + return _header->p_memsz;
3.66 + }
3.67 +
3.68 + l4re_rm_flags_t region_flags()
3.69 + {
3.70 + l4re_rm_flags_t flags = 0;
3.71 +
3.72 + if (_header->p_flags & PF_R)
3.73 + flags |= L4RE_RM_F_R;
3.74 + if (_header->p_flags & PF_W)
3.75 + flags |= L4RE_RM_F_W;
3.76 + if (_header->p_flags & PF_X)
3.77 + flags |= L4RE_RM_F_X;
3.78 +
3.79 + return flags;
3.80 + }
3.81 +};
3.82 +
3.83 +
3.84 +
3.85 +/* Generic interface for an ELF payload. */
3.86 +
3.87 +class Payload
3.88 {
3.89 public:
3.90 virtual l4_addr_t entry_point() = 0;
3.91 - virtual offset_t header_size() = 0;
3.92 + virtual offset_t header_extent() = 0;
3.93 + virtual offset_t program_header_extent() = 0;
3.94 + virtual unsigned int segments() = 0;
3.95 + virtual ProgramSegment *segment(unsigned int i) = 0;
3.96 };
3.97
3.98 -template <typename HEADER>
3.99 -class Payload : public PayloadBase
3.100 +template <typename HEADER, typename PROGRAM_HEADER>
3.101 +class PayloadVariant : public Payload
3.102 {
3.103 protected:
3.104 HEADER *_header;
3.105
3.106 public:
3.107 - explicit Payload(HEADER *header)
3.108 + explicit PayloadVariant(HEADER *header)
3.109 : _header(header)
3.110 {
3.111 }
3.112 @@ -299,20 +381,40 @@
3.113 return _header->e_entry;
3.114 }
3.115
3.116 - offset_t header_size()
3.117 + offset_t header_extent()
3.118 {
3.119 return sizeof(HEADER);
3.120 }
3.121 +
3.122 + offset_t program_header_extent()
3.123 + {
3.124 + return _header->e_phoff + _header->e_phentsize * _header->e_phnum;
3.125 + }
3.126 +
3.127 + unsigned int segments()
3.128 + {
3.129 + return _header->e_phnum;
3.130 + }
3.131 +
3.132 + ProgramSegment *segment(unsigned int i)
3.133 + {
3.134 + if (i >= segments())
3.135 + return NULL;
3.136 +
3.137 + return new ProgramSegmentVariant<PROGRAM_HEADER>(
3.138 + (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff +
3.139 + _header->e_phentsize * i));
3.140 + }
3.141 };
3.142
3.143 -static PayloadBase *get_payload(char *buf)
3.144 +static Payload *get_payload(char *buf)
3.145 {
3.146 switch (buf[EI_CLASS])
3.147 {
3.148 case (char) 1:
3.149 - return new Payload<Elf32_Ehdr>((Elf32_Ehdr *) buf);
3.150 + return new PayloadVariant<Elf32_Ehdr, Elf32_Phdr>((Elf32_Ehdr *) buf);
3.151 case (char) 2:
3.152 - return new Payload<Elf64_Ehdr>((Elf64_Ehdr *) buf);
3.153 + return new PayloadVariant<Elf64_Ehdr, Elf64_Phdr>((Elf64_Ehdr *) buf);
3.154 default:
3.155 return NULL;
3.156 }
3.157 @@ -374,7 +476,7 @@
3.158 return 1;
3.159 }
3.160
3.161 - PayloadBase *payload = get_payload(buf);
3.162 + Payload *payload = get_payload(buf);
3.163
3.164 if (payload == NULL)
3.165 {
3.166 @@ -383,9 +485,9 @@
3.167 }
3.168
3.169 client_seek(file, 0, SEEK_SET);
3.170 - nread = client_read(file, buf, payload->header_size());
3.171 + nread = client_read(file, buf, payload->header_extent());
3.172
3.173 - if (nread < payload->header_size())
3.174 + if (nread < payload->header_extent())
3.175 {
3.176 printf("Header incomplete.\n");
3.177 return 1;
3.178 @@ -393,21 +495,55 @@
3.179
3.180 printf("Program start: %lx\n", payload->entry_point());
3.181
3.182 - /* Copy the payload regions to new dataspaces.
3.183 - NOTE: This should be directed by the ELF metadata. */
3.184 + client_seek(file, 0, SEEK_SET);
3.185 + nread = client_read(file, buf, payload->program_header_extent());
3.186 +
3.187 + if (nread < payload->program_header_extent())
3.188 + {
3.189 + printf("Program headers incomplete.\n");
3.190 + return 1;
3.191 + }
3.192 +
3.193 + /* Make appropriate segments, although program segments could be made
3.194 + interoperable with these. */
3.195 +
3.196 + Segment *segments[payload->segments() + 1];
3.197 +
3.198 + for (unsigned int i = 0; i < payload->segments(); i++)
3.199 + {
3.200 + ProgramSegment *ps = payload->segment(i);
3.201 +
3.202 + printf("Segment(0x%lx, 0x%lx, 0x%x, 0x%lx, 0x%lx): %s\n",
3.203 + ps->region_address(),
3.204 + ps->region_size(),
3.205 + ps->region_flags(),
3.206 + ps->file_offset(),
3.207 + ps->file_contents(),
3.208 + ps->loadable() ? "loadable" : "other");
3.209 +
3.210 + if (ps->loadable())
3.211 + segments[i] = ps->segment();
3.212 + else
3.213 + segments[i] = NULL;
3.214 + }
3.215 +
3.216 + /* Copy the payload regions to new dataspaces. */
3.217
3.218 address_t program_start = payload->entry_point();
3.219 offset_t initial_stack_size = 16 * L4_PAGESIZE;
3.220
3.221 - Segment program(0x1000000, 0x28326, L4_FPAGE_RWX, 0, 0x28326);
3.222 - Segment data(0x1029360, 0x8068, L4_FPAGE_RW, 0x28360, 0x2058);
3.223 Segment stack(Utcb_area_start - initial_stack_size, initial_stack_size, L4_FPAGE_RW);
3.224 - Segment *segments[] = {&program, &data, &stack, NULL};
3.225 - Segment **segment;
3.226 +
3.227 + segments[payload->segments()] = &stack;
3.228
3.229 - for (segment = segments; *segment != NULL; segment++)
3.230 + for (unsigned int i = 0; i < payload->segments() + 1; i++)
3.231 {
3.232 - err = (*segment)->allocate();
3.233 + Segment *segment = segments[i];
3.234 +
3.235 + if (segment == NULL)
3.236 + continue;
3.237 +
3.238 + err = segment->allocate();
3.239
3.240 if (err)
3.241 {
3.242 @@ -415,7 +551,7 @@
3.243 return 1;
3.244 }
3.245
3.246 - err = (*segment)->fill(file);
3.247 + err = segment->fill(file);
3.248
3.249 if (err)
3.250 {
3.251 @@ -435,8 +571,15 @@
3.252
3.253 init_pager(&config);
3.254
3.255 - for (segment = segments; *segment != NULL; segment++)
3.256 - exec_pager.add((*segment)->region());
3.257 + for (unsigned int i = 0; i < payload->segments() + 1; i++)
3.258 + {
3.259 + Segment *segment = segments[i];
3.260 +
3.261 + if (segment == NULL)
3.262 + continue;
3.263 +
3.264 + exec_pager.add(segment->region());
3.265 + }
3.266
3.267 err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config);
3.268