Skip to content

Commit 9b2a33a

Browse files
Add support for x86 64 bit integer stack arguments.
1 parent a400e9e commit 9b2a33a

File tree

7 files changed

+109
-34
lines changed

7 files changed

+109
-34
lines changed

intTests/test_llvm_x86_08/test

1.09 KB
Binary file not shown.

intTests/test_llvm_x86_08/test.bc

3.04 KB
Binary file not shown.

intTests/test_llvm_x86_08/test.c

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
unsigned long test(unsigned long a, unsigned long b, unsigned long c, unsigned long d,unsigned long e, unsigned long f, unsigned long g, unsigned long h) {
2+
return g - h;
3+
}
4+
5+
int main() {
6+
return 0;
7+
}
8+

intTests/test_llvm_x86_08/test.o

1.06 KB
Binary file not shown.

intTests/test_llvm_x86_08/test.saw

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
enable_experimental;
2+
3+
m <- llvm_load_module "test.bc";
4+
5+
let test_spec = do {
6+
x <- llvm_fresh_var "x" (llvm_int 64);
7+
llvm_execute_func
8+
[ llvm_term {{ 0 : [64] }}
9+
, llvm_term {{ 1 : [64] }}
10+
, llvm_term {{ 2 : [64] }}
11+
, llvm_term {{ 3 : [64] }}
12+
, llvm_term {{ 4 : [64] }}
13+
, llvm_term {{ 5 : [64] }}
14+
, llvm_term x
15+
, llvm_term {{ 1 : [64] }}
16+
];
17+
llvm_return (llvm_term {{ x - 1 }});
18+
};
19+
20+
llvm_verify_x86 m "./test" "test" [] true test_spec w4;
21+

intTests/test_llvm_x86_08/test.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
set -e
3+
4+
clang -c -emit-llvm -g -frecord-command-line test.c
5+
# clang -c -target x86_64 test.c
6+
# ld.lld -o test test.o
7+
clang -o test test.c
8+
$SAW test.saw
9+

src/SAWScript/Crucible/LLVM/X86.hs

+71-34
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,8 @@ setupMemory globsyms balign = do
975975

976976
setArgs env tyenv nameEnv . fmap snd . Map.elems $ ms ^. MS.csArgBindings
977977

978+
pushFreshReturnAddress
979+
978980
pure env
979981

980982
-- | Given an alist of symbol names and sizes (in bytes), allocate space and copy
@@ -1008,8 +1010,7 @@ setupGlobals globsyms = do
10081010
mem' <- liftIO $ foldlM writeGlobal mem globs
10091011
x86Mem .= mem'
10101012

1011-
-- | Allocate memory for the stack, and pushes a fresh pointer as the return
1012-
-- address.
1013+
-- | Allocate memory for the stack.
10131014
allocateStack ::
10141015
X86Constraints =>
10151016
Integer {- ^ Stack size in bytes -} ->
@@ -1021,16 +1022,31 @@ allocateStack szInt balign = do
10211022
mem <- use x86Mem
10221023
regs <- use x86Regs
10231024
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
1025+
(base, finalMem) <- liftIO $ C.LLVM.doMalloc bak C.LLVM.HeapAlloc C.LLVM.Mutable "stack_alloc" mem sz balign
1026+
ptr <- liftIO $ C.LLVM.doPtrAddOffset bak finalMem base sz
1027+
x86Mem .= finalMem
1028+
finalRegs <- setReg Macaw.RSP ptr regs
1029+
x86Regs .= finalRegs
1030+
1031+
-- | Push a fresh pointer as the return address.
1032+
pushFreshReturnAddress ::
1033+
X86Constraints =>
1034+
X86Sim ()
1035+
pushFreshReturnAddress = do
1036+
SomeOnlineBackend bak <- use x86Backend
1037+
sym <- use x86Sym
1038+
mem <- use x86Mem
1039+
regs <- use x86Regs
10251040
sn <- case W4.userSymbol "stack" of
10261041
Left err -> throwX86 $ "Invalid symbol for stack: " <> show err
10271042
Right sn -> pure sn
10281043
fresh <- liftIO $ C.LLVM.LLVMPointer
10291044
<$> W4.natLit sym 0
10301045
<*> 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
1046+
rsp <- getReg Macaw.RSP regs
1047+
ptr <- liftIO $ C.LLVM.doPtrAddOffset bak mem rsp =<< W4.bvLit sym knownNat (BV.mkBV knownNat (-8))
1048+
let writeAlign = C.LLVM.noAlignment
1049+
finalMem <- liftIO $ C.LLVM.doStore bak mem ptr
10341050
(C.LLVM.LLVMPointerRepr $ knownNat @64)
10351051
(C.LLVM.bitvectorType 8) writeAlign fresh
10361052
x86Mem .= finalMem
@@ -1152,36 +1168,57 @@ setArgs ::
11521168
Map MS.AllocIndex C.LLVM.Ident {- ^ Associates each AllocIndex with its name -} ->
11531169
[MS.SetupValue LLVM] {- ^ Arguments passed to llvm_execute_func -} ->
11541170
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
1171+
setArgs env tyenv nameEnv args = do
1172+
SomeOnlineBackend bak <- use x86Backend
1173+
sym <- use x86Sym
1174+
cc <- use x86CrucibleContext
1175+
mem <- use x86Mem
1176+
let
1177+
setRegSetupValue rs (reg, sval) =
1178+
exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \case
1179+
ty | C.LLVM.isPointerMemType ty -> do
1180+
val <- C.LLVM.unpackMemValue sym (C.LLVM.LLVMPointerRepr $ knownNat @64)
1181+
=<< resolveSetupVal cc mem env tyenv nameEnv sval
1182+
setReg reg val rs
1183+
C.LLVM.IntType 64 -> do
1184+
val <- C.LLVM.unpackMemValue sym (C.LLVM.LLVMPointerRepr $ knownNat @64)
1185+
=<< resolveSetupVal cc mem env tyenv nameEnv sval
1186+
setReg reg val rs
1187+
C.LLVM.IntType _ -> do
1188+
C.LLVM.LLVMValInt base off <- resolveSetupVal cc mem env tyenv nameEnv sval
1189+
case testLeq (incNat $ W4.bvWidth off) (knownNat @64) of
1190+
Nothing -> fail "Argument bitvector does not fit in a single general-purpose register"
1191+
Just LeqProof -> do
1192+
off' <- W4.bvZext sym (knownNat @64) off
11691193
val <- C.LLVM.unpackMemValue sym (C.LLVM.LLVMPointerRepr $ knownNat @64)
1170-
=<< resolveSetupVal cc mem env tyenv nameEnv sval
1194+
$ C.LLVM.LLVMValInt base off'
11711195
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
1196+
_ -> fail "Argument does not fit into a single general-purpose register"
1197+
regs <- use x86Regs
1198+
newRegs <- liftIO . foldlM setRegSetupValue regs $ zip argRegs args
1199+
x86Regs .= newRegs
1200+
1201+
let stackArgs = reverse $ Prelude.drop (length argRegs) args
1202+
forM_ stackArgs $ \sval -> do
1203+
liftIO $ exceptToFail (typeOfSetupValue cc tyenv nameEnv sval) >>= \case
1204+
C.LLVM.PtrType _ -> pure ()
1205+
C.LLVM.IntType 64 -> pure ()
1206+
_ -> fail "Stack argument is not a 64 bit integer."
1207+
1208+
regs' <- use x86Regs
1209+
rsp <- getReg Macaw.RSP regs'
1210+
rsp' <- liftIO $ C.LLVM.doPtrAddOffset bak mem rsp =<< W4.bvLit sym knownNat (BV.mkBV knownNat (-8))
1211+
newRegs' <- setReg Macaw.RSP rsp' regs'
1212+
x86Regs .= newRegs'
1213+
1214+
val <- liftIO $ C.LLVM.unpackMemValue sym (C.LLVM.LLVMPointerRepr $ knownNat @64)
1215+
=<< resolveSetupVal cc mem env tyenv nameEnv sval
1216+
1217+
mem' <- use x86Mem
1218+
mem'' <- liftIO $
1219+
C.LLVM.doStore bak mem' rsp' (C.LLVM.LLVMPointerRepr $ knownNat @64) (C.LLVM.bitvectorType 8) C.LLVM.noAlignment val
1220+
x86Mem .= mem''
1221+
11851222
where argRegs = [Macaw.RDI, Macaw.RSI, Macaw.RDX, Macaw.RCX, Macaw.R8, Macaw.R9]
11861223

11871224
--------------------------------------------------------------------------------

0 commit comments

Comments
 (0)