Skip to content

Basic Block Detection #187

Closed
Closed
@ds5678

Description

@ds5678

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.
  • 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 and CallNoReturn.

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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions