| ... | ... | @@ -925,58 +925,22 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 925 | 925 | try self.allocateDataConstSegment(); |
| 926 | 926 | try self.allocateDataSegment(); |
| 927 | 927 | self.allocateLinkeditSegment(); |
| 928 | | try self.allocLocalSymbols(); |
| 928 | try self.allocateLocals(); |
| 929 | 929 | } |
| 930 | 930 | |
| 931 | | try self.allocateGlobalSymbols(); |
| 931 | try self.allocateGlobals(); |
| 932 | 932 | |
| 933 | | log.debug("locals:", .{}); |
| 934 | | for (self.locals.items) |sym, id| { |
| 935 | | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 936 | | } |
| 937 | | log.debug("globals:", .{}); |
| 938 | | for (self.globals.items) |sym, id| { |
| 939 | | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 940 | | } |
| 941 | | log.debug("undefs:", .{}); |
| 942 | | for (self.undefs.items) |sym, id| { |
| 943 | | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 944 | | } |
| 945 | | { |
| 946 | | log.debug("resolver:", .{}); |
| 947 | | var it = self.symbol_resolver.iterator(); |
| 948 | | while (it.next()) |entry| { |
| 949 | | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); |
| 950 | | } |
| 933 | if (build_options.enable_logging) { |
| 934 | self.logSymtab(); |
| 935 | self.logSectionOrdinals(); |
| 951 | 936 | } |
| 952 | 937 | |
| 953 | | log.debug("GOT entries:", .{}); |
| 954 | | for (self.got_entries_map.keys()) |key| { |
| 955 | | switch (key) { |
| 956 | | .local => |sym_index| log.debug(" {} => {d}", .{ key, sym_index }), |
| 957 | | .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }), |
| 958 | | } |
| 959 | | } |
| 960 | | |
| 961 | | log.debug("stubs:", .{}); |
| 962 | | for (self.stubs_map.keys()) |key| { |
| 963 | | log.debug(" {} => {s}", .{ key, self.getString(key) }); |
| 964 | | } |
| 965 | | |
| 966 | | for (self.section_ordinals.keys()) |match, i| { |
| 967 | | const seg = self.load_commands.items[match.seg].Segment; |
| 968 | | const sect = seg.sections.items[match.sect]; |
| 969 | | log.debug("{d}: {d},{d} == {s},{s}", .{ |
| 970 | | i + 1, |
| 971 | | match.seg, |
| 972 | | match.sect, |
| 973 | | commands.segmentName(sect), |
| 974 | | commands.sectionName(sect), |
| 975 | | }); |
| 938 | if (use_stage1) { |
| 939 | try self.writeAllAtoms(); |
| 940 | } else { |
| 941 | try self.writeAtoms(); |
| 976 | 942 | } |
| 977 | 943 | |
| 978 | | try self.writeAtoms(); |
| 979 | | |
| 980 | 944 | if (self.bss_section_index) |idx| { |
| 981 | 945 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 982 | 946 | const sect = &seg.sections.items[idx]; |
| ... | ... | @@ -1910,7 +1874,7 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 1910 | 1874 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); |
| 1911 | 1875 | } |
| 1912 | 1876 | |
| 1913 | | fn allocLocalSymbols(self: *MachO) !void { |
| 1877 | fn allocateLocals(self: *MachO) !void { |
| 1914 | 1878 | var it = self.atoms.iterator(); |
| 1915 | 1879 | while (it.next()) |entry| { |
| 1916 | 1880 | const match = entry.key_ptr.*; |
| ... | ... | @@ -1938,7 +1902,7 @@ fn allocLocalSymbols(self: *MachO) !void { |
| 1938 | 1902 | sym.n_value = base_vaddr; |
| 1939 | 1903 | sym.n_sect = n_sect; |
| 1940 | 1904 | |
| 1941 | | log.debug(" {d}: {s} @0x{x}", .{ |
| 1905 | log.debug(" {d}: {s} allocated at 0x{x}", .{ |
| 1942 | 1906 | atom.local_sym_index, |
| 1943 | 1907 | self.getString(sym.n_strx), |
| 1944 | 1908 | base_vaddr, |
| ... | ... | @@ -1967,7 +1931,7 @@ fn allocLocalSymbols(self: *MachO) !void { |
| 1967 | 1931 | } |
| 1968 | 1932 | } |
| 1969 | 1933 | |
| 1970 | | fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void { |
| 1934 | fn shiftLocalsByOffset(self: *MachO, match: MatchingSection, offset: i64) !void { |
| 1971 | 1935 | var atom = self.atoms.get(match) orelse return; |
| 1972 | 1936 | |
| 1973 | 1937 | while (true) { |
| ... | ... | @@ -1990,7 +1954,9 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void |
| 1990 | 1954 | } |
| 1991 | 1955 | } |
| 1992 | 1956 | |
| 1993 | | fn allocateGlobalSymbols(self: *MachO) !void { |
| 1957 | fn allocateGlobals(self: *MachO) !void { |
| 1958 | log.debug("allocating global symbols", .{}); |
| 1959 | |
| 1994 | 1960 | var sym_it = self.symbol_resolver.valueIterator(); |
| 1995 | 1961 | while (sym_it.next()) |resolv| { |
| 1996 | 1962 | if (resolv.where != .global) continue; |
| ... | ... | @@ -2000,7 +1966,60 @@ fn allocateGlobalSymbols(self: *MachO) !void { |
| 2000 | 1966 | const sym = &self.globals.items[resolv.where_index]; |
| 2001 | 1967 | sym.n_value = local_sym.n_value; |
| 2002 | 1968 | sym.n_sect = local_sym.n_sect; |
| 2003 | | log.debug("allocating global symbol {s} at 0x{x}", .{ self.getString(sym.n_strx), local_sym.n_value }); |
| 1969 | |
| 1970 | log.debug(" {d}: {s} allocated at 0x{x}", .{ |
| 1971 | resolv.where_index, |
| 1972 | self.getString(sym.n_strx), |
| 1973 | local_sym.n_value, |
| 1974 | }); |
| 1975 | } |
| 1976 | } |
| 1977 | |
| 1978 | fn writeAllAtoms(self: *MachO) !void { |
| 1979 | var it = self.atoms.iterator(); |
| 1980 | while (it.next()) |entry| { |
| 1981 | const match = entry.key_ptr.*; |
| 1982 | const seg = self.load_commands.items[match.seg].Segment; |
| 1983 | const sect = seg.sections.items[match.sect]; |
| 1984 | var atom: *Atom = entry.value_ptr.*; |
| 1985 | |
| 1986 | var buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1987 | defer buffer.deinit(); |
| 1988 | try buffer.ensureTotalCapacity(sect.size); |
| 1989 | |
| 1990 | log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| 1991 | |
| 1992 | while (atom.prev) |prev| { |
| 1993 | atom = prev; |
| 1994 | } |
| 1995 | |
| 1996 | while (true) { |
| 1997 | const atom_sym = self.locals.items[atom.local_sym_index]; |
| 1998 | const padding_size: usize = if (atom.next) |next| blk: { |
| 1999 | const next_sym = self.locals.items[next.local_sym_index]; |
| 2000 | const size = next_sym.n_value - (atom_sym.n_value + atom.size); |
| 2001 | break :blk try math.cast(usize, size); |
| 2002 | } else 0; |
| 2003 | |
| 2004 | log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym }); |
| 2005 | |
| 2006 | try atom.resolveRelocs(self); |
| 2007 | buffer.appendSliceAssumeCapacity(atom.code.items); |
| 2008 | |
| 2009 | var i: usize = 0; |
| 2010 | while (i < padding_size) : (i += 1) { |
| 2011 | buffer.appendAssumeCapacity(0); |
| 2012 | } |
| 2013 | |
| 2014 | if (atom.next) |next| { |
| 2015 | atom = next; |
| 2016 | } else { |
| 2017 | assert(buffer.items.len == sect.size); |
| 2018 | log.debug(" (writing at file offset 0x{x})", .{sect.offset}); |
| 2019 | try self.base.file.?.pwriteAll(buffer.items, sect.offset); |
| 2020 | break; |
| 2021 | } |
| 2022 | } |
| 2004 | 2023 | } |
| 2005 | 2024 | } |
| 2006 | 2025 | |
| ... | ... | @@ -2048,6 +2067,7 @@ fn writeAtoms(self: *MachO) !void { |
| 2048 | 2067 | atom.dirty = false; |
| 2049 | 2068 | } else { |
| 2050 | 2069 | if (file_offset) |off| { |
| 2070 | log.debug(" (writing at file offset 0x{x})", .{off}); |
| 2051 | 2071 | try self.base.file.?.pwriteAll(buffer.items, off); |
| 2052 | 2072 | } |
| 2053 | 2073 | file_offset = null; |
| ... | ... | @@ -2057,13 +2077,6 @@ fn writeAtoms(self: *MachO) !void { |
| 2057 | 2077 | if (atom.next) |next| { |
| 2058 | 2078 | atom = next; |
| 2059 | 2079 | } else { |
| 2060 | | if (buffer.items.len != sect.size) { |
| 2061 | | log.warn("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| 2062 | | log.warn(" alignment: 0x{x}", .{sect.@"align"}); |
| 2063 | | log.warn(" expected: 0x{x}", .{sect.size}); |
| 2064 | | log.warn(" given: 0x{x}", .{buffer.items.len}); |
| 2065 | | } |
| 2066 | | assert(buffer.items.len == sect.size); |
| 2067 | 2080 | if (file_offset) |off| { |
| 2068 | 2081 | log.debug(" (writing at file offset 0x{x})", .{off}); |
| 2069 | 2082 | try self.base.file.?.pwriteAll(buffer.items, off); |
| ... | ... | @@ -4576,7 +4589,7 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { |
| 4576 | 4589 | moved_sect.addr + moved_sect.size, |
| 4577 | 4590 | }); |
| 4578 | 4591 | |
| 4579 | | try self.allocateLocalSymbols(.{ |
| 4592 | try self.shiftLocalsByOffset(.{ |
| 4580 | 4593 | .seg = @intCast(u16, next), |
| 4581 | 4594 | .sect = @intCast(u16, moved_sect_id), |
| 4582 | 4595 | }, @intCast(i64, offset_amt)); |
| ... | ... | @@ -4650,7 +4663,7 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void { |
| 4650 | 4663 | moved_sect.addr + moved_sect.size, |
| 4651 | 4664 | }); |
| 4652 | 4665 | |
| 4653 | | try self.allocateLocalSymbols(.{ |
| 4666 | try self.shiftLocalsByOffset(.{ |
| 4654 | 4667 | .seg = match.seg, |
| 4655 | 4668 | .sect = next, |
| 4656 | 4669 | }, @intCast(i64, offset_amt)); |
| ... | ... | @@ -5733,7 +5746,7 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 { |
| 5733 | 5746 | return new_off; |
| 5734 | 5747 | } |
| 5735 | 5748 | |
| 5736 | | pub fn getString(self: *MachO, off: u32) []const u8 { |
| 5749 | pub fn getString(self: MachO, off: u32) []const u8 { |
| 5737 | 5750 | assert(off < self.strtab.items.len); |
| 5738 | 5751 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.items.ptr + off), 0); |
| 5739 | 5752 | } |
| ... | ... | @@ -6026,3 +6039,55 @@ fn snapshotState(self: *MachO) !void { |
| 6026 | 6039 | try std.json.stringify(snapshot, .{}, writer); |
| 6027 | 6040 | try writer.writeByte(']'); |
| 6028 | 6041 | } |
| 6042 | |
| 6043 | fn logSymtab(self: MachO) void { |
| 6044 | log.debug("locals:", .{}); |
| 6045 | for (self.locals.items) |sym, id| { |
| 6046 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 6047 | } |
| 6048 | |
| 6049 | log.debug("globals:", .{}); |
| 6050 | for (self.globals.items) |sym, id| { |
| 6051 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 6052 | } |
| 6053 | |
| 6054 | log.debug("undefs:", .{}); |
| 6055 | for (self.undefs.items) |sym, id| { |
| 6056 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| 6057 | } |
| 6058 | |
| 6059 | { |
| 6060 | log.debug("resolver:", .{}); |
| 6061 | var it = self.symbol_resolver.iterator(); |
| 6062 | while (it.next()) |entry| { |
| 6063 | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); |
| 6064 | } |
| 6065 | } |
| 6066 | |
| 6067 | log.debug("GOT entries:", .{}); |
| 6068 | for (self.got_entries_map.keys()) |key| { |
| 6069 | switch (key) { |
| 6070 | .local => |sym_index| log.debug(" {} => {d}", .{ key, sym_index }), |
| 6071 | .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }), |
| 6072 | } |
| 6073 | } |
| 6074 | |
| 6075 | log.debug("stubs:", .{}); |
| 6076 | for (self.stubs_map.keys()) |key| { |
| 6077 | log.debug(" {} => {s}", .{ key, self.getString(key) }); |
| 6078 | } |
| 6079 | } |
| 6080 | |
| 6081 | fn logSectionOrdinals(self: MachO) void { |
| 6082 | for (self.section_ordinals.keys()) |match, i| { |
| 6083 | const seg = self.load_commands.items[match.seg].Segment; |
| 6084 | const sect = seg.sections.items[match.sect]; |
| 6085 | log.debug("ord {d}: {d},{d} => {s},{s}", .{ |
| 6086 | i + 1, |
| 6087 | match.seg, |
| 6088 | match.sect, |
| 6089 | commands.segmentName(sect), |
| 6090 | commands.sectionName(sect), |
| 6091 | }); |
| 6092 | } |
| 6093 | } |