1.1 --- a/tests/dstest_exec.cc Tue May 10 22:39:15 2022 +0200
1.2 +++ b/tests/dstest_exec.cc Wed May 11 01:23:28 2022 +0200
1.3 @@ -275,21 +275,103 @@
1.4
1.5
1.6
1.7 -class PayloadBase
1.8 +/* Generic program segment interface. */
1.9 +
1.10 +class ProgramSegment
1.11 +{
1.12 +public:
1.13 + virtual bool loadable() = 0;
1.14 + virtual offset_t file_contents() = 0;
1.15 + virtual offset_t file_offset() = 0;
1.16 + virtual l4_addr_t region_address() = 0;
1.17 + virtual offset_t region_size() = 0;
1.18 + virtual l4re_rm_flags_t region_flags() = 0;
1.19 +
1.20 + Segment *segment()
1.21 + {
1.22 + return new Segment(
1.23 + region_address(),
1.24 + region_size(),
1.25 + region_flags(),
1.26 + file_offset(),
1.27 + file_contents());
1.28 + }
1.29 +};
1.30 +
1.31 +template <typename PROGRAM_HEADER>
1.32 +class ProgramSegmentVariant : public ProgramSegment
1.33 +{
1.34 +protected:
1.35 + PROGRAM_HEADER *_header;
1.36 +
1.37 +public:
1.38 + explicit ProgramSegmentVariant(PROGRAM_HEADER *header)
1.39 + : _header(header)
1.40 + {
1.41 + }
1.42 +
1.43 + bool loadable()
1.44 + {
1.45 + return _header->p_type == PT_LOAD;
1.46 + }
1.47 +
1.48 + offset_t file_contents()
1.49 + {
1.50 + return _header->p_filesz;
1.51 + }
1.52 +
1.53 + offset_t file_offset()
1.54 + {
1.55 + return _header->p_offset;
1.56 + }
1.57 +
1.58 + l4_addr_t region_address()
1.59 + {
1.60 + return _header->p_vaddr;
1.61 + }
1.62 +
1.63 + offset_t region_size()
1.64 + {
1.65 + return _header->p_memsz;
1.66 + }
1.67 +
1.68 + l4re_rm_flags_t region_flags()
1.69 + {
1.70 + l4re_rm_flags_t flags = 0;
1.71 +
1.72 + if (_header->p_flags & PF_R)
1.73 + flags |= L4RE_RM_F_R;
1.74 + if (_header->p_flags & PF_W)
1.75 + flags |= L4RE_RM_F_W;
1.76 + if (_header->p_flags & PF_X)
1.77 + flags |= L4RE_RM_F_X;
1.78 +
1.79 + return flags;
1.80 + }
1.81 +};
1.82 +
1.83 +
1.84 +
1.85 +/* Generic interface for an ELF payload. */
1.86 +
1.87 +class Payload
1.88 {
1.89 public:
1.90 virtual l4_addr_t entry_point() = 0;
1.91 - virtual offset_t header_size() = 0;
1.92 + virtual offset_t header_extent() = 0;
1.93 + virtual offset_t program_header_extent() = 0;
1.94 + virtual unsigned int segments() = 0;
1.95 + virtual ProgramSegment *segment(unsigned int i) = 0;
1.96 };
1.97
1.98 -template <typename HEADER>
1.99 -class Payload : public PayloadBase
1.100 +template <typename HEADER, typename PROGRAM_HEADER>
1.101 +class PayloadVariant : public Payload
1.102 {
1.103 protected:
1.104 HEADER *_header;
1.105
1.106 public:
1.107 - explicit Payload(HEADER *header)
1.108 + explicit PayloadVariant(HEADER *header)
1.109 : _header(header)
1.110 {
1.111 }
1.112 @@ -299,20 +381,40 @@
1.113 return _header->e_entry;
1.114 }
1.115
1.116 - offset_t header_size()
1.117 + offset_t header_extent()
1.118 {
1.119 return sizeof(HEADER);
1.120 }
1.121 +
1.122 + offset_t program_header_extent()
1.123 + {
1.124 + return _header->e_phoff + _header->e_phentsize * _header->e_phnum;
1.125 + }
1.126 +
1.127 + unsigned int segments()
1.128 + {
1.129 + return _header->e_phnum;
1.130 + }
1.131 +
1.132 + ProgramSegment *segment(unsigned int i)
1.133 + {
1.134 + if (i >= segments())
1.135 + return NULL;
1.136 +
1.137 + return new ProgramSegmentVariant<PROGRAM_HEADER>(
1.138 + (PROGRAM_HEADER *) ((char *) _header + _header->e_phoff +
1.139 + _header->e_phentsize * i));
1.140 + }
1.141 };
1.142
1.143 -static PayloadBase *get_payload(char *buf)
1.144 +static Payload *get_payload(char *buf)
1.145 {
1.146 switch (buf[EI_CLASS])
1.147 {
1.148 case (char) 1:
1.149 - return new Payload<Elf32_Ehdr>((Elf32_Ehdr *) buf);
1.150 + return new PayloadVariant<Elf32_Ehdr, Elf32_Phdr>((Elf32_Ehdr *) buf);
1.151 case (char) 2:
1.152 - return new Payload<Elf64_Ehdr>((Elf64_Ehdr *) buf);
1.153 + return new PayloadVariant<Elf64_Ehdr, Elf64_Phdr>((Elf64_Ehdr *) buf);
1.154 default:
1.155 return NULL;
1.156 }
1.157 @@ -374,7 +476,7 @@
1.158 return 1;
1.159 }
1.160
1.161 - PayloadBase *payload = get_payload(buf);
1.162 + Payload *payload = get_payload(buf);
1.163
1.164 if (payload == NULL)
1.165 {
1.166 @@ -383,9 +485,9 @@
1.167 }
1.168
1.169 client_seek(file, 0, SEEK_SET);
1.170 - nread = client_read(file, buf, payload->header_size());
1.171 + nread = client_read(file, buf, payload->header_extent());
1.172
1.173 - if (nread < payload->header_size())
1.174 + if (nread < payload->header_extent())
1.175 {
1.176 printf("Header incomplete.\n");
1.177 return 1;
1.178 @@ -393,21 +495,55 @@
1.179
1.180 printf("Program start: %lx\n", payload->entry_point());
1.181
1.182 - /* Copy the payload regions to new dataspaces.
1.183 - NOTE: This should be directed by the ELF metadata. */
1.184 + client_seek(file, 0, SEEK_SET);
1.185 + nread = client_read(file, buf, payload->program_header_extent());
1.186 +
1.187 + if (nread < payload->program_header_extent())
1.188 + {
1.189 + printf("Program headers incomplete.\n");
1.190 + return 1;
1.191 + }
1.192 +
1.193 + /* Make appropriate segments, although program segments could be made
1.194 + interoperable with these. */
1.195 +
1.196 + Segment *segments[payload->segments() + 1];
1.197 +
1.198 + for (unsigned int i = 0; i < payload->segments(); i++)
1.199 + {
1.200 + ProgramSegment *ps = payload->segment(i);
1.201 +
1.202 + printf("Segment(0x%lx, 0x%lx, 0x%x, 0x%lx, 0x%lx): %s\n",
1.203 + ps->region_address(),
1.204 + ps->region_size(),
1.205 + ps->region_flags(),
1.206 + ps->file_offset(),
1.207 + ps->file_contents(),
1.208 + ps->loadable() ? "loadable" : "other");
1.209 +
1.210 + if (ps->loadable())
1.211 + segments[i] = ps->segment();
1.212 + else
1.213 + segments[i] = NULL;
1.214 + }
1.215 +
1.216 + /* Copy the payload regions to new dataspaces. */
1.217
1.218 address_t program_start = payload->entry_point();
1.219 offset_t initial_stack_size = 16 * L4_PAGESIZE;
1.220
1.221 - Segment program(0x1000000, 0x28326, L4_FPAGE_RWX, 0, 0x28326);
1.222 - Segment data(0x1029360, 0x8068, L4_FPAGE_RW, 0x28360, 0x2058);
1.223 Segment stack(Utcb_area_start - initial_stack_size, initial_stack_size, L4_FPAGE_RW);
1.224 - Segment *segments[] = {&program, &data, &stack, NULL};
1.225 - Segment **segment;
1.226 +
1.227 + segments[payload->segments()] = &stack;
1.228
1.229 - for (segment = segments; *segment != NULL; segment++)
1.230 + for (unsigned int i = 0; i < payload->segments() + 1; i++)
1.231 {
1.232 - err = (*segment)->allocate();
1.233 + Segment *segment = segments[i];
1.234 +
1.235 + if (segment == NULL)
1.236 + continue;
1.237 +
1.238 + err = segment->allocate();
1.239
1.240 if (err)
1.241 {
1.242 @@ -415,7 +551,7 @@
1.243 return 1;
1.244 }
1.245
1.246 - err = (*segment)->fill(file);
1.247 + err = segment->fill(file);
1.248
1.249 if (err)
1.250 {
1.251 @@ -435,8 +571,15 @@
1.252
1.253 init_pager(&config);
1.254
1.255 - for (segment = segments; *segment != NULL; segment++)
1.256 - exec_pager.add((*segment)->region());
1.257 + for (unsigned int i = 0; i < payload->segments() + 1; i++)
1.258 + {
1.259 + Segment *segment = segments[i];
1.260 +
1.261 + if (segment == NULL)
1.262 + continue;
1.263 +
1.264 + exec_pager.add(segment->region());
1.265 + }
1.266
1.267 err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config);
1.268