authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-20 14:07:02+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-21 22:44:28+02:00
logbee35fe3f018dd7b52716f757974ba405266558b
treeb24c52e0291512cb57ddd0d52f79659ebdf37955
parentae8fb2151425dc7f61ad46e4c13b6c61f67cc68b

coff: add image base to GOT relocations

Sort base relocations by address for deterministic debugging.

1 files changed, 61 insertions(+), 52 deletions(-)

src/link/Coff.zig+61-52
......@@ -107,12 +107,6 @@ const HotUpdateState = struct {
107107 loaded_base_address: ?std.os.windows.HMODULE = null,
108108};
109109
110const Entry = struct {
111 target: SymbolWithLoc,
112 // Index into the synthetic symbol table (i.e., file == null).
113 sym_index: u32,
114};
115
116110const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation));
117111const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
118112const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
......@@ -843,17 +837,17 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
843837 const file_offset = header.pointer_to_raw_data + entry_offset;
844838 const vmaddr = header.virtual_address + entry_offset;
845839
846 log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value });
840 log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.getImageBase() });
847841
848842 switch (self.ptr_width) {
849843 .p32 => {
850844 var buf: [4]u8 = undefined;
851 mem.writeIntLittle(u32, &buf, @intCast(u32, entry_value));
845 mem.writeIntLittle(u32, &buf, @intCast(u32, entry_value + self.getImageBase()));
852846 try self.base.file.?.pwriteAll(&buf, file_offset);
853847 },
854848 .p64 => {
855849 var buf: [8]u8 = undefined;
856 mem.writeIntLittle(u64, &buf, entry_value);
850 mem.writeIntLittle(u64, &buf, entry_value + self.getImageBase());
857851 try self.base.file.?.pwriteAll(&buf, file_offset);
858852 },
859853 }
......@@ -881,12 +875,14 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
881875 switch (self.ptr_width) {
882876 .p32 => {
883877 var buf: [4]u8 = undefined;
878 mem.writeIntLittle(u32, &buf, @intCast(u32, entry_value + slide));
884879 writeMem(handle, pvaddr, &buf) catch |err| {
885880 log.warn("writing to protected memory failed with error: {s}", .{@errorName(err)});
886881 };
887882 },
888883 .p64 => {
889884 var buf: [8]u8 = undefined;
885 mem.writeIntLittle(u64, &buf, entry_value + slide);
890886 writeMem(handle, pvaddr, &buf) catch |err| {
891887 log.warn("writing to protected memory failed with error: {s}", .{@errorName(err)});
892888 };
......@@ -1744,69 +1740,82 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl_index: Module.Dec
17441740fn writeBaseRelocations(self: *Coff) !void {
17451741 const gpa = self.base.allocator;
17461742
1747 var pages = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa);
1743 var page_table = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa);
17481744 defer {
1749 var it = pages.valueIterator();
1745 var it = page_table.valueIterator();
17501746 while (it.next()) |inner| {
17511747 inner.deinit();
17521748 }
1753 pages.deinit();
1749 page_table.deinit();
17541750 }
17551751
1756 var it = self.base_relocs.iterator();
1757 while (it.next()) |entry| {
1758 const atom_index = entry.key_ptr.*;
1759 const atom = self.getAtom(atom_index);
1760 const sym = atom.getSymbol(self);
1761 const offsets = entry.value_ptr.*;
1762
1763 for (offsets.items) |offset| {
1764 const rva = sym.value + offset;
1765 const page = mem.alignBackwardGeneric(u32, rva, self.page_size);
1766 const gop = try pages.getOrPut(page);
1767 if (!gop.found_existing) {
1768 gop.value_ptr.* = std.ArrayList(coff.BaseRelocation).init(gpa);
1752 {
1753 var it = self.base_relocs.iterator();
1754 while (it.next()) |entry| {
1755 const atom_index = entry.key_ptr.*;
1756 const atom = self.getAtom(atom_index);
1757 const sym = atom.getSymbol(self);
1758 const offsets = entry.value_ptr.*;
1759
1760 for (offsets.items) |offset| {
1761 const rva = sym.value + offset;
1762 const page = mem.alignBackwardGeneric(u32, rva, self.page_size);
1763 const gop = try page_table.getOrPut(page);
1764 if (!gop.found_existing) {
1765 gop.value_ptr.* = std.ArrayList(coff.BaseRelocation).init(gpa);
1766 }
1767 try gop.value_ptr.append(.{
1768 .offset = @intCast(u12, rva - page),
1769 .type = .DIR64,
1770 });
17691771 }
1770 try gop.value_ptr.append(.{
1771 .offset = @intCast(u12, rva - page),
1772 .type = .DIR64,
1773 });
17741772 }
1775 }
17761773
1777 {
1778 const header = &self.sections.items(.header)[self.got_section_index.?];
1779 for (self.got_table.entries.items, 0..) |entry, index| {
1780 if (!self.got_table.lookup.contains(entry)) continue;
1774 {
1775 const header = &self.sections.items(.header)[self.got_section_index.?];
1776 for (self.got_table.entries.items, 0..) |entry, index| {
1777 if (!self.got_table.lookup.contains(entry)) continue;
17811778
1782 const sym = self.getSymbol(entry);
1783 if (sym.section_number == .UNDEFINED) continue;
1779 const sym = self.getSymbol(entry);
1780 if (sym.section_number == .UNDEFINED) continue;
17841781
1785 const rva = @intCast(u32, header.virtual_address + index * self.ptr_width.size());
1786 const page = mem.alignBackwardGeneric(u32, rva, self.page_size);
1787 const gop = try pages.getOrPut(page);
1788 if (!gop.found_existing) {
1789 gop.value_ptr.* = std.ArrayList(coff.BaseRelocation).init(gpa);
1782 const rva = @intCast(u32, header.virtual_address + index * self.ptr_width.size());
1783 const page = mem.alignBackwardGeneric(u32, rva, self.page_size);
1784 const gop = try page_table.getOrPut(page);
1785 if (!gop.found_existing) {
1786 gop.value_ptr.* = std.ArrayList(coff.BaseRelocation).init(gpa);
1787 }
1788 try gop.value_ptr.append(.{
1789 .offset = @intCast(u12, rva - page),
1790 .type = .DIR64,
1791 });
17901792 }
1791 try gop.value_ptr.append(.{
1792 .offset = @intCast(u12, rva - page),
1793 .type = .DIR64,
1794 });
17951793 }
17961794 }
17971795
1796 // Sort pages by address.
1797 var pages = try std.ArrayList(u32).initCapacity(gpa, page_table.count());
1798 defer pages.deinit();
1799 {
1800 var it = page_table.keyIterator();
1801 while (it.next()) |page| {
1802 pages.appendAssumeCapacity(page.*);
1803 }
1804 }
1805 std.sort.sort(u32, pages.items, {}, std.sort.asc(u32));
1806
17981807 var buffer = std.ArrayList(u8).init(gpa);
17991808 defer buffer.deinit();
18001809
1801 var pages_it = pages.iterator();
1802 while (pages_it.next()) |entry| {
1810 for (pages.items) |page| {
1811 const entries = page_table.getPtr(page).?;
18031812 // Pad to required 4byte alignment
18041813 if (!mem.isAlignedGeneric(
18051814 usize,
1806 entry.value_ptr.items.len * @sizeOf(coff.BaseRelocation),
1815 entries.items.len * @sizeOf(coff.BaseRelocation),
18071816 @sizeOf(u32),
18081817 )) {
1809 try entry.value_ptr.append(.{
1818 try entries.append(.{
18101819 .offset = 0,
18111820 .type = .ABSOLUTE,
18121821 });
......@@ -1814,14 +1823,14 @@ fn writeBaseRelocations(self: *Coff) !void {
18141823
18151824 const block_size = @intCast(
18161825 u32,
1817 entry.value_ptr.items.len * @sizeOf(coff.BaseRelocation) + @sizeOf(coff.BaseRelocationDirectoryEntry),
1826 entries.items.len * @sizeOf(coff.BaseRelocation) + @sizeOf(coff.BaseRelocationDirectoryEntry),
18181827 );
18191828 try buffer.ensureUnusedCapacity(block_size);
18201829 buffer.appendSliceAssumeCapacity(mem.asBytes(&coff.BaseRelocationDirectoryEntry{
1821 .page_rva = entry.key_ptr.*,
1830 .page_rva = page,
18221831 .block_size = block_size,
18231832 }));
1824 buffer.appendSliceAssumeCapacity(mem.sliceAsBytes(entry.value_ptr.items));
1833 buffer.appendSliceAssumeCapacity(mem.sliceAsBytes(entries.items));
18251834 }
18261835
18271836 const header = &self.sections.items(.header)[self.reloc_section_index.?];