Skip to content

Commit 23d148e

Browse files
schmeeandrewrk
authored andcommitted
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 parent eace690 commit 23d148e

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

lib/std/debug.zig

+29-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const io = std.io;
66
const os = std.os;
77
const fs = std.fs;
88
const process = std.process;
9+
const testing = std.testing;
910
const elf = std.elf;
1011
const DW = std.dwarf;
1112
const macho = std.macho;
@@ -559,7 +560,7 @@ pub const TTY = struct {
559560

560561
fn 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

584+
test "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
579607
pub 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) {

0 commit comments

Comments
 (0)