| author | |
| committer | |
| log | 81183365852e7f871500a3f71810ae3b468f0027 |
| tree | 96a4de9d67ed5cf4330c81564c23973db381a7d3 |
| parent | 3562edf13772bca66b4f04fc87be25b518393221 |
Now, we don't erroneously write to the string table on every
write of global and undef symbols.3 files changed, 80 insertions(+), 108 deletions(-)
src/codegen.zig+5-13| ... | @@ -1920,21 +1920,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1920,21 +1920,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1920 | } | 1920 | } |
| 1921 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | 1921 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 1922 | const decl = func_payload.data; | 1922 | const decl = func_payload.data; |
| 1923 | // We don't free the decl_name immediately unless it already exists. | ||
| 1924 | // If it doesn't, it will get autofreed when we clean up the extern symbol table. | ||
| 1925 | const decl_name = try std.fmt.allocPrint(self.bin_file.allocator, "_{s}", .{decl.name}); | 1923 | const decl_name = try std.fmt.allocPrint(self.bin_file.allocator, "_{s}", .{decl.name}); |
| 1924 | defer self.bin_file.allocator.free(decl_name); | ||
| 1926 | const already_defined = macho_file.extern_lazy_symbols.contains(decl_name); | 1925 | const already_defined = macho_file.extern_lazy_symbols.contains(decl_name); |
| 1927 | const symbol: u32 = if (macho_file.extern_lazy_symbols.getIndex(decl_name)) |index| blk: { | 1926 | const symbol: u32 = if (macho_file.extern_lazy_symbols.getIndex(decl_name)) |index| |
| 1928 | self.bin_file.allocator.free(decl_name); | 1927 | @intCast(u32, index) |
| 1929 | break :blk @intCast(u32, index); | 1928 | else |
| 1930 | } else blk: { | 1929 | try macho_file.addExternSymbol(decl_name); |
| 1931 | const index = @intCast(u32, macho_file.extern_lazy_symbols.items().len); | ||
| 1932 | try macho_file.extern_lazy_symbols.putNoClobber(self.bin_file.allocator, decl_name, .{ | ||
| 1933 | .name = decl_name, | ||
| 1934 | .dylib_ordinal = 1, // TODO this is now hardcoded, since we only support libSystem. | ||
| 1935 | }); | ||
| 1936 | break :blk index; | ||
| 1937 | }; | ||
| 1938 | const start = self.code.items.len; | 1930 | const start = self.code.items.len; |
| 1939 | const len: usize = blk: { | 1931 | const len: usize = blk: { |
| 1940 | switch (arch) { | 1932 | switch (arch) { |
src/link/MachO.zig+39-50| ... | @@ -1011,11 +1011,11 @@ pub fn deinit(self: *MachO) void { | ... | @@ -1011,11 +1011,11 @@ pub fn deinit(self: *MachO) void { |
| 1011 | ds.deinit(self.base.allocator); | 1011 | ds.deinit(self.base.allocator); |
| 1012 | } | 1012 | } |
| 1013 | for (self.extern_lazy_symbols.items()) |*entry| { | 1013 | for (self.extern_lazy_symbols.items()) |*entry| { |
| 1014 | entry.value.deinit(self.base.allocator); | 1014 | self.base.allocator.free(entry.key); |
| 1015 | } | 1015 | } |
| 1016 | self.extern_lazy_symbols.deinit(self.base.allocator); | 1016 | self.extern_lazy_symbols.deinit(self.base.allocator); |
| 1017 | for (self.extern_nonlazy_symbols.items()) |*entry| { | 1017 | for (self.extern_nonlazy_symbols.items()) |*entry| { |
| 1018 | entry.value.deinit(self.base.allocator); | 1018 | self.base.allocator.free(entry.key); |
| 1019 | } | 1019 | } |
| 1020 | self.extern_nonlazy_symbols.deinit(self.base.allocator); | 1020 | self.extern_nonlazy_symbols.deinit(self.base.allocator); |
| 1021 | self.pie_fixups.deinit(self.base.allocator); | 1021 | self.pie_fixups.deinit(self.base.allocator); |
| ... | @@ -2042,9 +2042,16 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -2042,9 +2042,16 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 2042 | } | 2042 | } |
| 2043 | if (!self.extern_nonlazy_symbols.contains("dyld_stub_binder")) { | 2043 | if (!self.extern_nonlazy_symbols.contains("dyld_stub_binder")) { |
| 2044 | const index = @intCast(u32, self.extern_nonlazy_symbols.items().len); | 2044 | const index = @intCast(u32, self.extern_nonlazy_symbols.items().len); |
| 2045 | const name = try std.fmt.allocPrint(self.base.allocator, "dyld_stub_binder", .{}); | 2045 | const name = try self.base.allocator.dupe(u8, "dyld_stub_binder"); |
| 2046 | const offset = try self.makeString("dyld_stub_binder"); | ||
| 2046 | try self.extern_nonlazy_symbols.putNoClobber(self.base.allocator, name, .{ | 2047 | try self.extern_nonlazy_symbols.putNoClobber(self.base.allocator, name, .{ |
| 2047 | .name = name, | 2048 | .inner = .{ |
| 2049 | .n_strx = offset, | ||
| 2050 | .n_type = std.macho.N_UNDF | std.macho.N_EXT, | ||
| 2051 | .n_sect = 0, | ||
| 2052 | .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER, | ||
| 2053 | .n_value = 0, | ||
| 2054 | }, | ||
| 2048 | .dylib_ordinal = 1, // TODO this is currently hardcoded. | 2055 | .dylib_ordinal = 1, // TODO this is currently hardcoded. |
| 2049 | .segment = self.data_const_segment_cmd_index.?, | 2056 | .segment = self.data_const_segment_cmd_index.?, |
| 2050 | .offset = index * @sizeOf(u64), | 2057 | .offset = index * @sizeOf(u64), |
| ... | @@ -2222,15 +2229,15 @@ pub fn makeStaticString(comptime bytes: []const u8) [16]u8 { | ... | @@ -2222,15 +2229,15 @@ pub fn makeStaticString(comptime bytes: []const u8) [16]u8 { |
| 2222 | return buf; | 2229 | return buf; |
| 2223 | } | 2230 | } |
| 2224 | 2231 | ||
| 2225 | pub fn makeString(self: *MachO, bytes: []const u8) !u32 { | 2232 | fn makeString(self: *MachO, bytes: []const u8) !u32 { |
| 2226 | try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); | 2233 | try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); |
| 2227 | const result = @intCast(u32, self.string_table.items.len); | 2234 | const offset = @intCast(u32, self.string_table.items.len); |
| 2228 | self.string_table.appendSliceAssumeCapacity(bytes); | 2235 | self.string_table.appendSliceAssumeCapacity(bytes); |
| 2229 | self.string_table.appendAssumeCapacity(0); | 2236 | self.string_table.appendAssumeCapacity(0); |
| 2230 | self.string_table_dirty = true; | 2237 | self.string_table_dirty = true; |
| 2231 | if (self.d_sym) |*ds| | 2238 | if (self.d_sym) |*ds| |
| 2232 | ds.string_table_dirty = true; | 2239 | ds.string_table_dirty = true; |
| 2233 | return result; | 2240 | return offset; |
| 2234 | } | 2241 | } |
| 2235 | 2242 | ||
| 2236 | fn getString(self: *MachO, str_off: u32) []const u8 { | 2243 | fn getString(self: *MachO, str_off: u32) []const u8 { |
| ... | @@ -2246,6 +2253,23 @@ fn updateString(self: *MachO, old_str_off: u32, new_name: []const u8) !u32 { | ... | @@ -2246,6 +2253,23 @@ fn updateString(self: *MachO, old_str_off: u32, new_name: []const u8) !u32 { |
| 2246 | return self.makeString(new_name); | 2253 | return self.makeString(new_name); |
| 2247 | } | 2254 | } |
| 2248 | 2255 | ||
| 2256 | pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 { | ||
| 2257 | const index = @intCast(u32, self.extern_lazy_symbols.items().len); | ||
| 2258 | const offset = try self.makeString(name); | ||
| 2259 | const sym_name = try self.base.allocator.dupe(u8, name); | ||
| 2260 | try self.extern_lazy_symbols.putNoClobber(self.base.allocator, sym_name, .{ | ||
| 2261 | .inner = .{ | ||
| 2262 | .n_strx = offset, | ||
| 2263 | .n_type = macho.N_UNDF | macho.N_EXT, | ||
| 2264 | .n_sect = 0, | ||
| 2265 | .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER, | ||
| 2266 | .n_value = 0, | ||
| 2267 | }, | ||
| 2268 | .dylib_ordinal = 1, // TODO this is now hardcoded, since we only support libSystem. | ||
| 2269 | }); | ||
| 2270 | return index; | ||
| 2271 | } | ||
| 2272 | |||
| 2249 | const NextSegmentAddressAndOffset = struct { | 2273 | const NextSegmentAddressAndOffset = struct { |
| 2250 | address: u64, | 2274 | address: u64, |
| 2251 | offset: u64, | 2275 | offset: u64, |
| ... | @@ -2585,24 +2609,10 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { | ... | @@ -2585,24 +2609,10 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |
| 2585 | defer undefs.deinit(); | 2609 | defer undefs.deinit(); |
| 2586 | try undefs.ensureCapacity(nundefs); | 2610 | try undefs.ensureCapacity(nundefs); |
| 2587 | for (self.extern_lazy_symbols.items()) |entry| { | 2611 | for (self.extern_lazy_symbols.items()) |entry| { |
| 2588 | const name = try self.makeString(entry.key); | 2612 | undefs.appendAssumeCapacity(entry.value.inner); |
| 2589 | undefs.appendAssumeCapacity(.{ | ||
| 2590 | .n_strx = name, | ||
| 2591 | .n_type = std.macho.N_UNDF | std.macho.N_EXT, | ||
| 2592 | .n_sect = 0, | ||
| 2593 | .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER, | ||
| 2594 | .n_value = 0, | ||
| 2595 | }); | ||
| 2596 | } | 2613 | } |
| 2597 | for (self.extern_nonlazy_symbols.items()) |entry| { | 2614 | for (self.extern_nonlazy_symbols.items()) |entry| { |
| 2598 | const name = try self.makeString(entry.key); | 2615 | undefs.appendAssumeCapacity(entry.value.inner); |
| 2599 | undefs.appendAssumeCapacity(.{ | ||
| 2600 | .n_strx = name, | ||
| 2601 | .n_type = std.macho.N_UNDF | std.macho.N_EXT, | ||
| 2602 | .n_sect = 0, | ||
| 2603 | .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER, | ||
| 2604 | .n_value = 0, | ||
| 2605 | }); | ||
| 2606 | } | 2616 | } |
| 2607 | 2617 | ||
| 2608 | const locals_off = symtab.symoff; | 2618 | const locals_off = symtab.symoff; |
| ... | @@ -2781,19 +2791,12 @@ fn writeRebaseInfoTable(self: *MachO) !void { | ... | @@ -2781,19 +2791,12 @@ fn writeRebaseInfoTable(self: *MachO) !void { |
| 2781 | const tracy = trace(@src()); | 2791 | const tracy = trace(@src()); |
| 2782 | defer tracy.end(); | 2792 | defer tracy.end(); |
| 2783 | 2793 | ||
| 2784 | var symbols = try self.base.allocator.alloc(*const ExternSymbol, self.extern_lazy_symbols.items().len); | 2794 | const size = try rebaseInfoSize(self.extern_lazy_symbols.items()); |
| 2785 | defer self.base.allocator.free(symbols); | ||
| 2786 | |||
| 2787 | for (self.extern_lazy_symbols.items()) |*entry, i| { | ||
| 2788 | symbols[i] = &entry.value; | ||
| 2789 | } | ||
| 2790 | |||
| 2791 | const size = try rebaseInfoSize(symbols); | ||
| 2792 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | 2795 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); |
| 2793 | defer self.base.allocator.free(buffer); | 2796 | defer self.base.allocator.free(buffer); |
| 2794 | 2797 | ||
| 2795 | var stream = std.io.fixedBufferStream(buffer); | 2798 | var stream = std.io.fixedBufferStream(buffer); |
| 2796 | try writeRebaseInfo(symbols, stream.writer()); | 2799 | try writeRebaseInfo(self.extern_lazy_symbols.items(), stream.writer()); |
| 2797 | 2800 | ||
| 2798 | const linkedit_segment = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2801 | const linkedit_segment = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2799 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | 2802 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; |
| ... | @@ -2820,19 +2823,12 @@ fn writeBindingInfoTable(self: *MachO) !void { | ... | @@ -2820,19 +2823,12 @@ fn writeBindingInfoTable(self: *MachO) !void { |
| 2820 | const tracy = trace(@src()); | 2823 | const tracy = trace(@src()); |
| 2821 | defer tracy.end(); | 2824 | defer tracy.end(); |
| 2822 | 2825 | ||
| 2823 | var symbols = try self.base.allocator.alloc(*const ExternSymbol, self.extern_nonlazy_symbols.items().len); | 2826 | const size = try bindInfoSize(self.extern_nonlazy_symbols.items()); |
| 2824 | defer self.base.allocator.free(symbols); | ||
| 2825 | |||
| 2826 | for (self.extern_nonlazy_symbols.items()) |*entry, i| { | ||
| 2827 | symbols[i] = &entry.value; | ||
| 2828 | } | ||
| 2829 | |||
| 2830 | const size = try bindInfoSize(symbols); | ||
| 2831 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | 2827 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); |
| 2832 | defer self.base.allocator.free(buffer); | 2828 | defer self.base.allocator.free(buffer); |
| 2833 | 2829 | ||
| 2834 | var stream = std.io.fixedBufferStream(buffer); | 2830 | var stream = std.io.fixedBufferStream(buffer); |
| 2835 | try writeBindInfo(symbols, stream.writer()); | 2831 | try writeBindInfo(self.extern_nonlazy_symbols.items(), stream.writer()); |
| 2836 | 2832 | ||
| 2837 | const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2833 | const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2838 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | 2834 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; |
| ... | @@ -2856,19 +2852,12 @@ fn writeBindingInfoTable(self: *MachO) !void { | ... | @@ -2856,19 +2852,12 @@ fn writeBindingInfoTable(self: *MachO) !void { |
| 2856 | fn writeLazyBindingInfoTable(self: *MachO) !void { | 2852 | fn writeLazyBindingInfoTable(self: *MachO) !void { |
| 2857 | if (!self.lazy_binding_info_dirty) return; | 2853 | if (!self.lazy_binding_info_dirty) return; |
| 2858 | 2854 | ||
| 2859 | var symbols = try self.base.allocator.alloc(*const ExternSymbol, self.extern_lazy_symbols.items().len); | 2855 | const size = try lazyBindInfoSize(self.extern_lazy_symbols.items()); |
| 2860 | defer self.base.allocator.free(symbols); | ||
| 2861 | |||
| 2862 | for (self.extern_lazy_symbols.items()) |*entry, i| { | ||
| 2863 | symbols[i] = &entry.value; | ||
| 2864 | } | ||
| 2865 | |||
| 2866 | const size = try lazyBindInfoSize(symbols); | ||
| 2867 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | 2856 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); |
| 2868 | defer self.base.allocator.free(buffer); | 2857 | defer self.base.allocator.free(buffer); |
| 2869 | 2858 | ||
| 2870 | var stream = std.io.fixedBufferStream(buffer); | 2859 | var stream = std.io.fixedBufferStream(buffer); |
| 2871 | try writeLazyBindInfo(symbols, stream.writer()); | 2860 | try writeLazyBindInfo(self.extern_lazy_symbols.items(), stream.writer()); |
| 2872 | 2861 | ||
| 2873 | const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2862 | const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2874 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | 2863 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; |
src/link/MachO/imports.zig+36-45| ... | @@ -7,12 +7,8 @@ const assert = std.debug.assert; | ... | @@ -7,12 +7,8 @@ const assert = std.debug.assert; |
| 7 | const Allocator = mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| 8 | 8 | ||
| 9 | pub const ExternSymbol = struct { | 9 | pub const ExternSymbol = struct { |
| 10 | /// Symbol name. | 10 | /// MachO symbol table entry. |
| 11 | /// We own the memory, therefore we'll need to free it by calling `deinit`. | 11 | inner: macho.nlist_64, |
| 12 | /// In self-hosted, we don't expect it to be null ever. | ||
| 13 | /// However, this is for backwards compatibility with LLD when | ||
| 14 | /// we'll be patching things up post mortem. | ||
| 15 | name: ?[]u8 = null, | ||
| 16 | 12 | ||
| 17 | /// Id of the dynamic library where the specified entries can be found. | 13 | /// Id of the dynamic library where the specified entries can be found. |
| 18 | /// Id of 0 means self. | 14 | /// Id of 0 means self. |
| ... | @@ -26,22 +22,16 @@ pub const ExternSymbol = struct { | ... | @@ -26,22 +22,16 @@ pub const ExternSymbol = struct { |
| 26 | 22 | ||
| 27 | /// Offset relative to the start address of the `segment`. | 23 | /// Offset relative to the start address of the `segment`. |
| 28 | offset: u32 = 0, | 24 | offset: u32 = 0, |
| 29 | |||
| 30 | pub fn deinit(self: *ExternSymbol, allocator: *Allocator) void { | ||
| 31 | if (self.name) |name| { | ||
| 32 | allocator.free(name); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | }; | 25 | }; |
| 36 | 26 | ||
| 37 | pub fn rebaseInfoSize(symbols: []*const ExternSymbol) !u64 { | 27 | pub fn rebaseInfoSize(symbols: anytype) !u64 { |
| 38 | var stream = std.io.countingWriter(std.io.null_writer); | 28 | var stream = std.io.countingWriter(std.io.null_writer); |
| 39 | var writer = stream.writer(); | 29 | var writer = stream.writer(); |
| 40 | var size: u64 = 0; | 30 | var size: u64 = 0; |
| 41 | 31 | ||
| 42 | for (symbols) |symbol| { | 32 | for (symbols) |entry| { |
| 43 | size += 2; | 33 | size += 2; |
| 44 | try leb.writeILEB128(writer, symbol.offset); | 34 | try leb.writeILEB128(writer, entry.value.offset); |
| 45 | size += 1; | 35 | size += 1; |
| 46 | } | 36 | } |
| 47 | 37 | ||
| ... | @@ -49,8 +39,9 @@ pub fn rebaseInfoSize(symbols: []*const ExternSymbol) !u64 { | ... | @@ -49,8 +39,9 @@ pub fn rebaseInfoSize(symbols: []*const ExternSymbol) !u64 { |
| 49 | return size; | 39 | return size; |
| 50 | } | 40 | } |
| 51 | 41 | ||
| 52 | pub fn writeRebaseInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | 42 | pub fn writeRebaseInfo(symbols: anytype, writer: anytype) !void { |
| 53 | for (symbols) |symbol| { | 43 | for (symbols) |entry| { |
| 44 | const symbol = entry.value; | ||
| 54 | try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.REBASE_TYPE_POINTER)); | 45 | try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.REBASE_TYPE_POINTER)); |
| 55 | try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); | 46 | try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); |
| 56 | try leb.writeILEB128(writer, symbol.offset); | 47 | try leb.writeILEB128(writer, symbol.offset); |
| ... | @@ -59,23 +50,23 @@ pub fn writeRebaseInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | ... | @@ -59,23 +50,23 @@ pub fn writeRebaseInfo(symbols: []*const ExternSymbol, writer: anytype) !void { |
| 59 | try writer.writeByte(macho.REBASE_OPCODE_DONE); | 50 | try writer.writeByte(macho.REBASE_OPCODE_DONE); |
| 60 | } | 51 | } |
| 61 | 52 | ||
| 62 | pub fn bindInfoSize(symbols: []*const ExternSymbol) !u64 { | 53 | pub fn bindInfoSize(symbols: anytype) !u64 { |
| 63 | var stream = std.io.countingWriter(std.io.null_writer); | 54 | var stream = std.io.countingWriter(std.io.null_writer); |
| 64 | var writer = stream.writer(); | 55 | var writer = stream.writer(); |
| 65 | var size: u64 = 0; | 56 | var size: u64 = 0; |
| 66 | 57 | ||
| 67 | for (symbols) |symbol| { | 58 | for (symbols) |entry| { |
| 59 | const symbol = entry.value; | ||
| 60 | |||
| 68 | size += 1; | 61 | size += 1; |
| 69 | if (symbol.dylib_ordinal > 15) { | 62 | if (symbol.dylib_ordinal > 15) { |
| 70 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); | 63 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
| 71 | } | 64 | } |
| 72 | size += 1; | 65 | size += 1; |
| 73 | 66 | ||
| 74 | if (symbol.name) |name| { | 67 | size += 1; |
| 75 | size += 1; | 68 | size += entry.key.len; |
| 76 | size += name.len; | 69 | size += 1; |
| 77 | size += 1; | ||
| 78 | } | ||
| 79 | 70 | ||
| 80 | size += 1; | 71 | size += 1; |
| 81 | try leb.writeILEB128(writer, symbol.offset); | 72 | try leb.writeILEB128(writer, symbol.offset); |
| ... | @@ -86,8 +77,10 @@ pub fn bindInfoSize(symbols: []*const ExternSymbol) !u64 { | ... | @@ -86,8 +77,10 @@ pub fn bindInfoSize(symbols: []*const ExternSymbol) !u64 { |
| 86 | return size; | 77 | return size; |
| 87 | } | 78 | } |
| 88 | 79 | ||
| 89 | pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | 80 | pub fn writeBindInfo(symbols: anytype, writer: anytype) !void { |
| 90 | for (symbols) |symbol| { | 81 | for (symbols) |entry| { |
| 82 | const symbol = entry.value; | ||
| 83 | |||
| 91 | if (symbol.dylib_ordinal > 15) { | 84 | if (symbol.dylib_ordinal > 15) { |
| 92 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); | 85 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); |
| 93 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); | 86 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
| ... | @@ -98,11 +91,9 @@ pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | ... | @@ -98,11 +91,9 @@ pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { |
| 98 | } | 91 | } |
| 99 | try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.BIND_TYPE_POINTER)); | 92 | try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.BIND_TYPE_POINTER)); |
| 100 | 93 | ||
| 101 | if (symbol.name) |name| { | 94 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags. |
| 102 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags. | 95 | try writer.writeAll(entry.key); |
| 103 | try writer.writeAll(name); | 96 | try writer.writeByte(0); |
| 104 | try writer.writeByte(0); | ||
| 105 | } | ||
| 106 | 97 | ||
| 107 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); | 98 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); |
| 108 | try leb.writeILEB128(writer, symbol.offset); | 99 | try leb.writeILEB128(writer, symbol.offset); |
| ... | @@ -111,23 +102,24 @@ pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | ... | @@ -111,23 +102,24 @@ pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { |
| 111 | } | 102 | } |
| 112 | } | 103 | } |
| 113 | 104 | ||
| 114 | pub fn lazyBindInfoSize(symbols: []*const ExternSymbol) !u64 { | 105 | pub fn lazyBindInfoSize(symbols: anytype) !u64 { |
| 115 | var stream = std.io.countingWriter(std.io.null_writer); | 106 | var stream = std.io.countingWriter(std.io.null_writer); |
| 116 | var writer = stream.writer(); | 107 | var writer = stream.writer(); |
| 117 | var size: u64 = 0; | 108 | var size: u64 = 0; |
| 118 | 109 | ||
| 119 | for (symbols) |symbol| { | 110 | for (symbols) |entry| { |
| 111 | const symbol = entry.value; | ||
| 120 | size += 1; | 112 | size += 1; |
| 121 | try leb.writeILEB128(writer, symbol.offset); | 113 | try leb.writeILEB128(writer, symbol.offset); |
| 122 | size += 1; | 114 | size += 1; |
| 123 | if (symbol.dylib_ordinal > 15) { | 115 | if (symbol.dylib_ordinal > 15) { |
| 124 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); | 116 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
| 125 | } | 117 | } |
| 126 | if (symbol.name) |name| { | 118 | |
| 127 | size += 1; | 119 | size += 1; |
| 128 | size += name.len; | 120 | size += entry.key.len; |
| 129 | size += 1; | 121 | size += 1; |
| 130 | } | 122 | |
| 131 | size += 2; | 123 | size += 2; |
| 132 | } | 124 | } |
| 133 | 125 | ||
| ... | @@ -135,8 +127,9 @@ pub fn lazyBindInfoSize(symbols: []*const ExternSymbol) !u64 { | ... | @@ -135,8 +127,9 @@ pub fn lazyBindInfoSize(symbols: []*const ExternSymbol) !u64 { |
| 135 | return size; | 127 | return size; |
| 136 | } | 128 | } |
| 137 | 129 | ||
| 138 | pub fn writeLazyBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { | 130 | pub fn writeLazyBindInfo(symbols: anytype, writer: anytype) !void { |
| 139 | for (symbols) |symbol| { | 131 | for (symbols) |entry| { |
| 132 | const symbol = entry.value; | ||
| 140 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); | 133 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); |
| 141 | try leb.writeILEB128(writer, symbol.offset); | 134 | try leb.writeILEB128(writer, symbol.offset); |
| 142 | 135 | ||
| ... | @@ -149,11 +142,9 @@ pub fn writeLazyBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void | ... | @@ -149,11 +142,9 @@ pub fn writeLazyBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void |
| 149 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal))); | 142 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal))); |
| 150 | } | 143 | } |
| 151 | 144 | ||
| 152 | if (symbol.name) |name| { | 145 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags. |
| 153 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags. | 146 | try writer.writeAll(entry.key); |
| 154 | try writer.writeAll(name); | 147 | try writer.writeByte(0); |
| 155 | try writer.writeByte(0); | ||
| 156 | } | ||
| 157 | 148 | ||
| 158 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); | 149 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); |
| 159 | try writer.writeByte(macho.BIND_OPCODE_DONE); | 150 | try writer.writeByte(macho.BIND_OPCODE_DONE); |