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;
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;
......@@ -559,7 +560,7 @@ pub const TTY = struct {
559560
560561fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
561562 var min: usize = 0;
562 var max: usize = symbols.len;
563 var max: usize = symbols.len - 1;
563564 while (min < max) {
564565 const mid = min + (max - min) / 2;
565566 const curr = &symbols[mid];
......@@ -572,9 +573,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
572573 return curr;
573574 }
574575 }
576
577 const max_sym = &symbols[symbols.len - 1];
578 if (address >= max_sym.address())
579 return max_sym;
580
575581 return null;
576582}
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
578606/// TODO resources https://github.com/ziglang/zig/issues/4353
579607pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
580608 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {