diff options
| -rw-r--r-- | lib/std/elf.zig | 46 | ||||
| -rw-r--r-- | src/Compilation.zig | 2 | ||||
| -rw-r--r-- | src/codegen/x86_64/Emit.zig | 12 | ||||
| -rw-r--r-- | src/link/Elf2.zig | 422 | ||||
| -rw-r--r-- | src/link/MappedFile.zig | 6 |
5 files changed, 289 insertions, 199 deletions
diff --git a/lib/std/elf.zig b/lib/std/elf.zig index c5f8a7ea80..2f00cef22c 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -943,11 +943,30 @@ pub const Elf32 = struct { unused: u5 = 0, }; }; + pub const Rel = extern struct { + offset: Elf32.Addr, + info: Info, + addend: u0 = 0, + + pub const Info = packed struct(u32) { + type: u8, + sym: u24, + }; + }; + pub const Rela = extern struct { + offset: Elf32.Addr, + info: Info, + addend: i32, + + pub const Info = Elf32.Rel.Info; + }; comptime { assert(@sizeOf(Elf32.Ehdr) == 52); assert(@sizeOf(Elf32.Phdr) == 32); assert(@sizeOf(Elf32.Shdr) == 40); assert(@sizeOf(Elf32.Sym) == 16); + assert(@sizeOf(Elf32.Rel) == 8); + assert(@sizeOf(Elf32.Rela) == 12); } }; pub const Elf64 = struct { @@ -1008,11 +1027,30 @@ pub const Elf64 = struct { pub const Info = Elf32.Sym.Info; pub const Other = Elf32.Sym.Other; }; + pub const Rel = extern struct { + offset: Elf64.Addr, + info: Info, + addend: u0 = 0, + + pub const Info = packed struct(u64) { + type: u32, + sym: u32, + }; + }; + pub const Rela = extern struct { + offset: Elf64.Addr, + info: Info, + addend: i64, + + pub const Info = Elf64.Rel.Info; + }; comptime { assert(@sizeOf(Elf64.Ehdr) == 64); assert(@sizeOf(Elf64.Phdr) == 56); assert(@sizeOf(Elf64.Shdr) == 64); assert(@sizeOf(Elf64.Sym) == 24); + assert(@sizeOf(Elf64.Rel) == 16); + assert(@sizeOf(Elf64.Rela) == 24); } }; pub const ElfN = switch (@sizeOf(usize)) { @@ -1428,6 +1466,14 @@ pub const CLASS = enum(u8) { _, pub const NUM = @typeInfo(CLASS).@"enum".fields.len; + + pub fn ElfN(comptime class: CLASS) type { + return switch (class) { + .NONE, _ => comptime unreachable, + .@"32" => Elf32, + .@"64" => Elf64, + }; + } }; /// Deprecated, use `@intFromEnum(std.elf.DATA.NONE)` diff --git a/src/Compilation.zig b/src/Compilation.zig index 99d4d80b92..488f7db675 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1989,7 +1989,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, break :s if (is_exe_or_dyn_lib and build_options.have_llvm) .dyn_lib else .zcu; }, } - if (options.config.use_new_linker) break :s .zcu; + if (options.config.use_new_linker) break :s .obj; } if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm if (is_exe_or_dyn_lib) break :s .lib; diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig index 3f4ef1b999..0aac146bc0 100644 --- a/src/codegen/x86_64/Emit.zig +++ b/src/codegen/x86_64/Emit.zig @@ -217,9 +217,7 @@ pub fn emitMir(emit: *Emit) Error!void { }, emit.lower.target), reloc_info), .mov => try emit.encodeInst(try .new(.none, .mov, &.{ lowered_inst.ops[0], - .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ - .base = .{ .reg = .ds }, - }) }, + .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{}) }, }, emit.lower.target), reloc_info), else => unreachable, } else if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) { @@ -720,7 +718,7 @@ pub fn emitMir(emit: *Emit) Error!void { for (emit.table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{ .r_offset = table_reloc.source_offset, - .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32"), + .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32S"), .r_addend = @as(i64, table_offset) + table_reloc.target_offset, }, zo); for (emit.lower.mir.table) |entry| { @@ -738,7 +736,7 @@ pub fn emitMir(emit: *Emit) Error!void { table_reloc.source_offset, @enumFromInt(emit.atom_index), @as(i64, table_offset) + table_reloc.target_offset, - .{ .X86_64 = .@"32" }, + .{ .X86_64 = .@"32S" }, ); for (emit.lower.mir.table) |entry| { try elf.addReloc( @@ -824,7 +822,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI const zo = elf_file.zigObjectPtr().?; const atom = zo.symbol(emit.atom_index).atom(elf_file).?; const r_type: std.elf.R_X86_64 = if (!emit.pic) - .@"32" + .@"32S" else if (reloc.target.is_extern and !reloc.target.force_pcrel_direct) .GOTPCREL else @@ -855,7 +853,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI end_offset - 4, @enumFromInt(reloc.target.index), reloc.off, - .{ .X86_64 = .@"32" }, + .{ .X86_64 = .@"32S" }, ) else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc( @enumFromInt(emit.atom_index), end_offset - 4, diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index b7a27f1dcd..162fe99796 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -12,10 +12,8 @@ inputs: std.ArrayList(struct { }), input_sections: std.ArrayList(struct { ii: Node.InputIndex, - ni: MappedFile.Node.Index, - addr: u64, - offset: u64, - size: u64, + si: Symbol.Index, + file_location: MappedFile.Node.FileLocation, }), input_section_pending_index: u32, globals: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index), @@ -59,7 +57,7 @@ pub const Node = union(enum) { return elf.inputs.items[@intFromEnum(ii)].si; } - pub fn nextSymbol(ii: InputIndex, elf: *const Elf) Symbol.Index { + pub fn endSymbol(ii: InputIndex, elf: *const Elf) Symbol.Index { const next_ii = @intFromEnum(ii) + 1; return if (next_ii < elf.inputs.items.len) @as(InputIndex, @enumFromInt(next_ii)).symbol(elf) @@ -75,17 +73,12 @@ pub const Node = union(enum) { return elf.input_sections.items[@intFromEnum(isi)].ii; } - pub fn node(isi: InputSectionIndex, elf: *const Elf) MappedFile.Node.Index { - return elf.input_sections.items[@intFromEnum(isi)].ni; + pub fn symbol(isi: InputSectionIndex, elf: *const Elf) Symbol.Index { + return elf.input_sections.items[@intFromEnum(isi)].si; } - pub fn addr(isi: InputSectionIndex, elf: *Elf) *u64 { - return &elf.input_sections.items[@intFromEnum(isi)].addr; - } - - pub fn fileLocation(isi: InputSectionIndex, elf: *const Elf) struct { u64, u64 } { - const input_section = &elf.input_sections.items[@intFromEnum(isi)]; - return .{ input_section.offset, input_section.size }; + pub fn fileLocation(isi: InputSectionIndex, elf: *const Elf) MappedFile.Node.FileLocation { + return elf.input_sections.items[@intFromEnum(isi)].file_location; } }; @@ -302,9 +295,12 @@ pub const Symbol = struct { } pub fn applyLocationRelocs(si: Symbol.Index, elf: *Elf) void { - for (elf.relocs.items[@intFromEnum(si.get(elf).loc_relocs)..]) |*reloc| { - if (reloc.loc != si) break; - reloc.apply(elf); + switch (si.get(elf).loc_relocs) { + .none => {}, + else => |loc_relocs| for (elf.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| { + if (reloc.loc != si) break; + reloc.apply(elf); + }, } } @@ -390,7 +386,7 @@ pub const Reloc = extern struct { target_value, target_endian, ), - .PC32 => std.mem.writeInt( + .PC32, .PLT32 => std.mem.writeInt( i32, loc_slice[0..4], @intCast(@as(i64, @bitCast(target_value -% loc_value))), @@ -402,6 +398,12 @@ pub const Reloc = extern struct { @intCast(target_value), target_endian, ), + .@"32S" => std.mem.writeInt( + i32, + loc_slice[0..4], + @intCast(@as(i64, @bitCast(target_value))), + target_endian, + ), .TPOFF32 => { const phdr = @field(elf.phdrSlice(), @tagName(class)); const ph = &phdr[elf.getNode(elf.known.tls).segment]; @@ -632,12 +634,7 @@ fn initHeaders( switch (class) { .NONE, _ => unreachable, inline else => |ct_class| { - const ElfN = switch (ct_class) { - .NONE, _ => comptime unreachable, - .@"32" => std.elf.Elf32, - .@"64" => std.elf.Elf64, - }; - + const ElfN = ct_class.ElfN(); assert(Node.Known.ehdr == try elf.mf.addOnlyChildNode(gpa, Node.Known.rodata, .{ .size = @sizeOf(ElfN.Ehdr), .alignment = addr_align, @@ -717,11 +714,7 @@ fn initHeaders( switch (class) { .NONE, _ => unreachable, inline else => |ct_class| { - const ElfN = switch (ct_class) { - .NONE, _ => comptime unreachable, - .@"32" => std.elf.Elf32, - .@"64" => std.elf.Elf64, - }; + const ElfN = ct_class.ElfN(); const target_endian = elf.targetEndian(); const phdr: []ElfN.Phdr = @ptrCast(@alignCast(Node.Known.phdr.slice(&elf.mf))); @@ -1293,23 +1286,32 @@ pub fn loadInput(elf: *Elf, input: link.Input) !void { switch (elf.identClass()) { .NONE, _ => unreachable, inline else => |class| { - const ehdr = try r.peekStruct( - @typeInfo(@FieldType(EhdrPtr, @tagName(class))).pointer.child, - target_endian, - ); + const ElfN = class.ElfN(); + const ehdr = try r.peekStruct(ElfN.Ehdr, target_endian); if (ehdr.type != .REL) return diags.failParse(object.path, "unsupported object type", .{}); if (ehdr.machine != elf.ehdrField(.machine)) return diags.failParse(object.path, "wrong machine", .{}); if (ehdr.shoff == 0 or ehdr.shnum <= 1) return; - if (ehdr.shstrndx == std.elf.SHN_UNDEF or ehdr.shstrndx >= ehdr.shnum) - return diags.failParse(object.path, "missing section names", .{}); - const Shdr = @typeInfo(@FieldType(ShdrSlice, @tagName(class))).pointer.child; - if (ehdr.shentsize < @sizeOf(Shdr)) + if (ehdr.shentsize < @sizeOf(ElfN.Shdr)) return diags.failParse(object.path, "unsupported shentsize", .{}); + const sections = try gpa.alloc(struct { + shdr: ElfN.Shdr, + si: Symbol.Index, + }, ehdr.shnum); + defer gpa.free(sections); + try fr.seekTo(ehdr.shoff); + for (sections) |*section| { + section.* = .{ + .shdr = try r.peekStruct(ElfN.Shdr, target_endian), + .si = .null, + }; + try fr.seekBy(ehdr.shentsize); + } const shstrtab = shstrtab: { - try fr.seekTo(ehdr.shoff + ehdr.shentsize * ehdr.shstrndx); - const shdr = try r.peekStruct(Shdr, target_endian); + if (ehdr.shstrndx == std.elf.SHN_UNDEF or ehdr.shstrndx >= ehdr.shnum) + return diags.failParse(object.path, "missing section names", .{}); + const shdr = §ions[ehdr.shstrndx].shdr; if (shdr.type != std.elf.SHT_STRTAB) return diags.failParse(object.path, "invalid shstrtab type", .{}); const shstrtab = try gpa.alloc(u8, @intCast(shdr.size)); @@ -1319,141 +1321,186 @@ pub fn loadInput(elf: *Elf, input: link.Input) !void { break :shstrtab shstrtab; }; defer gpa.free(shstrtab); - const Sym = @typeInfo(@FieldType(SymPtr, @tagName(class))).pointer.child; - try fr.seekTo(ehdr.shoff + ehdr.shentsize); - var symtab_shdr: Shdr = .{ - .name = 0, - .type = 0, - .flags = .{ .shf = .{} }, - .addr = 0, - .offset = 0, - .size = 0, - .link = 0, - .info = 0, - .addralign = 0, - .entsize = 0, - }; - const sections = try gpa.alloc(struct { - shndx: u32, - ni: MappedFile.Node.Index, - }, ehdr.shnum); - defer gpa.free(sections); - @memset(sections, .{ .shndx = std.elf.SHN_UNDEF, .ni = .none }); - for (sections[1..ehdr.shnum]) |*section| { - const shdr = try r.peekStruct(Shdr, target_endian); - try r.discardAll(ehdr.shentsize); - switch (shdr.type) { - else => continue, - std.elf.SHT_PROGBITS => {}, - std.elf.SHT_SYMTAB => { - if (symtab_shdr.entsize > 0) - return diags.failParse(object.path, "too many symtabs", .{}); - if (shdr.entsize < @sizeOf(Sym)) - return diags.failParse(object.path, "unsupported entsize", .{}); - symtab_shdr = shdr; - continue; - }, - std.elf.SHT_NOBITS => {}, - } - if (shdr.name >= shstrtab.len) continue; - const name = std.mem.sliceTo(shstrtab[shdr.name..], 0); - const si = namedSection(name) orelse continue; - section.shndx = elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx); - try elf.nodes.ensureUnusedCapacity(gpa, 1); - try elf.input_sections.ensureUnusedCapacity(gpa, 1); - section.ni = try elf.mf.addLastChildNode(gpa, si.node(elf), .{ - .size = shdr.size, - .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( - usize, - @intCast(@max(shdr.addralign, 1)), - )), - .moved = true, - }); - elf.nodes.appendAssumeCapacity(.{ - .input_section = @enumFromInt(elf.input_sections.items.len), - }); - elf.input_sections.addOneAssumeCapacity().* = .{ - .ii = ii, - .ni = section.ni, - .addr = shdr.addr, - .offset = shdr.offset, - .size = shdr.size, - }; - elf.synth_prog_node.increaseEstimatedTotalItems(1); - } - if (symtab_shdr.info <= 1) return; - const strtab = strtab: { - try fr.seekTo(ehdr.shoff + ehdr.shentsize * symtab_shdr.link); - const shdr = try r.peekStruct(Shdr, target_endian); - if (shdr.type != std.elf.SHT_STRTAB) - return diags.failParse(object.path, "invalid strtab type", .{}); - const strtab = try gpa.alloc(u8, @intCast(shdr.size)); - errdefer gpa.free(strtab); - try fr.seekTo(shdr.offset); - try r.readSliceAll(strtab); - break :strtab strtab; + try elf.nodes.ensureUnusedCapacity(gpa, ehdr.shnum - 1); + try elf.symtab.ensureUnusedCapacity(gpa, ehdr.shnum - 1); + try elf.input_sections.ensureUnusedCapacity(gpa, ehdr.shnum - 1); + for (sections[1..]) |*section| switch (section.shdr.type) { + else => {}, + std.elf.SHT_PROGBITS, std.elf.SHT_NOBITS => { + if (section.shdr.name >= shstrtab.len) continue; + const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); + const parent_si = namedSection(name) orelse continue; + const ni = try elf.mf.addLastChildNode(gpa, parent_si.node(elf), .{ + .size = section.shdr.size, + .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( + usize, + @intCast(@max(section.shdr.addralign, 1)), + )), + .moved = true, + }); + elf.nodes.appendAssumeCapacity(.{ + .input_section = @enumFromInt(elf.input_sections.items.len), + }); + section.si = try elf.initSymbolAssumeCapacity(.{ + .type = .SECTION, + .shndx = elf.targetLoad(&@field(elf.symPtr(parent_si), @tagName(class)).shndx), + }); + section.si.get(elf).ni = ni; + elf.input_sections.addOneAssumeCapacity().* = .{ + .ii = ii, + .si = section.si, + .file_location = .{ + .offset = section.shdr.offset, + .size = section.shdr.size, + }, + }; + elf.synth_prog_node.increaseEstimatedTotalItems(1); + }, }; - defer gpa.free(strtab); - try elf.symtab.ensureUnusedCapacity(gpa, symtab_shdr.info); - try elf.globals.ensureUnusedCapacity(gpa, symtab_shdr.info); - try fr.seekTo(symtab_shdr.offset + symtab_shdr.entsize); - for (1..try std.math.divExact( - usize, - @intCast(symtab_shdr.size), - @intCast(symtab_shdr.entsize), - )) |_| { - const input_sym = try r.peekStruct(Sym, target_endian); - try r.discardAll64(symtab_shdr.entsize); - switch (input_sym.info.type) { - else => continue, - .OBJECT, .FUNC => {}, - } - if (input_sym.name >= strtab.len or input_sym.shndx >= sections.len) continue; - const name = std.mem.sliceTo(strtab[input_sym.name..], 0); - const si = try elf.initSymbolAssumeCapacity(.{ - .name = name, - .value = input_sym.value, - .size = input_sym.size, - .type = input_sym.info.type, - .bind = input_sym.info.bind, - .visibility = input_sym.other.visibility, - .shndx = @intCast(sections[input_sym.shndx].shndx), - }); - { - const sym = si.get(elf); - sym.ni = sections[input_sym.shndx].ni; - assert(sym.loc_relocs == .none); - sym.loc_relocs = @enumFromInt(elf.relocs.items.len); - } - switch (input_sym.info.bind) { - else => {}, - .GLOBAL => { - const gop = elf.globals.getOrPutAssumeCapacity(elf.targetLoad( - &@field(elf.symPtr(si), @tagName(class)).name, - )); - if (gop.found_existing) switch (elf.targetLoad( - switch (elf.symPtr(gop.value_ptr.*)) { - inline else => |sym| &sym.info, + var symmap: std.ArrayList(Symbol.Index) = .empty; + defer symmap.deinit(gpa); + for (sections[1..], 1..) |*symtab, symtab_shndx| switch (symtab.shdr.type) { + else => {}, + std.elf.SHT_SYMTAB => { + if (symtab.shdr.entsize < @sizeOf(ElfN.Sym)) + return diags.failParse(object.path, "unsupported symtab entsize", .{}); + const strtab = strtab: { + if (symtab.shdr.link == std.elf.SHN_UNDEF or symtab.shdr.link >= ehdr.shnum) + return diags.failParse(object.path, "missing symbol names", .{}); + const shdr = §ions[symtab.shdr.link].shdr; + if (shdr.type != std.elf.SHT_STRTAB) + return diags.failParse(object.path, "invalid strtab type", .{}); + const strtab = try gpa.alloc(u8, @intCast(shdr.size)); + errdefer gpa.free(strtab); + try fr.seekTo(shdr.offset); + try r.readSliceAll(strtab); + break :strtab strtab; + }; + defer gpa.free(strtab); + const symnum = try std.math.divExact( + u32, + @intCast(symtab.shdr.size), + @intCast(symtab.shdr.entsize), + ); + symmap.clearRetainingCapacity(); + try symmap.resize(gpa, symnum); + try elf.symtab.ensureUnusedCapacity(gpa, symnum); + try elf.globals.ensureUnusedCapacity(gpa, symnum); + try fr.seekTo(symtab.shdr.offset + symtab.shdr.entsize); + symmap.items[0] = .null; + for (symmap.items[1..]) |*si| { + si.* = .null; + const input_sym = try r.peekStruct(ElfN.Sym, target_endian); + try fr.seekBy(@intCast(symtab.shdr.entsize)); + if (input_sym.name >= strtab.len or + input_sym.shndx == std.elf.SHN_UNDEF or + input_sym.shndx >= ehdr.shnum) continue; + switch (input_sym.info.type) { + else => continue, + .SECTION => { + const section = §ions[input_sym.shndx]; + if (input_sym.value == section.shdr.addr) si.* = section.si; + continue; + }, + .OBJECT, .FUNC => {}, + } + const name = std.mem.sliceTo(strtab[input_sym.name..], 0); + const parent_si = sections[input_sym.shndx].si; + si.* = try elf.initSymbolAssumeCapacity(.{ + .name = name, + .value = input_sym.value, + .size = input_sym.size, + .type = input_sym.info.type, + .bind = input_sym.info.bind, + .visibility = input_sym.other.visibility, + .shndx = elf.targetLoad(switch (elf.symPtr(parent_si)) { + inline else => |parent_sym| &parent_sym.shndx, + }), + }); + si.get(elf).ni = parent_si.get(elf).ni; + switch (input_sym.info.bind) { + else => {}, + .GLOBAL => { + const gop = elf.globals.getOrPutAssumeCapacity(elf.targetLoad( + &@field(elf.symPtr(si.*), @tagName(class)).name, + )); + if (gop.found_existing) switch (elf.targetLoad( + switch (elf.symPtr(gop.value_ptr.*)) { + inline else => |sym| &sym.info, + }, + ).bind) { + else => unreachable, + .GLOBAL => return diags.failParse( + object.path, + "multiple definitions of '{s}'", + .{name}, + ), + .WEAK => {}, + }; + gop.value_ptr.* = si.*; + }, + .WEAK => { + const gop = elf.globals.getOrPutAssumeCapacity(elf.targetLoad( + &@field(elf.symPtr(si.*), @tagName(class)).name, + )); + if (!gop.found_existing) gop.value_ptr.* = si.*; }, - ).bind) { - else => unreachable, - .GLOBAL => return diags.failParse( + } + } + for (sections[1..]) |*rels| switch (rels.shdr.type) { + else => {}, + inline std.elf.SHT_REL, std.elf.SHT_RELA => |sht| { + if (rels.shdr.link != symtab_shndx or + rels.shdr.info == std.elf.SHN_UNDEF or + rels.shdr.info >= ehdr.shnum) continue; + const Rel = switch (sht) { + else => comptime unreachable, + std.elf.SHT_REL => ElfN.Rel, + std.elf.SHT_RELA => ElfN.Rela, + }; + if (rels.shdr.entsize < @sizeOf(Rel)) return diags.failParse( object.path, - "multiple definitions of '{s}'", - .{name}, - ), - .WEAK => {}, - }; - gop.value_ptr.* = si; - }, - .WEAK => { - const gop = elf.globals.getOrPutAssumeCapacity(elf.targetLoad( - &@field(elf.symPtr(si), @tagName(class)).name, - )); - if (!gop.found_existing) gop.value_ptr.* = si; - }, - } - } + "unsupported rel entsize", + .{}, + ); + const loc_sec = §ions[rels.shdr.info]; + if (loc_sec.si == .null) continue; + const relnum = try std.math.divExact( + u32, + @intCast(rels.shdr.size), + @intCast(rels.shdr.entsize), + ); + try elf.relocs.ensureUnusedCapacity(gpa, relnum); + try fr.seekTo(rels.shdr.offset); + for (0..relnum) |_| { + const rel = try r.peekStruct(Rel, target_endian); + try fr.seekBy(@intCast(rels.shdr.entsize)); + if (rel.info.sym >= symnum) continue; + const target_si = symmap.items[rel.info.sym]; + if (target_si == .null) continue; + elf.addReloc( + loc_sec.si, + rel.offset - loc_sec.shdr.addr, + target_si, + rel.addend, + switch (elf.ehdrField(.machine)) { + else => unreachable, + inline .AARCH64, + .PPC64, + .RISCV, + .X86_64, + => |machine| @unionInit( + Reloc.Type, + @tagName(machine), + @enumFromInt(rel.info.type), + ), + }, + ) catch unreachable; + } + }, + }; + }, + }; }, } }, @@ -1512,11 +1559,10 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In reloc_info.addend, switch (elf.ehdrField(.machine)) { else => unreachable, - .X86_64 => .{ .X86_64 = switch (elf.identClass()) { - .NONE, _ => unreachable, - .@"32" => .@"32", - .@"64" => .@"64", - } }, + .AARCH64 => .{ .AARCH64 = .ABS64 }, + .PPC64 => .{ .PPC64 = .ADDR64 }, + .RISCV => .{ .RISCV = .@"64" }, + .X86_64 => .{ .X86_64 = .@"64" }, }, ); return switch (elf.symPtr(target_si)) { @@ -1912,11 +1958,11 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool { if (elf.input_section_pending_index < elf.input_sections.items.len) { const isi: Node.InputSectionIndex = @enumFromInt(elf.input_section_pending_index); elf.input_section_pending_index += 1; - const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); + const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.symbol(elf).node(elf))); defer sub_prog_node.end(); elf.flushInputSection(isi) catch |err| switch (err) { else => |e| return comp.link_diags.fail("linker failed to read input section '{s}' from \"{f}\": {t}", .{ - elf.sectionName(elf.getNode(isi.node(elf).parent(&elf.mf)).section), + elf.sectionName(elf.getNode(isi.symbol(elf).node(elf).parent(&elf.mf)).section), isi.input(elf).path(elf).fmtEscapeString(), e, }), @@ -1954,7 +2000,7 @@ fn idleProgNode( .section => |si| elf.sectionName(si), .input_section => |isi| std.fmt.bufPrint(&name, "{f} {s}", .{ isi.input(elf).path(elf), - elf.sectionName(elf.getNode(isi.node(elf).parent(&elf.mf)).section), + elf.sectionName(elf.getNode(isi.symbol(elf).node(elf).parent(&elf.mf)).section), }) catch &name, .nav => |nmi| { const ip = &elf.base.comp.zcu.?.intern_pool; @@ -2078,8 +2124,8 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { } fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { - const offset, const size = isi.fileLocation(elf); - if (size == 0) return; + const file_loc = isi.fileLocation(elf); + if (file_loc.size == 0) return; const comp = elf.base.comp; const gpa = comp.gpa; const io = comp.io; @@ -2087,11 +2133,11 @@ fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { const file = try path.root_dir.handle.adaptToNewApi().openFile(io, path.sub_path, .{}); defer file.close(io); var fr = file.reader(io, &.{}); - try fr.seekTo(offset); + try fr.seekTo(file_loc.offset); var nw: MappedFile.Node.Writer = undefined; - isi.node(elf).writer(&elf.mf, gpa, &nw); + isi.symbol(elf).node(elf).writer(&elf.mf, gpa, &nw); defer nw.deinit(); - if (try nw.interface.sendFileAll(&fr, .limited(@intCast(size))) != size) return error.EndOfStream; + if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size) return error.EndOfStream; } fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { @@ -2132,13 +2178,13 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { }, }, .input_section => |isi| { - const addr = isi.addr(elf); - const old_addr = addr.*; + const old_addr = switch (elf.symPtr(isi.symbol(elf))) { + inline else => |sym| elf.targetLoad(&sym.value), + }; const new_addr = elf.computeNodeVAddr(ni); - addr.* = new_addr; const ii = isi.input(elf); var si = ii.symbol(elf); - const end_si = ii.nextSymbol(elf); + const end_si = ii.endSymbol(elf); while (cond: { si = si.next(); break :cond si != end_si; diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig index 7550638197..7d2f153a59 100644 --- a/src/link/MappedFile.zig +++ b/src/link/MappedFile.zig @@ -144,6 +144,8 @@ pub const Node = extern struct { } }; + pub const FileLocation = struct { offset: u64, size: u64 }; + pub const Index = enum(u32) { none, _, @@ -275,7 +277,7 @@ pub const Node = extern struct { ni: Node.Index, mf: *const MappedFile, set_has_content: bool, - ) struct { offset: u64, size: u64 } { + ) FileLocation { var offset, const size = ni.location(mf).resolve(mf); var parent_ni = ni; while (true) { @@ -402,8 +404,6 @@ pub const Node = extern struct { file_reader.interface.toss(n); return n; } - - assert(file_reader.logicalPos() == file_reader.pos); const w: *Writer = @fieldParentPtr("interface", interface); const n: usize = @intCast(w.mf.copyFileRange( file_reader.file, |
