| ... | ... | @@ -113,7 +113,6 @@ stub_helper_stubs_start_off: ?u64 = null, |
| 113 | 113 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 114 | 114 | |
| 115 | 115 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 116 | | strtab_cache: std.StringHashMapUnmanaged(u32) = .{}, |
| 117 | 116 | |
| 118 | 117 | has_dices: bool = false, |
| 119 | 118 | has_stabs: bool = false, |
| ... | ... | @@ -171,7 +170,7 @@ pub const TextBlock = struct { |
| 171 | 170 | .n_value = reg.address, |
| 172 | 171 | }); |
| 173 | 172 | nlists.appendAssumeCapacity(.{ |
| 174 | | .n_strx = try zld.makeString(sym.name), |
| 173 | .n_strx = sym.strx, |
| 175 | 174 | .n_type = macho.N_FUN, |
| 176 | 175 | .n_sect = section_id, |
| 177 | 176 | .n_desc = 0, |
| ... | ... | @@ -194,7 +193,7 @@ pub const TextBlock = struct { |
| 194 | 193 | }, |
| 195 | 194 | .global => { |
| 196 | 195 | try nlists.append(.{ |
| 197 | | .n_strx = try zld.makeString(sym.name), |
| 196 | .n_strx = sym.strx, |
| 198 | 197 | .n_type = macho.N_GSYM, |
| 199 | 198 | .n_sect = 0, |
| 200 | 199 | .n_desc = 0, |
| ... | ... | @@ -203,7 +202,7 @@ pub const TextBlock = struct { |
| 203 | 202 | }, |
| 204 | 203 | .static => { |
| 205 | 204 | try nlists.append(.{ |
| 206 | | .n_strx = try zld.makeString(sym.name), |
| 205 | .n_strx = sym.strx, |
| 207 | 206 | .n_type = macho.N_STSYM, |
| 208 | 207 | .n_sect = reg.sectionId(zld), |
| 209 | 208 | .n_desc = 0, |
| ... | ... | @@ -349,26 +348,20 @@ pub fn deinit(self: *Zld) void { |
| 349 | 348 | self.dylibs.deinit(self.allocator); |
| 350 | 349 | |
| 351 | 350 | for (self.imports.items) |sym| { |
| 352 | | sym.deinit(self.allocator); |
| 353 | 351 | self.allocator.destroy(sym); |
| 354 | 352 | } |
| 355 | 353 | self.imports.deinit(self.allocator); |
| 356 | 354 | |
| 357 | 355 | for (self.locals.items) |sym| { |
| 358 | | sym.deinit(self.allocator); |
| 359 | 356 | self.allocator.destroy(sym); |
| 360 | 357 | } |
| 361 | 358 | self.locals.deinit(self.allocator); |
| 362 | 359 | |
| 360 | for (self.globals.keys()) |key| { |
| 361 | self.allocator.free(key); |
| 362 | } |
| 363 | 363 | self.globals.deinit(self.allocator); |
| 364 | 364 | |
| 365 | | { |
| 366 | | var it = self.strtab_cache.keyIterator(); |
| 367 | | while (it.next()) |key| { |
| 368 | | self.allocator.free(key.*); |
| 369 | | } |
| 370 | | } |
| 371 | | self.strtab_cache.deinit(self.allocator); |
| 372 | 365 | self.strtab.deinit(self.allocator); |
| 373 | 366 | |
| 374 | 367 | // TODO dealloc all blocks |
| ... | ... | @@ -1168,7 +1161,7 @@ fn allocateTextBlocks(self: *Zld) !void { |
| 1168 | 1161 | sym.payload.regular.address = base_addr; |
| 1169 | 1162 | |
| 1170 | 1163 | log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{ |
| 1171 | | sym.name, |
| 1164 | self.getString(sym.strx), |
| 1172 | 1165 | base_addr, |
| 1173 | 1166 | base_addr + block.size, |
| 1174 | 1167 | block.size, |
| ... | ... | @@ -1231,7 +1224,7 @@ fn writeTextBlocks(self: *Zld) !void { |
| 1231 | 1224 | |
| 1232 | 1225 | const sym = self.locals.items[block.local_sym_index]; |
| 1233 | 1226 | log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{ |
| 1234 | | sym.name, |
| 1227 | self.getString(sym.strx), |
| 1235 | 1228 | aligned_base_off, |
| 1236 | 1229 | aligned_base_off + block.size, |
| 1237 | 1230 | block.size, |
| ... | ... | @@ -1552,14 +1545,17 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1552 | 1545 | |
| 1553 | 1546 | if (Symbol.isSect(sym) and !Symbol.isExt(sym)) { |
| 1554 | 1547 | // Regular symbol local to translation unit |
| 1555 | | const symbol = try Symbol.new(self.allocator, sym_name); |
| 1556 | | symbol.payload = .{ |
| 1557 | | .regular = .{ |
| 1558 | | .linkage = .translation_unit, |
| 1559 | | .address = sym.n_value, |
| 1560 | | .weak_ref = Symbol.isWeakRef(sym), |
| 1561 | | .file = object, |
| 1562 | | .local_sym_index = @intCast(u32, self.locals.items.len), |
| 1548 | const symbol = try self.allocator.create(Symbol); |
| 1549 | symbol.* = .{ |
| 1550 | .strx = try self.makeString(sym_name), |
| 1551 | .payload = .{ |
| 1552 | .regular = .{ |
| 1553 | .linkage = .translation_unit, |
| 1554 | .address = sym.n_value, |
| 1555 | .weak_ref = Symbol.isWeakRef(sym), |
| 1556 | .file = object, |
| 1557 | .local_sym_index = @intCast(u32, self.locals.items.len), |
| 1558 | }, |
| 1563 | 1559 | }, |
| 1564 | 1560 | }; |
| 1565 | 1561 | try self.locals.append(self.allocator, symbol); |
| ... | ... | @@ -1569,9 +1565,13 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1569 | 1565 | |
| 1570 | 1566 | const symbol = self.globals.get(sym_name) orelse symbol: { |
| 1571 | 1567 | // Insert new global symbol. |
| 1572 | | const symbol = try Symbol.new(self.allocator, sym_name); |
| 1573 | | symbol.payload.undef.file = object; |
| 1574 | | try self.globals.putNoClobber(self.allocator, symbol.name, symbol); |
| 1568 | const symbol = try self.allocator.create(Symbol); |
| 1569 | symbol.* = .{ |
| 1570 | .strx = try self.makeString(sym_name), |
| 1571 | .payload = .{ .undef = .{ .file = object } }, |
| 1572 | }; |
| 1573 | const alloc_name = try self.allocator.dupe(u8, sym_name); |
| 1574 | try self.globals.putNoClobber(self.allocator, alloc_name, symbol); |
| 1575 | 1575 | break :symbol symbol; |
| 1576 | 1576 | }; |
| 1577 | 1577 | |
| ... | ... | @@ -1628,7 +1628,8 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1628 | 1628 | fn resolveSymbols(self: *Zld) !void { |
| 1629 | 1629 | // TODO mimicking insertion of null symbol from incremental linker. |
| 1630 | 1630 | // This will need to moved. |
| 1631 | | const null_sym = try Symbol.new(self.allocator, ""); |
| 1631 | const null_sym = try self.allocator.create(Symbol); |
| 1632 | null_sym.* = .{ .strx = 0, .payload = .{ .undef = .{} } }; |
| 1632 | 1633 | try self.locals.append(self.allocator, null_sym); |
| 1633 | 1634 | |
| 1634 | 1635 | // First pass, resolve symbols in provided objects. |
| ... | ... | @@ -1639,12 +1640,13 @@ fn resolveSymbols(self: *Zld) !void { |
| 1639 | 1640 | // Second pass, resolve symbols in static libraries. |
| 1640 | 1641 | var sym_it = self.globals.iterator(); |
| 1641 | 1642 | while (sym_it.next()) |entry| { |
| 1643 | const sym_name = entry.key_ptr.*; |
| 1642 | 1644 | const symbol = entry.value_ptr.*; |
| 1643 | 1645 | if (symbol.payload != .undef) continue; |
| 1644 | 1646 | |
| 1645 | 1647 | for (self.archives.items) |archive| { |
| 1646 | 1648 | // Check if the entry exists in a static archive. |
| 1647 | | const offsets = archive.toc.get(symbol.name) orelse { |
| 1649 | const offsets = archive.toc.get(sym_name) orelse { |
| 1648 | 1650 | // No hit. |
| 1649 | 1651 | continue; |
| 1650 | 1652 | }; |
| ... | ... | @@ -1734,21 +1736,27 @@ fn resolveSymbols(self: *Zld) !void { |
| 1734 | 1736 | // Third pass, resolve symbols in dynamic libraries. |
| 1735 | 1737 | { |
| 1736 | 1738 | // Put dyld_stub_binder as an undefined special symbol. |
| 1737 | | const symbol = try Symbol.new(self.allocator, "dyld_stub_binder"); |
| 1739 | const symbol = try self.allocator.create(Symbol); |
| 1740 | symbol.* = .{ |
| 1741 | .strx = try self.makeString("dyld_stub_binder"), |
| 1742 | .payload = .{ .undef = .{} }, |
| 1743 | }; |
| 1738 | 1744 | const index = @intCast(u32, self.got_entries.items.len); |
| 1739 | 1745 | symbol.got_index = index; |
| 1740 | 1746 | try self.got_entries.append(self.allocator, symbol); |
| 1741 | | try self.globals.putNoClobber(self.allocator, symbol.name, symbol); |
| 1747 | const alloc_name = try self.allocator.dupe(u8, "dyld_stub_binder"); |
| 1748 | try self.globals.putNoClobber(self.allocator, alloc_name, symbol); |
| 1742 | 1749 | } |
| 1743 | 1750 | |
| 1744 | 1751 | var referenced = std.AutoHashMap(*Dylib, void).init(self.allocator); |
| 1745 | 1752 | defer referenced.deinit(); |
| 1746 | 1753 | |
| 1747 | | loop: for (self.globals.values()) |symbol| { |
| 1754 | loop: for (self.globals.keys()) |sym_name| { |
| 1755 | const symbol = self.globals.get(sym_name).?; |
| 1748 | 1756 | if (symbol.payload != .undef) continue; |
| 1749 | 1757 | |
| 1750 | 1758 | for (self.dylibs.items) |dylib| { |
| 1751 | | if (!dylib.symbols.contains(symbol.name)) continue; |
| 1759 | if (!dylib.symbols.contains(sym_name)) continue; |
| 1752 | 1760 | |
| 1753 | 1761 | try referenced.put(dylib, {}); |
| 1754 | 1762 | const index = @intCast(u32, self.imports.items.len); |
| ... | ... | @@ -1798,10 +1806,11 @@ fn resolveSymbols(self: *Zld) !void { |
| 1798 | 1806 | } |
| 1799 | 1807 | |
| 1800 | 1808 | var has_undefined = false; |
| 1801 | | for (self.globals.values()) |symbol| { |
| 1809 | for (self.globals.keys()) |sym_name| { |
| 1810 | const symbol = self.globals.get(sym_name).?; |
| 1802 | 1811 | if (symbol.payload != .undef) continue; |
| 1803 | 1812 | |
| 1804 | | log.err("undefined reference to symbol '{s}'", .{symbol.name}); |
| 1813 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| 1805 | 1814 | if (symbol.payload.undef.file) |file| { |
| 1806 | 1815 | log.err(" | referenced in {s}", .{file.name.?}); |
| 1807 | 1816 | } |
| ... | ... | @@ -2344,7 +2353,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2344 | 2353 | .offset = base_offset + sym.got_index.? * @sizeOf(u64), |
| 2345 | 2354 | .segment_id = segment_id, |
| 2346 | 2355 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2347 | | .name = sym.name, |
| 2356 | .name = self.getString(sym.strx), |
| 2348 | 2357 | }); |
| 2349 | 2358 | } |
| 2350 | 2359 | } |
| ... | ... | @@ -2372,7 +2381,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2372 | 2381 | .offset = binding.offset + base_offset, |
| 2373 | 2382 | .segment_id = match.seg, |
| 2374 | 2383 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2375 | | .name = bind_sym.name, |
| 2384 | .name = self.getString(bind_sym.strx), |
| 2376 | 2385 | }); |
| 2377 | 2386 | } |
| 2378 | 2387 | |
| ... | ... | @@ -2395,7 +2404,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2395 | 2404 | .offset = base_offset, |
| 2396 | 2405 | .segment_id = segment_id, |
| 2397 | 2406 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2398 | | .name = sym.name, |
| 2407 | .name = self.getString(sym.strx), |
| 2399 | 2408 | }); |
| 2400 | 2409 | } |
| 2401 | 2410 | |
| ... | ... | @@ -2435,7 +2444,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2435 | 2444 | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2436 | 2445 | .segment_id = segment_id, |
| 2437 | 2446 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2438 | | .name = sym.name, |
| 2447 | .name = self.getString(sym.strx), |
| 2439 | 2448 | }); |
| 2440 | 2449 | } |
| 2441 | 2450 | } |
| ... | ... | @@ -2547,7 +2556,7 @@ fn writeExportInfo(self: *Zld) !void { |
| 2547 | 2556 | if (sym.payload != .regular) continue; |
| 2548 | 2557 | const reg = sym.payload.regular; |
| 2549 | 2558 | if (reg.linkage != .global) continue; |
| 2550 | | try sorted_globals.append(sym.name); |
| 2559 | try sorted_globals.append(self.getString(sym.strx)); |
| 2551 | 2560 | } |
| 2552 | 2561 | |
| 2553 | 2562 | std.sort.sort([]const u8, sorted_globals.items, {}, Sorter.lessThan); |
| ... | ... | @@ -2556,10 +2565,10 @@ fn writeExportInfo(self: *Zld) !void { |
| 2556 | 2565 | const sym = self.globals.get(sym_name) orelse unreachable; |
| 2557 | 2566 | const reg = sym.payload.regular; |
| 2558 | 2567 | |
| 2559 | | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym.name, reg.address }); |
| 2568 | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, reg.address }); |
| 2560 | 2569 | |
| 2561 | 2570 | try trie.put(.{ |
| 2562 | | .name = sym.name, |
| 2571 | .name = sym_name, |
| 2563 | 2572 | .vmaddr_offset = reg.address - base_address, |
| 2564 | 2573 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 2565 | 2574 | }); |
| ... | ... | @@ -2597,7 +2606,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2597 | 2606 | |
| 2598 | 2607 | for (self.locals.items) |symbol, i| { |
| 2599 | 2608 | if (i == 0) continue; // skip null symbol |
| 2600 | | if (symbol.isTemp()) continue; // TODO when merging codepaths, this should go into freelist |
| 2609 | if (symbol.isTemp(self)) continue; // TODO when merging codepaths, this should go into freelist |
| 2601 | 2610 | |
| 2602 | 2611 | const reg = symbol.payload.regular; |
| 2603 | 2612 | const nlist = try symbol.asNlist(self); |
| ... | ... | @@ -2673,7 +2682,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2673 | 2682 | const nlist = try sym.asNlist(self); |
| 2674 | 2683 | const id = @intCast(u32, undefs.items.len); |
| 2675 | 2684 | try undefs.append(nlist); |
| 2676 | | try undef_dir.putNoClobber(sym.name, id); |
| 2685 | try undef_dir.putNoClobber(self.getString(sym.strx), id); |
| 2677 | 2686 | } |
| 2678 | 2687 | |
| 2679 | 2688 | const nlocals = locals.items.len; |
| ... | ... | @@ -2735,7 +2744,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2735 | 2744 | |
| 2736 | 2745 | stubs.reserved1 = 0; |
| 2737 | 2746 | for (self.stubs.items) |sym| { |
| 2738 | | const id = undef_dir.get(sym.name) orelse unreachable; |
| 2747 | const sym_name = self.getString(sym.strx); |
| 2748 | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2739 | 2749 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2740 | 2750 | } |
| 2741 | 2751 | |
| ... | ... | @@ -2743,7 +2753,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2743 | 2753 | for (self.got_entries.items) |sym| { |
| 2744 | 2754 | switch (sym.payload) { |
| 2745 | 2755 | .proxy => { |
| 2746 | | const id = undef_dir.get(sym.name) orelse unreachable; |
| 2756 | const sym_name = self.getString(sym.strx); |
| 2757 | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2747 | 2758 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2748 | 2759 | }, |
| 2749 | 2760 | else => { |
| ... | ... | @@ -2754,7 +2765,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2754 | 2765 | |
| 2755 | 2766 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; |
| 2756 | 2767 | for (self.stubs.items) |sym| { |
| 2757 | | const id = undef_dir.get(sym.name) orelse unreachable; |
| 2768 | const sym_name = self.getString(sym.strx); |
| 2769 | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2758 | 2770 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2759 | 2771 | } |
| 2760 | 2772 | |
| ... | ... | @@ -2940,11 +2952,6 @@ fn writeHeader(self: *Zld) !void { |
| 2940 | 2952 | } |
| 2941 | 2953 | |
| 2942 | 2954 | pub fn makeString(self: *Zld, string: []const u8) !u32 { |
| 2943 | | if (self.strtab_cache.get(string)) |off| { |
| 2944 | | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); |
| 2945 | | return off; |
| 2946 | | } |
| 2947 | | |
| 2948 | 2955 | try self.strtab.ensureUnusedCapacity(self.allocator, string.len + 1); |
| 2949 | 2956 | const new_off = @intCast(u32, self.strtab.items.len); |
| 2950 | 2957 | |
| ... | ... | @@ -2953,12 +2960,10 @@ pub fn makeString(self: *Zld, string: []const u8) !u32 { |
| 2953 | 2960 | self.strtab.appendSliceAssumeCapacity(string); |
| 2954 | 2961 | self.strtab.appendAssumeCapacity(0); |
| 2955 | 2962 | |
| 2956 | | try self.strtab_cache.putNoClobber(self.allocator, try self.allocator.dupe(u8, string), new_off); |
| 2957 | | |
| 2958 | 2963 | return new_off; |
| 2959 | 2964 | } |
| 2960 | 2965 | |
| 2961 | | pub fn getString(self: *Zld, off: u32) ?[]const u8 { |
| 2966 | pub fn getString(self: *Zld, off: u32) []const u8 { |
| 2962 | 2967 | assert(off < self.strtab.items.len); |
| 2963 | 2968 | return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + off)); |
| 2964 | 2969 | } |