authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-01-22 22:52:27+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-31 23:55:19+01:00
log8e497eb32c90fdb40ea31bc968b3f4de02f91c1b
tree65c7aeb03f3d39608f30901b4633162114ab3892
parent2913950ca9deea6cbbbfea6f4592db366961c428

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;
...@@ -568,7 +569,7 @@ pub const TTY = struct {...@@ -568,7 +569,7 @@ pub const TTY = struct {
568569
569fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {570fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
570 var min: usize = 0;571 var min: usize = 0;
571 var max: usize = symbols.len;572 var max: usize = symbols.len - 1;
572 while (min < max) {573 while (min < max) {
573 const mid = min + (max - min) / 2;574 const mid = min + (max - min) / 2;
574 const curr = &symbols[mid];575 const curr = &symbols[mid];
...@@ -581,9 +582,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach...@@ -581,9 +582,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
581 return curr;582 return curr;
582 }583 }
583 }584 }
585
586 const max_sym = &symbols[symbols.len - 1];
587 if (address >= max_sym.address())
588 return max_sym;
589
584 return null;590 return null;
585}591}
586592
593test "machoSearchSymbols" {
594 const symbols = [_]MachoSymbol{
595 .{ .addr = 100, .strx = undefined, .size = undefined, .ofile = undefined },
596 .{ .addr = 200, .strx = undefined, .size = undefined, .ofile = undefined },
597 .{ .addr = 300, .strx = undefined, .size = undefined, .ofile = undefined },
598 };
599
600 try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 0));
601 try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 99));
602 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 100).?);
603 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 150).?);
604 try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 199).?);
605
606 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 200).?);
607 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 250).?);
608 try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 299).?);
609
610 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 300).?);
611 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 301).?);
612 try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?);
613}
614
587/// TODO resources https://github.com/ziglang/zig/issues/4353615/// TODO resources https://github.com/ziglang/zig/issues/4353
588pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {616pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
589 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {617 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {