| ... | ... | @@ -418,17 +418,26 @@ const AllocateSegmentOpts = struct { |
| 418 | 418 | }; |
| 419 | 419 | |
| 420 | 420 | pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 { |
| 421 | const gpa = self.base.allocator; |
| 421 | 422 | const index = @as(u16, @intCast(self.phdrs.items.len)); |
| 422 | | try self.phdrs.ensureUnusedCapacity(self.base.allocator, 1); |
| 423 | try self.phdrs.ensureUnusedCapacity(gpa, 1); |
| 423 | 424 | const off = self.findFreeSpace(opts.size, opts.alignment); |
| 424 | | // Memory is always allocated in sequence. |
| 425 | | // TODO is this correct? Or should we implement something similar to `findFreeSpace`? |
| 426 | | // How would that impact HCS? |
| 425 | // Currently, we automatically allocate memory in sequence by finding the largest |
| 426 | // allocated virtual address and going from there. |
| 427 | // TODO we want to keep machine code segment in the furthest memory range among all |
| 428 | // segments as it is most likely to grow. |
| 427 | 429 | const addr = opts.addr orelse blk: { |
| 428 | | assert(index >= 1); |
| 429 | | const phdr = &self.phdrs.items[index - 1]; |
| 430 | | const increased_size = padToIdeal(phdr.p_vaddr + phdr.p_memsz); |
| 431 | | break :blk mem.alignForward(u64, increased_size, opts.alignment); |
| 430 | const reserved_capacity = self.calcImageBase() * 4; |
| 431 | // Calculate largest VM address |
| 432 | const count = self.phdrs.items.len; |
| 433 | var addresses = std.ArrayList(u64).init(gpa); |
| 434 | defer addresses.deinit(); |
| 435 | try addresses.ensureTotalCapacityPrecise(count); |
| 436 | for (self.phdrs.items) |phdr| { |
| 437 | addresses.appendAssumeCapacity(phdr.p_vaddr + reserved_capacity); |
| 438 | } |
| 439 | mem.sort(u64, addresses.items, {}, std.sort.asc(u64)); |
| 440 | break :blk mem.alignForward(u64, addresses.items[count - 1], opts.alignment); |
| 432 | 441 | }; |
| 433 | 442 | log.debug("allocating phdr({d})({c}{c}{c}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 434 | 443 | index, |