Remove flexdis86 dependency; use macaw-x86

This commit is contained in:
Joe Hendrix 2017-05-04 16:17:51 -07:00
parent 6e10aaa447
commit 88c4017c3f
No known key found for this signature in database
GPG Key ID: 00F67DE32381DB9F
4 changed files with 8 additions and 151 deletions

View File

@ -1,4 +1,9 @@
The macaw library implements architecture-independent binary code discovery. Support for specific architectures is provided by implementing the semantics of that architecture. The library is written in terms of an abstract interface to memory, for which an ELF backend is provided (via the elf-edit_ library). There is also a dependency on flexdis86_, which is an x86_64 disassembler, but that does not tie the discovery algorithm to x86_64. The basic code discovery is based on a variant of Value Set Analysis (VSA).
The macaw library implements architecture-independent binary code
discovery. Support for specific architectures is provided by
implementing the semantics of that architecture. The library is
written in terms of an abstract interface to memory, for which an ELF
backend is provided (via the elf-edit_ library). The basic code
discovery is based on a variant of Value Set Analysis (VSA).
The most important user-facing abstractions are:
@ -7,6 +12,8 @@ The most important user-facing abstractions are:
* The ``cfgFromAddrs`` function, defined in ``Data.Macaw.Discovery``, which performs code discovery on a ``Memory`` given some initial parameters (semantics to use via ``ArchitectureInfo`` and some entry points.
* The ``DiscoveryInfo`` type, which is the result of ``cfgFromAddrs``; it contains a collection of ``DiscoveryFunInfo`` records, each of which represents a discovered function. Every basic block is assigned to at least one function.
Architecture-specific code goes into separate libraries. X86-specific code is in the macaw-x86 repo.
An abbreviated example of using macaw on an ELF file looks like::
import qualified Data.Map as M

View File

@ -13,7 +13,6 @@ library
bytestring,
containers >= 0.5.8.1,
elf-edit >= 0.28,
flexdis86 >= 0.1.1,
galois-dwarf,
IntervalMap >= 0.5,
lens >= 4.7,
@ -39,7 +38,6 @@ library
Data.Macaw.Dwarf
Data.Macaw.Memory
Data.Macaw.Memory.ElfLoader
Data.Macaw.Memory.Flexdis86
Data.Macaw.Memory.Permissions
Data.Macaw.Types

View File

@ -1,136 +0,0 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Macaw.Memory.Flexdis86
( MemoryByteReader
, runMemoryByteReader
, readInstruction
) where
import Control.Lens
import Control.Monad.Except
import Control.Monad.State.Strict
import qualified Data.ByteString as BS
import Data.Word
import Data.Macaw.Memory
import qualified Data.Macaw.Memory.Permissions as Perm
import qualified Flexdis86 as Flexdis
import Flexdis86.ByteReader
------------------------------------------------------------------------
-- MemStream
data PrevData w = PrevData { prevBytes :: [Word8]
, prevRanges :: [SegmentRange w]
}
emptyPrevData :: PrevData w
emptyPrevData = PrevData { prevBytes = [], prevRanges = [] }
consByte :: Word8 -> PrevData w -> PrevData w
consByte w pd = pd { prevBytes = w:prevBytes pd
}
prevSegments :: PrevData w -> [SegmentRange w]
prevSegments pd | null (prevBytes pd) = reverse (prevRanges pd)
| otherwise = reverse (prevRanges pd) ++ [ByteRegion (BS.pack (prevBytes pd))]
-- | A stream of memory
data MemStream w = MS { msSegment :: !(MemSegment w)
-- ^ The current segment
, msStart :: !(MemWord w)
-- ^ The initial offset for the stream.
, msPrev :: !(PrevData w)
-- ^ The values read so far.
, msOffset :: !(MemWord w)
-- ^ The current address
, msNext :: ![SegmentRange w]
-- ^ The next bytes to read.
}
msStartAddr :: MemStream w -> SegmentedAddr w
msStartAddr ms = SegmentedAddr (msSegment ms) (msStart ms)
msAddr :: MemStream w -> SegmentedAddr w
msAddr ms = SegmentedAddr (msSegment ms) (msOffset ms)
------------------------------------------------------------------------
-- MemoryByteReader
newtype MemoryByteReader w a = MBR { unMBR :: ExceptT (MemoryError w) (State (MemStream w)) a }
deriving (Functor, Applicative, MonadError (MemoryError w))
instance Monad (MemoryByteReader w) where
return = MBR . return
MBR m >>= f = MBR $ m >>= unMBR . f
fail msg = do
addr <- MBR $ gets msAddr
throwError $ UserMemoryError addr msg
-- | Create a memory stream pointing to given address, and return pair whose
-- first element is the value read or an error, and whose second element is
-- the address of the next value to read.
runMemoryByteReader :: Integral (MemWord w)
=> Perm.Flags
-- ^ Permissions that memory accesses are expected to
-- satisfy.
-- Added so we can check for read and/or execute permission.
-> Memory w -- ^ Memory to read from.
-> SegmentedAddr w -- ^ Starting address.
-> MemoryByteReader w a -- ^ Byte reader to read values from.
-> Either (MemoryError w) (a, SegmentedAddr w)
runMemoryByteReader reqPerm _mem addr (MBR m) = do
let seg = addrSegment addr
if not (segmentFlags seg `Perm.hasPerm` reqPerm) then
Left $ PermissionsError addr
else do
contents <- addrContentsAfter addr
let ms0 = MS { msSegment = seg
, msStart = addr^.addrOffset
, msPrev = emptyPrevData
, msOffset = addr^.addrOffset
, msNext = contents
}
case runState (runExceptT m) ms0 of
(Left e, _) -> Left e
(Right v, s) -> Right (v, msAddr s)
instance Num (MemWord w) => ByteReader (MemoryByteReader w) where
readByte = do
ms <- MBR get
-- If remaining bytes are empty
case msNext ms of
[] ->
MBR $ throwError $ AccessViolation (msAddr ms)
RelocatableAddr{}:_ -> do
MBR $ throwError $ UnalignedRelocation (msAddr ms)
-- Throw error if we try to read a relocation as a symbolic reference
SymbolicRef{}:_ -> do
MBR $ throwError $ UnalignedRelocation (msAddr ms)
ByteRegion bs:rest -> do
if BS.null bs then do
throwError $ AccessViolation (msAddr ms)
else do
let v = BS.head bs
let ms' = ms { msPrev = consByte v (msPrev ms)
, msOffset = msOffset ms + 1
, msNext = ByteRegion (BS.tail bs) : rest
}
MBR $ v <$ put ms'
invalidInstruction = do
ms <- MBR $ get
throwError $ InvalidInstruction (msStartAddr ms) (prevSegments (msPrev ms))
------------------------------------------------------------------------
-- readInstruction
-- | Read instruction at a given memory address.
readInstruction :: Memory 64 -- Memory to read.
-> SegmentedAddr 64 -- Address to read from.
-> Either (MemoryError 64)
(Flexdis.InstructionInstance, SegmentedAddr 64)
readInstruction mem addr = runMemoryByteReader Perm.execute mem addr m
where m = Flexdis.disassembleInstruction

View File

@ -1,12 +0,0 @@
flags: {}
packages:
- '.'
- 'deps/elf-edit'
- 'deps/flexdis86'
- 'deps/galois-dwarf'
- 'deps/parameterized-utils'
extra-deps:
- containers-0.5.8.1
- kan-extensions-5.0.1
- lens-4.15.1
resolver: lts-6.23