@@ -129,6 +129,7 @@ class AsmSpec:
129129
130130 """
131131
132+ ctx : pcode .BinaryContext
132133 addrmap : defaultdict [int , list [SpecStmt ]] = dataclasses .field (
133134 default_factory = lambda : defaultdict (list )
134135 )
@@ -151,6 +152,15 @@ def add_cut(self, label: str, addr: int, expr: pcode.StateProp):
151152 def add_assign (self , label : str , addr : int , name : str , expr : pcode .StateExpr ):
152153 self .addrmap [addr ].append (Assign (label , addr , name , expr ))
153154
155+ def find_label (self , label : str ) -> int :
156+ assert self .ctx .loader is not None , (
157+ "BinaryContext must be loaded before disassembling"
158+ )
159+ sym = self .ctx .loader .find_symbol (label )
160+ if sym is None :
161+ raise Exception (f"Symbol { label } not found in binary { self .ctx .filename } " )
162+ return sym .rebased_addr
163+
154164 @classmethod
155165 def of_file (cls , filename : str , ctx : pcode .BinaryContext ):
156166 COMMASEP = r"\s*(?:,\s*)?"
@@ -173,16 +183,7 @@ def of_file(cls, filename: str, ctx: pcode.BinaryContext):
173183 decls ["read" ] = smt .Array (
174184 "read" , smt .BitVecSort (ctx .bits ), smt .BoolSort ()
175185 ).decl ()
176- spec = cls ()
177-
178- def find_label (label : str ) -> int :
179- assert ctx .loader is not None , (
180- "BinaryContext must be loaded before disassembling"
181- )
182- sym = ctx .loader .find_symbol (label )
183- if sym is None :
184- raise Exception (f"Symbol { label } not found in binary { ctx .filename } " )
185- return sym .rebased_addr
186+ spec = cls (ctx )
186187
187188 def parse_smt (smt_bool : str , linemo : int , line : str ) -> smt .BoolRef :
188189 # parse with slightly nicer error throwing, saying which line in asm responsible
@@ -210,7 +211,7 @@ def parse_smt(smt_bool: str, linemo: int, line: str) -> smt.BoolRef:
210211 ): # A little bit of sanity checking that we don't miss any "kd_" line
211212 if match := boolstmt_pattern .match (line ):
212213 cmd , label , expr = match .groups ()
213- addr = find_label (label )
214+ addr = spec . find_label (label )
214215 smt_string = "\n " .join (preludes + ["(assert " , expr , ")" ])
215216 expr = parse_smt (smt_string , lineno , line )
216217 if cmd == "kd_entry" :
@@ -226,7 +227,7 @@ def parse_smt(smt_bool: str, linemo: int, line: str) -> smt.BoolRef:
226227 elif match := assign_pattern .match (line ):
227228 label , name , expr = match .groups ()
228229 # Turn expression `expr` into dummy assertion `expr == expr` for parsing
229- addr = find_label (label )
230+ addr = spec . find_label (label )
230231 smt_string = "\n " .join (
231232 preludes + ["(assert (=" , expr , expr , "))" ]
232233 )
@@ -242,10 +243,8 @@ def parse_smt(smt_bool: str, linemo: int, line: str) -> smt.BoolRef:
242243
243244 return spec
244245
245- def __repr__ (self ):
246- return json .dumps (
247- dataclasses .asdict (self ), indent = 2 , default = lambda b : b .sexpr ()
248- )
246+ def json (self ):
247+ return json .dumps (self .addrmap , indent = 2 , default = lambda b : b .sexpr ())
249248
250249
251250type Trace = list [int ] # TODO | SpecStmt
@@ -633,9 +632,18 @@ def __repr__(self):
633632 return super ().__repr__ () + f"\n \n from VC: { self .vc } "
634633
635634
635+ @dataclass (frozen = True )
636+ class AsmProof :
637+ spec : AsmSpec
638+ pfs : tuple [kd .Proof ]
639+
640+ def __repr__ (self ):
641+ return f"AsmProof(spec={ self .spec } )"
642+
643+
636644class AsmProofState :
637- def __init__ (self , ctx : pcode . BinaryContext , spec : AsmSpec ):
638- self .ctx = ctx
645+ def __init__ (self , spec : AsmSpec ):
646+ self .ctx = spec . ctx
639647 self .spec = spec
640648 # self._spec = spec.copy() # TODO copy
641649 mem = self .ctx .init_mem ()
@@ -662,22 +670,23 @@ def exact(self, pf: kd.Proof):
662670 self .pfs .append (pf )
663671
664672 def qed (self ):
665- assert len (self .vcs ) == len (self .pfs )
666- assert all (
667- isinstance (pf , kd .Proof ) and pf .thm .eq (vc .vc (self .ctx ))
668- for vc , pf in zip (self .vcs , self .pfs )
669- )
673+ assert all (isinstance (pf , kd .Proof ) for pf in self .pfs )
674+ for vc in self .vcs :
675+ assert any (pf .thm .eq (vc .vc (self .ctx )) for pf in self .pfs ), (
676+ f"VC not proved: { vc } "
677+ )
678+ return AsmProof (self .spec , tuple (self .pfs )) # Todo: More in here?
670679
671680
672681class Debug :
673682 def __init__ (
674683 self ,
675684 ctx : pcode .BinaryContext ,
676- spec : AsmSpec = AsmSpec () ,
685+ spec : Optional [ AsmSpec ] = None ,
677686 verbose = True ,
678687 ):
679688 self .ctx = ctx
680- self .spec : AsmSpec = spec
689+ self .spec : AsmSpec = spec if spec is not None else AsmSpec ( ctx )
681690 self .tracestates : list [TraceState ] = []
682691 self .vcs : list [VerificationCondition ] = []
683692 self .breakpoints = set ()
0 commit comments