From 983d6dcd9ea75e05abd8ce2bd247bbad3960acd7 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 15 Sep 2021 16:57:10 +0200 Subject: macho: implement object relinking in stage2 * In watch mode, when changing the C source, we will trigger complete relinking of objects, dylibs and archives (atoms coming from the incremental updates stay put however). This means, we need to undo metadata populated when linking in objects, archives and dylibs. * Remove unused splitting section into atoms bit. This optimisation will probably be best rewritten from scratch once self-hosted matures so parking the idea for now. Also, for easier management of atoms spawned from the Object file, keep the atoms subgraph as part of the Object file struct. * Remove obsolete ref to static initializers in object struct. * Implement handling of global symbol collision in updateDeclExports. --- src/link/MachO/Atom.zig | 102 +++++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 44 deletions(-) (limited to 'src/link/MachO/Atom.zig') diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 298855934e..6dbe853451 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -645,7 +645,6 @@ const RelocContext = struct { allocator: *Allocator, object: *Object, macho_file: *MachO, - parsed_atoms: *Object.ParsedAtoms, }; fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation { @@ -877,12 +876,16 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC .sect = context.macho_file.got_section_index.?, }; - if (context.parsed_atoms.getPtr(match)) |last| { + if (!context.object.start_atoms.contains(match)) { + try context.object.start_atoms.putNoClobber(context.allocator, match, atom); + } + + if (context.object.end_atoms.getPtr(match)) |last| { last.*.next = atom; atom.prev = last.*; last.* = atom; } else { - try context.parsed_atoms.putNoClobber(match, atom); + try context.object.end_atoms.putNoClobber(context.allocator, match, atom); } } else if (parsed_rel.payload == .unsigned) { switch (parsed_rel.where) { @@ -939,52 +942,63 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC if (parsed_rel.where != .undef) break :blk; if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk; - const stub_helper_atom = try context.macho_file.createStubHelperAtom(); - const laptr_atom = try context.macho_file.createLazyPointerAtom( - stub_helper_atom.local_sym_index, - parsed_rel.where_index, - ); - const stub_atom = try context.macho_file.createStubAtom(laptr_atom.local_sym_index); - try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stub_atom); // TODO clean this up! - if (context.parsed_atoms.getPtr(.{ - .seg = context.macho_file.text_segment_cmd_index.?, - .sect = context.macho_file.stub_helper_section_index.?, - })) |last| { - last.*.next = stub_helper_atom; - stub_helper_atom.prev = last.*; - last.* = stub_helper_atom; - } else { - try context.parsed_atoms.putNoClobber(.{ + const stub_helper_atom = atom: { + const atom = try context.macho_file.createStubHelperAtom(); + const match = MachO.MatchingSection{ .seg = context.macho_file.text_segment_cmd_index.?, .sect = context.macho_file.stub_helper_section_index.?, - }, stub_helper_atom); - } - if (context.parsed_atoms.getPtr(.{ - .seg = context.macho_file.text_segment_cmd_index.?, - .sect = context.macho_file.stubs_section_index.?, - })) |last| { - last.*.next = stub_atom; - stub_atom.prev = last.*; - last.* = stub_atom; - } else { - try context.parsed_atoms.putNoClobber(.{ - .seg = context.macho_file.text_segment_cmd_index.?, - .sect = context.macho_file.stubs_section_index.?, - }, stub_atom); - } - if (context.parsed_atoms.getPtr(.{ - .seg = context.macho_file.data_segment_cmd_index.?, - .sect = context.macho_file.la_symbol_ptr_section_index.?, - })) |last| { - last.*.next = laptr_atom; - laptr_atom.prev = last.*; - last.* = laptr_atom; - } else { - try context.parsed_atoms.putNoClobber(.{ + }; + if (!context.object.start_atoms.contains(match)) { + try context.object.start_atoms.putNoClobber(context.allocator, match, atom); + } + if (context.object.end_atoms.getPtr(match)) |last| { + last.*.next = atom; + atom.prev = last.*; + last.* = atom; + } else { + try context.object.end_atoms.putNoClobber(context.allocator, match, atom); + } + break :atom atom; + }; + const laptr_atom = atom: { + const atom = try context.macho_file.createLazyPointerAtom( + stub_helper_atom.local_sym_index, + parsed_rel.where_index, + ); + const match = MachO.MatchingSection{ .seg = context.macho_file.data_segment_cmd_index.?, .sect = context.macho_file.la_symbol_ptr_section_index.?, - }, laptr_atom); + }; + if (!context.object.start_atoms.contains(match)) { + try context.object.start_atoms.putNoClobber(context.allocator, match, atom); + } + if (context.object.end_atoms.getPtr(match)) |last| { + last.*.next = atom; + atom.prev = last.*; + last.* = atom; + } else { + try context.object.end_atoms.putNoClobber(context.allocator, match, atom); + } + break :atom atom; + }; + { + const atom = try context.macho_file.createStubAtom(laptr_atom.local_sym_index); + const match = MachO.MatchingSection{ + .seg = context.macho_file.text_segment_cmd_index.?, + .sect = context.macho_file.stubs_section_index.?, + }; + if (!context.object.start_atoms.contains(match)) { + try context.object.start_atoms.putNoClobber(context.allocator, match, atom); + } + if (context.object.end_atoms.getPtr(match)) |last| { + last.*.next = atom; + atom.prev = last.*; + last.* = atom; + } else { + try context.object.end_atoms.putNoClobber(context.allocator, match, atom); + } + try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, atom); } } } -- cgit v1.2.3