| author | |
| committer | |
| log | b9bac32a2562985ca7a67877169343975fd8f851 |
| tree | bf0f26530abc99fee00ba73d2e0a9de1e27f8dfc |
| parent | c59583e43de35e91ac194860cd1eb63e61c272aa |
5 files changed, 266 insertions(+), 163 deletions(-)
src/link/MachO.zig+139-32| ... | @@ -22,16 +22,10 @@ dylibs: std.ArrayListUnmanaged(File.Index) = .{}, | ... | @@ -22,16 +22,10 @@ dylibs: std.ArrayListUnmanaged(File.Index) = .{}, |
| 22 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, | 22 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, |
| 23 | sections: std.MultiArrayList(Section) = .{}, | 23 | sections: std.MultiArrayList(Section) = .{}, |
| 24 | 24 | ||
| 25 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | 25 | resolver: SymbolResolver = .{}, |
| 26 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 27 | symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 28 | globals: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, | ||
| 29 | /// This table will be populated after `scanRelocs` has run. | 26 | /// This table will be populated after `scanRelocs` has run. |
| 30 | /// Key is symbol index. | 27 | /// Key is symbol index. |
| 31 | undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Atom.Index)) = .{}, | 28 | undefs: std.AutoHashMapUnmanaged(Ref, std.ArrayListUnmanaged(Ref)) = .{}, |
| 32 | /// Global symbols we need to resolve for the link to succeed. | ||
| 33 | undefined_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 34 | boundary_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 35 | 29 | ||
| 36 | dyld_info_cmd: macho.dyld_info_command = .{}, | 30 | dyld_info_cmd: macho.dyld_info_command = .{}, |
| 37 | symtab_cmd: macho.symtab_command = .{}, | 31 | symtab_cmd: macho.symtab_command = .{}, |
| ... | @@ -55,19 +49,8 @@ eh_frame_sect_index: ?u8 = null, | ... | @@ -55,19 +49,8 @@ eh_frame_sect_index: ?u8 = null, |
| 55 | unwind_info_sect_index: ?u8 = null, | 49 | unwind_info_sect_index: ?u8 = null, |
| 56 | objc_stubs_sect_index: ?u8 = null, | 50 | objc_stubs_sect_index: ?u8 = null, |
| 57 | 51 | ||
| 58 | mh_execute_header_index: ?Symbol.Index = null, | ||
| 59 | mh_dylib_header_index: ?Symbol.Index = null, | ||
| 60 | dyld_private_index: ?Symbol.Index = null, | ||
| 61 | dyld_stub_binder_index: ?Symbol.Index = null, | ||
| 62 | dso_handle_index: ?Symbol.Index = null, | ||
| 63 | objc_msg_send_index: ?Symbol.Index = null, | ||
| 64 | entry_index: ?Symbol.Index = null, | ||
| 65 | |||
| 66 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, | 52 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| 67 | 53 | ||
| 68 | /// String interning table | ||
| 69 | strings: StringTable = .{}, | ||
| 70 | |||
| 71 | /// Output synthetic sections | 54 | /// Output synthetic sections |
| 72 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 55 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 73 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 56 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -4196,7 +4179,7 @@ const Section = struct { | ... | @@ -4196,7 +4179,7 @@ const Section = struct { |
| 4196 | pub const LiteralPool = struct { | 4179 | pub const LiteralPool = struct { |
| 4197 | table: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | 4180 | table: std.AutoArrayHashMapUnmanaged(void, void) = .{}, |
| 4198 | keys: std.ArrayListUnmanaged(Key) = .{}, | 4181 | keys: std.ArrayListUnmanaged(Key) = .{}, |
| 4199 | values: std.ArrayListUnmanaged(Atom.Index) = .{}, | 4182 | values: std.ArrayListUnmanaged(MachO.Ref) = .{}, |
| 4200 | data: std.ArrayListUnmanaged(u8) = .{}, | 4183 | data: std.ArrayListUnmanaged(u8) = .{}, |
| 4201 | 4184 | ||
| 4202 | pub fn deinit(lp: *LiteralPool, allocator: Allocator) void { | 4185 | pub fn deinit(lp: *LiteralPool, allocator: Allocator) void { |
| ... | @@ -4206,17 +4189,21 @@ pub const LiteralPool = struct { | ... | @@ -4206,17 +4189,21 @@ pub const LiteralPool = struct { |
| 4206 | lp.data.deinit(allocator); | 4189 | lp.data.deinit(allocator); |
| 4207 | } | 4190 | } |
| 4208 | 4191 | ||
| 4209 | pub fn getAtom(lp: LiteralPool, index: Index, macho_file: *MachO) *Atom { | ||
| 4210 | assert(index < lp.values.items.len); | ||
| 4211 | return macho_file.getAtom(lp.values.items[index]).?; | ||
| 4212 | } | ||
| 4213 | |||
| 4214 | const InsertResult = struct { | 4192 | const InsertResult = struct { |
| 4215 | found_existing: bool, | 4193 | found_existing: bool, |
| 4216 | index: Index, | 4194 | index: Index, |
| 4217 | atom: *Atom.Index, | 4195 | ref: *MachO.Ref, |
| 4218 | }; | 4196 | }; |
| 4219 | 4197 | ||
| 4198 | pub fn getSymbolRef(lp: LiteralPool, index: Index) MachO.Ref { | ||
| 4199 | assert(index < lp.values.items.len); | ||
| 4200 | return lp.values.items[index]; | ||
| 4201 | } | ||
| 4202 | |||
| 4203 | pub fn getSymbol(lp: LiteralPool, index: Index, macho_file: *MachO) *Symbol { | ||
| 4204 | return lp.getSymbolRef(index).getSymbol(macho_file).?; | ||
| 4205 | } | ||
| 4206 | |||
| 4220 | pub fn insert(lp: *LiteralPool, allocator: Allocator, @"type": u8, string: []const u8) !InsertResult { | 4207 | pub fn insert(lp: *LiteralPool, allocator: Allocator, @"type": u8, string: []const u8) !InsertResult { |
| 4221 | const size: u32 = @intCast(string.len); | 4208 | const size: u32 = @intCast(string.len); |
| 4222 | try lp.data.ensureUnusedCapacity(allocator, size); | 4209 | try lp.data.ensureUnusedCapacity(allocator, size); |
| ... | @@ -4278,12 +4265,6 @@ const HotUpdateState = struct { | ... | @@ -4278,12 +4265,6 @@ const HotUpdateState = struct { |
| 4278 | mach_task: ?std.c.MachTask = null, | 4265 | mach_task: ?std.c.MachTask = null, |
| 4279 | }; | 4266 | }; |
| 4280 | 4267 | ||
| 4281 | pub const DynamicRelocs = struct { | ||
| 4282 | rebase_relocs: u32 = 0, | ||
| 4283 | bind_relocs: u32 = 0, | ||
| 4284 | weak_bind_relocs: u32 = 0, | ||
| 4285 | }; | ||
| 4286 | |||
| 4287 | pub const SymtabCtx = struct { | 4268 | pub const SymtabCtx = struct { |
| 4288 | ilocal: u32 = 0, | 4269 | ilocal: u32 = 0, |
| 4289 | istab: u32 = 0, | 4270 | istab: u32 = 0, |
| ... | @@ -4293,6 +4274,7 @@ pub const SymtabCtx = struct { | ... | @@ -4293,6 +4274,7 @@ pub const SymtabCtx = struct { |
| 4293 | nstabs: u32 = 0, | 4274 | nstabs: u32 = 0, |
| 4294 | nexports: u32 = 0, | 4275 | nexports: u32 = 0, |
| 4295 | nimports: u32 = 0, | 4276 | nimports: u32 = 0, |
| 4277 | stroff: u32 = 0, | ||
| 4296 | strsize: u32 = 0, | 4278 | strsize: u32 = 0, |
| 4297 | }; | 4279 | }; |
| 4298 | 4280 | ||
| ... | @@ -4579,6 +4561,131 @@ const UndefinedTreatment = enum { | ... | @@ -4579,6 +4561,131 @@ const UndefinedTreatment = enum { |
| 4579 | dynamic_lookup, | 4561 | dynamic_lookup, |
| 4580 | }; | 4562 | }; |
| 4581 | 4563 | ||
| 4564 | /// A reference to atom or symbol in an input file. | ||
| 4565 | /// If file == 0, symbol is an undefined global. | ||
| 4566 | pub const Ref = struct { | ||
| 4567 | index: u32, | ||
| 4568 | file: File.Index, | ||
| 4569 | |||
| 4570 | pub fn eql(ref: Ref, other: Ref) bool { | ||
| 4571 | return ref.index == other.index and ref.file == other.file; | ||
| 4572 | } | ||
| 4573 | |||
| 4574 | pub fn getFile(ref: Ref, macho_file: *MachO) ?File { | ||
| 4575 | return macho_file.getFile(ref.file); | ||
| 4576 | } | ||
| 4577 | |||
| 4578 | pub fn getAtom(ref: Ref, macho_file: *MachO) ?*Atom { | ||
| 4579 | const file = ref.getFile(macho_file) orelse return null; | ||
| 4580 | return file.getAtom(ref.index); | ||
| 4581 | } | ||
| 4582 | |||
| 4583 | pub fn getSymbol(ref: Ref, macho_file: *MachO) ?*Symbol { | ||
| 4584 | const file = ref.getFile(macho_file) orelse return null; | ||
| 4585 | return switch (file) { | ||
| 4586 | inline else => |x| &x.symbols.items[ref.index], | ||
| 4587 | }; | ||
| 4588 | } | ||
| 4589 | |||
| 4590 | pub fn format( | ||
| 4591 | ref: Ref, | ||
| 4592 | comptime unused_fmt_string: []const u8, | ||
| 4593 | options: std.fmt.FormatOptions, | ||
| 4594 | writer: anytype, | ||
| 4595 | ) !void { | ||
| 4596 | _ = unused_fmt_string; | ||
| 4597 | _ = options; | ||
| 4598 | try writer.print("%{d} in file({d})", .{ ref.index, ref.file }); | ||
| 4599 | } | ||
| 4600 | }; | ||
| 4601 | |||
| 4602 | pub const SymbolResolver = struct { | ||
| 4603 | keys: std.ArrayListUnmanaged(Key) = .{}, | ||
| 4604 | values: std.ArrayListUnmanaged(Ref) = .{}, | ||
| 4605 | table: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | ||
| 4606 | |||
| 4607 | const Result = struct { | ||
| 4608 | found_existing: bool, | ||
| 4609 | index: Index, | ||
| 4610 | ref: *Ref, | ||
| 4611 | }; | ||
| 4612 | |||
| 4613 | pub fn deinit(resolver: *SymbolResolver, allocator: Allocator) void { | ||
| 4614 | resolver.keys.deinit(allocator); | ||
| 4615 | resolver.values.deinit(allocator); | ||
| 4616 | resolver.table.deinit(allocator); | ||
| 4617 | } | ||
| 4618 | |||
| 4619 | pub fn getOrPut( | ||
| 4620 | resolver: *SymbolResolver, | ||
| 4621 | allocator: Allocator, | ||
| 4622 | ref: Ref, | ||
| 4623 | macho_file: *MachO, | ||
| 4624 | ) !Result { | ||
| 4625 | const adapter = Adapter{ .keys = resolver.keys.items, .macho_file = macho_file }; | ||
| 4626 | const key = Key{ .index = ref.index, .file = ref.file }; | ||
| 4627 | const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter); | ||
| 4628 | if (!gop.found_existing) { | ||
| 4629 | try resolver.keys.append(allocator, key); | ||
| 4630 | _ = try resolver.values.addOne(allocator); | ||
| 4631 | } | ||
| 4632 | return .{ | ||
| 4633 | .found_existing = gop.found_existing, | ||
| 4634 | .index = @intCast(gop.index + 1), | ||
| 4635 | .ref = &resolver.values.items[gop.index], | ||
| 4636 | }; | ||
| 4637 | } | ||
| 4638 | |||
| 4639 | pub fn get(resolver: SymbolResolver, index: Index) ?Ref { | ||
| 4640 | if (index == 0) return null; | ||
| 4641 | return resolver.values.items[index - 1]; | ||
| 4642 | } | ||
| 4643 | |||
| 4644 | pub fn reset(resolver: *SymbolResolver) void { | ||
| 4645 | resolver.keys.clearRetainingCapacity(); | ||
| 4646 | resolver.values.clearRetainingCapacity(); | ||
| 4647 | resolver.table.clearRetainingCapacity(); | ||
| 4648 | } | ||
| 4649 | |||
| 4650 | const Key = struct { | ||
| 4651 | index: Symbol.Index, | ||
| 4652 | file: File.Index, | ||
| 4653 | |||
| 4654 | fn getName(key: Key, macho_file: *MachO) [:0]const u8 { | ||
| 4655 | const ref = Ref{ .index = key.index, .file = key.file }; | ||
| 4656 | return ref.getSymbol(macho_file).?.getName(macho_file); | ||
| 4657 | } | ||
| 4658 | |||
| 4659 | fn eql(key: Key, other: Key, macho_file: *MachO) bool { | ||
| 4660 | const key_name = key.getName(macho_file); | ||
| 4661 | const other_name = other.getName(macho_file); | ||
| 4662 | return mem.eql(u8, key_name, other_name); | ||
| 4663 | } | ||
| 4664 | |||
| 4665 | fn hash(key: Key, macho_file: *MachO) u32 { | ||
| 4666 | const name = key.getName(macho_file); | ||
| 4667 | return @truncate(Hash.hash(0, name)); | ||
| 4668 | } | ||
| 4669 | }; | ||
| 4670 | |||
| 4671 | const Adapter = struct { | ||
| 4672 | keys: []const Key, | ||
| 4673 | macho_file: *MachO, | ||
| 4674 | |||
| 4675 | pub fn eql(ctx: @This(), key: Key, b_void: void, b_map_index: usize) bool { | ||
| 4676 | _ = b_void; | ||
| 4677 | const other = ctx.keys[b_map_index]; | ||
| 4678 | return key.eql(other, ctx.macho_file); | ||
| 4679 | } | ||
| 4680 | |||
| 4681 | pub fn hash(ctx: @This(), key: Key) u32 { | ||
| 4682 | return key.hash(ctx.macho_file); | ||
| 4683 | } | ||
| 4684 | }; | ||
| 4685 | |||
| 4686 | pub const Index = u32; | ||
| 4687 | }; | ||
| 4688 | |||
| 4582 | const MachO = @This(); | 4689 | const MachO = @This(); |
| 4583 | 4690 | ||
| 4584 | const std = @import("std"); | 4691 | const std = @import("std"); |
src/link/MachO/Atom.zig+74-92| ... | @@ -47,16 +47,6 @@ pub fn getFile(self: Atom, macho_file: *MachO) File { | ... | @@ -47,16 +47,6 @@ pub fn getFile(self: Atom, macho_file: *MachO) File { |
| 47 | return macho_file.getFile(self.file).?; | 47 | return macho_file.getFile(self.file).?; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | pub fn getData(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ||
| 51 | assert(buffer.len == self.size); | ||
| 52 | switch (self.getFile(macho_file)) { | ||
| 53 | .internal => |x| try x.getAtomData(self, buffer), | ||
| 54 | .object => |x| try x.getAtomData(macho_file, self, buffer), | ||
| 55 | .zig_object => |x| try x.getAtomData(macho_file, self, buffer), | ||
| 56 | else => unreachable, | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | pub fn getRelocs(self: Atom, macho_file: *MachO) []const Relocation { | 50 | pub fn getRelocs(self: Atom, macho_file: *MachO) []const Relocation { |
| 61 | return switch (self.getFile(macho_file)) { | 51 | return switch (self.getFile(macho_file)) { |
| 62 | .dylib => unreachable, | 52 | .dylib => unreachable, |
| ... | @@ -88,8 +78,7 @@ pub fn getPriority(self: Atom, macho_file: *MachO) u64 { | ... | @@ -88,8 +78,7 @@ pub fn getPriority(self: Atom, macho_file: *MachO) u64 { |
| 88 | } | 78 | } |
| 89 | 79 | ||
| 90 | pub fn getUnwindRecords(self: Atom, macho_file: *MachO) []const UnwindInfo.Record.Index { | 80 | pub fn getUnwindRecords(self: Atom, macho_file: *MachO) []const UnwindInfo.Record.Index { |
| 91 | if (!self.flags.unwind) return &[0]UnwindInfo.Record.Index{}; | 81 | const extra = self.getExtra(macho_file); |
| 92 | const extra = self.getExtra(macho_file).?; | ||
| 93 | return switch (self.getFile(macho_file)) { | 82 | return switch (self.getFile(macho_file)) { |
| 94 | .dylib => unreachable, | 83 | .dylib => unreachable, |
| 95 | .zig_object, .internal => &[0]UnwindInfo.Record.Index{}, | 84 | .zig_object, .internal => &[0]UnwindInfo.Record.Index{}, |
| ... | @@ -110,44 +99,39 @@ pub fn markUnwindRecordsDead(self: Atom, macho_file: *MachO) void { | ... | @@ -110,44 +99,39 @@ pub fn markUnwindRecordsDead(self: Atom, macho_file: *MachO) void { |
| 110 | } | 99 | } |
| 111 | 100 | ||
| 112 | pub fn getThunk(self: Atom, macho_file: *MachO) *Thunk { | 101 | pub fn getThunk(self: Atom, macho_file: *MachO) *Thunk { |
| 113 | assert(self.flags.thunk); | 102 | const extra = self.getExtra(macho_file); |
| 114 | const extra = self.getExtra(macho_file).?; | ||
| 115 | return macho_file.getThunk(extra.thunk); | 103 | return macho_file.getThunk(extra.thunk); |
| 116 | } | 104 | } |
| 117 | 105 | ||
| 118 | pub fn getLiteralPoolIndex(self: Atom, macho_file: *MachO) ?MachO.LiteralPool.Index { | ||
| 119 | if (!self.flags.literal_pool) return null; | ||
| 120 | return self.getExtra(macho_file).?.literal_index; | ||
| 121 | } | ||
| 122 | |||
| 123 | const AddExtraOpts = struct { | 106 | const AddExtraOpts = struct { |
| 124 | thunk: ?u32 = null, | 107 | thunk: ?u32 = null, |
| 125 | rel_index: ?u32 = null, | 108 | rel_index: ?u32 = null, |
| 126 | rel_count: ?u32 = null, | 109 | rel_count: ?u32 = null, |
| 110 | rel_out_index: ?u32 = null, | ||
| 111 | rel_out_count: ?u32 = null, | ||
| 127 | unwind_index: ?u32 = null, | 112 | unwind_index: ?u32 = null, |
| 128 | unwind_count: ?u32 = null, | 113 | unwind_count: ?u32 = null, |
| 129 | literal_index: ?u32 = null, | 114 | literal_pool_index: ?u32 = null, |
| 115 | literal_symbol_index: ?u32 = null, | ||
| 130 | }; | 116 | }; |
| 131 | 117 | ||
| 132 | pub fn addExtra(atom: *Atom, opts: AddExtraOpts, macho_file: *MachO) !void { | 118 | pub fn addExtra(atom: *Atom, opts: AddExtraOpts, macho_file: *MachO) void { |
| 133 | if (atom.getExtra(macho_file) == null) { | 119 | const file = atom.getFile(macho_file); |
| 134 | atom.extra = try macho_file.addAtomExtra(.{}); | 120 | var extra = file.getAtomExtra(atom.extra); |
| 135 | } | ||
| 136 | var extra = atom.getExtra(macho_file).?; | ||
| 137 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { | 121 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { |
| 138 | if (@field(opts, field.name)) |x| { | 122 | if (@field(opts, field.name)) |x| { |
| 139 | @field(extra, field.name) = x; | 123 | @field(extra, field.name) = x; |
| 140 | } | 124 | } |
| 141 | } | 125 | } |
| 142 | atom.setExtra(extra, macho_file); | 126 | file.setAtomExtra(atom.extra, extra); |
| 143 | } | 127 | } |
| 144 | 128 | ||
| 145 | pub inline fn getExtra(atom: Atom, macho_file: *MachO) ?Extra { | 129 | pub inline fn getExtra(atom: Atom, macho_file: *MachO) Extra { |
| 146 | return macho_file.getAtomExtra(atom.extra); | 130 | return atom.getFile(macho_file).getAtomExtra(atom.extra); |
| 147 | } | 131 | } |
| 148 | 132 | ||
| 149 | pub inline fn setExtra(atom: Atom, extra: Extra, macho_file: *MachO) void { | 133 | pub inline fn setExtra(atom: Atom, extra: Extra, macho_file: *MachO) void { |
| 150 | macho_file.setAtomExtra(atom.extra, extra); | 134 | atom.getFile(macho_file).setAtomExtra(atom.extra, extra); |
| 151 | } | 135 | } |
| 152 | 136 | ||
| 153 | pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 { | 137 | pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 { |
| ... | @@ -467,7 +451,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -467,7 +451,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 467 | 451 | ||
| 468 | switch (rel.type) { | 452 | switch (rel.type) { |
| 469 | .branch => { | 453 | .branch => { |
| 470 | const symbol = rel.getTargetSymbol(macho_file); | 454 | const symbol = rel.getTargetSymbol(self, macho_file); |
| 471 | if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) { | 455 | if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) { |
| 472 | symbol.flags.stubs = true; | 456 | symbol.flags.stubs = true; |
| 473 | if (symbol.flags.weak) { | 457 | if (symbol.flags.weak) { |
| ... | @@ -482,7 +466,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -482,7 +466,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 482 | .got_load_page, | 466 | .got_load_page, |
| 483 | .got_load_pageoff, | 467 | .got_load_pageoff, |
| 484 | => { | 468 | => { |
| 485 | const symbol = rel.getTargetSymbol(macho_file); | 469 | const symbol = rel.getTargetSymbol(self, macho_file); |
| 486 | if (symbol.flags.import or | 470 | if (symbol.flags.import or |
| 487 | (symbol.flags.@"export" and symbol.flags.weak) or | 471 | (symbol.flags.@"export" and symbol.flags.weak) or |
| 488 | symbol.flags.interposable or | 472 | symbol.flags.interposable or |
| ... | @@ -496,18 +480,18 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -496,18 +480,18 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 496 | }, | 480 | }, |
| 497 | 481 | ||
| 498 | .zig_got_load => { | 482 | .zig_got_load => { |
| 499 | assert(rel.getTargetSymbol(macho_file).flags.has_zig_got); | 483 | assert(rel.getTargetSymbol(self, macho_file).flags.has_zig_got); |
| 500 | }, | 484 | }, |
| 501 | 485 | ||
| 502 | .got => { | 486 | .got => { |
| 503 | rel.getTargetSymbol(macho_file).flags.needs_got = true; | 487 | rel.getTargetSymbol(self, macho_file).flags.needs_got = true; |
| 504 | }, | 488 | }, |
| 505 | 489 | ||
| 506 | .tlv, | 490 | .tlv, |
| 507 | .tlvp_page, | 491 | .tlvp_page, |
| 508 | .tlvp_pageoff, | 492 | .tlvp_pageoff, |
| 509 | => { | 493 | => { |
| 510 | const symbol = rel.getTargetSymbol(macho_file); | 494 | const symbol = rel.getTargetSymbol(self, macho_file); |
| 511 | if (!symbol.flags.tlv) { | 495 | if (!symbol.flags.tlv) { |
| 512 | try macho_file.reportParseError2( | 496 | try macho_file.reportParseError2( |
| 513 | self.getFile(macho_file).getIndex(), | 497 | self.getFile(macho_file).getIndex(), |
| ... | @@ -526,7 +510,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -526,7 +510,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 526 | .unsigned => { | 510 | .unsigned => { |
| 527 | if (rel.meta.length == 3) { // TODO this really should check if this is pointer width | 511 | if (rel.meta.length == 3) { // TODO this really should check if this is pointer width |
| 528 | if (rel.tag == .@"extern") { | 512 | if (rel.tag == .@"extern") { |
| 529 | const symbol = rel.getTargetSymbol(macho_file); | 513 | const symbol = rel.getTargetSymbol(self, macho_file); |
| 530 | if (symbol.isTlvInit(macho_file)) { | 514 | if (symbol.isTlvInit(macho_file)) { |
| 531 | macho_file.has_tlv = true; | 515 | macho_file.has_tlv = true; |
| 532 | continue; | 516 | continue; |
| ... | @@ -559,14 +543,15 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { | ... | @@ -559,14 +543,15 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 559 | fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { | 543 | fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { |
| 560 | if (rel.tag == .local) return false; | 544 | if (rel.tag == .local) return false; |
| 561 | 545 | ||
| 562 | const sym = rel.getTargetSymbol(macho_file); | 546 | const file = self.getFile(macho_file); |
| 563 | if (sym.getFile(macho_file) == null) { | 547 | const ref = file.getSymbolRef(rel.target, macho_file); |
| 548 | if (ref.getFile(macho_file) == null) { | ||
| 564 | const gpa = macho_file.base.comp.gpa; | 549 | const gpa = macho_file.base.comp.gpa; |
| 565 | const gop = try macho_file.undefs.getOrPut(gpa, rel.target); | 550 | const gop = try macho_file.undefs.getOrPut(gpa, .{ .index = rel.target, .file = self.file }); |
| 566 | if (!gop.found_existing) { | 551 | if (!gop.found_existing) { |
| 567 | gop.value_ptr.* = .{}; | 552 | gop.value_ptr.* = .{}; |
| 568 | } | 553 | } |
| 569 | try gop.value_ptr.append(gpa, self.atom_index); | 554 | try gop.value_ptr.append(gpa, .{ .index = self.atom_index, .file = self.file }); |
| 570 | return true; | 555 | return true; |
| 571 | } | 556 | } |
| 572 | 557 | ||
| ... | @@ -582,7 +567,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -582,7 +567,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 582 | const name = self.getName(macho_file); | 567 | const name = self.getName(macho_file); |
| 583 | const relocs = self.getRelocs(macho_file); | 568 | const relocs = self.getRelocs(macho_file); |
| 584 | 569 | ||
| 585 | relocs_log.debug("{x}: {s}", .{ self.getAddress(macho_file), name }); | 570 | relocs_log.debug("{x}: {s}", .{ self.value, name }); |
| 586 | 571 | ||
| 587 | var has_error = false; | 572 | var has_error = false; |
| 588 | var stream = std.io.fixedBufferStream(buffer); | 573 | var stream = std.io.fixedBufferStream(buffer); |
| ... | @@ -593,7 +578,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -593,7 +578,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 593 | const subtractor = if (rel.meta.has_subtractor) relocs[i - 1] else null; | 578 | const subtractor = if (rel.meta.has_subtractor) relocs[i - 1] else null; |
| 594 | 579 | ||
| 595 | if (rel.tag == .@"extern") { | 580 | if (rel.tag == .@"extern") { |
| 596 | if (rel.getTargetSymbol(macho_file).getFile(macho_file) == null) continue; | 581 | if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue; |
| 597 | } | 582 | } |
| 598 | 583 | ||
| 599 | try stream.seekTo(rel_offset); | 584 | try stream.seekTo(rel_offset); |
| ... | @@ -601,8 +586,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -601,8 +586,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 601 | switch (err) { | 586 | switch (err) { |
| 602 | error.RelaxFail => { | 587 | error.RelaxFail => { |
| 603 | const target = switch (rel.tag) { | 588 | const target = switch (rel.tag) { |
| 604 | .@"extern" => rel.getTargetSymbol(macho_file).getName(macho_file), | 589 | .@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file), |
| 605 | .local => rel.getTargetAtom(macho_file).getName(macho_file), | 590 | .local => rel.getTargetAtom(self, macho_file).getName(macho_file), |
| 606 | }; | 591 | }; |
| 607 | try macho_file.reportParseError2( | 592 | try macho_file.reportParseError2( |
| 608 | file.getIndex(), | 593 | file.getIndex(), |
| ... | @@ -642,12 +627,12 @@ fn resolveRelocInner( | ... | @@ -642,12 +627,12 @@ fn resolveRelocInner( |
| 642 | const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow; | 627 | const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow; |
| 643 | const P = @as(i64, @intCast(self.getAddress(macho_file))) + @as(i64, @intCast(rel_offset)); | 628 | const P = @as(i64, @intCast(self.getAddress(macho_file))) + @as(i64, @intCast(rel_offset)); |
| 644 | const A = rel.addend + rel.getRelocAddend(cpu_arch); | 629 | const A = rel.addend + rel.getRelocAddend(cpu_arch); |
| 645 | const S: i64 = @intCast(rel.getTargetAddress(macho_file)); | 630 | const S: i64 = @intCast(rel.getTargetAddress(self, macho_file)); |
| 646 | const G: i64 = @intCast(rel.getGotTargetAddress(macho_file)); | 631 | const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file)); |
| 647 | const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); | 632 | const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); |
| 648 | const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(macho_file))) else 0; | 633 | const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0; |
| 649 | // Address of the __got_zig table entry if any. | 634 | // Address of the __got_zig table entry if any. |
| 650 | const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file))); | 635 | const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(self, macho_file))); |
| 651 | 636 | ||
| 652 | const divExact = struct { | 637 | const divExact = struct { |
| 653 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { | 638 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { |
| ... | @@ -668,7 +653,7 @@ fn resolveRelocInner( | ... | @@ -668,7 +653,7 @@ fn resolveRelocInner( |
| 668 | rel_offset, | 653 | rel_offset, |
| 669 | @tagName(rel.type), | 654 | @tagName(rel.type), |
| 670 | S + A - SUB, | 655 | S + A - SUB, |
| 671 | rel.getTargetAtom(macho_file).atom_index, | 656 | rel.getTargetAtom(self, macho_file).atom_index, |
| 672 | }), | 657 | }), |
| 673 | .@"extern" => relocs_log.debug(" {x}<+{d}>: {s}: [=> {x}] G({x}) ZG({x}) ({s})", .{ | 658 | .@"extern" => relocs_log.debug(" {x}<+{d}>: {s}: [=> {x}] G({x}) ZG({x}) ({s})", .{ |
| 674 | P, | 659 | P, |
| ... | @@ -677,7 +662,7 @@ fn resolveRelocInner( | ... | @@ -677,7 +662,7 @@ fn resolveRelocInner( |
| 677 | S + A - SUB, | 662 | S + A - SUB, |
| 678 | G + A, | 663 | G + A, |
| 679 | ZIG_GOT + A, | 664 | ZIG_GOT + A, |
| 680 | rel.getTargetSymbol(macho_file).getName(macho_file), | 665 | rel.getTargetSymbol(self, macho_file).getName(macho_file), |
| 681 | }), | 666 | }), |
| 682 | } | 667 | } |
| 683 | 668 | ||
| ... | @@ -688,7 +673,7 @@ fn resolveRelocInner( | ... | @@ -688,7 +673,7 @@ fn resolveRelocInner( |
| 688 | assert(!rel.meta.pcrel); | 673 | assert(!rel.meta.pcrel); |
| 689 | if (rel.meta.length == 3) { | 674 | if (rel.meta.length == 3) { |
| 690 | if (rel.tag == .@"extern") { | 675 | if (rel.tag == .@"extern") { |
| 691 | const sym = rel.getTargetSymbol(macho_file); | 676 | const sym = rel.getTargetSymbol(self, macho_file); |
| 692 | if (sym.isTlvInit(macho_file)) { | 677 | if (sym.isTlvInit(macho_file)) { |
| 693 | try writer.writeInt(u64, @intCast(S - TLS), .little); | 678 | try writer.writeInt(u64, @intCast(S - TLS), .little); |
| 694 | return; | 679 | return; |
| ... | @@ -718,7 +703,7 @@ fn resolveRelocInner( | ... | @@ -718,7 +703,7 @@ fn resolveRelocInner( |
| 718 | .aarch64 => { | 703 | .aarch64 => { |
| 719 | const disp: i28 = math.cast(i28, S + A - P) orelse blk: { | 704 | const disp: i28 = math.cast(i28, S + A - P) orelse blk: { |
| 720 | const thunk = self.getThunk(macho_file); | 705 | const thunk = self.getThunk(macho_file); |
| 721 | const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file)); | 706 | const S_: i64 = @intCast(thunk.getTargetAddress(rel.getTargetSymbolRef(self, macho_file), macho_file)); |
| 722 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; | 707 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; |
| 723 | }; | 708 | }; |
| 724 | aarch64.writeBranchImm(disp, code[rel_offset..][0..4]); | 709 | aarch64.writeBranchImm(disp, code[rel_offset..][0..4]); |
| ... | @@ -731,7 +716,7 @@ fn resolveRelocInner( | ... | @@ -731,7 +716,7 @@ fn resolveRelocInner( |
| 731 | assert(rel.tag == .@"extern"); | 716 | assert(rel.tag == .@"extern"); |
| 732 | assert(rel.meta.length == 2); | 717 | assert(rel.meta.length == 2); |
| 733 | assert(rel.meta.pcrel); | 718 | assert(rel.meta.pcrel); |
| 734 | if (rel.getTargetSymbol(macho_file).flags.has_got) { | 719 | if (rel.getTargetSymbol(self, macho_file).flags.has_got) { |
| 735 | try writer.writeInt(i32, @intCast(G + A - P), .little); | 720 | try writer.writeInt(i32, @intCast(G + A - P), .little); |
| 736 | } else { | 721 | } else { |
| 737 | try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file); | 722 | try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file); |
| ... | @@ -754,7 +739,7 @@ fn resolveRelocInner( | ... | @@ -754,7 +739,7 @@ fn resolveRelocInner( |
| 754 | assert(rel.tag == .@"extern"); | 739 | assert(rel.tag == .@"extern"); |
| 755 | assert(rel.meta.length == 2); | 740 | assert(rel.meta.length == 2); |
| 756 | assert(rel.meta.pcrel); | 741 | assert(rel.meta.pcrel); |
| 757 | const sym = rel.getTargetSymbol(macho_file); | 742 | const sym = rel.getTargetSymbol(self, macho_file); |
| 758 | if (sym.flags.tlv_ptr) { | 743 | if (sym.flags.tlv_ptr) { |
| 759 | const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file)); | 744 | const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file)); |
| 760 | try writer.writeInt(i32, @intCast(S_ + A - P), .little); | 745 | try writer.writeInt(i32, @intCast(S_ + A - P), .little); |
| ... | @@ -777,7 +762,7 @@ fn resolveRelocInner( | ... | @@ -777,7 +762,7 @@ fn resolveRelocInner( |
| 777 | assert(rel.tag == .@"extern"); | 762 | assert(rel.tag == .@"extern"); |
| 778 | assert(rel.meta.length == 2); | 763 | assert(rel.meta.length == 2); |
| 779 | assert(rel.meta.pcrel); | 764 | assert(rel.meta.pcrel); |
| 780 | const sym = rel.getTargetSymbol(macho_file); | 765 | const sym = rel.getTargetSymbol(self, macho_file); |
| 781 | const source = math.cast(u64, P) orelse return error.Overflow; | 766 | const source = math.cast(u64, P) orelse return error.Overflow; |
| 782 | const target = target: { | 767 | const target = target: { |
| 783 | const target = switch (rel.type) { | 768 | const target = switch (rel.type) { |
| ... | @@ -836,7 +821,7 @@ fn resolveRelocInner( | ... | @@ -836,7 +821,7 @@ fn resolveRelocInner( |
| 836 | assert(rel.meta.length == 2); | 821 | assert(rel.meta.length == 2); |
| 837 | assert(!rel.meta.pcrel); | 822 | assert(!rel.meta.pcrel); |
| 838 | 823 | ||
| 839 | const sym = rel.getTargetSymbol(macho_file); | 824 | const sym = rel.getTargetSymbol(self, macho_file); |
| 840 | const target = target: { | 825 | const target = target: { |
| 841 | const target = if (sym.flags.tlv_ptr) blk: { | 826 | const target = if (sym.flags.tlv_ptr) blk: { |
| 842 | const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file)); | 827 | const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file)); |
| ... | @@ -980,48 +965,47 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 { | ... | @@ -980,48 +965,47 @@ pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 { |
| 980 | } | 965 | } |
| 981 | } | 966 | } |
| 982 | 967 | ||
| 983 | pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.ArrayList(macho.relocation_info)) !void { | 968 | pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.relocation_info) !void { |
| 984 | const tracy = trace(@src()); | 969 | const tracy = trace(@src()); |
| 985 | defer tracy.end(); | 970 | defer tracy.end(); |
| 986 | 971 | ||
| 987 | const cpu_arch = macho_file.getTarget().cpu.arch; | 972 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 988 | const relocs = self.getRelocs(macho_file); | 973 | const relocs = self.getRelocs(macho_file); |
| 989 | var stream = std.io.fixedBufferStream(code); | ||
| 990 | 974 | ||
| 975 | var i: usize = 0; | ||
| 991 | for (relocs) |rel| { | 976 | for (relocs) |rel| { |
| 977 | defer i += 1; | ||
| 992 | const rel_offset = rel.offset - self.off; | 978 | const rel_offset = rel.offset - self.off; |
| 993 | const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow; | 979 | const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow; |
| 994 | const r_symbolnum = r_symbolnum: { | 980 | const r_symbolnum = r_symbolnum: { |
| 995 | const r_symbolnum: u32 = switch (rel.tag) { | 981 | const r_symbolnum: u32 = switch (rel.tag) { |
| 996 | .local => rel.getTargetAtom(macho_file).out_n_sect + 1, | 982 | .local => rel.getTargetAtom(self, macho_file).out_n_sect + 1, |
| 997 | .@"extern" => rel.getTargetSymbol(macho_file).getOutputSymtabIndex(macho_file).?, | 983 | .@"extern" => rel.getTargetSymbol(self, macho_file).getOutputSymtabIndex(macho_file).?, |
| 998 | }; | 984 | }; |
| 999 | break :r_symbolnum math.cast(u24, r_symbolnum) orelse return error.Overflow; | 985 | break :r_symbolnum math.cast(u24, r_symbolnum) orelse return error.Overflow; |
| 1000 | }; | 986 | }; |
| 1001 | const r_extern = rel.tag == .@"extern"; | 987 | const r_extern = rel.tag == .@"extern"; |
| 1002 | var addend = rel.addend + rel.getRelocAddend(cpu_arch); | 988 | var addend = rel.addend + rel.getRelocAddend(cpu_arch); |
| 1003 | if (rel.tag == .local) { | 989 | if (rel.tag == .local) { |
| 1004 | const target: i64 = @intCast(rel.getTargetAddress(macho_file)); | 990 | const target: i64 = @intCast(rel.getTargetAddress(self, macho_file)); |
| 1005 | addend += target; | 991 | addend += target; |
| 1006 | } | 992 | } |
| 1007 | 993 | ||
| 1008 | try stream.seekTo(rel_offset); | ||
| 1009 | |||
| 1010 | switch (cpu_arch) { | 994 | switch (cpu_arch) { |
| 1011 | .aarch64 => { | 995 | .aarch64 => { |
| 1012 | if (rel.type == .unsigned) switch (rel.meta.length) { | 996 | if (rel.type == .unsigned) switch (rel.meta.length) { |
| 1013 | 0, 1 => unreachable, | 997 | 0, 1 => unreachable, |
| 1014 | 2 => try stream.writer().writeInt(i32, @truncate(addend), .little), | 998 | 2 => mem.writeInt(i32, code[rel_offset..][0..4], @truncate(addend), .little), |
| 1015 | 3 => try stream.writer().writeInt(i64, addend, .little), | 999 | 3 => mem.writeInt(i64, code[rel_offset..][0..8], addend, .little), |
| 1016 | } else if (addend > 0) { | 1000 | } else if (addend > 0) { |
| 1017 | buffer.appendAssumeCapacity(.{ | 1001 | buffer[i] = .{ |
| 1018 | .r_address = r_address, | 1002 | .r_address = r_address, |
| 1019 | .r_symbolnum = @bitCast(math.cast(i24, addend) orelse return error.Overflow), | 1003 | .r_symbolnum = @bitCast(math.cast(i24, addend) orelse return error.Overflow), |
| 1020 | .r_pcrel = 0, | 1004 | .r_pcrel = 0, |
| 1021 | .r_length = 2, | 1005 | .r_length = 2, |
| 1022 | .r_extern = 0, | 1006 | .r_extern = 0, |
| 1023 | .r_type = @intFromEnum(macho.reloc_type_arm64.ARM64_RELOC_ADDEND), | 1007 | .r_type = @intFromEnum(macho.reloc_type_arm64.ARM64_RELOC_ADDEND), |
| 1024 | }); | 1008 | }; |
| 1025 | } | 1009 | } |
| 1026 | 1010 | ||
| 1027 | const r_type: macho.reloc_type_arm64 = switch (rel.type) { | 1011 | 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 | ... | @@ -1045,14 +1029,14 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra |
| 1045 | .tlv, | 1029 | .tlv, |
| 1046 | => unreachable, | 1030 | => unreachable, |
| 1047 | }; | 1031 | }; |
| 1048 | buffer.appendAssumeCapacity(.{ | 1032 | buffer[i] = .{ |
| 1049 | .r_address = r_address, | 1033 | .r_address = r_address, |
| 1050 | .r_symbolnum = r_symbolnum, | 1034 | .r_symbolnum = r_symbolnum, |
| 1051 | .r_pcrel = @intFromBool(rel.meta.pcrel), | 1035 | .r_pcrel = @intFromBool(rel.meta.pcrel), |
| 1052 | .r_extern = @intFromBool(r_extern), | 1036 | .r_extern = @intFromBool(r_extern), |
| 1053 | .r_length = rel.meta.length, | 1037 | .r_length = rel.meta.length, |
| 1054 | .r_type = @intFromEnum(r_type), | 1038 | .r_type = @intFromEnum(r_type), |
| 1055 | }); | 1039 | }; |
| 1056 | }, | 1040 | }, |
| 1057 | .x86_64 => { | 1041 | .x86_64 => { |
| 1058 | if (rel.meta.pcrel) { | 1042 | if (rel.meta.pcrel) { |
| ... | @@ -1064,8 +1048,8 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra | ... | @@ -1064,8 +1048,8 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra |
| 1064 | } | 1048 | } |
| 1065 | switch (rel.meta.length) { | 1049 | switch (rel.meta.length) { |
| 1066 | 0, 1 => unreachable, | 1050 | 0, 1 => unreachable, |
| 1067 | 2 => try stream.writer().writeInt(i32, @truncate(addend), .little), | 1051 | 2 => mem.writeInt(i32, code[rel_offset..][0..4], @truncate(addend), .little), |
| 1068 | 3 => try stream.writer().writeInt(i64, addend, .little), | 1052 | 3 => mem.writeInt(i64, code[rel_offset..][0..8], addend, .little), |
| 1069 | } | 1053 | } |
| 1070 | 1054 | ||
| 1071 | const r_type: macho.reloc_type_x86_64 = switch (rel.type) { | 1055 | 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 | ... | @@ -1089,18 +1073,20 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra |
| 1089 | .tlvp_pageoff, | 1073 | .tlvp_pageoff, |
| 1090 | => unreachable, | 1074 | => unreachable, |
| 1091 | }; | 1075 | }; |
| 1092 | buffer.appendAssumeCapacity(.{ | 1076 | buffer[i] = .{ |
| 1093 | .r_address = r_address, | 1077 | .r_address = r_address, |
| 1094 | .r_symbolnum = r_symbolnum, | 1078 | .r_symbolnum = r_symbolnum, |
| 1095 | .r_pcrel = @intFromBool(rel.meta.pcrel), | 1079 | .r_pcrel = @intFromBool(rel.meta.pcrel), |
| 1096 | .r_extern = @intFromBool(r_extern), | 1080 | .r_extern = @intFromBool(r_extern), |
| 1097 | .r_length = rel.meta.length, | 1081 | .r_length = rel.meta.length, |
| 1098 | .r_type = @intFromEnum(r_type), | 1082 | .r_type = @intFromEnum(r_type), |
| 1099 | }); | 1083 | }; |
| 1100 | }, | 1084 | }, |
| 1101 | else => unreachable, | 1085 | else => unreachable, |
| 1102 | } | 1086 | } |
| 1103 | } | 1087 | } |
| 1088 | |||
| 1089 | assert(i == buffer.len); | ||
| 1104 | } | 1090 | } |
| 1105 | 1091 | ||
| 1106 | pub fn format( | 1092 | pub fn format( |
| ... | @@ -1139,16 +1125,15 @@ fn format2( | ... | @@ -1139,16 +1125,15 @@ fn format2( |
| 1139 | const atom = ctx.atom; | 1125 | const atom = ctx.atom; |
| 1140 | const macho_file = ctx.macho_file; | 1126 | const macho_file = ctx.macho_file; |
| 1141 | const file = atom.getFile(macho_file); | 1127 | const file = atom.getFile(macho_file); |
| 1142 | try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d})", .{ | 1128 | try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{ |
| 1143 | atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file), | 1129 | atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file), |
| 1144 | atom.out_n_sect, atom.alignment, atom.size, | 1130 | atom.out_n_sect, atom.alignment, atom.size, |
| 1145 | atom.getRelocs(macho_file).len, | 1131 | atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk, |
| 1146 | }); | 1132 | }); |
| 1147 | if (atom.flags.thunk) try writer.print(" : thunk({d})", .{atom.getExtra(macho_file).?.thunk}); | ||
| 1148 | if (!atom.flags.alive) try writer.writeAll(" : [*]"); | 1133 | if (!atom.flags.alive) try writer.writeAll(" : [*]"); |
| 1149 | if (atom.flags.unwind) { | 1134 | if (atom.getUnwindRecords(macho_file).len > 0) { |
| 1150 | try writer.writeAll(" : unwind{ "); | 1135 | try writer.writeAll(" : unwind{ "); |
| 1151 | const extra = atom.getExtra(macho_file).?; | 1136 | const extra = atom.getExtra(macho_file); |
| 1152 | for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| { | 1137 | for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| { |
| 1153 | const rec = file.object.getUnwindRecord(index); | 1138 | const rec = file.object.getUnwindRecord(index); |
| 1154 | try writer.print("{d}", .{index}); | 1139 | try writer.print("{d}", .{index}); |
| ... | @@ -1167,18 +1152,6 @@ pub const Flags = packed struct { | ... | @@ -1167,18 +1152,6 @@ pub const Flags = packed struct { |
| 1167 | 1152 | ||
| 1168 | /// Specifies if this atom has been visited during garbage collection. | 1153 | /// Specifies if this atom has been visited during garbage collection. |
| 1169 | visited: bool = false, | 1154 | visited: bool = false, |
| 1170 | |||
| 1171 | /// Whether this atom has a range extension thunk. | ||
| 1172 | thunk: bool = false, | ||
| 1173 | |||
| 1174 | /// Whether this atom has any relocations. | ||
| 1175 | relocs: bool = false, | ||
| 1176 | |||
| 1177 | /// Whether this atom has any unwind records. | ||
| 1178 | unwind: bool = false, | ||
| 1179 | |||
| 1180 | /// Whether this atom has LiteralPool entry. | ||
| 1181 | literal_pool: bool = false, | ||
| 1182 | }; | 1155 | }; |
| 1183 | 1156 | ||
| 1184 | pub const Extra = struct { | 1157 | pub const Extra = struct { |
| ... | @@ -1191,6 +1164,12 @@ pub const Extra = struct { | ... | @@ -1191,6 +1164,12 @@ pub const Extra = struct { |
| 1191 | /// Count of relocations belonging to this atom. | 1164 | /// Count of relocations belonging to this atom. |
| 1192 | rel_count: u32 = 0, | 1165 | rel_count: u32 = 0, |
| 1193 | 1166 | ||
| 1167 | /// Start index of relocations being written out to file for this atom. | ||
| 1168 | rel_out_index: u32 = 0, | ||
| 1169 | |||
| 1170 | /// Count of relocations written out to file for this atom. | ||
| 1171 | rel_out_count: u32 = 0, | ||
| 1172 | |||
| 1194 | /// Start index of relocations belonging to this atom. | 1173 | /// Start index of relocations belonging to this atom. |
| 1195 | unwind_index: u32 = 0, | 1174 | unwind_index: u32 = 0, |
| 1196 | 1175 | ||
| ... | @@ -1198,7 +1177,10 @@ pub const Extra = struct { | ... | @@ -1198,7 +1177,10 @@ pub const Extra = struct { |
| 1198 | unwind_count: u32 = 0, | 1177 | unwind_count: u32 = 0, |
| 1199 | 1178 | ||
| 1200 | /// Index into LiteralPool entry for this atom. | 1179 | /// Index into LiteralPool entry for this atom. |
| 1201 | literal_index: u32 = 0, | 1180 | literal_pool_index: u32 = 0, |
| 1181 | |||
| 1182 | /// Index into the File's symbol table for local symbol representing this literal atom. | ||
| 1183 | literal_symbol_index: u32 = 0, | ||
| 1202 | }; | 1184 | }; |
| 1203 | 1185 | ||
| 1204 | pub const Alignment = @import("../../InternPool.zig").Alignment; | 1186 | pub const Alignment = @import("../../InternPool.zig").Alignment; |
src/link/MachO/InternalObject.zig+6| ... | @@ -639,6 +639,12 @@ pub fn asFile(self: *InternalObject) File { | ... | @@ -639,6 +639,12 @@ pub fn asFile(self: *InternalObject) File { |
| 639 | return .{ .internal = self }; | 639 | return .{ .internal = self }; |
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | pub fn getAtomRelocs(self: *const InternalObject, atom: Atom, macho_file: *MachO) []const Relocation { | ||
| 643 | const extra = atom.getExtra(macho_file).?; | ||
| 644 | const relocs = self.sections.items(.relocs)[atom.n_sect]; | ||
| 645 | return relocs.items[extra.rel_index..][0..extra.rel_count]; | ||
| 646 | } | ||
| 647 | |||
| 642 | fn addAtom(self: *InternalObject, allocator: Allocator) !Atom.Index { | 648 | fn addAtom(self: *InternalObject, allocator: Allocator) !Atom.Index { |
| 643 | const atom_index: Atom.Index = @intCast(self.atoms.items.len); | 649 | const atom_index: Atom.Index = @intCast(self.atoms.items.len); |
| 644 | const atom = try self.atoms.addOne(allocator); | 650 | const atom = try self.atoms.addOne(allocator); |
src/link/MachO/Object.zig+10-4| ... | @@ -1860,7 +1860,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { | ... | @@ -1860,7 +1860,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { |
| 1860 | const name = sym.getName(macho_file); | 1860 | const name = sym.getName(macho_file); |
| 1861 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; | 1861 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; |
| 1862 | } | 1862 | } |
| 1863 | const sect = macho_file.sections.items(.header)[sym.out_n_sect]; | 1863 | const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)]; |
| 1864 | if (sect.isCode()) { | 1864 | if (sect.isCode()) { |
| 1865 | self.output_symtab_ctx.nstabs += 4; // N_BNSYM, N_FUN, N_FUN, N_ENSYM | 1865 | self.output_symtab_ctx.nstabs += 4; // N_BNSYM, N_FUN, N_FUN, N_ENSYM |
| 1866 | } else if (sym.visibility == .global) { | 1866 | } else if (sym.visibility == .global) { |
| ... | @@ -2198,13 +2198,13 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { | ... | @@ -2198,13 +2198,13 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { |
| 2198 | const name = sym.getName(macho_file); | 2198 | const name = sym.getName(macho_file); |
| 2199 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; | 2199 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; |
| 2200 | } | 2200 | } |
| 2201 | const sect = macho_file.sections.items(.header)[sym.out_n_sect]; | 2201 | const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)]; |
| 2202 | const sym_n_strx = n_strx: { | 2202 | const sym_n_strx = n_strx: { |
| 2203 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; | 2203 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; |
| 2204 | const osym = macho_file.symtab.items[symtab_index]; | 2204 | const osym = macho_file.symtab.items[symtab_index]; |
| 2205 | break :n_strx osym.n_strx; | 2205 | break :n_strx osym.n_strx; |
| 2206 | }; | 2206 | }; |
| 2207 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; | 2207 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0; |
| 2208 | const sym_n_value = sym.getAddress(.{}, macho_file); | 2208 | const sym_n_value = sym.getAddress(.{}, macho_file); |
| 2209 | const sym_size = sym.getSize(macho_file); | 2209 | const sym_size = sym.getSize(macho_file); |
| 2210 | if (sect.isCode()) { | 2210 | if (sect.isCode()) { |
| ... | @@ -2299,7 +2299,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { | ... | @@ -2299,7 +2299,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { |
| 2299 | const osym = macho_file.symtab.items[symtab_index]; | 2299 | const osym = macho_file.symtab.items[symtab_index]; |
| 2300 | break :n_strx osym.n_strx; | 2300 | break :n_strx osym.n_strx; |
| 2301 | }; | 2301 | }; |
| 2302 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; | 2302 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0; |
| 2303 | const sym_n_value = sym.getAddress(.{}, macho_file); | 2303 | const sym_n_value = sym.getAddress(.{}, macho_file); |
| 2304 | const sym_size = sym.getSize(macho_file); | 2304 | const sym_size = sym.getSize(macho_file); |
| 2305 | if (stab.is_func) { | 2305 | if (stab.is_func) { |
| ... | @@ -2340,6 +2340,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { | ... | @@ -2340,6 +2340,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { |
| 2340 | } | 2340 | } |
| 2341 | } | 2341 | } |
| 2342 | 2342 | ||
| 2343 | pub fn getAtomRelocs(self: *const Object, atom: Atom, macho_file: *MachO) []const Relocation { | ||
| 2344 | const extra = atom.getExtra(macho_file).?; | ||
| 2345 | const relocs = self.sections.items(.relocs)[atom.n_sect]; | ||
| 2346 | return relocs.items[extra.rel_index..][0..extra.rel_count]; | ||
| 2347 | } | ||
| 2348 | |||
| 2343 | fn addString(self: *Object, allocator: Allocator, name: [:0]const u8) error{OutOfMemory}!u32 { | 2349 | fn addString(self: *Object, allocator: Allocator, name: [:0]const u8) error{OutOfMemory}!u32 { |
| 2344 | const off: u32 = @intCast(self.strtab.items.len); | 2350 | const off: u32 = @intCast(self.strtab.items.len); |
| 2345 | try self.strtab.ensureUnusedCapacity(allocator, name.len + 1); | 2351 | try self.strtab.ensureUnusedCapacity(allocator, name.len + 1); |
src/link/MachO/Symbol.zig+37-35| ... | @@ -9,17 +9,16 @@ name: u32 = 0, | ... | @@ -9,17 +9,16 @@ name: u32 = 0, |
| 9 | /// File where this symbol is defined. | 9 | /// File where this symbol is defined. |
| 10 | file: File.Index = 0, | 10 | file: File.Index = 0, |
| 11 | 11 | ||
| 12 | /// Atom containing this symbol if any. | 12 | /// Reference to Atom containing this symbol if any. |
| 13 | /// Index of 0 means there is no associated atom with this symbol. | ||
| 14 | /// Use `getAtom` to get the pointer to the atom. | 13 | /// Use `getAtom` to get the pointer to the atom. |
| 15 | atom: Atom.Index = 0, | 14 | atom_ref: MachO.Ref = .{ .index = 0, .file = 0 }, |
| 16 | 15 | ||
| 17 | /// Assigned output section index for this symbol. | 16 | /// Assigned output section index for this symbol. |
| 18 | out_n_sect: u8 = 0, | 17 | out_n_sect: u8 = 0, |
| 19 | 18 | ||
| 20 | /// Index of the source nlist this symbol references. | 19 | /// Index of the source nlist this symbol references. |
| 21 | /// Use `getNlist` to pull the nlist from the relevant file. | 20 | /// Use `getNlist` to pull the nlist from the relevant file. |
| 22 | nlist_idx: Index = 0, | 21 | nlist_idx: u32 = 0, |
| 23 | 22 | ||
| 24 | /// Misc flags for the symbol packaged as packed struct for compression. | 23 | /// Misc flags for the symbol packaged as packed struct for compression. |
| 25 | flags: Flags = .{}, | 24 | flags: Flags = .{}, |
| ... | @@ -55,16 +54,19 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool { | ... | @@ -55,16 +54,19 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool { |
| 55 | } | 54 | } |
| 56 | 55 | ||
| 57 | pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 { | 56 | pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 { |
| 58 | if (symbol.flags.global) return macho_file.strings.getAssumeExists(symbol.name); | ||
| 59 | return switch (symbol.getFile(macho_file).?) { | 57 | return switch (symbol.getFile(macho_file).?) { |
| 60 | .dylib => unreachable, // There are no local symbols for dylibs | ||
| 61 | .zig_object => |x| x.strtab.getAssumeExists(symbol.name), | 58 | .zig_object => |x| x.strtab.getAssumeExists(symbol.name), |
| 62 | inline else => |x| x.getString(symbol.name), | 59 | inline else => |x| x.getString(symbol.name), |
| 63 | }; | 60 | }; |
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom { | 63 | pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom { |
| 67 | return macho_file.getAtom(symbol.atom); | 64 | return symbol.atom_ref.getAtom(macho_file); |
| 65 | } | ||
| 66 | |||
| 67 | pub fn getOutputSectionIndex(symbol: Symbol, macho_file: *MachO) u8 { | ||
| 68 | if (symbol.getAtom(macho_file)) |atom| return atom.out_n_sect; | ||
| 69 | return symbol.out_n_sect; | ||
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File { | 72 | pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File { |
| ... | @@ -75,8 +77,10 @@ pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File { | ... | @@ -75,8 +77,10 @@ pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File { |
| 75 | pub fn getNlist(symbol: Symbol, macho_file: *MachO) macho.nlist_64 { | 77 | pub fn getNlist(symbol: Symbol, macho_file: *MachO) macho.nlist_64 { |
| 76 | const file = symbol.getFile(macho_file).?; | 78 | const file = symbol.getFile(macho_file).?; |
| 77 | return switch (file) { | 79 | return switch (file) { |
| 80 | .dylib => unreachable, | ||
| 81 | .zig_object => unreachable, | ||
| 78 | .object => |x| x.symtab.items(.nlist)[symbol.nlist_idx], | 82 | .object => |x| x.symtab.items(.nlist)[symbol.nlist_idx], |
| 79 | else => unreachable, | 83 | .internal => |x| x.symtab.items[symbol.nlist_idx], |
| 80 | }; | 84 | }; |
| 81 | } | 85 | } |
| 82 | 86 | ||
| ... | @@ -124,33 +128,35 @@ pub fn getAddress(symbol: Symbol, opts: struct { | ... | @@ -124,33 +128,35 @@ pub fn getAddress(symbol: Symbol, opts: struct { |
| 124 | 128 | ||
| 125 | pub fn getGotAddress(symbol: Symbol, macho_file: *MachO) u64 { | 129 | pub fn getGotAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 126 | if (!symbol.flags.has_got) return 0; | 130 | if (!symbol.flags.has_got) return 0; |
| 127 | const extra = symbol.getExtra(macho_file).?; | 131 | const extra = symbol.getExtra(macho_file); |
| 128 | return macho_file.got.getAddress(extra.got, macho_file); | 132 | return macho_file.got.getAddress(extra.got, macho_file); |
| 129 | } | 133 | } |
| 130 | 134 | ||
| 131 | pub fn getStubsAddress(symbol: Symbol, macho_file: *MachO) u64 { | 135 | pub fn getStubsAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 132 | if (!symbol.flags.stubs) return 0; | 136 | if (!symbol.flags.stubs) return 0; |
| 133 | const extra = symbol.getExtra(macho_file).?; | 137 | const extra = symbol.getExtra(macho_file); |
| 134 | return macho_file.stubs.getAddress(extra.stubs, macho_file); | 138 | return macho_file.stubs.getAddress(extra.stubs, macho_file); |
| 135 | } | 139 | } |
| 136 | 140 | ||
| 137 | pub fn getObjcStubsAddress(symbol: Symbol, macho_file: *MachO) u64 { | 141 | pub fn getObjcStubsAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 138 | if (!symbol.flags.objc_stubs) return 0; | 142 | if (!symbol.flags.objc_stubs) return 0; |
| 139 | const extra = symbol.getExtra(macho_file).?; | 143 | const extra = symbol.getExtra(macho_file); |
| 140 | return macho_file.objc_stubs.getAddress(extra.objc_stubs, macho_file); | 144 | return macho_file.objc_stubs.getAddress(extra.objc_stubs, macho_file); |
| 141 | } | 145 | } |
| 142 | 146 | ||
| 143 | pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 { | 147 | pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 144 | if (!symbol.flags.objc_stubs) return 0; | 148 | if (!symbol.flags.objc_stubs) return 0; |
| 145 | const extra = symbol.getExtra(macho_file).?; | 149 | const extra = symbol.getExtra(macho_file); |
| 146 | const atom = macho_file.getAtom(extra.objc_selrefs).?; | 150 | const file = symbol.getFile(macho_file).?; |
| 147 | assert(atom.flags.alive); | 151 | return switch (file) { |
| 148 | return atom.getAddress(macho_file); | 152 | .dylib, .zig_object => unreachable, |
| 153 | .object, .internal => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file), | ||
| 154 | }; | ||
| 149 | } | 155 | } |
| 150 | 156 | ||
| 151 | pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 { | 157 | pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 152 | if (!symbol.flags.tlv_ptr) return 0; | 158 | if (!symbol.flags.tlv_ptr) return 0; |
| 153 | const extra = symbol.getExtra(macho_file).?; | 159 | const extra = symbol.getExtra(macho_file); |
| 154 | return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file); | 160 | return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file); |
| 155 | } | 161 | } |
| 156 | 162 | ||
| ... | @@ -162,14 +168,14 @@ const GetOrCreateZigGotEntryResult = struct { | ... | @@ -162,14 +168,14 @@ const GetOrCreateZigGotEntryResult = struct { |
| 162 | pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult { | 168 | pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult { |
| 163 | assert(!macho_file.base.isRelocatable()); | 169 | assert(!macho_file.base.isRelocatable()); |
| 164 | assert(symbol.flags.needs_zig_got); | 170 | assert(symbol.flags.needs_zig_got); |
| 165 | if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).?.zig_got }; | 171 | if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got }; |
| 166 | const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file); | 172 | const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file); |
| 167 | return .{ .found_existing = false, .index = index }; | 173 | return .{ .found_existing = false, .index = index }; |
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 { | 176 | pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 171 | if (!symbol.flags.has_zig_got) return 0; | 177 | if (!symbol.flags.has_zig_got) return 0; |
| 172 | const extras = symbol.getExtra(macho_file).?; | 178 | const extras = symbol.getExtra(macho_file); |
| 173 | return macho_file.zig_got.entryAddress(extras.zig_got, macho_file); | 179 | return macho_file.zig_got.entryAddress(extras.zig_got, macho_file); |
| 174 | } | 180 | } |
| 175 | 181 | ||
| ... | @@ -202,11 +208,8 @@ const AddExtraOpts = struct { | ... | @@ -202,11 +208,8 @@ const AddExtraOpts = struct { |
| 202 | symtab: ?u32 = null, | 208 | symtab: ?u32 = null, |
| 203 | }; | 209 | }; |
| 204 | 210 | ||
| 205 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) !void { | 211 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void { |
| 206 | if (symbol.getExtra(macho_file) == null) { | 212 | var extra = symbol.getExtra(macho_file); |
| 207 | symbol.extra = try macho_file.addSymbolExtra(.{}); | ||
| 208 | } | ||
| 209 | var extra = symbol.getExtra(macho_file).?; | ||
| 210 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { | 213 | inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| { |
| 211 | if (@field(opts, field.name)) |x| { | 214 | if (@field(opts, field.name)) |x| { |
| 212 | @field(extra, field.name) = x; | 215 | @field(extra, field.name) = x; |
| ... | @@ -215,18 +218,22 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) !void { | ... | @@ -215,18 +218,22 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) !void { |
| 215 | symbol.setExtra(extra, macho_file); | 218 | symbol.setExtra(extra, macho_file); |
| 216 | } | 219 | } |
| 217 | 220 | ||
| 218 | pub inline fn getExtra(symbol: Symbol, macho_file: *MachO) ?Extra { | 221 | pub inline fn getExtra(symbol: Symbol, macho_file: *MachO) Extra { |
| 219 | return macho_file.getSymbolExtra(symbol.extra); | 222 | return switch (symbol.getFile(macho_file).?) { |
| 223 | inline else => |x| x.getSymbolExtra(symbol.extra), | ||
| 224 | }; | ||
| 220 | } | 225 | } |
| 221 | 226 | ||
| 222 | pub inline fn setExtra(symbol: Symbol, extra: Extra, macho_file: *MachO) void { | 227 | pub inline fn setExtra(symbol: Symbol, extra: Extra, macho_file: *MachO) void { |
| 223 | macho_file.setSymbolExtra(symbol.extra, extra); | 228 | return switch (symbol.getFile(macho_file).?) { |
| 229 | inline else => |x| x.setSymbolExtra(symbol.extra, extra), | ||
| 230 | }; | ||
| 224 | } | 231 | } |
| 225 | 232 | ||
| 226 | pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) void { | 233 | pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) void { |
| 227 | if (symbol.isLocal()) { | 234 | if (symbol.isLocal()) { |
| 228 | out.n_type = if (symbol.flags.abs) macho.N_ABS else macho.N_SECT; | 235 | out.n_type = if (symbol.flags.abs) macho.N_ABS else macho.N_SECT; |
| 229 | out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.out_n_sect + 1); | 236 | out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.getOutputSectionIndex(macho_file) + 1); |
| 230 | out.n_desc = 0; | 237 | out.n_desc = 0; |
| 231 | out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file); | 238 | out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file); |
| 232 | 239 | ||
| ... | @@ -238,7 +245,7 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo | ... | @@ -238,7 +245,7 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo |
| 238 | assert(symbol.visibility == .global); | 245 | assert(symbol.visibility == .global); |
| 239 | out.n_type = macho.N_EXT; | 246 | out.n_type = macho.N_EXT; |
| 240 | out.n_type |= if (symbol.flags.abs) macho.N_ABS else macho.N_SECT; | 247 | out.n_type |= if (symbol.flags.abs) macho.N_ABS else macho.N_SECT; |
| 241 | out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.out_n_sect + 1); | 248 | out.n_sect = if (symbol.flags.abs) 0 else @intCast(symbol.getOutputSectionIndex(macho_file) + 1); |
| 242 | out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file); | 249 | out.n_value = symbol.getAddress(.{ .stubs = false }, macho_file); |
| 243 | out.n_desc = 0; | 250 | out.n_desc = 0; |
| 244 | 251 | ||
| ... | @@ -318,8 +325,8 @@ fn format2( | ... | @@ -318,8 +325,8 @@ fn format2( |
| 318 | symbol.getAddress(.{}, ctx.macho_file), | 325 | symbol.getAddress(.{}, ctx.macho_file), |
| 319 | }); | 326 | }); |
| 320 | if (symbol.getFile(ctx.macho_file)) |file| { | 327 | if (symbol.getFile(ctx.macho_file)) |file| { |
| 321 | if (symbol.out_n_sect != 0) { | 328 | if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) { |
| 322 | try writer.print(" : sect({d})", .{symbol.out_n_sect}); | 329 | try writer.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)}); |
| 323 | } | 330 | } |
| 324 | if (symbol.getAtom(ctx.macho_file)) |atom| { | 331 | if (symbol.getAtom(ctx.macho_file)) |atom| { |
| 325 | try writer.print(" : atom({d})", .{atom.atom_index}); | 332 | try writer.print(" : atom({d})", .{atom.atom_index}); |
| ... | @@ -346,11 +353,6 @@ pub const Flags = packed struct { | ... | @@ -346,11 +353,6 @@ pub const Flags = packed struct { |
| 346 | /// Whether the symbol is exported at runtime. | 353 | /// Whether the symbol is exported at runtime. |
| 347 | @"export": bool = false, | 354 | @"export": bool = false, |
| 348 | 355 | ||
| 349 | /// Whether the symbol is effectively an extern and takes part in global | ||
| 350 | /// symbol resolution. Then, its name will be saved in global string interning | ||
| 351 | /// table. | ||
| 352 | global: bool = false, | ||
| 353 | |||
| 354 | /// Whether this symbol is weak. | 356 | /// Whether this symbol is weak. |
| 355 | weak: bool = false, | 357 | weak: bool = false, |
| 356 | 358 |