authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-01 20:20:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-04 15:31:47+02:00
log737a8bf2041158b3036bda9130f9ce3f6c1ad582
tree3e033ef41421ca05eecd76bbd1016d9ff0f40237
parent2ba23abd9d267f6e007df1661da32be583145a6b

Redo local symbols and offsets tracking to match Elf's approach


2 files changed, 48 insertions(+), 30 deletions(-)

src/codegen.zig+2-2
......@@ -1532,7 +1532,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15321532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
15331533 const func = func_val.func;
15341534 const got = &macho_file.sections.items[macho_file.got_section_index.?];
1535 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index.? * @sizeOf(u64);
1535 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
15361536 // Here, we store the got address in %rax, and then call %rax
15371537 // movabsq [addr], %rax
15381538 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
......@@ -2591,7 +2591,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
25912591 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
25922592 const decl = payload.decl;
25932593 const got = &macho_file.sections.items[macho_file.got_section_index.?];
2594 const got_addr = got.addr + decl.link.macho.offset_table_index.? * ptr_bytes;
2594 const got_addr = got.addr + decl.link.macho.offset_table_index * ptr_bytes;
25952595 return MCValue{ .memory = got_addr };
25962596 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
25972597 const decl = payload.decl;
src/link/MachO.zig+46-28
......@@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System";
149149const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib";
150150
151151pub const TextBlock = struct {
152 /// Index into the symbol table
153 symbol_table_index: ?u32,
152 /// Each decl always gets a local symbol with the fully qualified name.
153 /// The vaddr and size are found here directly.
154 /// The file offset is found by computing the vaddr offset from the section vaddr
155 /// the symbol references, and adding that to the file offset of the section.
156 /// If this field is 0, it means the codegen size = 0 and there is no symbol or
157 /// offset table entry.
158 local_sym_index: u32,
154159 /// Index into offset table
155 offset_table_index: ?u32,
160 /// This field is undefined for symbols with size = 0.
161 offset_table_index: u32,
156162 /// Size of this text block
163 /// Unlike in Elf, we need to store the size of this symbol as part of
164 /// the TextBlock since macho.nlist_64 lacks this information.
157165 size: u64,
158166 /// Points to the previous and next neighbours
159167 prev: ?*TextBlock,
160168 next: ?*TextBlock,
161169
162170 pub const empty = TextBlock{
163 .symbol_table_index = null,
164 .offset_table_index = null,
171 .local_sym_index = 0,
172 .offset_table_index = undefined,
165173 .size = 0,
166174 .prev = null,
167175 .next = null,
......@@ -190,6 +198,15 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
190198
191199 self.base.file = file;
192200
201 // Index 0 is always a null symbol.
202 try self.local_symbols.append(allocator, .{
203 .n_strx = 0,
204 .n_type = 0,
205 .n_sect = 0,
206 .n_desc = 0,
207 .n_value = 0,
208 });
209
193210 switch (options.output_mode) {
194211 .Exe => {},
195212 .Obj => {},
......@@ -717,26 +734,26 @@ pub fn deinit(self: *MachO) void {
717734}
718735
719736pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
720 if (decl.link.macho.symbol_table_index) |_| return;
737 if (decl.link.macho.local_sym_index != 0) return;
721738
722739 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);
723740 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
724741
725742 log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });
726 decl.link.macho.symbol_table_index = @intCast(u32, self.local_symbols.items.len);
743 decl.link.macho.local_sym_index = @intCast(u32, self.local_symbols.items.len);
727744 _ = self.local_symbols.addOneAssumeCapacity();
728745
729746 decl.link.macho.offset_table_index = @intCast(u32, self.offset_table.items.len);
730747 _ = self.offset_table.addOneAssumeCapacity();
731748
732 self.local_symbols.items[decl.link.macho.symbol_table_index.?] = .{
749 self.local_symbols.items[decl.link.macho.local_sym_index] = .{
733750 .n_strx = 0,
734751 .n_type = 0,
735752 .n_sect = 0,
736753 .n_desc = 0,
737754 .n_value = 0,
738755 };
739 self.offset_table.items[decl.link.macho.offset_table_index.?] = 0;
756 self.offset_table.items[decl.link.macho.offset_table_index] = 0;
740757}
741758
742759pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
......@@ -761,7 +778,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
761778 log.debug("generated code {}\n", .{code});
762779
763780 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
764 const symbol = &self.local_symbols.items[decl.link.macho.symbol_table_index.?];
781 const symbol = &self.local_symbols.items[decl.link.macho.local_sym_index];
765782
766783 const decl_name = mem.spanZ(decl.name);
767784 const name_str_index = try self.makeString(decl_name);
......@@ -776,10 +793,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
776793 .n_desc = 0,
777794 .n_value = addr,
778795 };
779 self.offset_table.items[decl.link.macho.offset_table_index.?] = addr;
796 self.offset_table.items[decl.link.macho.offset_table_index] = addr;
780797
781 try self.writeSymbol(decl.link.macho.symbol_table_index.?);
782 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index.?);
798 try self.writeSymbol(decl.link.macho.local_sym_index);
799 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index);
783800
784801 const text_section = self.sections.items[self.text_section_index.?];
785802 const section_offset = symbol.n_value - text_section.addr;
......@@ -805,8 +822,8 @@ pub fn updateDeclExports(
805822 defer tracy.end();
806823
807824 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
808 if (decl.link.macho.symbol_table_index == null) return;
809 const decl_sym = &self.local_symbols.items[decl.link.macho.symbol_table_index.?];
825 if (decl.link.macho.local_sym_index == 0) return;
826 const decl_sym = &self.local_symbols.items[decl.link.macho.local_sym_index];
810827
811828 for (exports) |exp| {
812829 if (exp.options.section) |section_name| {
......@@ -867,7 +884,8 @@ pub fn updateDeclExports(
867884pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
868885
869886pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
870 return self.local_symbols.items[decl.link.macho.symbol_table_index.?].n_value;
887 assert(decl.link.macho.local_sym_index != 0);
888 return self.local_symbols.items[decl.link.macho.local_sym_index].n_value;
871889}
872890
873891pub fn populateMissingMetadata(self: *MachO) !void {
......@@ -1126,17 +1144,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11261144 });
11271145 self.cmd_table_dirty = true;
11281146 }
1129 if (self.dyld_stub_binder_index == null) {
1130 self.dyld_stub_binder_index = @intCast(u16, self.undef_symbols.items.len);
1131 const name = try self.makeString("dyld_stub_binder");
1132 try self.undef_symbols.append(self.base.allocator, .{
1133 .n_strx = name,
1134 .n_type = macho.N_UNDF | macho.N_EXT,
1135 .n_sect = 0,
1136 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1137 .n_value = 0,
1138 });
1139 }
11401147 {
11411148 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
11421149 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo;
......@@ -1175,6 +1182,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11751182 symtab.strsize = file_size;
11761183 }
11771184 }
1185 if (self.dyld_stub_binder_index == null) {
1186 self.dyld_stub_binder_index = @intCast(u16, self.undef_symbols.items.len);
1187 const name = try self.makeString("dyld_stub_binder");
1188 try self.undef_symbols.append(self.base.allocator, .{
1189 .n_strx = name,
1190 .n_type = macho.N_UNDF | macho.N_EXT,
1191 .n_sect = 0,
1192 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1193 .n_value = 0,
1194 });
1195 }
11781196}
11791197
11801198fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
......@@ -1184,7 +1202,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
11841202 var block_placement: ?*TextBlock = null;
11851203 const addr = blk: {
11861204 if (self.last_text_block) |last| {
1187 const last_symbol = self.local_symbols.items[last.symbol_table_index.?];
1205 const last_symbol = self.local_symbols.items[last.local_sym_index];
11881206 // TODO pad out with NOPs and reenable
11891207 // const ideal_capacity = last.size * alloc_num / alloc_den;
11901208 // const ideal_capacity_end_addr = last_symbol.n_value + ideal_capacity;