| ... | @@ -444,7 +444,44 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section | ... | @@ -444,7 +444,44 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section |
| 444 | return index; | 444 | return index; |
| 445 | } | 445 | } |
| 446 | | 446 | |
| 447 | fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { | 447 | fn growSection(self: *Coff, sect_id: u32, needed_size: u32) !void { |
| | 448 | const header = &self.sections.items(.header)[sect_id]; |
| | 449 | const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id]; |
| | 450 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); |
| | 451 | |
| | 452 | if (needed_size > sect_capacity) { |
| | 453 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); |
| | 454 | const current_size = if (maybe_last_atom_index) |last_atom_index| blk: { |
| | 455 | const last_atom = self.getAtom(last_atom_index); |
| | 456 | const sym = last_atom.getSymbol(self); |
| | 457 | break :blk (sym.value + last_atom.size) - header.virtual_address; |
| | 458 | } else 0; |
| | 459 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ |
| | 460 | self.getSectionName(header), |
| | 461 | header.pointer_to_raw_data, |
| | 462 | new_offset, |
| | 463 | }); |
| | 464 | const amt = try self.base.file.?.copyRangeAll( |
| | 465 | header.pointer_to_raw_data, |
| | 466 | self.base.file.?, |
| | 467 | new_offset, |
| | 468 | current_size, |
| | 469 | ); |
| | 470 | if (amt != current_size) return error.InputOutput; |
| | 471 | header.pointer_to_raw_data = new_offset; |
| | 472 | } |
| | 473 | |
| | 474 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); |
| | 475 | if (needed_size > sect_vm_capacity) { |
| | 476 | try self.growSectionVirtualMemory(sect_id, needed_size); |
| | 477 | self.markRelocsDirtyByAddress(header.virtual_address + needed_size); |
| | 478 | } |
| | 479 | |
| | 480 | header.virtual_size = @max(header.virtual_size, needed_size); |
| | 481 | header.size_of_raw_data = needed_size; |
| | 482 | } |
| | 483 | |
| | 484 | fn growSectionVirtualMemory(self: *Coff, sect_id: u32, needed_size: u32) !void { |
| 448 | const header = &self.sections.items(.header)[sect_id]; | 485 | const header = &self.sections.items(.header)[sect_id]; |
| 449 | const increased_size = padToIdeal(needed_size); | 486 | const increased_size = padToIdeal(needed_size); |
| 450 | const old_aligned_end = header.virtual_address + mem.alignForwardGeneric(u32, header.virtual_size, self.page_size); | 487 | const old_aligned_end = header.virtual_address + mem.alignForwardGeneric(u32, header.virtual_size, self.page_size); |
| ... | @@ -551,38 +588,8 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme | ... | @@ -551,38 +588,8 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme |
| 551 | else | 588 | else |
| 552 | true; | 589 | true; |
| 553 | if (expand_section) { | 590 | if (expand_section) { |
| 554 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | | |
| 555 | const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; | 591 | const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; |
| 556 | if (needed_size > sect_capacity) { | 592 | try self.growSection(sect_id, needed_size); |
| 557 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); | | |
| 558 | const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: { | | |
| 559 | const last_atom = self.getAtom(last_atom_index); | | |
| 560 | const sym = last_atom.getSymbol(self); | | |
| 561 | break :blk (sym.value + last_atom.size) - header.virtual_address; | | |
| 562 | } else 0; | | |
| 563 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | | |
| 564 | self.getSectionName(header), | | |
| 565 | header.pointer_to_raw_data, | | |
| 566 | new_offset, | | |
| 567 | }); | | |
| 568 | const amt = try self.base.file.?.copyRangeAll( | | |
| 569 | header.pointer_to_raw_data, | | |
| 570 | self.base.file.?, | | |
| 571 | new_offset, | | |
| 572 | current_size, | | |
| 573 | ); | | |
| 574 | if (amt != current_size) return error.InputOutput; | | |
| 575 | header.pointer_to_raw_data = new_offset; | | |
| 576 | } | | |
| 577 | | | |
| 578 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); | | |
| 579 | if (needed_size > sect_vm_capacity) { | | |
| 580 | try self.growSectionVM(sect_id, needed_size); | | |
| 581 | self.markRelocsDirtyByAddress(header.virtual_address + needed_size); | | |
| 582 | } | | |
| 583 | | | |
| 584 | header.virtual_size = @max(header.virtual_size, needed_size); | | |
| 585 | header.size_of_raw_data = needed_size; | | |
| 586 | maybe_last_atom_index.* = atom_index; | 593 | maybe_last_atom_index.* = atom_index; |
| 587 | } | 594 | } |
| 588 | | 595 | |
| ... | @@ -814,8 +821,9 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { | ... | @@ -814,8 +821,9 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { |
| 814 | | 821 | |
| 815 | for (relocs.items) |*reloc| { | 822 | for (relocs.items) |*reloc| { |
| 816 | if (!reloc.dirty) continue; | 823 | if (!reloc.dirty) continue; |
| 817 | reloc.resolve(atom_index, code, self); | 824 | if (reloc.resolve(atom_index, code, self)) { |
| 818 | reloc.dirty = false; | 825 | reloc.dirty = false; |
| | 826 | } |
| 819 | } | 827 | } |
| 820 | } | 828 | } |
| 821 | | 829 | |
| ... | @@ -1581,25 +1589,8 @@ fn writeBaseRelocations(self: *Coff) !void { | ... | @@ -1581,25 +1589,8 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1581 | } | 1589 | } |
| 1582 | | 1590 | |
| 1583 | const header = &self.sections.items(.header)[self.reloc_section_index.?]; | 1591 | const header = &self.sections.items(.header)[self.reloc_section_index.?]; |
| 1584 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | | |
| 1585 | const needed_size = @intCast(u32, buffer.items.len); | 1592 | const needed_size = @intCast(u32, buffer.items.len); |
| 1586 | if (needed_size > sect_capacity) { | 1593 | try self.growSection(self.reloc_section_index.?, needed_size); |
| 1587 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); | | |
| 1588 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | | |
| 1589 | self.getSectionName(header), | | |
| 1590 | header.pointer_to_raw_data, | | |
| 1591 | new_offset, | | |
| 1592 | }); | | |
| 1593 | header.pointer_to_raw_data = new_offset; | | |
| 1594 | | | |
| 1595 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); | | |
| 1596 | if (needed_size > sect_vm_capacity) { | | |
| 1597 | // TODO: we want to enforce .reloc after every alloc section. | | |
| 1598 | try self.growSectionVM(self.reloc_section_index.?, needed_size); | | |
| 1599 | } | | |
| 1600 | } | | |
| 1601 | header.virtual_size = @max(header.virtual_size, needed_size); | | |
| 1602 | header.size_of_raw_data = needed_size; | | |
| 1603 | | 1594 | |
| 1604 | try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); | 1595 | try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); |
| 1605 | | 1596 | |
| ... | @@ -1638,21 +1629,7 @@ fn writeImportTables(self: *Coff) !void { | ... | @@ -1638,21 +1629,7 @@ fn writeImportTables(self: *Coff) !void { |
| 1638 | } | 1629 | } |
| 1639 | | 1630 | |
| 1640 | const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size; | 1631 | const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size; |
| 1641 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | 1632 | try self.growSection(self.idata_section_index.?, needed_size); |
| 1642 | if (needed_size > sect_capacity) { | | |
| 1643 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); | | |
| 1644 | log.debug("moving .idata from 0x{x} to 0x{x}", .{ header.pointer_to_raw_data, new_offset }); | | |
| 1645 | header.pointer_to_raw_data = new_offset; | | |
| 1646 | | | |
| 1647 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); | | |
| 1648 | if (needed_size > sect_vm_capacity) { | | |
| 1649 | try self.growSectionVM(self.idata_section_index.?, needed_size); | | |
| 1650 | self.markRelocsDirtyByAddress(header.virtual_address + needed_size); | | |
| 1651 | } | | |
| 1652 | | | |
| 1653 | header.virtual_size = @max(header.virtual_size, needed_size); | | |
| 1654 | header.size_of_raw_data = needed_size; | | |
| 1655 | } | | |
| 1656 | | 1633 | |
| 1657 | // Do the actual writes | 1634 | // Do the actual writes |
| 1658 | var buffer = std.ArrayList(u8).init(gpa); | 1635 | var buffer = std.ArrayList(u8).init(gpa); |