| ... | ... | @@ -149,19 +149,27 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System"; |
| 149 | 149 | const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib"; |
| 150 | 150 | |
| 151 | 151 | pub 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, |
| 154 | 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 | 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 | 165 | size: u64, |
| 158 | 166 | /// Points to the previous and next neighbours |
| 159 | 167 | prev: ?*TextBlock, |
| 160 | 168 | next: ?*TextBlock, |
| 161 | 169 | |
| 162 | 170 | pub const empty = TextBlock{ |
| 163 | | .symbol_table_index = null, |
| 164 | | .offset_table_index = null, |
| 171 | .local_sym_index = 0, |
| 172 | .offset_table_index = undefined, |
| 165 | 173 | .size = 0, |
| 166 | 174 | .prev = null, |
| 167 | 175 | .next = null, |
| ... | ... | @@ -190,6 +198,15 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 190 | 198 | |
| 191 | 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 | 210 | switch (options.output_mode) { |
| 194 | 211 | .Exe => {}, |
| 195 | 212 | .Obj => {}, |
| ... | ... | @@ -717,26 +734,26 @@ pub fn deinit(self: *MachO) void { |
| 717 | 734 | } |
| 718 | 735 | |
| 719 | 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 | 739 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); |
| 723 | 740 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 724 | 741 | |
| 725 | 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 | 744 | _ = self.local_symbols.addOneAssumeCapacity(); |
| 728 | 745 | |
| 729 | 746 | decl.link.macho.offset_table_index = @intCast(u32, self.offset_table.items.len); |
| 730 | 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 | 750 | .n_strx = 0, |
| 734 | 751 | .n_type = 0, |
| 735 | 752 | .n_sect = 0, |
| 736 | 753 | .n_desc = 0, |
| 737 | 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 | 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 | 778 | log.debug("generated code {}\n", .{code}); |
| 762 | 779 | |
| 763 | 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 | 783 | const decl_name = mem.spanZ(decl.name); |
| 767 | 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 | 793 | .n_desc = 0, |
| 777 | 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.?); |
| 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); |
| 783 | 800 | |
| 784 | 801 | const text_section = self.sections.items[self.text_section_index.?]; |
| 785 | 802 | const section_offset = symbol.n_value - text_section.addr; |
| ... | ... | @@ -805,8 +822,8 @@ pub fn updateDeclExports( |
| 805 | 822 | defer tracy.end(); |
| 806 | 823 | |
| 807 | 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; |
| 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]; |
| 810 | 827 | |
| 811 | 828 | for (exports) |exp| { |
| 812 | 829 | if (exp.options.section) |section_name| { |
| ... | ... | @@ -867,7 +884,8 @@ pub fn updateDeclExports( |
| 867 | 884 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {} |
| 868 | 885 | |
| 869 | 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 | 891 | pub fn populateMissingMetadata(self: *MachO) !void { |
| ... | ... | @@ -1126,17 +1144,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1126 | 1144 | }); |
| 1127 | 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 | 1148 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 1142 | 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 | 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 | 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 | 1202 | var block_placement: ?*TextBlock = null; |
| 1185 | 1203 | const addr = blk: { |
| 1186 | 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 | 1206 | // TODO pad out with NOPs and reenable |
| 1189 | 1207 | // const ideal_capacity = last.size * alloc_num / alloc_den; |
| 1190 | 1208 | // const ideal_capacity_end_addr = last_symbol.n_value + ideal_capacity; |