| ... | @@ -154,17 +154,13 @@ stub_preamble_sym_index: ?u32 = null, | ... | @@ -154,17 +154,13 @@ stub_preamble_sym_index: ?u32 = null, |
| 154 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 154 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 155 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 155 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 156 | | 156 | |
| 157 | got_entries: std.ArrayListUnmanaged(GotIndirectionKey) = .{}, | 157 | got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *TextBlock) = .{}, |
| 158 | got_entries_map: std.AutoHashMapUnmanaged(GotIndirectionKey, u32) = .{}, | | |
| 159 | | | |
| 160 | got_entries_free_list: std.ArrayListUnmanaged(u32) = .{}, | | |
| 161 | | 158 | |
| 162 | stubs: std.ArrayListUnmanaged(u32) = .{}, | 159 | stubs: std.ArrayListUnmanaged(u32) = .{}, |
| 163 | stubs_map: std.AutoHashMapUnmanaged(u32, u32) = .{}, | 160 | stubs_map: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 164 | | 161 | |
| 165 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 162 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 166 | | 163 | |
| 167 | got_entries_count_dirty: bool = false, | | |
| 168 | load_commands_dirty: bool = false, | 164 | load_commands_dirty: bool = false, |
| 169 | rebase_info_dirty: bool = false, | 165 | rebase_info_dirty: bool = false, |
| 170 | binding_info_dirty: bool = false, | 166 | binding_info_dirty: bool = false, |
| ... | @@ -876,7 +872,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -876,7 +872,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 876 | self.error_flags.no_entry_point_found = false; | 872 | self.error_flags.no_entry_point_found = false; |
| 877 | } | 873 | } |
| 878 | | 874 | |
| 879 | assert(!self.got_entries_count_dirty); | | |
| 880 | assert(!self.load_commands_dirty); | 875 | assert(!self.load_commands_dirty); |
| 881 | assert(!self.rebase_info_dirty); | 876 | assert(!self.rebase_info_dirty); |
| 882 | assert(!self.binding_info_dirty); | 877 | assert(!self.binding_info_dirty); |
| ... | @@ -1731,16 +1726,9 @@ fn allocateTextSegment(self: *MachO) !void { | ... | @@ -1731,16 +1726,9 @@ fn allocateTextSegment(self: *MachO) !void { |
| 1731 | | 1726 | |
| 1732 | fn allocateDataConstSegment(self: *MachO) !void { | 1727 | fn allocateDataConstSegment(self: *MachO) !void { |
| 1733 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 1728 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 1734 | const nentries = @intCast(u32, self.got_entries.items.len); | | |
| 1735 | | | |
| 1736 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 1729 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1737 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; | 1730 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| 1738 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; | 1731 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; |
| 1739 | | | |
| 1740 | // Set got size | | |
| 1741 | const got = &seg.sections.items[self.got_section_index.?]; | | |
| 1742 | got.size += nentries * @sizeOf(u64); | | |
| 1743 | | | |
| 1744 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); | 1732 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); |
| 1745 | } | 1733 | } |
| 1746 | | 1734 | |
| ... | @@ -1927,7 +1915,7 @@ fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32 | ... | @@ -1927,7 +1915,7 @@ fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32 |
| 1927 | return atom; | 1915 | return atom; |
| 1928 | } | 1916 | } |
| 1929 | | 1917 | |
| 1930 | fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | 1918 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1931 | // TODO converge with `allocateTextBlock` | 1919 | // TODO converge with `allocateTextBlock` |
| 1932 | const seg = self.load_commands.items[match.seg].Segment; | 1920 | const seg = self.load_commands.items[match.seg].Segment; |
| 1933 | const sect = seg.sections.items[match.sect]; | 1921 | const sect = seg.sections.items[match.sect]; |
| ... | @@ -1936,7 +1924,8 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | ... | @@ -1936,7 +1924,8 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1936 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 1924 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1937 | break :blk last_atom_sym.n_value + last.size; | 1925 | break :blk last_atom_sym.n_value + last.size; |
| 1938 | } else sect.addr; | 1926 | } else sect.addr; |
| 1939 | const atom_alignment = try math.powi(u32, 2, atom.alignment); | 1927 | // const atom_alignment = try math.powi(u32, 2, atom.alignment); TODO |
| | 1928 | const atom_alignment = math.powi(u32, 2, atom.alignment) catch unreachable; |
| 1940 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); | 1929 | const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment); |
| 1941 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); | 1930 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1942 | | 1931 | |
| ... | @@ -1956,7 +1945,7 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | ... | @@ -1956,7 +1945,7 @@ fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1956 | return vaddr; | 1945 | return vaddr; |
| 1957 | } | 1946 | } |
| 1958 | | 1947 | |
| 1959 | fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | 1948 | pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { |
| 1960 | const seg = self.load_commands.items[match.seg].Segment; | 1949 | const seg = self.load_commands.items[match.seg].Segment; |
| 1961 | const sect = seg.sections.items[match.sect]; | 1950 | const sect = seg.sections.items[match.sect]; |
| 1962 | const sym = self.locals.items[atom.local_sym_index]; | 1951 | const sym = self.locals.items[atom.local_sym_index]; |
| ... | @@ -1967,7 +1956,7 @@ fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | ... | @@ -1967,7 +1956,7 @@ fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { |
| 1967 | try self.writeLocalSymbol(atom.local_sym_index); | 1956 | try self.writeLocalSymbol(atom.local_sym_index); |
| 1968 | } | 1957 | } |
| 1969 | | 1958 | |
| 1970 | fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | 1959 | pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { |
| 1971 | // Update target section's metadata | 1960 | // Update target section's metadata |
| 1972 | // TODO should we update segment's size here too? | 1961 | // TODO should we update segment's size here too? |
| 1973 | // How does it tie with incremental space allocs? | 1962 | // How does it tie with incremental space allocs? |
| ... | @@ -1988,7 +1977,7 @@ fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !v | ... | @@ -1988,7 +1977,7 @@ fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !v |
| 1988 | } | 1977 | } |
| 1989 | } | 1978 | } |
| 1990 | | 1979 | |
| 1991 | fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { | 1980 | pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { |
| 1992 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1981 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1993 | try self.locals.append(self.base.allocator, .{ | 1982 | try self.locals.append(self.base.allocator, .{ |
| 1994 | .n_strx = try self.makeString("got_entry"), | 1983 | .n_strx = try self.makeString("got_entry"), |
| ... | @@ -2804,15 +2793,12 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2804,15 +2793,12 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2804 | } | 2793 | } |
| 2805 | | 2794 | |
| 2806 | // Add dyld_stub_binder as the final GOT entry. | 2795 | // Add dyld_stub_binder as the final GOT entry. |
| 2807 | const got_index = @intCast(u32, self.got_entries.items.len); | | |
| 2808 | const got_entry = GotIndirectionKey{ | 2796 | const got_entry = GotIndirectionKey{ |
| 2809 | .where = .undef, | 2797 | .where = .undef, |
| 2810 | .where_index = self.dyld_stub_binder_index.?, | 2798 | .where_index = self.dyld_stub_binder_index.?, |
| 2811 | }; | 2799 | }; |
| 2812 | try self.got_entries.append(self.base.allocator, got_entry); | | |
| 2813 | try self.got_entries_map.putNoClobber(self.base.allocator, got_entry, got_index); | | |
| 2814 | | | |
| 2815 | const atom = try self.createGotAtom(got_entry); | 2800 | const atom = try self.createGotAtom(got_entry); |
| | 2801 | try self.got_entries_map.putNoClobber(self.base.allocator, got_entry, atom); |
| 2816 | const match = MatchingSection{ | 2802 | const match = MatchingSection{ |
| 2817 | .seg = self.data_const_segment_cmd_index.?, | 2803 | .seg = self.data_const_segment_cmd_index.?, |
| 2818 | .sect = self.got_section_index.?, | 2804 | .sect = self.got_section_index.?, |
| ... | @@ -2917,7 +2903,6 @@ fn flushZld(self: *MachO) !void { | ... | @@ -2917,7 +2903,6 @@ fn flushZld(self: *MachO) !void { |
| 2917 | sect.offset = 0; | 2903 | sect.offset = 0; |
| 2918 | } | 2904 | } |
| 2919 | | 2905 | |
| 2920 | try self.writeGotEntries(); | | |
| 2921 | try self.setEntryPoint(); | 2906 | try self.setEntryPoint(); |
| 2922 | try self.writeRebaseInfoTableZld(); | 2907 | try self.writeRebaseInfoTableZld(); |
| 2923 | try self.writeBindInfoTableZld(); | 2908 | try self.writeBindInfoTableZld(); |
| ... | @@ -2952,29 +2937,6 @@ fn flushZld(self: *MachO) !void { | ... | @@ -2952,29 +2937,6 @@ fn flushZld(self: *MachO) !void { |
| 2952 | } | 2937 | } |
| 2953 | } | 2938 | } |
| 2954 | | 2939 | |
| 2955 | fn writeGotEntries(self: *MachO) !void { | | |
| 2956 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 2957 | const sect = seg.sections.items[self.got_section_index.?]; | | |
| 2958 | | | |
| 2959 | var buffer = try self.base.allocator.alloc(u8, self.got_entries.items.len * @sizeOf(u64)); | | |
| 2960 | defer self.base.allocator.free(buffer); | | |
| 2961 | | | |
| 2962 | var stream = std.io.fixedBufferStream(buffer); | | |
| 2963 | var writer = stream.writer(); | | |
| 2964 | | | |
| 2965 | for (self.got_entries.items) |key| { | | |
| 2966 | const address: u64 = switch (key.where) { | | |
| 2967 | .local => self.locals.items[key.where_index].n_value, | | |
| 2968 | .undef => 0, | | |
| 2969 | }; | | |
| 2970 | try writer.writeIntLittle(u64, address); | | |
| 2971 | } | | |
| 2972 | | | |
| 2973 | log.debug("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len }); | | |
| 2974 | | | |
| 2975 | try self.base.file.?.pwriteAll(buffer, sect.offset); | | |
| 2976 | } | | |
| 2977 | | | |
| 2978 | fn setEntryPoint(self: *MachO) !void { | 2940 | fn setEntryPoint(self: *MachO) !void { |
| 2979 | if (self.base.options.output_mode != .Exe) return; | 2941 | if (self.base.options.output_mode != .Exe) return; |
| 2980 | | 2942 | |
| ... | @@ -3028,22 +2990,6 @@ fn writeRebaseInfoTableZld(self: *MachO) !void { | ... | @@ -3028,22 +2990,6 @@ fn writeRebaseInfoTableZld(self: *MachO) !void { |
| 3028 | } | 2990 | } |
| 3029 | } | 2991 | } |
| 3030 | | 2992 | |
| 3031 | if (self.got_section_index) |idx| { | | |
| 3032 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 3033 | const sect = seg.sections.items[idx]; | | |
| 3034 | const base_offset = sect.addr - seg.inner.vmaddr; | | |
| 3035 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | | |
| 3036 | | | |
| 3037 | for (self.got_entries.items) |entry, i| { | | |
| 3038 | if (entry.where == .undef) continue; | | |
| 3039 | | | |
| 3040 | try pointers.append(.{ | | |
| 3041 | .offset = base_offset + i * @sizeOf(u64), | | |
| 3042 | .segment_id = segment_id, | | |
| 3043 | }); | | |
| 3044 | } | | |
| 3045 | } | | |
| 3046 | | | |
| 3047 | std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp); | 2993 | std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp); |
| 3048 | | 2994 | |
| 3049 | const size = try bind.rebaseInfoSize(pointers.items); | 2995 | const size = try bind.rebaseInfoSize(pointers.items); |
| ... | @@ -3068,25 +3014,6 @@ fn writeBindInfoTableZld(self: *MachO) !void { | ... | @@ -3068,25 +3014,6 @@ fn writeBindInfoTableZld(self: *MachO) !void { |
| 3068 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); | 3014 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); |
| 3069 | defer pointers.deinit(); | 3015 | defer pointers.deinit(); |
| 3070 | | 3016 | |
| 3071 | if (self.got_section_index) |idx| { | | |
| 3072 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 3073 | const sect = seg.sections.items[idx]; | | |
| 3074 | const base_offset = sect.addr - seg.inner.vmaddr; | | |
| 3075 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | | |
| 3076 | | | |
| 3077 | for (self.got_entries.items) |entry, i| { | | |
| 3078 | if (entry.where == .local) continue; | | |
| 3079 | | | |
| 3080 | const sym = self.undefs.items[entry.where_index]; | | |
| 3081 | try pointers.append(.{ | | |
| 3082 | .offset = base_offset + i * @sizeOf(u64), | | |
| 3083 | .segment_id = segment_id, | | |
| 3084 | .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER), | | |
| 3085 | .name = self.getString(sym.n_strx), | | |
| 3086 | }); | | |
| 3087 | } | | |
| 3088 | } | | |
| 3089 | | | |
| 3090 | { | 3017 | { |
| 3091 | var it = self.blocks.iterator(); | 3018 | var it = self.blocks.iterator(); |
| 3092 | while (it.next()) |entry| { | 3019 | while (it.next()) |entry| { |
| ... | @@ -3319,7 +3246,7 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -3319,7 +3246,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 3319 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; | 3246 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 3320 | | 3247 | |
| 3321 | const nstubs = @intCast(u32, self.stubs.items.len); | 3248 | const nstubs = @intCast(u32, self.stubs.items.len); |
| 3322 | const ngot_entries = @intCast(u32, self.got_entries.items.len); | 3249 | const ngot_entries = @intCast(u32, self.got_entries_map.keys().len); |
| 3323 | | 3250 | |
| 3324 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | 3251 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 3325 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; | 3252 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; |
| ... | @@ -3344,10 +3271,10 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -3344,10 +3271,10 @@ fn writeSymbolTable(self: *MachO) !void { |
| 3344 | } | 3271 | } |
| 3345 | | 3272 | |
| 3346 | got.reserved1 = nstubs; | 3273 | got.reserved1 = nstubs; |
| 3347 | for (self.got_entries.items) |entry| { | 3274 | for (self.got_entries_map.keys()) |key| { |
| 3348 | switch (entry.where) { | 3275 | switch (key.where) { |
| 3349 | .undef => { | 3276 | .undef => { |
| 3350 | try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index); | 3277 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key.where_index); |
| 3351 | }, | 3278 | }, |
| 3352 | .local => { | 3279 | .local => { |
| 3353 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); | 3280 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); |
| ... | @@ -3373,9 +3300,7 @@ pub fn deinit(self: *MachO) void { | ... | @@ -3373,9 +3300,7 @@ pub fn deinit(self: *MachO) void { |
| 3373 | } | 3300 | } |
| 3374 | | 3301 | |
| 3375 | self.section_ordinals.deinit(self.base.allocator); | 3302 | self.section_ordinals.deinit(self.base.allocator); |
| 3376 | self.got_entries.deinit(self.base.allocator); | | |
| 3377 | self.got_entries_map.deinit(self.base.allocator); | 3303 | self.got_entries_map.deinit(self.base.allocator); |
| 3378 | self.got_entries_free_list.deinit(self.base.allocator); | | |
| 3379 | self.stubs.deinit(self.base.allocator); | 3304 | self.stubs.deinit(self.base.allocator); |
| 3380 | self.stubs_map.deinit(self.base.allocator); | 3305 | self.stubs_map.deinit(self.base.allocator); |
| 3381 | self.strtab_dir.deinit(self.base.allocator); | 3306 | self.strtab_dir.deinit(self.base.allocator); |
| ... | @@ -3539,8 +3464,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | ... | @@ -3539,8 +3464,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { |
| 3539 | if (decl.link.macho.local_sym_index != 0) return; | 3464 | if (decl.link.macho.local_sym_index != 0) return; |
| 3540 | | 3465 | |
| 3541 | try self.locals.ensureUnusedCapacity(self.base.allocator, 1); | 3466 | try self.locals.ensureUnusedCapacity(self.base.allocator, 1); |
| 3542 | try self.got_entries.ensureUnusedCapacity(self.base.allocator, 1); | | |
| 3543 | | | |
| 3544 | try self.decls.putNoClobber(self.base.allocator, decl, {}); | 3467 | try self.decls.putNoClobber(self.base.allocator, decl, {}); |
| 3545 | | 3468 | |
| 3546 | if (self.locals_free_list.popOrNull()) |i| { | 3469 | if (self.locals_free_list.popOrNull()) |i| { |
| ... | @@ -3552,20 +3475,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | ... | @@ -3552,20 +3475,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { |
| 3552 | _ = self.locals.addOneAssumeCapacity(); | 3475 | _ = self.locals.addOneAssumeCapacity(); |
| 3553 | } | 3476 | } |
| 3554 | | 3477 | |
| 3555 | const got_index: u32 = blk: { | | |
| 3556 | if (self.got_entries_free_list.popOrNull()) |i| { | | |
| 3557 | log.debug("reusing GOT entry index {d} for {s}", .{ i, decl.name }); | | |
| 3558 | break :blk i; | | |
| 3559 | } else { | | |
| 3560 | const got_index = @intCast(u32, self.got_entries.items.len); | | |
| 3561 | log.debug("allocating GOT entry index {d} for {s}", .{ got_index, decl.name }); | | |
| 3562 | _ = self.got_entries.addOneAssumeCapacity(); | | |
| 3563 | self.got_entries_count_dirty = true; | | |
| 3564 | self.rebase_info_dirty = true; | | |
| 3565 | break :blk got_index; | | |
| 3566 | } | | |
| 3567 | }; | | |
| 3568 | | | |
| 3569 | self.locals.items[decl.link.macho.local_sym_index] = .{ | 3478 | self.locals.items[decl.link.macho.local_sym_index] = .{ |
| 3570 | .n_strx = 0, | 3479 | .n_strx = 0, |
| 3571 | .n_type = 0, | 3480 | .n_type = 0, |
| ... | @@ -3573,12 +3482,19 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | ... | @@ -3573,12 +3482,19 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { |
| 3573 | .n_desc = 0, | 3482 | .n_desc = 0, |
| 3574 | .n_value = 0, | 3483 | .n_value = 0, |
| 3575 | }; | 3484 | }; |
| 3576 | const got_entry = GotIndirectionKey{ | 3485 | |
| | 3486 | // TODO try popping from free list first before allocating a new GOT atom. |
| | 3487 | const key = GotIndirectionKey{ |
| 3577 | .where = .local, | 3488 | .where = .local, |
| 3578 | .where_index = decl.link.macho.local_sym_index, | 3489 | .where_index = decl.link.macho.local_sym_index, |
| 3579 | }; | 3490 | }; |
| 3580 | self.got_entries.items[got_index] = got_entry; | 3491 | const got_atom = try self.createGotAtom(key); |
| 3581 | try self.got_entries_map.putNoClobber(self.base.allocator, got_entry, got_index); | 3492 | _ = try self.allocateAtom(got_atom, .{ |
| | 3493 | .seg = self.data_const_segment_cmd_index.?, |
| | 3494 | .sect = self.got_section_index.?, |
| | 3495 | }); |
| | 3496 | try self.got_entries_map.put(self.base.allocator, key, got_atom); |
| | 3497 | self.rebase_info_dirty = true; |
| 3582 | } | 3498 | } |
| 3583 | | 3499 | |
| 3584 | pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 3500 | pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| ... | @@ -3760,11 +3676,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3760,11 +3676,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3760 | | 3676 | |
| 3761 | if (vaddr != symbol.n_value) { | 3677 | if (vaddr != symbol.n_value) { |
| 3762 | log.debug(" (writing new GOT entry)", .{}); | 3678 | log.debug(" (writing new GOT entry)", .{}); |
| 3763 | const got_index = self.got_entries_map.get(.{ | 3679 | const match = MatchingSection{ |
| | 3680 | .seg = self.data_const_segment_cmd_index.?, |
| | 3681 | .sect = self.got_section_index.?, |
| | 3682 | }; |
| | 3683 | const got_atom = self.got_entries_map.get(.{ |
| 3764 | .where = .local, | 3684 | .where = .local, |
| 3765 | .where_index = decl.link.macho.local_sym_index, | 3685 | .where_index = decl.link.macho.local_sym_index, |
| 3766 | }) orelse unreachable; | 3686 | }) orelse unreachable; |
| 3767 | try self.writeGotEntry(got_index); | 3687 | // _ = try self.allocateAtom(got_atom, match); |
| | 3688 | try self.writeAtom(got_atom, match); |
| 3768 | } | 3689 | } |
| 3769 | | 3690 | |
| 3770 | symbol.n_value = vaddr; | 3691 | symbol.n_value = vaddr; |
| ... | @@ -3802,11 +3723,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3802,11 +3723,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3802 | .n_desc = 0, | 3723 | .n_desc = 0, |
| 3803 | .n_value = addr, | 3724 | .n_value = addr, |
| 3804 | }; | 3725 | }; |
| 3805 | const got_index = self.got_entries_map.get(.{ | 3726 | const match = MatchingSection{ |
| | 3727 | .seg = self.data_const_segment_cmd_index.?, |
| | 3728 | .sect = self.got_section_index.?, |
| | 3729 | }; |
| | 3730 | const got_atom = self.got_entries_map.get(.{ |
| 3806 | .where = .local, | 3731 | .where = .local, |
| 3807 | .where_index = decl.link.macho.local_sym_index, | 3732 | .where_index = decl.link.macho.local_sym_index, |
| 3808 | }) orelse unreachable; | 3733 | }) orelse unreachable; |
| 3809 | try self.writeGotEntry(got_index); | 3734 | // _ = try self.allocateAtom(got_atom, match); |
| | 3735 | try self.writeAtom(got_atom, match); |
| 3810 | | 3736 | |
| 3811 | try self.writeLocalSymbol(decl.link.macho.local_sym_index); | 3737 | try self.writeLocalSymbol(decl.link.macho.local_sym_index); |
| 3812 | if (self.d_sym) |*ds| | 3738 | if (self.d_sym) |*ds| |
| ... | @@ -3955,13 +3881,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { | ... | @@ -3955,13 +3881,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 3955 | if (decl.link.macho.local_sym_index != 0) { | 3881 | if (decl.link.macho.local_sym_index != 0) { |
| 3956 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; | 3882 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; |
| 3957 | | 3883 | |
| 3958 | const got_key = GotIndirectionKey{ | 3884 | // TODO free GOT atom here. |
| 3959 | .where = .local, | | |
| 3960 | .where_index = decl.link.macho.local_sym_index, | | |
| 3961 | }; | | |
| 3962 | const got_index = self.got_entries_map.get(got_key) orelse unreachable; | | |
| 3963 | _ = self.got_entries_map.remove(got_key); | | |
| 3964 | self.got_entries_free_list.append(self.base.allocator, got_index) catch {}; | | |
| 3965 | | 3885 | |
| 3966 | self.locals.items[decl.link.macho.local_sym_index].n_type = 0; | 3886 | self.locals.items[decl.link.macho.local_sym_index].n_type = 0; |
| 3967 | decl.link.macho.local_sym_index = 0; | 3887 | decl.link.macho.local_sym_index = 0; |
| ... | @@ -4789,29 +4709,6 @@ fn findFreeSpaceLinkedit(self: *MachO, object_size: u64, min_alignment: u16, sta | ... | @@ -4789,29 +4709,6 @@ fn findFreeSpaceLinkedit(self: *MachO, object_size: u64, min_alignment: u16, sta |
| 4789 | return st; | 4709 | return st; |
| 4790 | } | 4710 | } |
| 4791 | | 4711 | |
| 4792 | fn writeGotEntry(self: *MachO, index: usize) !void { | | |
| 4793 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 4794 | const sect = &seg.sections.items[self.got_section_index.?]; | | |
| 4795 | const off = sect.offset + @sizeOf(u64) * index; | | |
| 4796 | | | |
| 4797 | if (self.got_entries_count_dirty) { | | |
| 4798 | // TODO relocate. | | |
| 4799 | self.got_entries_count_dirty = false; | | |
| 4800 | } | | |
| 4801 | | | |
| 4802 | const got_entry = self.got_entries.items[index]; | | |
| 4803 | const sym = switch (got_entry.where) { | | |
| 4804 | .local => self.locals.items[got_entry.where_index], | | |
| 4805 | .undef => self.undefs.items[got_entry.where_index], | | |
| 4806 | }; | | |
| 4807 | log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{ | | |
| 4808 | off, | | |
| 4809 | sym.n_value, | | |
| 4810 | self.getString(sym.n_strx), | | |
| 4811 | }); | | |
| 4812 | try self.base.file.?.pwriteAll(mem.asBytes(&sym.n_value), off); | | |
| 4813 | } | | |
| 4814 | | | |
| 4815 | fn relocateSymbolTable(self: *MachO) !void { | 4712 | fn relocateSymbolTable(self: *MachO) !void { |
| 4816 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 4713 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 4817 | const nlocals = self.locals.items.len; | 4714 | const nlocals = self.locals.items.len; |
| ... | @@ -4901,7 +4798,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void { | ... | @@ -4901,7 +4798,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void { |
| 4901 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; | 4798 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| 4902 | | 4799 | |
| 4903 | const nstubs = @intCast(u32, self.stubs.items.len); | 4800 | const nstubs = @intCast(u32, self.stubs.items.len); |
| 4904 | const ngot_entries = @intCast(u32, self.got_entries.items.len); | 4801 | const ngot_entries = @intCast(u32, self.got_entries_map.keys().len); |
| 4905 | const allocated_size = self.allocatedSizeLinkedit(dysymtab.indirectsymoff); | 4802 | const allocated_size = self.allocatedSizeLinkedit(dysymtab.indirectsymoff); |
| 4906 | const nindirectsyms = nstubs * 2 + ngot_entries; | 4803 | const nindirectsyms = nstubs * 2 + ngot_entries; |
| 4907 | const needed_size = @intCast(u32, nindirectsyms * @sizeOf(u32)); | 4804 | const needed_size = @intCast(u32, nindirectsyms * @sizeOf(u32)); |
| ... | @@ -4927,10 +4824,10 @@ fn writeIndirectSymbolTable(self: *MachO) !void { | ... | @@ -4927,10 +4824,10 @@ fn writeIndirectSymbolTable(self: *MachO) !void { |
| 4927 | } | 4824 | } |
| 4928 | | 4825 | |
| 4929 | got.reserved1 = nstubs; | 4826 | got.reserved1 = nstubs; |
| 4930 | for (self.got_entries.items) |entry| { | 4827 | for (self.got_entries_map.keys()) |key| { |
| 4931 | switch (entry.where) { | 4828 | switch (key.where) { |
| 4932 | .undef => { | 4829 | .undef => { |
| 4933 | try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index); | 4830 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key.where_index); |
| 4934 | }, | 4831 | }, |
| 4935 | .local => { | 4832 | .local => { |
| 4936 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); | 4833 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); |
| ... | @@ -5147,22 +5044,6 @@ fn writeRebaseInfoTable(self: *MachO) !void { | ... | @@ -5147,22 +5044,6 @@ fn writeRebaseInfoTable(self: *MachO) !void { |
| 5147 | } | 5044 | } |
| 5148 | } | 5045 | } |
| 5149 | | 5046 | |
| 5150 | if (self.got_section_index) |idx| { | | |
| 5151 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 5152 | const sect = seg.sections.items[idx]; | | |
| 5153 | const base_offset = sect.addr - seg.inner.vmaddr; | | |
| 5154 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | | |
| 5155 | | | |
| 5156 | for (self.got_entries.items) |entry, i| { | | |
| 5157 | if (entry.where == .undef) continue; | | |
| 5158 | | | |
| 5159 | try pointers.append(.{ | | |
| 5160 | .offset = base_offset + i * @sizeOf(u64), | | |
| 5161 | .segment_id = segment_id, | | |
| 5162 | }); | | |
| 5163 | } | | |
| 5164 | } | | |
| 5165 | | | |
| 5166 | std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp); | 5047 | std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp); |
| 5167 | | 5048 | |
| 5168 | const size = try bind.rebaseInfoSize(pointers.items); | 5049 | const size = try bind.rebaseInfoSize(pointers.items); |
| ... | @@ -5199,25 +5080,6 @@ fn writeBindInfoTable(self: *MachO) !void { | ... | @@ -5199,25 +5080,6 @@ fn writeBindInfoTable(self: *MachO) !void { |
| 5199 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); | 5080 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); |
| 5200 | defer pointers.deinit(); | 5081 | defer pointers.deinit(); |
| 5201 | | 5082 | |
| 5202 | if (self.got_section_index) |idx| { | | |
| 5203 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 5204 | const sect = seg.sections.items[idx]; | | |
| 5205 | const base_offset = sect.addr - seg.inner.vmaddr; | | |
| 5206 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | | |
| 5207 | | | |
| 5208 | for (self.got_entries.items) |entry, i| { | | |
| 5209 | if (entry.where == .local) continue; | | |
| 5210 | | | |
| 5211 | const sym = self.undefs.items[entry.where_index]; | | |
| 5212 | try pointers.append(.{ | | |
| 5213 | .offset = base_offset + i * @sizeOf(u64), | | |
| 5214 | .segment_id = segment_id, | | |
| 5215 | .dylib_ordinal = @divExact(sym.n_desc, macho.N_SYMBOL_RESOLVER), | | |
| 5216 | .name = self.getString(sym.n_strx), | | |
| 5217 | }); | | |
| 5218 | } | | |
| 5219 | } | | |
| 5220 | | | |
| 5221 | { | 5083 | { |
| 5222 | var it = self.blocks.iterator(); | 5084 | var it = self.blocks.iterator(); |
| 5223 | while (it.next()) |entry| { | 5085 | while (it.next()) |entry| { |