authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-17 23:48:44+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-22 16:58:21+02:00
log0da8ba816a14aeb43c0c98adc13943336f9525fa
treeaf203e98ffaa2874b973f7645003cb0935e6a593
parent41b91442f4af293d4cbbabbe9e451bd31c5c5679

macho: do not store stabs; generate on-the-fly instead


3 files changed, 214 insertions(+), 285 deletions(-)

src/link/MachO.zig+206-60
...@@ -4,6 +4,7 @@ const std = @import("std");...@@ -4,6 +4,7 @@ const std = @import("std");
4const build_options = @import("build_options");4const build_options = @import("build_options");
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const dwarf = std.dwarf;
7const fmt = std.fmt;8const fmt = std.fmt;
8const fs = std.fs;9const fs = std.fs;
9const log = std.log.scoped(.link);10const log = std.log.scoped(.link);
...@@ -187,7 +188,6 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},...@@ -187,7 +188,6 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},
187load_commands_dirty: bool = false,188load_commands_dirty: bool = false,
188sections_order_dirty: bool = false,189sections_order_dirty: bool = false,
189has_dices: bool = false,190has_dices: bool = false,
190has_stabs: bool = false,
191191
192/// A helper var to indicate if we are at the start of the incremental updates, or192/// A helper var to indicate if we are at the start of the incremental updates, or
193/// already somewhere further along the update-and-run chain.193/// already somewhere further along the update-and-run chain.
...@@ -725,6 +725,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -725,6 +725,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
725 man.hash.add(self.base.options.headerpad_max_install_names);725 man.hash.add(self.base.options.headerpad_max_install_names);
726 man.hash.add(dead_strip);726 man.hash.add(dead_strip);
727 man.hash.add(self.base.options.dead_strip_dylibs);727 man.hash.add(self.base.options.dead_strip_dylibs);
728 man.hash.add(self.base.options.strip);
728 man.hash.addListOfBytes(self.base.options.lib_dirs);729 man.hash.addListOfBytes(self.base.options.lib_dirs);
729 man.hash.addListOfBytes(self.base.options.framework_dirs);730 man.hash.addListOfBytes(self.base.options.framework_dirs);
730 link.hashAddSystemLibs(&man.hash, self.base.options.frameworks);731 link.hashAddSystemLibs(&man.hash, self.base.options.frameworks);
...@@ -1388,9 +1389,15 @@ fn parseObject(self: *MachO, path: []const u8) !bool {...@@ -1388,9 +1389,15 @@ fn parseObject(self: *MachO, path: []const u8) !bool {
1388 const name = try self.base.allocator.dupe(u8, path);1389 const name = try self.base.allocator.dupe(u8, path);
1389 errdefer self.base.allocator.free(name);1390 errdefer self.base.allocator.free(name);
13901391
1392 const mtime: u64 = mtime: {
1393 const stat = file.stat() catch break :mtime 0;
1394 break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
1395 };
1396
1391 var object = Object{1397 var object = Object{
1392 .name = name,1398 .name = name,
1393 .file = file,1399 .file = file,
1400 .mtime = mtime,
1394 };1401 };
13951402
1396 object.parse(self.base.allocator, self.base.options.target) catch |err| switch (err) {1403 object.parse(self.base.allocator, self.base.options.target) catch |err| switch (err) {
...@@ -2910,7 +2917,6 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2910,7 +2917,6 @@ fn createTentativeDefAtoms(self: *MachO) !void {
2910 try atom.contained.append(gpa, .{2917 try atom.contained.append(gpa, .{
2911 .sym_index = global.sym_index,2918 .sym_index = global.sym_index,
2912 .offset = 0,2919 .offset = 0,
2913 .stab = if (object.debug_info) |_| .static else null,
2914 });2920 });
29152921
2916 try object.managed_atoms.append(gpa, atom);2922 try object.managed_atoms.append(gpa, atom);
...@@ -6188,64 +6194,6 @@ fn writeSymtab(self: *MachO) !void {...@@ -6188,64 +6194,6 @@ fn writeSymtab(self: *MachO) !void {
6188 }6194 }
61896195
6190 for (self.objects.items) |object, object_id| {6196 for (self.objects.items) |object, object_id| {
6191 if (self.has_stabs) {
6192 if (object.debug_info) |_| {
6193 // Open scope
6194 try locals.ensureUnusedCapacity(3);
6195 locals.appendAssumeCapacity(.{
6196 .n_strx = try self.strtab.insert(gpa, object.tu_comp_dir.?),
6197 .n_type = macho.N_SO,
6198 .n_sect = 0,
6199 .n_desc = 0,
6200 .n_value = 0,
6201 });
6202 locals.appendAssumeCapacity(.{
6203 .n_strx = try self.strtab.insert(gpa, object.tu_name.?),
6204 .n_type = macho.N_SO,
6205 .n_sect = 0,
6206 .n_desc = 0,
6207 .n_value = 0,
6208 });
6209 locals.appendAssumeCapacity(.{
6210 .n_strx = try self.strtab.insert(gpa, object.name),
6211 .n_type = macho.N_OSO,
6212 .n_sect = 0,
6213 .n_desc = 1,
6214 .n_value = object.mtime orelse 0,
6215 });
6216
6217 for (object.managed_atoms.items) |atom| {
6218 for (atom.contained.items) |sym_at_off| {
6219 const stab = sym_at_off.stab orelse continue;
6220 const sym_loc = SymbolWithLoc{
6221 .sym_index = sym_at_off.sym_index,
6222 .file = atom.file,
6223 };
6224 const sym = self.getSymbol(sym_loc);
6225 if (sym.n_strx == 0) continue;
6226 if (sym.n_desc == N_DESC_GCED) continue;
6227 if (self.symbolIsTemp(sym_loc)) continue;
6228
6229 const nlists = try stab.asNlists(.{
6230 .sym_index = sym_at_off.sym_index,
6231 .file = atom.file,
6232 }, self);
6233 defer gpa.free(nlists);
6234
6235 try locals.appendSlice(nlists);
6236 }
6237 }
6238
6239 // Close scope
6240 try locals.append(.{
6241 .n_strx = 0,
6242 .n_type = macho.N_SO,
6243 .n_sect = 0,
6244 .n_desc = 0,
6245 .n_value = 0,
6246 });
6247 }
6248 }
6249 for (object.symtab.items) |sym, sym_id| {6197 for (object.symtab.items) |sym, sym_id| {
6250 if (sym.n_strx == 0) continue; // no name, skip6198 if (sym.n_strx == 0) continue; // no name, skip
6251 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip6199 if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip
...@@ -6256,6 +6204,10 @@ fn writeSymtab(self: *MachO) !void {...@@ -6256,6 +6204,10 @@ fn writeSymtab(self: *MachO) !void {
6256 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));6204 out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc));
6257 try locals.append(out_sym);6205 try locals.append(out_sym);
6258 }6206 }
6207
6208 if (!self.base.options.strip) {
6209 try self.generateSymbolStabs(object, &locals);
6210 }
6259 }6211 }
62606212
6261 var exports = std.ArrayList(macho.nlist_64).init(gpa);6213 var exports = std.ArrayList(macho.nlist_64).init(gpa);
...@@ -6663,6 +6615,200 @@ pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate:...@@ -6663,6 +6615,200 @@ pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate:
6663 return i;6615 return i;
6664}6616}
66656617
6618const DebugInfo = struct {
6619 inner: dwarf.DwarfInfo,
6620 debug_info: []const u8,
6621 debug_abbrev: []const u8,
6622 debug_str: []const u8,
6623 debug_line: []const u8,
6624 debug_line_str: []const u8,
6625 debug_ranges: []const u8,
6626
6627 pub fn parse(allocator: Allocator, object: Object) !?DebugInfo {
6628 var debug_info = blk: {
6629 const index = object.dwarf_debug_info_index orelse return null;
6630 break :blk try object.getSectionContents(index);
6631 };
6632 var debug_abbrev = blk: {
6633 const index = object.dwarf_debug_abbrev_index orelse return null;
6634 break :blk try object.getSectionContents(index);
6635 };
6636 var debug_str = blk: {
6637 const index = object.dwarf_debug_str_index orelse return null;
6638 break :blk try object.getSectionContents(index);
6639 };
6640 var debug_line = blk: {
6641 const index = object.dwarf_debug_line_index orelse return null;
6642 break :blk try object.getSectionContents(index);
6643 };
6644 var debug_line_str = blk: {
6645 if (object.dwarf_debug_line_str_index) |ind| {
6646 break :blk try object.getSectionContents(ind);
6647 }
6648 break :blk &[0]u8{};
6649 };
6650 var debug_ranges = blk: {
6651 if (object.dwarf_debug_ranges_index) |ind| {
6652 break :blk try object.getSectionContents(ind);
6653 }
6654 break :blk &[0]u8{};
6655 };
6656
6657 var inner: dwarf.DwarfInfo = .{
6658 .endian = .Little,
6659 .debug_info = debug_info,
6660 .debug_abbrev = debug_abbrev,
6661 .debug_str = debug_str,
6662 .debug_line = debug_line,
6663 .debug_line_str = debug_line_str,
6664 .debug_ranges = debug_ranges,
6665 };
6666 try dwarf.openDwarfDebugInfo(&inner, allocator);
6667
6668 return DebugInfo{
6669 .inner = inner,
6670 .debug_info = debug_info,
6671 .debug_abbrev = debug_abbrev,
6672 .debug_str = debug_str,
6673 .debug_line = debug_line,
6674 .debug_line_str = debug_line_str,
6675 .debug_ranges = debug_ranges,
6676 };
6677 }
6678
6679 pub fn deinit(self: *DebugInfo, allocator: Allocator) void {
6680 self.inner.deinit(allocator);
6681 }
6682};
6683
6684pub fn generateSymbolStabs(
6685 self: *MachO,
6686 object: Object,
6687 locals: *std.ArrayList(macho.nlist_64),
6688) !void {
6689 assert(!self.base.options.strip);
6690
6691 const gpa = self.base.allocator;
6692
6693 log.debug("parsing debug info in '{s}'", .{object.name});
6694
6695 var debug_info = (try DebugInfo.parse(gpa, object)) orelse return;
6696
6697 // We assume there is only one CU.
6698 const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {
6699 error.MissingDebugInfo => {
6700 // TODO audit cases with missing debug info and audit our dwarf.zig module.
6701 log.debug("invalid or missing debug info in {s}; skipping", .{object.name});
6702 return;
6703 },
6704 else => |e| return e,
6705 };
6706 const tu_name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.name);
6707 const tu_comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir);
6708 const source_symtab = object.getSourceSymtab();
6709
6710 // Open scope
6711 try locals.ensureUnusedCapacity(3);
6712 locals.appendAssumeCapacity(.{
6713 .n_strx = try self.strtab.insert(gpa, tu_comp_dir),
6714 .n_type = macho.N_SO,
6715 .n_sect = 0,
6716 .n_desc = 0,
6717 .n_value = 0,
6718 });
6719 locals.appendAssumeCapacity(.{
6720 .n_strx = try self.strtab.insert(gpa, tu_name),
6721 .n_type = macho.N_SO,
6722 .n_sect = 0,
6723 .n_desc = 0,
6724 .n_value = 0,
6725 });
6726 locals.appendAssumeCapacity(.{
6727 .n_strx = try self.strtab.insert(gpa, object.name),
6728 .n_type = macho.N_OSO,
6729 .n_sect = 0,
6730 .n_desc = 1,
6731 .n_value = object.mtime,
6732 });
6733
6734 for (object.managed_atoms.items) |atom| {
6735 for (atom.contained.items) |sym_at_off| {
6736 const sym_loc = SymbolWithLoc{
6737 .sym_index = sym_at_off.sym_index,
6738 .file = atom.file,
6739 };
6740 const sym = self.getSymbol(sym_loc);
6741 const sym_name = self.getSymbolName(sym_loc);
6742 if (sym.n_strx == 0) continue;
6743 if (sym.n_desc == N_DESC_GCED) continue;
6744 if (self.symbolIsTemp(sym_loc)) continue;
6745 if (sym_at_off.sym_index >= source_symtab.len) continue; // synthetic, linker generated
6746
6747 const source_sym = source_symtab[sym_at_off.sym_index];
6748 const size: ?u64 = size: {
6749 if (source_sym.tentative()) break :size null;
6750 for (debug_info.inner.func_list.items) |func| {
6751 if (func.pc_range) |range| {
6752 if (source_sym.n_value >= range.start and source_sym.n_value < range.end) {
6753 break :size range.end - range.start;
6754 }
6755 }
6756 }
6757 break :size null;
6758 };
6759
6760 if (size) |ss| {
6761 try locals.ensureUnusedCapacity(4);
6762 locals.appendAssumeCapacity(.{
6763 .n_strx = 0,
6764 .n_type = macho.N_BNSYM,
6765 .n_sect = sym.n_sect,
6766 .n_desc = 0,
6767 .n_value = sym.n_value,
6768 });
6769 locals.appendAssumeCapacity(.{
6770 .n_strx = try self.strtab.insert(gpa, sym_name),
6771 .n_type = macho.N_FUN,
6772 .n_sect = sym.n_sect,
6773 .n_desc = 0,
6774 .n_value = sym.n_value,
6775 });
6776 locals.appendAssumeCapacity(.{
6777 .n_strx = 0,
6778 .n_type = macho.N_FUN,
6779 .n_sect = 0,
6780 .n_desc = 0,
6781 .n_value = ss,
6782 });
6783 locals.appendAssumeCapacity(.{
6784 .n_strx = 0,
6785 .n_type = macho.N_ENSYM,
6786 .n_sect = sym.n_sect,
6787 .n_desc = 0,
6788 .n_value = ss,
6789 });
6790 } else {
6791 try locals.append(.{
6792 .n_strx = try self.strtab.insert(gpa, sym_name),
6793 .n_type = macho.N_STSYM,
6794 .n_sect = sym.n_sect,
6795 .n_desc = 0,
6796 .n_value = sym.n_value,
6797 });
6798 }
6799 }
6800 }
6801
6802 // Close scope
6803 try locals.append(.{
6804 .n_strx = 0,
6805 .n_type = macho.N_SO,
6806 .n_sect = 0,
6807 .n_desc = 0,
6808 .n_value = 0,
6809 });
6810}
6811
6666fn snapshotState(self: *MachO) !void {6812fn snapshotState(self: *MachO) !void {
6667 const emit = self.base.options.emit orelse {6813 const emit = self.base.options.emit orelse {
6668 log.debug("no emit directory found; skipping snapshot...", .{});6814 log.debug("no emit directory found; skipping snapshot...", .{});
src/link/MachO/Atom.zig-70
...@@ -78,76 +78,6 @@ pub const Binding = struct {...@@ -78,76 +78,6 @@ pub const Binding = struct {
78pub const SymbolAtOffset = struct {78pub const SymbolAtOffset = struct {
79 sym_index: u32,79 sym_index: u32,
80 offset: u64,80 offset: u64,
81 stab: ?Stab = null,
82};
83
84pub const Stab = union(enum) {
85 function: u64,
86 static,
87 global,
88
89 pub fn asNlists(stab: Stab, sym_loc: SymbolWithLoc, macho_file: *MachO) ![]macho.nlist_64 {
90 const gpa = macho_file.base.allocator;
91
92 var nlists = std.ArrayList(macho.nlist_64).init(gpa);
93 defer nlists.deinit();
94
95 const sym = macho_file.getSymbol(sym_loc);
96 const sym_name = macho_file.getSymbolName(sym_loc);
97 switch (stab) {
98 .function => |size| {
99 try nlists.ensureUnusedCapacity(4);
100 nlists.appendAssumeCapacity(.{
101 .n_strx = 0,
102 .n_type = macho.N_BNSYM,
103 .n_sect = sym.n_sect,
104 .n_desc = 0,
105 .n_value = sym.n_value,
106 });
107 nlists.appendAssumeCapacity(.{
108 .n_strx = try macho_file.strtab.insert(gpa, sym_name),
109 .n_type = macho.N_FUN,
110 .n_sect = sym.n_sect,
111 .n_desc = 0,
112 .n_value = sym.n_value,
113 });
114 nlists.appendAssumeCapacity(.{
115 .n_strx = 0,
116 .n_type = macho.N_FUN,
117 .n_sect = 0,
118 .n_desc = 0,
119 .n_value = size,
120 });
121 nlists.appendAssumeCapacity(.{
122 .n_strx = 0,
123 .n_type = macho.N_ENSYM,
124 .n_sect = sym.n_sect,
125 .n_desc = 0,
126 .n_value = size,
127 });
128 },
129 .global => {
130 try nlists.append(.{
131 .n_strx = try macho_file.strtab.insert(gpa, sym_name),
132 .n_type = macho.N_GSYM,
133 .n_sect = 0,
134 .n_desc = 0,
135 .n_value = 0,
136 });
137 },
138 .static => {
139 try nlists.append(.{
140 .n_strx = try macho_file.strtab.insert(gpa, sym_name),
141 .n_type = macho.N_STSYM,
142 .n_sect = sym.n_sect,
143 .n_desc = 0,
144 .n_value = sym.n_value,
145 });
146 },
147 }
148
149 return nlists.toOwnedSlice();
150 }
151};81};
15282
153pub const Relocation = struct {83pub const Relocation = struct {
src/link/MachO/Object.zig+8-155
...@@ -3,7 +3,6 @@ const Object = @This();...@@ -3,7 +3,6 @@ const Object = @This();
3const std = @import("std");3const std = @import("std");
4const build_options = @import("build_options");4const build_options = @import("build_options");
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const dwarf = std.dwarf;
7const fs = std.fs;6const fs = std.fs;
8const io = std.io;7const io = std.io;
9const log = std.log.scoped(.link);8const log = std.log.scoped(.link);
...@@ -17,9 +16,11 @@ const Allocator = mem.Allocator;...@@ -17,9 +16,11 @@ const Allocator = mem.Allocator;
17const Atom = @import("Atom.zig");16const Atom = @import("Atom.zig");
18const MachO = @import("../MachO.zig");17const MachO = @import("../MachO.zig");
19const MatchingSection = MachO.MatchingSection;18const MatchingSection = MachO.MatchingSection;
19const SymbolWithLoc = MachO.SymbolWithLoc;
2020
21file: fs.File,21file: fs.File,
22name: []const u8,22name: []const u8,
23mtime: u64,
2324
24/// Data contents of the file. Includes sections, and data of load commands.25/// Data contents of the file. Includes sections, and data of load commands.
25/// Excludes the backing memory for the header and load commands.26/// Excludes the backing memory for the header and load commands.
...@@ -51,12 +52,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -51,12 +52,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
51strtab: []const u8 = &.{},52strtab: []const u8 = &.{},
52data_in_code_entries: []const macho.data_in_code_entry = &.{},53data_in_code_entries: []const macho.data_in_code_entry = &.{},
5354
54// Debug info
55debug_info: ?DebugInfo = null,
56tu_name: ?[]const u8 = null,
57tu_comp_dir: ?[]const u8 = null,
58mtime: ?u64 = null,
59
60sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},55sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},
6156
62/// List of atoms that map to the symbols parsed from this object file.57/// List of atoms that map to the symbols parsed from this object file.
...@@ -65,72 +60,6 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},...@@ -65,72 +60,6 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
65/// Table of atoms belonging to this object file indexed by the symbol index.60/// Table of atoms belonging to this object file indexed by the symbol index.
66atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{},61atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{},
6762
68const DebugInfo = struct {
69 inner: dwarf.DwarfInfo,
70 debug_info: []const u8,
71 debug_abbrev: []const u8,
72 debug_str: []const u8,
73 debug_line: []const u8,
74 debug_line_str: []const u8,
75 debug_ranges: []const u8,
76
77 pub fn parseFromObject(allocator: Allocator, object: *const Object) !?DebugInfo {
78 var debug_info = blk: {
79 const index = object.dwarf_debug_info_index orelse return null;
80 break :blk try object.getSectionContents(index);
81 };
82 var debug_abbrev = blk: {
83 const index = object.dwarf_debug_abbrev_index orelse return null;
84 break :blk try object.getSectionContents(index);
85 };
86 var debug_str = blk: {
87 const index = object.dwarf_debug_str_index orelse return null;
88 break :blk try object.getSectionContents(index);
89 };
90 var debug_line = blk: {
91 const index = object.dwarf_debug_line_index orelse return null;
92 break :blk try object.getSectionContents(index);
93 };
94 var debug_line_str = blk: {
95 if (object.dwarf_debug_line_str_index) |ind| {
96 break :blk try object.getSectionContents(ind);
97 }
98 break :blk &[0]u8{};
99 };
100 var debug_ranges = blk: {
101 if (object.dwarf_debug_ranges_index) |ind| {
102 break :blk try object.getSectionContents(ind);
103 }
104 break :blk &[0]u8{};
105 };
106
107 var inner: dwarf.DwarfInfo = .{
108 .endian = .Little,
109 .debug_info = debug_info,
110 .debug_abbrev = debug_abbrev,
111 .debug_str = debug_str,
112 .debug_line = debug_line,
113 .debug_line_str = debug_line_str,
114 .debug_ranges = debug_ranges,
115 };
116 try dwarf.openDwarfDebugInfo(&inner, allocator);
117
118 return DebugInfo{
119 .inner = inner,
120 .debug_info = debug_info,
121 .debug_abbrev = debug_abbrev,
122 .debug_str = debug_str,
123 .debug_line = debug_line,
124 .debug_line_str = debug_line_str,
125 .debug_ranges = debug_ranges,
126 };
127 }
128
129 pub fn deinit(self: *DebugInfo, allocator: Allocator) void {
130 self.inner.deinit(allocator);
131 }
132};
133
134pub fn deinit(self: *Object, gpa: Allocator) void {63pub fn deinit(self: *Object, gpa: Allocator) void {
135 for (self.load_commands.items) |*lc| {64 for (self.load_commands.items) |*lc| {
136 lc.deinit(gpa);65 lc.deinit(gpa);
...@@ -147,10 +76,6 @@ pub fn deinit(self: *Object, gpa: Allocator) void {...@@ -147,10 +76,6 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
147 self.managed_atoms.deinit(gpa);76 self.managed_atoms.deinit(gpa);
14877
149 gpa.free(self.name);78 gpa.free(self.name);
150
151 if (self.debug_info) |*db| {
152 db.deinit(gpa);
153 }
154}79}
15580
156pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {81pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {
...@@ -253,7 +178,6 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {...@@ -253,7 +178,6 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {
253178
254 try self.parseSymtab(allocator);179 try self.parseSymtab(allocator);
255 self.parseDataInCode();180 self.parseDataInCode();
256 try self.parseDebugInfo(allocator);
257}181}
258182
259const Context = struct {183const Context = struct {
...@@ -462,7 +386,6 @@ pub fn splitIntoAtomsOneShot(...@@ -462,7 +386,6 @@ pub fn splitIntoAtomsOneShot(
462 }386 }
463 break :blk false;387 break :blk false;
464 };388 };
465 macho_file.has_stabs = macho_file.has_stabs or self.debug_info != null;
466389
467 if (subsections_via_symbols and filtered_syms.len > 0) {390 if (subsections_via_symbols and filtered_syms.len > 0) {
468 // If the first nlist does not match the start of the section,391 // If the first nlist does not match the start of the section,
...@@ -566,7 +489,6 @@ pub fn splitIntoAtomsOneShot(...@@ -566,7 +489,6 @@ pub fn splitIntoAtomsOneShot(
566 try atom.contained.append(gpa, .{489 try atom.contained.append(gpa, .{
567 .sym_index = alias,490 .sym_index = alias,
568 .offset = 0,491 .offset = 0,
569 .stab = null,
570 });492 });
571 try self.atom_by_index_table.put(gpa, alias, atom);493 try self.atom_by_index_table.put(gpa, alias, atom);
572 }494 }
...@@ -671,54 +593,17 @@ fn createAtomFromSubsection(...@@ -671,54 +593,17 @@ fn createAtomFromSubsection(
671 // we can properly allocate addresses down the line.593 // we can properly allocate addresses down the line.
672 // While we're at it, we need to update segment,section mapping of each symbol too.594 // While we're at it, we need to update segment,section mapping of each symbol too.
673 try atom.contained.ensureTotalCapacity(gpa, indexes.len + 1);595 try atom.contained.ensureTotalCapacity(gpa, indexes.len + 1);
674596 atom.contained.appendAssumeCapacity(.{
675 {597 .sym_index = sym_index,
676 const stab: ?Atom.Stab = if (self.debug_info) |di| blk: {598 .offset = 0,
677 // TODO there has to be a better to handle this.599 });
678 for (di.inner.func_list.items) |func| {
679 if (func.pc_range) |range| {
680 if (sym.n_value >= range.start and sym.n_value < range.end) {
681 break :blk Atom.Stab{
682 .function = range.end - range.start,
683 };
684 }
685 }
686 }
687 // TODO
688 // if (zld.globals.contains(zld.getString(sym.strx))) break :blk .global;
689 break :blk .static;
690 } else null;
691
692 atom.contained.appendAssumeCapacity(.{
693 .sym_index = sym_index,
694 .offset = 0,
695 .stab = stab,
696 });
697 }
698600
699 for (indexes) |inner_sym_index| {601 for (indexes) |inner_sym_index| {
700 const inner_sym = &self.symtab.items[inner_sym_index.index];602 const inner_sym = &self.symtab.items[inner_sym_index.index];
701 inner_sym.n_sect = macho_file.getSectionOrdinal(match);603 inner_sym.n_sect = macho_file.getSectionOrdinal(match);
702
703 const stab: ?Atom.Stab = if (self.debug_info) |di| blk: {
704 // TODO there has to be a better to handle this.
705 for (di.inner.func_list.items) |func| {
706 if (func.pc_range) |range| {
707 if (inner_sym.n_value >= range.start and inner_sym.n_value < range.end) {
708 break :blk Atom.Stab{
709 .function = range.end - range.start,
710 };
711 }
712 }
713 }
714 // TODO
715 // if (zld.globals.contains(zld.getString(sym.strx))) break :blk .global;
716 break :blk .static;
717 } else null;
718 atom.contained.appendAssumeCapacity(.{604 atom.contained.appendAssumeCapacity(.{
719 .sym_index = inner_sym_index.index,605 .sym_index = inner_sym_index.index,
720 .offset = inner_sym.n_value - sym.n_value,606 .offset = inner_sym.n_value - sym.n_value,
721 .stab = stab,
722 });607 });
723608
724 try self.atom_by_index_table.putNoClobber(gpa, inner_sym_index.index, atom);609 try self.atom_by_index_table.putNoClobber(gpa, inner_sym_index.index, atom);
...@@ -755,7 +640,7 @@ fn parseSymtab(self: *Object, allocator: Allocator) !void {...@@ -755,7 +640,7 @@ fn parseSymtab(self: *Object, allocator: Allocator) !void {
755 self.strtab = self.contents[symtab.stroff..][0..symtab.strsize];640 self.strtab = self.contents[symtab.stroff..][0..symtab.strsize];
756}641}
757642
758fn getSourceSymtab(self: *Object) []const macho.nlist_64 {643pub fn getSourceSymtab(self: Object) []const macho.nlist_64 {
759 const index = self.symtab_cmd_index orelse return &[0]macho.nlist_64{};644 const index = self.symtab_cmd_index orelse return &[0]macho.nlist_64{};
760 const symtab = self.load_commands.items[index].symtab;645 const symtab = self.load_commands.items[index].symtab;
761 const symtab_size = @sizeOf(macho.nlist_64) * symtab.nsyms;646 const symtab_size = @sizeOf(macho.nlist_64) * symtab.nsyms;
...@@ -766,38 +651,6 @@ fn getSourceSymtab(self: *Object) []const macho.nlist_64 {...@@ -766,38 +651,6 @@ fn getSourceSymtab(self: *Object) []const macho.nlist_64 {
766 );651 );
767}652}
768653
769fn parseDebugInfo(self: *Object, allocator: Allocator) !void {
770 log.debug("parsing debug info in '{s}'", .{self.name});
771
772 var debug_info = blk: {
773 var di = try DebugInfo.parseFromObject(allocator, self);
774 break :blk di orelse return;
775 };
776
777 // We assume there is only one CU.
778 const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {
779 error.MissingDebugInfo => {
780 // TODO audit cases with missing debug info and audit our dwarf.zig module.
781 log.debug("invalid or missing debug info in {s}; skipping", .{self.name});
782 return;
783 },
784 else => |e| return e,
785 };
786 const name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.name);
787 const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir);
788
789 self.debug_info = debug_info;
790 self.tu_name = name;
791 self.tu_comp_dir = comp_dir;
792
793 if (self.mtime == null) {
794 self.mtime = mtime: {
795 const stat = self.file.stat() catch break :mtime 0;
796 break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
797 };
798 }
799}
800
801fn parseDataInCode(self: *Object) void {654fn parseDataInCode(self: *Object) void {
802 const index = self.data_in_code_cmd_index orelse return;655 const index = self.data_in_code_cmd_index orelse return;
803 const data_in_code = self.load_commands.items[index].linkedit_data;656 const data_in_code = self.load_commands.items[index].linkedit_data;
...@@ -808,7 +661,7 @@ fn parseDataInCode(self: *Object) void {...@@ -808,7 +661,7 @@ fn parseDataInCode(self: *Object) void {
808 );661 );
809}662}
810663
811fn getSectionContents(self: Object, sect_id: u16) error{Overflow}![]const u8 {664pub fn getSectionContents(self: Object, sect_id: u16) error{Overflow}![]const u8 {
812 const sect = self.getSection(sect_id);665 const sect = self.getSection(sect_id);
813 const size = math.cast(usize, sect.size) orelse return error.Overflow;666 const size = math.cast(usize, sect.size) orelse return error.Overflow;
814 log.debug("getting {s},{s} data at 0x{x} - 0x{x}", .{667 log.debug("getting {s},{s} data at 0x{x} - 0x{x}", .{