Closed
Description
Motivation
Separating the binary into basic blocks could improve analysis.
- Many native function starts can be identified with call instruction to their address.
- In particular, the function starts can be determined before
MethodAnalysisContext.RawBytes
is assigned. The increased number of known functions would improve the accuracy when determining the end point of the method.
- In particular, the function starts can be determined before
- Basic blocks are important for control flow analysis.
- The basic block detection can be done before ISIL conversion, which would allow the conversion process to use it for more accurate separation of
Jump
andCallNoReturn
.
Design Concept
/// <summary>
/// A <see href="https://en.wikipedia.org/wiki/Basic_block">Basic Block</see> of assembly instructions.
/// </summary>
/// <param name="Start">The address of the entry instruction.</param>
/// <param name="End">The address of the exit instruction.</param>
/// <param name="JumpTarget">The address being jumped to after exiting the block. This is 0 iff the block returns.</param>
/// <param name="ConditionalJump">If true, the exit jump is conditional and control might flow to the next block instead of <paramref name="JumpTarget"/>.</param>
public readonly record struct BasicBlock(ulong Start, ulong End, ulong JumpTarget, bool ConditionalJump)
{
/// <summary>
/// The length of this block in the address space.
/// </summary>
public ulong Length => End - Start + 1;
/// <summary>
/// Does this block end with a return instruction?
/// </summary>
public bool IsReturnBlock => JumpTarget == 0;
/// <summary>
/// Divide due to a jump into the middle of the block.
/// </summary>
/// <param name="innerJump">The jump target inside this block.</param>
/// <param name="lowerBlock">The resulting block that contains <see cref="Start"/>.</param>
/// <param name="upperBlock">The resulting block that contains <see cref="End"/>.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="innerJump"/> is not an inside address.</exception>
public void Divide(ulong innerJump, out BasicBlock lowerBlock, out BasicBlock upperBlock)
{
if (!IsInside(innerJump))
throw new ArgumentOutOfRangeException(nameof(innerJump), innerJump, null);
lowerBlock = new(Start, innerJump - 1, innerJump, false);
upperBlock = new(innerJump, End, JumpTarget, ConditionalJump);
}
/// <summary>
/// Is the address contained in this block and not <see cref="Start"/>?
/// </summary>
/// <param name="address"></param>
/// <returns>True if <paramref name="address"/> is any contained and not <see cref="Start"/>.</returns>
public bool IsInside(ulong address) => address > Start && address <= End;
/// <summary>
/// Is the address contained in this block?
/// </summary>
/// <param name="address"></param>
/// <returns>True if <paramref name="address"/> is within the bounds of this block.</returns>
public bool Contains(ulong address) => address >= Start && address <= End;
}