authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-26 14:23:28+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-26 14:23:28+02:00
log570c75cb7440935990338ee733cce4a0b966c57b
tree2cae498cce39de4746fa802f783e1db3605b5942
parent432fb7054d3214f992af5a2ef652b72d531d660b

macho: write all atoms in flush so that we can resolve relocs


2 files changed, 59 insertions(+), 87 deletions(-)

src/link/MachO.zig+45-62
...@@ -788,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -788,6 +788,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
788 try self.allocateTextBlocks();788 try self.allocateTextBlocks();
789 try self.flushZld();789 try self.flushZld();
790 } else {790 } else {
791 try self.writeAtoms();
791 try self.flushModule(comp);792 try self.flushModule(comp);
792 }793 }
793 }794 }
...@@ -1901,8 +1902,7 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64...@@ -1901,8 +1902,7 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64
1901 const last_atom_sym = self.locals.items[last.local_sym_index];1902 const last_atom_sym = self.locals.items[last.local_sym_index];
1902 break :blk last_atom_sym.n_value + last.size;1903 break :blk last_atom_sym.n_value + last.size;
1903 } else sect.addr;1904 } else sect.addr;
1904 // const atom_alignment = try math.powi(u32, 2, atom.alignment); TODO1905 const atom_alignment = try math.powi(u32, 2, atom.alignment);
1905 const atom_alignment = math.powi(u32, 2, atom.alignment) catch unreachable;
1906 const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment);1906 const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment);
1907 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });1907 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });
19081908
...@@ -1954,6 +1954,20 @@ pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection...@@ -1954,6 +1954,20 @@ pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection
1954 }1954 }
1955}1955}
19561956
1957fn writeAtoms(self: *MachO) !void {
1958 var it = self.blocks.iterator();
1959 while (it.next()) |entry| {
1960 const match = entry.key_ptr.*;
1961 var atom: *TextBlock = entry.value_ptr.*;
1962
1963 while (atom.prev) |prev| {
1964 try self.writeAtom(atom, match);
1965 atom = prev;
1966 }
1967 try self.writeAtom(atom, match);
1968 }
1969}
1970
1957pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock {1971pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock {
1958 const local_sym_index = @intCast(u32, self.locals.items.len);1972 const local_sym_index = @intCast(u32, self.locals.items.len);
1959 try self.locals.append(self.base.allocator, .{1973 try self.locals.append(self.base.allocator, .{
...@@ -2588,21 +2602,17 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2588,21 +2602,17 @@ fn resolveSymbols(self: *MachO) !void {
2588 if (!use_stage1) {2602 if (!use_stage1) {
2589 {2603 {
2590 const atom = try self.createDyldPrivateAtom();2604 const atom = try self.createDyldPrivateAtom();
2591 const match = MatchingSection{2605 _ = try self.allocateAtom(atom, .{
2592 .seg = self.data_segment_cmd_index.?,2606 .seg = self.data_segment_cmd_index.?,
2593 .sect = self.data_section_index.?,2607 .sect = self.data_section_index.?,
2594 };2608 });
2595 _ = try self.allocateAtom(atom, match);
2596 try self.writeAtom(atom, match);
2597 }2609 }
2598 {2610 {
2599 const atom = try self.createStubHelperPreambleAtom();2611 const atom = try self.createStubHelperPreambleAtom();
2600 const match = MatchingSection{2612 _ = try self.allocateAtom(atom, .{
2601 .seg = self.text_segment_cmd_index.?,2613 .seg = self.text_segment_cmd_index.?,
2602 .sect = self.stub_helper_section_index.?,2614 .sect = self.stub_helper_section_index.?,
2603 };2615 });
2604 _ = try self.allocateAtom(atom, match);
2605 try self.writeAtom(atom, match);
2606 }2616 }
2607 }2617 }
26082618
...@@ -2634,12 +2644,10 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2634,12 +2644,10 @@ fn resolveSymbols(self: *MachO) !void {
2634 if (self.stubs_map.contains(resolv.where_index)) break :outer_blk;2644 if (self.stubs_map.contains(resolv.where_index)) break :outer_blk;
2635 const stub_helper_atom = blk: {2645 const stub_helper_atom = blk: {
2636 const atom = try self.createStubHelperAtom();2646 const atom = try self.createStubHelperAtom();
2637 const match = MatchingSection{2647 _ = try self.allocateAtom(atom, .{
2638 .seg = self.text_segment_cmd_index.?,2648 .seg = self.text_segment_cmd_index.?,
2639 .sect = self.stub_helper_section_index.?,2649 .sect = self.stub_helper_section_index.?,
2640 };2650 });
2641 _ = try self.allocateAtom(atom, match);
2642 try self.writeAtom(atom, match);
2643 break :blk atom;2651 break :blk atom;
2644 };2652 };
2645 const laptr_atom = blk: {2653 const laptr_atom = blk: {
...@@ -2647,22 +2655,18 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2647,22 +2655,18 @@ fn resolveSymbols(self: *MachO) !void {
2647 stub_helper_atom.local_sym_index,2655 stub_helper_atom.local_sym_index,
2648 resolv.where_index,2656 resolv.where_index,
2649 );2657 );
2650 const match = MatchingSection{2658 _ = try self.allocateAtom(atom, .{
2651 .seg = self.data_segment_cmd_index.?,2659 .seg = self.data_segment_cmd_index.?,
2652 .sect = self.la_symbol_ptr_section_index.?,2660 .sect = self.la_symbol_ptr_section_index.?,
2653 };2661 });
2654 _ = try self.allocateAtom(atom, match);
2655 try self.writeAtom(atom, match);
2656 break :blk atom;2662 break :blk atom;
2657 };2663 };
2658 const stub_atom = blk: {2664 const stub_atom = blk: {
2659 const atom = try self.createStubAtom(laptr_atom.local_sym_index);2665 const atom = try self.createStubAtom(laptr_atom.local_sym_index);
2660 const match = MatchingSection{2666 _ = try self.allocateAtom(atom, .{
2661 .seg = self.text_segment_cmd_index.?,2667 .seg = self.text_segment_cmd_index.?,
2662 .sect = self.stubs_section_index.?,2668 .sect = self.stubs_section_index.?,
2663 };2669 });
2664 _ = try self.allocateAtom(atom, match);
2665 try self.writeAtom(atom, match);
2666 break :blk atom;2670 break :blk atom;
2667 };2671 };
2668 try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom);2672 try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom);
...@@ -2793,7 +2797,6 @@ fn resolveDyldStubBinder(self: *MachO) !void {...@@ -2793,7 +2797,6 @@ fn resolveDyldStubBinder(self: *MachO) !void {
2793 // TODO remove once we can incrementally update in stage1 too.2797 // TODO remove once we can incrementally update in stage1 too.
2794 if (!(build_options.is_stage1 and self.base.options.use_stage1)) {2798 if (!(build_options.is_stage1 and self.base.options.use_stage1)) {
2795 _ = try self.allocateAtom(atom, match);2799 _ = try self.allocateAtom(atom, match);
2796 try self.writeAtom(atom, match);
2797 } else {2800 } else {
2798 try self.allocateAtomStage1(atom, match);2801 try self.allocateAtomStage1(atom, match);
2799 }2802 }
...@@ -3480,10 +3483,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {...@@ -3480,10 +3483,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
3480 .where_index = decl.link.macho.local_sym_index,3483 .where_index = decl.link.macho.local_sym_index,
3481 };3484 };
3482 const got_atom = try self.createGotAtom(key);3485 const got_atom = try self.createGotAtom(key);
3483 _ = try self.allocateAtom(got_atom, .{
3484 .seg = self.data_const_segment_cmd_index.?,
3485 .sect = self.got_section_index.?,
3486 });
3487 try self.got_entries_map.put(self.base.allocator, key, got_atom);3486 try self.got_entries_map.put(self.base.allocator, key, got_atom);
3488 self.rebase_info_dirty = true;3487 self.rebase_info_dirty = true;
3489}3488}
...@@ -3549,9 +3548,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3549,9 +3548,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
3549 },3548 },
3550 }3549 }
35513550
3552 const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);3551 _ = try self.placeDecl(decl, decl.link.macho.code.items.len);
3553
3554 try self.writeCode(symbol, decl.link.macho.code.items);
35553552
3556 if (debug_buffers) |db| {3553 if (debug_buffers) |db| {
3557 try self.d_sym.?.commitDeclDebugInfo(3554 try self.d_sym.?.commitDeclDebugInfo(
...@@ -3642,9 +3639,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3642,9 +3639,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3642 },3639 },
3643 }3640 }
3644 };3641 };
3645 const symbol = try self.placeDecl(decl, code.len);3642 _ = try self.placeDecl(decl, code.len);
3646
3647 try self.writeCode(symbol, code);
36483643
3649 // Since we updated the vaddr and the size, each corresponding export symbol also3644 // Since we updated the vaddr and the size, each corresponding export symbol also
3650 // needs to be updated.3645 // needs to be updated.
...@@ -3667,16 +3662,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64...@@ -3667,16 +3662,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
36673662
3668 if (vaddr != symbol.n_value) {3663 if (vaddr != symbol.n_value) {
3669 log.debug(" (writing new GOT entry)", .{});3664 log.debug(" (writing new GOT entry)", .{});
3670 const match = MatchingSection{
3671 .seg = self.data_const_segment_cmd_index.?,
3672 .sect = self.got_section_index.?,
3673 };
3674 const got_atom = self.got_entries_map.get(.{3665 const got_atom = self.got_entries_map.get(.{
3675 .where = .local,3666 .where = .local,
3676 .where_index = decl.link.macho.local_sym_index,3667 .where_index = decl.link.macho.local_sym_index,
3677 }) orelse unreachable;3668 }) orelse unreachable;
3678 // _ = try self.allocateAtom(got_atom, match);3669 _ = try self.allocateAtom(got_atom, .{
3679 try self.writeAtom(got_atom, match);3670 .seg = self.data_const_segment_cmd_index.?,
3671 .sect = self.got_section_index.?,
3672 });
3680 }3673 }
36813674
3682 symbol.n_value = vaddr;3675 symbol.n_value = vaddr;
...@@ -3714,40 +3707,29 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64...@@ -3714,40 +3707,29 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
3714 .n_desc = 0,3707 .n_desc = 0,
3715 .n_value = addr,3708 .n_value = addr,
3716 };3709 };
3717 const match = MatchingSection{
3718 .seg = self.data_const_segment_cmd_index.?,
3719 .sect = self.got_section_index.?,
3720 };
3721 const got_atom = self.got_entries_map.get(.{3710 const got_atom = self.got_entries_map.get(.{
3722 .where = .local,3711 .where = .local,
3723 .where_index = decl.link.macho.local_sym_index,3712 .where_index = decl.link.macho.local_sym_index,
3724 }) orelse unreachable;3713 }) orelse unreachable;
3725 // _ = try self.allocateAtom(got_atom, match);3714 _ = try self.allocateAtom(got_atom, .{
3726 try self.writeAtom(got_atom, match);3715 .seg = self.data_const_segment_cmd_index.?,
3716 .sect = self.got_section_index.?,
3717 });
37273718
3728 try self.writeLocalSymbol(decl.link.macho.local_sym_index);3719 try self.writeLocalSymbol(decl.link.macho.local_sym_index);
3729 if (self.d_sym) |*ds|3720 if (self.d_sym) |*ds|
3730 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);3721 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);
3731 }3722 }
37323723
3733 // Resolve relocations3724 // // Resolve relocations
3734 try decl.link.macho.resolveRelocs(self);3725 // try decl.link.macho.resolveRelocs(self);
3735 // TODO this requires further investigation: should we dispose of resolved relocs, or keep them3726 // // TODO this requires further investigation: should we dispose of resolved relocs, or keep them
3736 // so that we can reapply them when moving/growing sections?3727 // // so that we can reapply them when moving/growing sections?
3737 decl.link.macho.relocs.clearAndFree(self.base.allocator);3728 // decl.link.macho.relocs.clearAndFree(self.base.allocator);
37383729
3739 return symbol;3730 return symbol;
3740}3731}
37413732
3742fn writeCode(self: *MachO, symbol: *macho.nlist_64, code: []const u8) !void {
3743 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
3744 const text_section = text_segment.sections.items[self.text_section_index.?];
3745 const section_offset = symbol.n_value - text_section.addr;
3746 const file_offset = text_section.offset + section_offset;
3747 log.debug("writing code for symbol {s} at file offset 0x{x}", .{ self.getString(symbol.n_strx), file_offset });
3748 try self.base.file.?.pwriteAll(code, file_offset);
3749}
3750
3751pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {3733pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {
3752 if (self.d_sym) |*ds| {3734 if (self.d_sym) |*ds| {
3753 try ds.updateDeclLineNumber(module, decl);3735 try ds.updateDeclLineNumber(module, decl);
...@@ -3983,7 +3965,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3983,7 +3965,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3983 .aarch64 => 3 * @sizeOf(u32),3965 .aarch64 => 3 * @sizeOf(u32),
3984 else => unreachable, // unhandled architecture type3966 else => unreachable, // unhandled architecture type
3985 };3967 };
3986 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;3968 const needed_size = stub_size * self.base.options.symbol_count_hint;
3987 const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);3969 const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
3988 assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.3970 assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.
39893971
...@@ -4739,8 +4721,9 @@ fn writeLocalSymbol(self: *MachO, index: usize) !void {...@@ -4739,8 +4721,9 @@ fn writeLocalSymbol(self: *MachO, index: usize) !void {
4739 try self.relocateSymbolTable();4721 try self.relocateSymbolTable();
4740 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;4722 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
4741 const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;4723 const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;
4742 log.debug("writing local symbol {} at 0x{x}", .{ index, off });4724 const sym = self.locals.items[index];
4743 try self.base.file.?.pwriteAll(mem.asBytes(&self.locals.items[index]), off);4725 log.debug("writing local symbol {s}: {} at 0x{x}", .{ self.getString(sym.n_strx), sym, off });
4726 try self.base.file.?.pwriteAll(mem.asBytes(&sym), off);
4744}4727}
47454728
4746fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {4729fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
src/link/MachO/TextBlock.zig+14-25
...@@ -75,6 +75,8 @@ dbg_info_off: u32,...@@ -75,6 +75,8 @@ dbg_info_off: u32,
75/// Size of the .debug_info tag for this Decl, not including padding.75/// Size of the .debug_info tag for this Decl, not including padding.
76dbg_info_len: u32,76dbg_info_len: u32,
7777
78dirty: bool = true,
79
78pub const SymbolAtOffset = struct {80pub const SymbolAtOffset = struct {
79 local_sym_index: u32,81 local_sym_index: u32,
80 offset: u64,82 offset: u64,
...@@ -843,7 +845,6 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -843,7 +845,6 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
843 };845 };
844 if (!(build_options.is_stage1 and context.macho_file.base.options.use_stage1)) {846 if (!(build_options.is_stage1 and context.macho_file.base.options.use_stage1)) {
845 _ = try context.macho_file.allocateAtom(atom, match);847 _ = try context.macho_file.allocateAtom(atom, match);
846 try context.macho_file.writeAtom(atom, match);
847 } else {848 } else {
848 try context.macho_file.allocateAtomStage1(atom, match);849 try context.macho_file.allocateAtomStage1(atom, match);
849 }850 }
...@@ -924,30 +925,18 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -924,30 +925,18 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
924 .sect = context.macho_file.stubs_section_index.?,925 .sect = context.macho_file.stubs_section_index.?,
925 });926 });
926 } else {927 } else {
927 {928 _ = try context.macho_file.allocateAtom(stub_helper_atom, .{
928 const match = MachO.MatchingSection{929 .seg = context.macho_file.text_segment_cmd_index.?,
929 .seg = context.macho_file.text_segment_cmd_index.?,930 .sect = context.macho_file.stub_helper_section_index.?,
930 .sect = context.macho_file.stub_helper_section_index.?,931 });
931 };932 _ = try context.macho_file.allocateAtom(laptr_atom, .{
932 _ = try context.macho_file.allocateAtom(stub_helper_atom, match);933 .seg = context.macho_file.data_segment_cmd_index.?,
933 try context.macho_file.writeAtom(stub_helper_atom, match);934 .sect = context.macho_file.la_symbol_ptr_section_index.?,
934 }935 });
935 {936 _ = try context.macho_file.allocateAtom(stub_atom, .{
936 const match = MachO.MatchingSection{937 .seg = context.macho_file.text_segment_cmd_index.?,
937 .seg = context.macho_file.data_segment_cmd_index.?,938 .sect = context.macho_file.stubs_section_index.?,
938 .sect = context.macho_file.la_symbol_ptr_section_index.?,939 });
939 };
940 _ = try context.macho_file.allocateAtom(laptr_atom, match);
941 try context.macho_file.writeAtom(laptr_atom, match);
942 }
943 {
944 const match = MachO.MatchingSection{
945 .seg = context.macho_file.text_segment_cmd_index.?,
946 .sect = context.macho_file.stubs_section_index.?,
947 };
948 _ = try context.macho_file.allocateAtom(stub_atom, match);
949 try context.macho_file.writeAtom(stub_atom, match);
950 }
951 }940 }
952 }941 }
953 }942 }