authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-18 12:37:25+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-20 19:41:29+01:00
logb9c02e4076204c49500fd1d0dcb91420aed17f03
treea89d863b97585a14379e147b2586ee29a8fcc711
parent2a350cf1745f08c98c5897ce2d27627d28ea00da

elvis entered the building


1 files changed, 130 insertions(+), 69 deletions(-)

lib/std/debug.zig+130-69
...@@ -700,7 +700,8 @@ fn printSourceAtAddressMacOs(di1: *DebugInfo, out_stream: var, address: usize, t...@@ -700,7 +700,8 @@ fn printSourceAtAddressMacOs(di1: *DebugInfo, out_stream: var, address: usize, t
700 const di = try di1.lookupByAddress(address);700 const di = try di1.lookupByAddress(address);
701701
702 const base_addr = di.base_address;702 const base_addr = di.base_address;
703 const adjusted_addr = 0x100000000 + (address - base_addr);703 const adjusted_addr = address - base_addr;
704 assert(adjusted_addr >= 0x100000000);
704705
705 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {706 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
706 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);707 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
...@@ -734,7 +735,6 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres...@@ -734,7 +735,6 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres
734 const module = try debug_info.lookupByAddress(address);735 const module = try debug_info.lookupByAddress(address);
735736
736 const reloc_address = address - module.base_address;737 const reloc_address = address - module.base_address;
737 warn("reloc {x} => {x}\n", .{ address, reloc_address });
738738
739 if (module.dwarf.findCompileUnit(reloc_address) catch null) |compile_unit| {739 if (module.dwarf.findCompileUnit(reloc_address) catch null) |compile_unit| {
740 const compile_unit_name = try compile_unit.die.getAttrString(&module.dwarf, DW.AT_name);740 const compile_unit_name = try compile_unit.die.getAttrString(&module.dwarf, DW.AT_name);
...@@ -1078,29 +1078,33 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DW.DwarfInfo {...@@ -1078,29 +1078,33 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DW.DwarfInfo {
1078}1078}
10791079
1080/// TODO resources https://github.com/ziglang/zig/issues/43531080/// TODO resources https://github.com/ziglang/zig/issues/4353
1081fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {1081fn openMachODebugInfo(allocator: *mem.Allocator, memmo: []const u8) !ObjectDebugInfo {
1082 const hdr = &std.c._mh_execute_header;1082 // const hdr = &std.c._mh_execute_header;
1083 const hdr = @ptrCast(
1084 *const macho.mach_header_64,
1085 @alignCast(@alignOf(macho.mach_header_64), memmo.ptr),
1086 );
1083 assert(hdr.magic == std.macho.MH_MAGIC_64);1087 assert(hdr.magic == std.macho.MH_MAGIC_64);
10841088
1085 const hdr_base = @ptrCast([*]u8, hdr);1089 const hdr_base = @ptrCast([*]const u8, hdr);
1086 var ptr = hdr_base + @sizeOf(macho.mach_header_64);1090 var ptr = hdr_base + @sizeOf(macho.mach_header_64);
1087 var ncmd: u32 = hdr.ncmds;1091 var ncmd: u32 = hdr.ncmds;
1088 const symtab = while (ncmd != 0) : (ncmd -= 1) {1092 const symtab = while (ncmd != 0) : (ncmd -= 1) {
1089 const lc = @ptrCast(*std.macho.load_command, ptr);1093 const lc = @ptrCast(*const std.macho.load_command, ptr);
1090 switch (lc.cmd) {1094 switch (lc.cmd) {
1091 std.macho.LC_SYMTAB => break @ptrCast(*std.macho.symtab_command, ptr),1095 std.macho.LC_SYMTAB => break @ptrCast(*const std.macho.symtab_command, ptr),
1092 else => {},1096 else => {},
1093 }1097 }
1094 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);1098 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
1095 } else {1099 } else {
1096 return error.MissingDebugInfo;1100 return error.MissingDebugInfo;
1097 };1101 };
1098 const syms = @ptrCast([*]macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];1102 const syms = @ptrCast([*]const macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];
1099 const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize];1103 const strings = @ptrCast([*]const u8, hdr_base + symtab.stroff)[0..symtab.strsize];
11001104
1101 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);1105 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
11021106
1103 var ofile: ?*macho.nlist_64 = null;1107 var ofile: ?*const macho.nlist_64 = null;
1104 var reloc: u64 = 0;1108 var reloc: u64 = 0;
1105 var symbol_index: usize = 0;1109 var symbol_index: usize = 0;
1106 var last_len: u64 = 0;1110 var last_len: u64 = 0;
...@@ -1148,8 +1152,10 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -1148,8 +1152,10 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
1148 // This sort is so that we can binary search later.1152 // This sort is so that we can binary search later.
1149 std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);1153 std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);
11501154
1151 return DebugInfo{1155 return ObjectDebugInfo{
1152 .ofiles = DebugInfo.OFileTable.init(allocator),1156 .base_address = undefined,
1157 .mapped_memory = undefined,
1158 .ofiles = ObjectDebugInfo.OFileTable.init(allocator),
1153 .symbols = symbols,1159 .symbols = symbols,
1154 .strings = strings,1160 .strings = strings,
1155 };1161 };
...@@ -1188,8 +1194,8 @@ fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {...@@ -1188,8 +1194,8 @@ fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
1188}1194}
11891195
1190const MachoSymbol = struct {1196const MachoSymbol = struct {
1191 nlist: *macho.nlist_64,1197 nlist: *const macho.nlist_64,
1192 ofile: ?*macho.nlist_64,1198 ofile: ?*const macho.nlist_64,
1193 reloc: u64,1199 reloc: u64,
11941200
1195 /// Returns the address from the macho file1201 /// Returns the address from the macho file
...@@ -1233,18 +1239,68 @@ pub const DebugInfo = struct {...@@ -1233,18 +1239,68 @@ pub const DebugInfo = struct {
12331239
1234 var i: u32 = 0;1240 var i: u32 = 0;
1235 while (i < image_count) : (i += 1) {1241 while (i < image_count) : (i += 1) {
1242 const base_address = std.c._dyld_get_image_vmaddr_slide(i);
1243
1244 if (address < base_address) continue;
1245
1236 const header = std.c._dyld_get_image_header(i) orelse continue;1246 const header = std.c._dyld_get_image_header(i) orelse continue;
1237 // The array of load commands is right after the header1247 // The array of load commands is right after the header
1238 var cmd_ptr = @intToPtr([*]u8, @ptrToInt(header) + @sizeOf(macho.mach_header_64));1248 var cmd_ptr = @intToPtr([*]u8, @ptrToInt(header) + @sizeOf(macho.mach_header_64));
1239 const cmd_ptr_end = cmd_ptr + header.sizeofcmds;
12401249
1241 var cmd = 1250 var cmds = header.ncmds;
1242 for (cmds) |*lc| {1251 while (cmds != 0) : (cmds -= 1) {
1252 const lc = @ptrCast(
1253 *macho.load_command,
1254 @alignCast(@alignOf(macho.load_command), cmd_ptr),
1255 );
1256 cmd_ptr += lc.cmdsize;
1243 if (lc.cmd != macho.LC_SEGMENT_64) continue;1257 if (lc.cmd != macho.LC_SEGMENT_64) continue;
12441258
1245 const segment_cmd = @ptrCast(*macho.segment_command_64, lc);1259 const segment_cmd = @ptrCast(
1260 *const std.macho.segment_command_64,
1261 @alignCast(@alignOf(std.macho.segment_command_64), lc),
1262 );
1263
1264 const rebased_address = address - base_address;
1265 const seg_start = segment_cmd.vmaddr;
1266 const seg_end = seg_start + segment_cmd.vmsize;
1267
1268 if (rebased_address >= seg_start and rebased_address < seg_end) {
1269 if (self.address_map.getValue(base_address)) |obj_di| {
1270 return obj_di;
1271 }
1272
1273 const image_name = std.c._dyld_get_image_name(i);
1274 const exe_file = try fs.openFileAbsoluteC(image_name, .{});
1275 errdefer exe_file.close();
1276
1277 const exe_len = math.cast(usize, try exe_file.getEndPos()) catch
1278 return error.DebugInfoTooLarge;
1279 const exe_mmap = try os.mmap(
1280 null,
1281 exe_len,
1282 os.PROT_READ,
1283 os.MAP_SHARED,
1284 exe_file.handle,
1285 0,
1286 );
1287 errdefer os.munmap(exe_mmap);
1288
1289 const obj_di = try self.allocator.create(ObjectDebugInfo);
1290 errdefer self.allocator.destroy(obj_di);
1291
1292 try self.address_map.putNoClobber(base_address, obj_di);
1293
1294 obj_di.* = try openMachODebugInfo(self.allocator, exe_mmap);
1295 obj_di.base_address = base_address;
1296 obj_di.mapped_memory = exe_mmap;
1297
1298 return obj_di;
1299 }
1246 }1300 }
1247 }1301 }
1302
1303 return error.DebugInfoNotFound;
1248 }1304 }
12491305
1250 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1306 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
...@@ -1252,7 +1308,8 @@ pub const DebugInfo = struct {...@@ -1252,7 +1308,8 @@ pub const DebugInfo = struct {
12521308
1253 var modules: [32]windows.HMODULE = undefined;1309 var modules: [32]windows.HMODULE = undefined;
1254 var modules_needed: windows.DWORD = undefined;1310 var modules_needed: windows.DWORD = undefined;
1255 // XXX Ask for the number of modules by passing size zero1311 // TODO: Ask for the number of modules by passing size zero, 32 ought to
1312 // be enough for everyone in the meanwhile
1256 if (windows.kernel32.K32EnumProcessModules(1313 if (windows.kernel32.K32EnumProcessModules(
1257 process_handle,1314 process_handle,
1258 @ptrCast([*]windows.HMODULE, &modules),1315 @ptrCast([*]windows.HMODULE, &modules),
...@@ -1275,6 +1332,10 @@ pub const DebugInfo = struct {...@@ -1275,6 +1332,10 @@ pub const DebugInfo = struct {
1275 const seg_end = seg_start + info.SizeOfImage;1332 const seg_end = seg_start + info.SizeOfImage;
12761333
1277 if (address >= seg_start and address < seg_end) {1334 if (address >= seg_start and address < seg_end) {
1335 if (self.address_map.getValue(seg_start)) |obj_di| {
1336 return obj_di;
1337 }
1338
1278 var name_buffer: [windows.PATH_MAX_WIDE + 4:0]u16 = undefined;1339 var name_buffer: [windows.PATH_MAX_WIDE + 4:0]u16 = undefined;
1279 // openFileAbsoluteW requires the prefix to be present1340 // openFileAbsoluteW requires the prefix to be present
1280 mem.copy(u16, name_buffer[0..4], &[_]u16{ '\\', '?', '?', '\\' });1341 mem.copy(u16, name_buffer[0..4], &[_]u16{ '\\', '?', '?', '\\' });
...@@ -1286,12 +1347,8 @@ pub const DebugInfo = struct {...@@ -1286,12 +1347,8 @@ pub const DebugInfo = struct {
1286 );1347 );
1287 assert(len > 0);1348 assert(len > 0);
12881349
1289 if (self.address_map.getValue(seg_start)) |obj_di| {1350 // The compiler segfaults if the slicing is done as a parameter
1290 return obj_di;1351 // (#4423)
1291 }
1292
1293 // XXX: The compiler segfaults if the slicing is done as a
1294 // parameter (#4423)
1295 const tmp = name_buffer[0..:0];1352 const tmp = name_buffer[0..:0];
1296 const file_obj = try fs.openFileAbsoluteW(tmp, .{});1353 const file_obj = try fs.openFileAbsoluteW(tmp, .{});
1297 errdefer file_obj.close();1354 errdefer file_obj.close();
...@@ -1312,11 +1369,49 @@ pub const DebugInfo = struct {...@@ -1312,11 +1369,49 @@ pub const DebugInfo = struct {
1312 }1369 }
13131370
1314 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1371 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1315 var ctx = DIPContext{ .address = address };1372 var ctx: struct {
1373 // Input
1374 address: usize,
1375 // Output
1376 base_address: usize = undefined,
1377 name: []const u8 = undefined,
1378 } = .{ .address = address };
1379 const CtxTy = @TypeOf(ctx);
1380
1381 if (os.dl_iterate_phdr(&ctx, anyerror, struct {
1382 fn callback(info: *os.dl_phdr_info, size: usize, context: *CtxTy) !void {
1383 // The base address is too high
1384 if (context.address < info.dlpi_addr)
1385 return;
13161386
1317 // XXX Locking?1387 const phdrs = info.dlpi_phdr[0..info.dlpi_phnum];
1318 if (os.dl_iterate_phdr(DIPContext, dl_iterate_phdr_callback, &ctx) == 0)1388 for (phdrs) |*phdr| {
1389 if (phdr.p_type != elf.PT_LOAD) continue;
1390
1391 const seg_start = info.dlpi_addr + phdr.p_vaddr;
1392 const seg_end = seg_start + phdr.p_memsz;
1393
1394 if (context.address >= seg_start and context.address < seg_end) {
1395 // Android libc uses NULL instead of an empty string to mark the
1396 // main program
1397 context.name = if (info.dlpi_name) |dlpi_name|
1398 mem.toSliceConst(u8, dlpi_name)
1399 else
1400 "";
1401 context.base_address = info.dlpi_addr;
1402 // Stop the iteration
1403 return error.Found;
1404 }
1405 }
1406 }
1407 }.callback)) {
1319 return error.DebugInfoNotFound;1408 return error.DebugInfoNotFound;
1409 } else |err| {
1410 switch (err) {
1411 error.Found => {},
1412 else => return error.DebugInfoNotFound,
1413 }
1414 }
13201415
1321 if (self.address_map.getValue(ctx.base_address)) |obj_di| {1416 if (self.address_map.getValue(ctx.base_address)) |obj_di| {
1322 return obj_di;1417 return obj_di;
...@@ -1355,58 +1450,24 @@ pub const DebugInfo = struct {...@@ -1355,58 +1450,24 @@ pub const DebugInfo = struct {
1355 }1450 }
1356};1451};
13571452
1358const DIPContext = struct {1453const DIPContext = struct {};
1359 address: usize,
1360 base_address: usize = undefined,
1361 name: []const u8 = undefined,
1362};
1363
1364fn dl_iterate_phdr_callback(info: *os.dl_phdr_info, size: usize, context: ?*DIPContext) callconv(.C) i32 {
1365 const address = context.?.address;
1366
1367 // The base address is too high
1368 if (address < info.dlpi_addr)
1369 return 0;
1370
1371 const phdrs = info.dlpi_phdr[0..info.dlpi_phnum];
1372 for (phdrs) |*phdr| {
1373 if (phdr.p_type != elf.PT_LOAD) continue;
1374
1375 const seg_start = info.dlpi_addr + phdr.p_vaddr;
1376 const seg_end = seg_start + phdr.p_memsz;
1377
1378 if (address >= seg_start and address < seg_end) {
1379 // Android libc uses NULL instead of an empty string to mark the
1380 // main program
1381 context.?.name = if (info.dlpi_name) |dlpi_name|
1382 mem.toSliceConst(u8, dlpi_name)
1383 else
1384 "";
1385 context.?.base_address = info.dlpi_addr;
1386 // Stop the iteration
1387 return 1;
1388 }
1389 }
1390
1391 // Continue the iteration
1392 return 0;
1393}
13941454
1395pub const ObjectDebugInfo = switch (builtin.os) {1455pub const ObjectDebugInfo = switch (builtin.os) {
1396 .macosx, .ios, .watchos, .tvos => struct {1456 .macosx, .ios, .watchos, .tvos => struct {
1397 base_address: usize,1457 base_address: usize,
1458 mapped_memory: []u8,
1398 symbols: []const MachoSymbol,1459 symbols: []const MachoSymbol,
1399 strings: []const u8,1460 strings: []const u8,
1400 ofiles: OFileTable,1461 ofiles: OFileTable,
14011462
1402 const OFileTable = std.HashMap(1463 const OFileTable = std.HashMap(
1403 *macho.nlist_64,1464 *const macho.nlist_64,
1404 DW.DwarfInfo,1465 DW.DwarfInfo,
1405 std.hash_map.getHashPtrAddrFn(*macho.nlist_64),1466 std.hash_map.getHashPtrAddrFn(*const macho.nlist_64),
1406 std.hash_map.getTrivialEqlFn(*macho.nlist_64),1467 std.hash_map.getTrivialEqlFn(*const macho.nlist_64),
1407 );1468 );
14081469
1409 pub fn allocator(self: DebugInfo) *mem.Allocator {1470 pub fn allocator(self: @This()) *mem.Allocator {
1410 return self.ofiles.allocator;1471 return self.ofiles.allocator;
1411 }1472 }
1412 },1473 },
...@@ -1426,7 +1487,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {...@@ -1426,7 +1487,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {
1426};1487};
14271488
1428/// TODO resources https://github.com/ziglang/zig/issues/43531489/// TODO resources https://github.com/ziglang/zig/issues/4353
1429fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, address: usize) !LineInfo {1490fn getLineNumberInfoMacOs(di: *ObjectDebugInfo, symbol: MachoSymbol, address: usize) !LineInfo {
1430 const ofile = symbol.ofile orelse return error.MissingDebugInfo;1491 const ofile = symbol.ofile orelse return error.MissingDebugInfo;
1431 const gop = try di.ofiles.getOrPut(ofile);1492 const gop = try di.ofiles.getOrPut(ofile);
1432 const dwarf_info = if (gop.found_existing) &gop.kv.value else blk: {1493 const dwarf_info = if (gop.found_existing) &gop.kv.value else blk: {