* Emit the (modified) PE executable. */
| 281 | * Emit the (modified) PE executable. |
| 282 | */ |
| 283 | size_t emitPE(Binary *B, const MappingSet &mappings, size_t mapping_size) |
| 284 | { |
| 285 | uint8_t *data = B->patched.bytes; |
| 286 | size_t size = B->patched.size; |
| 287 | uint32_t mapping_align = (uint32_t)WINDOWS_VIRTUAL_ALLOC_SIZE; |
| 288 | stat_input_file_size = size; |
| 289 | size = ALIGN(size, mapping_align); |
| 290 | |
| 291 | // Emit all mappings: |
| 292 | PIMAGE_OPTIONAL_HEADER64 opt_hdr = B->pe.opt_hdr; |
| 293 | uint32_t size_of_image = opt_hdr->SizeOfImage; |
| 294 | for (auto mapping: mappings) |
| 295 | { |
| 296 | uint8_t *base = data + size; |
| 297 | mapping->offset = (off_t)size; |
| 298 | flattenMapping(B, base, mapping, /*int3=*/0xcc); |
| 299 | size += mapping->size; |
| 300 | } |
| 301 | |
| 302 | // Emit the loader: |
| 303 | uint32_t section_align = opt_hdr->SectionAlignment; |
| 304 | uint32_t file_align = B->pe.opt_hdr->FileAlignment; |
| 305 | size = ALIGN(size, file_align); |
| 306 | off_t loader_offset = (off_t)size; |
| 307 | struct e9_config_s *config = (struct e9_config_s *)(data + size); |
| 308 | size_t config_offset = size; |
| 309 | size += sizeof(struct e9_config_s) + sizeof(struct e9_config_pe_s); |
| 310 | const char magic[] = "E9PATCH"; |
| 311 | memcpy(config->magic, magic, sizeof(magic)); |
| 312 | const char version[] = STRING(VERSION); |
| 313 | memcpy(config->version, version, sizeof(version)); |
| 314 | config->base = (intptr_t)size_of_image; |
| 315 | |
| 316 | std::vector<Bounds> bounds; |
| 317 | config->maps[1] = (uint32_t)(size - config_offset); |
| 318 | for (auto mapping: mappings) |
| 319 | { |
| 320 | stat_num_physical_bytes += mapping->size; |
| 321 | off_t offset_0 = mapping->offset; |
| 322 | for (; mapping != nullptr; mapping = mapping->merged) |
| 323 | { |
| 324 | bounds.clear(); |
| 325 | getVirtualBounds(mapping, WINDOWS_VIRTUAL_ALLOC_SIZE, bounds); |
| 326 | bool r = ((mapping->prot & PROT_READ) != 0); |
| 327 | bool w = ((mapping->prot & PROT_WRITE) != 0); |
| 328 | bool x = ((mapping->prot & PROT_EXEC) != 0); |
| 329 | for (const auto b: bounds) |
| 330 | { |
| 331 | intptr_t base = mapping->base + b.lb; |
| 332 | size_t len = b.ub - b.lb; |
| 333 | off_t offset = offset_0 + b.lb; |
| 334 | |
| 335 | debug("load trampoline: MapViewOfFileEx(addr=" ADDRESS_FORMAT |
| 336 | ",size=%zu,offset=+%zu,prot=%c%c%c)", |
| 337 | ADDRESS(base), len, offset_0, (r? 'r': '-'), |
| 338 | (w? 'w': '-'), (x? 'x': '-')); |
| 339 | stat_num_virtual_bytes += len; |
| 340 |
no test coverage detected