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 {
788788 try self.allocateTextBlocks();
789789 try self.flushZld();
790790 } else {
791 try self.writeAtoms();
791792 try self.flushModule(comp);
792793 }
793794 }
......@@ -1901,8 +1902,7 @@ pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64
19011902 const last_atom_sym = self.locals.items[last.local_sym_index];
19021903 break :blk last_atom_sym.n_value + last.size;
19031904 } else sect.addr;
1904 // const atom_alignment = try math.powi(u32, 2, atom.alignment); TODO
1905 const atom_alignment = math.powi(u32, 2, atom.alignment) catch unreachable;
1905 const atom_alignment = try math.powi(u32, 2, atom.alignment);
19061906 const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment);
19071907 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
19541954 }
19551955}
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
19571971pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock {
19581972 const local_sym_index = @intCast(u32, self.locals.items.len);
19591973 try self.locals.append(self.base.allocator, .{
......@@ -2588,21 +2602,17 @@ fn resolveSymbols(self: *MachO) !void {
25882602 if (!use_stage1) {
25892603 {
25902604 const atom = try self.createDyldPrivateAtom();
2591 const match = MatchingSection{
2605 _ = try self.allocateAtom(atom, .{
25922606 .seg = self.data_segment_cmd_index.?,
25932607 .sect = self.data_section_index.?,
2594 };
2595 _ = try self.allocateAtom(atom, match);
2596 try self.writeAtom(atom, match);
2608 });
25972609 }
25982610 {
25992611 const atom = try self.createStubHelperPreambleAtom();
2600 const match = MatchingSection{
2612 _ = try self.allocateAtom(atom, .{
26012613 .seg = self.text_segment_cmd_index.?,
26022614 .sect = self.stub_helper_section_index.?,
2603 };
2604 _ = try self.allocateAtom(atom, match);
2605 try self.writeAtom(atom, match);
2615 });
26062616 }
26072617 }
26082618
......@@ -2634,12 +2644,10 @@ fn resolveSymbols(self: *MachO) !void {
26342644 if (self.stubs_map.contains(resolv.where_index)) break :outer_blk;
26352645 const stub_helper_atom = blk: {
26362646 const atom = try self.createStubHelperAtom();
2637 const match = MatchingSection{
2647 _ = try self.allocateAtom(atom, .{
26382648 .seg = self.text_segment_cmd_index.?,
26392649 .sect = self.stub_helper_section_index.?,
2640 };
2641 _ = try self.allocateAtom(atom, match);
2642 try self.writeAtom(atom, match);
2650 });
26432651 break :blk atom;
26442652 };
26452653 const laptr_atom = blk: {
......@@ -2647,22 +2655,18 @@ fn resolveSymbols(self: *MachO) !void {
26472655 stub_helper_atom.local_sym_index,
26482656 resolv.where_index,
26492657 );
2650 const match = MatchingSection{
2658 _ = try self.allocateAtom(atom, .{
26512659 .seg = self.data_segment_cmd_index.?,
26522660 .sect = self.la_symbol_ptr_section_index.?,
2653 };
2654 _ = try self.allocateAtom(atom, match);
2655 try self.writeAtom(atom, match);
2661 });
26562662 break :blk atom;
26572663 };
26582664 const stub_atom = blk: {
26592665 const atom = try self.createStubAtom(laptr_atom.local_sym_index);
2660 const match = MatchingSection{
2666 _ = try self.allocateAtom(atom, .{
26612667 .seg = self.text_segment_cmd_index.?,
26622668 .sect = self.stubs_section_index.?,
2663 };
2664 _ = try self.allocateAtom(atom, match);
2665 try self.writeAtom(atom, match);
2669 });
26662670 break :blk atom;
26672671 };
26682672 try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom);
......@@ -2793,7 +2797,6 @@ fn resolveDyldStubBinder(self: *MachO) !void {
27932797 // TODO remove once we can incrementally update in stage1 too.
27942798 if (!(build_options.is_stage1 and self.base.options.use_stage1)) {
27952799 _ = try self.allocateAtom(atom, match);
2796 try self.writeAtom(atom, match);
27972800 } else {
27982801 try self.allocateAtomStage1(atom, match);
27992802 }
......@@ -3480,10 +3483,6 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
34803483 .where_index = decl.link.macho.local_sym_index,
34813484 };
34823485 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 });
34873486 try self.got_entries_map.put(self.base.allocator, key, got_atom);
34883487 self.rebase_info_dirty = true;
34893488}
......@@ -3549,9 +3548,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
35493548 },
35503549 }
35513550
3552 const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);
3553
3554 try self.writeCode(symbol, decl.link.macho.code.items);
3551 _ = try self.placeDecl(decl, decl.link.macho.code.items.len);
35553552
35563553 if (debug_buffers) |db| {
35573554 try self.d_sym.?.commitDeclDebugInfo(
......@@ -3642,9 +3639,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
36423639 },
36433640 }
36443641 };
3645 const symbol = try self.placeDecl(decl, code.len);
3646
3647 try self.writeCode(symbol, code);
3642 _ = try self.placeDecl(decl, code.len);
36483643
36493644 // Since we updated the vaddr and the size, each corresponding export symbol also
36503645 // needs to be updated.
......@@ -3667,16 +3662,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
36673662
36683663 if (vaddr != symbol.n_value) {
36693664 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 };
36743665 const got_atom = self.got_entries_map.get(.{
36753666 .where = .local,
36763667 .where_index = decl.link.macho.local_sym_index,
36773668 }) orelse unreachable;
3678 // _ = try self.allocateAtom(got_atom, match);
3679 try self.writeAtom(got_atom, match);
3669 _ = try self.allocateAtom(got_atom, .{
3670 .seg = self.data_const_segment_cmd_index.?,
3671 .sect = self.got_section_index.?,
3672 });
36803673 }
36813674
36823675 symbol.n_value = vaddr;
......@@ -3714,40 +3707,29 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
37143707 .n_desc = 0,
37153708 .n_value = addr,
37163709 };
3717 const match = MatchingSection{
3718 .seg = self.data_const_segment_cmd_index.?,
3719 .sect = self.got_section_index.?,
3720 };
37213710 const got_atom = self.got_entries_map.get(.{
37223711 .where = .local,
37233712 .where_index = decl.link.macho.local_sym_index,
37243713 }) orelse unreachable;
3725 // _ = try self.allocateAtom(got_atom, match);
3726 try self.writeAtom(got_atom, match);
3714 _ = try self.allocateAtom(got_atom, .{
3715 .seg = self.data_const_segment_cmd_index.?,
3716 .sect = self.got_section_index.?,
3717 });
37273718
37283719 try self.writeLocalSymbol(decl.link.macho.local_sym_index);
37293720 if (self.d_sym) |*ds|
37303721 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);
37313722 }
37323723
3733 // Resolve relocations
3734 try decl.link.macho.resolveRelocs(self);
3735 // 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?
3737 decl.link.macho.relocs.clearAndFree(self.base.allocator);
3724 // // Resolve relocations
3725 // try decl.link.macho.resolveRelocs(self);
3726 // // TODO this requires further investigation: should we dispose of resolved relocs, or keep them
3727 // // so that we can reapply them when moving/growing sections?
3728 // decl.link.macho.relocs.clearAndFree(self.base.allocator);
37383729
37393730 return symbol;
37403731}
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
37513733pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {
37523734 if (self.d_sym) |*ds| {
37533735 try ds.updateDeclLineNumber(module, decl);
......@@ -3983,7 +3965,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39833965 .aarch64 => 3 * @sizeOf(u32),
39843966 else => unreachable, // unhandled architecture type
39853967 };
3986 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3968 const needed_size = stub_size * self.base.options.symbol_count_hint;
39873969 const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
39883970 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 {
47394721 try self.relocateSymbolTable();
47404722 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
47414723 const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;
4742 log.debug("writing local symbol {} at 0x{x}", .{ index, off });
4743 try self.base.file.?.pwriteAll(mem.asBytes(&self.locals.items[index]), off);
4724 const sym = self.locals.items[index];
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);
47444727}
47454728
47464729fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
src/link/MachO/TextBlock.zig+14-25
......@@ -75,6 +75,8 @@ dbg_info_off: u32,
7575/// Size of the .debug_info tag for this Decl, not including padding.
7676dbg_info_len: u32,
7777
78dirty: bool = true,
79
7880pub const SymbolAtOffset = struct {
7981 local_sym_index: u32,
8082 offset: u64,
......@@ -843,7 +845,6 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
843845 };
844846 if (!(build_options.is_stage1 and context.macho_file.base.options.use_stage1)) {
845847 _ = try context.macho_file.allocateAtom(atom, match);
846 try context.macho_file.writeAtom(atom, match);
847848 } else {
848849 try context.macho_file.allocateAtomStage1(atom, match);
849850 }
......@@ -924,30 +925,18 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
924925 .sect = context.macho_file.stubs_section_index.?,
925926 });
926927 } else {
927 {
928 const match = MachO.MatchingSection{
929 .seg = context.macho_file.text_segment_cmd_index.?,
930 .sect = context.macho_file.stub_helper_section_index.?,
931 };
932 _ = try context.macho_file.allocateAtom(stub_helper_atom, match);
933 try context.macho_file.writeAtom(stub_helper_atom, match);
934 }
935 {
936 const match = MachO.MatchingSection{
937 .seg = context.macho_file.data_segment_cmd_index.?,
938 .sect = context.macho_file.la_symbol_ptr_section_index.?,
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 }
928 _ = try context.macho_file.allocateAtom(stub_helper_atom, .{
929 .seg = context.macho_file.text_segment_cmd_index.?,
930 .sect = context.macho_file.stub_helper_section_index.?,
931 });
932 _ = try context.macho_file.allocateAtom(laptr_atom, .{
933 .seg = context.macho_file.data_segment_cmd_index.?,
934 .sect = context.macho_file.la_symbol_ptr_section_index.?,
935 });
936 _ = try context.macho_file.allocateAtom(stub_atom, .{
937 .seg = context.macho_file.text_segment_cmd_index.?,
938 .sect = context.macho_file.stubs_section_index.?,
939 });
951940 }
952941 }
953942 }