Skip to content

Commit cb07678

Browse files
committed
pcode cace actually firing now
1 parent c4c0be2 commit cb07678

File tree

5 files changed

+82
-28
lines changed

5 files changed

+82
-28
lines changed

src/kdrag/contrib/pcode/__init__.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,23 @@ def getRegisterName(self) -> str:
106106
return f"Roff{self.offset:X}_size{self.size}"
107107

108108

109+
# Varnode by default has pointer identity. This makes dictionaries not work correctly.
110+
111+
pypcode.Varnode.__hash__ = lambda self: hash((self.space.name, self.offset, self.size))
112+
113+
114+
def varnode_eq(self: pypcode.Varnode, other) -> bool:
115+
return (
116+
isinstance(other, pypcode.Varnode)
117+
and self.space.name == other.space.name
118+
and self.offset == other.offset
119+
and self.size == other.size
120+
)
121+
122+
123+
pypcode.Varnode.__eq__ = varnode_eq
124+
125+
109126
class CachedArray(NamedTuple):
110127
"""
111128
CachedArray keeps some writes unapplied to the array.
@@ -163,28 +180,6 @@ def store(self, vnode: pypcode.Varnode, value: smt.BitVecRef) -> "CachedArray":
163180
assert all(own in cache for own in owner.values())
164181
return self._replace(data=data, cache=cache, owner=owner)
165182

166-
"""
167-
def flush(self, vnode) -> smt.ArrayRef:
168-
offset0 = vnode.offset
169-
data = self.data
170-
owner = self.owner
171-
cache = self.cache
172-
flushed = {}
173-
for i in range(vnode.size):
174-
offset = offset0 + 1
175-
vnode1 = owner.get(offset)
176-
if vnode1 is not None and vnode1 not in flushed:
177-
data = bv.store_concat(data, vnode1.offset, cache[vnode1])
178-
flushed.add(vnode1)
179-
return data
180-
181-
def flush_all(self) -> smt.ArrayRef: # to_expr
182-
data = self.data
183-
for vnode, value in self.cache.items():
184-
data = bv.store_concat(data, vnode.offset, value)
185-
return data
186-
"""
187-
188183
def read(self, vnode: pypcode.Varnode) -> smt.BitVecRef:
189184
if vnode in self.cache:
190185
return self.cache[vnode]

src/kdrag/contrib/pcode/asmspec.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def vc(self, ctx: pcode.BinaryContext) -> smt.BoolRef:
326326
if isinstance(self.assertion, OutOfGas):
327327
return smt.BoolVal(False)
328328
return smt.Implies(
329-
smt.And(*self.path_cond),
329+
smt.simplify(smt.And(*self.path_cond)),
330330
substitute_state(self.assertion.expr, ctx, self.memstate, self.ghost_env),
331331
)
332332

src/kdrag/printers/c.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,30 @@
99

1010

1111
def ctype_of_sort(s: smt.SortRef):
12+
"""
13+
>>> ctype_of_sort(smt.ArraySort(smt.BitVecSort(8), smt.BitVecSort(32), smt.BitVecSort(16)))
14+
'uint16_t**'
15+
"""
1216
if s == smt.BoolSort():
1317
return "bool"
14-
if isinstance(s, smt.BitVecSortRef):
18+
elif isinstance(s, smt.BitVecSortRef):
1519
if s.size() in [8, 16, 32, 64]:
1620
return f"uint{s.size()}_t"
1721
else:
1822
raise NotImplementedError("No support for arbitrary C int sizes", s.size())
23+
elif isinstance(s, smt.ArraySortRef):
24+
doms = smt.domains(s)
25+
assert all(
26+
isinstance(d, smt.BitVecSortRef) and d.size() in [8, 16, 32, 64]
27+
for d in doms
28+
)
29+
range_ = ctype_of_sort(s.range())
30+
return range_ + "*" * len(doms)
31+
# datatypes and enums
32+
# elif isinstance(s, smt.DatatypeSortRef):
33+
# if s.num_constructors() != 1:
34+
# raise NotImplementedError("No support for multi-constructor datatypes", s)
35+
1936
else:
2037
raise NotImplementedError(f"Cannot convert {s} to C type")
2138

@@ -100,6 +117,12 @@ def is_valid_c_identifier_strict(identifier: str) -> bool:
100117
def c_of_expr(
101118
ctx: list[smt.ExprRef], sig: list[smt.FuncDeclRef], e: smt.ExprRef
102119
) -> str:
120+
"""
121+
>>> x,y = smt.BitVecs("x y", 32)
122+
>>> mem = smt.Array("mem", smt.BitVecSort(32), smt.BitVecSort(8))
123+
>>> c_of_expr([x,y,mem], [], mem[x + y])
124+
'(mem[(x + y)])'
125+
"""
103126
ctype_of_sort(e.sort()) # check sort is supported
104127
if any(e.eq(c) for c in ctx):
105128
assert is_valid_c_identifier_strict(e.decl().name())
@@ -115,6 +138,11 @@ def c_of_expr(
115138
return f"""{e.decl().name()}({", ".join(children)})"""
116139
elif smt.is_if(e):
117140
return f"({children[0]} ? {children[1]} : {children[2]})"
141+
elif smt.is_select(e):
142+
assert nargs == 2
143+
return f"({children[0]}[{children[1]}])"
144+
elif smt.is_store(e):
145+
raise NotImplementedError("Store expressions not supported in C codegen", e)
118146
elif isinstance(e, smt.BoolRef):
119147
if smt.is_true(e):
120148
return "true"
@@ -175,7 +203,7 @@ def cstring(name, args, body):
175203
return f"""\
176204
#include <stdint.h>
177205
#include <stdbool.h>
178-
{ctype_of_sort(body.sort())} {name}({', '.join([f"{ctype_of_sort(arg.sort())} {arg.decl().name()}" for arg in args])}){{
206+
{ctype_of_sort(body.sort())} {name}({", ".join([f"{ctype_of_sort(arg.sort())} {arg.decl().name()}" for arg in args])}){{
179207
return {c_of_expr(args, [decl], body)};
180208
}}
181209
"""
@@ -225,7 +253,7 @@ def compile_c(c_code, opts=[]):
225253
def link(name, args, body, filename):
226254
ffi = cffi.FFI()
227255
ffi.cdef(f"""\
228-
{ctype_of_sort(body.sort())} {name}({', '.join([f"{ctype_of_sort(arg.sort())}" for arg in args])});
256+
{ctype_of_sort(body.sort())} {name}({", ".join([f"{ctype_of_sort(arg.sort())}" for arg in args])});
229257
""")
230258
lib = ffi.dlopen(filename)
231259
return lib

src/kdrag/solvers/__init__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,34 @@ def check(self):
454454
return self.check_tptp_status(self.res.stdout)
455455

456456

457+
"""
458+
class EProverSolver(BaseSolver):
459+
def __init__(self):
460+
new = download(
461+
"https://github.com/philzook58/eprover/releases/download/E.3.2.5-ho/eprover-ho",
462+
"eprover-ho",
463+
"56a1dd51be0ba3194851cfb6f4ecc563c82cd5e2f5009dd1a7268af91150c9cd",
464+
)
465+
super().__init__()
466+
self.options["format"] = "tff"
467+
468+
def check(self):
469+
filename = "/tmp/eprover.p"
470+
self.write_tptp(filename, format=self.options["format"])
471+
cmd = [
472+
binpath("eprover-ho"),
473+
"--auto-schedule=8",
474+
filename,
475+
]
476+
if "timeout" in self.options:
477+
cmd.extend(["--cpu-limit=" + str(self.options["timeout"] // 1000 + 1)])
478+
self.res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
479+
if len(self.res.stderr) > 0:
480+
raise Exception("Eprover error", self.res.stderr)
481+
return self.check_tptp_status(self.res.stdout)
482+
"""
483+
484+
457485
class EProverTHFSolver(BaseSolver):
458486
def check(self):
459487
filename = "/tmp/eprover.p"

src/kdrag/tactics.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,13 @@ def __repr__(self):
357357
return "Nothing to do!"
358358
ctxrepr = pprint.pformat(self.ctx)
359359
goalrepr = repr(self.goal)
360-
if len(ctxrepr) + len(goalrepr) <= 75:
360+
totlen = len(ctxrepr) + len(goalrepr)
361+
if totlen <= 75:
361362
goalctx = ctxrepr + " ?|= " + repr(self.goal)
362-
else:
363+
elif totlen <= 1000:
363364
goalctx = ctxrepr + "\n?|= " + repr(self.goal)
365+
else:
366+
return "?|= " + self.to_expr().sexpr()
364367
if len(self.sig) == 0:
365368
return goalctx
366369
else:

0 commit comments

Comments
 (0)