authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-26 09:55:04-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-26 09:55:04-05:00
log3839ea89785856bbed0624a6a18eb6e5acfb46c3
tree5aadd86ef359eb847bf842f9594690737f0e67c4
parentd9fb6c20540300013dc67ec144b555b8ab649646
signature Commit is signed but in an unrecognized format.

fix debug info code not being freestanding compatible

in stack tracing code, the idea was to detect the tty settings at the top of the stack and pass the information down. somewhere along the way this got changed so that setTtyColor was assuming the global stderr_file was related to the output stream the stack trace was being printed to. now, tty_color is changed to tty_config, and it is an enum rather than a bool, telling how tty colors are expected to be handled. windows is still incorrectly looking at stderr_file.

1 files changed, 123 insertions(+), 107 deletions(-)

lib/std/debug.zig+123-107
......@@ -81,10 +81,20 @@ pub fn getSelfDebugInfo() !*DebugInfo {
8181 }
8282}
8383
84fn wantTtyColor() bool {
84fn detectTTYConfig() TTY.Config {
8585 var bytes: [128]u8 = undefined;
8686 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
87 return if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| true else |_| stderr_file.isTty();
87 if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| {
88 return .escape_codes;
89 } else |_| {
90 if (stderr_file.supportsAnsiEscapeCodes()) {
91 return .escape_codes;
92 } else if (builtin.os == .windows) {
93 return .windows_api;
94 } else {
95 return .no_color;
96 }
97 }
8898}
8999
90100/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
......@@ -99,7 +109,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
99109 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
100110 return;
101111 };
102 writeCurrentStackTrace(stderr, debug_info, wantTtyColor(), start_addr) catch |err| {
112 writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| {
103113 stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
104114 return;
105115 };
......@@ -118,16 +128,16 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
118128 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
119129 return;
120130 };
121 const tty_color = wantTtyColor();
122 printSourceAtAddress(debug_info, stderr, ip, tty_color) catch return;
131 const tty_config = detectTTYConfig();
132 printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return;
123133 const first_return_address = @intToPtr(*const usize, bp + @sizeOf(usize)).*;
124 printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_color) catch return;
134 printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_config) catch return;
125135 var it = StackIterator{
126136 .first_addr = null,
127137 .fp = bp,
128138 };
129139 while (it.next()) |return_address| {
130 printSourceAtAddress(debug_info, stderr, return_address - 1, tty_color) catch return;
140 printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return;
131141 }
132142}
133143
......@@ -191,7 +201,7 @@ pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
191201 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
192202 return;
193203 };
194 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, wantTtyColor()) catch |err| {
204 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| {
195205 stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
196206 return;
197207 };
......@@ -264,7 +274,7 @@ pub fn writeStackTrace(
264274 out_stream: var,
265275 allocator: *mem.Allocator,
266276 debug_info: *DebugInfo,
267 tty_color: bool,
277 tty_config: TTY.Config,
268278) !void {
269279 if (builtin.strip_debug_info) return error.MissingDebugInfo;
270280 var frame_index: usize = 0;
......@@ -275,7 +285,7 @@ pub fn writeStackTrace(
275285 frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
276286 }) {
277287 const return_address = stack_trace.instruction_addresses[frame_index];
278 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
288 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
279289 }
280290}
281291
......@@ -319,20 +329,25 @@ pub const StackIterator = struct {
319329 }
320330};
321331
322pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
332pub fn writeCurrentStackTrace(
333 out_stream: var,
334 debug_info: *DebugInfo,
335 tty_config: TTY.Config,
336 start_addr: ?usize,
337) !void {
323338 if (builtin.os == .windows) {
324 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr);
339 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
325340 }
326341 var it = StackIterator.init(start_addr);
327342 while (it.next()) |return_address| {
328 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
343 try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
329344 }
330345}
331346
332347pub fn writeCurrentStackTraceWindows(
333348 out_stream: var,
334349 debug_info: *DebugInfo,
335 tty_color: bool,
350 tty_config: TTY.Config,
336351 start_addr: ?usize,
337352) !void {
338353 var addr_buf: [1024]usize = undefined;
......@@ -345,23 +360,28 @@ pub fn writeCurrentStackTraceWindows(
345360 return;
346361 } else 0;
347362 for (addrs[start_i..]) |addr| {
348 try printSourceAtAddress(debug_info, out_stream, addr, tty_color);
363 try printSourceAtAddress(debug_info, out_stream, addr, tty_config);
349364 }
350365}
351366
352367/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
353368/// make this `noasync fn` and remove the individual noasync calls.
354pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
369pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
355370 if (builtin.os == .windows) {
356 return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_color);
371 return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
357372 }
358373 if (comptime std.Target.current.isDarwin()) {
359 return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color);
374 return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_config);
360375 }
361 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_color);
376 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
362377}
363378
364fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_address: usize, tty_color: bool) !void {
379fn printSourceAtAddressWindows(
380 di: *DebugInfo,
381 out_stream: var,
382 relocated_address: usize,
383 tty_config: TTY.Config,
384) !void {
365385 const allocator = getDebugInfoAllocator();
366386 const base_address = process.getBaseAddress();
367387 const relative_address = relocated_address - base_address;
......@@ -379,7 +399,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
379399 }
380400 } else {
381401 // we have no information to add to the address
382 return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_color, printLineFromFileAnyOs);
402 return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs);
383403 };
384404
385405 const mod = &di.modules[mod_index];
......@@ -507,84 +527,80 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
507527 relocated_address,
508528 symbol_name,
509529 obj_basename,
510 tty_color,
530 tty_config,
511531 printLineFromFileAnyOs,
512532 );
513533}
514534
515const TtyColor = enum {
516 Red,
517 Green,
518 Cyan,
519 White,
520 Dim,
521 Bold,
522 Reset,
523};
524
525/// TODO this is a special case hack right now. clean it up and maybe make it part of std.fmt
526fn setTtyColor(tty_color: TtyColor) void {
527 if (stderr_file.supportsAnsiEscapeCodes()) {
528 switch (tty_color) {
529 TtyColor.Red => {
530 stderr_file.write(RED) catch return;
531 },
532 TtyColor.Green => {
533 stderr_file.write(GREEN) catch return;
534 },
535 TtyColor.Cyan => {
536 stderr_file.write(CYAN) catch return;
537 },
538 TtyColor.White, TtyColor.Bold => {
539 stderr_file.write(WHITE) catch return;
540 },
541 TtyColor.Dim => {
542 stderr_file.write(DIM) catch return;
543 },
544 TtyColor.Reset => {
545 stderr_file.write(RESET) catch return;
546 },
547 }
548
549 return;
550 }
535pub const TTY = struct {
536 pub const Color = enum {
537 Red,
538 Green,
539 Cyan,
540 White,
541 Dim,
542 Bold,
543 Reset,
544 };
551545
552 if (builtin.os == .windows) {
553 const S = struct {
554 var attrs: windows.WORD = undefined;
555 var init_attrs = false;
556 };
557 if (!S.init_attrs) {
558 S.init_attrs = true;
559 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
560 // TODO handle error
561 _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
562 S.attrs = info.wAttributes;
563 }
546 pub const Config = enum {
547 no_color,
548 escape_codes,
549 // TODO give this a payload of file handle
550 windows_api,
551
552 fn setColor(conf: Config, out_stream: var, color: Color) void {
553 switch (conf) {
554 .no_color => return,
555 .escape_codes => switch (color) {
556 .Red => out_stream.write(RED) catch return,
557 .Green => out_stream.write(GREEN) catch return,
558 .Cyan => out_stream.write(CYAN) catch return,
559 .White, .Bold => out_stream.write(WHITE) catch return,
560 .Dim => out_stream.write(DIM) catch return,
561 .Reset => out_stream.write(RESET) catch return,
562 },
563 .windows_api => if (builtin.os == .windows) {
564 const S = struct {
565 var attrs: windows.WORD = undefined;
566 var init_attrs = false;
567 };
568 if (!S.init_attrs) {
569 S.init_attrs = true;
570 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
571 // TODO handle error
572 _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
573 S.attrs = info.wAttributes;
574 }
564575
565 // TODO handle errors
566 switch (tty_color) {
567 TtyColor.Red => {
568 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {};
569 },
570 TtyColor.Green => {
571 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {};
572 },
573 TtyColor.Cyan => {
574 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
575 },
576 TtyColor.White, TtyColor.Bold => {
577 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
578 },
579 TtyColor.Dim => {
580 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {};
581 },
582 TtyColor.Reset => {
583 _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {};
584 },
576 // TODO handle errors
577 switch (color) {
578 .Red => {
579 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {};
580 },
581 .Green => {
582 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {};
583 },
584 .Cyan => {
585 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
586 },
587 .White, .Bold => {
588 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
589 },
590 .Dim => {
591 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {};
592 },
593 .Reset => {
594 _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {};
595 },
596 }
597 } else {
598 unreachable;
599 },
600 }
585601 }
586 }
587}
602 };
603};
588604
589605fn populateModule(di: *DebugInfo, mod: *Module) !void {
590606 if (mod.populated)
......@@ -650,12 +666,12 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
650666 return null;
651667}
652668
653fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
669fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
654670 const base_addr = process.getBaseAddress();
655671 const adjusted_addr = 0x100000000 + (address - base_addr);
656672
657673 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
658 return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFileAnyOs);
674 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
659675 };
660676
661677 const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
......@@ -676,13 +692,13 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
676692 address,
677693 symbol_name,
678694 compile_unit_name,
679 tty_color,
695 tty_config,
680696 printLineFromFileAnyOs,
681697 );
682698}
683699
684pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
685 return debug_info.printSourceAtAddress(out_stream, address, tty_color, printLineFromFileAnyOs);
700pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
701 return debug_info.printSourceAtAddress(out_stream, address, tty_config, printLineFromFileAnyOs);
686702}
687703
688704fn printLineInfo(
......@@ -691,10 +707,10 @@ fn printLineInfo(
691707 address: usize,
692708 symbol_name: []const u8,
693709 compile_unit_name: []const u8,
694 tty_color: bool,
710 tty_config: TTY.Config,
695711 comptime printLineFromFile: var,
696712) !void {
697 if (tty_color) setTtyColor(.White);
713 tty_config.setColor(out_stream, .White);
698714
699715 if (line_info) |*li| {
700716 try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
......@@ -702,11 +718,11 @@ fn printLineInfo(
702718 try out_stream.print("???:?:?", .{});
703719 }
704720
705 if (tty_color) setTtyColor(.Reset);
721 tty_config.setColor(out_stream, .Reset);
706722 try out_stream.write(": ");
707 if (tty_color) setTtyColor(.Dim);
723 tty_config.setColor(out_stream, .Dim);
708724 try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
709 if (tty_color) setTtyColor(.Reset);
725 tty_config.setColor(out_stream, .Reset);
710726 try out_stream.write("\n");
711727
712728 // Show the matching source code line if possible
......@@ -717,9 +733,9 @@ fn printLineInfo(
717733 const space_needed = @intCast(usize, li.column - 1);
718734
719735 try out_stream.writeByteNTimes(' ', space_needed);
720 if (tty_color) setTtyColor(.Green);
736 tty_config.setColor(out_stream, .Green);
721737 try out_stream.write("^");
722 if (tty_color) setTtyColor(.Reset);
738 tty_config.setColor(out_stream, .Reset);
723739 }
724740 try out_stream.write("\n");
725741 } else |err| switch (err) {
......@@ -1167,11 +1183,11 @@ pub const DwarfInfo = struct {
11671183 self: *DwarfInfo,
11681184 out_stream: var,
11691185 address: usize,
1170 tty_color: bool,
1186 tty_config: TTY.Config,
11711187 comptime printLineFromFile: var,
11721188 ) !void {
11731189 const compile_unit = self.findCompileUnit(address) catch {
1174 return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFile);
1190 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFile);
11751191 };
11761192
11771193 const compile_unit_name = try compile_unit.die.getAttrString(self, DW.AT_name);
......@@ -1188,7 +1204,7 @@ pub const DwarfInfo = struct {
11881204 address,
11891205 symbol_name,
11901206 compile_unit_name,
1191 tty_color,
1207 tty_config,
11921208 printLineFromFile,
11931209 );
11941210 }