Commit 352941b030
Changed files (2)
src
link
src/link/MachO/relocatable.zig
@@ -12,7 +12,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
if (module_obj_path) |path| try positionals.append(.{ .path = path });
- if (positionals.items.len == 1) {
+ if (macho_file.getZigObject() == null and positionals.items.len == 1) {
// Instead of invoking a full-blown `-r` mode on the input which sadly will strip all
// debug info segments/sections (this is apparently by design by Apple), we copy
// the *only* input file over.
@@ -26,6 +26,11 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
return;
}
+ if (macho_file.getZigObject() != null and positionals.items.len > 0) {
+ try macho_file.reportUnexpectedError("TODO: build-obj for ZigObject and input object files", .{});
+ return error.FlushFailure;
+ }
+
for (positionals.items) |obj| {
macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
error.MalformedObject,
@@ -46,8 +51,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
try macho_file.addUndefinedGlobals();
try macho_file.resolveSymbols();
- markExports(macho_file);
- claimUnresolved(macho_file);
+ try markExports(macho_file);
+ try claimUnresolved(macho_file);
try initOutputSections(macho_file);
try macho_file.sortSections();
try macho_file.addAtomsToSections();
@@ -109,8 +114,13 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
try writeHeader(macho_file, ncmds, sizeofcmds);
}
-fn markExports(macho_file: *MachO) void {
- for (macho_file.objects.items) |index| {
+fn markExports(macho_file: *MachO) error{OutOfMemory}!void {
+ var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
+ defer objects.deinit();
+ if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
+ objects.appendSliceAssumeCapacity(macho_file.objects.items);
+
+ for (objects.items) |index| {
for (macho_file.getFile(index).?.getSymbols()) |sym_index| {
const sym = macho_file.getSymbol(sym_index);
const file = sym.getFile(macho_file) orelse continue;
@@ -122,13 +132,22 @@ fn markExports(macho_file: *MachO) void {
}
}
-fn claimUnresolved(macho_file: *MachO) void {
- for (macho_file.objects.items) |index| {
- const object = macho_file.getFile(index).?.object;
+fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void {
+ var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
+ defer objects.deinit();
+ if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
+ objects.appendSliceAssumeCapacity(macho_file.objects.items);
- for (object.symbols.items, 0..) |sym_index, i| {
+ for (objects.items) |index| {
+ const file = macho_file.getFile(index).?;
+
+ for (file.getSymbols(), 0..) |sym_index, i| {
const nlist_idx = @as(Symbol.Index, @intCast(i));
- const nlist = object.symtab.items(.nlist)[nlist_idx];
+ const nlist = switch (file) {
+ .object => |x| x.symtab.items(.nlist)[nlist_idx],
+ .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
+ else => unreachable,
+ };
if (!nlist.ext()) continue;
if (!nlist.undf()) continue;
@@ -290,7 +309,7 @@ fn writeAtoms(macho_file: *MachO) !void {
assert(atom.flags.alive);
const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;
const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
- try atom.getFile(macho_file).object.getAtomData(atom.*, code[off..][0..atom_size]);
+ try atom.getData(macho_file, code[off..][0..atom_size]);
try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs);
}
@@ -501,5 +520,6 @@ const trace = @import("../../tracy.zig").trace;
const Atom = @import("Atom.zig");
const Compilation = @import("../../Compilation.zig");
+const File = @import("file.zig").File;
const MachO = @import("../MachO.zig");
const Symbol = @import("Symbol.zig");
src/link/MachO.zig
@@ -285,8 +285,7 @@ pub fn createEmpty(
};
try self.d_sym.?.initMetadata(self);
} else {
- try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{});
- return error.Unexpected;
+ @panic("TODO: implement generating and emitting __DWARF in .o file");
},
.code_view => unreachable,
}
@@ -2025,7 +2024,7 @@ pub fn sortSections(self: *MachO) !void {
for (zo.symtab.items(.nlist)) |*sym| {
if (sym.sect()) {
- sym.n_sect = backlinks[sym.n_sect];
+ sym.n_sect = backlinks[sym.n_sect - 1] + 1;
}
}
@@ -3391,8 +3390,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
.prot = macho.PROT.READ | macho.PROT.WRITE,
});
}
- } else {
- @panic("TODO initMetadata when relocatable");
}
const appendSect = struct {
@@ -3415,7 +3412,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
},
.flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
});
- appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?);
+ if (!self.base.isRelocatable()) appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?);
}
if (!self.base.isRelocatable()) {
@@ -3427,33 +3424,35 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
{
self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{});
- appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?);
+ if (!self.base.isRelocatable()) appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?);
}
{
self.zig_data_sect_index = try self.addSection("__DATA_ZIG", "__data_zig", .{});
- appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?);
+ if (!self.base.isRelocatable()) appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?);
}
{
self.zig_bss_sect_index = try self.addSection("__BSS_ZIG", "__bss_zig", .{
.flags = macho.S_ZEROFILL,
});
- appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
+ if (!self.base.isRelocatable()) appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
}
}
pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
const sect = &self.sections.items(.header)[sect_index];
- const seg_id = self.sections.items(.segment_id)[sect_index];
- const seg = &self.segments.items[seg_id];
if (needed_size > self.allocatedSize(sect.offset) and !sect.isZerofill()) {
const existing_size = sect.size;
sect.size = 0;
// Must move the entire section.
- const new_offset = self.findFreeSpace(needed_size, self.getPageSize());
+ const alignment = if (self.base.isRelocatable())
+ try math.powi(u32, 2, sect.@"align")
+ else
+ self.getPageSize();
+ const new_offset = self.findFreeSpace(needed_size, alignment);
log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
sect.segName(),
@@ -3465,26 +3464,32 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
sect.offset = @intCast(new_offset);
- seg.fileoff = new_offset;
}
sect.size = needed_size;
- if (!sect.isZerofill()) {
- seg.filesize = needed_size;
- }
- const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);
- if (needed_size > mem_capacity) {
- var err = try self.addErrorWithNotes(2);
- try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
- seg_id,
- seg.segName(),
- });
- try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});
- try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
- }
+ if (!self.base.isRelocatable()) {
+ const seg_id = self.sections.items(.segment_id)[sect_index];
+ const seg = &self.segments.items[seg_id];
+ seg.fileoff = sect.offset;
- seg.vmsize = needed_size;
+ if (!sect.isZerofill()) {
+ seg.filesize = needed_size;
+ }
+
+ const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);
+ if (needed_size > mem_capacity) {
+ var err = try self.addErrorWithNotes(2);
+ try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
+ seg_id,
+ seg.segName(),
+ });
+ try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});
+ try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
+ }
+
+ seg.vmsize = needed_size;
+ }
}
pub fn getTarget(self: MachO) std.Target {