macho: emit incomplete object file
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user