authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-01-22 22:52:27+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-02 22:06:32-07:00
log23d148e5c7ab036ef686606f11a2343940890f5a
tree5b8c3d54cb44c0d691dcda5b9c1b5cbba2e17ed0
parenteace6906ce5c23bc78e6e68876a5ede984c21a72

debug: fix edge cases in macOS debug symbol lookup

This commit fixes two related things: 1. If the loop goes all the way through the slice without a match, on the last iteration `mid == symbols.len - 1` which causes `&symbols[mid + 1]` to be out of bounds. End one step before that instead. 2. If the address we're looking for is greater than the address of the last symbol in the slice, we now match it to that symbol. Previously, we would miss this case since we only matched if the address was _in between_ the address of two symbols.

1 files changed, 29 insertions(+), 1 deletions(-)

lib/std/debug.zig+29-1
...@@ -6,6 +6,7 @@ const io = std.io;...@@ -6,6 +6,7 @@ const io = std.io;
6const os = std.os;6const os = std.os;
7const fs = std.fs;7const fs = std.fs;
8const process = std.process;8const process = std.process;
9const testing = std.testing;
9const elf = std.elf;10const elf = std.elf;
10const DW = std.dwarf;11const DW = std.dwarf;
11const macho = std.macho;12const macho = std.macho;
...@@ -559,7 +560,7 @@ pub const TTY = struct {...@@ -559,7 +560,7 @@ pub const TTY = struct {
559560
560fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {561fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
561 var min: usize = 0;562 var min: usize = 0;
562 var max: usize = symbols.len;563 var max: usize = symbols.len - 1;
563 while (min < max) {564 while (min < max) {
564 const mid = min + (max - min) / 2;565 const mid = min + (max - min) / 2;
565 const curr = &symbols[mid];566 const curr = &symbols[mid];
...@@ -572,9 +573,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach...@@ -572,9 +573,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
572 return curr;573 return curr;
573 }574 }
574 }575 }
576
577 const max_sym = &symbols[symbols.len - 1];
578 if (address >= max_sym.address())
579 return max_sym;
580
575 return null;581 return null;
576}582}
577583
584test "machoSearchSymbols" {
585 const symbols = [_]MachoSymbol{
586 .{ .addr = 100, .strx = undefined, .size = undefined, .ofile = undefined },
587 .{ .addr = 200, .strx = undefined, .size = undefined, .ofile = undefined },
588 .{ .addr = 300, .strx = undefined, .size = undefined, .ofile = undefined },
589 };
590
591 try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 0));
592 try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 99));
593 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 100).?);
594 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 150).?);
595 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 199).?);
596
597 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 200).?);
598 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 250).?);
599 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 299).?);
600
601 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 300).?);
602 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 301).?);
603 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?);
604}
605
578/// TODO resources https://github.com/ziglang/zig/issues/4353606/// TODO resources https://github.com/ziglang/zig/issues/4353
579pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {607pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
580 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {608 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {