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;
66const os = std.os;
77const fs = std.fs;
88const process = std.process;
9const testing = std.testing;
910const elf = std.elf;
1011const DW = std.dwarf;
1112const macho = std.macho;
......@@ -568,7 +569,7 @@ pub const TTY = struct {
568569
569570fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
570571 var min: usize = 0;
571 var max: usize = symbols.len;
572 var max: usize = symbols.len - 1;
572573 while (min < max) {
573574 const mid = min + (max - min) / 2;
574575 const curr = &symbols[mid];
......@@ -581,9 +582,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
581582 return curr;
582583 }
583584 }
585
586 const max_sym = &symbols[symbols.len - 1];
587 if (address >= max_sym.address())
588 return max_sym;
589
584590 return null;
585591}
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
587615/// TODO resources https://github.com/ziglang/zig/issues/4353
588616pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
589617 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {