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 {...@@ -1532,7 +1532,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1532 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1533 const func = func_val.func;1533 const func = func_val.func;
1534 const got = &macho_file.sections.items[macho_file.got_section_index.?];1534 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);
1536 // Here, we store the got address in %rax, and then call %rax1536 // Here, we store the got address in %rax, and then call %rax
1537 // movabsq [addr], %rax1537 // movabsq [addr], %rax
1538 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });1538 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
...@@ -2591,7 +2591,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2591,7 +2591,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2591 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {2591 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
2592 const decl = payload.decl;2592 const decl = payload.decl;
2593 const got = &macho_file.sections.items[macho_file.got_section_index.?];2593 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;
2595 return MCValue{ .memory = got_addr };2595 return MCValue{ .memory = got_addr };
2596 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {2596 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2597 const decl = payload.decl;2597 const decl = payload.decl;
src/link/MachO.zig+46-28
...@@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System";...@@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System";
149const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib";149const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib";
150150
151pub const TextBlock = struct {151pub const TextBlock = struct {
152 /// Index into the symbol table152 /// Each decl always gets a local symbol with the fully qualified name.
153 symbol_table_index: ?u32,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,
154 /// Index into offset table159 /// Index into offset table
155 offset_table_index: ?u32,160 /// This field is undefined for symbols with size = 0.
161 offset_table_index: u32,
156 /// Size of this text block162 /// 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.
157 size: u64,165 size: u64,
158 /// Points to the previous and next neighbours166 /// Points to the previous and next neighbours
159 prev: ?*TextBlock,167 prev: ?*TextBlock,
160 next: ?*TextBlock,168 next: ?*TextBlock,
161169
162 pub const empty = TextBlock{170 pub const empty = TextBlock{
163 .symbol_table_index = null,171 .local_sym_index = 0,
164 .offset_table_index = null,172 .offset_table_index = undefined,
165 .size = 0,173 .size = 0,
166 .prev = null,174 .prev = null,
167 .next = null,175 .next = null,
...@@ -190,6 +198,15 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -190,6 +198,15 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
190198
191 self.base.file = file;199 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
193 switch (options.output_mode) {210 switch (options.output_mode) {
194 .Exe => {},211 .Exe => {},
195 .Obj => {},212 .Obj => {},
...@@ -717,26 +734,26 @@ pub fn deinit(self: *MachO) void {...@@ -717,26 +734,26 @@ pub fn deinit(self: *MachO) void {
717}734}
718735
719pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {736pub 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
722 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);739 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);
723 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);740 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
724741
725 log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });742 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);
727 _ = self.local_symbols.addOneAssumeCapacity();744 _ = self.local_symbols.addOneAssumeCapacity();
728745
729 decl.link.macho.offset_table_index = @intCast(u32, self.offset_table.items.len);746 decl.link.macho.offset_table_index = @intCast(u32, self.offset_table.items.len);
730 _ = self.offset_table.addOneAssumeCapacity();747 _ = 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] = .{
733 .n_strx = 0,750 .n_strx = 0,
734 .n_type = 0,751 .n_type = 0,
735 .n_sect = 0,752 .n_sect = 0,
736 .n_desc = 0,753 .n_desc = 0,
737 .n_value = 0,754 .n_value = 0,
738 };755 };
739 self.offset_table.items[decl.link.macho.offset_table_index.?] = 0;756 self.offset_table.items[decl.link.macho.offset_table_index] = 0;
740}757}
741758
742pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {759pub 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 {...@@ -761,7 +778,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
761 log.debug("generated code {}\n", .{code});778 log.debug("generated code {}\n", .{code});
762779
763 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);780 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
766 const decl_name = mem.spanZ(decl.name);783 const decl_name = mem.spanZ(decl.name);
767 const name_str_index = try self.makeString(decl_name);784 const name_str_index = try self.makeString(decl_name);
...@@ -776,10 +793,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -776,10 +793,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
776 .n_desc = 0,793 .n_desc = 0,
777 .n_value = addr,794 .n_value = addr,
778 };795 };
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.?);798 try self.writeSymbol(decl.link.macho.local_sym_index);
782 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index.?);799 try self.writeOffsetTableEntry(decl.link.macho.offset_table_index);
783800
784 const text_section = self.sections.items[self.text_section_index.?];801 const text_section = self.sections.items[self.text_section_index.?];
785 const section_offset = symbol.n_value - text_section.addr;802 const section_offset = symbol.n_value - text_section.addr;
...@@ -805,8 +822,8 @@ pub fn updateDeclExports(...@@ -805,8 +822,8 @@ pub fn updateDeclExports(
805 defer tracy.end();822 defer tracy.end();
806823
807 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);824 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;825 if (decl.link.macho.local_sym_index == 0) return;
809 const decl_sym = &self.local_symbols.items[decl.link.macho.symbol_table_index.?];826 const decl_sym = &self.local_symbols.items[decl.link.macho.local_sym_index];
810827
811 for (exports) |exp| {828 for (exports) |exp| {
812 if (exp.options.section) |section_name| {829 if (exp.options.section) |section_name| {
...@@ -867,7 +884,8 @@ pub fn updateDeclExports(...@@ -867,7 +884,8 @@ pub fn updateDeclExports(
867pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}884pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
868885
869pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {886pub 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;
871}889}
872890
873pub fn populateMissingMetadata(self: *MachO) !void {891pub fn populateMissingMetadata(self: *MachO) !void {
...@@ -1126,17 +1144,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1126,17 +1144,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1126 });1144 });
1127 self.cmd_table_dirty = true;1145 self.cmd_table_dirty = true;
1128 }1146 }
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 }
1140 {1147 {
1141 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;1148 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
1142 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo;1149 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo;
...@@ -1175,6 +1182,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1175,6 +1182,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1175 symtab.strsize = file_size;1182 symtab.strsize = file_size;
1176 }1183 }
1177 }1184 }
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 }
1178}1196}
11791197
1180fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {1198fn 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,...@@ -1184,7 +1202,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
1184 var block_placement: ?*TextBlock = null;1202 var block_placement: ?*TextBlock = null;
1185 const addr = blk: {1203 const addr = blk: {
1186 if (self.last_text_block) |last| {1204 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];
1188 // TODO pad out with NOPs and reenable1206 // TODO pad out with NOPs and reenable
1189 // const ideal_capacity = last.size * alloc_num / alloc_den;1207 // const ideal_capacity = last.size * alloc_num / alloc_den;
1190 // const ideal_capacity_end_addr = last_symbol.n_value + ideal_capacity;1208 // const ideal_capacity_end_addr = last_symbol.n_value + ideal_capacity;