authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-22 12:44:21+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-22 12:44:21+01:00
log495e894225d3bb5695681be87ed0cd1b7f9825a2
treefba03aa09c92f65c62cb4bbf485a781e5017530b
parent41bca1ce760f415df5bc89acb0f609659e9bdad8

delete extra code, more forgiveness


2 files changed, 48 insertions(+), 192 deletions(-)

lib/std/debug.zig+37-192
......@@ -390,179 +390,6 @@ pub fn writeCurrentStackTraceWindows(
390390 }
391391}
392392
393/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
394/// make this `noasync fn` and remove the individual noasync calls.
395pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
396 // if (builtin.os == .windows) {
397 // return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
398 // }
399 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
400}
401
402/// TODO resources https://github.com/ziglang/zig/issues/4353
403fn printSourceAtAddressWindows(
404 debug_info: *DebugInfo,
405 out_stream: var,
406 address: usize,
407 tty_config: TTY.Config,
408) !void {
409 const allocator = debug_info.allocator;
410
411 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
412 error.MissingDebugInfo, error.InvalidDebugInfo => {
413 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
414 },
415 else => return err,
416 };
417 const relocated_address = address - module.base_address;
418
419 var coff_section: *coff.Section = undefined;
420 const mod_index = for (module.sect_contribs) |sect_contrib| {
421 if (sect_contrib.Section > module.coff.sections.len) continue;
422 // Remember that SectionContribEntry.Section is 1-based.
423 coff_section = &module.coff.sections.toSlice()[sect_contrib.Section - 1];
424
425 const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
426 const vaddr_end = vaddr_start + sect_contrib.Size;
427 if (relocated_address >= vaddr_start and relocated_address < vaddr_end) {
428 break sect_contrib.ModuleIndex;
429 }
430 } else {
431 // we have no information to add to the address
432 return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs);
433 };
434
435 const mod = &module.modules[mod_index];
436 try populateModule(module, mod);
437 const obj_basename = fs.path.basename(mod.obj_file_name);
438
439 var symbol_i: usize = 0;
440 const symbol_name = if (!mod.populated) "???" else while (symbol_i != mod.symbols.len) {
441 const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);
442 if (prefix.RecordLen < 2)
443 return error.InvalidDebugInfo;
444 switch (prefix.RecordKind) {
445 .S_LPROC32, .S_GPROC32 => {
446 const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]);
447 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
448 const vaddr_end = vaddr_start + proc_sym.CodeSize;
449 if (relocated_address >= vaddr_start and relocated_address < vaddr_end) {
450 break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym));
451 }
452 },
453 else => {},
454 }
455 symbol_i += prefix.RecordLen + @sizeOf(u16);
456 if (symbol_i > mod.symbols.len)
457 return error.InvalidDebugInfo;
458 } else "???";
459
460 const subsect_info = mod.subsect_info;
461
462 var sect_offset: usize = 0;
463 var skip_len: usize = undefined;
464 const opt_line_info = subsections: {
465 const checksum_offset = mod.checksum_offset orelse break :subsections null;
466 while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
467 const subsect_hdr = @ptrCast(*pdb.DebugSubsectionHeader, &subsect_info[sect_offset]);
468 skip_len = subsect_hdr.Length;
469 sect_offset += @sizeOf(pdb.DebugSubsectionHeader);
470
471 switch (subsect_hdr.Kind) {
472 pdb.DebugSubsectionKind.Lines => {
473 var line_index = sect_offset;
474
475 const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);
476 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
477 line_index += @sizeOf(pdb.LineFragmentHeader);
478 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
479 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
480
481 if (relocated_address >= frag_vaddr_start and relocated_address < frag_vaddr_end) {
482 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
483 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
484 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
485 const subsection_end_index = sect_offset + subsect_hdr.Length;
486
487 while (line_index < subsection_end_index) {
488 const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
489 line_index += @sizeOf(pdb.LineBlockFragmentHeader);
490 const start_line_index = line_index;
491
492 const has_column = line_hdr.Flags.LF_HaveColumns;
493
494 // All line entries are stored inside their line block by ascending start address.
495 // Heuristic: we want to find the last line entry
496 // that has a vaddr_start <= relocated_address.
497 // This is done with a simple linear search.
498 var line_i: u32 = 0;
499 while (line_i < block_hdr.NumLines) : (line_i += 1) {
500 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
501 line_index += @sizeOf(pdb.LineNumberEntry);
502
503 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
504 if (relocated_address < vaddr_start) {
505 break;
506 }
507 }
508
509 // line_i == 0 would mean that no matching LineNumberEntry was found.
510 if (line_i > 0) {
511 const subsect_index = checksum_offset + block_hdr.NameIndex;
512 const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);
513 const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;
514 try module.pdb.string_table.seekTo(strtab_offset);
515 const source_file_name = try module.pdb.string_table.readNullTermString(allocator);
516
517 const line_entry_idx = line_i - 1;
518
519 const column = if (has_column) blk: {
520 const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
521 const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx;
522 const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]);
523 break :blk col_num_entry.StartColumn;
524 } else 0;
525
526 const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry);
527 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]);
528 const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
529
530 break :subsections LineInfo{
531 .allocator = allocator,
532 .file_name = source_file_name,
533 .line = flags.Start,
534 .column = column,
535 };
536 }
537 }
538
539 // Checking that we are not reading garbage after the (possibly) multiple block fragments.
540 if (line_index != subsection_end_index) {
541 return error.InvalidDebugInfo;
542 }
543 }
544 },
545 else => {},
546 }
547
548 if (sect_offset > subsect_info.len)
549 return error.InvalidDebugInfo;
550 } else {
551 break :subsections null;
552 }
553 };
554
555 try printLineInfo(
556 out_stream,
557 opt_line_info,
558 relocated_address,
559 symbol_name,
560 obj_basename,
561 tty_config,
562 printLineFromFileAnyOs,
563 );
564}
565
566393pub const TTY = struct {
567394 pub const Color = enum {
568395 Red,
......@@ -698,23 +525,32 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
698525 return null;
699526}
700527
701pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
528/// TODO resources https://github.com/ziglang/zig/issues/4353
529pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
702530 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
703531 error.MissingDebugInfo, error.InvalidDebugInfo => {
704 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
532 return printLineInfo(
533 out_stream,
534 null,
535 address,
536 "???",
537 "???",
538 tty_config,
539 printLineFromFileAnyOs,
540 );
705541 },
706542 else => return err,
707543 };
708544
709 const info = try module.getSymbolAtAddress(address);
710 defer info.deinit();
545 const symbol_info = try module.getSymbolAtAddress(address);
546 defer symbol_info.deinit();
711547
712548 return printLineInfo(
713549 out_stream,
714 info.line_info,
550 symbol_info.line_info,
715551 address,
716 info.symbol_name,
717 info.compile_unit_name,
552 symbol_info.symbol_name,
553 symbol_info.compile_unit_name,
718554 tty_config,
719555 printLineFromFileAnyOs,
720556 );
......@@ -972,7 +808,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {
972808
973809/// TODO resources https://github.com/ziglang/zig/issues/4353
974810pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo {
975 const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo;
811 const mapped_mem = try mapWholeFile(elf_file_path);
976812
977813 var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);
978814 var efile = try elf.Elf.openStream(
......@@ -1015,7 +851,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !M
1015851
1016852/// TODO resources https://github.com/ziglang/zig/issues/4353
1017853fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ModuleDebugInfo {
1018 const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo;
854 const mapped_mem = try mapWholeFile(macho_file_path);
1019855
1020856 const hdr = @ptrCast(
1021857 *const macho.mach_header_64,
......@@ -1228,12 +1064,15 @@ pub const DebugInfo = struct {
12281064 const obj_di = try self.allocator.create(ModuleDebugInfo);
12291065 errdefer self.allocator.destroy(obj_di);
12301066
1231 try self.address_map.putNoClobber(base_address, obj_di);
1232
12331067 const macho_path = mem.toSliceConst(u8, std.c._dyld_get_image_name(i));
1234 obj_di.* = try openMachODebugInfo(self.allocator, macho_path);
1068 obj_di.* = openMachODebugInfo(self.allocator, macho_path) catch |err| switch (err) {
1069 error.FileNotFound => return error.MissingDebugInfo,
1070 else => return err,
1071 };
12351072 obj_di.base_address = base_address;
12361073
1074 try self.address_map.putNoClobber(base_address, obj_di);
1075
12371076 return obj_di;
12381077 }
12391078 }
......@@ -1307,11 +1146,14 @@ pub const DebugInfo = struct {
13071146 const obj_di = try self.allocator.create(ModuleDebugInfo);
13081147 errdefer self.allocator.destroy(obj_di);
13091148
1310 try self.address_map.putNoClobber(seg_start, obj_di);
1311
1312 obj_di.* = try openCoffDebugInfo(self.allocator, name_buffer[0..:0]);
1149 obj_di.* = openCoffDebugInfo(self.allocator, name_buffer[0..:0]) catch |err| switch (err) {
1150 error.FileNotFound => return error.MissingDebugInfo,
1151 else => return err,
1152 };
13131153 obj_di.base_address = seg_start;
13141154
1155 try self.address_map.putNoClobber(seg_start, obj_di);
1156
13151157 return obj_di;
13161158 }
13171159 }
......@@ -1376,11 +1218,14 @@ pub const DebugInfo = struct {
13761218 const obj_di = try self.allocator.create(ModuleDebugInfo);
13771219 errdefer self.allocator.destroy(obj_di);
13781220
1379 try self.address_map.putNoClobber(ctx.base_address, obj_di);
1380
1381 obj_di.* = try openElfDebugInfo(self.allocator, elf_path);
1221 obj_di.* = openElfDebugInfo(self.allocator, elf_path) catch |err| switch (err) {
1222 error.FileNotFound => return error.MissingDebugInfo,
1223 else => return err,
1224 };
13821225 obj_di.base_address = ctx.base_address;
13831226
1227 try self.address_map.putNoClobber(ctx.base_address, obj_di);
1228
13841229 return obj_di;
13851230 }
13861231};
......@@ -1412,7 +1257,7 @@ pub const ModuleDebugInfo = switch (builtin.os) {
14121257 }
14131258
14141259 fn loadOFile(self: *@This(), o_file_path: []const u8) !DW.DwarfInfo {
1415 const mapped_mem = mapWholeFile(o_file_path) catch |_| return error.InvalidDebugInfo;
1260 const mapped_mem = try mapWholeFile(o_file_path);
14161261
14171262 const hdr = @ptrCast(
14181263 *const macho.mach_header_64,
lib/std/macho.zig+11
......@@ -24,6 +24,17 @@ pub const load_command = extern struct {
2424 cmdsize: u32,
2525};
2626
27pub const uuid_command = extern struct {
28 /// LC_UUID
29 cmd: u32,
30
31 /// sizeof(struct uuid_command)
32 cmdsize: u32,
33
34 /// the 128-bit uuid
35 uuid: [16]u8,
36};
37
2738/// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
2839/// "stab" style symbol table information as described in the header files
2940/// <nlist.h> and <stab.h>.