diff options
author | Simon Marlow <marlowsd@gmail.com> | 2008-05-28 12:52:58 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2008-05-28 12:52:58 +0000 |
commit | 526c3af1dc98987b6949f4df73c0debccf9875bd (patch) | |
tree | e9dd06d73e2f4281cec06d1f46ae63f1063799e6 /compiler/utils/Fingerprint.hsc | |
parent | 842e9d6628a27cf1f420d53f6a5901935dc50c54 (diff) | |
download | haskell-526c3af1dc98987b6949f4df73c0debccf9875bd.tar.gz |
Use MD5 checksums for recompilation checking (fixes #1372, #1959)
This is a much more robust way to do recompilation checking. The idea
is to create a fingerprint of the ABI of an interface, and track
dependencies by recording the fingerprints of ABIs that a module
depends on. If any of those ABIs have changed, then we need to
recompile.
In bug #1372 we weren't recording dependencies on package modules,
this patch fixes that by recording fingerprints of package modules
that we depend on. Within a package there is still fine-grained
recompilation avoidance as before.
We currently use MD5 for fingerprints, being a good compromise between
efficiency and security. We're not worried about attackers, but we
are worried about accidental collisions.
All the MD5 sums do make interface files a bit bigger, but compile
times on the whole are about the same as before. Recompilation
avoidance should be a bit more accurate than in 6.8.2 due to fixing
#1959, especially when using -O.
Diffstat (limited to 'compiler/utils/Fingerprint.hsc')
-rw-r--r-- | compiler/utils/Fingerprint.hsc | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/compiler/utils/Fingerprint.hsc b/compiler/utils/Fingerprint.hsc new file mode 100644 index 0000000000..d5a2409a26 --- /dev/null +++ b/compiler/utils/Fingerprint.hsc @@ -0,0 +1,77 @@ +-- ---------------------------------------------------------------------------- +-- +-- (c) The University of Glasgow 2006 +-- +-- Fingerprints for recompilation checking and ABI versioning. +-- +-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance +-- +-- ---------------------------------------------------------------------------- + +module Fingerprint ( + Fingerprint(..), fingerprint0, + readHexFingerprint, + fingerprintData + ) where + +#include "md5.h" +##include "HsVersions.h" + +import Outputable + +import Foreign +import Foreign.C +import Text.Printf +import Data.Word +import Numeric ( readHex ) + +-- Using 128-bit MD5 fingerprints for now. + +data Fingerprint = Fingerprint {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 + deriving (Eq, Ord) + -- or ByteString? + +fingerprint0 :: Fingerprint +fingerprint0 = Fingerprint 0 0 + +instance Outputable Fingerprint where + ppr (Fingerprint w1 w2) = text (printf "%016x%016x" w1 w2) + +-- useful for parsing the output of 'md5sum', should we want to do that. +readHexFingerprint :: String -> Fingerprint +readHexFingerprint s = Fingerprint w1 w2 + where (s1,s2) = splitAt 16 s + [(w1,"")] = readHex s1 + [(w2,"")] = readHex (take 16 s2) + +peekFingerprint :: Ptr Word8 -> IO Fingerprint +peekFingerprint p = do + let peekW64 :: Ptr Word8 -> Int -> Word64 -> IO Word64 + STRICT3(peekW64) + peekW64 _ 0 i = return i + peekW64 p n i = do + w8 <- peek p + peekW64 (p `plusPtr` 1) (n-1) + ((i `shiftL` 8) .|. fromIntegral w8) + + high <- peekW64 p 8 0 + low <- peekW64 (p `plusPtr` 8) 8 0 + return (Fingerprint high low) + +fingerprintData :: Ptr Word8 -> Int -> IO Fingerprint +fingerprintData buf len = do + allocaBytes (#const sizeof(struct MD5Context)) $ \pctxt -> do + c_MD5Init pctxt + c_MD5Update pctxt buf (fromIntegral len) + allocaBytes 16 $ \pdigest -> do + c_MD5Final pdigest pctxt + peekFingerprint (castPtr pdigest) + +data MD5Context + +foreign import ccall unsafe "MD5Init" + c_MD5Init :: Ptr MD5Context -> IO () +foreign import ccall unsafe "MD5Update" + c_MD5Update :: Ptr MD5Context -> Ptr Word8 -> CInt -> IO () +foreign import ccall unsafe "MD5Final" + c_MD5Final :: Ptr Word8 -> Ptr MD5Context -> IO () |