A simpler RISC-style view of x86 assembly language |
Require
Import
List TheoryList ZArith.
Require
Import
Asm.Util.Specif.
Require
Import
Asm.Util.Tactics.
Require
Import
Asm.Util.ListUtil.
Require
Import
Asm.Util.Monad.
Require
Import
Asm.Util.Maps.
Require
Import
Asm.Bitvector.Bitvector.
Require
Import
Asm.X86.X86.
Require
Import
ProofOS.Trusted.Safety.
Require
Import
ProofOS.Trusted.Machine.
Require
Import
ProofOS.Trusted.Arches.
Require
Import
ProofOS.AbsInt.Bounded.
Require
Import
ProofOS.AbsInt.Reduce.
Set Implicit
Arguments.
Types describing the SAL assembly language |
Pseudo-registers |
Inductive
salReg : Set :=
| SX86 : reg32 -> salReg
| STmp1 : salReg
| STmp2 : salReg.
Side-effect-free expressions |
Inductive
salExp : Set :=
| SConst : int32 -> salExp
| SReg : salReg -> salExp
| SArith : arith_op -> salExp -> salExp -> salExp
| SShift : shift_op -> salExp -> nat -> salExp.
Kinds of indirect jumps, corresponding to which real x86 instruction was compiled to a SAL jump instruction |
Inductive
salIJump : Set :=
| SCall
| SRet.
Kinds of arithmetic comparisons |
Inductive
salCmp : Set :=
| SWithCF
| SNoCF.
Commands, which don't touch the program counter |
Inductive
salCmd : Set :=
| SSet : salReg -> salExp -> salCmd
| SLoad : salReg -> salExp -> salCmd
| SStore : salExp -> salExp -> salCmd
| SCompare : salCmp -> arith_op -> salExp -> salExp -> salCmd.
Jumps, which end instructions |
Inductive
salJump : Set :=
| SFail : salJump
| SFallthru : salJump
| SJump : int32 -> salJump
| SIndirectJump : salIJump -> salExp -> salJump
| SConditionalJump : cc -> int32 -> salJump.
Definition
salInstr := (list salCmd * salJump)%type.
Operational semantics of SAL |
Building finite maps |
Definition
salReg_eq_dec : forall (r1 r2 : salReg), {r1 = r2} + {r1 <> r2}.
Module
SalRegIndexed <: INDEXED_TYPE.
Definition
t := salReg.
Definition
index r :=
(match r with
| SX86 r' => Reg32Indexed.index r'
| STmp1 => 9
| STmp2 => 10
end)%positive.
Theorem
index_inj: forall (x y: t), index x = index y -> x = y.
Definition
eq := salReg_eq_dec.
Definition
invert p :=
(match p with
| 9 => STmp1
| 10 => STmp2
| _ => SX86 (Reg32Indexed.invert p)
end)%positive.
Theorem
invert_index : forall x, invert (index x) = x.
End
SalRegIndexed.
Module
SalRegMap := IMap(SalRegIndexed).
Definition
salRegs := SalRegMap.t int32.
The type of SAL machine states |
Record
salState : Set := {
SstRegs : salRegs;
SstFlags : flags;
SstMem : mem;
SstPc : int32
}.
Accessors and mutators |
Definition
get_instr st := decode_instr (SstMem st) (SstPc st).
Definition
get_reg st r :=
SalRegMap.get r (SstRegs st).
Definition
set_reg st r n :=
Build_salState (SalRegMap.set r n (SstRegs st)) (SstFlags st) (SstMem st) (SstPc st).
Definition
get_flag st f := FlagMap.get f (SstFlags st).
Definition
set_flag st f b := Build_salState (SstRegs st)
(FlagMap.set f b (SstFlags st)) (SstMem st) (SstPc st).
Definition
get_mem st a :=
Int32Map.get a (SstMem st).
Definition
set_mem st a n :=
Build_salState (SstRegs st) (SstFlags st) (Int32Map.set a n (SstMem st)) (SstPc st).
Definition
set_pc st pc :=
Build_salState (SstRegs st) (SstFlags st) (SstMem st) pc.
Combined 32-bit memory accessor/mutator |
Definition
get_mem32 st a := get_mem32' (SstMem st) a.
Definition
set_mem32 st a v :=
Build_salState (SstRegs st) (SstFlags st) (set_mem32' (SstMem st) a v) (SstPc st).
Lemma
invert_set_mem32 : forall st addr v,
get_mem32 (set_mem32 st addr v) addr = v.
Theorem
invert_set_mem32_neq : forall st addr addr' v,
not_too_high addr
-> not_too_high addr'
-> apart addr addr'
-> get_mem32 (set_mem32 st addr v) addr' = get_mem32 st addr'.
Expression evaluation |
Definition
eval_shift sop n1 n2 :=
match sop with
| Shl => bshl32 n1 n2
| Shr => bshr32 n1 n2
end.
Fixpoint
evalExp (st : salState) (e : salExp) {struct e} : int32 :=
match e with
| SConst n => n
| SReg r => get_reg st r
| SArith aop e1 e2 => eval_arith aop (evalExp st e1) (evalExp st e2)
| SShift sop e n => eval_shift sop (evalExp st e) n
end.
Definition
arith_flags st aop n1 n2 :=
Build_salState (SstRegs st) (arith_flags' (SstFlags st) aop n1 n2)
(SstMem st) (SstPc st).
Definition
arith_flags_no_CF st aop n1 n2 :=
Build_salState (SstRegs st) (arith_flags_no_CF' (SstFlags st) aop n1 n2)
(SstMem st) (SstPc st).
Definition
set_arith_flags cmp :=
match cmp with
| SWithCF => arith_flags
| SNoCF => arith_flags_no_CF
end.
Definition
check_cc st cb := check_cc' (SstFlags st) cb.
Definition
salExecCmd (st : salState) (cmd : salCmd) : salState :=
match cmd with
| SSet r e => set_reg st r (evalExp st e)
| SLoad r e => set_reg st r (get_mem32 st (evalExp st e))
| SStore e1 e2 => set_mem32 st (evalExp st e1) (evalExp st e2)
| SCompare cmp aop e1 e2 => set_arith_flags cmp st aop (evalExp st e1) (evalExp st e2)
end.
Definition
salExecJmp (jmp : salJump) (nextPc : int32) (st : salState) : option salState :=
match jmp with
| SFail => None
| SFallthru => Some (set_pc st nextPc)
| SJump pc => Some (set_pc st pc)
| SIndirectJump _ e => Some (set_pc st (evalExp st e))
| SConditionalJump co pc =>
Some (if check_cc st co
then set_pc st pc
else set_pc st nextPc)
end.
Definition
salExec' (insPc : salInstr * int32) (st : salState) : option salState :=
salExecJmp (snd (fst insPc)) (snd insPc) (fold_left salExecCmd (fst (fst insPc)) st).
Definition
salAddr (addr : address) : salExp :=
let n := SConst (addrDisp addr) in
let n := match addrBase addr with
| None => n
| Some base => SArith Add
n (SReg (SX86 base))
end in
match addrIndex addr with
| None => n
| Some (sc, idx) =>
SArith Add
n (SShift Shl (SReg (SX86 idx)) (scale_shift sc))
end.
Definition
salGenop (tmp : salReg) (gop : genop32) : list salCmd * salExp :=
match gop with
| Imm n => (nil, SConst n)
| Reg r => (nil, SReg (SX86 r))
| Address a => (cons (SLoad tmp (salAddr a)) nil, SReg tmp)
end.
Definition
failureInstr : salInstr := (nil, SFail).
Definition
salCompile insPc :=
match fst insPc with
| Arith aop (Reg r) g =>
let (loads, g') := salGenop STmp1 g in
(app loads
(cons (SCompare SWithCF aop (SReg (SX86 r)) g')
(cons (SSet (SX86 r) (SArith aop (SReg (SX86 r)) g'))
nil)), SFallthru)
| Arith aop (Address a) g =>
let (loads, g') := salGenop STmp2 g in
(app (cons (SLoad STmp1 (salAddr a)) loads)
(cons (SCompare SWithCF aop (SReg STmp1) g')
(cons (SStore (salAddr a) (SArith aop (SReg STmp1) g'))
nil)), SFallthru)
| Call g =>
let (loads, g') := salGenop STmp1 g in
(app (cons (SStore (SArith Add
(SConst neg_four) (SReg (SX86 ESP))) (SConst (snd insPc)))
(cons (SSet (SX86 ESP) (SArith Sub (SReg (SX86 ESP)) (SConst four)))
nil)) loads,
SIndirectJump SCall g')
| Cmp g1 g2 =>
let (loads1, g1') := salGenop STmp1 g1 in
let (loads2, g2') := salGenop STmp2 g2 in
(app (app loads1 loads2) (cons (SCompare SWithCF Sub g1' g2') nil), SFallthru)
| Inc (Reg r) =>
(cons (SCompare SNoCF Add
(SReg (SX86 r)) (SConst bone32))
(cons (SSet (SX86 r) (SArith Add
(SReg (SX86 r)) (SConst bone32)))
nil), SFallthru)
| Inc (Address a) =>
(cons (SLoad STmp1 (salAddr a))
(cons (SCompare SNoCF Add
(SReg STmp1) (SConst bone32))
(cons (SStore (salAddr a) (SArith Add
(SReg STmp1) (SConst bone32)))
nil)), SFallthru)
| Jcc c pc =>
(nil, SConditionalJump c pc)
| Jmp pc =>
(nil, SJump pc)
| Lea r a =>
(cons (SSet (SX86 r) (salAddr a)) nil, SFallthru)
| Leave =>
(cons (SSet (SX86 ESP) (SArith Add
(SConst four) (SReg (SX86 EBP))))
(cons (SLoad (SX86 EBP) (SReg (SX86 EBP)))
nil), SFallthru)
| Mov (Reg r) g =>
let (loads, g') := salGenop STmp1 g in
(app loads (cons (SSet (SX86 r) g') nil), SFallthru)
| Mov (Address a) g =>
let (loads, g') := salGenop STmp1 g in
(app loads (cons (SStore (salAddr a) g') nil), SFallthru)
| Pop (Reg r) =>
(cons (SLoad (SX86 r) (SReg (SX86 ESP)))
(cons (SSet (SX86 ESP) (SArith Add
(SConst four) (SReg (SX86 ESP))))
nil), SFallthru)
| Pop (Address a) =>
(cons (SLoad STmp1 (SReg (SX86 ESP)))
(cons (SStore (salAddr a) (SReg STmp1))
(cons (SSet (SX86 ESP) (SArith Add
(SConst four) (SReg (SX86 ESP))))
nil)), SFallthru)
| Push g =>
let (loads, g') := salGenop STmp1 g in
(app loads
(cons (SStore (SArith Add
(SConst neg_four) (SReg (SX86 ESP))) g')
(cons (SSet (SX86 ESP) (SArith Add
(SConst neg_four) (SReg (SX86 ESP))))
nil)), SFallthru)
| Ret =>
(cons (SLoad STmp1 (SReg (SX86 ESP)))
(cons (SSet (SX86 ESP) (SArith Add
(SConst four) (SReg (SX86 ESP))))
nil), SIndirectJump SRet (SReg STmp1))
| _ => failureInstr
end.
Definition
salInstruction := (instr * salInstr)%type.
Definition
get_sal_instr st :=
let (ins, pc) := get_instr st in
((ins, salCompile (ins, pc)), pc).
Definition
salExec (insPc : salInstruction * int32) (st st' : salState) :=
salExec' (snd (fst insPc), snd insPc) st = Some st'.
The SAL abstract machine |
Concretization relation |
Record
R (st : state) (st' : salState) : Prop := {
Rregs : forall r, get_reg st' (SX86 r) = get_reg32 st r;
Rflags : SstFlags st' = stFlags st;
Rmem : SstMem st' = stMem st;
Rpc : SstPc st' = stPc st
}.
Module
Sal86 (Param : M86_PARAM) <: MACHINE.
Definition
mstate := salState.
Definition
minitState st := exists st', R st' st /\ Param.minitState st'.
Definition
minstr := salInstruction.
Definition
mget_instr := get_sal_instr.
Definition
mexec := salExec.
End
Sal86.
Relating SAL to X86 |
Module
Make (Param : M86_PARAM).
Module
MC := M86(Param).
Module
M := Sal86(Param).
Module
Checker (_Abs : ABSTRACTION with Module Mac := M)
: CHECKER with Module Mac := MC.
Module
Reduction <: REDUCTION.
Definition
cameFrom : forall (ins : instr * salInstr),
{ins' : instr
| forall abs nextPc, get_sal_instr abs = (ins, nextPc)
-> forall st, R st abs -> Defs.get_instr st = (ins', nextPc)}.
Definition
liftState (st : state) :=
Build_salState
(SalRegMap.set (SX86 EAX) (get_reg32 st EAX)
(SalRegMap.set (SX86 ECX) (get_reg32 st ECX)
(SalRegMap.set (SX86 EDX) (get_reg32 st EDX)
(SalRegMap.set (SX86 EBX) (get_reg32 st EBX)
(SalRegMap.set (SX86 ESP) (get_reg32 st ESP)
(SalRegMap.set (SX86 EBP) (get_reg32 st EBP)
(SalRegMap.set (SX86 ESI) (get_reg32 st ESI)
(SalRegMap.set (SX86 EDI) (get_reg32 st EDI)
(SalRegMap.init bzero32)))))))))
(stFlags st) (stMem st) (stPc st).
Theorem
init : forall conc, Param.minitState conc
-> exists abs, R conc abs /\ M.minitState abs.
Hint
Constructors exec write_genop32.
Definition
check_cc_eq : forall abs conc c,
R conc abs
-> check_cc abs c = Defs.check_cc conc c.
Definition
check_cc_imp : forall abs conc c b,
R conc abs
-> check_cc abs c = b
-> Defs.check_cc conc c = b.
Hint
Resolve check_cc_imp.
Definition
check_cc_eq' : forall abs conc c,
SstFlags abs = stFlags conc
-> check_cc abs c = Defs.check_cc conc c.
Definition
check_cc_imp' : forall abs conc c b,
SstFlags abs = stFlags conc
-> Defs.check_cc conc c = b
-> check_cc abs c = b.
Hint
Rewrite check_cc_imp' using assumption : Maps.
Hint
Rewrite SalRegMap.gss Reg32Map.gss : Maps.
Hint
Rewrite SalRegMap.gso Reg32Map.gso using congruence : Maps.
Hint
Unfold get_reg get_reg32 set_pc arith_flags.
Ltac
unfold_get :=
match goal with
| [ H : forall r : reg32, get_reg _ _ = get_reg32 _ _ |- _ ] =>
unfold get_reg, get_reg32 in H; rewrite H; repeat rewrite H
end.
Ltac
rewrite_get :=
match goal with
| [ H : forall r : reg32, get_reg _ _ = get_reg32 _ _ |- _ ] =>
rewrite H; repeat rewrite H
end.
Ltac
get_cases :=
match goal with
| [ |- context[Reg32Map.get ?r0 (Reg32Map.set ?r _ _)] ] =>
destruct (reg32_eq_dec r0 r); subst; autorewrite with Maps
end.
Lemma
eval_addr_reg : forall r conc,
eval_addr (Build_address bzero32 (Some r) None) conc
= get_reg32 conc r.
Hint
Rewrite eval_addr_reg : Maps.
Lemma
eval_addr_stack : forall r conc,
eval_addr (Build_address neg_four (Some r) None) conc
= badd32 neg_four (get_reg32 conc r).
Hint
Rewrite eval_addr_stack : Maps.
Lemma
evalExp_salAddr : forall conc abs a,
(forall r : reg32,
SalRegMap.get (SX86 r) (SstRegs abs) =
Reg32Map.get r (stRegs32 conc))
-> evalExp abs (salAddr a) = eval_addr a conc.
Definition
compile : forall (insPc : instr * int32),
{ins' : salInstruction
| forall conc abs,
R conc abs
-> (forall abs', salExec (ins', snd insPc) abs abs'
-> exists conc', exec insPc conc conc')
/\ (forall conc', exec insPc conc conc'
-> exists abs', salExec (ins', snd insPc) abs abs'
/\ R conc' abs')}.
Definition
R := R.
Module
Conc := MC.
Module
Abs := _Abs.
End
Reduction.
Module
Ch := Reduce.Make(Reduction).
Module
Mac := MC.
Definition
verify := Ch.verify.
End
Checker.
End
Make.