Skip to content

Commit

Permalink
Merge pull request #155 from kubkon/update-zig
Browse files Browse the repository at this point in the history
update to latest zig changes
  • Loading branch information
kubkon authored Sep 9, 2024
2 parents 8b0e293 + 4bedccc commit 2401d66
Show file tree
Hide file tree
Showing 20 changed files with 516 additions and 491 deletions.
8 changes: 4 additions & 4 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

.dependencies = .{
.@"zig-yaml" = .{
.url = "https://github.com/kubkon/zig-yaml/archive/325dbdd276604dccf184c32fef9600b0ac48343d.tar.gz",
.hash = "1220e8870ca83e47b98807e89b5b636072413f6c09f9b26037e4c98c55e4960ac55a",
.url = "https://github.com/kubkon/zig-yaml/archive/a551d00ab041f4799420ab224cdc3efdf978092c.tar.gz",
.hash = "12208398e1393f83a39d03f3ef4893607650b6227dc7f1eee3db4d163fbc2c0c37ca",
},
.@"zig-dis-x86_64" = .{
.url = "https://github.com/kubkon/zig-dis-x86_64/archive/5203b9affc5045e000ae7963d988e155e98e396d.tar.gz",
.hash = "12207252f0592e53e8794d5a41409791d5c8c70e0de67bfba48844406619847cc971",
.url = "https://github.com/kubkon/zig-dis-x86_64/archive/53b2e2dae9e824d7b4994e767c2cbb4f39e443a9.tar.gz",
.hash = "1220f2b9588352067d5b6f3b68d5461cea52f4425c9144f6757db775cf2f19cb5d26",
},
},

Expand Down
21 changes: 15 additions & 6 deletions src/Coff.zig
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ fn parseArchive(self: *Coff, obj: LinkObject, queue: anytype) ParseError!bool {

var has_parse_error = false;
for (archive.members.items) |member| {
const member_cpu_arch = member.machine.toTargetCpuArch() orelse {
const member_cpu_arch = cpuArchFromCoffMachineType(member.machine) orelse {
extra_log.debug("{s}({s}): TODO unhandled machine type {}", .{ obj.path, member.name, member.machine });
continue;
};
Expand Down Expand Up @@ -1395,6 +1395,15 @@ pub fn getImageBase(self: Coff) u64 {
};
}

/// TODO convert from std.Target.Cpu.Arch into std.coff.MachineType and remove this.
fn cpuArchFromCoffMachineType(em: std.coff.MachineType) ?std.Target.Cpu.Arch {
return switch (em) {
.ARM64 => .aarch64,
.X64 => .x86_64,
else => null,
};
}

pub fn addAlternateName(self: *Coff, from: []const u8, to: []const u8) !void {
const gpa = self.base.allocator;
const from_index = blk: {
Expand Down Expand Up @@ -1493,14 +1502,14 @@ pub fn getSymbol(self: *Coff, index: Symbol.Index) *Symbol {
}

pub fn addSymbolExtra(self: *Coff, extra: Symbol.Extra) !u32 {
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
try self.symbols_extra.ensureUnusedCapacity(self.base.allocator, fields.len);
return self.addSymbolExtraAssumeCapacity(extra);
}

pub fn addSymbolExtraAssumeCapacity(self: *Coff, extra: Symbol.Extra) u32 {
const index = @as(u32, @intCast(self.symbols_extra.items.len));
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
inline for (fields) |field| {
self.symbols_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
Expand All @@ -1512,7 +1521,7 @@ pub fn addSymbolExtraAssumeCapacity(self: *Coff, extra: Symbol.Extra) u32 {

pub fn getSymbolExtra(self: Coff, index: u32) ?Symbol.Extra {
if (index == 0) return null;
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
var i: usize = index;
var result: Symbol.Extra = undefined;
inline for (fields) |field| {
Expand All @@ -1527,7 +1536,7 @@ pub fn getSymbolExtra(self: Coff, index: u32) ?Symbol.Extra {

pub fn setSymbolExtra(self: *Coff, index: u32, extra: Symbol.Extra) void {
assert(index > 0);
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
inline for (fields, 0..) |field, i| {
self.symbols_extra.items[index + i] = switch (field.type) {
u32 => @field(extra, field.name),
Expand Down Expand Up @@ -1636,7 +1645,7 @@ fn formatSectionFlags(
) !void {
_ = options;
_ = unused_fmt_string;
inline for (@typeInfo(coff.SectionHeaderFlags).Struct.fields) |field| {
inline for (@typeInfo(coff.SectionHeaderFlags).@"struct".fields) |field| {
if (@field(flags, field.name) == 0b1) {
try writer.writeAll(field.name ++ " ");
}
Expand Down
2 changes: 1 addition & 1 deletion src/Coff/Symbol.zig
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, coff_file: *Coff) !void {
symbol.extra = try coff_file.addSymbolExtra(.{});
}
var extra = symbol.getExtra(coff_file).?;
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
if (@field(opts, field.name)) |x| {
@field(extra, field.name) = x;
}
Expand Down
103 changes: 89 additions & 14 deletions src/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ fn calcSectionSizes(self: *Elf) !void {
if (atoms.items.len == 0) continue;

// Create jump/branch range extenders if needed.
try thunks.createThunks(@intCast(i), self);
try self.createThunks(@intCast(i));
}
}

Expand Down Expand Up @@ -1833,7 +1833,7 @@ fn parseObject(self: *Elf, obj: LinkObject) !bool {
try file.seekTo(0);

if (!Object.isValidHeader(&header)) return false;
const obj_arch = header.e_machine.toTargetCpuArch().?;
const obj_arch = cpuArchFromElfMachine(header.e_machine);
try self.validateOrSetCpuArch(obj.path, obj_arch);
try self.validateEFlags(obj.path, header.e_flags);

Expand Down Expand Up @@ -1899,7 +1899,8 @@ fn parseShared(self: *Elf, obj: LinkObject) !bool {
try file.seekTo(0);

if (!SharedObject.isValidHeader(&header)) return false;
try self.validateOrSetCpuArch(obj.path, header.e_machine.toTargetCpuArch().?);
const cpu_arch = cpuArchFromElfMachine(header.e_machine);
try self.validateOrSetCpuArch(obj.path, cpu_arch);

const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
self.files.set(index, .{ .shared = .{
Expand Down Expand Up @@ -1971,6 +1972,16 @@ fn validateOrSetCpuArch(self: *Elf, name: []const u8, cpu_arch: std.Target.Cpu.A
}
}

/// TODO convert from std.Target.Cpu.Arch into std.elf.EM and remove this.
fn cpuArchFromElfMachine(em: std.elf.EM) std.Target.Cpu.Arch {
return switch (em) {
.AARCH64 => .aarch64,
.X86_64 => .x86_64,
.RISCV => .riscv64,
else => @panic("unhandled e_machine value"),
};
}

fn validateEFlags(self: *Elf, name: []const u8, e_flags: elf.Elf64_Word) !void {
// validateOrSetCpuArch should be called before this.
const self_cpu_arch = self.options.cpu_arch.?;
Expand Down Expand Up @@ -2767,14 +2778,14 @@ pub fn getAtom(self: Elf, atom_index: Atom.Index) ?*Atom {
}

pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
const fields = @typeInfo(Atom.Extra).Struct.fields;
const fields = @typeInfo(Atom.Extra).@"struct".fields;
try self.atoms_extra.ensureUnusedCapacity(self.base.allocator, fields.len);
return self.addAtomExtraAssumeCapacity(extra);
}

pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
const index = @as(u32, @intCast(self.atoms_extra.items.len));
const fields = @typeInfo(Atom.Extra).Struct.fields;
const fields = @typeInfo(Atom.Extra).@"struct".fields;
inline for (fields) |field| {
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
Expand All @@ -2786,7 +2797,7 @@ pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {

pub fn getAtomExtra(self: *Elf, index: u32) ?Atom.Extra {
if (index == 0) return null;
const fields = @typeInfo(Atom.Extra).Struct.fields;
const fields = @typeInfo(Atom.Extra).@"struct".fields;
var i: usize = index;
var result: Atom.Extra = undefined;
inline for (fields) |field| {
Expand All @@ -2801,7 +2812,7 @@ pub fn getAtomExtra(self: *Elf, index: u32) ?Atom.Extra {

pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
assert(index > 0);
const fields = @typeInfo(Atom.Extra).Struct.fields;
const fields = @typeInfo(Atom.Extra).@"struct".fields;
inline for (fields, 0..) |field, i| {
self.atoms_extra.items[index + i] = switch (field.type) {
u32 => @field(extra, field.name),
Expand All @@ -2810,7 +2821,7 @@ pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
}
}

pub fn addThunk(self: *Elf) !Thunk.Index {
fn addThunk(self: *Elf) !Thunk.Index {
const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
const thunk = try self.thunks.addOne(self.base.allocator);
thunk.* = .{};
Expand All @@ -2822,6 +2833,71 @@ pub fn getThunk(self: *Elf, index: Thunk.Index) *Thunk {
return &self.thunks.items[index];
}

fn createThunks(self: *Elf, shndx: u32) !void {
const advance = struct {
fn advance(shdr: *elf.Elf64_Shdr, size: u64, pow2_align: u8) !i64 {
const alignment = try math.powi(u32, 2, pow2_align);
const offset = mem.alignForward(u64, shdr.sh_size, alignment);
const padding = offset - shdr.sh_size;
shdr.sh_size += padding + size;
shdr.sh_addralign = @max(shdr.sh_addralign, alignment);
return @intCast(offset);
}
}.advance;

const gpa = self.base.allocator;
const cpu_arch = self.options.cpu_arch.?;
const slice = self.sections.slice();
const shdr = &slice.items(.shdr)[shndx];
const atoms = slice.items(.atoms)[shndx].items;
assert(atoms.len > 0);

for (atoms) |atom_index| {
self.getAtom(atom_index).?.value = -1;
}

var i: usize = 0;
while (i < atoms.len) {
const start = i;
const start_atom = self.getAtom(atoms[start]).?;
assert(start_atom.flags.alive);
start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment);
i += 1;

while (i < atoms.len) : (i += 1) {
const atom_index = atoms[i];
const atom = self.getAtom(atom_index).?;
assert(atom.flags.alive);
const alignment = try math.powi(u32, 2, atom.alignment);
if (@as(i64, @intCast(mem.alignForward(u64, shdr.sh_size, alignment))) - start_atom.value >= Thunk.maxAllowedDistance(cpu_arch)) break;
atom.value = try advance(shdr, atom.size, atom.alignment);
}

// Insert a thunk at the group end
const thunk_index = try self.addThunk();
const thunk = self.getThunk(thunk_index);
thunk.out_shndx = shndx;

// Scan relocs in the group and create trampolines for any unreachable callsite
for (atoms[start..i]) |atom_index| {
const atom = self.getAtom(atom_index).?;
const object = atom.getObject(self);
log.debug("atom({d}) {s}", .{ atom_index, atom.getName(self) });
for (atom.getRelocs(self)) |rel| {
if (Thunk.isReachable(atom, rel, self)) continue;
const target = object.symbols.items[rel.r_sym()];
try thunk.symbols.put(gpa, target, {});
}
try atom.addExtra(.{ .thunk = thunk_index }, self);
atom.flags.thunk = true;
}

thunk.value = try advance(shdr, thunk.size(self), 2);

log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(self) });
}
}

pub fn addSymbol(self: *Elf) !Symbol.Index {
const index = @as(Symbol.Index, @intCast(self.symbols.items.len));
const symbol = try self.symbols.addOne(self.base.allocator);
Expand All @@ -2835,14 +2911,14 @@ pub fn getSymbol(self: *Elf, index: Symbol.Index) *Symbol {
}

pub fn addSymbolExtra(self: *Elf, extra: Symbol.Extra) !u32 {
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
try self.symbols_extra.ensureUnusedCapacity(self.base.allocator, fields.len);
return self.addSymbolExtraAssumeCapacity(extra);
}

pub fn addSymbolExtraAssumeCapacity(self: *Elf, extra: Symbol.Extra) u32 {
const index = @as(u32, @intCast(self.symbols_extra.items.len));
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
inline for (fields) |field| {
self.symbols_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
Expand All @@ -2854,7 +2930,7 @@ pub fn addSymbolExtraAssumeCapacity(self: *Elf, extra: Symbol.Extra) u32 {

pub fn getSymbolExtra(self: *Elf, index: u32) ?Symbol.Extra {
if (index == 0) return null;
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
var i: usize = index;
var result: Symbol.Extra = undefined;
inline for (fields) |field| {
Expand All @@ -2869,7 +2945,7 @@ pub fn getSymbolExtra(self: *Elf, index: u32) ?Symbol.Extra {

pub fn setSymbolExtra(self: *Elf, index: u32, extra: Symbol.Extra) void {
assert(index > 0);
const fields = @typeInfo(Symbol.Extra).Struct.fields;
const fields = @typeInfo(Symbol.Extra).@"struct".fields;
inline for (fields, 0..) |field, i| {
self.symbols_extra.items[index + i] = switch (field.type) {
u32 => @field(extra, field.name),
Expand Down Expand Up @@ -3312,7 +3388,6 @@ const relocatable = @import("Elf/relocatable.zig");
const relocation = @import("Elf/relocation.zig");
const state_log = std.log.scoped(.state);
const synthetic = @import("Elf/synthetic.zig");
const thunks = @import("Elf/thunks.zig");
const trace = @import("tracy.zig").trace;
const riscv = @import("riscv.zig");

Expand Down Expand Up @@ -3342,6 +3417,6 @@ const SharedObject = @import("Elf/SharedObject.zig");
const StringTable = @import("StringTable.zig");
const Symbol = @import("Elf/Symbol.zig");
const ThreadPool = std.Thread.Pool;
const Thunk = @import("Elf/thunks.zig").Thunk;
const Thunk = @import("Elf/Thunk.zig");
const VerneedSection = synthetic.VerneedSection;
const Zld = @import("Zld.zig");
4 changes: 2 additions & 2 deletions src/Elf/Atom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {
atom.extra = try elf_file.addAtomExtra(.{});
}
var extra = atom.getExtra(elf_file).?;
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
if (@field(opts, field.name)) |x| {
@field(extra, field.name) = x;
}
Expand Down Expand Up @@ -1890,4 +1890,4 @@ const Fde = @import("eh_frame.zig").Fde;
const File = @import("file.zig").File;
const Object = @import("Object.zig");
const Symbol = @import("Symbol.zig");
const Thunk = @import("thunks.zig").Thunk;
const Thunk = @import("Thunk.zig");
2 changes: 1 addition & 1 deletion src/Elf/LdScript.zig
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const Command = enum {
as_needed,

fn fromString(s: []const u8) ?Command {
inline for (@typeInfo(Command).Enum.fields) |field| {
inline for (@typeInfo(Command).@"enum".fields) |field| {
const upper_name = n: {
comptime var buf: [field.name.len]u8 = undefined;
inline for (field.name, 0..) |c, i| {
Expand Down
2 changes: 1 addition & 1 deletion src/Elf/Symbol.zig
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
symbol.extra = try elf_file.addSymbolExtra(.{});
}
var extra = symbol.getExtra(elf_file).?;
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
inline for (@typeInfo(@TypeOf(opts)).@"struct".fields) |field| {
if (@field(opts, field.name)) |x| {
@field(extra, field.name) = x;
}
Expand Down
Loading

0 comments on commit 2401d66

Please sign in to comment.