Commit 7542c3260f
Changed files (5)
lib
std
src
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)`
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,
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;
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,
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;