Skip to content

Commit 86f648b

Browse files
committed
WIP: Support JDK 9 or later
This allows SAW to deal with JDK 9 or later, which packages its standard library not in a JAR file, but in a JIMAGE file. Extracting `.class` files from JIMAGE files proves to be surprisingly tricky, and I've carefully documented the intricacies of doing so in `Note [Loading classes from JIMAGE files]` in `SAWScript.JavaCodebase`. This fixes #861. Remaining tasks: * Ideally, the code in `SAWScript.JavaCodebase` would be upstreamed to `crucible-jvm`, where the all-important `Codebase` data type lives. Until that happens, I needed to introduce some ugly hacks in order to make everything typecheck. In particular, the (hopefully temporary) `SAWScript.JavaCodebase` module defines a version of `Codebase` that keeps track of JIMAGE-related paths. Other things: * I removed the dependency on the `xdg-basedir`, as it was unused. This dependency was likely added quite some time ago, and it appears that `saw-script` switched over to using XDG-related functionality from the `directory` library since then. I opted to use `directory` to find the `.cache` directory as well, so I have made that clear in the `.cabal` file. * The `biJavaCodebase :: Codebase` field of `BuiltinContext` is completely unused, which I noticed when making changes to the `Codebase` type. Let's just remove it. This fixes #1003.
1 parent a2b9c75 commit 86f648b

File tree

16 files changed

+459
-41
lines changed

16 files changed

+459
-41
lines changed

.github/workflows/build.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
matrix:
3636
os: [ubuntu-latest]
3737
ghc: ["8.6.5", "8.8.4", "8.10.2"]
38+
jdk: ["8", "15"]
3839
continue-on-error: [false]
3940
include:
4041
- os: macos-latest
@@ -108,7 +109,7 @@ jobs:
108109

109110
- uses: actions/setup-java@v1
110111
with:
111-
java-version: "8"
112+
java-version: ${{ matrix.jdk }}
112113
java-package: jdk
113114
architecture: x64
114115

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## New Features
44

5+
SAW now supports verifying Java code using JDK 9 or later.
6+
57
When verifying Java code, the path to Java can be specified with the new
68
`--java-bin-dirs`/`-b` command-line option. Alternatively, if
79
`--java-bin-dirs` is not set, then SAW searches the `PATH` to find Java.

doc/manual/manual.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -1568,10 +1568,7 @@ the `java_load_class` function.
15681568
The resulting `JavaClass` can be passed into the various functions
15691569
described below to perform analysis of specific Java methods.
15701570

1571-
Java class files from any JDK newer than version 6 should work. However,
1572-
JDK version 9 and newer do not contain a JAR file containing the
1573-
standard libraries, and therefore do not currently work with SAW. We are
1574-
investigating the best way to resolve this issue.
1571+
Java class files from any JDK newer than version 6 should work.
15751572

15761573
## Notes on Compiling Code for SAW
15771574

doc/tutorial/tutorial.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,7 @@ locates Java. Run the code in this section with the command:
236236
Alternatively, if Java is located on your `PATH`, you can omit the `-b`
237237
option entirely.
238238

239-
Both Oracle JDK and OpenJDK versions 6 through 8 work well with SAW.
240-
From version 9 onward, the core libraries are no longer stored in a
241-
standard JAR file, making them inacessible to SAW. We're currently
242-
considering strategies for working with newer Java versions.
239+
Both Oracle JDK and OpenJDK versions 6 and later work well with SAW.
243240

244241
Now we can do the proof both within and across languages (from
245242
`ffs_compare.saw`):

saw-remote-api/src/SAWServer.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import Verifier.SAW.TypedTerm (TypedTerm, CryptolModule)
4747

4848
import qualified SAWScript.Crucible.Common.MethodSpec as CMS (CrucibleMethodSpecIR)
4949
import qualified SAWScript.Crucible.LLVM.MethodSpecIR as CMS (SomeLLVM, LLVMModule)
50+
import SAWScript.JavaCodebase (loadCodebase)
5051
import SAWScript.JavaExpr (JavaType(..))
5152
import SAWScript.Options (defaultOptions)
5253
import SAWScript.Position (Pos(..))
@@ -165,9 +166,9 @@ initialState readFileFn =
165166
ss <- basic_ss sc
166167
let jarFiles = []
167168
classPaths = []
168-
jcb <- JSS.loadCodebase jarFiles classPaths
169+
javaBinDirs = []
170+
jcb <- loadCodebase jarFiles classPaths javaBinDirs
169171
let bic = BuiltinContext { biSharedContext = sc
170-
, biJavaCodebase = jcb
171172
, biBasicSS = ss
172173
}
173174
cenv <- initCryptolEnv sc

saw-script.cabal

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ library
2929
base >= 4
3030
, aig
3131
, array
32+
, base16-bytestring >= 0.1 && < 1.1
3233
, binary
3334
, bimap
3435
, bytestring
@@ -40,6 +41,7 @@ library
4041
, crucible >= 0.4
4142
, crucible-jvm
4243
, crucible-llvm >= 0.2
44+
, cryptohash-sha1 >= 0.11 && < 0.12
4345
, deepseq
4446
, either
4547
, exceptions
@@ -85,7 +87,6 @@ library
8587
, utf8-string
8688
, what4 >= 0.4
8789
, vector
88-
, xdg-basedir
8990
, GraphSCC
9091
, macaw-base
9192
, macaw-x86
@@ -114,6 +115,7 @@ library
114115
SAWScript.Import
115116
SAWScript.ImportAIG
116117
SAWScript.Interpreter
118+
SAWScript.JavaCodebase
117119
SAWScript.JavaExpr
118120
SAWScript.JavaTools
119121
SAWScript.JavaPretty

src/SAWScript/Crucible/JVM/Builtins.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ import qualified Lang.Crucible.Simulator.GlobalState as Crucible
8484
import qualified Lang.Crucible.Simulator.SimError as Crucible
8585

8686
-- crucible-jvm
87-
import qualified Lang.JVM.Codebase as CB
8887
import qualified Lang.Crucible.JVM as CJ
8988

9089
-- parameterized-utils
@@ -107,6 +106,7 @@ import qualified SAWScript.Position as SS
107106
import SAWScript.Options
108107
import SAWScript.Crucible.JVM.BuiltinsJVM (prepareClassTopLevel)
109108

109+
import SAWScript.JavaCodebase (Codebase)
110110
import SAWScript.JavaExpr (JavaType(..))
111111

112112
import qualified SAWScript.Crucible.Common as Common
@@ -138,7 +138,7 @@ ppJVMAbortedResult _cc = Common.ppAbortedResult (\_gp -> mempty)
138138
-- number of classes we load is way too large, and the classes take a
139139
-- long time to parse and translate.
140140

141-
allClassRefs :: CB.Codebase -> J.ClassName -> IO (Set J.ClassName)
141+
allClassRefs :: Codebase -> J.ClassName -> IO (Set J.ClassName)
142142
allClassRefs cb c0 = go seen0 [c0]
143143
where
144144
seen0 = Set.fromList CJ.initClasses

src/SAWScript/Crucible/JVM/BuiltinsJVM.hs

+5-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import Verifier.SAW.Simulator.What4.ReturnTrip
7474

7575
-- saw-script
7676
import SAWScript.Builtins(fixPos)
77+
import SAWScript.JavaCodebase (Codebase)
7778
import SAWScript.Value
7879
import SAWScript.Options(Options,simVerbose)
7980
import SAWScript.Crucible.Common
@@ -83,14 +84,17 @@ import SAWScript.Crucible.LLVM.Builtins (setupArg, setupArgs, getGlobalPair, run
8384
import qualified Language.JVM.Common as J
8485
import qualified Language.JVM.Parser as J
8586
import qualified SAWScript.Utils as J
86-
import qualified Lang.JVM.Codebase as JCB
8787

8888
-- crucible-jvm
8989
import Lang.Crucible.JVM (IsCodebase(..))
9090
import qualified Lang.Crucible.JVM as CJ
9191

9292
import Debug.Trace
9393

94+
instance IsCodebase Codebase where
95+
lookupClass cb = J.lookupClass cb fixPos
96+
findMethod cb = J.findMethod cb fixPos
97+
9498
-----------------------------------------------------------------------
9599
-- | Make sure the class is in the database and allocate handles for its
96100
-- methods and static fields

src/SAWScript/Crucible/JVM/MethodSpecIR.hs

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import qualified Lang.Crucible.FunctionHandle as Crucible (HandleAllocator)
3737

3838
-- crucible-jvm
3939
import qualified Lang.Crucible.JVM as CJ
40-
import qualified Lang.JVM.Codebase as CB
4140

4241
-- jvm-parser
4342
import qualified Language.JVM.Parser as J
@@ -48,6 +47,7 @@ import Verifier.SAW.TypedTerm (TypedTerm)
4847
import SAWScript.Crucible.Common (Sym)
4948
import qualified SAWScript.Crucible.Common.MethodSpec as MS
5049
import qualified SAWScript.Crucible.Common.Setup.Type as Setup
50+
import SAWScript.JavaCodebase (Codebase)
5151

5252
--------------------------------------------------------------------------------
5353
-- ** Language features
@@ -177,12 +177,12 @@ instance PPL.Pretty JVMPointsTo where
177177
--------------------------------------------------------------------------------
178178
-- *** JVMCrucibleContext
179179

180-
type instance MS.Codebase CJ.JVM = CB.Codebase
180+
type instance MS.Codebase CJ.JVM = Codebase
181181

182182
data JVMCrucibleContext =
183183
JVMCrucibleContext
184184
{ _jccJVMClass :: J.Class
185-
, _jccCodebase :: CB.Codebase
185+
, _jccCodebase :: Codebase
186186
, _jccJVMContext :: CJ.JVMContext
187187
, _jccBackend :: Sym -- This is stored inside field _ctxSymInterface of Crucible.SimContext; why do we need another one?
188188
, _jccHandleAllocator :: Crucible.HandleAllocator
@@ -195,7 +195,7 @@ type instance MS.CrucibleContext CJ.JVM = JVMCrucibleContext
195195
--------------------------------------------------------------------------------
196196

197197
initialDefCrucibleMethodSpecIR ::
198-
CB.Codebase ->
198+
Codebase ->
199199
J.ClassName ->
200200
J.Method ->
201201
ProgramLoc ->

src/SAWScript/Interpreter.hs

+2-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import SAWScript.AST (Located(..),Import(..))
5050
import SAWScript.Builtins
5151
import SAWScript.Exceptions (failTypecheck)
5252
import qualified SAWScript.Import
53+
import SAWScript.JavaCodebase (loadCodebase)
5354
import SAWScript.JavaExpr
5455
import SAWScript.LLVMBuiltins
5556
import SAWScript.Options
@@ -70,8 +71,6 @@ import Verifier.SAW.TypedAST
7071
import Verifier.SAW.TypedTerm
7172
import qualified Verifier.SAW.CryptolEnv as CEnv
7273

73-
import qualified Lang.JVM.Codebase as JCB
74-
7574
import qualified Verifier.SAW.Cryptol.Prelude as CryptolSAW
7675

7776
-- Crucible
@@ -418,7 +417,7 @@ buildTopLevelEnv proxy opts =
418417
simps <- scSimpset sc0 cryptolDefs [] convs
419418
let sc = rewritingSharedContext sc0 simps
420419
ss <- basic_ss sc
421-
jcb <- JCB.loadCodebase (jarList opts) (classPath opts)
420+
jcb <- loadCodebase (jarList opts) (classPath opts) (javaBinDirs opts)
422421
currDir <- getCurrentDirectory
423422
Crucible.withHandleAllocator $ \halloc -> do
424423
let ro0 = TopLevelRO
@@ -433,7 +432,6 @@ buildTopLevelEnv proxy opts =
433432
}
434433
let bic = BuiltinContext {
435434
biSharedContext = sc
436-
, biJavaCodebase = jcb
437435
, biBasicSS = ss
438436
}
439437
primsAvail = Set.fromList [Current]

0 commit comments

Comments
 (0)