Skip to content

derive and expose address keyed NZCV flag liveness - #289

Open
leftbyte wants to merge 6 commits into
static-analysis-engineering:masterfrom
leftbyte:dphung/pir-req2-flag-liveness
Open

derive and expose address keyed NZCV flag liveness#289
leftbyte wants to merge 6 commits into
static-analysis-engineering:masterfrom
leftbyte:dphung/pir-req2-flag-liveness

Conversation

@leftbyte

@leftbyte leftbyte commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

CodeHawk records per-instruction flag-reaching-def facts but exposes no liveness. This PR derives NZCV flag live-in/live-out for each instruction address and attaches it to the function's provenance, so a consumer can tell whether a flag set by a compare is still needed past a given point.

This metadata is used by the the patcher's predicated-if in-place patching mechanism as a safety check to confirm NZCV are dead at the region exit before replacing a compare.

@leftbyte
leftbyte force-pushed the dphung/pir-req2-flag-liveness branch from 2f0d5b2 to c6c3bb1 Compare August 7, 2026 04:52
@leftbyte leftbyte changed the title derive and expose address-keyed NZCV flag-liveness WIP: derive and expose address-keyed NZCV flag-liveness Aug 7, 2026
@leftbyte leftbyte changed the title WIP: derive and expose address-keyed NZCV flag-liveness SKETCH: derive and expose address-keyed NZCV flag-liveness Aug 7, 2026
@leftbyte leftbyte changed the title SKETCH: derive and expose address-keyed NZCV flag-liveness WIP: derive and expose address-keyed NZCV flag-liveness Aug 7, 2026
@leftbyte leftbyte changed the title WIP: derive and expose address-keyed NZCV flag-liveness WIP: derive and expose address keyed NZCV flag liveness Aug 11, 2026
@leftbyte leftbyte changed the title WIP: derive and expose address keyed NZCV flag liveness derive and expose address keyed NZCV flag liveness Aug 18, 2026

@waskyo waskyo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First pass. I'd like to do a second pass looking at the algo but ran out of time today for that.

Comment thread chb/ast/ASTProvenance.py Outdated
Comment thread chb/astinterface/ASTILiveness.py Outdated
Comment thread chb/astinterface/ASTInterfaceFunction.py Outdated
Comment thread chb/astinterface/ASTILiveness.py Outdated
Sequence[Optional[Union["FlagReachingDefFact",
"ReachingDefFact"]]]],
names: Optional[Set[str]] = None
) -> Tuple[Dict[str, Set[str]], Dict[str, Set[str]]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This style seems wrong, should follow what CHB already does.

(fwiw, I didn't review the rest of the code for similar issues)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...fixed? I think you're referring to that weird indentation.


def _use_kill(
self,
get_facts: Callable[

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have the docstring document what this is passed and what it is supposed to generate

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

if fact is None:
continue
name = str(fact.variable)
if name == "PC":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you document that PC is always ignored (I think?) in the docstring as part of the names documentation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread chb/astinterface/ASTILiveness.py Outdated
use[iaddr].add(name)
for d in fact.deflocations:
da = str(d)
if da == "init" or da.startswith("F"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this check translate to? Maybe you could add a small inline function that does this check and has a docstring explaining it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added inline function with some docstring.

Comment thread chb/astinterface/ASTILiveness.py Outdated
Comment thread chb/astinterface/ASTILiveness.py Outdated
"""Block address -> its instruction addresses in execution order.

Sorted lexicographically, matching how BasicBlock orders its own
instructions. A numeric (int, 16) key would raise on the analysis's

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't figure out what this sentence means:

A numeric (int, 16) key would raise on the analysis's inlined-instruction addresses (e.g. "F:0x...._0x....").

Is it explaining something about what the function is doing or how it's generating the return value?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated comment to hopefully make it clearer.

result[ia] = {"live-in": lin, "live-out": lout}
return result

def _backward(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you haven't already, it would be good to check with Henny if CHB doesn't already have code to do this traversal (same for the _blocks and _edges functions).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_edges has an equivalent so that's fixed but the other functionality does not.

Dan Phung added 3 commits August 21, 2026 10:57
Add ASTILiveness, which computes NZCV flag live-in/live-out per
instruction address for a function by building per-address use/kill sets
from the per-instruction flag-reaching-def facts and running a backward
live-variable fixpoint over the CFG.

Block instructions are ordered with the same lexicographic sort BasicBlock
uses, which also tolerates the analysis's inlined-instruction addresses.
Add a flag-liveness map (keyed by instruction address) to ASTProvenance
with the standard getter/setter, and round-trip it through
serialize/deserialize alongside the other provenance facts.
Compute flag-liveness in mk_asts, alongside set_ast_provenance, so it
flows through the same builder path as the other provenance facts (rather
than only on the results-ast command path). The computation is auxiliary
and guarded so a failure cannot abort AST generation.
@leftbyte
leftbyte force-pushed the dphung/pir-req2-flag-liveness branch 2 times, most recently from 730154a to 9615655 Compare August 21, 2026 20:30
Dan Phung added 2 commits August 21, 2026 13:47
is_real_def_site excluded any "F"-prefixed def-site as "not a site in
this function's CFG", which was wrong. Those instructions execute and
define what they define, and their addresses are ordinary keys in
fn.blocks and fn.instructions. _use_kill was therefore recording uses at
those addresses while discarding their kills.
An "init" def-site means the value was defined on function entry rather
than by an instruction. For a registers that is ordinary and an incoming
parameter is defined exactly there. This is not normal for a flag
because the ABI leaves NZCV undefined on entry to a function.
@leftbyte
leftbyte force-pushed the dphung/pir-req2-flag-liveness branch from 9615655 to 0c1a707 Compare August 21, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants