| ... | @@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System"; | ... | @@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System"; |
| 149 | const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib"; | 149 | const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib"; |
| 150 | | 150 | |
| 151 | pub const TextBlock = struct { | 151 | pub const TextBlock = struct { |
| 152 | /// Index into the symbol table | 152 | /// 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 table | 159 | /// 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 block | 162 | /// 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 neighbours | 166 | /// Points to the previous and next neighbours |
| 159 | prev: ?*TextBlock, | 167 | prev: ?*TextBlock, |
| 160 | next: ?*TextBlock, | 168 | next: ?*TextBlock, |
| 161 | | 169 | |
| 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 |
| 190 | | 198 | |
| 191 | self.base.file = file; | 199 | self.base.file = file; |
| 192 | | 200 | |
| | 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 | } |
| 718 | | 735 | |
| 719 | pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | 736 | pub 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; |
| 721 | | 738 | |
| 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); |
| 724 | | 741 | |
| 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(); |
| 728 | | 745 | |
| 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(); |
| 731 | | 748 | |
| 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 | } |
| 741 | | 758 | |
| 742 | pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | 759 | 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,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}); |
| 762 | | 779 | |
| 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]; |
| 765 | | 782 | |
| 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; |
| 780 | | 797 | |
| 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); |
| 783 | | 800 | |
| 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(); |
| 806 | | 823 | |
| 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]; |
| 810 | | 827 | |
| 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( |
| 867 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {} | 884 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {} |
| 868 | | 885 | |
| 869 | pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { | 886 | pub 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 | } |
| 872 | | 890 | |
| 873 | pub fn populateMissingMetadata(self: *MachO) !void { | 891 | pub 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 | } |
| 1179 | | 1197 | |
| 1180 | fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | 1198 | fn 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 reenable | 1206 | // 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; |