authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-09 14:18:28+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-09 14:18:28+02:00
log1efdb137d14058f3c428a001838b963de16694ea
tree5393bbbcfa325ec82684dbb542cfd4744555e7c8
parent23be9cae346614d7d42d9c1c6426bfe2d6721c68

macho: don't allocate atoms when parsing objects


3 files changed, 182 insertions(+), 78 deletions(-)

src/link/MachO.zig+105-65
......@@ -2594,30 +2594,64 @@ fn resolveDyldStubBinder(self: *MachO) !void {
25942594}
25952595
25962596fn parseTextBlocks(self: *MachO) !void {
2597 var parsed_atoms = Object.ParsedAtoms.init(self.base.allocator);
2598 defer parsed_atoms.deinit();
2599
2600 var first_atoms = Object.ParsedAtoms.init(self.base.allocator);
2601 defer first_atoms.deinit();
2602
25972603 var section_metadata = std.AutoHashMap(MatchingSection, struct {
25982604 size: u64,
25992605 alignment: u32,
26002606 }).init(self.base.allocator);
26012607 defer section_metadata.deinit();
26022608
2603 for (self.objects.items) |object| {
2604 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
2605 for (seg.sections.items) |sect| {
2606 const match = (try self.getMatchingSection(sect)) orelse {
2607 log.debug("unhandled section", .{});
2608 continue;
2609 };
2610 const res = try section_metadata.getOrPut(match);
2611 if (!res.found_existing) {
2612 res.value_ptr.* = .{
2609 for (self.objects.items) |*object, object_id| {
2610 var atoms_in_objects = try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
2611 defer atoms_in_objects.deinit();
2612
2613 var it = atoms_in_objects.iterator();
2614 while (it.next()) |entry| {
2615 const match = entry.key_ptr.*;
2616 const last_atom = entry.value_ptr.*;
2617 var atom = last_atom;
2618
2619 const metadata = try section_metadata.getOrPut(match);
2620 if (!metadata.found_existing) {
2621 metadata.value_ptr.* = .{
26132622 .size = 0,
26142623 .alignment = 0,
26152624 };
26162625 }
2617 const size = padToIdeal(sect.size);
2618 const alignment = try math.powi(u32, 2, sect.@"align");
2619 res.value_ptr.size += mem.alignForwardGeneric(u64, size, alignment);
2620 res.value_ptr.alignment = math.max(res.value_ptr.alignment, sect.@"align");
2626
2627 while (true) {
2628 const alignment = try math.powi(u32, 2, atom.alignment);
2629 metadata.value_ptr.size += mem.alignForwardGeneric(u64, atom.size, alignment);
2630 metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment);
2631
2632 const sym = self.locals.items[atom.local_sym_index];
2633 log.debug(" {s}: n_value=0x{x}, size=0x{x}, alignment=0x{x}", .{
2634 self.getString(sym.n_strx),
2635 sym.n_value,
2636 atom.size,
2637 atom.alignment,
2638 });
2639
2640 if (atom.prev) |prev| {
2641 atom = prev;
2642 } else break;
2643 }
2644
2645 if (parsed_atoms.getPtr(match)) |last| {
2646 last.*.next = atom;
2647 atom.prev = last.*;
2648 last.* = atom;
2649 }
2650 _ = try parsed_atoms.put(match, last_atom);
2651
2652 if (!first_atoms.contains(match)) {
2653 try first_atoms.putNoClobber(match, atom);
2654 }
26212655 }
26222656 }
26232657
......@@ -2625,63 +2659,69 @@ fn parseTextBlocks(self: *MachO) !void {
26252659 while (it.next()) |entry| {
26262660 const match = entry.key_ptr.*;
26272661 const metadata = entry.value_ptr.*;
2628 const seg = self.load_commands.items[match.seg].Segment;
2629 const sect = seg.sections.items[match.sect];
2662 const seg = &self.load_commands.items[match.seg].Segment;
2663 const sect = &seg.sections.items[match.sect];
26302664 log.debug("{s},{s} => size: 0x{x}, alignment: 0x{x}", .{
2631 commands.segmentName(sect),
2632 commands.sectionName(sect),
2665 commands.segmentName(sect.*),
2666 commands.sectionName(sect.*),
26332667 metadata.size,
26342668 metadata.alignment,
26352669 });
2670 sect.@"align" = math.max(sect.@"align", metadata.alignment);
26362671 try self.growSection(match, @intCast(u32, metadata.size));
2637 }
26382672
2639 for (self.objects.items) |*object, object_id| {
2640 try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
2641 }
2642
2643 // it = section_metadata.iterator();
2644 // while (it.next()) |entry| {
2645 // const match = entry.key_ptr.*;
2646 // const metadata = entry.value_ptr.*;
2647 // const seg = self.load_commands.items[match.seg].Segment;
2648 // const sect = seg.sections.items[match.sect];
2649
2650 // var buffer = try self.base.allocator.alloc(u8, metadata.size);
2651 // defer self.base.allocator.free(buffer);
2652 // log.warn("{s},{s} buffer size 0x{x}", .{
2653 // commands.segmentName(sect),
2654 // commands.sectionName(sect),
2655 // metadata.size,
2656 // });
2657
2658 // var atom = self.blocks.get(match).?;
2659
2660 // while (atom.prev) |prev| {
2661 // atom = prev;
2662 // }
2663
2664 // const base = blk: {
2665 // const sym = self.locals.items[atom.local_sym_index];
2666 // break :blk sym.n_value;
2667 // };
2668
2669 // while (true) {
2670 // const sym = self.locals.items[atom.local_sym_index];
2671 // const offset = sym.n_value - base;
2672 // try atom.resolveRelocs(self);
2673 // log.warn("writing atom for symbol {s} at buffer offset 0x{x}", .{
2674 // self.getString(sym.n_strx),
2675 // offset,
2676 // });
2677 // mem.copy(u8, buffer[offset..][0..atom.code.items.len], atom.code.items);
2678 // atom.dirty = false;
2679
2680 // if (atom.next) |next| {
2681 // atom = next;
2682 // } else break;
2683 // }
2684 // }
2673 var base_vaddr = if (self.blocks.get(match)) |last| blk: {
2674 const last_atom_sym = self.locals.items[last.local_sym_index];
2675 break :blk last_atom_sym.n_value + last.size;
2676 } else sect.addr;
2677 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2678
2679 var atom = first_atoms.get(match).?;
2680 while (true) {
2681 const alignment = try math.powi(u32, 2, atom.alignment);
2682 base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment);
2683
2684 const sym = &self.locals.items[atom.local_sym_index];
2685 sym.n_value = base_vaddr;
2686 sym.n_sect = n_sect;
2687
2688 log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{
2689 self.getString(sym.n_strx),
2690 base_vaddr,
2691 base_vaddr + atom.size,
2692 atom.size,
2693 atom.alignment,
2694 });
2695
2696 // Update each alias (if any)
2697 for (atom.aliases.items) |index| {
2698 const alias_sym = &self.locals.items[index];
2699 alias_sym.n_value = base_vaddr;
2700 alias_sym.n_sect = n_sect;
2701 }
2702
2703 // Update each symbol contained within the TextBlock
2704 for (atom.contained.items) |sym_at_off| {
2705 const contained_sym = &self.locals.items[sym_at_off.local_sym_index];
2706 contained_sym.n_value = base_vaddr + sym_at_off.offset;
2707 contained_sym.n_sect = n_sect;
2708 }
2709
2710 base_vaddr += atom.size;
2711
2712 if (atom.next) |next| {
2713 atom = next;
2714 } else break;
2715 }
2716
2717 if (self.blocks.getPtr(match)) |last| {
2718 const first_atom = first_atoms.get(match).?;
2719 last.*.next = first_atom;
2720 first_atom.prev = last.*;
2721 last.* = first_atom;
2722 }
2723 _ = try self.blocks.put(self.base.allocator, match, parsed_atoms.get(match).?);
2724 }
26852725}
26862726
26872727fn addDataInCodeLC(self: *MachO) !void {
src/link/MachO/Object.zig+32-4
......@@ -317,6 +317,7 @@ const Context = struct {
317317 object: *Object,
318318 macho_file: *MachO,
319319 match: MachO.MatchingSection,
320 parsed_atoms: *ParsedAtoms,
320321};
321322
322323const TextBlockParser = struct {
......@@ -430,6 +431,7 @@ const TextBlockParser = struct {
430431 .allocator = context.allocator,
431432 .object = context.object,
432433 .macho_file = context.macho_file,
434 .parsed_atoms = context.parsed_atoms,
433435 });
434436
435437 if (context.macho_file.has_dices) {
......@@ -455,12 +457,15 @@ const TextBlockParser = struct {
455457 }
456458};
457459
460pub const ParsedAtoms = std.AutoHashMap(MachO.MatchingSection, *TextBlock);
461
458462pub fn parseTextBlocks(
459463 self: *Object,
460464 allocator: *Allocator,
461465 object_id: u16,
462466 macho_file: *MachO,
463) !void {
467) !ParsedAtoms {
468 var parsed_atoms = ParsedAtoms.init(allocator);
464469 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
465470
466471 log.debug("analysing {s}", .{self.name});
......@@ -589,6 +594,7 @@ pub fn parseTextBlocks(
589594 .allocator = allocator,
590595 .object = self,
591596 .macho_file = macho_file,
597 .parsed_atoms = &parsed_atoms,
592598 });
593599
594600 if (macho_file.has_dices) {
......@@ -604,7 +610,13 @@ pub fn parseTextBlocks(
604610 }
605611 }
606612
607 _ = try macho_file.allocateAtom(block, match);
613 if (parsed_atoms.getPtr(match)) |last| {
614 last.*.next = block;
615 block.prev = last.*;
616 last.* = block;
617 } else {
618 try parsed_atoms.putNoClobber(match, block);
619 }
608620 try self.text_blocks.append(allocator, block);
609621 }
610622
......@@ -620,6 +632,7 @@ pub fn parseTextBlocks(
620632 .object = self,
621633 .macho_file = macho_file,
622634 .match = match,
635 .parsed_atoms = &parsed_atoms,
623636 })) |block| {
624637 const sym = macho_file.locals.items[block.local_sym_index];
625638 const is_ext = blk: {
......@@ -651,7 +664,13 @@ pub fn parseTextBlocks(
651664 }
652665 }
653666
654 _ = try macho_file.allocateAtom(block, match);
667 if (parsed_atoms.getPtr(match)) |last| {
668 last.*.next = block;
669 block.prev = last.*;
670 last.* = block;
671 } else {
672 try parsed_atoms.putNoClobber(match, block);
673 }
655674 try self.text_blocks.append(allocator, block);
656675 }
657676
......@@ -696,6 +715,7 @@ pub fn parseTextBlocks(
696715 .allocator = allocator,
697716 .object = self,
698717 .macho_file = macho_file,
718 .parsed_atoms = &parsed_atoms,
699719 });
700720
701721 if (macho_file.has_dices) {
......@@ -747,10 +767,18 @@ pub fn parseTextBlocks(
747767 });
748768 }
749769
750 _ = try macho_file.allocateAtom(block, match);
770 if (parsed_atoms.getPtr(match)) |last| {
771 last.*.next = block;
772 block.prev = last.*;
773 last.* = block;
774 } else {
775 try parsed_atoms.putNoClobber(match, block);
776 }
751777 try self.text_blocks.append(allocator, block);
752778 }
753779 }
780
781 return parsed_atoms;
754782}
755783
756784fn parseSymtab(self: *Object, allocator: *Allocator) !void {
src/link/MachO/TextBlock.zig+45-9
......@@ -628,6 +628,7 @@ const RelocContext = struct {
628628 allocator: *Allocator,
629629 object: *Object,
630630 macho_file: *MachO,
631 parsed_atoms: *Object.ParsedAtoms,
631632};
632633
633634fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {
......@@ -855,7 +856,14 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
855856 .seg = context.macho_file.data_const_segment_cmd_index.?,
856857 .sect = context.macho_file.got_section_index.?,
857858 };
858 _ = try context.macho_file.allocateAtom(atom, match);
859
860 if (context.parsed_atoms.getPtr(match)) |last| {
861 last.*.next = atom;
862 atom.prev = last.*;
863 last.* = atom;
864 } else {
865 try context.parsed_atoms.putNoClobber(match, atom);
866 }
859867 } else if (parsed_rel.payload == .unsigned) {
860868 switch (parsed_rel.where) {
861869 .undef => {
......@@ -918,18 +926,46 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
918926 );
919927 const stub_atom = try context.macho_file.createStubAtom(laptr_atom.local_sym_index);
920928 try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stub_atom);
921 _ = try context.macho_file.allocateAtom(stub_helper_atom, .{
929 // TODO clean this up!
930 if (context.parsed_atoms.getPtr(.{
922931 .seg = context.macho_file.text_segment_cmd_index.?,
923932 .sect = context.macho_file.stub_helper_section_index.?,
924 });
925 _ = try context.macho_file.allocateAtom(laptr_atom, .{
926 .seg = context.macho_file.data_segment_cmd_index.?,
927 .sect = context.macho_file.la_symbol_ptr_section_index.?,
928 });
929 _ = try context.macho_file.allocateAtom(stub_atom, .{
933 })) |last| {
934 last.*.next = stub_helper_atom;
935 stub_helper_atom.prev = last.*;
936 last.* = stub_helper_atom;
937 } else {
938 try context.parsed_atoms.putNoClobber(.{
939 .seg = context.macho_file.text_segment_cmd_index.?,
940 .sect = context.macho_file.stub_helper_section_index.?,
941 }, stub_helper_atom);
942 }
943 if (context.parsed_atoms.getPtr(.{
930944 .seg = context.macho_file.text_segment_cmd_index.?,
931945 .sect = context.macho_file.stubs_section_index.?,
932 });
946 })) |last| {
947 last.*.next = stub_atom;
948 stub_atom.prev = last.*;
949 last.* = stub_atom;
950 } else {
951 try context.parsed_atoms.putNoClobber(.{
952 .seg = context.macho_file.text_segment_cmd_index.?,
953 .sect = context.macho_file.stubs_section_index.?,
954 }, stub_atom);
955 }
956 if (context.parsed_atoms.getPtr(.{
957 .seg = context.macho_file.data_segment_cmd_index.?,
958 .sect = context.macho_file.la_symbol_ptr_section_index.?,
959 })) |last| {
960 last.*.next = laptr_atom;
961 laptr_atom.prev = last.*;
962 last.* = laptr_atom;
963 } else {
964 try context.parsed_atoms.putNoClobber(.{
965 .seg = context.macho_file.data_segment_cmd_index.?,
966 .sect = context.macho_file.la_symbol_ptr_section_index.?,
967 }, laptr_atom);
968 }
933969 }
934970 }
935971}