| ... | ... | @@ -2594,30 +2594,64 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2594 | 2594 | } |
| 2595 | 2595 | |
| 2596 | 2596 | fn 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 | |
| 2597 | 2603 | var section_metadata = std.AutoHashMap(MatchingSection, struct { |
| 2598 | 2604 | size: u64, |
| 2599 | 2605 | alignment: u32, |
| 2600 | 2606 | }).init(self.base.allocator); |
| 2601 | 2607 | defer section_metadata.deinit(); |
| 2602 | 2608 | |
| 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.* = .{ |
| 2613 | 2622 | .size = 0, |
| 2614 | 2623 | .alignment = 0, |
| 2615 | 2624 | }; |
| 2616 | 2625 | } |
| 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 | } |
| 2621 | 2655 | } |
| 2622 | 2656 | } |
| 2623 | 2657 | |
| ... | ... | @@ -2625,63 +2659,69 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2625 | 2659 | while (it.next()) |entry| { |
| 2626 | 2660 | const match = entry.key_ptr.*; |
| 2627 | 2661 | 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]; |
| 2630 | 2664 | 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.*), |
| 2633 | 2667 | metadata.size, |
| 2634 | 2668 | metadata.alignment, |
| 2635 | 2669 | }); |
| 2670 | sect.@"align" = math.max(sect.@"align", metadata.alignment); |
| 2636 | 2671 | try self.growSection(match, @intCast(u32, metadata.size)); |
| 2637 | | } |
| 2638 | 2672 | |
| 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 | } |
| 2685 | 2725 | } |
| 2686 | 2726 | |
| 2687 | 2727 | fn addDataInCodeLC(self: *MachO) !void { |