Commit f86a38564f
Changed files (2)
src
link
src/link/MachO/synthetic.zig
@@ -18,15 +18,15 @@ pub const ZigGotSection = struct {
}
pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, macho_file: *MachO) !Index {
- const comp = macho_file.base.comp;
- const gpa = comp.gpa;
+ const gpa = macho_file.base.comp.gpa;
+ const zo = macho_file.getZigObject().?;
const index = try zig_got.allocateEntry(gpa);
const entry = &zig_got.entries.items[index];
entry.* = sym_index;
- const symbol = macho_file.getSymbol(sym_index);
+ const symbol = zo.getSymbol(sym_index);
assert(symbol.flags.needs_zig_got);
symbol.flags.has_zig_got = true;
- try symbol.addExtra(.{ .zig_got = index }, macho_file);
+ symbol.addExtra(.{ .zig_got = index }, macho_file);
return index;
}
@@ -53,9 +53,10 @@ pub const ZigGotSection = struct {
try macho_file.growSection(macho_file.zig_got_sect_index.?, needed_size);
zig_got.dirty = false;
}
+ const zo = macho_file.getZigObject().?;
const off = zig_got.entryOffset(index, macho_file);
const entry = zig_got.entries.items[index];
- const value = macho_file.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file);
+ const value = zo.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file);
var buf: [8]u8 = undefined;
std.mem.writeInt(u64, &buf, value, .little);
@@ -63,8 +64,9 @@ pub const ZigGotSection = struct {
}
pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void {
+ const zo = macho_file.getZigObject().?;
for (zig_got.entries.items) |entry| {
- const symbol = macho_file.getSymbol(entry);
+ const symbol = zo.getSymbol(entry);
const value = symbol.address(.{ .stubs = false }, macho_file);
try writer.writeInt(u64, value, .little);
}
@@ -87,22 +89,25 @@ pub const ZigGotSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
+ const zig_got = ctx.zig_got;
+ const macho_file = ctx.macho_file;
+ const zo = macho_file.getZigObject().?;
try writer.writeAll("__zig_got\n");
- for (ctx.zig_got.entries.items, 0..) |entry, index| {
- const symbol = ctx.macho_file.getSymbol(entry);
+ for (zig_got.entries.items, 0..) |entry, index| {
+ const symbol = zo.getSymbol(entry);
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
index,
- ctx.zig_got.entryAddress(@intCast(index), ctx.macho_file),
+ zig_got.entryAddress(@intCast(index), macho_file),
entry,
- symbol.getAddress(.{}, ctx.macho_file),
- symbol.getName(ctx.macho_file),
+ symbol.getAddress(.{}, macho_file),
+ symbol.getName(macho_file),
});
}
}
};
pub const GotSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
pub const Index = u32;
@@ -110,14 +115,14 @@ pub const GotSection = struct {
got.symbols.deinit(allocator);
}
- pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
+ pub fn addSymbol(got: *GotSection, ref: MachO.Ref, macho_file: *MachO) !void {
const gpa = macho_file.base.comp.gpa;
const index = @as(Index, @intCast(got.symbols.items.len));
const entry = try got.symbols.addOne(gpa);
- entry.* = sym_index;
- const symbol = macho_file.getSymbol(sym_index);
+ entry.* = ref;
+ const symbol = ref.getSymbol(macho_file).?;
symbol.flags.has_got = true;
- try symbol.addExtra(.{ .got = index }, macho_file);
+ symbol.addExtra(.{ .got = index }, macho_file);
}
pub fn getAddress(got: GotSection, index: Index, macho_file: *MachO) u64 {
@@ -133,8 +138,8 @@ pub const GotSection = struct {
pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void {
const tracy = trace(@src());
defer tracy.end();
- for (got.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (got.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);
try writer.writeInt(u64, value, .little);
}
@@ -157,12 +162,12 @@ pub const GotSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
- for (ctx.got.symbols.items, 0..) |entry, i| {
- const symbol = ctx.macho_file.getSymbol(entry);
+ for (ctx.got.symbols.items, 0..) |ref, i| {
+ const symbol = ref.getSymbol(ctx.macho_file).?;
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
i,
symbol.getGotAddress(ctx.macho_file),
- entry,
+ ref,
symbol.getAddress(.{}, ctx.macho_file),
symbol.getName(ctx.macho_file),
});
@@ -171,7 +176,7 @@ pub const GotSection = struct {
};
pub const StubsSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
pub const Index = u32;
@@ -179,13 +184,13 @@ pub const StubsSection = struct {
stubs.symbols.deinit(allocator);
}
- pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
+ pub fn addSymbol(stubs: *StubsSection, ref: MachO.Ref, macho_file: *MachO) !void {
const gpa = macho_file.base.comp.gpa;
const index = @as(Index, @intCast(stubs.symbols.items.len));
const entry = try stubs.symbols.addOne(gpa);
- entry.* = sym_index;
- const symbol = macho_file.getSymbol(sym_index);
- try symbol.addExtra(.{ .stubs = index }, macho_file);
+ entry.* = ref;
+ const symbol = ref.getSymbol(macho_file).?;
+ symbol.addExtra(.{ .stubs = index }, macho_file);
}
pub fn getAddress(stubs: StubsSection, index: Index, macho_file: *MachO) u64 {
@@ -205,8 +210,8 @@ pub const StubsSection = struct {
const cpu_arch = macho_file.getTarget().cpu.arch;
const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];
- for (stubs.symbols.items, 0..) |sym_index, idx| {
- const sym = macho_file.getSymbol(sym_index);
+ for (stubs.symbols.items, 0..) |ref, idx| {
+ const sym = ref.getSymbol(macho_file).?;
const source = sym.getAddress(.{ .stubs = true }, macho_file);
const target = laptr_sect.addr + idx * @sizeOf(u64);
switch (cpu_arch) {
@@ -248,12 +253,12 @@ pub const StubsSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
- for (ctx.stubs.symbols.items, 0..) |entry, i| {
- const symbol = ctx.macho_file.getSymbol(entry);
+ for (ctx.stubs.symbols.items, 0..) |ref, i| {
+ const symbol = ref.getSymbol(ctx.macho_file).?;
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
i,
symbol.getStubsAddress(ctx.macho_file),
- entry,
+ ref,
symbol.getAddress(.{}, ctx.macho_file),
symbol.getName(ctx.macho_file),
});
@@ -284,8 +289,8 @@ pub const StubsHelperSection = struct {
_ = stubs_helper;
const cpu_arch = macho_file.getTarget().cpu.arch;
var s: usize = preambleSize(cpu_arch);
- for (macho_file.stubs.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.stubs.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
if (sym.flags.weak) continue;
s += entrySize(cpu_arch);
}
@@ -304,8 +309,8 @@ pub const StubsHelperSection = struct {
const entry_size = entrySize(cpu_arch);
var idx: usize = 0;
- for (macho_file.stubs.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.stubs.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
if (sym.flags.weak) continue;
const offset = macho_file.lazy_bind.offsets.items[idx];
const source: i64 = @intCast(sect.addr + preamble_size + entry_size * idx);
@@ -339,14 +344,15 @@ pub const StubsHelperSection = struct {
fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {
_ = stubs_helper;
+ const obj = macho_file.getInternalObject().?;
const cpu_arch = macho_file.getTarget().cpu.arch;
const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
const dyld_private_addr = target: {
- const sym = macho_file.getSymbol(macho_file.dyld_private_index.?);
+ const sym = obj.getDyldPrivateRef(macho_file).?.getSymbol(macho_file).?;
break :target sym.getAddress(.{}, macho_file);
};
const dyld_stub_binder_addr = target: {
- const sym = macho_file.getSymbol(macho_file.dyld_stub_binder_index.?);
+ const sym = obj.getDyldStubBinderRef(macho_file).?.getSymbol(macho_file).?;
break :target sym.getGotAddress(macho_file);
};
switch (cpu_arch) {
@@ -402,8 +408,8 @@ pub const LaSymbolPtrSection = struct {
const cpu_arch = macho_file.getTarget().cpu.arch;
const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
var stub_helper_idx: u32 = 0;
- for (macho_file.stubs.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.stubs.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
if (sym.flags.weak) {
const value = sym.getAddress(.{ .stubs = false }, macho_file);
try writer.writeInt(u64, @intCast(value), .little);
@@ -418,7 +424,7 @@ pub const LaSymbolPtrSection = struct {
};
pub const TlvPtrSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
pub const Index = u32;
@@ -426,13 +432,13 @@ pub const TlvPtrSection = struct {
tlv.symbols.deinit(allocator);
}
- pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
+ pub fn addSymbol(tlv: *TlvPtrSection, ref: MachO.Ref, macho_file: *MachO) !void {
const gpa = macho_file.base.comp.gpa;
const index = @as(Index, @intCast(tlv.symbols.items.len));
const entry = try tlv.symbols.addOne(gpa);
- entry.* = sym_index;
- const symbol = macho_file.getSymbol(sym_index);
- try symbol.addExtra(.{ .tlv_ptr = index }, macho_file);
+ entry.* = ref;
+ const symbol = ref.getSymbol(macho_file).?;
+ symbol.addExtra(.{ .tlv_ptr = index }, macho_file);
}
pub fn getAddress(tlv: TlvPtrSection, index: Index, macho_file: *MachO) u64 {
@@ -449,8 +455,8 @@ pub const TlvPtrSection = struct {
const tracy = trace(@src());
defer tracy.end();
- for (tlv.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (tlv.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
if (sym.flags.import) {
try writer.writeInt(u64, 0, .little);
} else {
@@ -476,12 +482,12 @@ pub const TlvPtrSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
- for (ctx.tlv.symbols.items, 0..) |entry, i| {
- const symbol = ctx.macho_file.getSymbol(entry);
+ for (ctx.tlv.symbols.items, 0..) |ref, i| {
+ const symbol = ref.getSymbol(ctx.macho_file).?;
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
i,
symbol.getTlvPtrAddress(ctx.macho_file),
- entry,
+ ref,
symbol.getAddress(.{}, ctx.macho_file),
symbol.getName(ctx.macho_file),
});
@@ -490,7 +496,7 @@ pub const TlvPtrSection = struct {
};
pub const ObjcStubsSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
pub fn deinit(objc: *ObjcStubsSection, allocator: Allocator) void {
objc.symbols.deinit(allocator);
@@ -504,13 +510,13 @@ pub const ObjcStubsSection = struct {
};
}
- pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
+ pub fn addSymbol(objc: *ObjcStubsSection, ref: MachO.Ref, macho_file: *MachO) !void {
const gpa = macho_file.base.comp.gpa;
const index = @as(Index, @intCast(objc.symbols.items.len));
const entry = try objc.symbols.addOne(gpa);
- entry.* = sym_index;
- const symbol = macho_file.getSymbol(sym_index);
- try symbol.addExtra(.{ .objc_stubs = index }, macho_file);
+ entry.* = ref;
+ const symbol = ref.getSymbol(macho_file).?;
+ symbol.addExtra(.{ .objc_stubs = index }, macho_file);
}
pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 {
@@ -527,8 +533,10 @@ pub const ObjcStubsSection = struct {
const tracy = trace(@src());
defer tracy.end();
- for (objc.symbols.items, 0..) |sym_index, idx| {
- const sym = macho_file.getSymbol(sym_index);
+ const obj = macho_file.getInternalObject().?;
+
+ for (objc.symbols.items, 0..) |ref, idx| {
+ const sym = ref.getSymbol(macho_file).?;
const addr = objc.getAddress(@intCast(idx), macho_file);
switch (macho_file.getTarget().cpu.arch) {
.x86_64 => {
@@ -540,7 +548,7 @@ pub const ObjcStubsSection = struct {
}
try writer.writeAll(&.{ 0xff, 0x25 });
{
- const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?);
+ const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
const target = target_sym.getGotAddress(macho_file);
const source = addr + 7;
try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);
@@ -560,7 +568,7 @@ pub const ObjcStubsSection = struct {
);
}
{
- const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?);
+ const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
const target = target_sym.getGotAddress(macho_file);
const source = addr + 2 * @sizeOf(u32);
const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
@@ -599,12 +607,12 @@ pub const ObjcStubsSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
- for (ctx.objc.symbols.items, 0..) |entry, i| {
- const symbol = ctx.macho_file.getSymbol(entry);
+ for (ctx.objc.symbols.items, 0..) |ref, i| {
+ const symbol = ref.getSymbol(ctx.macho_file).?;
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
i,
symbol.getObjcStubsAddress(ctx.macho_file),
- entry,
+ ref,
symbol.getAddress(.{}, ctx.macho_file),
symbol.getName(ctx.macho_file),
});
@@ -620,31 +628,89 @@ pub const Indsymtab = struct {
return @intCast(macho_file.stubs.symbols.items.len * 2 + macho_file.got.symbols.items.len);
}
+ pub fn updateSize(ind: *Indsymtab, macho_file: *MachO) !void {
+ macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
+ }
+
pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void {
const tracy = trace(@src());
defer tracy.end();
_ = ind;
- for (macho_file.stubs.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.stubs.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
}
- for (macho_file.got.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.got.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
}
- for (macho_file.stubs.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
+ for (macho_file.stubs.symbols.items) |ref| {
+ const sym = ref.getSymbol(macho_file).?;
try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
}
}
};
+pub const DataInCode = struct {
+ entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
+
+ pub fn deinit(dice: *DataInCode, allocator: Allocator) void {
+ dice.entries.deinit(allocator);
+ }
+
+ pub fn size(dice: DataInCode) usize {
+ return dice.entries.items.len * @sizeOf(macho.data_in_code_entry);
+ }
+
+ pub fn updateSize(dice: *DataInCode, macho_file: *MachO) !void {
+ const gpa = macho_file.base.comp.gpa;
+ const base_address = if (!macho_file.base.isRelocatable())
+ macho_file.getTextSegment().vmaddr
+ else
+ 0;
+
+ for (macho_file.objects.items) |index| {
+ const object = macho_file.getFile(index).?.object;
+ const dices = object.getDataInCode();
+
+ try dice.entries.ensureUnusedCapacity(gpa, dices.len);
+
+ var next_dice: usize = 0;
+ for (object.getAtoms()) |atom_index| {
+ if (next_dice >= dices.len) break;
+ const atom = object.getAtom(atom_index) orelse continue;
+ if (!atom.flags.alive) continue;
+ const start_off = atom.getInputAddress(macho_file);
+ const end_off = start_off + atom.size;
+ const start_dice = next_dice;
+
+ if (end_off < dices[next_dice].offset) continue;
+
+ while (next_dice < dices.len and
+ dices[next_dice].offset < end_off) : (next_dice += 1)
+ {}
+
+ if (atom.alive.load(.seq_cst)) for (dices[start_dice..next_dice]) |d| {
+ dice.entries.appendAssumeCapacity(.{
+ .offset = @intCast(atom.getAddress(macho_file) + d.offset - start_off - base_address),
+ .length = d.length,
+ .kind = d.kind,
+ });
+ };
+ }
+ }
+
+ macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
+ }
+};
+
const aarch64 = @import("../aarch64.zig");
const assert = std.debug.assert;
+const macho = std.macho;
const math = std.math;
const std = @import("std");
const trace = @import("../../tracy.zig").trace;
src/link/MachO.zig
@@ -68,6 +68,7 @@ weak_bind: WeakBind = .{},
lazy_bind: LazyBind = .{},
export_trie: ExportTrie = .{},
unwind_info: UnwindInfo = .{},
+data_in_code: DataInCode = .{},
/// Tracked loadable segments during incremental linking.
zig_text_seg_index: ?u8 = null,
@@ -316,6 +317,7 @@ pub fn deinit(self: *MachO) void {
self.lazy_bind.deinit(gpa);
self.export_trie.deinit(gpa);
self.unwind_info.deinit(gpa);
+ self.data_in_code.deinit(gpa);
self.thunks.deinit(gpa);
}
@@ -4524,6 +4526,7 @@ const Bind = bind.Bind;
const Cache = std.Build.Cache;
const CodeSignature = @import("MachO/CodeSignature.zig");
const Compilation = @import("../Compilation.zig");
+const DataInCode = synthetic.DataInCode;
pub const DebugSymbols = @import("MachO/DebugSymbols.zig");
const Dylib = @import("MachO/Dylib.zig");
const ExportTrie = @import("MachO/dyld_info/Trie.zig");