mirror of
https://github.com/LLVMParty/striga
synced 2026-06-21 13:43:42 +00:00
40 lines
1.2 KiB
Python
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
|