diff --git a/Handle/BNBasicBlock.cs b/Handle/BNBasicBlock.cs index 3d2fa64..97a8ce4 100644 --- a/Handle/BNBasicBlock.cs +++ b/Handle/BNBasicBlock.cs @@ -802,7 +802,9 @@ ref length break; } - yield return new InstructionTextLine(tokens); + // Carry the instruction's start address on the line, mirroring Python's + // Function.instructions / BinaryView.instructions which yield (tokens, addr). + yield return new InstructionTextLine(tokens, address); address += length; } diff --git a/NavigationExtensions.cs b/NavigationExtensions.cs index ea5d8d1..563792e 100644 --- a/NavigationExtensions.cs +++ b/NavigationExtensions.cs @@ -529,8 +529,7 @@ private static void VerifyDerivedStringLayout() return null; } - // Match the requested platform (or the view default) first, then fall back to the - // first candidate, exactly as Python does. + // Match the requested platform (or the view default) first. Platform? resolved = platform; if (null == resolved) { @@ -545,7 +544,18 @@ private static void VerifyDerivedStringLayout() } } - return candidates[0]; + // Implicit-platform lookups fall back to the first candidate, exactly as Python does + // when plat is None (get_function_at falls back to funcs[0]). An explicit platform + // with no match returns null: Python's plat-is-not-None branch is a strict + // BNGetAnalysisFunction(view, plat, addr) lookup that returns None when no function on + // that platform sits at the address -- it must NOT silently return a different + // platform's function. + if (null == platform) + { + return candidates[0]; + } + + return null; } /// diff --git a/Struct/BNInstructionTextLine.cs b/Struct/BNInstructionTextLine.cs index 331e882..f959e6f 100644 --- a/Struct/BNInstructionTextLine.cs +++ b/Struct/BNInstructionTextLine.cs @@ -20,18 +20,30 @@ internal unsafe struct BNInstructionTextLine public ulong count; } - public sealed class InstructionTextLine + public sealed class InstructionTextLine { public InstructionTextToken[] Tokens { get; } = Array.Empty(); - - public InstructionTextLine() + + // The virtual address of the first byte of the instruction this line disassembles. Python's + // Function.instructions / BinaryView.instructions generators yield (tokens, addr) per + // instruction; this field carries that address so consumers do not lose it. It is 0 when the + // line was not produced by an address-walking generator (e.g. synthesized token lists). + public ulong Address { get; } = 0; + + public InstructionTextLine() { - + } - - public InstructionTextLine(InstructionTextToken[] tokens) + + public InstructionTextLine(InstructionTextToken[] tokens) { - this.Tokens = tokens; + this.Tokens = tokens; + } + + public InstructionTextLine(InstructionTextToken[] tokens, ulong address) + { + this.Tokens = tokens; + this.Address = address; } public override string ToString() @@ -42,7 +54,7 @@ public override string ToString() { builder.Append(token.Text); } - + return builder.ToString(); } }