| ... | @@ -520,19 +520,36 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u | ... | @@ -520,19 +520,36 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 520 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | 520 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); |
| 521 | const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; | 521 | const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; |
| 522 | if (needed_size > sect_capacity) { | 522 | if (needed_size > sect_capacity) { |
| 523 | // const new_offset = self.findFreeSpace(needed_size, self.page_size); | 523 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); |
| 524 | // const current_size = if (last_atom) |atom| blk: { | 524 | const current_size = if (maybe_last_atom.*) |last_atom| blk: { |
| 525 | // const sym = last_atom.getSymbol(self); | 525 | const sym = last_atom.getSymbol(self); |
| 526 | // break :blk (sym.value + atom.size) - header.virtual_address; | 526 | break :blk (sym.value + last_atom.size) - header.virtual_address; |
| 527 | // } else 0; | 527 | } else 0; |
| 528 | // log.debug("moving {s} from 0x{x} to 0x{x}", .{ header.pointer_to_raw_data, new_offset }); | 528 | log.debug("moving {s} from (0x{x} - 0x{x}) to (0x{x} - 0x{x})", .{ |
| 529 | // const amt = try self.base.file.?.copyRangeAll(header.pointer_to_raw_data, self.base.file.?, new_offset, current_size); | 529 | self.getSectionName(header), |
| 530 | // if (amt != current_size) return error.InputOutput; | 530 | header.pointer_to_raw_data, |
| 531 | | 531 | header.pointer_to_raw_data + current_size, |
| 532 | @panic("TODO move section"); | 532 | new_offset, |
| 533 | // header.virtual_size = needed_size; | 533 | new_offset + current_size, |
| 534 | // header.size_of_raw_data = mem.alignForwardGeneric(u32, needed_size, default_file_alignment); | 534 | }); |
| | 535 | const amt = try self.base.file.?.copyRangeAll( |
| | 536 | header.pointer_to_raw_data, |
| | 537 | self.base.file.?, |
| | 538 | new_offset, |
| | 539 | current_size, |
| | 540 | ); |
| | 541 | if (amt != current_size) return error.InputOutput; |
| | 542 | header.pointer_to_raw_data = new_offset; |
| | 543 | } |
| | 544 | |
| | 545 | const sect_vm_capacity = self.allocatedSizeVM(header.virtual_address); |
| | 546 | if (needed_size > sect_vm_capacity) { |
| | 547 | log.err("needed {x}, available {x}", .{ needed_size, sect_vm_capacity }); |
| | 548 | @panic("TODO expand section in virtual address space"); |
| 535 | } | 549 | } |
| | 550 | |
| | 551 | header.virtual_size = @maximum(header.virtual_size, needed_size); |
| | 552 | header.size_of_raw_data = needed_size; |
| 536 | maybe_last_atom.* = atom; | 553 | maybe_last_atom.* = atom; |
| 537 | } | 554 | } |
| 538 | | 555 | |
| ... | @@ -778,8 +795,9 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { | ... | @@ -778,8 +795,9 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 778 | | 795 | |
| 779 | if (reloc.pcrel) { | 796 | if (reloc.pcrel) { |
| 780 | const source_vaddr = source_sym.value + reloc.offset; | 797 | const source_vaddr = source_sym.value + reloc.offset; |
| 781 | const disp = target_vaddr_with_addend - source_vaddr - 4; | 798 | const disp = |
| 782 | try self.base.file.?.pwriteAll(mem.asBytes(&@intCast(u32, disp)), file_offset + reloc.offset); | 799 | @intCast(i32, target_vaddr_with_addend) - @intCast(i32, source_vaddr) - 4; |
| | 800 | try self.base.file.?.pwriteAll(mem.asBytes(&disp), file_offset + reloc.offset); |
| 783 | continue; | 801 | continue; |
| 784 | } | 802 | } |
| 785 | | 803 | |
| ... | @@ -1515,7 +1533,24 @@ fn writeBaseRelocations(self: *Coff) !void { | ... | @@ -1515,7 +1533,24 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1515 | const header = &self.sections.items(.header)[self.reloc_section_index.?]; | 1533 | const header = &self.sections.items(.header)[self.reloc_section_index.?]; |
| 1516 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | 1534 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); |
| 1517 | const needed_size = @intCast(u32, buffer.items.len); | 1535 | const needed_size = @intCast(u32, buffer.items.len); |
| 1518 | assert(needed_size < sect_capacity); // TODO expand .reloc section | 1536 | if (needed_size > sect_capacity) { |
| | 1537 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); |
| | 1538 | log.debug("writing {s} at 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| | 1539 | self.getSectionName(header), |
| | 1540 | header.pointer_to_raw_data, |
| | 1541 | header.pointer_to_raw_data + needed_size, |
| | 1542 | new_offset, |
| | 1543 | new_offset + needed_size, |
| | 1544 | }); |
| | 1545 | header.pointer_to_raw_data = new_offset; |
| | 1546 | |
| | 1547 | const sect_vm_capacity = self.allocatedSizeVM(header.virtual_address); |
| | 1548 | if (needed_size > sect_vm_capacity) { |
| | 1549 | @panic("TODO expand section in virtual address space"); |
| | 1550 | } |
| | 1551 | } |
| | 1552 | header.virtual_size = @maximum(header.virtual_size, needed_size); |
| | 1553 | header.size_of_raw_data = needed_size; |
| 1519 | | 1554 | |
| 1520 | try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); | 1555 | try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); |
| 1521 | | 1556 | |
| ... | @@ -1608,6 +1643,8 @@ fn writeImportTable(self: *Coff) !void { | ... | @@ -1608,6 +1643,8 @@ fn writeImportTable(self: *Coff) !void { |
| 1608 | } | 1643 | } |
| 1609 | | 1644 | |
| 1610 | fn writeStrtab(self: *Coff) !void { | 1645 | fn writeStrtab(self: *Coff) !void { |
| | 1646 | if (self.strtab_offset == null) return; |
| | 1647 | |
| 1611 | const allocated_size = self.allocatedSize(self.strtab_offset.?); | 1648 | const allocated_size = self.allocatedSize(self.strtab_offset.?); |
| 1612 | const needed_size = @intCast(u32, self.strtab.len()); | 1649 | const needed_size = @intCast(u32, self.strtab.len()); |
| 1613 | | 1650 | |
| ... | @@ -1840,6 +1877,20 @@ fn findFreeSpace(self: *Coff, object_size: u32, min_alignment: u32) u32 { | ... | @@ -1840,6 +1877,20 @@ fn findFreeSpace(self: *Coff, object_size: u32, min_alignment: u32) u32 { |
| 1840 | return start; | 1877 | return start; |
| 1841 | } | 1878 | } |
| 1842 | | 1879 | |
| | 1880 | fn allocatedSizeVM(self: *Coff, start: u32) u32 { |
| | 1881 | if (start == 0) |
| | 1882 | return 0; |
| | 1883 | var min_pos: u32 = std.math.maxInt(u32); |
| | 1884 | if (self.strtab_offset) |off| { |
| | 1885 | if (off > start and off < min_pos) min_pos = off; |
| | 1886 | } |
| | 1887 | for (self.sections.items(.header)) |header| { |
| | 1888 | if (header.virtual_address <= start) continue; |
| | 1889 | if (header.virtual_address < min_pos) min_pos = header.virtual_address; |
| | 1890 | } |
| | 1891 | return min_pos - start; |
| | 1892 | } |
| | 1893 | |
| 1843 | fn detectAllocCollisionVM(self: *Coff, start: u32, size: u32) ?u32 { | 1894 | fn detectAllocCollisionVM(self: *Coff, start: u32, size: u32) ?u32 { |
| 1844 | const headers_size = @maximum(self.getSizeOfHeaders(), 0x1000); | 1895 | const headers_size = @maximum(self.getSizeOfHeaders(), 0x1000); |
| 1845 | if (start < headers_size) | 1896 | if (start < headers_size) |