authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-29 18:15:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-30 10:42:21+02:00
logf0d4ce4494f910508a127aad83cfbc557ac4aef9
tree7e2c74dbf6a34c41ed1c912e9662b5c0e6857591
parentdb1a3bb0e70338dc5261adf148284c1408d3df87

coff: add basic handling of GOT PC relative indirection


4 files changed, 157 insertions(+), 64 deletions(-)

src/arch/x86_64/CodeGen.zig+47-15
...@@ -2664,6 +2664,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2664,6 +2664,10 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2664 };2664 };
2665 const mod = self.bin_file.options.module.?;2665 const mod = self.bin_file.options.module.?;
2666 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);2666 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
2667 const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag)
2668 fn_owner_decl.link.macho.sym_index
2669 else
2670 fn_owner_decl.link.coff.sym_index;
2667 _ = try self.addInst(.{2671 _ = try self.addInst(.{
2668 .tag = .lea_pie,2672 .tag = .lea_pie,
2669 .ops = Mir.Inst.Ops.encode(.{2673 .ops = Mir.Inst.Ops.encode(.{
...@@ -2672,7 +2676,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2672,7 +2676,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2672 }),2676 }),
2673 .data = .{2677 .data = .{
2674 .relocation = .{2678 .relocation = .{
2675 .atom_index = fn_owner_decl.link.macho.sym_index,2679 .atom_index = atom_index,
2676 .sym_index = sym_index,2680 .sym_index = sym_index,
2677 },2681 },
2678 },2682 },
...@@ -3961,21 +3965,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3961,21 +3965,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3961 // Due to incremental compilation, how function calls are generated depends3965 // Due to incremental compilation, how function calls are generated depends
3962 // on linking.3966 // on linking.
3963 const mod = self.bin_file.options.module.?;3967 const mod = self.bin_file.options.module.?;
3964 if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) {3968 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3965 if (self.air.value(callee)) |func_value| {3969 if (self.air.value(callee)) |func_value| {
3966 if (func_value.castTag(.function)) |func_payload| {3970 if (func_value.castTag(.function)) |func_payload| {
3967 const func = func_payload.data;3971 const func = func_payload.data;
3968 const ptr_bits = self.target.cpu.arch.ptrBitWidth();3972 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3969 const ptr_bytes: u64 = @divExact(ptr_bits, 8);3973 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3970 const fn_owner_decl = mod.declPtr(func.owner_decl);3974 const fn_owner_decl = mod.declPtr(func.owner_decl);
3971 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {3975 const got_addr = blk: {
3972 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];3976 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
3973 break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes);3977 break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes);
3974 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {3978 };
3975 const got_atom = coff_file.getGotAtomForSymbol(.{ .sym_index = fn_owner_decl.link.coff.sym_index, .file = null }).?;
3976 const got_sym = coff_file.getSymbol(got_atom.getSymbolWithLoc());
3977 break :blk got_sym.value;
3978 } else unreachable;
3979 _ = try self.addInst(.{3979 _ = try self.addInst(.{
3980 .tag = .call,3980 .tag = .call,
3981 .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),3981 .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
...@@ -3999,14 +3999,47 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3999,14 +3999,47 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3999 .data = undefined,3999 .data = undefined,
4000 });4000 });
4001 }4001 }
4002 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4002 } else if (self.bin_file.cast(link.File.Coff)) |_| {
4003 if (self.air.value(callee)) |func_value| {4003 if (self.air.value(callee)) |func_value| {
4004 if (func_value.castTag(.function)) |func_payload| {4004 if (func_value.castTag(.function)) |func_payload| {
4005 const func = func_payload.data;4005 const func = func_payload.data;
4006 const fn_owner_decl = mod.declPtr(func.owner_decl);4006 const fn_owner_decl = mod.declPtr(func.owner_decl);
4007 try self.genSetReg(Type.initTag(.usize), .rax, .{4007 const sym_index = fn_owner_decl.link.coff.sym_index;
4008 .got_load = fn_owner_decl.link.macho.sym_index,4008 try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index });
4009 // callq *%rax
4010 _ = try self.addInst(.{
4011 .tag = .call,
4012 .ops = Mir.Inst.Ops.encode(.{
4013 .reg1 = .rax,
4014 .flags = 0b01,
4015 }),
4016 .data = undefined,
4009 });4017 });
4018 } else if (func_value.castTag(.extern_fn)) |_| {
4019 return self.fail("TODO implement calling extern functions", .{});
4020 } else {
4021 return self.fail("TODO implement calling bitcasted functions", .{});
4022 }
4023 } else {
4024 assert(ty.zigTypeTag() == .Pointer);
4025 const mcv = try self.resolveInst(callee);
4026 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4027 _ = try self.addInst(.{
4028 .tag = .call,
4029 .ops = Mir.Inst.Ops.encode(.{
4030 .reg1 = .rax,
4031 .flags = 0b01,
4032 }),
4033 .data = undefined,
4034 });
4035 }
4036 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4037 if (self.air.value(callee)) |func_value| {
4038 if (func_value.castTag(.function)) |func_payload| {
4039 const func = func_payload.data;
4040 const fn_owner_decl = mod.declPtr(func.owner_decl);
4041 const sym_index = fn_owner_decl.link.macho.sym_index;
4042 try self.genSetReg(Type.initTag(.usize), .rax, .{ .got_load = sym_index });
4010 // callq *%rax4043 // callq *%rax
4011 _ = try self.addInst(.{4044 _ = try self.addInst(.{
4012 .tag = .call,4045 .tag = .call,
...@@ -6847,10 +6880,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6847,10 +6880,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6847 // the linker has enough info to perform relocations.6880 // the linker has enough info to perform relocations.
6848 assert(decl.link.macho.sym_index != 0);6881 assert(decl.link.macho.sym_index != 0);
6849 return MCValue{ .got_load = decl.link.macho.sym_index };6882 return MCValue{ .got_load = decl.link.macho.sym_index };
6850 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {6883 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6851 const got_atom = coff_file.getGotAtomForSymbol(.{ .sym_index = decl.link.coff.sym_index, .file = null }).?;6884 assert(decl.link.coff.sym_index != 0);
6852 const got_sym = coff_file.getSymbol(got_atom.getSymbolWithLoc());6885 return MCValue{ .got_load = decl.link.coff.sym_index };
6853 return MCValue{ .memory = got_sym.value };
6854 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {6886 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6855 try p9.seeDecl(decl_index);6887 try p9.seeDecl(decl_index);
6856 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;6888 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
src/arch/x86_64/Emit.zig+20-1
...@@ -994,6 +994,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -994,6 +994,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
994 );994 );
995995
996 const end_offset = emit.code.items.len;996 const end_offset = emit.code.items.len;
997 const gpa = emit.bin_file.allocator;
997998
998 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {999 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
999 const reloc_type = switch (ops.flags) {1000 const reloc_type = switch (ops.flags) {
...@@ -1003,7 +1004,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1003,7 +1004,7 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1003 };1004 };
1004 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;1005 const atom = macho_file.atom_by_index_table.get(relocation.atom_index).?;
1005 log.debug("adding reloc of type {} to local @{d}", .{ reloc_type, relocation.sym_index });1006 log.debug("adding reloc of type {} to local @{d}", .{ reloc_type, relocation.sym_index });
1006 try atom.relocs.append(emit.bin_file.allocator, .{1007 try atom.relocs.append(gpa, .{
1007 .offset = @intCast(u32, end_offset - 4),1008 .offset = @intCast(u32, end_offset - 4),
1008 .target = .{ .sym_index = relocation.sym_index, .file = null },1009 .target = .{ .sym_index = relocation.sym_index, .file = null },
1009 .addend = 0,1010 .addend = 0,
...@@ -1012,6 +1013,24 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1012,6 +1013,24 @@ fn mirLeaPie(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1012 .length = 2,1013 .length = 2,
1013 .@"type" = reloc_type,1014 .@"type" = reloc_type,
1014 });1015 });
1016 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
1017 const atom = coff_file.atom_by_index_table.get(relocation.atom_index).?;
1018 log.debug("adding reloc to local @{d}", .{relocation.sym_index});
1019 const gop = try coff_file.relocs.getOrPut(gpa, atom);
1020 if (!gop.found_existing) {
1021 gop.value_ptr.* = .{};
1022 }
1023 try gop.value_ptr.append(gpa, .{
1024 .@"type" = switch (ops.flags) {
1025 0b00 => .got_pcrel,
1026 0b01 => .direct,
1027 else => return emit.fail("TODO unused LEA PIE variants 0b10 and 0b11", .{}),
1028 },
1029 .target = .{ .sym_index = relocation.sym_index, .file = null },
1030 .offset = @intCast(u32, end_offset - 4),
1031 .addend = 0,
1032 .prev_vaddr = atom.getSymbol(coff_file).value,
1033 });
1015 } else {1034 } else {
1016 return emit.fail(1035 return emit.fail(
1017 "TODO implement lea reg, [rip + reloc] for linking backends different than MachO",1036 "TODO implement lea reg, [rip + reloc] for linking backends different than MachO",
src/link/Coff.zig+82-43
...@@ -104,6 +104,10 @@ unnamed_const_atoms: UnnamedConstTable = .{},...@@ -104,6 +104,10 @@ unnamed_const_atoms: UnnamedConstTable = .{},
104relocs: RelocTable = .{},104relocs: RelocTable = .{},
105105
106const Reloc = struct {106const Reloc = struct {
107 @"type": enum {
108 got_pcrel,
109 direct,
110 },
107 target: SymbolWithLoc,111 target: SymbolWithLoc,
108 offset: u32,112 offset: u32,
109 addend: u32,113 addend: u32,
...@@ -413,10 +417,11 @@ pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void {...@@ -413,10 +417,11 @@ pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void {
413 try self.decls.putNoClobber(gpa, decl_index, null);417 try self.decls.putNoClobber(gpa, decl_index, null);
414}418}
415419
416fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32, sect_id: u16) !u32 {420fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 {
417 const tracy = trace(@src());421 const tracy = trace(@src());
418 defer tracy.end();422 defer tracy.end();
419423
424 const sect_id = @enumToInt(atom.getSymbol(self).section_number) - 1;
420 const header = &self.sections.items(.header)[sect_id];425 const header = &self.sections.items(.header)[sect_id];
421 const free_list = &self.sections.items(.free_list)[sect_id];426 const free_list = &self.sections.items(.free_list)[sect_id];
422 const maybe_last_atom = &self.sections.items(.last_atom)[sect_id];427 const maybe_last_atom = &self.sections.items(.last_atom)[sect_id];
...@@ -580,18 +585,20 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {...@@ -580,18 +585,20 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
580585
581 try self.managed_atoms.append(gpa, atom);586 try self.managed_atoms.append(gpa, atom);
582 try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom);587 try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom);
588 self.got_entries.getPtr(target).?.* = atom.sym_index;
583589
584 const sym = atom.getSymbolPtr(self);590 const sym = atom.getSymbolPtr(self);
585 sym.value = try self.allocateAtom(atom, atom.size, atom.alignment, self.got_section_index.?);
586 sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1);591 sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1);
592 sym.value = try self.allocateAtom(atom, atom.size, atom.alignment);
587593
588 log.debug("allocated {s} atom at 0x{x}", .{ atom.getName(self), sym.value });594 log.debug("allocated GOT atom at 0x{x}", .{sym.value});
589595
590 const gop_relocs = try self.relocs.getOrPut(gpa, atom);596 const gop_relocs = try self.relocs.getOrPut(gpa, atom);
591 if (!gop_relocs.found_existing) {597 if (!gop_relocs.found_existing) {
592 gop_relocs.value_ptr.* = .{};598 gop_relocs.value_ptr.* = .{};
593 }599 }
594 try gop_relocs.value_ptr.append(gpa, .{600 try gop_relocs.value_ptr.append(gpa, .{
601 .@"type" = .direct,
595 .target = target,602 .target = target,
596 .offset = 0,603 .offset = 0,
597 .addend = 0,604 .addend = 0,
...@@ -601,72 +608,98 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {...@@ -601,72 +608,98 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
601 return atom;608 return atom;
602}609}
603610
604fn growAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32, sect_id: u16) !u32 {611fn growAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 {
605 const sym = atom.getSymbol(self);612 const sym = atom.getSymbol(self);
606 const align_ok = mem.alignBackwardGeneric(u32, sym.value, alignment) == sym.value;613 const align_ok = mem.alignBackwardGeneric(u32, sym.value, alignment) == sym.value;
607 const need_realloc = !align_ok or new_atom_size > atom.capacity(self);614 const need_realloc = !align_ok or new_atom_size > atom.capacity(self);
608 if (!need_realloc) return sym.value;615 if (!need_realloc) return sym.value;
609 return self.allocateAtom(atom, new_atom_size, alignment, sect_id);616 return self.allocateAtom(atom, new_atom_size, alignment);
610}617}
611618
612fn shrinkAtom(self: *Coff, atom: *Atom, new_block_size: u32, sect_id: u16) void {619fn shrinkAtom(self: *Coff, atom: *Atom, new_block_size: u32) void {
613 _ = self;620 _ = self;
614 _ = atom;621 _ = atom;
615 _ = new_block_size;622 _ = new_block_size;
616 _ = sect_id;
617 // TODO check the new capacity, and if it crosses the size threshold into a big enough623 // TODO check the new capacity, and if it crosses the size threshold into a big enough
618 // capacity, insert a free list node for it.624 // capacity, insert a free list node for it.
619}625}
620626
621fn writeAtom(self: *Coff, atom: *Atom, code: []const u8, sect_id: u16) !void {627fn writeAtom(self: *Coff, atom: *Atom, code: []const u8) !void {
622 const section = self.sections.get(sect_id);
623 const sym = atom.getSymbol(self);628 const sym = atom.getSymbol(self);
629 const section = self.sections.get(@enumToInt(sym.section_number) - 1);
624 const file_offset = section.header.pointer_to_raw_data + sym.value - section.header.virtual_address;630 const file_offset = section.header.pointer_to_raw_data + sym.value - section.header.virtual_address;
625 const resolved = try self.resolveRelocs(atom, code);
626 defer self.base.allocator.free(resolved);
627 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });631 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });
628 try self.base.file.?.pwriteAll(resolved, file_offset);632 try self.base.file.?.pwriteAll(code, file_offset);
633 try self.resolveRelocs(atom);
629}634}
630635
631fn writeGotAtom(self: *Coff, atom: *Atom) !void {636fn writeGotAtom(self: *Coff, atom: *Atom) !void {
632 switch (self.ptr_width) {637 switch (self.ptr_width) {
633 .p32 => {638 .p32 => {
634 var buffer: [@sizeOf(u32)]u8 = [_]u8{0} ** @sizeOf(u32);639 var buffer: [@sizeOf(u32)]u8 = [_]u8{0} ** @sizeOf(u32);
635 try self.writeAtom(atom, &buffer, self.got_section_index.?);640 try self.writeAtom(atom, &buffer);
636 },641 },
637 .p64 => {642 .p64 => {
638 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);643 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);
639 try self.writeAtom(atom, &buffer, self.got_section_index.?);644 try self.writeAtom(atom, &buffer);
640 },645 },
641 }646 }
642}647}
643648
644fn resolveRelocs(self: *Coff, atom: *Atom, code: []const u8) ![]const u8 {649fn resolveRelocs(self: *Coff, atom: *Atom) !void {
645 const gpa = self.base.allocator;650 const relocs = self.relocs.get(atom) orelse return;
646 const resolved = try gpa.dupe(u8, code);651 const source_sym = atom.getSymbol(self);
647 const relocs = self.relocs.get(atom) orelse return resolved;652 const source_section = self.sections.get(@enumToInt(source_sym.section_number) - 1).header;
653 const file_offset = source_section.pointer_to_raw_data + source_sym.value - source_section.virtual_address;
654
655 log.debug("relocating '{s}'", .{atom.getName(self)});
648656
649 for (relocs.items) |*reloc| {657 for (relocs.items) |*reloc| {
650 const target_sym = self.getSymbol(reloc.target);658 const target_vaddr = switch (reloc.@"type") {
651 const target_vaddr = target_sym.value + reloc.addend;659 .got_pcrel => blk: {
652 if (target_vaddr == reloc.prev_vaddr) continue;660 const got_atom = self.getGotAtomForSymbol(reloc.target) orelse continue;
661 break :blk got_atom.getSymbol(self).value;
662 },
663 .direct => self.getSymbol(reloc.target).value,
664 };
665 const target_vaddr_with_addend = target_vaddr + reloc.addend;
653666
654 log.debug(" ({x}: [() => 0x{x} ({s}))", .{ reloc.offset, target_vaddr, self.getSymbolName(reloc.target) });667 if (target_vaddr_with_addend == reloc.prev_vaddr) continue;
655668
656 switch (self.ptr_width) {669 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{
657 .p32 => mem.writeIntLittle(u32, resolved[reloc.offset..][0..4], @intCast(u32, target_vaddr)),670 reloc.offset,
658 .p64 => mem.writeIntLittle(u64, resolved[reloc.offset..][0..8], target_vaddr),671 target_vaddr_with_addend,
672 self.getSymbolName(reloc.target),
673 @tagName(reloc.@"type"),
674 });
675
676 switch (reloc.@"type") {
677 .got_pcrel => {
678 const source_vaddr = source_sym.value + reloc.offset;
679 const disp = target_vaddr_with_addend - source_vaddr - 4;
680 try self.base.file.?.pwriteAll(mem.asBytes(&@intCast(u32, disp)), file_offset + reloc.offset);
681 },
682 .direct => switch (self.ptr_width) {
683 .p32 => try self.base.file.?.pwriteAll(
684 mem.asBytes(&@intCast(u32, target_vaddr_with_addend + default_image_base_exe)),
685 file_offset + reloc.offset,
686 ),
687 .p64 => try self.base.file.?.pwriteAll(
688 mem.asBytes(&(target_vaddr_with_addend + default_image_base_exe)),
689 file_offset + reloc.offset,
690 ),
691 },
659 }692 }
660693
661 reloc.prev_vaddr = target_vaddr;694 reloc.prev_vaddr = target_vaddr_with_addend;
662 }695 }
663
664 return resolved;
665}696}
666697
667fn freeAtom(self: *Coff, atom: *Atom, sect_id: u16) void {698fn freeAtom(self: *Coff, atom: *Atom) void {
668 log.debug("freeAtom {*}", .{atom});699 log.debug("freeAtom {*}", .{atom});
669700
701 const sym = atom.getSymbol(self);
702 const sect_id = @enumToInt(sym.section_number) - 1;
670 const free_list = &self.sections.items(.free_list)[sect_id];703 const free_list = &self.sections.items(.free_list)[sect_id];
671 var already_have_free_list_node = false;704 var already_have_free_list_node = false;
672 {705 {
...@@ -858,11 +891,14 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -858,11 +891,14 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
858 assert(atom.sym_index != 0); // Caller forgot to allocateDeclIndexes()891 assert(atom.sym_index != 0); // Caller forgot to allocateDeclIndexes()
859 if (atom.size != 0) {892 if (atom.size != 0) {
860 const sym = atom.getSymbolPtr(self);893 const sym = atom.getSymbolPtr(self);
894 try self.setSymbolName(sym, decl_name);
895 sym.section_number = @intToEnum(coff.SectionNumber, sect_index + 1);
896 sym.@"type" = .{ .complex_type = complex_type, .base_type = .NULL };
897
861 const capacity = atom.capacity(self);898 const capacity = atom.capacity(self);
862 const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment);899 const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment);
863
864 if (need_realloc) {900 if (need_realloc) {
865 const vaddr = try self.growAtom(atom, code_len, required_alignment, sect_index);901 const vaddr = try self.growAtom(atom, code_len, required_alignment);
866 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr });902 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr });
867 log.debug(" (required alignment 0x{x}", .{required_alignment});903 log.debug(" (required alignment 0x{x}", .{required_alignment});
868904
...@@ -873,24 +909,20 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -873,24 +909,20 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
873 try self.writeGotAtom(got_atom);909 try self.writeGotAtom(got_atom);
874 }910 }
875 } else if (code_len < atom.size) {911 } else if (code_len < atom.size) {
876 self.shrinkAtom(atom, code_len, sect_index);912 self.shrinkAtom(atom, code_len);
877 }913 }
878 atom.size = code_len;914 atom.size = code_len;
879 try self.setSymbolName(sym, decl_name);
880 sym.section_number = @intToEnum(coff.SectionNumber, sect_index + 1);
881 sym.@"type" = .{ .complex_type = complex_type, .base_type = .NULL };
882 } else {915 } else {
883 const sym = atom.getSymbolPtr(self);916 const sym = atom.getSymbolPtr(self);
884 try self.setSymbolName(sym, decl_name);917 try self.setSymbolName(sym, decl_name);
885 const vaddr = try self.allocateAtom(atom, code_len, required_alignment, sect_index);918 sym.section_number = @intToEnum(coff.SectionNumber, sect_index + 1);
886 errdefer self.freeAtom(atom, sect_index);919 sym.@"type" = .{ .complex_type = complex_type, .base_type = .NULL };
887920
921 const vaddr = try self.allocateAtom(atom, code_len, required_alignment);
922 errdefer self.freeAtom(atom);
888 log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, vaddr });923 log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, vaddr });
889
890 atom.size = code_len;924 atom.size = code_len;
891 sym.value = vaddr;925 sym.value = vaddr;
892 sym.section_number = @intToEnum(coff.SectionNumber, sect_index + 1);
893 sym.@"type" = .{ .complex_type = complex_type, .base_type = .NULL };
894926
895 const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null };927 const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null };
896 _ = try self.allocateGotEntry(got_target);928 _ = try self.allocateGotEntry(got_target);
...@@ -898,7 +930,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -898,7 +930,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
898 try self.writeGotAtom(got_atom);930 try self.writeGotAtom(got_atom);
899 }931 }
900932
901 try self.writeAtom(atom, code, sect_index);933 try self.writeAtom(atom, code);
902}934}
903935
904pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {936pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {
...@@ -912,8 +944,8 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {...@@ -912,8 +944,8 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {
912 log.debug("freeDecl {*}", .{decl});944 log.debug("freeDecl {*}", .{decl});
913945
914 const kv = self.decls.fetchRemove(decl_index);946 const kv = self.decls.fetchRemove(decl_index);
915 if (kv.?.value) |index| {947 if (kv.?.value) |_| {
916 self.freeAtom(&decl.link.coff, index);948 self.freeAtom(&decl.link.coff);
917 }949 }
918950
919 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.951 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
...@@ -1134,6 +1166,13 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1134,6 +1166,13 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
1134 self.logSymtab();1166 self.logSymtab();
1135 }1167 }
11361168
1169 {
1170 var it = self.relocs.keyIterator();
1171 while (it.next()) |atom| {
1172 try self.resolveRelocs(atom.*);
1173 }
1174 }
1175
1137 if (self.getEntryPoint()) |entry_sym_loc| {1176 if (self.getEntryPoint()) |entry_sym_loc| {
1138 self.entry_addr = self.getSymbol(entry_sym_loc).value;1177 self.entry_addr = self.getSymbol(entry_sym_loc).value;
1139 }1178 }
src/link/Coff/Atom.zig+8-5
...@@ -45,8 +45,11 @@ pub fn deinit(self: *Atom, gpa: Allocator) void {...@@ -45,8 +45,11 @@ pub fn deinit(self: *Atom, gpa: Allocator) void {
45}45}
4646
47/// Returns symbol referencing this atom.47/// Returns symbol referencing this atom.
48pub fn getSymbol(self: Atom, coff_file: *Coff) coff.Symbol {48pub fn getSymbol(self: Atom, coff_file: *const Coff) *const coff.Symbol {
49 return self.getSymbolPtr(coff_file).*;49 return coff_file.getSymbol(.{
50 .sym_index = self.sym_index,
51 .file = self.file,
52 });
50}53}
5154
52/// Returns pointer-to-symbol referencing this atom.55/// Returns pointer-to-symbol referencing this atom.
...@@ -62,7 +65,7 @@ pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc {...@@ -62,7 +65,7 @@ pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc {
62}65}
6366
64/// Returns the name of this atom.67/// Returns the name of this atom.
65pub fn getName(self: Atom, coff_file: *Coff) []const u8 {68pub fn getName(self: Atom, coff_file: *const Coff) []const u8 {
66 return coff_file.getSymbolName(.{69 return coff_file.getSymbolName(.{
67 .sym_index = self.sym_index,70 .sym_index = self.sym_index,
68 .file = self.file,71 .file = self.file,
...@@ -70,7 +73,7 @@ pub fn getName(self: Atom, coff_file: *Coff) []const u8 {...@@ -70,7 +73,7 @@ pub fn getName(self: Atom, coff_file: *Coff) []const u8 {
70}73}
7174
72/// Returns how much room there is to grow in virtual address space.75/// Returns how much room there is to grow in virtual address space.
73pub fn capacity(self: Atom, coff_file: *Coff) u32 {76pub fn capacity(self: Atom, coff_file: *const Coff) u32 {
74 const self_sym = self.getSymbol(coff_file);77 const self_sym = self.getSymbol(coff_file);
75 if (self.next) |next| {78 if (self.next) |next| {
76 const next_sym = next.getSymbol(coff_file);79 const next_sym = next.getSymbol(coff_file);
...@@ -82,7 +85,7 @@ pub fn capacity(self: Atom, coff_file: *Coff) u32 {...@@ -82,7 +85,7 @@ pub fn capacity(self: Atom, coff_file: *Coff) u32 {
82 }85 }
83}86}
8487
85pub fn freeListEligible(self: Atom, coff_file: *Coff) bool {88pub fn freeListEligible(self: Atom, coff_file: *const Coff) bool {
86 // No need to keep a free list node for the last atom.89 // No need to keep a free list node for the last atom.
87 const next = self.next orelse return false;90 const next = self.next orelse return false;
88 const self_sym = self.getSymbol(coff_file);91 const self_sym = self.getSymbol(coff_file);