| ... | @@ -37,13 +37,14 @@ strtab_offset: ?u32 = null, | ... | @@ -37,13 +37,14 @@ strtab_offset: ?u32 = null, |
| 37 | | 37 | |
| 38 | temp_strtab: StringTable(.temp_strtab) = .{}, | 38 | temp_strtab: StringTable(.temp_strtab) = .{}, |
| 39 | | 39 | |
| 40 | got_entries: std.ArrayListUnmanaged(Entry) = .{}, | 40 | got_table: TableSection(SymbolWithLoc) = .{}, |
| 41 | got_entries_free_list: std.ArrayListUnmanaged(u32) = .{}, | | |
| 42 | got_entries_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{}, | | |
| 43 | | 41 | |
| 44 | /// A table of ImportTables partitioned by the library name. | 42 | /// A table of ImportTables partitioned by the library name. |
| 45 | /// Key is an offset into the interning string table `temp_strtab`. | 43 | /// Key is an offset into the interning string table `temp_strtab`. |
| 46 | import_tables: std.AutoArrayHashMapUnmanaged(u32, ImportTable) = .{}, | 44 | import_tables: std.AutoArrayHashMapUnmanaged(u32, ImportTable) = .{}, |
| | 45 | |
| | 46 | got_table_count_dirty: bool = true, |
| | 47 | got_table_contents_dirty: bool = true, |
| 47 | imports_count_dirty: bool = true, | 48 | imports_count_dirty: bool = true, |
| 48 | | 49 | |
| 49 | /// Virtual address of the entry point procedure relative to image base. | 50 | /// Virtual address of the entry point procedure relative to image base. |
| ... | @@ -188,7 +189,8 @@ pub const PtrWidth = enum { | ... | @@ -188,7 +189,8 @@ pub const PtrWidth = enum { |
| 188 | p32, | 189 | p32, |
| 189 | p64, | 190 | p64, |
| 190 | | 191 | |
| 191 | fn abiSize(pw: PtrWidth) u4 { | 192 | /// Size in bytes. |
| | 193 | pub fn size(pw: PtrWidth) u4 { |
| 192 | return switch (pw) { | 194 | return switch (pw) { |
| 193 | .p32 => 4, | 195 | .p32 => 4, |
| 194 | .p64 => 8, | 196 | .p64 => 8, |
| ... | @@ -310,9 +312,7 @@ pub fn deinit(self: *Coff) void { | ... | @@ -310,9 +312,7 @@ pub fn deinit(self: *Coff) void { |
| 310 | self.globals_free_list.deinit(gpa); | 312 | self.globals_free_list.deinit(gpa); |
| 311 | self.strtab.deinit(gpa); | 313 | self.strtab.deinit(gpa); |
| 312 | self.temp_strtab.deinit(gpa); | 314 | self.temp_strtab.deinit(gpa); |
| 313 | self.got_entries.deinit(gpa); | 315 | self.got_table.deinit(gpa); |
| 314 | self.got_entries_free_list.deinit(gpa); | | |
| 315 | self.got_entries_table.deinit(gpa); | | |
| 316 | | 316 | |
| 317 | for (self.import_tables.values()) |*itab| { | 317 | for (self.import_tables.values()) |*itab| { |
| 318 | itab.deinit(gpa); | 318 | itab.deinit(gpa); |
| ... | @@ -371,7 +371,7 @@ fn populateMissingMetadata(self: *Coff) !void { | ... | @@ -371,7 +371,7 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 371 | } | 371 | } |
| 372 | | 372 | |
| 373 | if (self.got_section_index == null) { | 373 | if (self.got_section_index == null) { |
| 374 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * self.ptr_width.abiSize(); | 374 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * self.ptr_width.size(); |
| 375 | self.got_section_index = try self.allocateSection(".got", file_size, .{ | 375 | self.got_section_index = try self.allocateSection(".got", file_size, .{ |
| 376 | .CNT_INITIALIZED_DATA = 1, | 376 | .CNT_INITIALIZED_DATA = 1, |
| 377 | .MEM_READ = 1, | 377 | .MEM_READ = 1, |
| ... | @@ -396,7 +396,7 @@ fn populateMissingMetadata(self: *Coff) !void { | ... | @@ -396,7 +396,7 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 396 | } | 396 | } |
| 397 | | 397 | |
| 398 | if (self.idata_section_index == null) { | 398 | if (self.idata_section_index == null) { |
| 399 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * self.ptr_width.abiSize(); | 399 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * self.ptr_width.size(); |
| 400 | self.idata_section_index = try self.allocateSection(".idata", file_size, .{ | 400 | self.idata_section_index = try self.allocateSection(".idata", file_size, .{ |
| 401 | .CNT_INITIALIZED_DATA = 1, | 401 | .CNT_INITIALIZED_DATA = 1, |
| 402 | .MEM_READ = 1, | 402 | .MEM_READ = 1, |
| ... | @@ -698,26 +698,11 @@ fn allocateGlobal(self: *Coff) !u32 { | ... | @@ -698,26 +698,11 @@ fn allocateGlobal(self: *Coff) !u32 { |
| 698 | return index; | 698 | return index; |
| 699 | } | 699 | } |
| 700 | | 700 | |
| 701 | pub fn allocateGotEntry(self: *Coff, target: SymbolWithLoc) !u32 { | 701 | fn addGotEntry(self: *Coff, target: SymbolWithLoc) !void { |
| 702 | const gpa = self.base.allocator; | 702 | if (self.got_table.lookup.contains(target)) return; |
| 703 | try self.got_entries.ensureUnusedCapacity(gpa, 1); | 703 | const got_index = try self.got_table.allocateEntry(self.base.allocator, target); |
| 704 | | 704 | try self.writeOffsetTableEntry(got_index); |
| 705 | const index: u32 = blk: { | 705 | self.got_table_count_dirty = true; |
| 706 | if (self.got_entries_free_list.popOrNull()) |index| { | | |
| 707 | log.debug(" (reusing GOT entry index {d})", .{index}); | | |
| 708 | break :blk index; | | |
| 709 | } else { | | |
| 710 | log.debug(" (allocating GOT entry at index {d})", .{self.got_entries.items.len}); | | |
| 711 | const index = @intCast(u32, self.got_entries.items.len); | | |
| 712 | _ = self.got_entries.addOneAssumeCapacity(); | | |
| 713 | break :blk index; | | |
| 714 | } | | |
| 715 | }; | | |
| 716 | | | |
| 717 | self.got_entries.items[index] = .{ .target = target, .sym_index = 0 }; | | |
| 718 | try self.got_entries_table.putNoClobber(gpa, target, index); | | |
| 719 | | | |
| 720 | return index; | | |
| 721 | } | 706 | } |
| 722 | | 707 | |
| 723 | pub fn createAtom(self: *Coff) !Atom.Index { | 708 | pub fn createAtom(self: *Coff) !Atom.Index { |
| ... | @@ -737,37 +722,6 @@ pub fn createAtom(self: *Coff) !Atom.Index { | ... | @@ -737,37 +722,6 @@ pub fn createAtom(self: *Coff) !Atom.Index { |
| 737 | return atom_index; | 722 | return atom_index; |
| 738 | } | 723 | } |
| 739 | | 724 | |
| 740 | fn createGotAtom(self: *Coff, target: SymbolWithLoc) !Atom.Index { | | |
| 741 | const atom_index = try self.createAtom(); | | |
| 742 | const atom = self.getAtomPtr(atom_index); | | |
| 743 | atom.size = @sizeOf(u64); | | |
| 744 | | | |
| 745 | const sym = atom.getSymbolPtr(self); | | |
| 746 | sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1); | | |
| 747 | sym.value = try self.allocateAtom(atom_index, atom.size, @sizeOf(u64)); | | |
| 748 | | | |
| 749 | log.debug("allocated GOT atom at 0x{x}", .{sym.value}); | | |
| 750 | | | |
| 751 | try Atom.addRelocation(self, atom_index, .{ | | |
| 752 | .type = .direct, | | |
| 753 | .target = target, | | |
| 754 | .offset = 0, | | |
| 755 | .addend = 0, | | |
| 756 | .pcrel = false, | | |
| 757 | .length = 3, | | |
| 758 | }); | | |
| 759 | | | |
| 760 | const target_sym = self.getSymbol(target); | | |
| 761 | switch (target_sym.section_number) { | | |
| 762 | .UNDEFINED => @panic("TODO generate a binding for undefined GOT target"), | | |
| 763 | .ABSOLUTE => {}, | | |
| 764 | .DEBUG => unreachable, // not possible | | |
| 765 | else => try Atom.addBaseRelocation(self, atom_index, 0), | | |
| 766 | } | | |
| 767 | | | |
| 768 | return atom_index; | | |
| 769 | } | | |
| 770 | | | |
| 771 | fn growAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignment: u32) !u32 { | 725 | fn growAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignment: u32) !u32 { |
| 772 | const atom = self.getAtom(atom_index); | 726 | const atom = self.getAtom(atom_index); |
| 773 | const sym = atom.getSymbol(self); | 727 | const sym = atom.getSymbol(self); |
| ... | @@ -873,17 +827,73 @@ fn writeMem(handle: std.ChildProcess.Id, pvaddr: std.os.windows.LPVOID, code: [] | ... | @@ -873,17 +827,73 @@ fn writeMem(handle: std.ChildProcess.Id, pvaddr: std.os.windows.LPVOID, code: [] |
| 873 | if (amt != code.len) return error.InputOutput; | 827 | if (amt != code.len) return error.InputOutput; |
| 874 | } | 828 | } |
| 875 | | 829 | |
| 876 | fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { | 830 | fn writeOffsetTableEntry(self: *Coff, index: usize) !void { |
| | 831 | const sect_id = self.got_section_index.?; |
| | 832 | |
| | 833 | if (self.got_table_count_dirty) { |
| | 834 | const needed_size = @intCast(u32, self.got_table.entries.items.len * self.ptr_width.size()); |
| | 835 | try self.growSection(sect_id, needed_size); |
| | 836 | self.got_table_count_dirty = false; |
| | 837 | } |
| | 838 | |
| | 839 | const header = &self.sections.items(.header)[sect_id]; |
| | 840 | const entry = self.got_table.entries.items[index]; |
| | 841 | const entry_value = self.getSymbol(entry).value; |
| | 842 | const entry_offset = index * self.ptr_width.size(); |
| | 843 | const file_offset = header.pointer_to_raw_data + entry_offset; |
| | 844 | const vmaddr = header.virtual_address + entry_offset; |
| | 845 | |
| | 846 | log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value }); |
| | 847 | |
| 877 | switch (self.ptr_width) { | 848 | switch (self.ptr_width) { |
| 878 | .p32 => { | 849 | .p32 => { |
| 879 | var buffer: [@sizeOf(u32)]u8 = [_]u8{0} ** @sizeOf(u32); | 850 | var buf: [4]u8 = undefined; |
| 880 | try self.writeAtom(atom_index, &buffer); | 851 | mem.writeIntLittle(u32, &buf, @intCast(u32, entry_value)); |
| | 852 | try self.base.file.?.pwriteAll(&buf, file_offset); |
| 881 | }, | 853 | }, |
| 882 | .p64 => { | 854 | .p64 => { |
| 883 | var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64); | 855 | var buf: [8]u8 = undefined; |
| 884 | try self.writeAtom(atom_index, &buffer); | 856 | mem.writeIntLittle(u64, &buf, entry_value); |
| | 857 | try self.base.file.?.pwriteAll(&buf, file_offset); |
| 885 | }, | 858 | }, |
| 886 | } | 859 | } |
| | 860 | |
| | 861 | if (is_hot_update_compatible) { |
| | 862 | if (self.base.child_pid) |handle| { |
| | 863 | const gpa = self.base.allocator; |
| | 864 | const slide = @ptrToInt(self.hot_state.loaded_base_address.?); |
| | 865 | const actual_vmaddr = vmaddr + slide; |
| | 866 | const pvaddr = @intToPtr(*anyopaque, actual_vmaddr); |
| | 867 | log.debug("writing GOT entry to memory at address {x}", .{actual_vmaddr}); |
| | 868 | if (build_options.enable_logging) { |
| | 869 | switch (self.ptr_width) { |
| | 870 | .p32 => { |
| | 871 | var buf: [4]u8 = undefined; |
| | 872 | try debugMem(gpa, handle, pvaddr, &buf); |
| | 873 | }, |
| | 874 | .p64 => { |
| | 875 | var buf: [8]u8 = undefined; |
| | 876 | try debugMem(gpa, handle, pvaddr, &buf); |
| | 877 | }, |
| | 878 | } |
| | 879 | } |
| | 880 | |
| | 881 | switch (self.ptr_width) { |
| | 882 | .p32 => { |
| | 883 | var buf: [4]u8 = undefined; |
| | 884 | writeMem(handle, pvaddr, &buf) catch |err| { |
| | 885 | log.warn("writing to protected memory failed with error: {s}", .{@errorName(err)}); |
| | 886 | }; |
| | 887 | }, |
| | 888 | .p64 => { |
| | 889 | var buf: [8]u8 = undefined; |
| | 890 | writeMem(handle, pvaddr, &buf) catch |err| { |
| | 891 | log.warn("writing to protected memory failed with error: {s}", .{@errorName(err)}); |
| | 892 | }; |
| | 893 | }, |
| | 894 | } |
| | 895 | } |
| | 896 | } |
| 887 | } | 897 | } |
| 888 | | 898 | |
| 889 | fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { | 899 | fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { |
| ... | @@ -904,6 +914,15 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { | ... | @@ -904,6 +914,15 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { |
| 904 | reloc.dirty = true; | 914 | reloc.dirty = true; |
| 905 | } | 915 | } |
| 906 | } | 916 | } |
| | 917 | |
| | 918 | // TODO: dirty only really affected GOT cells |
| | 919 | for (self.got_table.entries.items) |entry| { |
| | 920 | const target_addr = self.getSymbol(entry).value; |
| | 921 | if (target_addr >= addr) { |
| | 922 | self.got_table_contents_dirty = true; |
| | 923 | break; |
| | 924 | } |
| | 925 | } |
| 907 | } | 926 | } |
| 908 | | 927 | |
| 909 | fn resolveRelocs(self: *Coff, atom_index: Atom.Index, relocs: []*const Relocation, code: []u8, image_base: u64) void { | 928 | fn resolveRelocs(self: *Coff, atom_index: Atom.Index, relocs: []*const Relocation, code: []u8, image_base: u64) void { |
| ... | @@ -994,17 +1013,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void { | ... | @@ -994,17 +1013,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void { |
| 994 | self.locals_free_list.append(gpa, sym_index) catch {}; | 1013 | self.locals_free_list.append(gpa, sym_index) catch {}; |
| 995 | | 1014 | |
| 996 | // Try freeing GOT atom if this decl had one | 1015 | // Try freeing GOT atom if this decl had one |
| 997 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | 1016 | self.got_table.freeEntry(gpa, .{ .sym_index = sym_index }); |
| 998 | if (self.got_entries_table.get(got_target)) |got_index| { | | |
| 999 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; | | |
| 1000 | self.got_entries.items[got_index] = .{ | | |
| 1001 | .target = .{ .sym_index = 0, .file = null }, | | |
| 1002 | .sym_index = 0, | | |
| 1003 | }; | | |
| 1004 | _ = self.got_entries_table.remove(got_target); | | |
| 1005 | | | |
| 1006 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); | | |
| 1007 | } | | |
| 1008 | | 1017 | |
| 1009 | self.locals.items[sym_index].section_number = .UNDEFINED; | 1018 | self.locals.items[sym_index].section_number = .UNDEFINED; |
| 1010 | _ = self.atom_by_index_table.remove(sym_index); | 1019 | _ = self.atom_by_index_table.remove(sym_index); |
| ... | @@ -1243,14 +1252,7 @@ fn updateLazySymbolAtom( | ... | @@ -1243,14 +1252,7 @@ fn updateLazySymbolAtom( |
| 1243 | atom.size = code_len; | 1252 | atom.size = code_len; |
| 1244 | symbol.value = vaddr; | 1253 | symbol.value = vaddr; |
| 1245 | | 1254 | |
| 1246 | const got_target = SymbolWithLoc{ .sym_index = local_sym_index, .file = null }; | 1255 | try self.addGotEntry(.{ .sym_index = local_sym_index }); |
| 1247 | const got_index = try self.allocateGotEntry(got_target); | | |
| 1248 | const got_atom_index = try self.createGotAtom(got_target); | | |
| 1249 | const got_atom = self.getAtom(got_atom_index); | | |
| 1250 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; | | |
| 1251 | try self.writePtrWidthAtom(got_atom_index); | | |
| 1252 | | | |
| 1253 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); | | |
| 1254 | try self.writeAtom(atom_index, code); | 1256 | try self.writeAtom(atom_index, code); |
| 1255 | } | 1257 | } |
| 1256 | | 1258 | |
| ... | @@ -1321,6 +1323,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple | ... | @@ -1321,6 +1323,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple |
| 1321 | const decl_metadata = self.decls.get(decl_index).?; | 1323 | const decl_metadata = self.decls.get(decl_index).?; |
| 1322 | const atom_index = decl_metadata.atom; | 1324 | const atom_index = decl_metadata.atom; |
| 1323 | const atom = self.getAtom(atom_index); | 1325 | const atom = self.getAtom(atom_index); |
| | 1326 | const sym_index = atom.getSymbolIndex().?; |
| 1324 | const sect_index = decl_metadata.section; | 1327 | const sect_index = decl_metadata.section; |
| 1325 | const code_len = @intCast(u32, code.len); | 1328 | const code_len = @intCast(u32, code.len); |
| 1326 | | 1329 | |
| ... | @@ -1340,10 +1343,8 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple | ... | @@ -1340,10 +1343,8 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple |
| 1340 | if (vaddr != sym.value) { | 1343 | if (vaddr != sym.value) { |
| 1341 | sym.value = vaddr; | 1344 | sym.value = vaddr; |
| 1342 | log.debug(" (updating GOT entry)", .{}); | 1345 | log.debug(" (updating GOT entry)", .{}); |
| 1343 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; | 1346 | const got_entry_index = self.got_table.lookup.get(.{ .sym_index = sym_index }).?; |
| 1344 | const got_atom_index = self.getGotAtomIndexForSymbol(got_target).?; | 1347 | try self.writeOffsetTableEntry(got_entry_index); |
| 1345 | self.markRelocsDirtyByTarget(got_target); | | |
| 1346 | try self.writePtrWidthAtom(got_atom_index); | | |
| 1347 | } | 1348 | } |
| 1348 | } else if (code_len < atom.size) { | 1349 | } else if (code_len < atom.size) { |
| 1349 | self.shrinkAtom(atom_index, code_len); | 1350 | self.shrinkAtom(atom_index, code_len); |
| ... | @@ -1361,15 +1362,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple | ... | @@ -1361,15 +1362,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple |
| 1361 | self.getAtomPtr(atom_index).size = code_len; | 1362 | self.getAtomPtr(atom_index).size = code_len; |
| 1362 | sym.value = vaddr; | 1363 | sym.value = vaddr; |
| 1363 | | 1364 | |
| 1364 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; | 1365 | try self.addGotEntry(.{ .sym_index = sym_index }); |
| 1365 | const got_index = try self.allocateGotEntry(got_target); | | |
| 1366 | const got_atom_index = try self.createGotAtom(got_target); | | |
| 1367 | const got_atom = self.getAtom(got_atom_index); | | |
| 1368 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; | | |
| 1369 | try self.writePtrWidthAtom(got_atom_index); | | |
| 1370 | } | 1366 | } |
| 1371 | | 1367 | |
| 1372 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); | | |
| 1373 | try self.writeAtom(atom_index, code); | 1368 | try self.writeAtom(atom_index, code); |
| 1374 | } | 1369 | } |
| 1375 | | 1370 | |
| ... | @@ -1651,6 +1646,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -1651,6 +1646,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1651 | try self.writeAtom(atom_index, code.items); | 1646 | try self.writeAtom(atom_index, code.items); |
| 1652 | } | 1647 | } |
| 1653 | | 1648 | |
| | 1649 | // Update GOT if it got moved in memory. |
| | 1650 | if (self.got_table_contents_dirty) { |
| | 1651 | for (self.got_table.entries.items, 0..) |entry, i| { |
| | 1652 | if (!self.got_table.lookup.contains(entry)) continue; |
| | 1653 | // TODO: write all in one go rather than incrementally. |
| | 1654 | try self.writeOffsetTableEntry(i); |
| | 1655 | } |
| | 1656 | self.got_table_contents_dirty = false; |
| | 1657 | } |
| | 1658 | |
| 1654 | try self.writeBaseRelocations(); | 1659 | try self.writeBaseRelocations(); |
| 1655 | | 1660 | |
| 1656 | if (self.getEntryPoint()) |entry_sym_loc| { | 1661 | if (self.getEntryPoint()) |entry_sym_loc| { |
| ... | @@ -1752,10 +1757,10 @@ fn writeBaseRelocations(self: *Coff) !void { | ... | @@ -1752,10 +1757,10 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1752 | while (it.next()) |entry| { | 1757 | while (it.next()) |entry| { |
| 1753 | const atom_index = entry.key_ptr.*; | 1758 | const atom_index = entry.key_ptr.*; |
| 1754 | const atom = self.getAtom(atom_index); | 1759 | const atom = self.getAtom(atom_index); |
| | 1760 | const sym = atom.getSymbol(self); |
| 1755 | const offsets = entry.value_ptr.*; | 1761 | const offsets = entry.value_ptr.*; |
| 1756 | | 1762 | |
| 1757 | for (offsets.items) |offset| { | 1763 | for (offsets.items) |offset| { |
| 1758 | const sym = atom.getSymbol(self); | | |
| 1759 | const rva = sym.value + offset; | 1764 | const rva = sym.value + offset; |
| 1760 | const page = mem.alignBackwardGeneric(u32, rva, self.page_size); | 1765 | const page = mem.alignBackwardGeneric(u32, rva, self.page_size); |
| 1761 | const gop = try pages.getOrPut(page); | 1766 | const gop = try pages.getOrPut(page); |
| ... | @@ -1769,6 +1774,27 @@ fn writeBaseRelocations(self: *Coff) !void { | ... | @@ -1769,6 +1774,27 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1769 | } | 1774 | } |
| 1770 | } | 1775 | } |
| 1771 | | 1776 | |
| | 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; |
| | 1781 | |
| | 1782 | const sym = self.getSymbol(entry); |
| | 1783 | if (sym.section_number == .UNDEFINED) continue; |
| | 1784 | |
| | 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); |
| | 1790 | } |
| | 1791 | try gop.value_ptr.append(.{ |
| | 1792 | .offset = @intCast(u12, rva - page), |
| | 1793 | .type = .DIR64, |
| | 1794 | }); |
| | 1795 | } |
| | 1796 | } |
| | 1797 | |
| 1772 | var buffer = std.ArrayList(u8).init(gpa); | 1798 | var buffer = std.ArrayList(u8).init(gpa); |
| 1773 | defer buffer.deinit(); | 1799 | defer buffer.deinit(); |
| 1774 | | 1800 | |
| ... | @@ -2315,14 +2341,6 @@ pub fn getAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.In | ... | @@ -2315,14 +2341,6 @@ pub fn getAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.In |
| 2315 | return self.atom_by_index_table.get(sym_loc.sym_index); | 2341 | return self.atom_by_index_table.get(sym_loc.sym_index); |
| 2316 | } | 2342 | } |
| 2317 | | 2343 | |
| 2318 | /// Returns GOT atom that references `sym_loc` if one exists. | | |
| 2319 | /// Returns null otherwise. | | |
| 2320 | pub fn getGotAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.Index { | | |
| 2321 | const got_index = self.got_entries_table.get(sym_loc) orelse return null; | | |
| 2322 | const got_entry = self.got_entries.items[got_index]; | | |
| 2323 | return self.getAtomIndexForSymbol(.{ .sym_index = got_entry.sym_index, .file = null }); | | |
| 2324 | } | | |
| 2325 | | | |
| 2326 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { | 2344 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { |
| 2327 | if (name.len <= 8) { | 2345 | if (name.len <= 8) { |
| 2328 | mem.copy(u8, &header.name, name); | 2346 | mem.copy(u8, &header.name, name); |
| ... | @@ -2410,25 +2428,7 @@ fn logSymtab(self: *Coff) void { | ... | @@ -2410,25 +2428,7 @@ fn logSymtab(self: *Coff) void { |
| 2410 | } | 2428 | } |
| 2411 | | 2429 | |
| 2412 | log.debug("GOT entries:", .{}); | 2430 | log.debug("GOT entries:", .{}); |
| 2413 | for (self.got_entries.items, 0..) |entry, i| { | 2431 | log.debug("{}", .{self.got_table}); |
| 2414 | const got_sym = self.getSymbol(.{ .sym_index = entry.sym_index, .file = null }); | | |
| 2415 | const target_sym = self.getSymbol(entry.target); | | |
| 2416 | if (target_sym.section_number == .UNDEFINED) { | | |
| 2417 | log.debug(" {d}@{x} => import('{s}')", .{ | | |
| 2418 | i, | | |
| 2419 | got_sym.value, | | |
| 2420 | self.getSymbolName(entry.target), | | |
| 2421 | }); | | |
| 2422 | } else { | | |
| 2423 | log.debug(" {d}@{x} => local(%{d}) in object({?d}) {s}", .{ | | |
| 2424 | i, | | |
| 2425 | got_sym.value, | | |
| 2426 | entry.target.sym_index, | | |
| 2427 | entry.target.file, | | |
| 2428 | logSymAttributes(target_sym, &buf), | | |
| 2429 | }); | | |
| 2430 | } | | |
| 2431 | } | | |
| 2432 | } | 2432 | } |
| 2433 | | 2433 | |
| 2434 | fn logSections(self: *Coff) void { | 2434 | fn logSections(self: *Coff) void { |
| ... | @@ -2484,6 +2484,7 @@ const LlvmObject = @import("../codegen/llvm.zig").Object; | ... | @@ -2484,6 +2484,7 @@ const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 2484 | const Module = @import("../Module.zig"); | 2484 | const Module = @import("../Module.zig"); |
| 2485 | const Object = @import("Coff/Object.zig"); | 2485 | const Object = @import("Coff/Object.zig"); |
| 2486 | const Relocation = @import("Coff/Relocation.zig"); | 2486 | const Relocation = @import("Coff/Relocation.zig"); |
| | 2487 | const TableSection = @import("table_section.zig").TableSection; |
| 2487 | const StringTable = @import("strtab.zig").StringTable; | 2488 | const StringTable = @import("strtab.zig").StringTable; |
| 2488 | const Type = @import("../type.zig").Type; | 2489 | const Type = @import("../type.zig").Type; |
| 2489 | const TypedValue = @import("../TypedValue.zig"); | 2490 | const TypedValue = @import("../TypedValue.zig"); |