Skip to content

Commit ae16c1d

Browse files
committed
std: use std.macho.LoadCommandIterator for MachO parsing in std.debug
1 parent b3d463c commit ae16c1d

File tree

1 file changed

+69
-98
lines changed

1 file changed

+69
-98
lines changed

lib/std/debug.zig

Lines changed: 69 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -968,24 +968,20 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn
968968
if (hdr.magic != macho.MH_MAGIC_64)
969969
return error.InvalidDebugInfo;
970970

971-
const hdr_base = @ptrCast([*]const u8, hdr);
972-
var ptr = hdr_base + @sizeOf(macho.mach_header_64);
973-
var ncmd: u32 = hdr.ncmds;
974-
const symtab = while (ncmd != 0) : (ncmd -= 1) {
975-
const lc = @ptrCast(*const std.macho.load_command, ptr);
976-
switch (lc.cmd) {
977-
.SYMTAB => break @ptrCast(*const std.macho.symtab_command, ptr),
978-
else => {},
979-
}
980-
ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
981-
} else {
982-
return error.MissingDebugInfo;
971+
var it = macho.LoadCommandIterator{
972+
.ncmds = hdr.ncmds,
973+
.buffer = mapped_mem[@sizeOf(macho.mach_header_64)..][0..hdr.sizeofcmds],
983974
};
975+
const symtab = while (it.next()) |cmd| switch (cmd.cmd()) {
976+
.SYMTAB => break cmd.cast(macho.symtab_command).?,
977+
else => {},
978+
} else return error.MissingDebugInfo;
979+
984980
const syms = @ptrCast(
985981
[*]const macho.nlist_64,
986-
@alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff),
982+
@alignCast(@alignOf(macho.nlist_64), &mapped_mem[symtab.symoff]),
987983
)[0..symtab.nsyms];
988-
const strings = @ptrCast([*]const u8, hdr_base + symtab.stroff)[0 .. symtab.strsize - 1 :0];
984+
const strings = mapped_mem[symtab.stroff..][0 .. symtab.strsize - 1 :0];
989985

990986
const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
991987

@@ -1200,48 +1196,46 @@ pub const DebugInfo = struct {
12001196
if (address < base_address) continue;
12011197

12021198
const header = std.c._dyld_get_image_header(i) orelse continue;
1203-
// The array of load commands is right after the header
1204-
var cmd_ptr = @intToPtr([*]u8, @ptrToInt(header) + @sizeOf(macho.mach_header_64));
1205-
1206-
var cmds = header.ncmds;
1207-
while (cmds != 0) : (cmds -= 1) {
1208-
const lc = @ptrCast(
1209-
*macho.load_command,
1210-
@alignCast(@alignOf(macho.load_command), cmd_ptr),
1211-
);
1212-
cmd_ptr += lc.cmdsize;
1213-
if (lc.cmd != .SEGMENT_64) continue;
12141199

1215-
const segment_cmd = @ptrCast(
1216-
*const std.macho.segment_command_64,
1217-
@alignCast(@alignOf(std.macho.segment_command_64), lc),
1218-
);
1200+
var it = macho.LoadCommandIterator{
1201+
.ncmds = header.ncmds,
1202+
.buffer = @alignCast(@alignOf(u64), @intToPtr(
1203+
[*]u8,
1204+
@ptrToInt(header) + @sizeOf(macho.mach_header_64),
1205+
))[0..header.sizeofcmds],
1206+
};
1207+
while (it.next()) |cmd| switch (cmd.cmd()) {
1208+
.SEGMENT_64 => {
1209+
const segment_cmd = cmd.cast(macho.segment_command_64).?;
1210+
const rebased_address = address - base_address;
1211+
const seg_start = segment_cmd.vmaddr;
1212+
const seg_end = seg_start + segment_cmd.vmsize;
1213+
1214+
if (rebased_address >= seg_start and rebased_address < seg_end) {
1215+
if (self.address_map.get(base_address)) |obj_di| {
1216+
return obj_di;
1217+
}
1218+
1219+
const obj_di = try self.allocator.create(ModuleDebugInfo);
1220+
errdefer self.allocator.destroy(obj_di);
1221+
1222+
const macho_path = mem.sliceTo(std.c._dyld_get_image_name(i), 0);
1223+
const macho_file = fs.cwd().openFile(macho_path, .{
1224+
.intended_io_mode = .blocking,
1225+
}) catch |err| switch (err) {
1226+
error.FileNotFound => return error.MissingDebugInfo,
1227+
else => return err,
1228+
};
1229+
obj_di.* = try readMachODebugInfo(self.allocator, macho_file);
1230+
obj_di.base_address = base_address;
12191231

1220-
const rebased_address = address - base_address;
1221-
const seg_start = segment_cmd.vmaddr;
1222-
const seg_end = seg_start + segment_cmd.vmsize;
1232+
try self.address_map.putNoClobber(base_address, obj_di);
12231233

1224-
if (rebased_address >= seg_start and rebased_address < seg_end) {
1225-
if (self.address_map.get(base_address)) |obj_di| {
12261234
return obj_di;
12271235
}
1228-
1229-
const obj_di = try self.allocator.create(ModuleDebugInfo);
1230-
errdefer self.allocator.destroy(obj_di);
1231-
1232-
const macho_path = mem.sliceTo(std.c._dyld_get_image_name(i), 0);
1233-
const macho_file = fs.cwd().openFile(macho_path, .{ .intended_io_mode = .blocking }) catch |err| switch (err) {
1234-
error.FileNotFound => return error.MissingDebugInfo,
1235-
else => return err,
1236-
};
1237-
obj_di.* = try readMachODebugInfo(self.allocator, macho_file);
1238-
obj_di.base_address = base_address;
1239-
1240-
try self.address_map.putNoClobber(base_address, obj_di);
1241-
1242-
return obj_di;
1243-
}
1244-
}
1236+
},
1237+
else => {},
1238+
};
12451239
}
12461240

12471241
return error.MissingDebugInfo;
@@ -1445,44 +1439,31 @@ pub const ModuleDebugInfo = switch (native_os) {
14451439
if (hdr.magic != std.macho.MH_MAGIC_64)
14461440
return error.InvalidDebugInfo;
14471441

1448-
const hdr_base = @ptrCast([*]const u8, hdr);
1449-
var ptr = hdr_base + @sizeOf(macho.mach_header_64);
1450-
var segptr = ptr;
1451-
var ncmd: u32 = hdr.ncmds;
1452-
var segcmd: ?*const macho.segment_command_64 = null;
1453-
var symtabcmd: ?*const macho.symtab_command = null;
1454-
1455-
while (ncmd != 0) : (ncmd -= 1) {
1456-
const lc = @ptrCast(*const std.macho.load_command, ptr);
1457-
switch (lc.cmd) {
1458-
.SEGMENT_64 => {
1459-
segcmd = @ptrCast(
1460-
*const std.macho.segment_command_64,
1461-
@alignCast(@alignOf(std.macho.segment_command_64), ptr),
1462-
);
1463-
segptr = ptr;
1464-
},
1465-
.SYMTAB => {
1466-
symtabcmd = @ptrCast(
1467-
*const std.macho.symtab_command,
1468-
@alignCast(@alignOf(std.macho.symtab_command), ptr),
1469-
);
1470-
},
1471-
else => {},
1472-
}
1473-
ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
1474-
}
1442+
var segcmd: ?macho.LoadCommandIterator.LoadCommand = null;
1443+
var symtabcmd: ?macho.symtab_command = null;
1444+
var it = macho.LoadCommandIterator{
1445+
.ncmds = hdr.ncmds,
1446+
.buffer = mapped_mem[@sizeOf(macho.mach_header_64)..][0..hdr.sizeofcmds],
1447+
};
1448+
while (it.next()) |cmd| switch (cmd.cmd()) {
1449+
.SEGMENT_64 => segcmd = cmd,
1450+
.SYMTAB => symtabcmd = cmd.cast(macho.symtab_command).?,
1451+
else => {},
1452+
};
14751453

14761454
if (segcmd == null or symtabcmd == null) return error.MissingDebugInfo;
14771455

14781456
// Parse symbols
14791457
const strtab = @ptrCast(
14801458
[*]const u8,
1481-
hdr_base + symtabcmd.?.stroff,
1459+
&mapped_mem[symtabcmd.?.stroff],
14821460
)[0 .. symtabcmd.?.strsize - 1 :0];
14831461
const symtab = @ptrCast(
14841462
[*]const macho.nlist_64,
1485-
@alignCast(@alignOf(macho.nlist_64), hdr_base + symtabcmd.?.symoff),
1463+
@alignCast(
1464+
@alignOf(macho.nlist_64),
1465+
&mapped_mem[symtabcmd.?.symoff],
1466+
),
14861467
)[0..symtabcmd.?.nsyms];
14871468

14881469
// TODO handle tentative (common) symbols
@@ -1496,25 +1477,15 @@ pub const ModuleDebugInfo = switch (native_os) {
14961477
addr_table.putAssumeCapacityNoClobber(sym_name, sym.n_value);
14971478
}
14981479

1499-
var opt_debug_line: ?*const macho.section_64 = null;
1500-
var opt_debug_info: ?*const macho.section_64 = null;
1501-
var opt_debug_abbrev: ?*const macho.section_64 = null;
1502-
var opt_debug_str: ?*const macho.section_64 = null;
1503-
var opt_debug_line_str: ?*const macho.section_64 = null;
1504-
var opt_debug_ranges: ?*const macho.section_64 = null;
1505-
1506-
const sections = @ptrCast(
1507-
[*]const macho.section_64,
1508-
@alignCast(@alignOf(macho.section_64), segptr + @sizeOf(std.macho.segment_command_64)),
1509-
)[0..segcmd.?.nsects];
1510-
for (sections) |*sect| {
1511-
// The section name may not exceed 16 chars and a trailing null may
1512-
// not be present
1513-
const name = if (mem.indexOfScalar(u8, sect.sectname[0..], 0)) |last|
1514-
sect.sectname[0..last]
1515-
else
1516-
sect.sectname[0..];
1480+
var opt_debug_line: ?macho.section_64 = null;
1481+
var opt_debug_info: ?macho.section_64 = null;
1482+
var opt_debug_abbrev: ?macho.section_64 = null;
1483+
var opt_debug_str: ?macho.section_64 = null;
1484+
var opt_debug_line_str: ?macho.section_64 = null;
1485+
var opt_debug_ranges: ?macho.section_64 = null;
15171486

1487+
for (segcmd.?.getSections()) |sect| {
1488+
const name = sect.sectName();
15181489
if (mem.eql(u8, name, "__debug_line")) {
15191490
opt_debug_line = sect;
15201491
} else if (mem.eql(u8, name, "__debug_info")) {

0 commit comments

Comments
 (0)