Files
2026-05-15 00:57:42 +02:00

40 lines
1.2 KiB
Python

from queue import Queue
from llvm import Module, Value
from striga import Semantics, Successor
from container import Container
def lift_bfs(
module: Module, container: Container, start: int, *, verbose=True
) -> Semantics:
sem = Semantics(module, verbose=verbose)
sem.begin(start)
queue: Queue[Successor] = Queue()
queue.put(Successor(0, sem.const64(start)))
# Keep destinations as LLVM Values instead of splitting constants into ints.
# This keeps the worklist uniform and matches later slicing/data-flow uses.
visited: set[Value] = set()
while not queue.empty():
src, dst = queue.get()
if not dst.is_constant:
if sem.verbose:
print(f"; non-constant branch destination: {hex(src)} -> {dst}")
continue
if dst in visited:
continue
visited.add(dst)
va = dst.const_zext_value
code = container.get_data(va, 15)
successors = sem.lift_bytes(va, code)
for successor in successors:
if successor.dst in visited:
continue
queue.put(successor)
sem.module.verify_or_raise()
return sem