angr.utils.ail

angr.utils.ail.dirty_has_side_effects(expr)

A dirty helper lifted from a VEX Dirty statement (mfx is set) may write memory or guest state (FLDENV, FSTENV, …) or observe the outside world (IN, RDTSC): it must survive even when its result is dead, and must neither be duplicated nor moved. Placeholders for unsupported operations and the 80-bit load are pure.

Return type:

bool

Parameters:

expr (DirtyExpression)

angr.utils.ail.is_phi_assignment(stmt)
Return type:

bool

Parameters:

stmt (Statement)

angr.utils.ail.is_scalar_int_convert(expr)

True for a plain integer width conversion: not lane-wise (vector_count is None) and neither side is floating point. Only these converts admit the usual integer rewrites (folding cascaded conversions, masking, etc.).

Return type:

bool

Parameters:

expr (Convert)

class angr.utils.ail.HasExprWalker

Bases: AILBlockViewer

Test if any expressions in exprs_to_check is used in another AIL expression.

__init__(exprs_to_check)
Parameters:

exprs_to_check (set[Expression])

Return type:

None

angr.utils.ail.is_head_controlled_loop_block(block)

Determine if the block is a “head-controlled loop.” A head-controlled loop (for the lack of a better term) is a single-block that contains a conditional jump towards the beginning of the block. This conditional jump controls whether the loop body (the remaining statements after the conditional jump) will be executed or not. It is usually the result of lifting rep stosX instructions on x86 and amd64.

A head-controlled loop block looks like the following (lifted from rep stosq qword ptr [rdi], rax):

## Block 4036df 00 | 0x4036df | LABEL_4036df: 01 | 0x4036df | vvar_27{reg 72} = 𝜙@64b [] 02 | 0x4036df | vvar_28{reg 24} = 𝜙@64b [] 03 | 0x4036df | t1 = rcx<8> 04 | 0x4036df | t4 = (t1 == 0x0<64>) 05 | 0x4036df | if (t4) { Goto 0x4036e2<64> } else { Goto 0x4036df<64> } 06 | 0x4036df | t5 = (t1 - 0x1<64>) 07 | 0x4036df | rcx<8> = t5 08 | 0x4036df | t7 = d<8> 09 | 0x4036df | t6 = (t7 << 0x3<8>) 10 | 0x4036df | t2 = rax<8> 11 | 0x4036df | t3 = rdi<8> 12 | 0x4036df | STORE(addr=t3, data=t2, size=8, endness=Iend_LE, guard=None) 13 | 0x4036df | t8 = (t3 + t6) 14 | 0x4036df | rdi<8> = t8

Where statement 5 is the conditional jump that controls the execution of the remaining statements of this block.

Parameters:

block (Block) – An AIL block.

Return type:

bool

Returns:

True if the block represents a head-controlled loop block, False otherwise.

angr.utils.ail.is_head_controlled_loop_jump(block, stmt)

Determine if a conditional jump in the middle of a block controls a head-controlled loop, i.e., it can leave the block. Jumps whose concrete targets all lie inside the block (e.g., libVEX alignment-check exits emitted for AArch64 ldar/stlr) cannot, and the SSA rewriting engine does not record a side-exit state for them.

Return type:

bool

Parameters:
angr.utils.ail.extract_partial_expr(base_expr, off, size, ail_manager, byte_width=8)
Return type:

Expression

Parameters:
angr.utils.ail.is_expr_used_as_reg_base_value(stmt, expr, srda)

Determine if the expression expr is used as the base value of an assignment of a full register in stmt.

This method returns True if the following conditions hold: - The statement is an assignment to a reg vvar A; - The src of the assignment statement is a bitwise-or expression; - One of the operands of the src expr is the high bits of expr; - expr is a phi var that relies on reg vvar A.

Return type:

bool

Parameters:
class angr.utils.ail.CallFinder

Bases: AILBlockViewer

Find the first Call statement or expression in a block.

__init__(include_macro=False)
angr.utils.ail.find_call(obj, include_macro=False)
Parameters:

obj (Block | Statement | Expression)

angr.utils.ail.has_call(obj, include_macro=False)
Parameters:

obj (Block | Statement | Expression)

angr.utils.ail.get_terminal_call(block)
Parameters:

block (Block)

angr.utils.ail.unwrap_stack_vvar_reference(expr)
Return type:

VirtualVariable | None

angr.utils.ail.unwrap_combo_reg_vvar_reference(expr)
Return type:

VirtualVariable | None

angr.utils.ail.deref_vvar_and_offset(expr)

If expr is a dereference of a VirtualVariable (possibly with an offset), return the VirtualVariable and offset. Otherwise, return (None, None).

Return type:

tuple[VirtualVariable, int] | tuple[None, None]

angr.utils.ail.extract_vvar_and_offset(expr)

If expr is a VirtualVariable (possibly with an offset), return the VirtualVariable and offset. Otherwise, return (None, None).

Return type:

tuple[VirtualVariable, int] | tuple[None, None]

angr.utils.ail.unwrap_stack_vvar_reference_with_offset(expr)
Return type:

tuple[VirtualVariable, int] | tuple[None, None]

class angr.utils.ail.CallVisitor

Bases: AILBlockViewer

Visit all Call statements and expressions in a graph, invoking a callback.

__init__(callback)
visit(graph)