reprospect.tools.sass.controlflow module

class reprospect.tools.sass.controlflow.BasicBlock(instructions: tuple[Instruction, ...])View on GitHub

Bases: object

Basic block in the control flow graph.

A basic block is a maximal sequence of consecutive instructions with:

  • single entry point (first instruction)

  • single exit point (last instruction)

  • no control flow instruction except possibly at the end

__init__(instructions: tuple[Instruction, ...]) None
instructions: tuple[Instruction, ...]
class reprospect.tools.sass.controlflow.ControlFlowView on GitHub

Bases: object

Analyze SASS instructions from a reprospect.tools.sass.Decoder to construct a reprospect.tools.sass.controlflow.Graph.

BRANCHING: Final[Pattern[str]] = re.compile('(BPT|BRA|BREAK|BRX|BRXU|EXIT|JMP|JMX|JMXU|RET)')

Branching instructions that create a new basic block.

SYNCHRONIZATION: Final[Pattern[str]] = re.compile('(BSSY)')
classmethod add_control_flow_edges(cfg: Graph) NoneView on GitHub

Analyze control flow and add edges between blocks.

classmethod analyze(instructions: Sequence[Instruction]) GraphView on GitHub

Analyze instructions to discover blocks.

classmethod create_blocks(instructions: Sequence[Instruction], entry_points: set[int]) tuple[BasicBlock, ...]View on GitHub

Create basic blocks from entry point instructions.

Note

It discards blocks that are made of NOP instructions (as nvdisasm does).

classmethod find_entry_points(instructions: Sequence[Instruction]) set[int]View on GitHub

Identify entry point instructions (first instruction of each basic block).

Entry points are:

  1. The first instruction.

  2. Any target of a branching or synchronization.

  3. Any instruction immediately following a branching.

classmethod get_target(instruction: Instruction) int | NoneView on GitHub

Get the target of a branching instruction.

>>> from reprospect.tools.sass.controlflow import ControlFlow
>>> from reprospect.tools.sass.decode      import ControlCode, Instruction
>>> ControlFlow.get_target(instruction = Instruction(offset = '0160', instruction = f'@!P0 BRA {hex(400)}', hex = '0x0000000000088947', control = ControlCode.decode(code = '0x000fea0003800000')))
400
class reprospect.tools.sass.controlflow.Graph(blocks: list[~reprospect.tools.sass.controlflow.BasicBlock] = <factory>, edges: dict[~reprospect.tools.sass.controlflow.BasicBlock, set[~reprospect.tools.sass.controlflow.BasicBlock]] = <factory>)View on GitHub

Bases: object

Control Flow Graph (CFG) representation of SASS code.

Blocks are reprospect.tools.sass.controlflow.BasicBlock, edges represent control flow between blocks.

__init__(blocks: list[~reprospect.tools.sass.controlflow.BasicBlock] = <factory>, edges: dict[~reprospect.tools.sass.controlflow.BasicBlock, set[~reprospect.tools.sass.controlflow.BasicBlock]] = <factory>) None
add_block(block: BasicBlock) NoneView on GitHub
add_blocks(blocks: Iterable[BasicBlock]) NoneView on GitHub
add_edge(src: BasicBlock, dst: BasicBlock) NoneView on GitHub
blocks: list[BasicBlock]
edges: dict[BasicBlock, set[BasicBlock]]

Adjacency list of where control flow may go for each block.

to_mermaid(frontmatter: dict[str, Any] | None = None) strView on GitHub

Generate a Mermaid flowchart diagram.

References: