| author | |
| committer | |
| log | 0135b4665988530c0bd6b36ef7cb93ecaf999776 |
| tree | dd9ba7fdc2173ecfa8fc028d24a2e63f62ada94d |
| parent | f87424ab6393c3208d96a4f078c71f745a37c84b |
6 files changed, 98 insertions(+), 103 deletions(-)
CMakeLists.txt-1| ... | ... | @@ -581,7 +581,6 @@ set(ZIG_STAGE2_SOURCES |
| 581 | 581 | "${CMAKE_SOURCE_DIR}/src/link/MachO/DebugSymbols.zig" |
| 582 | 582 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Dylib.zig" |
| 583 | 583 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Object.zig" |
| 584 | "${CMAKE_SOURCE_DIR}/src/link/MachO/StringTable.zig" | |
| 585 | 584 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Symbol.zig" |
| 586 | 585 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Trie.zig" |
| 587 | 586 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Zld.zig" |
src/link/MachO.zig+46-15| ... | ... | @@ -26,7 +26,6 @@ const target_util = @import("../target.zig"); |
| 26 | 26 | const DebugSymbols = @import("MachO/DebugSymbols.zig"); |
| 27 | 27 | const Trie = @import("MachO/Trie.zig"); |
| 28 | 28 | const CodeSignature = @import("MachO/CodeSignature.zig"); |
| 29 | const StringTable = @import("MachO/StringTable.zig"); | |
| 30 | 29 | const Zld = @import("MachO/Zld.zig"); |
| 31 | 30 | |
| 32 | 31 | usingnamespace @import("MachO/commands.zig"); |
| ... | ... | @@ -117,7 +116,8 @@ offset_table_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 117 | 116 | |
| 118 | 117 | stub_helper_stubs_start_off: ?u64 = null, |
| 119 | 118 | |
| 120 | strtab: StringTable = undefined, | |
| 119 | strtab: std.ArrayListUnmanaged(u8) = .{}, | |
| 120 | strtab_cache: std.StringHashMapUnmanaged(u32) = .{}, | |
| 121 | 121 | |
| 122 | 122 | /// Table of GOT entries. |
| 123 | 123 | offset_table: std.ArrayListUnmanaged(GOTEntry) = .{}, |
| ... | ... | @@ -418,7 +418,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO { |
| 418 | 418 | .file = null, |
| 419 | 419 | }, |
| 420 | 420 | .page_size = if (options.target.cpu.arch == .aarch64) 0x4000 else 0x1000, |
| 421 | .strtab = try StringTable.init(gpa), | |
| 422 | 421 | }; |
| 423 | 422 | |
| 424 | 423 | return self; |
| ... | ... | @@ -985,7 +984,14 @@ pub fn deinit(self: *MachO) void { |
| 985 | 984 | self.text_block_free_list.deinit(self.base.allocator); |
| 986 | 985 | self.offset_table.deinit(self.base.allocator); |
| 987 | 986 | self.offset_table_free_list.deinit(self.base.allocator); |
| 988 | self.strtab.deinit(); | |
| 987 | { | |
| 988 | var it = self.strtab_cache.keyIterator(); | |
| 989 | while (it.next()) |key| { | |
| 990 | self.base.allocator.free(key.*); | |
| 991 | } | |
| 992 | } | |
| 993 | self.strtab_cache.deinit(self.base.allocator); | |
| 994 | self.strtab.deinit(self.base.allocator); | |
| 989 | 995 | self.globals.deinit(self.base.allocator); |
| 990 | 996 | self.globals_free_list.deinit(self.base.allocator); |
| 991 | 997 | self.locals.deinit(self.base.allocator); |
| ... | ... | @@ -1203,7 +1209,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1203 | 1209 | const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)}); |
| 1204 | 1210 | defer self.base.allocator.free(new_name); |
| 1205 | 1211 | |
| 1206 | symbol.n_strx = try self.strtab.getOrPut(new_name); | |
| 1212 | symbol.n_strx = try self.makeString(new_name); | |
| 1207 | 1213 | symbol.n_type = macho.N_SECT; |
| 1208 | 1214 | symbol.n_sect = @intCast(u8, self.text_section_index.?) + 1; |
| 1209 | 1215 | symbol.n_desc = 0; |
| ... | ... | @@ -1215,7 +1221,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1215 | 1221 | const decl_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)}); |
| 1216 | 1222 | defer self.base.allocator.free(decl_name); |
| 1217 | 1223 | |
| 1218 | const name_str_index = try self.strtab.getOrPut(decl_name); | |
| 1224 | const name_str_index = try self.makeString(decl_name); | |
| 1219 | 1225 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); |
| 1220 | 1226 | |
| 1221 | 1227 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, addr }); |
| ... | ... | @@ -1405,14 +1411,14 @@ pub fn updateDeclExports( |
| 1405 | 1411 | if (exp.link.macho.sym_index) |i| { |
| 1406 | 1412 | const sym = &self.globals.items[i]; |
| 1407 | 1413 | sym.* = .{ |
| 1408 | .n_strx = try self.strtab.getOrPut(exp_name), | |
| 1414 | .n_strx = sym.n_strx, | |
| 1409 | 1415 | .n_type = n_type, |
| 1410 | 1416 | .n_sect = @intCast(u8, self.text_section_index.?) + 1, |
| 1411 | 1417 | .n_desc = n_desc, |
| 1412 | 1418 | .n_value = decl_sym.n_value, |
| 1413 | 1419 | }; |
| 1414 | 1420 | } else { |
| 1415 | const name_str_index = try self.strtab.getOrPut(exp_name); | |
| 1421 | const name_str_index = try self.makeString(exp_name); | |
| 1416 | 1422 | const i = if (self.globals_free_list.popOrNull()) |i| i else blk: { |
| 1417 | 1423 | _ = self.globals.addOneAssumeCapacity(); |
| 1418 | 1424 | self.export_info_dirty = true; |
| ... | ... | @@ -1788,7 +1794,8 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1788 | 1794 | symtab.symoff = @intCast(u32, symtab_off); |
| 1789 | 1795 | symtab.nsyms = @intCast(u32, self.base.options.symbol_count_hint); |
| 1790 | 1796 | |
| 1791 | const strtab_size = self.strtab.size(); | |
| 1797 | try self.strtab.append(self.base.allocator, 0); | |
| 1798 | const strtab_size = self.strtab.items.len; | |
| 1792 | 1799 | const strtab_off = self.findFreeSpaceLinkedit(strtab_size, 1, symtab_off); |
| 1793 | 1800 | log.debug("found string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + strtab_size }); |
| 1794 | 1801 | symtab.stroff = @intCast(u32, strtab_off); |
| ... | ... | @@ -1930,7 +1937,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1930 | 1937 | if (!self.nonlazy_imports.contains("dyld_stub_binder")) { |
| 1931 | 1938 | const index = @intCast(u32, self.nonlazy_imports.count()); |
| 1932 | 1939 | const name = try self.base.allocator.dupe(u8, "dyld_stub_binder"); |
| 1933 | const offset = try self.strtab.getOrPut("dyld_stub_binder"); | |
| 1940 | const offset = try self.makeString("dyld_stub_binder"); | |
| 1934 | 1941 | try self.nonlazy_imports.putNoClobber(self.base.allocator, name, .{ |
| 1935 | 1942 | .symbol = .{ |
| 1936 | 1943 | .n_strx = offset, |
| ... | ... | @@ -2063,7 +2070,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 2063 | 2070 | |
| 2064 | 2071 | pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 { |
| 2065 | 2072 | const index = @intCast(u32, self.lazy_imports.count()); |
| 2066 | const offset = try self.strtab.getOrPut(name); | |
| 2073 | const offset = try self.makeString(name); | |
| 2067 | 2074 | const sym_name = try self.base.allocator.dupe(u8, name); |
| 2068 | 2075 | const dylib_ordinal = 1; // TODO this is now hardcoded, since we only support libSystem. |
| 2069 | 2076 | try self.lazy_imports.putNoClobber(self.base.allocator, sym_name, .{ |
| ... | ... | @@ -2253,7 +2260,7 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void { |
| 2253 | 2260 | }, |
| 2254 | 2261 | } |
| 2255 | 2262 | }; |
| 2256 | const sym_name = self.strtab.get(sym.n_strx) orelse unreachable; | |
| 2263 | const sym_name = self.getString(sym.n_strx) orelse unreachable; | |
| 2257 | 2264 | log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{ off, sym.n_value, sym_name }); |
| 2258 | 2265 | try self.base.file.?.pwriteAll(mem.asBytes(&sym.n_value), off); |
| 2259 | 2266 | } |
| ... | ... | @@ -2751,7 +2758,7 @@ fn writeExportTrie(self: *MachO) !void { |
| 2751 | 2758 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2752 | 2759 | for (self.globals.items) |symbol| { |
| 2753 | 2760 | // TODO figure out if we should put all global symbols into the export trie |
| 2754 | const name = self.strtab.get(symbol.n_strx) orelse unreachable; | |
| 2761 | const name = self.getString(symbol.n_strx) orelse unreachable; | |
| 2755 | 2762 | assert(symbol.n_value >= text_segment.inner.vmaddr); |
| 2756 | 2763 | try trie.put(.{ |
| 2757 | 2764 | .name = name, |
| ... | ... | @@ -3032,7 +3039,7 @@ fn writeStringTable(self: *MachO) !void { |
| 3032 | 3039 | |
| 3033 | 3040 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 3034 | 3041 | const allocated_size = self.allocatedSizeLinkedit(symtab.stroff); |
| 3035 | const needed_size = mem.alignForwardGeneric(u64, self.strtab.size(), @alignOf(u64)); | |
| 3042 | const needed_size = mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)); | |
| 3036 | 3043 | |
| 3037 | 3044 | if (needed_size > allocated_size or self.strtab_needs_relocation) { |
| 3038 | 3045 | symtab.strsize = 0; |
| ... | ... | @@ -3042,7 +3049,7 @@ fn writeStringTable(self: *MachO) !void { |
| 3042 | 3049 | symtab.strsize = @intCast(u32, needed_size); |
| 3043 | 3050 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 3044 | 3051 | |
| 3045 | try self.base.file.?.pwriteAll(self.strtab.asSlice(), symtab.stroff); | |
| 3052 | try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff); | |
| 3046 | 3053 | self.load_commands_dirty = true; |
| 3047 | 3054 | self.strtab_dirty = false; |
| 3048 | 3055 | } |
| ... | ... | @@ -3173,3 +3180,27 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 3173 | 3180 | fn hasTlvDescriptors(_: *MachO) bool { |
| 3174 | 3181 | return false; |
| 3175 | 3182 | } |
| 3183 | ||
| 3184 | pub fn makeString(self: *MachO, string: []const u8) !u32 { | |
| 3185 | if (self.strtab_cache.get(string)) |off| { | |
| 3186 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); | |
| 3187 | return off; | |
| 3188 | } | |
| 3189 | ||
| 3190 | try self.strtab.ensureUnusedCapacity(self.base.allocator, string.len + 1); | |
| 3191 | const new_off = @intCast(u32, self.strtab.items.len); | |
| 3192 | ||
| 3193 | log.debug("writing new string '{s}' at offset 0x{x}", .{ string, new_off }); | |
| 3194 | ||
| 3195 | self.strtab.appendSliceAssumeCapacity(string); | |
| 3196 | self.strtab.appendAssumeCapacity(0); | |
| 3197 | ||
| 3198 | try self.strtab_cache.putNoClobber(self.base.allocator, try self.base.allocator.dupe(u8, string), new_off); | |
| 3199 | ||
| 3200 | return new_off; | |
| 3201 | } | |
| 3202 | ||
| 3203 | pub fn getString(self: *MachO, off: u32) ?[]const u8 { | |
| 3204 | assert(off < self.strtab.items.len); | |
| 3205 | return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + off)); | |
| 3206 | } |
src/link/MachO/DebugSymbols.zig+2-2| ... | ... | @@ -814,7 +814,7 @@ fn writeStringTable(self: *DebugSymbols) !void { |
| 814 | 814 | |
| 815 | 815 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 816 | 816 | const allocated_size = self.allocatedSizeLinkedit(symtab.stroff); |
| 817 | const needed_size = mem.alignForwardGeneric(u64, self.base.strtab.size(), @alignOf(u64)); | |
| 817 | const needed_size = mem.alignForwardGeneric(u64, self.base.strtab.items.len, @alignOf(u64)); | |
| 818 | 818 | |
| 819 | 819 | if (needed_size > allocated_size) { |
| 820 | 820 | symtab.strsize = 0; |
| ... | ... | @@ -823,7 +823,7 @@ fn writeStringTable(self: *DebugSymbols) !void { |
| 823 | 823 | symtab.strsize = @intCast(u32, needed_size); |
| 824 | 824 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 825 | 825 | |
| 826 | try self.file.pwriteAll(self.base.strtab.asSlice(), symtab.stroff); | |
| 826 | try self.file.pwriteAll(self.base.strtab.items, symtab.stroff); | |
| 827 | 827 | self.load_commands_dirty = true; |
| 828 | 828 | self.strtab_dirty = false; |
| 829 | 829 | } |
src/link/MachO/StringTable.zig deleted-64| ... | ... | @@ -1,64 +0,0 @@ |
| 1 | const StringTable = @This(); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const log = std.log.scoped(.strtab); | |
| 5 | const mem = std.mem; | |
| 6 | ||
| 7 | const Allocator = mem.Allocator; | |
| 8 | ||
| 9 | allocator: *Allocator, | |
| 10 | buffer: std.ArrayListUnmanaged(u8) = .{}, | |
| 11 | cache: std.StringHashMapUnmanaged(u32) = .{}, | |
| 12 | ||
| 13 | pub const Error = error{OutOfMemory}; | |
| 14 | ||
| 15 | pub fn init(allocator: *Allocator) Error!StringTable { | |
| 16 | var strtab = StringTable{ | |
| 17 | .allocator = allocator, | |
| 18 | }; | |
| 19 | try strtab.buffer.append(allocator, 0); | |
| 20 | return strtab; | |
| 21 | } | |
| 22 | ||
| 23 | pub fn deinit(self: *StringTable) void { | |
| 24 | { | |
| 25 | var it = self.cache.keyIterator(); | |
| 26 | while (it.next()) |key| { | |
| 27 | self.allocator.free(key.*); | |
| 28 | } | |
| 29 | } | |
| 30 | self.cache.deinit(self.allocator); | |
| 31 | self.buffer.deinit(self.allocator); | |
| 32 | } | |
| 33 | ||
| 34 | pub fn getOrPut(self: *StringTable, string: []const u8) Error!u32 { | |
| 35 | if (self.cache.get(string)) |off| { | |
| 36 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); | |
| 37 | return off; | |
| 38 | } | |
| 39 | ||
| 40 | try self.buffer.ensureUnusedCapacity(self.allocator, string.len + 1); | |
| 41 | const new_off = @intCast(u32, self.buffer.items.len); | |
| 42 | ||
| 43 | log.debug("writing new string '{s}' at offset 0x{x}", .{ string, new_off }); | |
| 44 | ||
| 45 | self.buffer.appendSliceAssumeCapacity(string); | |
| 46 | self.buffer.appendAssumeCapacity(0); | |
| 47 | ||
| 48 | try self.cache.putNoClobber(self.allocator, try self.allocator.dupe(u8, string), new_off); | |
| 49 | ||
| 50 | return new_off; | |
| 51 | } | |
| 52 | ||
| 53 | pub fn get(self: StringTable, off: u32) ?[]const u8 { | |
| 54 | if (off >= self.buffer.items.len) return null; | |
| 55 | return mem.spanZ(@ptrCast([*:0]const u8, self.buffer.items.ptr + off)); | |
| 56 | } | |
| 57 | ||
| 58 | pub fn asSlice(self: StringTable) []const u8 { | |
| 59 | return self.buffer.items; | |
| 60 | } | |
| 61 | ||
| 62 | pub fn size(self: StringTable) u64 { | |
| 63 | return self.buffer.items.len; | |
| 64 | } |
src/link/MachO/Symbol.zig+2-3| ... | ... | @@ -9,7 +9,6 @@ const mem = std.mem; |
| 9 | 9 | const Allocator = mem.Allocator; |
| 10 | 10 | const Dylib = @import("Dylib.zig"); |
| 11 | 11 | const Object = @import("Object.zig"); |
| 12 | const StringTable = @import("StringTable.zig"); | |
| 13 | 12 | const Zld = @import("Zld.zig"); |
| 14 | 13 | |
| 15 | 14 | /// Symbol name. Owned slice. |
| ... | ... | @@ -226,8 +225,8 @@ pub fn needsTlvOffset(self: Symbol, zld: *Zld) bool { |
| 226 | 225 | return sect_type == macho.S_THREAD_LOCAL_VARIABLES; |
| 227 | 226 | } |
| 228 | 227 | |
| 229 | pub fn asNlist(symbol: *Symbol, zld: *Zld, strtab: *StringTable) !macho.nlist_64 { | |
| 230 | const n_strx = try strtab.getOrPut(symbol.name); | |
| 228 | pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 { | |
| 229 | const n_strx = try zld.makeString(symbol.name); | |
| 231 | 230 | const nlist = nlist: { |
| 232 | 231 | switch (symbol.payload) { |
| 233 | 232 | .regular => |regular| { |
src/link/MachO/Zld.zig+48-18| ... | ... | @@ -18,7 +18,6 @@ const CodeSignature = @import("CodeSignature.zig"); |
| 18 | 18 | const Dylib = @import("Dylib.zig"); |
| 19 | 19 | const Object = @import("Object.zig"); |
| 20 | 20 | const Relocation = reloc.Relocation; |
| 21 | const StringTable = @import("StringTable.zig"); | |
| 22 | 21 | const Symbol = @import("Symbol.zig"); |
| 23 | 22 | const Trie = @import("Trie.zig"); |
| 24 | 23 | |
| ... | ... | @@ -26,7 +25,6 @@ usingnamespace @import("commands.zig"); |
| 26 | 25 | usingnamespace @import("bind.zig"); |
| 27 | 26 | |
| 28 | 27 | allocator: *Allocator, |
| 29 | strtab: StringTable, | |
| 30 | 28 | |
| 31 | 29 | target: ?std.Target = null, |
| 32 | 30 | page_size: ?u16 = null, |
| ... | ... | @@ -114,6 +112,9 @@ stub_helper_stubs_start_off: ?u64 = null, |
| 114 | 112 | |
| 115 | 113 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 116 | 114 | |
| 115 | strtab: std.ArrayListUnmanaged(u8) = .{}, | |
| 116 | strtab_cache: std.StringHashMapUnmanaged(u32) = .{}, | |
| 117 | ||
| 117 | 118 | has_dices: bool = false, |
| 118 | 119 | has_stabs: bool = false, |
| 119 | 120 | |
| ... | ... | @@ -169,7 +170,7 @@ pub const TextBlock = struct { |
| 169 | 170 | .n_value = reg.address, |
| 170 | 171 | }); |
| 171 | 172 | nlists.appendAssumeCapacity(.{ |
| 172 | .n_strx = try zld.strtab.getOrPut(sym.name), | |
| 173 | .n_strx = try zld.makeString(sym.name), | |
| 173 | 174 | .n_type = macho.N_FUN, |
| 174 | 175 | .n_sect = section_id, |
| 175 | 176 | .n_desc = 0, |
| ... | ... | @@ -192,7 +193,7 @@ pub const TextBlock = struct { |
| 192 | 193 | }, |
| 193 | 194 | .global => { |
| 194 | 195 | try nlists.append(.{ |
| 195 | .n_strx = try zld.strtab.getOrPut(sym.name), | |
| 196 | .n_strx = try zld.makeString(sym.name), | |
| 196 | 197 | .n_type = macho.N_GSYM, |
| 197 | 198 | .n_sect = 0, |
| 198 | 199 | .n_desc = 0, |
| ... | ... | @@ -201,7 +202,7 @@ pub const TextBlock = struct { |
| 201 | 202 | }, |
| 202 | 203 | .static => { |
| 203 | 204 | try nlists.append(.{ |
| 204 | .n_strx = try zld.strtab.getOrPut(sym.name), | |
| 205 | .n_strx = try zld.makeString(sym.name), | |
| 205 | 206 | .n_type = macho.N_STSYM, |
| 206 | 207 | .n_sect = reg.sectionId(zld), |
| 207 | 208 | .n_desc = 0, |
| ... | ... | @@ -311,10 +312,7 @@ pub const TextBlock = struct { |
| 311 | 312 | const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; |
| 312 | 313 | |
| 313 | 314 | pub fn init(allocator: *Allocator) !Zld { |
| 314 | return Zld{ | |
| 315 | .allocator = allocator, | |
| 316 | .strtab = try StringTable.init(allocator), | |
| 317 | }; | |
| 315 | return Zld{ .allocator = allocator }; | |
| 318 | 316 | } |
| 319 | 317 | |
| 320 | 318 | pub fn deinit(self: *Zld) void { |
| ... | ... | @@ -357,7 +355,15 @@ pub fn deinit(self: *Zld) void { |
| 357 | 355 | self.locals.deinit(self.allocator); |
| 358 | 356 | |
| 359 | 357 | self.globals.deinit(self.allocator); |
| 360 | self.strtab.deinit(); | |
| 358 | ||
| 359 | { | |
| 360 | var it = self.strtab_cache.keyIterator(); | |
| 361 | while (it.next()) |key| { | |
| 362 | self.allocator.free(key.*); | |
| 363 | } | |
| 364 | } | |
| 365 | self.strtab_cache.deinit(self.allocator); | |
| 366 | self.strtab.deinit(self.allocator); | |
| 361 | 367 | |
| 362 | 368 | // TODO dealloc all blocks |
| 363 | 369 | self.blocks.deinit(self.allocator); |
| ... | ... | @@ -2572,7 +2578,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2572 | 2578 | if (symbol.isTemp()) continue; // TODO when merging codepaths, this should go into freelist |
| 2573 | 2579 | |
| 2574 | 2580 | const reg = symbol.payload.regular; |
| 2575 | const nlist = try symbol.asNlist(self, &self.strtab); | |
| 2581 | const nlist = try symbol.asNlist(self); | |
| 2576 | 2582 | |
| 2577 | 2583 | if (reg.linkage == .translation_unit) { |
| 2578 | 2584 | try locals.append(nlist); |
| ... | ... | @@ -2588,21 +2594,21 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2588 | 2594 | // Open scope |
| 2589 | 2595 | try locals.ensureUnusedCapacity(4); |
| 2590 | 2596 | locals.appendAssumeCapacity(.{ |
| 2591 | .n_strx = try self.strtab.getOrPut(object.tu_comp_dir.?), | |
| 2597 | .n_strx = try self.makeString(object.tu_comp_dir.?), | |
| 2592 | 2598 | .n_type = macho.N_SO, |
| 2593 | 2599 | .n_sect = 0, |
| 2594 | 2600 | .n_desc = 0, |
| 2595 | 2601 | .n_value = 0, |
| 2596 | 2602 | }); |
| 2597 | 2603 | locals.appendAssumeCapacity(.{ |
| 2598 | .n_strx = try self.strtab.getOrPut(object.tu_name.?), | |
| 2604 | .n_strx = try self.makeString(object.tu_name.?), | |
| 2599 | 2605 | .n_type = macho.N_SO, |
| 2600 | 2606 | .n_sect = 0, |
| 2601 | 2607 | .n_desc = 0, |
| 2602 | 2608 | .n_value = 0, |
| 2603 | 2609 | }); |
| 2604 | 2610 | locals.appendAssumeCapacity(.{ |
| 2605 | .n_strx = try self.strtab.getOrPut(object.name.?), | |
| 2611 | .n_strx = try self.makeString(object.name.?), | |
| 2606 | 2612 | .n_type = macho.N_OSO, |
| 2607 | 2613 | .n_sect = 0, |
| 2608 | 2614 | .n_desc = 1, |
| ... | ... | @@ -2642,7 +2648,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2642 | 2648 | defer undef_dir.deinit(); |
| 2643 | 2649 | |
| 2644 | 2650 | for (self.imports.items) |sym| { |
| 2645 | const nlist = try sym.asNlist(self, &self.strtab); | |
| 2651 | const nlist = try sym.asNlist(self); | |
| 2646 | 2652 | const id = @intCast(u32, undefs.items.len); |
| 2647 | 2653 | try undefs.append(nlist); |
| 2648 | 2654 | try undef_dir.putNoClobber(sym.name, id); |
| ... | ... | @@ -2737,14 +2743,14 @@ fn writeStringTable(self: *Zld) !void { |
| 2737 | 2743 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2738 | 2744 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 2739 | 2745 | symtab.stroff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 2740 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.size(), @alignOf(u64))); | |
| 2746 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); | |
| 2741 | 2747 | seg.inner.filesize += symtab.strsize; |
| 2742 | 2748 | |
| 2743 | 2749 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 2744 | 2750 | |
| 2745 | try self.file.?.pwriteAll(self.strtab.asSlice(), symtab.stroff); | |
| 2751 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); | |
| 2746 | 2752 | |
| 2747 | if (symtab.strsize > self.strtab.size() and self.target.?.cpu.arch == .x86_64) { | |
| 2753 | if (symtab.strsize > self.strtab.items.len and self.target.?.cpu.arch == .x86_64) { | |
| 2748 | 2754 | // This is the last section, so we need to pad it out. |
| 2749 | 2755 | try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1); |
| 2750 | 2756 | } |
| ... | ... | @@ -2910,3 +2916,27 @@ fn writeHeader(self: *Zld) !void { |
| 2910 | 2916 | |
| 2911 | 2917 | try self.file.?.pwriteAll(mem.asBytes(&header), 0); |
| 2912 | 2918 | } |
| 2919 | ||
| 2920 | pub fn makeString(self: *Zld, string: []const u8) !u32 { | |
| 2921 | if (self.strtab_cache.get(string)) |off| { | |
| 2922 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); | |
| 2923 | return off; | |
| 2924 | } | |
| 2925 | ||
| 2926 | try self.strtab.ensureUnusedCapacity(self.allocator, string.len + 1); | |
| 2927 | const new_off = @intCast(u32, self.strtab.items.len); | |
| 2928 | ||
| 2929 | log.debug("writing new string '{s}' at offset 0x{x}", .{ string, new_off }); | |
| 2930 | ||
| 2931 | self.strtab.appendSliceAssumeCapacity(string); | |
| 2932 | self.strtab.appendAssumeCapacity(0); | |
| 2933 | ||
| 2934 | try self.strtab_cache.putNoClobber(self.allocator, try self.allocator.dupe(u8, string), new_off); | |
| 2935 | ||
| 2936 | return new_off; | |
| 2937 | } | |
| 2938 | ||
| 2939 | pub fn getString(self: *Zld, off: u32) ?[]const u8 { | |
| 2940 | assert(off < self.strtab.items.len); | |
| 2941 | return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + off)); | |
| 2942 | } |