| author | |
| committer | |
| log | d3d5ed992c339ef114115fb621e0659ce121e027 |
| tree | 397782fb0131dc932f53db662d080c3ab673c024 |
| parent | 517721bbccbbbe571c90226197948a9ae2430d8f |
4 files changed, 69 insertions(+), 46 deletions(-)
src/arch/riscv64/Emit.zig+12-12| ... | ... | @@ -56,17 +56,17 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 56 | 56 | const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20); |
| 57 | 57 | const lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I); |
| 58 | 58 | |
| 59 | try atom_ptr.addReloc(elf_file, .{ | |
| 59 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 60 | 60 | .r_offset = start_offset, |
| 61 | 61 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type, |
| 62 | 62 | .r_addend = 0, |
| 63 | }); | |
| 63 | }, zo); | |
| 64 | 64 | |
| 65 | try atom_ptr.addReloc(elf_file, .{ | |
| 65 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 66 | 66 | .r_offset = start_offset + 4, |
| 67 | 67 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type, |
| 68 | 68 | .r_addend = 0, |
| 69 | }); | |
| 69 | }, zo); | |
| 70 | 70 | }, |
| 71 | 71 | .load_tlv_reloc => |symbol| { |
| 72 | 72 | const elf_file = emit.bin_file.cast(.elf).?; |
| ... | ... | @@ -76,23 +76,23 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 76 | 76 | |
| 77 | 77 | const R_RISCV = std.elf.R_RISCV; |
| 78 | 78 | |
| 79 | try atom_ptr.addReloc(elf_file, .{ | |
| 79 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 80 | 80 | .r_offset = start_offset, |
| 81 | 81 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_HI20), |
| 82 | 82 | .r_addend = 0, |
| 83 | }); | |
| 83 | }, zo); | |
| 84 | 84 | |
| 85 | try atom_ptr.addReloc(elf_file, .{ | |
| 85 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 86 | 86 | .r_offset = start_offset + 4, |
| 87 | 87 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_ADD), |
| 88 | 88 | .r_addend = 0, |
| 89 | }); | |
| 89 | }, zo); | |
| 90 | 90 | |
| 91 | try atom_ptr.addReloc(elf_file, .{ | |
| 91 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 92 | 92 | .r_offset = start_offset + 8, |
| 93 | 93 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_LO12_I), |
| 94 | 94 | .r_addend = 0, |
| 95 | }); | |
| 95 | }, zo); | |
| 96 | 96 | }, |
| 97 | 97 | .call_extern_fn_reloc => |symbol| { |
| 98 | 98 | const elf_file = emit.bin_file.cast(.elf).?; |
| ... | ... | @@ -101,11 +101,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 101 | 101 | |
| 102 | 102 | const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT); |
| 103 | 103 | |
| 104 | try atom_ptr.addReloc(elf_file, .{ | |
| 104 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 105 | 105 | .r_offset = start_offset, |
| 106 | 106 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, |
| 107 | 107 | .r_addend = 0, |
| 108 | }); | |
| 108 | }, zo); | |
| 109 | 109 | }, |
| 110 | 110 | }; |
| 111 | 111 | } |
src/arch/x86_64/Emit.zig+10-10| ... | ... | @@ -48,11 +48,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 48 | 48 | const zo = elf_file.zigObjectPtr().?; |
| 49 | 49 | const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 50 | 50 | const r_type = @intFromEnum(std.elf.R_X86_64.PLT32); |
| 51 | try atom_ptr.addReloc(elf_file, .{ | |
| 51 | try atom_ptr.addReloc(elf_file.base.comp.gpa, .{ | |
| 52 | 52 | .r_offset = end_offset - 4, |
| 53 | 53 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 54 | 54 | .r_addend = lowered_relocs[0].off - 4, |
| 55 | }); | |
| 55 | }, zo); | |
| 56 | 56 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { |
| 57 | 57 | // Add relocation to the decl. |
| 58 | 58 | const zo = macho_file.getZigObject().?; |
| ... | ... | @@ -95,22 +95,22 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 95 | 95 | const zo = elf_file.zigObjectPtr().?; |
| 96 | 96 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 97 | 97 | const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD); |
| 98 | try atom.addReloc(elf_file, .{ | |
| 98 | try atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 99 | 99 | .r_offset = end_offset - 4, |
| 100 | 100 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 101 | 101 | .r_addend = lowered_relocs[0].off - 4, |
| 102 | }); | |
| 102 | }, zo); | |
| 103 | 103 | }, |
| 104 | 104 | .linker_dtpoff => |sym_index| { |
| 105 | 105 | const elf_file = emit.lower.bin_file.cast(.elf).?; |
| 106 | 106 | const zo = elf_file.zigObjectPtr().?; |
| 107 | 107 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 108 | 108 | const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32); |
| 109 | try atom.addReloc(elf_file, .{ | |
| 109 | try atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 110 | 110 | .r_offset = end_offset - 4, |
| 111 | 111 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 112 | 112 | .r_addend = lowered_relocs[0].off, |
| 113 | }); | |
| 113 | }, zo); | |
| 114 | 114 | }, |
| 115 | 115 | .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| { |
| 116 | 116 | const zo = elf_file.zigObjectPtr().?; |
| ... | ... | @@ -121,21 +121,21 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 121 | 121 | @intFromEnum(std.elf.R_X86_64.GOTPCREL) |
| 122 | 122 | else |
| 123 | 123 | @intFromEnum(std.elf.R_X86_64.PC32); |
| 124 | try atom.addReloc(elf_file, .{ | |
| 124 | try atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 125 | 125 | .r_offset = end_offset - 4, |
| 126 | 126 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 127 | 127 | .r_addend = lowered_relocs[0].off - 4, |
| 128 | }); | |
| 128 | }, zo); | |
| 129 | 129 | } else { |
| 130 | 130 | const r_type: u32 = if (sym.flags.is_tls) |
| 131 | 131 | @intFromEnum(std.elf.R_X86_64.TPOFF32) |
| 132 | 132 | else |
| 133 | 133 | @intFromEnum(std.elf.R_X86_64.@"32"); |
| 134 | try atom.addReloc(elf_file, .{ | |
| 134 | try atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 135 | 135 | .r_offset = end_offset - 4, |
| 136 | 136 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 137 | 137 | .r_addend = lowered_relocs[0].off, |
| 138 | }); | |
| 138 | }, zo); | |
| 139 | 139 | } |
| 140 | 140 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { |
| 141 | 141 | const zo = macho_file.getZigObject().?; |
src/link/Elf/Atom.zig+12-14| ... | ... | @@ -302,7 +302,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | // TODO create relocs free list |
| 305 | self.freeRelocs(elf_file); | |
| 305 | self.freeRelocs(zo); | |
| 306 | 306 | // TODO figure out how to free input section mappind in ZigModule |
| 307 | 307 | // const zig_object = elf_file.zigObjectPtr().? |
| 308 | 308 | // assert(zig_object.atoms.swapRemove(self.atom_index)); |
| ... | ... | @@ -377,21 +377,19 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void { |
| 377 | 377 | } |
| 378 | 378 | } |
| 379 | 379 | |
| 380 | pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void { | |
| 381 | const comp = elf_file.base.comp; | |
| 382 | const gpa = comp.gpa; | |
| 383 | const file_ptr = self.file(elf_file).?; | |
| 384 | assert(file_ptr == .zig_object); | |
| 385 | const zig_object = file_ptr.zig_object; | |
| 386 | const rels = &zig_object.relocs.items[self.relocs_section_index]; | |
| 387 | try rels.append(gpa, reloc); | |
| 380 | pub fn addReloc(self: Atom, alloc: Allocator, reloc: elf.Elf64_Rela, zo: *ZigObject) !void { | |
| 381 | const rels = &zo.relocs.items[self.relocs_section_index]; | |
| 382 | try rels.ensureUnusedCapacity(alloc, 1); | |
| 383 | self.addRelocAssumeCapacity(reloc, zo); | |
| 388 | 384 | } |
| 389 | 385 | |
| 390 | pub fn freeRelocs(self: Atom, elf_file: *Elf) void { | |
| 391 | const file_ptr = self.file(elf_file).?; | |
| 392 | assert(file_ptr == .zig_object); | |
| 393 | const zig_object = file_ptr.zig_object; | |
| 394 | zig_object.relocs.items[self.relocs_section_index].clearRetainingCapacity(); | |
| 386 | pub fn addRelocAssumeCapacity(self: Atom, reloc: elf.Elf64_Rela, zo: *ZigObject) void { | |
| 387 | const rels = &zo.relocs.items[self.relocs_section_index]; | |
| 388 | rels.appendAssumeCapacity(reloc); | |
| 389 | } | |
| 390 | ||
| 391 | pub fn freeRelocs(self: Atom, zo: *ZigObject) void { | |
| 392 | zo.relocs.items[self.relocs_section_index].clearRetainingCapacity(); | |
| 395 | 393 | } |
| 396 | 394 | |
| 397 | 395 | pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { |
src/link/Elf/ZigObject.zig+35-10| ... | ... | @@ -182,6 +182,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 182 | 182 | try dwarf.flushModule(pt); |
| 183 | 183 | try dwarf.resolveRelocs(); |
| 184 | 184 | |
| 185 | const gpa = elf_file.base.comp.gpa; | |
| 186 | ||
| 185 | 187 | // TODO invert this logic so that we manage the output section with the atom, not the |
| 186 | 188 | // other way around |
| 187 | 189 | for ([_]u32{ |
| ... | ... | @@ -206,24 +208,47 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 206 | 208 | const sym = self.symbol(sym_index); |
| 207 | 209 | const atom_ptr = self.atom(sym.ref.index).?; |
| 208 | 210 | if (!atom_ptr.alive) continue; |
| 209 | const shdr = elf_file.shdrs.items[sym.outputShndx(elf_file).?]; | |
| 211 | const shndx = sym.outputShndx(elf_file).?; | |
| 212 | const shdr = elf_file.shdrs.items[shndx]; | |
| 210 | 213 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 211 | 214 | esym.st_size = shdr.sh_size; |
| 212 | 215 | atom_ptr.size = shdr.sh_size; |
| 213 | 216 | atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); |
| 214 | 217 | |
| 215 | 218 | const relocs = &self.relocs.items[atom_ptr.relocsShndx().?]; |
| 216 | _ = relocs; | |
| 217 | 219 | for (sect.units.items) |*unit| { |
| 220 | try relocs.ensureUnusedCapacity(gpa, unit.external_relocs.items.len); | |
| 218 | 221 | for (unit.external_relocs.items) |reloc| { |
| 219 | 222 | const tsym = self.symbol(reloc.target_sym); |
| 220 | 223 | const r_offset = unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off; |
| 221 | const r_addend = reloc.target_off; | |
| 222 | std.debug.print("{s} <- r_off={x}, r_add={x}\n", .{ | |
| 224 | const r_addend: i64 = @intCast(reloc.target_off); | |
| 225 | const r_type: elf.R_X86_64 = switch (dwarf.address_size) { | |
| 226 | .@"32" => .@"32", | |
| 227 | .@"64" => .@"64", | |
| 228 | else => unreachable, | |
| 229 | }; | |
| 230 | log.debug("{s} <- r_off={x}, r_add={x}, r_type={s}\n", .{ | |
| 223 | 231 | tsym.name(elf_file), |
| 224 | 232 | r_offset, |
| 225 | 233 | r_addend, |
| 234 | @tagName(r_type), | |
| 226 | 235 | }); |
| 236 | atom_ptr.addRelocAssumeCapacity(.{ | |
| 237 | .r_offset = r_offset, | |
| 238 | .r_addend = r_addend, | |
| 239 | .r_info = (@as(u64, @intCast(reloc.target_sym)) << 32) | @intFromEnum(r_type), | |
| 240 | }, self); | |
| 241 | } | |
| 242 | } | |
| 243 | ||
| 244 | if (elf_file.base.isRelocatable() and relocs.items.len > 0) { | |
| 245 | const gop = try elf_file.output_rela_sections.getOrPut(gpa, shndx); | |
| 246 | if (!gop.found_existing) { | |
| 247 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)}); | |
| 248 | defer gpa.free(rela_sect_name); | |
| 249 | const rela_sh_name = try elf_file.insertShString(rela_sect_name); | |
| 250 | const rela_shndx = try elf_file.addRelaShdr(rela_sh_name, shndx); | |
| 251 | gop.value_ptr.* = .{ .shndx = rela_shndx }; | |
| 227 | 252 | } |
| 228 | 253 | } |
| 229 | 254 | } |
| ... | ... | @@ -698,11 +723,11 @@ pub fn getNavVAddr( |
| 698 | 723 | const vaddr = this_sym.address(.{}, elf_file); |
| 699 | 724 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; |
| 700 | 725 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 701 | try parent_atom.addReloc(elf_file, .{ | |
| 726 | try parent_atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 702 | 727 | .r_offset = reloc_info.offset, |
| 703 | 728 | .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type, |
| 704 | 729 | .r_addend = reloc_info.addend, |
| 705 | }); | |
| 730 | }, self); | |
| 706 | 731 | return @intCast(vaddr); |
| 707 | 732 | } |
| 708 | 733 | |
| ... | ... | @@ -717,11 +742,11 @@ pub fn getUavVAddr( |
| 717 | 742 | const vaddr = sym.address(.{}, elf_file); |
| 718 | 743 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?; |
| 719 | 744 | const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch); |
| 720 | try parent_atom.addReloc(elf_file, .{ | |
| 745 | try parent_atom.addReloc(elf_file.base.comp.gpa, .{ | |
| 721 | 746 | .r_offset = reloc_info.offset, |
| 722 | 747 | .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type, |
| 723 | 748 | .r_addend = reloc_info.addend, |
| 724 | }); | |
| 749 | }, self); | |
| 725 | 750 | return @intCast(vaddr); |
| 726 | 751 | } |
| 727 | 752 | |
| ... | ... | @@ -1068,7 +1093,7 @@ pub fn updateFunc( |
| 1068 | 1093 | log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav }); |
| 1069 | 1094 | |
| 1070 | 1095 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav); |
| 1071 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1096 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(self); | |
| 1072 | 1097 | |
| 1073 | 1098 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1074 | 1099 | defer code_buffer.deinit(); |
| ... | ... | @@ -1196,7 +1221,7 @@ pub fn updateNav( |
| 1196 | 1221 | |
| 1197 | 1222 | if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) { |
| 1198 | 1223 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index); |
| 1199 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | |
| 1224 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(self); | |
| 1200 | 1225 | |
| 1201 | 1226 | var code_buffer = std.ArrayList(u8).init(zcu.gpa); |
| 1202 | 1227 | defer code_buffer.deinit(); |