angr.analyses.decompiler.known_patterns¶
Known code patterns: context-aware, declarative descriptions of library/macro idioms that compilers inline, plus machinery (KnownPatternFinder) to find them in Clinic AIL graphs and outline them back into calls.
Each idiom is defined once as a KnownPatternTemplate that instantiates
itself into a concrete KnownPattern for the target’s
PatternContext (architecture / platform / C++ runtime), so a single
definition covers 32- and 64-bit, libstdc++ and MSVC, etc.
- class angr.analyses.decompiler.known_patterns.PITE
Bases:
PatternExprMatches an ITE (ternary) expression
cond ? iftrue : iffalse.Needed because ITERegionConverter (AFTER_GLOBAL_SIMPLIFICATION) collapses
if (c) x = a; else x = b;diamonds into a single ITE assignment before the KnownPatternOutliner runs, so a two-armed value-select idiom reaches the outliner as an expression, not as a PGraphPat region. (A triangle, with one arm empty as in the MSVC std::string::c_str SSO select, is not converted, which is why that idiom is still a PGraphPat.)- cond: PatternExpr
- iftrue: PatternExpr
- iffalse: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(cond, iftrue, iffalse, name=None)
- Parameters:
cond (PatternExpr)
iftrue (PatternExpr)
iffalse (PatternExpr)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.AllOf
Bases:
PatternGateOpens when every sub-gate opens.
- gates: tuple[PatternGate, ...]
- opens(gctx)
- Return type:
- Parameters:
gctx (GateContext)
- property requires_evidence: bool
Whether this gate can only be decided once the function’s matches are known. Such gates are evaluated a second time by the finder.
- property label: str
- __init__(gates=<factory>)
- Parameters:
gates (tuple[PatternGate, ...])
- Return type:
None
- class angr.analyses.decompiler.known_patterns.AnyOf
Bases:
PatternGateOpens when any sub-gate opens.
- gates: tuple[PatternGate, ...]
- opens(gctx)
- Return type:
- Parameters:
gctx (GateContext)
- property requires_evidence: bool
Whether this gate can only be decided once the function’s matches are known. Such gates are evaluated a second time by the finder.
- property label: str
- __init__(gates=<factory>)
- Parameters:
gates (tuple[PatternGate, ...])
- Return type:
None
- class angr.analyses.decompiler.known_patterns.CorroboratedBy
Bases:
PatternGateOpens in a function where at least one of
witnessesalready matched.Witnesses are given as template ``name``s or ``call_name``s; the finder puts both spellings of every established pattern into the evidence set.
- opens(gctx)
- Return type:
- Parameters:
gctx (GateContext)
- property requires_evidence: bool
Whether this gate can only be decided once the function’s matches are known. Such gates are evaluated a second time by the finder.
- property label: str
- class angr.analyses.decompiler.known_patterns.CppRef
Bases:
objectA reference to a C++ class type registered in the
cpp::stdSimTypeCollection, keyed by its unique (mangled-style) name.- unique_name: str
- class angr.analyses.decompiler.known_patterns.GateContext
Bases:
objectEverything a gate may look at.
- Variables:
ctx – The target’s
PatternContext(arch, platform, C++ runtime, and the binary-evidence facts).project – The Project, for gates that need to look past the context.
evidence – Names and call names of the patterns established in the function currently being matched: both the patterns that matched in the first stage and the known-pattern calls already present in the graph (outlined by an earlier round). Empty when gates are evaluated outside a function.
- ctx: PatternContext
- with_evidence(evidence)
- Return type:
- Parameters:
- __init__(ctx, project=None, evidence=frozenset({}))
- Parameters:
ctx (PatternContext)
project (Project | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.KnownPattern
Bases:
objectA known code idiom, described declaratively.
- Variables:
name – Identifier, e.g.
"std_string_length".display_name – Human-readable name, e.g.
"std::string::length".call_name – Target name of the synthesized Call.
pattern – The structural pattern to match.
params – Ordered parameters; their captures become the call arguments, in order.
returnty – Return type of the synthesized call.
returnty_factory – Optional callable building a call-site-specific return type from the values of the constant
extra_argscaptures (e.g. CONTAINING_RECORD returns a pointer to a record whose layout depends on the matched field offset). Falls back toreturntywhen it returns None or when the constant values are unavailable.extra_args – Names of (typically constant) captures appended to the call arguments after
params.arches – Allowed
archinfo.Arch.namevalues; None = any.platforms – Allowed OS names (
project.simos.name, lowercased); None = any.where – Optional cross-capture predicate evaluated on the bindings after a structural match.
collapse_capture – Optional capture name identifying the idiom that a match belongs to: within one function, matches binding it to the same virtual variable all describe one source-level idiom, and only the one with the largest
collapse_max_captureconstant is kept. The compiler folds CONTAINING_RECORD’s subtraction into every field displacement, so one source idiom otherwise emits a call per field, each naming a different (and mostly wrong) record base.collapse_max_capture – Capture whose constant value orders the collapsing; required when
collapse_captureis set.binary_guard – Optional predicate on the Project; the pattern is only used when it returns True (e.g. require C++ evidence for STL patterns to avoid false positives on plain C binaries).
default_enabled – Whether the pattern is used when the caller does not explicitly select patterns. Generic patterns prone to false positives should set this False.
- name: str
- display_name: str
- call_name: str
- pattern: PatternExpr | PatternStmt | PGraphPat
- params: tuple[PatternParam, ...]
- suppressed_by: tuple[str, str, str] | None = None¶
Drop a match of this pattern when a pattern whose name matches the regex matched on the same object:
(name regex, my capture, their capture). The two captures must bind.likes()-equal expressions. This is how a generic accessor yields to a specific one on the same base: a bareLoad(s + 8)is std::string::length on a string and _M_finish on a vector, and the vector’s other fields say which. Judged against every match of the suppressing family, selected or not, so it cannot interact with largest-match selection.
- claims_only: bool = False¶
Match only to claim a base for
suppressed_bypurposes; never outlined, never rewritten, never reported. For shapes that identify an object beyond doubt but are not worth naming: a vector’s capacity check says “this is a vector” and nothing a reader wants a call for.
- pure_calls: frozenset[str] = frozenset({})¶
Callees this pattern reads through
PCallResultwhose only effect is their result: once the pattern has consumed that result and nothing else does, the call goes too. Naming a callee in a pattern is already a claim about what it computes; this is the claim that it computes nothing else.__ctype_b_locreturns a table pointer, and a bare__ctype_b_loc();left behind afterisspace(c)is noise.
- const_args_of_call(call)
Recover the
extra_argsconstant values from a synthesized call’s trailing arguments. Returns None when the call does not carry them.
- prototype(arch, const_args=None)
Build the synthesized call’s prototype.
const_args(the values of the constantextra_argscaptures, seeconst_args_of_call()) enables call-site-specific return types viareturnty_factory. Returns None if any declared type fails to resolve.
- __init__(name, display_name, call_name, pattern, params, returnty=None, returnty_factory=None, extra_args=(), arches=None, platforms=None, where=None, collapse_capture=None, collapse_max_capture=None, binary_guard=None, default_enabled=True, suppressed_by=None, claims_only=False, pure_calls=frozenset({}))
- Parameters:
name (str)
display_name (str)
call_name (str)
pattern (PatternExpr | PatternStmt | PGraphPat)
params (tuple[PatternParam, ...])
returnty_factory (Callable[[Arch, dict[str, int]], SimType | None] | None)
where (Callable[[dict[str, Expression]], bool] | None)
collapse_capture (str | None)
collapse_max_capture (str | None)
default_enabled (bool)
claims_only (bool)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.KnownPatternFinder
Bases:
AnalysisFinds occurrences of KnownPatterns in a Clinic AIL graph.
The graph to match on is the final (SSA-form) Clinic graph, i.e.
decompiler.ail_graph/clinic.cc_graph. Matches are reported inself.matches;outline()turns a match into a synthesized call by invoking the Outliner analysis on a copy of the graph.- MAX_REMOTE_CHASE_DEPTH = 6¶
- __init__(func, ail_graph, patterns=None, chase_defs=True, chase_remote_defs=True, skip_conversions=True, vvar_id_start=48879, block_addr_start=2864381952, ail_manager=None, force_patterns=None)
patternsmay be pattern templates (KnownPatternTemplate) and/or already-concrete KnownPatterns; templates are instantiated for this binary’s PatternContext. When None, the registry is used, filtered down to the templates that are enabled for this target: default-on ones, ones named byforce_patterns, and ones whose gate opens (seegating).force_patternsis the user’s force-enable selection,"all"or an iterable of template names / call names, and is only consulted whenpatternsis None (an explicit pattern list is already a selection).
- matches: list[KnownPatternMatch]
- call_target_names(call)
Public face of
_resolve_call_target(), for the outliner’s clean-up of calls a pattern declared pure.
- apply_matches(matches, ail_graph)
Apply as many of
matchesas possible, batching where it matters.Applying one match at a time is fine until several of them interleave in one block, which is exactly what consecutive field swaps do:
- t1 = x->b; t2 = y->b; y->b = t1; x->b = t2;
^ the next field’s load sits in this one’s gap
Rewrite the first and the second’s statements have moved; rewrite it anyway and the third now has an opaque call sitting in its gap, which no disjointness test will let it move across. So the void statement-span matches of a block, which the finder has already checked do not conflict, are spliced in together, against the statement indices they were found at. Everything else keeps the one-at-a-time path.
Returns the new graph and the ids of the matches that were applied.
- Return type:
- Parameters:
matches (list[KnownPatternMatch])
ail_graph (DiGraph)
- outline(match, ail_graph=None)
Outline one match: split the anchor block so the matched span forms its own block, invoke the Outliner analysis on it, and rewrite the synthesized callsite into the pattern’s call. Operates on (and returns) a copy; neither
self._graphnorail_graphis mutated.- Return type:
- Parameters:
match (KnownPatternMatch)
ail_graph (DiGraph | None)
- MAX_LIFTED_EXPR_NODES = 8¶
Node budget for a lifted parameter expression; see _is_liftable.
- outline_at(location, pattern, ail_graph)
Find
patternatlocation((block_addr, block_idx)or(block_addr, block_idx, stmt_idx)) inail_graphand outline it.- Return type:
- Parameters:
- class angr.analyses.decompiler.known_patterns.KnownPatternMatch
Bases:
objectOne occurrence of a KnownPattern in an AIL graph.
For expression-level matches, the boundary is
consumed_stmt_idxs(statements wholly owned by the match, e.g. chased definitions) plusexpr_path(the location of the matched sub-expression inside the anchor statement). For statement-sequence matches,stmt_spanholds the ordered matched statement indices (the anchor is the first) andmatched_expris None.duplicated_stmt_idxsholds chased definitions that are copied into the outlined region instead of moved: the originals stay where they are (other code still uses them) and the copies make the pattern’s captured values the region’s live-ins. It is always disjoint fromconsumed_stmt_idxs.recomputed_defsdoes the same for definitions that live in another block (a CSE’d value, possibly reaching the anchor through a phi): the expression is pure, so the region recomputes it from the captured operands.- pattern: KnownPattern
- anchor_stmt_idx: int
- captures: dict[str, Expression]
- matched_expr: Expression | None
- recomputed_defs: tuple[tuple[int, Expression], ...] = ()¶
- __init__(pattern, block_loc, anchor_stmt_idx, expr_path, consumed_stmt_idxs, captures, matched_expr, duplicated_stmt_idxs=frozenset({}), recomputed_defs=(), base_aliases=(), stmt_span=None, block_map=None, consumed_by_block=None, frontier_locs=None)
- Parameters:
pattern (KnownPattern)
anchor_stmt_idx (int)
captures (dict[str, Expression])
matched_expr (Expression | None)
recomputed_defs (tuple[tuple[int, Expression], ...])
consumed_by_block (dict[tuple[int, int | None], frozenset[int]] | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.KnownPatternTemplate
Bases:
objectA context-aware pattern definition.
- Variables:
call_name – The synthesized call name (unique across templates).
build –
build(ctx) -> KnownPattern | None; emits the concrete pattern forctx(None if it cannot).arches – Allowed
Arch.namevalues; None = any.languages – Allowed languages ({“c”,”cpp”}); None = any.
runtimes – Allowed C++ runtimes ({“libstdcxx”,”msvc”}); None = any.
platforms – Allowed platforms ({“linux”,”windows”}); None = any.
default_enabled – Whether the template is used when the caller does not explicitly select patterns.
gate – Optional
PatternGatethat turns an opt-in template on for targets (or functions) where the evidence says the idiom is real; seegating. A gate can only open a template, never close a default-on one.
- call_name: str
- build: Callable[[PatternContext], KnownPattern | None]
- gate: PatternGate | None = None¶
- enabled_for(gate_ctx)
- Return type:
- Parameters:
gate_ctx (GateContext)
- applicable(ctx)
- Return type:
- Parameters:
ctx (PatternContext)
- instantiate(ctx)
The concrete pattern for
ctx, or None if this template does not apply there. Memoized: a KnownPattern is a frozen tree that depends on nothing but the context, and callers treat it read-only.- Return type:
- Parameters:
ctx (PatternContext)
- __init__(call_name, build, arches=None, languages=None, runtimes=None, platforms=None, default_enabled=False, name='', gate=None, _cache=<factory>)
- Parameters:
- Return type:
None
- class angr.analyses.decompiler.known_patterns.OutlineResult
Bases:
objectThe outcome of outlining one KnownPatternMatch.
- graph: DiGraph
- match: KnownPatternMatch
- call_stmt: Statement
- child_graph: DiGraph | None
- child_funcargs: list[VirtualVariable]
- __init__(graph, match, call_stmt, child_func, child_graph, child_funcargs)
- Parameters:
graph (DiGraph)
match (KnownPatternMatch)
call_stmt (Statement)
child_func (Function | None)
child_graph (DiGraph | None)
child_funcargs (list[VirtualVariable])
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PAny
Bases:
PatternExprMatches any expression.
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PAssign
Bases:
PatternStmtMatches an Assignment statement.
- dst: PatternExpr
- src: PatternExpr
- match(stmt, state, ctx)
- Return type:
- Parameters:
stmt (Statement)
state (MatchState)
ctx (MatchCtx)
- __init__(dst, src)
- Parameters:
dst (PatternExpr)
src (PatternExpr)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PBinOp
Bases:
PatternExprMatches a BinaryOp.
opmay be a single op string or a set of acceptable ops. Commutative ops try both operand orders unlesscommutativeis explicitly False.- operands: tuple[PatternExpr, PatternExpr]
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(op, operands, commutative=None, name=None)
- Parameters:
operands (tuple[PatternExpr, PatternExpr])
commutative (bool | None)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PBlockPat
Bases:
PatternNodeA labeled block of statements in a multi-block pattern graph. An empty
stmtssequence matches any block (structure alone identifies it).- label: str
- stmts: PStmtSeq
- class angr.analyses.decompiler.known_patterns.PCall
Bases:
PatternExprMatches a
Callwhose callee is one ofnames.The callee is what makes a pattern containing this node self-guarding: an idiom spelled around a named runtime function (
operator deletein the std::string destructor,__ctype_b_locinisspace) cannot be confused with arithmetic that happens to look alike, because no other code calls that function to do something else.namesis matched against every spelling the callee is known by (the raw symbol and its demangled form), so a pattern may name either. Prefer the mangled spelling: it is exact, while a demangled one carries the argument list and varies with the demangler.args=Noneleaves the arguments unconstrained; a tuple constrains them positionally, withNonein a slot meaning “any expression”.- args: tuple[PatternExpr | None, ...] | None = None¶
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(names, args=None, name=None)
- Parameters:
args (tuple[PatternExpr | None, ...] | None)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PCallResult
Bases:
PatternExprThe value a call to one of
namesreturned.A call’s result is rarely used where it is produced: the compiler assigns it to a register and reads that register, often in another block.
__ctype_b_loc()is called once per function and its table indexed at every predicate. So this node matches the virtual variable and looks up its definition read-only. Nothing is consumed, moved or recomputed; the call stays where the compiler put it.An inline
Callexpression is matched too, for the case where the value is used at its definition.- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PCallStmt
Bases:
PatternStmtMatches a statement whose effect is a call.
Ailment has no Call statement: a call whose result is discarded is a
SideEffectStatementwrapping the Call expression, and one whose result is kept is an ordinaryAssignment. Both spellings are the same idiom, so both match;dst, when given, also constrains the assigned destination, which requires the assignment form.- call: PCall
- dst: PatternExpr | None = None¶
- match(stmt, state, ctx)
- Return type:
- Parameters:
stmt (Statement)
state (MatchState)
ctx (MatchCtx)
- __init__(call, dst=None)
- Parameters:
call (PCall)
dst (PatternExpr | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PChoice
Bases:
PatternExprOrdered alternation: matches the first alternative that succeeds.
- alternatives: tuple[PatternExpr, ...]
- __init__(*alternatives)
- Parameters:
alternatives (PatternExpr)
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PCondJump
Bases:
PatternStmtMatches a ConditionalJump, matching its condition expression.
- condition: PatternExpr
- match(stmt, state, ctx)
- Return type:
- Parameters:
stmt (Statement)
state (MatchState)
ctx (MatchCtx)
- __init__(condition)
- Parameters:
condition (PatternExpr)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PConst
Bases:
PatternExprMatches a Const, by exact value or by predicate. Width is ignored unless
bitsis given (e.g. shift amounts are often 8-bit).- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PConv
Bases:
PatternExprMatches a Convert explicitly (never skipped).
- operand: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(operand, from_bits=None, to_bits=None, name=None)
- Parameters:
operand (PatternExpr)
from_bits (int | None)
to_bits (int | None)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PDefOf
Bases:
PatternExprinner, or a virtual variable whose reaching definition isinner.The compiler is free to compute a value once and use it twice, and it does so exactly where an idiom uses one value twice.
if (_M_p != &_M_local_buf) operator delete(_M_p, ...)reads _M_p in the compare and in the call, so gcc loads it into a register and the pattern seesLoad(s)in neither place; it sees the same virtual variable in both.Reading that variable’s definition is read-only. Nothing is consumed, moved or recomputed, and the identification stays accurate even if memory changes afterwards: the variable holds what the load produced at the definition, which is what the idiom meant. That is why this is not
peek_fn, whose contract (“can be recomputed at the use”) a load cannot satisfy.The unconsumed definition is left where it was, so a region that matches through this node keeps it as residue. That is harmless, and dead-code elimination removes it once the idiom’s other uses are gone.
- inner: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(inner, name=None)
- Parameters:
inner (PatternExpr)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PExtract
Bases:
PatternExprMatches an
Extract, a bit-slice of a wider value.This is how a scalar reaches integer code out of a vector register when the 128-bit op did not get narrowed away:
movq %xmm2,%raxon a value that came frommaxsd/mulsdlifts toExtract(vvar_128, 64bits@0)rather than to a Convert. Without a node for it, every libm bit-twiddle whose operand is a computed double rather than an incoming argument is unmatchable.bits/offsetdefault to unconstrained;offsetis in bits.- operand: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(operand, bits=None, offset=None, name=None)
- Parameters:
operand (PatternExpr)
bits (int | None)
offset (int | None)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PField
Bases:
PatternExprThe address of the field at
offsetinside the object bound tobase.Spelling a container’s fields as
PLoad(PVVar("v"))/PLoad(PVVar("v") + 8)requires the object to sit at the very address held in a virtual variable. That is the minority case: measured over the benchmark corpus, only 10-25% of the DWARF sites for astd::vectoraccessor read the container through a bare pointer; the rest reach it as a field of something else (this->tokens.size()), which lifts toLoad(this + 56)/Load(this + 64)and cannot bindvat all.PFieldmatches such an address and bindsbaseto the object’s own address:rootwhen the object is at offset 0, elseroot + K. Two fields of one object therefore unify onK, which is what keeps the node honest: it replaces the constraint “this displacement is exactly 8” with “these two displacements differ by exactly 8”.Only use it in patterns that reference at least two fields. With a single field there is no second displacement to constrain, so
PLoad(PField("s", 8))degenerates into “any load through a pointer plus a non-negative constant” and matches essentially everything.rootmust be a virtual variable: the outliner materializestmp = root + Kahead of the region so the synthesized call still takes a variable.- base: str
- offset: int
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PGraphPat
Bases:
PatternNodeA multi-block pattern: labeled blocks connected by edges.
blocksmaps a label to itsPBlockPat.edgesare(src_label, dst_label)pairs; a destination label that does not appear inblocksdenotes an external successor, a region exit that becomes the Outliner frontier.entryis the label of the single entry block. Captures unify across all blocks (one bindings environment).- entry: str
- class angr.analyses.decompiler.known_patterns.PLoad
Bases:
PatternExprMatches a memory Load.
sizeis in bytes.- addr: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(addr, size=None, name=None)
- Parameters:
addr (PatternExpr)
size (int | None)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PPhi
Bases:
PatternExprMatches a Phi expression, capturing it whole (its individual sources are not matched). Useful for loop-header blocks, whose statements are phi assignments.
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PStackField
Bases:
PatternExprA field of a container that lives on the stack.
A stack object never reaches the matcher as an object at all: variable recovery has already split it into one virtual variable per slot, so
std::string s;is a handful of independentvvar{s-112},vvar{s-96}and there is noLoad(s)to match and nos + 16to compare against. Measured over the benchmark corpus (kp-eval/stack_share.py), stack objects are 40-54% of the DWARF sites forstd::string::lengthand 15-35% forstd::vector<T>::size.This node matches the slot of the field at
offsetand bindsbaseto the object’s own stack offset, so two fields of one object unify on it exactly asPField’s two displacements do.as_addressmatches the address form (&slot, which lifts toUnaryOp("Reference", vvar)) rather than the value form;std::string::capacityneeds both, since it compares the data pointer against the address of the local buffer.The binding is a
StackBaseOffset, the object’s own address. That is both the thing two fields must agree on and, directly, the argument the synthesized call takes, so nothing has to be materialized for it.Matching is only half the problem, and the other half is why a pattern using this node is never outlined: the region for a stack container reads N independent slots, so its live-ins are N values rather than one pointer and there is nothing for a synthesized callee to take. Such a match is instead rewritten in place: the matched expression, or the whole region, is replaced by
call(&s), whose argument the binding already is. SeeKnownPatternFinder._rewrite_in_placeand_rewrite_graph_in_place.- base: str
- offset: int
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PStmtSeq
Bases:
PatternStmtMatches a group of statements within one block. When
ordered(the default), the statement patterns must match in order; withallow_gaps, unrelated statements may sit between the matched ones. Whenorderedis False, the statement patterns match statements of the block in any order (each pattern to a distinct statement), which suits idioms whose statement order the compiler chooses freely (e.g. list-link stores).- stmts: tuple[PatternStmt, ...]
- max_gap: int = 8¶
How many unmatched statements may sit between two matched ones. Without a bound the scan runs to the end of the block from every statement it could start at, quadratic per block per template, and finds nothing: an idiom’s statements are adjacent apart from what the scheduler interleaved, which is a handful of instructions rather than a basic block.
- __init__(stmts, allow_gaps=True, ordered=True, max_gap=8)
- Parameters:
stmts (tuple[PatternStmt, ...])
allow_gaps (bool)
ordered (bool)
max_gap (int)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PStore
Bases:
PatternStmtMatches a Store statement.
sizeis in bytes.- addr: PatternExpr
- value: PatternExpr
- match(stmt, state, ctx)
- Return type:
- Parameters:
stmt (Statement)
state (MatchState)
ctx (MatchCtx)
- __init__(addr, value, size=None)
- Parameters:
addr (PatternExpr)
value (PatternExpr)
size (int | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PUnaryOp
Bases:
PatternExprMatches a UnaryOp.
- operand: PatternExpr
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- __init__(op, operand, name=None)
- Parameters:
operand (PatternExpr)
name (str | None)
- Return type:
None
- class angr.analyses.decompiler.known_patterns.PVVar
Bases:
PatternExprMatches a VirtualVariable.
- match(expr, state, ctx)
- Return type:
- Parameters:
expr (Expression)
state (MatchState)
ctx (MatchCtx)
- class angr.analyses.decompiler.known_patterns.PatternContext
Bases:
objectTarget facts used to instantiate pattern templates.
The last two fields are binary evidence: facts about what kind of program this is, used by
gatingto switch whole pattern families on for targets where the idioms are certain to appear and off everywhere else.- arch_name: str
- bits: int
- ptr_size: int
- is_cpp: bool
- classmethod from_project(project)
- Return type:
- Parameters:
project (Project)
- property word_size: int
Load size (bytes) of a pointer / size_t field.
- property language: str
- __init__(arch_name, bits, ptr_size, platform, cxx_runtime, is_cpp, is_linux_kernel_object=False, is_windows_kernel_driver=False)
- class angr.analyses.decompiler.known_patterns.PatternGate
Bases:
objectBase class for template gates. Instances are callables so that a gate can be used anywhere a
Callable[[GateContext], bool]is expected.- opens(gctx)
- Return type:
- Parameters:
gctx (GateContext)
- property requires_evidence: bool
Whether this gate can only be decided once the function’s matches are known. Such gates are evaluated a second time by the finder.
- property label: str
- __init__()
- Return type:
None
- exception angr.analyses.decompiler.known_patterns.PatternGenerationError
Bases:
ExceptionRaised when a selection cannot be turned into a KnownPattern (ambiguous, unsupported, or inconsistent with the given arguments).
- class angr.analyses.decompiler.known_patterns.PatternGenerator
Bases:
objectGenerate a
KnownPatternfrom a text selection incodegen.text.- Parameters:
codegen – the
Decompiler.codegen(aCStructuredCodeGenerator).ail_graph (
DiGraph|None) – the graph the generated pattern will be matched against (Decompiler.ail_graph). Required for multi-block (control-flow-spanning) selections; optional otherwise.
- __init__(codegen, ail_graph=None)
- Parameters:
ail_graph (DiGraph | None)
- vvar_id_at(offset)
The AIL vvar id of the variable rendered at
offset, or None.
- offset_of(needle, start=0)
Convenience: the offset of
needlein the rendered text.
- generate(start_offset, end_offset, call_name, arg_offsets, *, name=None, display_name=None, returnty=None, param_types=None, const_arg_offsets=(), arches=None, platforms=None, binary_guard=None, default_enabled=False)
- class angr.analyses.decompiler.known_patterns.PatternParam
Bases:
objectOne parameter of the synthesized call.
- Variables:
capture – Name of the pattern capture bound to this parameter.
type – Argument type for the synthesized call’s prototype; flows into Typehoon as a per-argument subtype constraint.
type_hint – Optional cpp::std unique name emitted as a direct vvar type hint (for by-value captures where the vvar is the object rather than a pointer to it).
- capture: str
- class angr.analyses.decompiler.known_patterns.TargetGate
Bases:
PatternGateOpens when a predicate over the target’s
PatternContextholds.The predicate reads facts that were derived once from the loaded binary, so evaluating it is free and its result is the same for every function.
- name: str
- predicate: Callable[[PatternContext], bool]
- opens(gctx)
- Return type:
- Parameters:
gctx (GateContext)
- property label: str
- __init__(name, predicate)
- Parameters:
name (str)
predicate (Callable[[PatternContext], bool])
- Return type:
None
- exception angr.analyses.decompiler.known_patterns.UnknownPatternError
Bases:
ValueErrorRaised when a pattern selection names a template that is not registered.
- exception angr.analyses.decompiler.known_patterns.UnsupportedOutlineError
Bases:
ExceptionRaised when a match cannot be safely outlined (e.g. side-effecting statements interleave with the matched span, or the recovered callee interface does not agree with the pattern’s declared parameters).
- angr.analyses.decompiler.known_patterns.all_of(*gates)
- Return type:
- Parameters:
gates (PatternGate)
- angr.analyses.decompiler.known_patterns.any_of(*gates)
- Return type:
- Parameters:
gates (PatternGate)
- angr.analyses.decompiler.known_patterns.corroborated_by(*witnesses)
A gate that opens in a function where one of
witnessesmatched.- Return type:
- Parameters:
witnesses (str)
- angr.analyses.decompiler.known_patterns.exact_div_magic(elt_size, bits)
(shift, magic)of the exact-division-by-elt_sizeidiom.
- angr.analyses.decompiler.known_patterns.make_std_vector_size_exactdiv_template(elt_name, elt_size)
A non-power-of-two
std::vector<elt_name>::sizetemplate.
- angr.analyses.decompiler.known_patterns.make_std_vector_size_template(elt_name, log2_elt_size)
A power-of-two
std::vector<elt_name>::sizetemplate.
- angr.analyses.decompiler.known_patterns.make_template(call_name, build, *, arches=None, languages=None, runtimes=None, platforms=None, default_enabled=False, name='', gate=None)
- Return type:
- Parameters:
call_name (str)
build (Callable[[PatternContext], KnownPattern | None])
default_enabled (bool)
name (str)
gate (PatternGate | None)
- angr.analyses.decompiler.known_patterns.partition_templates(gate_ctx, forced=(), templates=None)
Split templates into
(enabled, deferred)for one target.enabledare the templates to match with right away: default-on ones, ones the caller force-enabled, and ones whose gate already opens on target evidence alone.deferredare the ones whose gate needs per-function evidence (seeCorroboratedBy) and must be re-evaluated by the finder once the first matching stage has run.- Return type:
tuple[list[KnownPatternTemplate],list[KnownPatternTemplate]]- Parameters:
gate_ctx (GateContext)
forced (Iterable[KnownPatternTemplate])
templates (Iterable[KnownPatternTemplate] | None)
- angr.analyses.decompiler.known_patterns.patterns_for(ctx, templates=None, *, enabled_only=False)
Instantiate the applicable templates for
ctxinto concrete KnownPatterns.templatesdefaults to the whole registry; withenabled_onlyonly default-enabled templates are used.- Return type:
- Parameters:
ctx (PatternContext)
templates (Iterable[KnownPatternTemplate] | None)
enabled_only (bool)
- angr.analyses.decompiler.known_patterns.register_pattern_template(template)
Register a KnownPatternTemplate. Call names are unique across templates (the architecture / runtime conditionals live inside each template’s
build).- Return type:
- Parameters:
template (KnownPatternTemplate)
- angr.analyses.decompiler.known_patterns.resolve_pattern_selection(selection)
Resolve a user’s force-enable selection into templates.
selectionis one of:None/ empty: nothing is force-enabled (returns an empty list);"all": every registered template, opt-in ones included;an iterable of template ``name``s and/or ``call_name``s (a comma-separated string is accepted too, for the string-valued decompilation option).
An unrecognized name raises
UnknownPatternErrorrather than silently selecting nothing.- Return type:
- Parameters:
Submodules
Apply call-site information (prototypes) for known-pattern calls. |
|
Utilities for splitting an AIL block into consecutive blocks within a graph. |
|
The CONTAINING_RECORD macro (Windows drivers) / container_of (Linux kernel): |
|
PatternContext: the architecture / platform / language facts a KnownPattern template needs to instantiate itself for a given binary. |
|
The glibc ctype macros: isspace, isdigit, . |
|
Declarative pattern-AST for describing known AIL code idioms (KnownPatterns). |
|
KnownPatternFinder: find occurrences of KnownPatterns in a Clinic AIL graph and outline them into calls via the Outliner analysis. |
|
Criteria gates: per-target (and per-function) enablement for pattern templates. |
|
PatternGenerator: build a KnownPattern from a decompilation text selection. |
|
Linux kernel |
|
Runtime-specific struct layout offsets for the STL container patterns. |
|
libm floating-point bit-twiddling idioms (fabs / -x / copysign / isnan / isinf). |
|
Doubly-linked-list idioms shared by Windows |
|
KnownPattern: declarative metadata around a pattern-AST. |
|
Single-expression glibc/POSIX macros that the preprocessor inlines into every caller, so they survive into decompiled output as bare bit arithmetic. |
|
protobuf has-bits accessors (protoc output for optional fields): |
|
The template registry: every |
|
Inlined MSVC |
|
The inlined |
|
libstdc++ std::string internals that are not accessors: the SSO test and the two length-setting idioms. |
|
Inlined std::string::length() / size() and empty(). |
|
Inlined |
|
Inlined std::vector<T>::size() and capacity(). |
|
C++ STL accessors, round two: std::string capacity/back/front and std::vector<T>::back(). |
|
C++ STL std::vector accessors beyond size()/capacity(): empty / operator[]. |
|
KnownPatternTemplate: a single, context-parameterized definition of an idiom that instantiates itself into a concrete |
|
Claims-only std::vector fingerprints: shapes that identify a vector beyond doubt but are not worth a call of their own. |
|
3-component float vector math (glm / DirectXMath / game-graphics code). |
|
Reads of |