@@ -78,6 +78,7 @@ import Verifier.SAW.SCTypeCheck (scTypeCheck)
78
78
79
79
import Verifier.SAW.Simulator.What4.ReturnTrip
80
80
81
+ import SAWScript.Panic (panic )
81
82
import SAWScript.Proof
82
83
import SAWScript.Prover.SolverStats
83
84
import SAWScript.TopLevel
@@ -960,11 +961,14 @@ setupMemory ::
960
961
setupMemory globsyms balign = do
961
962
setupGlobals globsyms
962
963
963
- -- Allocate a reasonable amount of stack (4 KiB + 0b10000 for least valid alignment + 1 qword for IP)
964
- allocateStack (4096 + 16 ) balign
965
-
966
964
ms <- use x86MethodSpec
967
965
966
+ -- Allocate a reasonable amount of stack (4 KiB + 1 qword for the previous
967
+ -- %rbp value + 1 qword for the return address + 1 qword for each stack
968
+ -- argument)
969
+ let argsStackSize = fromIntegral $ 8 * (length $ Prelude. drop (length argRegs) $ Map. elems $ ms ^. MS. csArgBindings)
970
+ allocateStack (4096 + 16 + argsStackSize) balign
971
+
968
972
let
969
973
tyenv = ms ^. MS. csPreState . MS. csAllocs
970
974
nameEnv = MS. csTypeNames ms
@@ -975,6 +979,8 @@ setupMemory globsyms balign = do
975
979
976
980
setArgs env tyenv nameEnv . fmap snd . Map. elems $ ms ^. MS. csArgBindings
977
981
982
+ pushFreshReturnAddress
983
+
978
984
pure env
979
985
980
986
-- | Given an alist of symbol names and sizes (in bytes), allocate space and copy
@@ -1008,8 +1014,7 @@ setupGlobals globsyms = do
1008
1014
mem' <- liftIO $ foldlM writeGlobal mem globs
1009
1015
x86Mem .= mem'
1010
1016
1011
- -- | Allocate memory for the stack, and pushes a fresh pointer as the return
1012
- -- address.
1017
+ -- | Allocate memory for the stack.
1013
1018
allocateStack ::
1014
1019
X86Constraints =>
1015
1020
Integer {- ^ Stack size in bytes -} ->
@@ -1020,17 +1025,44 @@ allocateStack szInt balign = do
1020
1025
sym <- use x86Sym
1021
1026
mem <- use x86Mem
1022
1027
regs <- use x86Regs
1023
- sz <- liftIO $ W4. bvLit sym knownNat $ BV. mkBV knownNat $ szInt + 8
1024
- (base, mem') <- liftIO $ C.LLVM. doMalloc bak C.LLVM. HeapAlloc C.LLVM. Mutable " stack_alloc" mem sz balign
1028
+ sz <- liftIO $ W4. bvLit sym knownNat $ BV. mkBV knownNat $ szInt
1029
+ (base, finalMem) <- liftIO $ C.LLVM. doMalloc bak C.LLVM. HeapAlloc C.LLVM. Mutable " stack_alloc" mem sz balign
1030
+ ptr <- liftIO $ C.LLVM. doPtrAddOffset bak finalMem base sz
1031
+ x86Mem .= finalMem
1032
+ finalRegs <- setReg Macaw. RSP ptr regs
1033
+ x86Regs .= finalRegs
1034
+
1035
+ -- | Push a fresh pointer as the return address.
1036
+ pushFreshReturnAddress ::
1037
+ X86Constraints =>
1038
+ X86Sim ()
1039
+ pushFreshReturnAddress = do
1040
+ SomeOnlineBackend bak <- use x86Backend
1041
+ sym <- use x86Sym
1042
+ mem <- use x86Mem
1043
+ regs <- use x86Regs
1025
1044
sn <- case W4. userSymbol " stack" of
1026
1045
Left err -> throwX86 $ " Invalid symbol for stack: " <> show err
1027
1046
Right sn -> pure sn
1028
1047
fresh <- liftIO $ C.LLVM. LLVMPointer
1029
1048
<$> W4. natLit sym 0
1030
1049
<*> W4. freshConstant sym sn (W4. BaseBVRepr $ knownNat @ 64 )
1031
- ptr <- liftIO $ C.LLVM. doPtrAddOffset bak mem' base =<< W4. bvLit sym knownNat (BV. mkBV knownNat szInt)
1032
- writeAlign <- integerToAlignment defaultStackBaseAlign
1033
- finalMem <- liftIO $ C.LLVM. doStore bak mem' ptr
1050
+ rsp <- getReg Macaw. RSP regs
1051
+
1052
+ -- x86-64 System V ABI specifies that: "In other words, the stack needs to be
1053
+ -- 16 (32 or 64) byte aligned immediately before the call instruction is
1054
+ -- executed. Once control has been transferred to the function entry point,
1055
+ -- i.e. immediately after the return address has been pushed, %rsp points to
1056
+ -- the return address, and the value of (%rsp + 8) is a multiple of 16 (32 or
1057
+ -- 64)."
1058
+ stackAlign <- integerToAlignment defaultStackBaseAlign
1059
+ is_aligned <- liftIO $ C.LLVM. isAligned sym (knownNat @ 64 ) rsp stackAlign
1060
+ when (W4. asConstantPred is_aligned /= Just True ) $
1061
+ panic " SAWScript.Crucible.LLVM.X86.pushFreshReturnAddress" [" %rsp is not 16 byte aligned before the call instruction is executed." ]
1062
+
1063
+ ptr <- liftIO $ C.LLVM. doPtrAddOffset bak mem rsp =<< W4. bvLit sym knownNat (BV. mkBV knownNat (- 8 ))
1064
+ let writeAlign = C.LLVM. noAlignment
1065
+ finalMem <- liftIO $ C.LLVM. doStore bak mem ptr
1034
1066
(C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1035
1067
(C.LLVM. bitvectorType 8 ) writeAlign fresh
1036
1068
x86Mem .= finalMem
@@ -1152,37 +1184,62 @@ setArgs ::
1152
1184
Map MS. AllocIndex C.LLVM. Ident {- ^ Associates each AllocIndex with its name -} ->
1153
1185
[MS. SetupValue LLVM ] {- ^ Arguments passed to llvm_execute_func -} ->
1154
1186
X86Sim ()
1155
- setArgs env tyenv nameEnv args
1156
- | length args > length argRegs = throwX86 " More arguments than would fit into general-purpose registers"
1157
- | otherwise = do
1158
- sym <- use x86Sym
1159
- cc <- use x86CrucibleContext
1160
- mem <- use x86Mem
1161
- let
1162
- setRegSetupValue rs (reg, sval) =
1163
- exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \ case
1164
- ty | C.LLVM. isPointerMemType ty -> do
1165
- val <- C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1166
- =<< resolveSetupVal cc mem env tyenv nameEnv sval
1167
- setReg reg val rs
1168
- C.LLVM. IntType 64 -> do
1187
+ setArgs env tyenv nameEnv args = do
1188
+ SomeOnlineBackend bak <- use x86Backend
1189
+ sym <- use x86Sym
1190
+ cc <- use x86CrucibleContext
1191
+ mem <- use x86Mem
1192
+ let
1193
+ setRegSetupValue rs (reg, sval) =
1194
+ exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \ case
1195
+ ty | C.LLVM. isPointerMemType ty -> do
1196
+ val <- C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1197
+ =<< resolveSetupVal cc mem env tyenv nameEnv sval
1198
+ setReg reg val rs
1199
+ C.LLVM. IntType 64 -> do
1200
+ val <- C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1201
+ =<< resolveSetupVal cc mem env tyenv nameEnv sval
1202
+ setReg reg val rs
1203
+ C.LLVM. IntType _ -> do
1204
+ C.LLVM. LLVMValInt base off <- resolveSetupVal cc mem env tyenv nameEnv sval
1205
+ case testLeq (incNat $ W4. bvWidth off) (knownNat @ 64 ) of
1206
+ Nothing -> fail " Argument bitvector does not fit in a single general-purpose register"
1207
+ Just LeqProof -> do
1208
+ off' <- W4. bvZext sym (knownNat @ 64 ) off
1169
1209
val <- C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1170
- =<< resolveSetupVal cc mem env tyenv nameEnv sval
1210
+ $ C.LLVM. LLVMValInt base off'
1171
1211
setReg reg val rs
1172
- C.LLVM. IntType _ -> do
1173
- C.LLVM. LLVMValInt base off <- resolveSetupVal cc mem env tyenv nameEnv sval
1174
- case testLeq (incNat $ W4. bvWidth off) (knownNat @ 64 ) of
1175
- Nothing -> fail " Argument bitvector does not fit in a single general-purpose register"
1176
- Just LeqProof -> do
1177
- off' <- W4. bvZext sym (knownNat @ 64 ) off
1178
- val <- C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1179
- $ C.LLVM. LLVMValInt base off'
1180
- setReg reg val rs
1181
- _ -> fail " Argument does not fit into a single general-purpose register"
1182
- regs <- use x86Regs
1183
- newRegs <- liftIO . foldlM setRegSetupValue regs $ zip argRegs args
1184
- x86Regs .= newRegs
1185
- where argRegs = [Macaw. RDI , Macaw. RSI , Macaw. RDX , Macaw. RCX , Macaw. R8 , Macaw. R9 ]
1212
+ _ -> fail " Argument does not fit into a single general-purpose register"
1213
+ regs <- use x86Regs
1214
+ newRegs <- liftIO . foldlM setRegSetupValue regs $ zip argRegs args
1215
+ x86Regs .= newRegs
1216
+
1217
+ -- x86-64 System V ABI specifies that: "Once registers are assigned, the
1218
+ -- arguments passed in memory are pushed on the stack in reversed
1219
+ -- (right-to-left21) order."
1220
+ let stackArgs = reverse $ Prelude. drop (length argRegs) args
1221
+ forM_ stackArgs $ \ sval -> do
1222
+ liftIO $ exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \ case
1223
+ C.LLVM. PtrType _ -> pure ()
1224
+ C.LLVM. IntType 64 -> pure ()
1225
+ _ -> fail " Stack argument is not a 64 bit integer."
1226
+
1227
+ regs' <- use x86Regs
1228
+ rsp <- getReg Macaw. RSP regs'
1229
+ rsp' <- liftIO $ C.LLVM. doPtrAddOffset bak mem rsp =<< W4. bvLit sym knownNat (BV. mkBV knownNat (- 8 ))
1230
+ newRegs' <- setReg Macaw. RSP rsp' regs'
1231
+ x86Regs .= newRegs'
1232
+
1233
+ val <- liftIO $ C.LLVM. unpackMemValue sym (C.LLVM. LLVMPointerRepr $ knownNat @ 64 )
1234
+ =<< resolveSetupVal cc mem env tyenv nameEnv sval
1235
+
1236
+ mem' <- use x86Mem
1237
+ mem'' <- liftIO $
1238
+ C.LLVM. doStore bak mem' rsp' (C.LLVM. LLVMPointerRepr $ knownNat @ 64 ) (C.LLVM. bitvectorType 8 ) C.LLVM. noAlignment val
1239
+ x86Mem .= mem''
1240
+
1241
+ argRegs :: [Macaw. X86Reg (Macaw. BVType 64 )]
1242
+ argRegs = [Macaw. RDI , Macaw. RSI , Macaw. RDX , Macaw. RCX , Macaw. R8 , Macaw. R9 ]
1186
1243
1187
1244
--------------------------------------------------------------------------------
1188
1245
-- ** Postcondition
0 commit comments