mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 22:09:49 +00:00
macho: migrate Atom and Symbol
This commit is contained in:
parent
c59583e43d
commit
b9bac32a25
@ -22,16 +22,10 @@ dylibs: std.ArrayListUnmanaged(File.Index) = .{},
|
||||
segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
|
||||
sections: std.MultiArrayList(Section) = .{},
|
||||
|
||||
symbols: std.ArrayListUnmanaged(Symbol) = .{},
|
||||
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
globals: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
resolver: SymbolResolver = .{},
|
||||
/// This table will be populated after `scanRelocs` has run.
|
||||
/// Key is symbol index.
|
||||
undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Atom.Index)) = .{},
|
||||
/// Global symbols we need to resolve for the link to succeed.
|
||||
undefined_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
boundary_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
undefs: std.AutoHashMapUnmanaged(Ref, std.ArrayListUnmanaged(Ref)) = .{},
|
||||
|
||||
dyld_info_cmd: macho.dyld_info_command = .{},
|
||||
symtab_cmd: macho.symtab_command = .{},
|
||||
@ -55,19 +49,8 @@ eh_frame_sect_index: ?u8 = null,
|
||||
unwind_info_sect_index: ?u8 = null,
|
||||
objc_stubs_sect_index: ?u8 = null,
|
||||
|
||||
mh_execute_header_index: ?Symbol.Index = null,
|
||||
mh_dylib_header_index: ?Symbol.Index = null,
|
||||
dyld_private_index: ?Symbol.Index = null,
|
||||
dyld_stub_binder_index: ?Symbol.Index = null,
|
||||
dso_handle_index: ?Symbol.Index = null,
|
||||
objc_msg_send_index: ?Symbol.Index = null,
|
||||
entry_index: ?Symbol.Index = null,
|
||||
|
||||
thunks: std.ArrayListUnmanaged(Thunk) = .{},
|
||||
|
||||
/// String interning table
|
||||
strings: StringTable = .{},
|
||||
|
||||
/// Output synthetic sections
|
||||
symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
strtab: std.ArrayListUnmanaged(u8) = .{},
|
||||
@ -4196,7 +4179,7 @@ const Section = struct {
|
||||
pub const LiteralPool = struct {
|
||||
table: std.AutoArrayHashMapUnmanaged(void, void) = .{},
|
||||
keys: std.ArrayListUnmanaged(Key) = .{},
|
||||
values: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
values: std.ArrayListUnmanaged(MachO.Ref) = .{},
|
||||
data: std.ArrayListUnmanaged(u8) = .{},
|
||||
|
||||
pub fn deinit(lp: *LiteralPool, allocator: Allocator) void {
|
||||
@ -4206,17 +4189,21 @@ pub const LiteralPool = struct {
|
||||
lp.data.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn getAtom(lp: LiteralPool, index: Index, macho_file: *MachO) *Atom {
|
||||
assert(index < lp.values.items.len);
|
||||
return macho_file.getAtom(lp.values.items[index]).?;
|
||||
}
|
||||
|
||||
const InsertResult = struct {
|
||||
found_existing: bool,
|
||||
index: Index,
|
||||
atom: *Atom.Index,
|
||||
ref: *MachO.Ref,
|
||||
};
|
||||
|
||||
pub fn getSymbolRef(lp: LiteralPool, index: Index) MachO.Ref {
|
||||
assert(index < lp.values.items.len);
|
||||
return lp.values.items[index];
|
||||
}
|
||||
|
||||
pub fn getSymbol(lp: LiteralPool, index: Index, macho_file: *MachO) *Symbol {
|
||||
return lp.getSymbolRef(index).getSymbol(macho_file).?;
|
||||
}
|
||||
|
||||
pub fn insert(lp: *LiteralPool, allocator: Allocator, @"type": u8, string: []const u8) !InsertResult {
|
||||
const size: u32 = @intCast(string.len);
|
||||
try lp.data.ensureUnusedCapacity(allocator, size);
|
||||
@ -4278,12 +4265,6 @@ const HotUpdateState = struct {
|
||||
mach_task: ?std.c.MachTask = null,
|
||||
};
|
||||
|
||||
pub const DynamicRelocs = struct {
|
||||
rebase_relocs: u32 = 0,
|
||||
bind_relocs: u32 = 0,
|
||||
weak_bind_relocs: u32 = 0,
|
||||
};
|
||||
|
||||
pub const SymtabCtx = struct {
|
||||
ilocal: u32 = 0,
|
||||
istab: u32 = 0,
|
||||
@ -4293,6 +4274,7 @@ pub const SymtabCtx = struct {
|
||||
nstabs: u32 = 0,
|
||||
nexports: u32 = 0,
|
||||
nimports: u32 = 0,
|
||||
stroff: u32 = 0,
|
||||
strsize: u32 = 0,
|
||||
};
|
||||
|
||||
@ -4579,6 +4561,131 @@ const UndefinedTreatment = enum {
|
||||
dynamic_lookup,
|
||||
};
|
||||
|
||||
/// A reference to atom or symbol in an input file.
|
||||
/// If file == 0, symbol is an undefined global.
|
||||
pub const Ref = struct {
|
||||
index: u32,
|
||||
file: File.Index,
|
||||
|
||||
pub fn eql(ref: Ref, other: Ref) bool {
|
||||
return ref.index == other.index and ref.file == other.file;
|
||||
}
|
||||
|
||||
pub fn getFile(ref: Ref, macho_file: *MachO) ?File {
|
||||
return macho_file.getFile(ref.file);
|
||||
}
|
||||
|
||||
pub fn getAtom(ref: Ref, macho_file: *MachO) ?*Atom {
|
||||
const file = ref.getFile(macho_file) orelse return null;
|
||||
return file.getAtom(ref.index);
|
||||
}
|
||||
|
||||
pub fn getSymbol(ref: Ref, macho_file: *MachO) ?*Symbol {
|
||||
const file = ref.getFile(macho_file) orelse return null;
|
||||
return switch (file) {
|
||||
inline else => |x| &x.symbols.items[ref.index],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
ref: Ref,
|
||||
comptime unused_fmt_string: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
_ = unused_fmt_string;
|
||||
_ = options;
|
||||
try writer.print("%{d} in file({d})", .{ ref.index, ref.file });
|
||||
}
|
||||
};
|
||||
|
||||
pub const SymbolResolver = struct {
|
||||
keys: std.ArrayListUnmanaged(Key) = .{},
|
||||
values: std.ArrayListUnmanaged(Ref) = .{},
|
||||
table: std.AutoArrayHashMapUnmanaged(void, void) = .{},
|
||||
|
||||
const Result = struct {
|
||||
found_existing: bool,
|
||||
index: Index,
|
||||
ref: *Ref,
|
||||
};
|
||||
|
||||
pub fn deinit(resolver: *SymbolResolver, allocator: Allocator) void {
|
||||
resolver.keys.deinit(allocator);
|
||||
resolver.values.deinit(allocator);
|
||||
resolver.table.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn getOrPut(
|
||||
resolver: *SymbolResolver,
|
||||
allocator: Allocator,
|
||||
ref: Ref,
|
||||
macho_file: *MachO,
|
||||
) !Result {
|
||||
const adapter = Adapter{ .keys = resolver.keys.items, .macho_file = macho_file };
|
||||
const key = Key{ .index = ref.index, .file = ref.file };
|
||||
const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter);
|
||||
if (!gop.found_existing) {
|
||||
try resolver.keys.append(allocator, key);
|
||||
_ = try resolver.values.addOne(allocator);
|
||||
}
|
||||
return .{
|
||||
.found_existing = gop.found_existing,
|
||||
.index = @intCast(gop.index + 1),
|
||||
.ref = &resolver.values.items[gop.index],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(resolver: SymbolResolver, index: Index) ?Ref {
|
||||
if (index == 0) return null;
|
||||
return resolver.values.items[index - 1];
|
||||
}
|
||||
|
||||
pub fn reset(resolver: *SymbolResolver) void {
|
||||
resolver.keys.clearRetainingCapacity();
|
||||
resolver.values.clearRetainingCapacity();
|
||||
resolver.table.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
const Key = struct {
|
||||
index: Symbol.Index,
|
||||
file: File.Index,
|
||||
|
||||
fn getName(key: Key, macho_file: *MachO) [:0]const u8 {
|
||||
const ref = Ref{ .index = key.index, .file = key.file };
|
||||
return ref.getSymbol(macho_file).?.getName(macho_file);
|
||||
}
|
||||
|
||||
fn eql(key: Key, other: Key, macho_file: *MachO) bool {
|
||||
const key_name = key.getName(macho_file);
|
||||
const other_name = other.getName(macho_file);
|
||||
return mem.eql(u8, key_name, other_name);
|
||||
}
|
||||
|
||||
fn hash(key: Key, macho_file: *MachO) u32 {
|
||||
const name = key.getName(macho_file);
|
||||
return @truncate(Hash.hash(0, name));
|
||||
}
|
||||
};
|
||||
|
||||
const Adapter = struct {
|
||||
keys: []const Key,
|
||||
macho_file: *MachO,
|
||||
|
||||
pub fn eql(ctx: @This(), key: Key, b_void: void, b_map_index: usize) bool {
|
||||
_ = b_void;
|
||||
const other = ctx.keys[b_map_index];
|
||||
return key.eql(other, ctx.macho_file);
|
||||
}
|
||||
|
||||
pub fn hash(ctx: @This(), key: Key) u32 {
|
||||
return key.hash(ctx.macho_file);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Index = u32;
|
||||
};
|
||||
|
||||
const MachO = @This();
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
@ -47,16 +47,6 @@ pub fn getFile(self: Atom, macho_file: *MachO) File {
|
||||
return macho_file.getFile(self.file).?;
|
||||
}
|
||||
|
||||
pub fn getData(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
assert(buffer.len == self.size);
|
||||
switch (self.getFile(macho_file)) {
|
||||
.internal => |x| try x.getAtomData(self, buffer),
|
||||
.object => |x| try x.getAtomData(macho_file, self, buffer),
|
||||
.zig_object => |x| try x.getAtomData(macho_file, self, buffer),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getRelocs(self: Atom, macho_file: *MachO) []const Relocation {
|
||||
return switch (self.getFile(macho_file)) {
|
||||
.dylib => unreachable,
|
||||
@ -88,8 +78,7 @@ pub fn getPriority(self: Atom, macho_file: *MachO) u64 {
|
||||
}
|
||||
|
||||
pub fn getUnwindRecords(self: Atom, macho_file: *MachO) []const UnwindInfo.Record.Index {
|
||||
if (!self.flags.unwind) return &[0]UnwindInfo.Record.Index{};
|
||||
const extra = self.getExtra(macho_file).?;
|
||||
const extra = self.getExtra(macho_file);
|
||||
return switch (self.getFile(macho_file)) {
|
||||
.dylib => unreachable,
|
||||
.zig_object, .internal => &[0]UnwindInfo.Record.Index{},
|
||||
@ -110,44 +99,39 @@ pub fn markUnwindRecordsDead(self: Atom, macho_file: *MachO) void {
|
||||
}
|
||||
|
||||
pub fn getThunk(self: Atom, macho_file: *MachO) *Thunk {
|
||||
assert(self.flags.thunk);
|
||||
const extra = self.getExtra(macho_file).?;
|
||||
const extra = self.getExtra(macho_file);
|
||||
return macho_file.getThunk(extra.thunk);
|
||||
}
|
||||
|
||||
pub fn getLiteralPoolIndex(self: Atom, macho_file: *MachO) ?MachO.LiteralPool.Index {
|
||||
if (!self.flags.literal_pool) return null;
|
||||
return self.getExtra(macho_file).?.literal_index;
|
||||
}
|
||||
|
||||
const AddExtraOpts = struct {
|
||||
thunk: ?u32 = null,
|
||||
rel_index: ?u32 = null,
|
||||
rel_count: ?u32 = null,
|
||||
rel_out_index: ?u32 = null,
|
||||
rel_out_count: ?u32 = null,
|
||||
unwind_index: ?u32 = null,
|
||||
unwind_count: ?u32 = null,
|
||||
literal_index: ?u32 = null,
|
||||
literal_pool_index: ?u32 = null,
|
||||
literal_symbol_index: ?u32 = null,
|
||||
};
|
||||
|
||||
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, macho_file: *MachO) !void {
|
||||
if (atom.getExtra(macho_file) == null) {
|
||||
atom.extra = try macho_file.addAtomExtra(.{});
|
||||
}
|
||||
var extra = atom.getExtra(macho_file).?;
|
||||
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, macho_file: *MachO) void {
|
||||
const file = atom.getFile(macho_file);
|
||||
var extra = file.getAtomExtra(atom.extra);
|
||||
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
|
||||
if (@field(opts, field.name)) |x| {
|
||||
@field(extra, field.name) = x;
|
||||
}
|
||||
}
|
||||
atom.setExtra(extra, macho_file);
|
||||
file.setAtomExtra(atom.extra, extra);
|
||||
}
|
||||
|
||||
pub inline fn getExtra(atom: Atom, macho_file: *MachO) ?Extra {
|
||||
return macho_file.getAtomExtra(atom.extra);
|
||||
pub inline fn getExtra(atom: Atom, macho_file: *MachO) Extra {
|
||||
return atom.getFile(macho_file).getAtomExtra(atom.extra);
|
||||
}
|
||||
|
||||
pub inline fn setExtra(atom: Atom, extra: Extra, macho_file: *MachO) void {
|
||||
macho_file.setAtomExtra(atom.extra, extra);
|
||||
atom.getFile(macho_file).setAtomExtra(atom.extra, extra);
|
||||
}
|
||||
|
||||
pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 {
|
||||
@ -467,7 +451,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
|
||||
|
||||
switch (rel.type) {
|
||||
.branch => {
|
||||
const symbol = rel.getTargetSymbol(macho_file);
|
||||
const symbol = rel.getTargetSymbol(self, macho_file);
|
||||
if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) {
|
||||
symbol.flags.stubs = true;
|
||||
if (symbol.flags.weak) {
|
||||
@ -482,7 +466,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
|
||||
.got_load_page,
|
||||
.got_load_pageoff,
|
||||
=> {
|
||||
const symbol = rel.getTargetSymbol(macho_file);
|
||||
const symbol = rel.getTargetSymbol(self, macho_file);
|
||||
if (symbol.flags.import or
|
||||
(symbol.flags.@"export" and symbol.flags.weak) or
|
||||
symbol.flags.interposable or
|
||||
@ -496,18 +480,18 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
|
||||
},
|
||||
|
||||
.zig_got_load => {
|
||||
assert(rel.getTargetSymbol(macho_file).flags.has_zig_got);
|
||||
assert(rel.getTargetSymbol(self, macho_file).flags.has_zig_got);
|
||||
},
|
||||
|
||||
.got => {
|
||||
rel.getTargetSymbol(macho_file).flags.needs_got = true;
|
||||
rel.getTargetSymbol(self, macho_file).flags.needs_got = true;
|
||||
},
|
||||
|
||||
.tlv,
|
||||
.tlvp_page,
|
||||
.tlvp_pageoff,
|
||||
=> {
|
||||
const symbol = rel.getTargetSymbol(macho_file);
|
||||
const symbol = rel.getTargetSymbol(self, macho_file);
|
||||
if (!symbol.flags.tlv) {
|
||||
try macho_file.reportParseError2(
|
||||
self.getFile(macho_file).getIndex(),
|
||||
@ -526,7 +510,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
|
||||
.unsigned => {
|
||||
if (rel.meta.length == 3) { // TODO this really should check if this is pointer width
|
||||
if (rel.tag == .@"extern") {
|
||||
const symbol = rel.getTargetSymbol(macho_file);
|
||||
const symbol = rel.getTargetSymbol(self, macho_file);
|
||||
if (symbol.isTlvInit(macho_file)) {
|
||||
macho_file.has_tlv = true;
|
||||
continue;
|
||||
@ -559,14 +543,15 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
|
||||
fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {
|
||||
if (rel.tag == .local) return false;
|
||||
|
||||
const sym = rel.getTargetSymbol(macho_file);
|
||||
if (sym.getFile(macho_file) == null) {
|
||||
const file = self.getFile(macho_file);
|
||||
const ref = file.getSymbolRef(rel.target, macho_file);
|
||||
if (ref.getFile(macho_file) == null) {
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
const gop = try macho_file.undefs.getOrPut(gpa, rel.target);
|
||||
const gop = try macho_file.undefs.getOrPut(gpa, .{ .index = rel.target, .file = self.file });
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
try gop.value_ptr.append(gpa, self.atom_index);
|
||||
try gop.value_ptr.append(gpa, .{ .index = self.atom_index, .file = self.file });
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -582,7 +567,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
const name = self.getName(macho_file);
|
||||
const relocs = self.getRelocs(macho_file);
|
||||
|
||||
relocs_log.debug("{x}: {s}", .{ self.getAddress(macho_file), name });
|
||||
relocs_log.debug("{x}: {s}", .{ self.value, name });
|
||||
|
||||
var has_error = false;
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
@ -593,7 +578,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
const subtractor = if (rel.meta.has_subtractor) relocs[i - 1] else null;
|
||||
|
||||
if (rel.tag == .@"extern") {
|
||||
if (rel.getTargetSymbol(macho_file).getFile(macho_file) == null) continue;
|
||||
if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;
|
||||
}
|
||||
|
||||
try stream.seekTo(rel_offset);
|
||||
@ -601,8 +586,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
switch (err) {
|
||||
error.RelaxFail => {
|
||||
const target = switch (rel.tag) {
|
||||
.@"extern" => rel.getTargetSymbol(macho_file).getName(macho_file),
|
||||
.local => rel.getTargetAtom(macho_file).getName(macho_file),
|
||||
.@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file),
|
||||
.local => rel.getTargetAtom(self, macho_file).getName(macho_file),
|
||||
};
|
||||
try macho_file.reportParseError2(
|
||||
file.getIndex(),
|
||||
@ -642,12 +627,12 @@ fn resolveRelocInner(
|
||||
const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;
|
||||
const P = @as(i64, @intCast(self.getAddress(macho_file))) + @as(i64, @intCast(rel_offset));
|
||||
const A = rel.addend + rel.getRelocAddend(cpu_arch);
|
||||
const S: i64 = @intCast(rel.getTargetAddress(macho_file));
|
||||
const G: i64 = @intCast(rel.getGotTargetAddress(macho_file));
|
||||
const S: i64 = @intCast(rel.getTargetAddress(self, macho_file));
|
||||
const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file));
|
||||
const TLS = @as(i64, @intCast(macho_file.getTlsAddress()));
|
||||
const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(macho_file))) else 0;
|
||||
const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0;
|
||||
// Address of the __got_zig table entry if any.
|
||||
const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file)));
|
||||
const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(self, macho_file)));
|
||||
|
||||
const divExact = struct {
|
||||
fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {
|
||||
@ -668,7 +653,7 @@ fn resolveRelocInner(
|
||||
rel_offset,
|
||||
@tagName(rel.type),
|
||||
S + A - SUB,
|
||||
rel.getTargetAtom(macho_file).atom_index,
|
||||
rel.getTargetAtom(self, macho_file).atom_index,
|
||||
}),
|
||||
.@"extern" => relocs_log.debug(" {x}<+{d}>: {s}: [=> {x}] G({x}) ZG({x}) ({s})", .{
|
||||
P,
|
||||
@ -677,7 +662,7 @@ fn resolveRelocInner(
|
||||
S + A - SUB,
|
||||
G + A,
|
||||
ZIG_GOT + A,
|
||||
rel.getTargetSymbol(macho_file).getName(macho_file),
|
||||
rel.getTargetSymbol(self, macho_file).getName(macho_file),
|
||||
}),
|
||||
}
|
||||
|
||||
@ -688,7 +673,7 @@ fn resolveRelocInner(
|
||||
assert(!rel.meta.pcrel);
|
||||
if (rel.meta.length == 3) {
|
||||
if (rel.tag == .@"extern") {
|
||||
const sym = rel.getTargetSymbol(macho_file);
|
||||
const sym = rel.getTargetSymbol(self, macho_file);
|
||||
if (sym.isTlvInit(macho_file)) {
|
||||
try writer.writeInt(u64, @intCast(S - TLS), .little);
|
||||
return;
|
||||
@ -718,7 +703,7 @@ fn resolveRelocInner(
|
||||
.aarch64 => {
|
||||
const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
|
||||
const thunk = self.getThunk(macho_file);
|
||||
const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));
|
||||
const S_: i64 = @intCast(thunk.getTargetAddress(rel.getTargetSymbolRef(self, macho_file), macho_file));
|
||||
break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
|
||||
};
|
||||
aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);
|
||||
@ -731,7 +716,7 @@ fn resolveRelocInner(
|
||||
assert(rel.tag == .@"extern");
|
||||
assert(rel.meta.length == 2);
|
||||
assert(rel.meta.pcrel);
|
||||
if (rel.getTargetSymbol(macho_file).flags.has_got) {
|
||||
if (rel.getTargetSymbol(self, macho_file).flags.has_got) {
|
||||
try writer.writeInt(i32, @intCast(G + A - P), .little);
|
||||
} else {
|
||||
try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);
|
||||
@ -754,7 +739,7 @@ fn resolveRelocInner(
|
||||
assert(rel.tag == .@"extern");
|
||||
assert(rel.meta.length == 2);
|
||||
assert(rel.meta.pcrel);
|
||||
const sym = rel.getTargetSymbol(macho_file);
|
||||
const sym = rel.getTargetSymbol(self, macho_file);
|
||||
if (sym.flags.tlv_ptr) {
|
||||
const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
|
||||
try writer.writeInt(i32, @intCast(S_ + A - P), .little);
|
||||
@ -777,7 +762,7 @@ fn resolveRelocInner(
|
||||
assert(rel.tag == .@"extern");
|
||||
assert(rel.meta.length == 2);
|
||||
assert(rel.meta.pcrel);
|
||||
const sym = rel.getTargetSymbol(macho_file);
|
||||
const sym = rel.getTargetSymbol(self, macho_file);
|
||||
const source = math.cast(u64, P) orelse return error.Overflow;
|
||||
const target = target: {
|
||||
const target = switch (rel.type) {
|
||||
@ -836,7 +821,7 @@ fn resolveRelocInner(
|
||||
assert(rel.meta.length == 2);
|
||||
assert(!rel.meta.pcrel);
|
||||
|
||||
const sym = rel.getTargetSymbol(macho_file);
|
||||
const sym = rel.getTargetSymbol(self, macho_file);
|
||||
const target = target: {
|
||||
const target = if (sym.flags.tlv_ptr) blk: {
|
||||
const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
|
||||
@ -980,48 +965,47 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.ArrayList(macho.relocation_info)) !void {
|
||||
pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const cpu_arch = macho_file.getTarget().cpu.arch;
|
||||
const relocs = self.getRelocs(macho_file);
|
||||
var stream = std.io.fixedBufferStream(code);
|
||||
|
||||
var i: usize = 0;
|
||||
for (relocs) |rel| {
|
||||
defer i += 1;
|
||||
const rel_offset = rel.offset - self.off;
|
||||
const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow;
|
||||
const r_symbolnum = r_symbolnum: {
|
||||
const r_symbolnum: u32 = switch (rel.tag) {
|
||||
.local => rel.getTargetAtom(macho_file).out_n_sect + 1,
|
||||
.@"extern" => rel.getTargetSymbol(macho_file).getOutputSymtabIndex(macho_file).?,
|
||||
.local => rel.getTargetAtom(self, macho_file).out_n_sect + 1,
|
||||
.@"extern" => rel.getTargetSymbol(self, macho_file).getOutputSymtabIndex(macho_file).?,
|
||||
};
|
||||
break :r_symbolnum math.cast(u24, r_symbolnum) orelse return error.Overflow;
|
||||
};
|
||||
const r_extern = rel.tag == .@"extern";
|
||||
var addend = rel.addend + rel.getRelocAddend(cpu_arch);
|
||||
if (rel.tag == .local) {
|
||||
const target: i64 = @intCast(rel.getTargetAddress(macho_file));
|
||||
const target: i64 = @intCast(rel.getTargetAddress(self, macho_file));
|
||||
addend += target;
|
||||
}
|
||||
|
||||
try stream.seekTo(rel_offset);
|
||||
|
||||
switch (cpu_arch) {
|
||||
.aarch64 => {
|
||||
if (rel.type == .unsigned) switch (rel.meta.length) {
|
||||
0, 1 => unreachable,
|
||||
2 => try stream.writer().writeInt(i32, @truncate(addend), .little),
|
||||
3 => try stream.writer().writeInt(i64, addend, .little),
|
||||
2 => mem.writeInt(i32, code[rel_offset..][0..4], @truncate(addend), .little),
|
||||
3 => mem.writeInt(i64, code[rel_offset..][0..8], addend, .little),
|
||||
} else if (addend > 0) {
|
||||
buffer.appendAssumeCapacity(.{
|
||||
buffer[i] = .{
|
||||
.r_address = r_address,
|
||||
.r_symbolnum = @bitCast(math.cast(i24, addend) orelse return error.Overflow),
|
||||
.r_pcrel = 0,
|
||||
.r_length = 2,
|
||||
.r_extern = 0,
|
||||
.r_type = @intFromEnum(macho.reloc_type_arm64.ARM64_RELOC_ADDEND),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const r_type: macho.reloc_type_arm64 = switch (rel.type) {
|
||||
@ -1045,14 +1029,14 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
|
||||
.tlv,
|
||||
=> unreachable,
|
||||
};
|
||||
buffer.appendAssumeCapacity(.{
|
||||
buffer[i] = .{
|
||||
.r_address = r_address,
|
||||
.r_symbolnum = r_symbolnum,
|
||||
.r_pcrel = @intFromBool(rel.meta.pcrel),
|
||||
.r_extern = @intFromBool(r_extern),
|
||||
.r_length = rel.meta.length,
|
||||
.r_type = @intFromEnum(r_type),
|
||||
});
|
||||
};
|
||||
},
|
||||
.x86_64 => {
|
||||
if (rel.meta.pcrel) {
|
||||
@ -1064,8 +1048,8 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
|
||||
}
|
||||
switch (rel.meta.length) {
|
||||
0, 1 => unreachable,
|
||||
2 => try stream.writer().writeInt(i32, @truncate(addend), .little),
|
||||
3 => try stream.writer().writeInt(i64, addend, .little),
|
||||
2 => mem.writeInt(i32, code[rel_offset..][0..4], @truncate(addend), .little),
|
||||
3 => mem.writeInt(i64, code[rel_offset..][0..8], addend, .little),
|
||||
}
|
||||
|
||||
const r_type: macho.reloc_type_x86_64 = switch (rel.type) {
|
||||
@ -1089,18 +1073,20 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
|
||||
.tlvp_pageoff,
|
||||
=> unreachable,
|
||||
};
|
||||
buffer.appendAssumeCapacity(.{
|
||||
buffer[i] = .{
|
||||
.r_address = r_address,
|
||||
.r_symbolnum = r_symbolnum,
|
||||
.r_pcrel = @intFromBool(rel.meta.pcrel),
|
||||
.r_extern = @intFromBool(r_extern),
|
||||
.r_length = rel.meta.length,
|
||||
.r_type = @intFromEnum(r_type),
|
||||
});
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
assert(i == buffer.len);
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
@ -1139,16 +1125,15 @@ fn format2(
|
||||
const atom = ctx.atom;
|
||||
const macho_file = ctx.macho_file;
|
||||
const file = atom.getFile(macho_file);
|
||||
try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d})", .{
|
||||
atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
|
||||
atom.out_n_sect, atom.alignment, atom.size,
|
||||
atom.getRelocs(macho_file).len,
|
||||
try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{
|
||||
atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
|
||||
atom.out_n_sect, atom.alignment, atom.size,
|
||||
atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,
|
||||
});
|
||||
if (atom.flags.thunk) try writer.print(" : thunk({d})", .{atom.getExtra(macho_file).?.thunk});
|
||||
if (!atom.flags.alive) try writer.writeAll(" : [*]");
|
||||
if (atom.flags.unwind) {
|
||||
if (atom.getUnwindRecords(macho_file).len > 0) {
|
||||
try writer.writeAll(" : unwind{ ");
|
||||
const extra = atom.getExtra(macho_file).?;
|
||||
const extra = atom.getExtra(macho_file);
|
||||
for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| {
|
||||
const rec = file.object.getUnwindRecord(index);
|
||||
try writer.print("{d}", .{index});
|
||||
@ -1167,18 +1152,6 @@ pub const Flags = packed struct {
|
||||
|
||||
/// Specifies if this atom has been visited during garbage collection.
|
||||
visited: bool = false,
|
||||
|
||||
/// Whether this atom has a range extension thunk.
|
||||
thunk: bool = false,
|
||||
|
||||
/// Whether this atom has any relocations.
|
||||
relocs: bool = false,
|
||||
|
||||
/// Whether this atom has any unwind records.
|
||||
unwind: bool = false,
|
||||
|
||||
/// Whether this atom has LiteralPool entry.
|
||||
literal_pool: bool = false,
|
||||
};
|
||||
|
||||
pub const Extra = struct {
|
||||
@ -1191,6 +1164,12 @@ pub const Extra = struct {
|
||||
/// Count of relocations belonging to this atom.
|
||||
rel_count: u32 = 0,
|
||||
|
||||
/// Start index of relocations being written out to file for this atom.
|
||||
rel_out_index: u32 = 0,
|
||||
|
||||
/// Count of relocations written out to file for this atom.
|
||||
rel_out_count: u32 = 0,
|
||||
|
||||
/// Start index of relocations belonging to this atom.
|
||||
unwind_index: u32 = 0,
|
||||
|
||||
@ -1198,7 +1177,10 @@ pub const Extra = struct {
|
||||
unwind_count: u32 = 0,
|
||||
|
||||
/// Index into LiteralPool entry for this atom.
|
||||
literal_index: u32 = 0,
|
||||
literal_pool_index: u32 = 0,
|
||||
|
||||
/// Index into the File's symbol table for local symbol representing this literal atom.
|
||||
literal_symbol_index: u32 = 0,
|
||||
};
|
||||
|
||||
pub const Alignment = @import("../../InternPool.zig").Alignment;
|
||||
|
||||
@ -639,6 +639,12 @@ pub fn asFile(self: *InternalObject) File {
|
||||
return .{ .internal = self };
|
||||
}
|
||||
|
||||
pub fn getAtomRelocs(self: *const InternalObject, atom: Atom, macho_file: *MachO) []const Relocation {
|
||||
const extra = atom.getExtra(macho_file).?;
|
||||
const relocs = self.sections.items(.relocs)[atom.n_sect];
|
||||
return relocs.items[extra.rel_index..][0..extra.rel_count];
|
||||
}
|
||||
|
||||
fn addAtom(self: *InternalObject, allocator: Allocator) !Atom.Index {
|
||||
const atom_index: Atom.Index = @intCast(self.atoms.items.len);
|
||||
const atom = try self.atoms.addOne(allocator);
|
||||
|
||||
@ -1860,7 +1860,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
|
||||
const name = sym.getName(macho_file);
|
||||
if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;
|
||||
}
|
||||
const sect = macho_file.sections.items(.header)[sym.out_n_sect];
|
||||
const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)];
|
||||
if (sect.isCode()) {
|
||||
self.output_symtab_ctx.nstabs += 4; // N_BNSYM, N_FUN, N_FUN, N_ENSYM
|
||||
} else if (sym.visibility == .global) {
|
||||
@ -2198,13 +2198,13 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
|
||||
const name = sym.getName(macho_file);
|
||||
if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;
|
||||
}
|
||||
const sect = macho_file.sections.items(.header)[sym.out_n_sect];
|
||||
const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)];
|
||||
const sym_n_strx = n_strx: {
|
||||
const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
|
||||
const osym = macho_file.symtab.items[symtab_index];
|
||||
break :n_strx osym.n_strx;
|
||||
};
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0;
|
||||
const sym_n_value = sym.getAddress(.{}, macho_file);
|
||||
const sym_size = sym.getSize(macho_file);
|
||||
if (sect.isCode()) {
|
||||
@ -2299,7 +2299,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
|
||||
const osym = macho_file.symtab.items[symtab_index];
|
||||
break :n_strx osym.n_strx;
|
||||
};
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
|
||||
const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0;
|
||||
const sym_n_value = sym.getAddress(.{}, macho_file);
|
||||
const sym_size = sym.getSize(macho_file);
|
||||
if (stab.is_func) {
|
||||
@ -2340,6 +2340,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getAtomRelocs(self: *const Object, atom: Atom, macho_file: *MachO) []const Relocation {
|
||||
const extra = atom.getExtra(macho_file).?;
|
||||
const relocs = self.sections.items(.relocs)[atom.n_sect];
|
||||
return relocs.items[extra.rel_index..][0..extra.rel_count];
|
||||
}
|
||||
|
||||
fn addString(self: *Object, allocator: Allocator, name: [:0]const u8) error{OutOfMemory}!u32 {
|
||||
const off: u32 = @intCast(self.strtab.items.len);
|
||||
try self.strtab.ensureUnusedCapacity(allocator, name.len + 1);
|
||||
|
||||
@ -9,17 +9,16 @@ name: u32 = 0,
|
||||
/// File where this symbol is defined.
|
||||
file: File.Index = 0,
|
||||
|
||||
/// Atom containing this symbol if any.
|
||||
/// Index of 0 means there is no associated atom with this symbol.
|
||||
/// Reference to Atom containing this symbol if any.
|
||||
/// Use `getAtom` to get the pointer to the atom.
|
||||
atom: Atom.Index = 0,
|
||||
atom_ref: MachO.Ref = .{ .index = 0, .file = 0 },
|
||||
|
||||
/// Assigned output section index for this symbol.
|
||||
out_n_sect: u8 = 0,
|
||||
|
||||
/// Index of the source nlist this symbol references.
|
||||
/// Use `getNlist` to pull the nlist from the relevant file.
|
||||
nlist_idx: Index = 0,
|
||||
nlist_idx: u32 = 0,
|
||||
|
||||
/// Misc flags for the symbol packaged as packed struct for compression.
|
||||
flags: Flags = .{},
|
||||
@ -55,16 +54,19 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {
|
||||
}
|
||||
|
||||
pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 {
|
||||
if (symbol.flags.global) return macho_file.strings.getAssumeExists(symbol.name);
|
||||
return switch (symbol.getFile(macho_file).?) {
|
||||
.dylib => unreachable, // There are no local symbols for dylibs
|
||||
.zig_object => |x| x.strtab.getAssumeExists(symbol.name),
|
||||
inline else => |x| x.getString(symbol.name),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom {
|
||||
return macho_file.getAtom(symbol.atom);
|
||||
return symbol.atom_ref.getAtom(macho_file);
|
||||
}
|
||||
|
||||
pub fn getOutputSectionIndex(symbol: Symbol, macho_file: *MachO) u8 {
|
||||
if (symbol.getAtom(macho_file)) |atom| return atom.out_n_sect;
|
||||
return symbol.out_n_sect;
|
||||
}
|
||||
|
||||
pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File {
|
||||
@ -75,8 +77,10 @@ pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File {
|
||||
pub fn getNlist(symbol: Symbol, macho_file: *MachO) macho.nlist_64 {
|
||||
const file = symbol.getFile(macho_file).?;
|
||||
return switch (file) {
|
||||
.dylib => unreachable,
|
||||
.zig_object => unreachable,
|
||||
.object => |x| x.symtab.items(.nlist)[symbol.nlist_idx],
|
||||
else => unreachable,
|
||||
.internal => |x| x.symtab.items[symbol.nlist_idx],
|
||||
};
|
||||
}
|
||||
|
||||
@ -124,33 +128,35 @@ pub fn getAddress(symbol: Symbol, opts: struct {
|
||||
|
||||
pub fn getGotAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.has_got) return 0;
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const extra = symbol.getExtra(macho_file);
|
||||
return macho_file.got.getAddress(extra.got, macho_file);
|
||||
}
|
||||
|
||||
pub fn getStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.stubs) return 0;
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const extra = symbol.getExtra(macho_file);
|
||||
return macho_file.stubs.getAddress(extra.stubs, macho_file);
|
||||
}
|
||||
|
||||
pub fn getObjcStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.objc_stubs) return 0;
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const extra = symbol.getExtra(macho_file);
|
||||
return macho_file.objc_stubs.getAddress(extra.objc_stubs, macho_file);
|
||||
}
|
||||
|
||||
pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.objc_stubs) return 0;
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const atom = macho_file.getAtom(extra.objc_selrefs).?;
|
||||
assert(atom.flags.alive);
|
||||
return atom.getAddress(macho_file);
|
||||
const extra = symbol.getExtra(macho_file);
|
||||
const file = symbol.getFile(macho_file).?;
|
||||
return switch (file) {
|
||||
.dylib, .zig_object => unreachable,
|
||||
.object, .internal => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.tlv_ptr) return 0;
|
||||
const extra = symbol.getExtra(macho_file).?;
|
||||
const extra = symbol.getExtra(macho_file);
|
||||
return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file);
|
||||
}
|
||||
|
||||
@ -162,14 +168,14 @@ const GetOrCreateZigGotEntryResult = struct {
|
||||
pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult {
|
||||
assert(!macho_file.base.isRelocatable());
|
||||
assert(symbol.flags.needs_zig_got);
|
||||
if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).?.zig_got };
|
||||
if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got };
|
||||
const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file);
|
||||
return .{ .found_existing = false, .index = index };
|
||||
}
|
||||
|
||||
pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 {
|
||||
if (!symbol.flags.has_zig_got) return 0;
|
||||
const extras = symbol.getExtra(macho_file).?;
|
||||
const extras = symbol.getExtra(macho_file);
|
||||
return macho_file.zig_got.entryAddress(extras.zig_got, macho_file);
|
||||
}
|
||||
|
||||
@ -202,11 +208,8 @@ const AddExtraOpts = struct {
|
||||
symtab: ?u32 = null,
|
||||
};
|
||||
|
||||
pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) !void {
|
||||
if (symbol.getExtra(macho_file) == null) {
|
||||
symbol.extra = try macho_file.addSymbolExtra(.{});
|
||||
}
|
||||
var extra = symbol.getExtra(macho_file).?;
|
||||
pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void {
|
||||
var extra = symbol.getExtra(macho_file);
|
||||
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
|
||||
if (@field(opts, field.name)) |x| {
|
||||
@field(extra, field.name) = x;
|
||||
@ -215,18 +218,22 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) !void {
|
||||
symbol.setExtra(extra, macho_file);
|
||||
}
|
||||
|
||||
pub inline fn getExtra(symbol: Symbol, macho_file: *MachO) ?Extra {
|
||||
return macho_file.getSymbolExtra(symbol.extra);
|
||||
pub inline fn getExtra(symbol: Symbol, macho_file: *MachO) Extra {
|
||||
return switch (symbol.getFile(macho_file).?) {
|
||||
inline else => |x| x.getSymbolExtra(symbol.extra),
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn setExtra(symbol: Symbol, extra: Extra, macho_file: *MachO) void {
|
||||
macho_file.setSymbolExtra(symbol.extra, extra);
|
||||
return switch (symbol.getFile(macho_file).?) {
|
||||
inline else => |x| x.setSymbolExtra(symbol.extra, extra),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) void {
|
||||
if (symbol.isLocal()) {
|
||||
out.n_type = if (symbol.flags.abs) macho.N_ABS else macho.N_SECT;
|
||||
out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.out_n_sect + 1);
|
||||
out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.getOutputSectionIndex(macho_file) + 1);
|
||||
out.n_desc = 0;
|
||||
out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file);
|
||||
|
||||
@ -238,7 +245,7 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo
|
||||
assert(symbol.visibility == .global);
|
||||
out.n_type = macho.N_EXT;
|
||||
out.n_type |= if (symbol.flags.abs) macho.N_ABS else macho.N_SECT;
|
||||
out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.out_n_sect + 1);
|
||||
out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.getOutputSectionIndex(macho_file) + 1);
|
||||
out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file);
|
||||
out.n_desc = 0;
|
||||
|
||||
@ -318,8 +325,8 @@ fn format2(
|
||||
symbol.getAddress(.{}, ctx.macho_file),
|
||||
});
|
||||
if (symbol.getFile(ctx.macho_file)) |file| {
|
||||
if (symbol.out_n_sect != 0) {
|
||||
try writer.print(" : sect({d})", .{symbol.out_n_sect});
|
||||
if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) {
|
||||
try writer.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)});
|
||||
}
|
||||
if (symbol.getAtom(ctx.macho_file)) |atom| {
|
||||
try writer.print(" : atom({d})", .{atom.atom_index});
|
||||
@ -346,11 +353,6 @@ pub const Flags = packed struct {
|
||||
/// Whether the symbol is exported at runtime.
|
||||
@"export": bool = false,
|
||||
|
||||
/// Whether the symbol is effectively an extern and takes part in global
|
||||
/// symbol resolution. Then, its name will be saved in global string interning
|
||||
/// table.
|
||||
global: bool = false,
|
||||
|
||||
/// Whether this symbol is weak.
|
||||
weak: bool = false,
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user