diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-01-09 20:38:55 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-01-13 23:55:18 +0100 |
| commit | 7d40aaad2b514703995458909b315f222543c4cd (patch) | |
| tree | 063c91b13265579d66a15c268e4546209fd79247 /src | |
| parent | b86d0e488b9dfc7d943da86a34998360e24da225 (diff) | |
| download | zig-7d40aaad2b514703995458909b315f222543c4cd.tar.gz zig-7d40aaad2b514703995458909b315f222543c4cd.zip | |
macho: document more code + add test case
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.zig | 23 | ||||
| -rw-r--r-- | src/link/MachO.zig | 62 | ||||
| -rw-r--r-- | src/link/MachO/imports.zig | 31 |
3 files changed, 54 insertions, 62 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index ad4215191f..05898c77c8 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1865,19 +1865,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // If it doesn't, it will get autofreed when we clean up the extern symbol table. const decl_name = try std.fmt.allocPrint(self.bin_file.allocator, "_{s}", .{decl.name}); const already_defined = macho_file.extern_lazy_symbols.contains(decl_name); - const symbol: u32 = blk: { - if (macho_file.extern_lazy_symbols.get(decl_name)) |sym| { - self.bin_file.allocator.free(decl_name); - break :blk sym.index; - } else { - const index = @intCast(u32, macho_file.extern_lazy_symbols.items().len); - try macho_file.extern_lazy_symbols.putNoClobber(self.bin_file.allocator, decl_name, .{ - .name = decl_name, - .dylib_ordinal = 1, // TODO this is now hardcoded, since we only support libSystem. - .index = index, - }); - break :blk index; - } + const symbol: u32 = if (macho_file.extern_lazy_symbols.getIndex(decl_name)) |index| blk: { + self.bin_file.allocator.free(decl_name); + break :blk @intCast(u32, index); + } else blk: { + const index = @intCast(u32, macho_file.extern_lazy_symbols.items().len); + try macho_file.extern_lazy_symbols.putNoClobber(self.bin_file.allocator, decl_name, .{ + .name = decl_name, + .dylib_ordinal = 1, // TODO this is now hardcoded, since we only support libSystem. + }); + break :blk index; }; try macho_file.stub_fixups.append(self.bin_file.allocator, .{ .symbol = symbol, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 7d86c27aa9..c3808911eb 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -159,19 +159,29 @@ last_text_block: ?*TextBlock = null, /// prior to calling `generateSymbol`, and then immediately deallocated /// rather than sitting in the global scope. pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{}, - +/// A list of all stub (extern decls) fixups required for this run of the linker. +/// Warning, this is currently NOT thread-safe. See the TODO below. +/// TODO Move this list inside `updateDecl` where it should be allocated +/// prior to calling `generateSymbol`, and then immediately deallocated +/// rather than sitting in the global scope. stub_fixups: std.ArrayListUnmanaged(StubFixup) = .{}, -pub const StubFixup = struct { - symbol: u32, - already_defined: bool, +pub const PieFixup = struct { + /// Target address we wanted to address in absolute terms. + address: u64, + /// Where in the byte stream we should perform the fixup. start: usize, + /// The length of the byte stream. For x86_64, this will be + /// variable. For aarch64, it will be fixed at 4 bytes. len: usize, }; -pub const PieFixup = struct { - /// Target address we wanted to address in absolute terms. - address: u64, +pub const StubFixup = struct { + /// Id of extern (lazy) symbol. + symbol: u32, + /// Signals whether the symbol has already been declared before. If so, + /// then there is no need to rewrite the stub entry and related. + already_defined: bool, /// Where in the byte stream we should perform the fixup. start: usize, /// The length of the byte stream. For x86_64, this will be @@ -1030,13 +1040,20 @@ pub fn deinit(self: *MachO) void { if (self.d_sym) |*ds| { ds.deinit(self.base.allocator); } + for (self.extern_lazy_symbols.items()) |*entry| { + entry.value.deinit(self.base.allocator); + } + self.extern_lazy_symbols.deinit(self.base.allocator); + for (self.extern_nonlazy_symbols.items()) |*entry| { + entry.value.deinit(self.base.allocator); + } + self.extern_nonlazy_symbols.deinit(self.base.allocator); self.pie_fixups.deinit(self.base.allocator); + self.stub_fixups.deinit(self.base.allocator); self.text_block_free_list.deinit(self.base.allocator); self.offset_table.deinit(self.base.allocator); self.offset_table_free_list.deinit(self.base.allocator); self.string_table.deinit(self.base.allocator); - self.extern_lazy_symbols.deinit(self.base.allocator); - self.extern_nonlazy_symbols.deinit(self.base.allocator); self.global_symbols.deinit(self.base.allocator); self.global_symbol_free_list.deinit(self.base.allocator); self.local_symbols.deinit(self.base.allocator); @@ -2047,7 +2064,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { try self.extern_nonlazy_symbols.putNoClobber(self.base.allocator, name, .{ .name = name, .dylib_ordinal = 1, // TODO this is currently hardcoded. - .index = index, .segment = self.data_const_segment_cmd_index.?, .offset = index * @sizeOf(u64), }); @@ -2582,12 +2598,12 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { } fn writeIndirectSymbolTable(self: *MachO) !void { - const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; - const stubs = &text_seg.sections.items[self.stubs_section_index.?]; - const dc_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; - const got = &dc_seg.sections.items[self.data_got_section_index.?]; - const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; - const la = &data_seg.sections.items[self.la_symbol_ptr_section_index.?]; + const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; + const stubs = &text_segment.sections.items[self.stubs_section_index.?]; + const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; + const got = &data_const_seg.sections.items[self.data_got_section_index.?]; + const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; + const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; dysymtab.nindirectsyms = 0; @@ -2595,8 +2611,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void { var off = dysymtab.indirectsymoff; stubs.reserved1 = 0; - for (self.extern_lazy_symbols.items()) |entry| { - const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value.index); + for (self.extern_lazy_symbols.items()) |_, i| { + const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); mem.writeIntLittle(u32, &buf, symtab_idx); try self.base.file.?.pwriteAll(&buf, off); off += @sizeOf(u32); @@ -2605,17 +2621,17 @@ fn writeIndirectSymbolTable(self: *MachO) !void { const base_id = @intCast(u32, self.extern_lazy_symbols.items().len); got.reserved1 = base_id; - for (self.extern_nonlazy_symbols.items()) |entry| { - const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value.index + base_id); + for (self.extern_nonlazy_symbols.items()) |_, i| { + const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id); mem.writeIntLittle(u32, &buf, symtab_idx); try self.base.file.?.pwriteAll(&buf, off); off += @sizeOf(u32); dysymtab.nindirectsyms += 1; } - la.reserved1 = got.reserved1 + @intCast(u32, self.extern_nonlazy_symbols.items().len); - for (self.extern_lazy_symbols.items()) |entry| { - const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value.index); + la_symbol_ptr.reserved1 = got.reserved1 + @intCast(u32, self.extern_nonlazy_symbols.items().len); + for (self.extern_lazy_symbols.items()) |_, i| { + const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); mem.writeIntLittle(u32, &buf, symtab_idx); try self.base.file.?.pwriteAll(&buf, off); off += @sizeOf(u32); diff --git a/src/link/MachO/imports.zig b/src/link/MachO/imports.zig index 8e0f72e1de..c5f6211f1a 100644 --- a/src/link/MachO/imports.zig +++ b/src/link/MachO/imports.zig @@ -20,13 +20,15 @@ pub const ExternSymbol = struct { /// dylibs. dylib_ordinal: i64 = 0, + /// Id of the segment where this symbol is defined (will have its address + /// resolved). segment: u16 = 0, + + /// Offset relative to the start address of the `segment`. offset: u32 = 0, - addend: ?i32 = null, - index: u32, pub fn deinit(self: *ExternSymbol, allocator: *Allocator) void { - if (self.name) |*name| { + if (self.name) |name| { allocator.free(name); } } @@ -77,12 +79,6 @@ pub fn bindInfoSize(symbols: []*const ExternSymbol) !u64 { size += 1; try leb.writeILEB128(writer, symbol.offset); - - if (symbol.addend) |addend| { - size += 1; - try leb.writeILEB128(writer, addend); - } - size += 2; } @@ -110,12 +106,6 @@ pub fn writeBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void { try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); try leb.writeILEB128(writer, symbol.offset); - - if (symbol.addend) |addend| { - try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); - try leb.writeILEB128(writer, addend); - } - try writer.writeByte(macho.BIND_OPCODE_DO_BIND); try writer.writeByte(macho.BIND_OPCODE_DONE); } @@ -129,12 +119,6 @@ pub fn lazyBindInfoSize(symbols: []*const ExternSymbol) !u64 { for (symbols) |symbol| { size += 1; try leb.writeILEB128(writer, symbol.offset); - - if (symbol.addend) |addend| { - size += 1; - try leb.writeILEB128(writer, addend); - } - size += 1; if (symbol.dylib_ordinal > 15) { try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); @@ -156,11 +140,6 @@ pub fn writeLazyBindInfo(symbols: []*const ExternSymbol, writer: anytype) !void try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); try leb.writeILEB128(writer, symbol.offset); - if (symbol.addend) |addend| { - try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); - try leb.writeILEB128(writer, addend); - } - if (symbol.dylib_ordinal > 15) { try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
