Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/link/MachO.zig
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,16 @@ fn addObject(self: *MachO, path: Path, handle: File.HandleIndex, offset: u64) !v
const tracy = trace(@src());
defer tracy.end();

const gpa = self.base.comp.gpa;
const comp = self.base.comp;
const gpa = comp.gpa;

const abs_path = try std.fs.path.resolvePosix(gpa, &.{
comp.dirs.cwd,
path.root_dir.path orelse ".",
path.sub_path,
});
errdefer gpa.free(abs_path);

const mtime: u64 = mtime: {
const file = self.getFileHandle(handle);
const stat = file.stat() catch break :mtime 0;
Expand All @@ -928,10 +937,7 @@ fn addObject(self: *MachO, path: Path, handle: File.HandleIndex, offset: u64) !v
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
self.files.set(index, .{ .object = .{
.offset = offset,
.path = .{
.root_dir = path.root_dir,
.sub_path = try gpa.dupe(u8, path.sub_path),
},
.path = abs_path,
.file_handle = handle,
.mtime = mtime,
.index = index,
Expand Down
24 changes: 16 additions & 8 deletions src/link/MachO/Archive.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ pub fn deinit(self: *Archive, allocator: Allocator) void {
}

pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File.HandleIndex, fat_arch: ?fat.Arch) !void {
const gpa = macho_file.base.comp.gpa;
const diags = &macho_file.base.comp.link_diags;
const comp = macho_file.base.comp;
const gpa = comp.gpa;
const diags = &comp.link_diags;

var arena = std.heap.ArenaAllocator.init(gpa);
defer arena.deinit();
Expand Down Expand Up @@ -55,23 +56,30 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
mem.eql(u8, name, SYMDEF_SORTED) or
mem.eql(u8, name, SYMDEF64_SORTED)) continue;

const abs_path = try std.fs.path.resolvePosix(gpa, &.{
comp.dirs.cwd,
path.root_dir.path orelse ".",
path.sub_path,
});
errdefer gpa.free(abs_path);

const o_basename = try gpa.dupe(u8, name);
errdefer gpa.free(o_basename);

const object: Object = .{
.offset = pos,
.in_archive = .{
.path = .{
.root_dir = path.root_dir,
.sub_path = try gpa.dupe(u8, path.sub_path),
},
.path = abs_path,
.size = hdr_size,
},
.path = Path.initCwd(try gpa.dupe(u8, name)),
.path = o_basename,
.file_handle = handle_index,
.index = undefined,
.alive = false,
.mtime = hdr.date() catch 0,
};

log.debug("extracting object '{f}' from archive '{f}'", .{ object.path, path });
log.debug("extracting object '{s}' from archive '{f}'", .{ o_basename, path });

try self.objects.append(gpa, object);
}
Expand Down
81 changes: 30 additions & 51 deletions src/link/MachO/Object.zig
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/// Non-zero for fat object files or archives
offset: u64,
/// Archive files cannot contain subdirectories, so only the basename is needed
/// for output. However, the full path is kept for error reporting.
path: Path,
/// If `in_archive` is not `null`, this is the basename of the object in the archive. Otherwise,
/// this is a fully-resolved absolute path, because that is the path we need to embed in stabs to
/// ensure the output does not depend on its cwd.
path: []u8,
file_handle: File.HandleIndex,
mtime: u64,
index: File.Index,
Expand Down Expand Up @@ -41,8 +42,8 @@ output_symtab_ctx: MachO.SymtabCtx = .{},
output_ar_state: Archive.ArState = .{},

pub fn deinit(self: *Object, allocator: Allocator) void {
if (self.in_archive) |*ar| allocator.free(ar.path.sub_path);
allocator.free(self.path.sub_path);
if (self.in_archive) |*ar| allocator.free(ar.path);
allocator.free(self.path);
for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| {
relocs.deinit(allocator);
sub.deinit(allocator);
Expand Down Expand Up @@ -1703,7 +1704,7 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void {
pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {
// Header
const size = try macho_file.cast(usize, self.output_ar_state.size);
const basename = std.fs.path.basename(self.path.sub_path);
const basename = std.fs.path.basename(self.path);
try Archive.writeHeader(basename, size, ar_format, writer);
// Data
const file = macho_file.getFileHandle(self.file_handle);
Expand Down Expand Up @@ -1756,12 +1757,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {
self.calcStabsSize(macho_file);
}

fn pathLen(path: Path) usize {
// +1 for the path separator
return (if (path.root_dir.path) |p| p.len + @intFromBool(path.sub_path.len != 0) else 0) + path.sub_path.len;
}

pub fn calcStabsSize(self: *Object, macho_file: *MachO) void {
fn calcStabsSize(self: *Object, macho_file: *MachO) void {
if (self.compile_unit) |cu| {
const comp_dir = cu.getCompDir(self.*);
const tu_name = cu.getTuName(self.*);
Expand All @@ -1771,9 +1767,11 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void {
self.output_symtab_ctx.strsize += @as(u32, @intCast(tu_name.len + 1)); // tu_name

if (self.in_archive) |ar| {
self.output_symtab_ctx.strsize += @intCast(pathLen(ar.path) + 1 + self.path.basename().len + 1 + 1);
// "/path/to/archive.a(object.o)\x00"
self.output_symtab_ctx.strsize += @intCast(ar.path.len + self.path.len + 3);
} else {
self.output_symtab_ctx.strsize += @intCast(pathLen(self.path) + 1);
// "/path/to/object.o\x00"
self.output_symtab_ctx.strsize += @intCast(self.path.len + 1);
}

for (self.symbols.items, 0..) |sym, i| {
Expand Down Expand Up @@ -2018,7 +2016,7 @@ pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) void {
self.writeStabs(n_strx, macho_file, ctx);
}

pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) void {
fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) void {
const writeFuncStab = struct {
inline fn writeFuncStab(
n_strx: u32,
Expand Down Expand Up @@ -2103,38 +2101,20 @@ pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) v
};
index += 1;
if (self.in_archive) |ar| {
if (ar.path.root_dir.path) |p| {
@memcpy(ctx.strtab.items[n_strx..][0..p.len], p);
n_strx += @intCast(p.len);
if (ar.path.sub_path.len != 0) {
ctx.strtab.items[n_strx] = '/';
n_strx += 1;
}
}
@memcpy(ctx.strtab.items[n_strx..][0..ar.path.sub_path.len], ar.path.sub_path);
n_strx += @intCast(ar.path.sub_path.len);
ctx.strtab.items[n_strx] = '(';
n_strx += 1;
const basename = self.path.basename();
@memcpy(ctx.strtab.items[n_strx..][0..basename.len], basename);
n_strx += @intCast(basename.len);
ctx.strtab.items[n_strx] = ')';
n_strx += 1;
ctx.strtab.items[n_strx] = 0;
// "/path/to/archive.a(object.o)\x00"
@memcpy(ctx.strtab.items[n_strx..][0..ar.path.len], ar.path);
n_strx += @intCast(ar.path.len);
ctx.strtab.items[n_strx..][0] = '(';
n_strx += 1;
@memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path);
n_strx += @intCast(self.path.len);
ctx.strtab.items[n_strx..][0..2].* = ")\x00".*;
n_strx += 2;
} else {
if (self.path.root_dir.path) |p| {
@memcpy(ctx.strtab.items[n_strx..][0..p.len], p);
n_strx += @intCast(p.len);
if (self.path.sub_path.len != 0) {
ctx.strtab.items[n_strx] = '/';
n_strx += 1;
}
}
@memcpy(ctx.strtab.items[n_strx..][0..self.path.sub_path.len], self.path.sub_path);
n_strx += @intCast(self.path.sub_path.len);
ctx.strtab.items[n_strx] = 0;
n_strx += 1;
// "/path/to/object.o\x00"
@memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path);
ctx.strtab.items[n_strx..][self.path.len] = 0;
n_strx += @intCast(self.path.len + 1);
}

for (self.symbols.items, 0..) |sym, i| {
Expand Down Expand Up @@ -2621,11 +2601,9 @@ pub fn fmtPath(self: Object) std.fmt.Alt(Object, formatPath) {

fn formatPath(object: Object, w: *Writer) Writer.Error!void {
if (object.in_archive) |ar| {
try w.print("{f}({s})", .{
ar.path, object.path.basename(),
});
try w.print("{s}({s})", .{ ar.path, object.path });
} else {
try w.print("{f}", .{object.path});
try w.writeAll(object.path);
}
}

Expand Down Expand Up @@ -2716,7 +2694,9 @@ const CompileUnit = struct {
};

const InArchive = struct {
path: Path,
/// This is a fully-resolved absolute path, because that is the path we need to embed in stabs
/// to ensure the output does not depend on its cwd.
path: []u8,
size: u32,
};

Expand Down Expand Up @@ -3094,7 +3074,6 @@ const log = std.log.scoped(.link);
const macho = std.macho;
const math = std.math;
const mem = std.mem;
const Path = std.Build.Cache.Path;
const Allocator = std.mem.Allocator;
const Writer = std.Io.Writer;

Expand Down
2 changes: 1 addition & 1 deletion src/link/MachO/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
pos = mem.alignForward(usize, pos, 2);
state.file_off = pos;
pos += @sizeOf(Archive.ar_hdr);
pos += mem.alignForward(usize, o.path.basename().len + 1, ptr_width);
pos += mem.alignForward(usize, std.fs.path.basename(o.path).len + 1, ptr_width);
pos += try macho_file.cast(usize, state.size);
},
else => unreachable,
Expand Down