| author | |
| committer | |
| log | 7a9eba2f8597a94e4a6def62253e9bf5220a46af |
| tree | 67c8a855e014cae8595a05048cb18b610b66a579 |
| parent | d07edfabd6e45a486d1611e357887d01b38db32e |
7 files changed, 252 insertions(+), 44 deletions(-)
src/arch/x86_64/CodeGen.zig+19-3| ... | @@ -125,7 +125,9 @@ const Owner = union(enum) { | ... | @@ -125,7 +125,9 @@ const Owner = union(enum) { |
| 125 | .func_index => |func_index| { | 125 | .func_index => |func_index| { |
| 126 | const mod = ctx.bin_file.options.module.?; | 126 | const mod = ctx.bin_file.options.module.?; |
| 127 | const decl_index = mod.funcOwnerDeclIndex(func_index); | 127 | const decl_index = mod.funcOwnerDeclIndex(func_index); |
| 128 | if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | 128 | if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { |
| 129 | return elf_file.getOrCreateMetadataForDecl(decl_index); | ||
| 130 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | ||
| 129 | const atom = try macho_file.getOrCreateAtomForDecl(decl_index); | 131 | const atom = try macho_file.getOrCreateAtomForDecl(decl_index); |
| 130 | return macho_file.getAtom(atom).getSymbolIndex().?; | 132 | return macho_file.getAtom(atom).getSymbolIndex().?; |
| 131 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { | 133 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { |
| ... | @@ -136,7 +138,10 @@ const Owner = union(enum) { | ... | @@ -136,7 +138,10 @@ const Owner = union(enum) { |
| 136 | } else unreachable; | 138 | } else unreachable; |
| 137 | }, | 139 | }, |
| 138 | .lazy_sym => |lazy_sym| { | 140 | .lazy_sym => |lazy_sym| { |
| 139 | if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | 141 | if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { |
| 142 | return elf_file.getOrCreateMetadataForLazySymbol(lazy_sym) catch |err| | ||
| 143 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | ||
| 144 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { | ||
| 140 | const atom = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | 145 | const atom = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| |
| 141 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | 146 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 142 | return macho_file.getAtom(atom).getSymbolIndex().?; | 147 | return macho_file.getAtom(atom).getSymbolIndex().?; |
| ... | @@ -8178,7 +8183,18 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8178,7 +8183,18 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8178 | } else if (func_value.getExternFunc(mod)) |extern_func| { | 8183 | } else if (func_value.getExternFunc(mod)) |extern_func| { |
| 8179 | const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name); | 8184 | const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name); |
| 8180 | const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); | 8185 | const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); |
| 8181 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { | 8186 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 8187 | const atom_index = try self.owner.getSymbolIndex(self); | ||
| 8188 | const sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name); | ||
| 8189 | _ = try self.addInst(.{ | ||
| 8190 | .tag = .call, | ||
| 8191 | .ops = .extern_fn_reloc, | ||
| 8192 | .data = .{ .reloc = .{ | ||
| 8193 | .atom_index = atom_index, | ||
| 8194 | .sym_index = sym_index, | ||
| 8195 | } }, | ||
| 8196 | }); | ||
| 8197 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | ||
| 8182 | const atom_index = try self.owner.getSymbolIndex(self); | 8198 | const atom_index = try self.owner.getSymbolIndex(self); |
| 8183 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); | 8199 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); |
| 8184 | _ = try self.addInst(.{ | 8200 | _ = try self.addInst(.{ |
src/arch/x86_64/Emit.zig+9-1| ... | @@ -41,7 +41,15 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -41,7 +41,15 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 41 | .offset = end_offset - 4, | 41 | .offset = end_offset - 4, |
| 42 | .length = @as(u5, @intCast(end_offset - start_offset)), | 42 | .length = @as(u5, @intCast(end_offset - start_offset)), |
| 43 | }), | 43 | }), |
| 44 | .linker_extern_fn => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | 44 | .linker_extern_fn => |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| { |
| 45 | // Add relocation to the decl. | ||
| 46 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | ||
| 47 | try atom_ptr.addReloc(elf_file, .{ | ||
| 48 | .r_offset = end_offset, | ||
| 49 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | std.elf.R_X86_64_PLT32, | ||
| 50 | .r_addend = -4, | ||
| 51 | }); | ||
| 52 | } else if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | ||
| 45 | // Add relocation to the decl. | 53 | // Add relocation to the decl. |
| 46 | const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; | 54 | const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; |
| 47 | const target = macho_file.getGlobalByIndex(symbol.sym_index); | 55 | const target = macho_file.getGlobalByIndex(symbol.sym_index); |
src/link.zig+1-1| ... | @@ -549,7 +549,7 @@ pub const File = struct { | ... | @@ -549,7 +549,7 @@ pub const File = struct { |
| 549 | switch (base.tag) { | 549 | switch (base.tag) { |
| 550 | // zig fmt: off | 550 | // zig fmt: off |
| 551 | .coff => return @fieldParentPtr(Coff, "base", base).getGlobalSymbol(name, lib_name), | 551 | .coff => return @fieldParentPtr(Coff, "base", base).getGlobalSymbol(name, lib_name), |
| 552 | .elf => unreachable, | 552 | .elf => return @fieldParentPtr(Elf, "base", base).getGlobalSymbol(name, lib_name), |
| 553 | .macho => return @fieldParentPtr(MachO, "base", base).getGlobalSymbol(name, lib_name), | 553 | .macho => return @fieldParentPtr(MachO, "base", base).getGlobalSymbol(name, lib_name), |
| 554 | .plan9 => unreachable, | 554 | .plan9 => unreachable, |
| 555 | .spirv => unreachable, | 555 | .spirv => unreachable, |
src/link/Elf.zig+28-5| ... | @@ -302,9 +302,9 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. | ... | @@ -302,9 +302,9 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. |
| 302 | const vaddr = this_sym.value; | 302 | const vaddr = this_sym.value; |
| 303 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?; | 303 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?; |
| 304 | try parent_atom.addReloc(self, .{ | 304 | try parent_atom.addReloc(self, .{ |
| 305 | .target = this_sym_index, | 305 | .r_offset = reloc_info.offset, |
| 306 | .offset = reloc_info.offset, | 306 | .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | elf.R_X86_64_64, |
| 307 | .addend = reloc_info.addend, | 307 | .r_addend = reloc_info.addend, |
| 308 | }); | 308 | }); |
| 309 | 309 | ||
| 310 | return vaddr; | 310 | return vaddr; |
| ... | @@ -1020,8 +1020,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1020,8 +1020,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1020 | // Beyond this point, everything has been allocated a virtual address and we can resolve | 1020 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 1021 | // the relocations. | 1021 | // the relocations. |
| 1022 | if (self.zig_module_index) |index| { | 1022 | if (self.zig_module_index) |index| { |
| 1023 | for (self.file(index).?.zig_module.atoms.items) |atom_index| { | 1023 | for (self.file(index).?.zig_module.atoms.keys()) |atom_index| { |
| 1024 | try self.atom(atom_index).?.resolveRelocs(self); | 1024 | const atom_ptr = self.atom(atom_index).?; |
| 1025 | if (!atom_ptr.alive) continue; | ||
| 1026 | const shdr = &self.shdrs.items[atom_ptr.output_section_index]; | ||
| 1027 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; | ||
| 1028 | const code = try gpa.alloc(u8, atom_ptr.size); | ||
| 1029 | defer gpa.free(code); | ||
| 1030 | const amt = try self.base.file.?.preadAll(code, file_offset); | ||
| 1031 | if (amt != code.len) return error.InputOutput; | ||
| 1032 | try atom_ptr.resolveRelocs(self, code); | ||
| 1033 | try self.base.file.?.pwriteAll(code, file_offset); | ||
| 1025 | } | 1034 | } |
| 1026 | } | 1035 | } |
| 1027 | 1036 | ||
| ... | @@ -2185,6 +2194,7 @@ fn updateDeclCode( | ... | @@ -2185,6 +2194,7 @@ fn updateDeclCode( |
| 2185 | const shdr_index = sym.output_section_index; | 2194 | const shdr_index = sym.output_section_index; |
| 2186 | 2195 | ||
| 2187 | sym.name_offset = try self.strtab.insert(gpa, decl_name); | 2196 | sym.name_offset = try self.strtab.insert(gpa, decl_name); |
| 2197 | atom_ptr.alive = true; | ||
| 2188 | atom_ptr.name_offset = sym.name_offset; | 2198 | atom_ptr.name_offset = sym.name_offset; |
| 2189 | esym.st_name = sym.name_offset; | 2199 | esym.st_name = sym.name_offset; |
| 2190 | esym.st_info |= stt_bits; | 2200 | esym.st_info |= stt_bits; |
| ... | @@ -2440,6 +2450,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. | ... | @@ -2440,6 +2450,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 2440 | local_esym.st_info |= elf.STT_OBJECT; | 2450 | local_esym.st_info |= elf.STT_OBJECT; |
| 2441 | local_esym.st_size = code.len; | 2451 | local_esym.st_size = code.len; |
| 2442 | const atom_ptr = local_sym.atom(self).?; | 2452 | const atom_ptr = local_sym.atom(self).?; |
| 2453 | atom_ptr.alive = true; | ||
| 2443 | atom_ptr.name_offset = name_str_index; | 2454 | atom_ptr.name_offset = name_str_index; |
| 2444 | atom_ptr.alignment = math.log2_int(u64, required_alignment); | 2455 | atom_ptr.alignment = math.log2_int(u64, required_alignment); |
| 2445 | atom_ptr.size = code.len; | 2456 | atom_ptr.size = code.len; |
| ... | @@ -2515,6 +2526,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -2515,6 +2526,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2515 | local_esym.st_info |= elf.STT_OBJECT; | 2526 | local_esym.st_info |= elf.STT_OBJECT; |
| 2516 | local_esym.st_size = code.len; | 2527 | local_esym.st_size = code.len; |
| 2517 | const atom_ptr = local_sym.atom(self).?; | 2528 | const atom_ptr = local_sym.atom(self).?; |
| 2529 | atom_ptr.alive = true; | ||
| 2518 | atom_ptr.name_offset = name_str_index; | 2530 | atom_ptr.name_offset = name_str_index; |
| 2519 | atom_ptr.alignment = math.log2_int(u64, required_alignment); | 2531 | atom_ptr.alignment = math.log2_int(u64, required_alignment); |
| 2520 | atom_ptr.size = code.len; | 2532 | atom_ptr.size = code.len; |
| ... | @@ -3374,6 +3386,17 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { | ... | @@ -3374,6 +3386,17 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { |
| 3374 | return self.resolver.get(name_off); | 3386 | return self.resolver.get(name_off); |
| 3375 | } | 3387 | } |
| 3376 | 3388 | ||
| 3389 | pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { | ||
| 3390 | _ = lib_name; | ||
| 3391 | const gpa = self.base.allocator; | ||
| 3392 | const name_off = try self.strtab.insert(gpa, name); | ||
| 3393 | const gop = try self.getOrPutGlobal(name_off); | ||
| 3394 | if (!gop.found_existing) { | ||
| 3395 | try self.unresolved.putNoClobber(gpa, name_off, {}); | ||
| 3396 | } | ||
| 3397 | return gop.index; | ||
| 3398 | } | ||
| 3399 | |||
| 3377 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { | 3400 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 3378 | return .{ .data = self }; | 3401 | return .{ .data = self }; |
| 3379 | } | 3402 | } |
src/link/Elf/Atom.zig+170-22| ... | @@ -26,7 +26,7 @@ relocs_section_index: Index = 0, | ... | @@ -26,7 +26,7 @@ relocs_section_index: Index = 0, |
| 26 | atom_index: Index = 0, | 26 | atom_index: Index = 0, |
| 27 | 27 | ||
| 28 | /// Specifies whether this atom is alive or has been garbage collected. | 28 | /// Specifies whether this atom is alive or has been garbage collected. |
| 29 | alive: bool = true, | 29 | alive: bool = false, |
| 30 | 30 | ||
| 31 | /// Specifies if the atom has been visited during garbage collection. | 31 | /// Specifies if the atom has been visited during garbage collection. |
| 32 | visited: bool = false, | 32 | visited: bool = false, |
| ... | @@ -192,6 +192,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { | ... | @@ -192,6 +192,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 192 | log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); | 192 | log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); |
| 193 | 193 | ||
| 194 | const gpa = elf_file.base.allocator; | 194 | const gpa = elf_file.base.allocator; |
| 195 | const zig_module = elf_file.file(self.file_index).?.zig_module; | ||
| 195 | const shndx = self.output_section_index; | 196 | const shndx = self.output_section_index; |
| 196 | const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; | 197 | const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; |
| 197 | const free_list = &meta.free_list; | 198 | const free_list = &meta.free_list; |
| ... | @@ -242,17 +243,18 @@ pub fn free(self: *Atom, elf_file: *Elf) void { | ... | @@ -242,17 +243,18 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 242 | 243 | ||
| 243 | // TODO create relocs free list | 244 | // TODO create relocs free list |
| 244 | self.freeRelocs(elf_file); | 245 | self.freeRelocs(elf_file); |
| 246 | assert(zig_module.atoms.swapRemove(self.atom_index)); | ||
| 245 | self.* = .{}; | 247 | self.* = .{}; |
| 246 | } | 248 | } |
| 247 | 249 | ||
| 248 | pub fn relocs(self: Atom, elf_file: *Elf) []const Relocation { | 250 | pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela { |
| 249 | const file_ptr = elf_file.file(self.file_index).?; | 251 | const file_ptr = elf_file.file(self.file_index).?; |
| 250 | if (file_ptr != .zig_module) @panic("TODO"); | 252 | if (file_ptr != .zig_module) @panic("TODO"); |
| 251 | const zig_module = file_ptr.zig_module; | 253 | const zig_module = file_ptr.zig_module; |
| 252 | return zig_module.relocs.items[self.relocs_section_index].items; | 254 | return zig_module.relocs.items[self.relocs_section_index].items; |
| 253 | } | 255 | } |
| 254 | 256 | ||
| 255 | pub fn addReloc(self: Atom, elf_file: *Elf, reloc: Relocation) !void { | 257 | pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void { |
| 256 | const gpa = elf_file.base.allocator; | 258 | const gpa = elf_file.base.allocator; |
| 257 | const file_ptr = elf_file.file(self.file_index).?; | 259 | const file_ptr = elf_file.file(self.file_index).?; |
| 258 | assert(file_ptr == .zig_module); | 260 | assert(file_ptr == .zig_module); |
| ... | @@ -269,31 +271,178 @@ pub fn freeRelocs(self: Atom, elf_file: *Elf) void { | ... | @@ -269,31 +271,178 @@ pub fn freeRelocs(self: Atom, elf_file: *Elf) void { |
| 269 | } | 271 | } |
| 270 | 272 | ||
| 271 | /// TODO mark relocs dirty | 273 | /// TODO mark relocs dirty |
| 272 | pub fn resolveRelocs(self: Atom, elf_file: *Elf) !void { | 274 | pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 273 | relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) }); | 275 | relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) }); |
| 274 | const shdr = &elf_file.shdrs.items[self.output_section_index]; | 276 | |
| 275 | for (self.relocs(elf_file)) |reloc| { | 277 | var stream = std.io.fixedBufferStream(code); |
| 276 | const target_sym = elf_file.symbol(reloc.target); | 278 | const cwriter = stream.writer(); |
| 277 | const target_vaddr = target_sym.value + reloc.addend; | 279 | |
| 278 | const section_offset = (self.value + reloc.offset) - shdr.sh_addr; | 280 | for (self.relocs(elf_file)) |rel| { |
| 279 | const file_offset = shdr.sh_offset + section_offset; | 281 | const r_type = rel.r_type(); |
| 280 | 282 | if (r_type == elf.R_X86_64_NONE) continue; | |
| 281 | relocs_log.debug(" ({x}: [() => 0x{x}] ({s}))", .{ | 283 | |
| 282 | reloc.offset, | 284 | const target = elf_file.symbol(rel.r_sym()); |
| 283 | target_vaddr, | 285 | |
| 284 | target_sym.name(elf_file), | 286 | // We will use equation format to resolve relocations: |
| 287 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ | ||
| 288 | // | ||
| 289 | // Address of the source atom. | ||
| 290 | const P = @as(i64, @intCast(self.value + rel.r_offset)); | ||
| 291 | // Addend from the relocation. | ||
| 292 | const A = rel.r_addend; | ||
| 293 | // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. | ||
| 294 | const S = @as(i64, @intCast(target.address(.{}, elf_file))); | ||
| 295 | // Address of the global offset table. | ||
| 296 | const GOT = blk: { | ||
| 297 | const shndx = if (elf_file.got_plt_section_index) |shndx| | ||
| 298 | shndx | ||
| 299 | else if (elf_file.got_section_index) |shndx| | ||
| 300 | shndx | ||
| 301 | else | ||
| 302 | null; | ||
| 303 | break :blk if (shndx) |index| @as(i64, @intCast(elf_file.shdrs.items[index].sh_addr)) else 0; | ||
| 304 | }; | ||
| 305 | // Relative offset to the start of the global offset table. | ||
| 306 | const G = @as(i64, @intCast(target.gotAddress(elf_file))) - GOT; | ||
| 307 | // // Address of the thread pointer. | ||
| 308 | // const TP = @as(i64, @intCast(elf_file.getTpAddress())); | ||
| 309 | // // Address of the dynamic thread pointer. | ||
| 310 | // const DTP = @as(i64, @intCast(elf_file.getDtpAddress())); | ||
| 311 | |||
| 312 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ({s})", .{ | ||
| 313 | fmtRelocType(r_type), | ||
| 314 | rel.r_offset, | ||
| 315 | P, | ||
| 316 | S + A, | ||
| 317 | G + GOT + A, | ||
| 318 | target.name(elf_file), | ||
| 285 | }); | 319 | }); |
| 286 | 320 | ||
| 287 | switch (elf_file.ptr_width) { | 321 | try stream.seekTo(rel.r_offset); |
| 288 | .p32 => try elf_file.base.file.?.pwriteAll( | 322 | |
| 289 | std.mem.asBytes(&@as(u32, @intCast(target_vaddr))), | 323 | switch (rel.r_type()) { |
| 290 | file_offset, | 324 | elf.R_X86_64_NONE => unreachable, |
| 291 | ), | 325 | elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A), |
| 292 | .p64 => try elf_file.base.file.?.pwriteAll(std.mem.asBytes(&target_vaddr), file_offset), | 326 | elf.R_X86_64_PLT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))), |
| 327 | else => @panic("TODO"), | ||
| 293 | } | 328 | } |
| 294 | } | 329 | } |
| 295 | } | 330 | } |
| 296 | 331 | ||
| 332 | pub fn fmtRelocType(r_type: u32) std.fmt.Formatter(formatRelocType) { | ||
| 333 | return .{ .data = r_type }; | ||
| 334 | } | ||
| 335 | |||
| 336 | fn formatRelocType( | ||
| 337 | r_type: u32, | ||
| 338 | comptime unused_fmt_string: []const u8, | ||
| 339 | options: std.fmt.FormatOptions, | ||
| 340 | writer: anytype, | ||
| 341 | ) !void { | ||
| 342 | _ = unused_fmt_string; | ||
| 343 | _ = options; | ||
| 344 | const str = switch (r_type) { | ||
| 345 | elf.R_X86_64_NONE => "R_X86_64_NONE", | ||
| 346 | elf.R_X86_64_64 => "R_X86_64_64", | ||
| 347 | elf.R_X86_64_PC32 => "R_X86_64_PC32", | ||
| 348 | elf.R_X86_64_GOT32 => "R_X86_64_GOT32", | ||
| 349 | elf.R_X86_64_PLT32 => "R_X86_64_PLT32", | ||
| 350 | elf.R_X86_64_COPY => "R_X86_64_COPY", | ||
| 351 | elf.R_X86_64_GLOB_DAT => "R_X86_64_GLOB_DAT", | ||
| 352 | elf.R_X86_64_JUMP_SLOT => "R_X86_64_JUMP_SLOT", | ||
| 353 | elf.R_X86_64_RELATIVE => "R_X86_64_RELATIVE", | ||
| 354 | elf.R_X86_64_GOTPCREL => "R_X86_64_GOTPCREL", | ||
| 355 | elf.R_X86_64_32 => "R_X86_64_32", | ||
| 356 | elf.R_X86_64_32S => "R_X86_64_32S", | ||
| 357 | elf.R_X86_64_16 => "R_X86_64_16", | ||
| 358 | elf.R_X86_64_PC16 => "R_X86_64_PC16", | ||
| 359 | elf.R_X86_64_8 => "R_X86_64_8", | ||
| 360 | elf.R_X86_64_PC8 => "R_X86_64_PC8", | ||
| 361 | elf.R_X86_64_DTPMOD64 => "R_X86_64_DTPMOD64", | ||
| 362 | elf.R_X86_64_DTPOFF64 => "R_X86_64_DTPOFF64", | ||
| 363 | elf.R_X86_64_TPOFF64 => "R_X86_64_TPOFF64", | ||
| 364 | elf.R_X86_64_TLSGD => "R_X86_64_TLSGD", | ||
| 365 | elf.R_X86_64_TLSLD => "R_X86_64_TLSLD", | ||
| 366 | elf.R_X86_64_DTPOFF32 => "R_X86_64_DTPOFF32", | ||
| 367 | elf.R_X86_64_GOTTPOFF => "R_X86_64_GOTTPOFF", | ||
| 368 | elf.R_X86_64_TPOFF32 => "R_X86_64_TPOFF32", | ||
| 369 | elf.R_X86_64_PC64 => "R_X86_64_PC64", | ||
| 370 | elf.R_X86_64_GOTOFF64 => "R_X86_64_GOTOFF64", | ||
| 371 | elf.R_X86_64_GOTPC32 => "R_X86_64_GOTPC32", | ||
| 372 | elf.R_X86_64_GOT64 => "R_X86_64_GOT64", | ||
| 373 | elf.R_X86_64_GOTPCREL64 => "R_X86_64_GOTPCREL64", | ||
| 374 | elf.R_X86_64_GOTPC64 => "R_X86_64_GOTPC64", | ||
| 375 | elf.R_X86_64_GOTPLT64 => "R_X86_64_GOTPLT64", | ||
| 376 | elf.R_X86_64_PLTOFF64 => "R_X86_64_PLTOFF64", | ||
| 377 | elf.R_X86_64_SIZE32 => "R_X86_64_SIZE32", | ||
| 378 | elf.R_X86_64_SIZE64 => "R_X86_64_SIZE64", | ||
| 379 | elf.R_X86_64_GOTPC32_TLSDESC => "R_X86_64_GOTPC32_TLSDESC", | ||
| 380 | elf.R_X86_64_TLSDESC_CALL => "R_X86_64_TLSDESC_CALL", | ||
| 381 | elf.R_X86_64_TLSDESC => "R_X86_64_TLSDESC", | ||
| 382 | elf.R_X86_64_IRELATIVE => "R_X86_64_IRELATIVE", | ||
| 383 | elf.R_X86_64_RELATIVE64 => "R_X86_64_RELATIVE64", | ||
| 384 | elf.R_X86_64_GOTPCRELX => "R_X86_64_GOTPCRELX", | ||
| 385 | elf.R_X86_64_REX_GOTPCRELX => "R_X86_64_REX_GOTPCRELX", | ||
| 386 | elf.R_X86_64_NUM => "R_X86_64_NUM", | ||
| 387 | else => "R_X86_64_UNKNOWN", | ||
| 388 | }; | ||
| 389 | try writer.print("{s}", .{str}); | ||
| 390 | } | ||
| 391 | |||
| 392 | pub fn format( | ||
| 393 | atom: Atom, | ||
| 394 | comptime unused_fmt_string: []const u8, | ||
| 395 | options: std.fmt.FormatOptions, | ||
| 396 | writer: anytype, | ||
| 397 | ) !void { | ||
| 398 | _ = atom; | ||
| 399 | _ = unused_fmt_string; | ||
| 400 | _ = options; | ||
| 401 | _ = writer; | ||
| 402 | @compileError("do not format symbols directly"); | ||
| 403 | } | ||
| 404 | |||
| 405 | pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(format2) { | ||
| 406 | return .{ .data = .{ | ||
| 407 | .atom = atom, | ||
| 408 | .elf_file = elf_file, | ||
| 409 | } }; | ||
| 410 | } | ||
| 411 | |||
| 412 | const FormatContext = struct { | ||
| 413 | atom: Atom, | ||
| 414 | elf_file: *Elf, | ||
| 415 | }; | ||
| 416 | |||
| 417 | fn format2( | ||
| 418 | ctx: FormatContext, | ||
| 419 | comptime unused_fmt_string: []const u8, | ||
| 420 | options: std.fmt.FormatOptions, | ||
| 421 | writer: anytype, | ||
| 422 | ) !void { | ||
| 423 | _ = options; | ||
| 424 | _ = unused_fmt_string; | ||
| 425 | const atom = ctx.atom; | ||
| 426 | const elf_file = ctx.elf_file; | ||
| 427 | try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x})", .{ | ||
| 428 | atom.atom_index, atom.name(elf_file), atom.value, | ||
| 429 | atom.output_section_index, atom.alignment, atom.size, | ||
| 430 | }); | ||
| 431 | // if (atom.fde_start != atom.fde_end) { | ||
| 432 | // try writer.writeAll(" : fdes{ "); | ||
| 433 | // for (atom.getFdes(elf_file), atom.fde_start..) |fde, i| { | ||
| 434 | // try writer.print("{d}", .{i}); | ||
| 435 | // if (!fde.alive) try writer.writeAll("([*])"); | ||
| 436 | // if (i < atom.fde_end - 1) try writer.writeAll(", "); | ||
| 437 | // } | ||
| 438 | // try writer.writeAll(" }"); | ||
| 439 | // } | ||
| 440 | const gc_sections = if (elf_file.base.options.gc_sections) |gc_sections| gc_sections else false; | ||
| 441 | if (gc_sections and !atom.alive) { | ||
| 442 | try writer.writeAll(" : [*]"); | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 297 | pub const Index = u32; | 446 | pub const Index = u32; |
| 298 | 447 | ||
| 299 | const std = @import("std"); | 448 | const std = @import("std"); |
| ... | @@ -306,4 +455,3 @@ const Allocator = std.mem.Allocator; | ... | @@ -306,4 +455,3 @@ const Allocator = std.mem.Allocator; |
| 306 | const Atom = @This(); | 455 | const Atom = @This(); |
| 307 | const Elf = @import("../Elf.zig"); | 456 | const Elf = @import("../Elf.zig"); |
| 308 | const File = @import("file.zig").File; | 457 | const File = @import("file.zig").File; |
| 309 | const Relocation = @import("Relocation.zig"); |
src/link/Elf/Relocation.zig deleted-8| ... | @@ -1,8 +0,0 @@ | ||
| 1 | target: Symbol.Index, | ||
| 2 | offset: u64, | ||
| 3 | addend: u32, | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | |||
| 7 | const Symbol = @import("Symbol.zig"); | ||
| 8 | const Relocation = @This(); | ||
src/link/Elf/ZigModule.zig+25-4| ... | @@ -8,8 +8,8 @@ local_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, | ... | @@ -8,8 +8,8 @@ local_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, |
| 8 | elf_global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | 8 | elf_global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 9 | global_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, | 9 | global_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, |
| 10 | 10 | ||
| 11 | atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, | 11 | atoms: std.AutoArrayHashMapUnmanaged(Atom.Index, void) = .{}, |
| 12 | relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)) = .{}, | 12 | relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{}, |
| 13 | 13 | ||
| 14 | alive: bool = true, | 14 | alive: bool = true, |
| 15 | 15 | ||
| ... | @@ -43,7 +43,7 @@ pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) ! | ... | @@ -43,7 +43,7 @@ pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) ! |
| 43 | const relocs = try self.relocs.addOne(gpa); | 43 | const relocs = try self.relocs.addOne(gpa); |
| 44 | relocs.* = .{}; | 44 | relocs.* = .{}; |
| 45 | atom_ptr.relocs_section_index = relocs_index; | 45 | atom_ptr.relocs_section_index = relocs_index; |
| 46 | try self.atoms.append(gpa, atom_index); | 46 | try self.atoms.putNoClobber(gpa, atom_index, {}); |
| 47 | return symbol_index; | 47 | return symbol_index; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| ... | @@ -184,6 +184,28 @@ fn formatSymtab( | ... | @@ -184,6 +184,28 @@ fn formatSymtab( |
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | pub fn fmtAtoms(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatAtoms) { | ||
| 188 | return .{ .data = .{ | ||
| 189 | .self = self, | ||
| 190 | .elf_file = elf_file, | ||
| 191 | } }; | ||
| 192 | } | ||
| 193 | |||
| 194 | fn formatAtoms( | ||
| 195 | ctx: FormatContext, | ||
| 196 | comptime unused_fmt_string: []const u8, | ||
| 197 | options: std.fmt.FormatOptions, | ||
| 198 | writer: anytype, | ||
| 199 | ) !void { | ||
| 200 | _ = unused_fmt_string; | ||
| 201 | _ = options; | ||
| 202 | try writer.writeAll(" atoms\n"); | ||
| 203 | for (ctx.self.atoms.keys()) |atom_index| { | ||
| 204 | const atom = ctx.elf_file.atom(atom_index) orelse continue; | ||
| 205 | try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)}); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 187 | const assert = std.debug.assert; | 209 | const assert = std.debug.assert; |
| 188 | const std = @import("std"); | 210 | const std = @import("std"); |
| 189 | const elf = std.elf; | 211 | const elf = std.elf; |
| ... | @@ -193,6 +215,5 @@ const Atom = @import("Atom.zig"); | ... | @@ -193,6 +215,5 @@ const Atom = @import("Atom.zig"); |
| 193 | const Elf = @import("../Elf.zig"); | 215 | const Elf = @import("../Elf.zig"); |
| 194 | const File = @import("file.zig").File; | 216 | const File = @import("file.zig").File; |
| 195 | const Module = @import("../../Module.zig"); | 217 | const Module = @import("../../Module.zig"); |
| 196 | const Relocation = @import("Relocation.zig"); | ||
| 197 | const Symbol = @import("Symbol.zig"); | 218 | const Symbol = @import("Symbol.zig"); |
| 198 | const ZigModule = @This(); | 219 | const ZigModule = @This(); |