mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-12-28 08:34:23 +03:00
Rename Memory exports.
This update renames many of the declarations exported by Data.Macaw.Memory so that we have more consistent names. The majority of the existing names are now exported with DEPRECATION warnings. Some of the symbol declarations that were not used by the Memory datatype have been moved to other modules. The minor version of macaw-base has been incremented.
This commit is contained in:
parent
8b0c58c661
commit
c886c19b03
@ -1,5 +1,5 @@
|
||||
name: macaw-base
|
||||
version: 0.3.1
|
||||
version: 0.3.2
|
||||
author: Galois, Inc.
|
||||
maintainer: jhendrix@galois.com
|
||||
build-type: Simple
|
||||
@ -72,6 +72,7 @@ library
|
||||
Data.Macaw.Memory.ElfLoader
|
||||
Data.Macaw.Memory.LoadCommon
|
||||
Data.Macaw.Memory.Permissions
|
||||
Data.Macaw.Memory.Symbols
|
||||
Data.Macaw.SCFG
|
||||
Data.Macaw.Types
|
||||
Data.Macaw.Utils.Pretty
|
||||
|
@ -180,7 +180,7 @@ partitionAbsoluteAddrs :: MemWidth w
|
||||
partitionAbsoluteAddrs addrSet b = foldl' f (s0, Set.empty) addrSet
|
||||
where s0 = if b then Set.singleton 0 else Set.empty
|
||||
f (intSet,badSet) addr =
|
||||
case msegAddr addr of
|
||||
case segoffAsAbsoluteAddr addr of
|
||||
Just addrVal -> seq intSet' $ (intSet', badSet)
|
||||
where intSet' = Set.insert (toInteger addrVal) intSet
|
||||
Nothing -> seq badSet' $ (intSet, badSet')
|
||||
@ -201,7 +201,7 @@ asFinSet nm (CodePointers addrSet b) = go (Set.toList addrSet) $! s0
|
||||
go :: [MemSegmentOff w] -> Set Integer -> SomeFinSet (BVType w)
|
||||
go [] s = debug DAbsInt ("dropping Codeptr " ++ nm) $ IsFin s
|
||||
go (seg_off: r) s =
|
||||
case msegAddr seg_off of
|
||||
case segoffAsAbsoluteAddr seg_off of
|
||||
Just addr -> go r $! Set.insert (toInteger addr) s
|
||||
Nothing -> NotFin
|
||||
asFinSet _ _ = NotFin
|
||||
@ -278,7 +278,7 @@ concretize (FinSet s) = Just s
|
||||
concretize (CodePointers s b) = Just $ Set.fromList $
|
||||
[ toInteger addr
|
||||
| mseg <- Set.toList s
|
||||
, addr <- maybeToList (msegAddr mseg)
|
||||
, addr <- maybeToList (segoffAsAbsoluteAddr mseg)
|
||||
]
|
||||
++ (if b then [0] else [])
|
||||
concretize (SubValue _ _) = Nothing -- we know nothing about _all_ values
|
||||
@ -675,9 +675,9 @@ bvsbb mem w (CodePointers s b) (FinSet t) (BoolConst False)
|
||||
vals = do
|
||||
x <- Set.toList s
|
||||
y <- Set.toList t
|
||||
let z = relativeSegmentAddr x & incAddr (negate y)
|
||||
let z = segoffAddr x & incAddr (negate y)
|
||||
case asSegmentOff mem z of
|
||||
Just z_mseg | segmentFlags (msegSegment z_mseg) `Perm.hasPerm` Perm.execute ->
|
||||
Just z_mseg | segmentFlags (segoffSegment z_mseg) `Perm.hasPerm` Perm.execute ->
|
||||
pure (Just z_mseg)
|
||||
_ ->
|
||||
pure Nothing
|
||||
@ -695,7 +695,7 @@ bvsbb _ _ xv@(CodePointers xs xb) (CodePointers ys yb) (BoolConst False)
|
||||
vals = do
|
||||
x <- Set.toList xs
|
||||
y <- Set.toList ys
|
||||
pure (relativeSegmentAddr x `diffAddr` relativeSegmentAddr y)
|
||||
pure (segoffAddr x `diffAddr` segoffAddr y)
|
||||
bvsbb _ w (FinSet s) (asFinSet "bvsub3" -> IsFin t) (BoolConst b) =
|
||||
setL (stridedInterval . SI.fromFoldable w) FinSet $ do
|
||||
x <- Set.toList s
|
||||
@ -732,9 +732,9 @@ bvsub mem w (CodePointers s b) (FinSet t)
|
||||
vals = do
|
||||
x <- Set.toList s
|
||||
y <- Set.toList t
|
||||
let z = relativeSegmentAddr x & incAddr (negate y)
|
||||
let z = segoffAddr x & incAddr (negate y)
|
||||
case asSegmentOff mem z of
|
||||
Just z_mseg | segmentFlags (msegSegment z_mseg) `Perm.hasPerm` Perm.execute ->
|
||||
Just z_mseg | segmentFlags (segoffSegment z_mseg) `Perm.hasPerm` Perm.execute ->
|
||||
pure (Just z_mseg)
|
||||
_ ->
|
||||
pure Nothing
|
||||
@ -752,7 +752,7 @@ bvsub _ _ xv@(CodePointers xs xb) (CodePointers ys yb)
|
||||
vals = do
|
||||
x <- Set.toList xs
|
||||
y <- Set.toList ys
|
||||
pure (relativeSegmentAddr x `diffAddr` relativeSegmentAddr y)
|
||||
pure (segoffAddr x `diffAddr` segoffAddr y)
|
||||
bvsub _ w (FinSet s) (asFinSet "bvsub3" -> IsFin t) =
|
||||
setL (stridedInterval . SI.fromFoldable w) FinSet $ do
|
||||
x <- Set.toList s
|
||||
@ -852,7 +852,7 @@ abstractSingleton mem w i
|
||||
| Just Refl <- testEquality w (memWidth mem)
|
||||
, 0 <= i && i <= maxUnsigned w
|
||||
, Just sa <- resolveAbsoluteAddr mem (fromInteger i)
|
||||
, segmentFlags (msegSegment sa) `Perm.hasPerm` Perm.execute =
|
||||
, segmentFlags (segoffSegment sa) `Perm.hasPerm` Perm.execute =
|
||||
CodePointers (Set.singleton sa) False
|
||||
| 0 <= i && i <= maxUnsigned w = FinSet (Set.singleton i)
|
||||
| otherwise = error $ "abstractSingleton given bad value: " ++ show i ++ " " ++ show w
|
||||
@ -1209,7 +1209,7 @@ transferValue c v = do
|
||||
-- TODO: Ensure a relocatable value is in code.
|
||||
RelocatableValue _w i
|
||||
| Just addr <- asSegmentOff (absMem c) i
|
||||
, segmentFlags (msegSegment addr) `Perm.hasPerm` Perm.execute ->
|
||||
, segmentFlags (segoffSegment addr) `Perm.hasPerm` Perm.execute ->
|
||||
CodePointers (Set.singleton addr) False
|
||||
| Just addr <- asAbsoluteAddr i ->
|
||||
FinSet $ Set.singleton $ toInteger addr
|
||||
|
@ -608,7 +608,7 @@ rewriteValue v =
|
||||
case sym of
|
||||
SectionIdentifier secIdx
|
||||
| Just val <- Map.lookup secIdx secIdxAddrMap -> do
|
||||
pure $! RelocatableValue repr (relativeSegmentAddr val)
|
||||
pure $! RelocatableValue repr (segoffAddr val)
|
||||
_ -> do
|
||||
pure $! SymbolValue repr sym
|
||||
AssignedValue (Assignment aid _) -> Rewriter $ do
|
||||
|
@ -97,7 +97,7 @@ import Data.Macaw.Types
|
||||
|
||||
isExecutableSegOff :: MemSegmentOff w -> Bool
|
||||
isExecutableSegOff sa =
|
||||
segmentFlags (msegSegment sa) `Perm.hasPerm` Perm.execute
|
||||
segmentFlags (segoffSegment sa) `Perm.hasPerm` Perm.execute
|
||||
|
||||
-- | Get code pointers out of a abstract value.
|
||||
identifyConcreteAddresses :: MemWidth w
|
||||
@ -251,14 +251,14 @@ dropUnusedCodeInParsedBlock ainfo b =
|
||||
sliceMemContents'
|
||||
:: MemWidth w
|
||||
=> Int -- ^ Number of bytes in each slice.
|
||||
-> [[SegmentRange w]] -- ^ Previous slices
|
||||
-> [[MemChunk w]] -- ^ Previous slices
|
||||
-> Integer -- ^ Number of slices to return
|
||||
-> [SegmentRange w] -- ^ Ranges to process next
|
||||
-> Either (DropError w) ([[SegmentRange w]],[SegmentRange w])
|
||||
-> [MemChunk w] -- ^ Ranges to process next
|
||||
-> Either (SplitError w) ([[MemChunk w]],[MemChunk w])
|
||||
sliceMemContents' stride prev c next
|
||||
| c <= 0 = pure (reverse prev, next)
|
||||
| otherwise =
|
||||
case splitSegmentRangeList next stride of
|
||||
case splitMemChunks next stride of
|
||||
Left e -> Left e
|
||||
Right (this, rest) -> sliceMemContents' stride (this:prev) (c-1) rest
|
||||
|
||||
@ -268,8 +268,8 @@ sliceMemContents
|
||||
:: MemWidth w
|
||||
=> Int -- ^ Number of bytes in each slice.
|
||||
-> Integer -- ^ Number of slices to return
|
||||
-> [SegmentRange w] -- ^ Ranges to process next
|
||||
-> Either (DropError w) ([[SegmentRange w]],[SegmentRange w])
|
||||
-> [MemChunk w] -- ^ Ranges to process next
|
||||
-> Either (SplitError w) ([[MemChunk w]],[MemChunk w])
|
||||
sliceMemContents stride c next = sliceMemContents' stride [] c next
|
||||
|
||||
------------------------------------------------------------------------
|
||||
@ -291,7 +291,7 @@ markAddrAsFunction rsn addr s
|
||||
| otherwise = addrWidthClass (memAddrWidth (memory s)) $
|
||||
-- We check that the function address ignores bytes so that we do
|
||||
-- not start disassembling at a relocation or BSS region.
|
||||
case contentsAfterSegmentOff addr of
|
||||
case segoffContentsAfter addr of
|
||||
Right (ByteRegion _:_) ->
|
||||
s & unexploredFunctions %~ Map.insert addr rsn
|
||||
_ -> s
|
||||
@ -458,7 +458,7 @@ data BoundedMemArray arch tp = BoundedMemArray
|
||||
-- if stride is less than the number of bytes read.
|
||||
, arEltType :: !(MemRepr tp)
|
||||
-- ^ Resolved type of elements in this array.
|
||||
, arSlices :: !(V.Vector [SegmentRange (ArchAddrWidth arch)])
|
||||
, arSlices :: !(V.Vector [MemChunk (ArchAddrWidth arch)])
|
||||
-- ^ The slices of memory in the array.
|
||||
--
|
||||
-- The `i`th element in the vector corresponds to the first `size`
|
||||
@ -473,7 +473,7 @@ deriving instance RegisterInfo (ArchReg arch) => Show (BoundedMemArray arch tp)
|
||||
|
||||
-- | Return true if the address stored is readable and not writable.
|
||||
isReadOnlyBoundedMemArray :: BoundedMemArray arch tp -> Bool
|
||||
isReadOnlyBoundedMemArray = Perm.isReadonly . segmentFlags . msegSegment . arBase
|
||||
isReadOnlyBoundedMemArray = Perm.isReadonly . segmentFlags . segoffSegment . arBase
|
||||
|
||||
absValueAsSegmentOff
|
||||
:: forall w
|
||||
@ -543,13 +543,13 @@ matchBoundedMemArray mem aps val
|
||||
<- Jmp.unsignedUpperBound (aps^.indexBounds) ixVal
|
||||
, cnt <- bnd+1
|
||||
-- Check array actually fits in memory.
|
||||
, cnt * toInteger stride <= msegByteCountAfter base
|
||||
, cnt * toInteger stride <= segoffBytesLeft base
|
||||
-- Get memory contents after base
|
||||
, Right contents <- contentsAfterSegmentOff base
|
||||
, Right contents <- segoffContentsAfter base
|
||||
-- Break up contents into a list of slices each with size stide
|
||||
, Right (strideSlices,_) <- sliceMemContents (fromInteger stride) cnt contents
|
||||
-- Take the given number of bytes out of each slices
|
||||
, Right slices <- traverse (\s -> fst <$> splitSegmentRangeList s (fromInteger (memReprBytes tp)))
|
||||
, Right slices <- traverse (\s -> fst <$> splitMemChunks s (fromInteger (memReprBytes tp)))
|
||||
(V.fromList strideSlices)
|
||||
= let r = BoundedMemArray
|
||||
{ arBase = base
|
||||
@ -637,7 +637,7 @@ deriving instance RegisterInfo (ArchReg arch) => Show (JumpTableLayout arch)
|
||||
resolveAsAbsoluteAddr :: forall w
|
||||
. Memory w
|
||||
-> Endianness
|
||||
-> [SegmentRange w]
|
||||
-> [MemChunk w]
|
||||
-> Maybe (MemAddr w)
|
||||
resolveAsAbsoluteAddr mem endianness l = addrWidthClass (memAddrWidth mem) $
|
||||
case l of
|
||||
@ -648,11 +648,11 @@ resolveAsAbsoluteAddr mem endianness l = addrWidthClass (memAddrWidth mem) $
|
||||
case relocationSym r of
|
||||
SymbolRelocation{} -> Nothing
|
||||
SectionIdentifier idx -> do
|
||||
addr <- Map.lookup idx (memSectionAddrMap mem)
|
||||
pure $ relativeSegmentAddr addr & incAddr (toInteger (relocationOffset r))
|
||||
addr <- Map.lookup idx (memSectionIndexMap mem)
|
||||
pure $! segoffAddr addr & incAddr (toInteger (relocationOffset r))
|
||||
SegmentBaseAddr idx -> do
|
||||
addr <- Map.lookup idx (memSegmentAddrMap mem)
|
||||
pure $ relativeSegmentAddr addr & incAddr (toInteger (relocationOffset r))
|
||||
seg <- Map.lookup idx (memSegmentIndexMap mem)
|
||||
pure $! segmentOffAddr seg (relocationOffset r)
|
||||
_ -> Nothing
|
||||
|
||||
-- This function resolves jump table entries.
|
||||
@ -677,10 +677,10 @@ resolveRelativeJumps mem base arrayRead ext = do
|
||||
forM slices $ \l -> do
|
||||
case l of
|
||||
[ByteRegion bs]
|
||||
| tgtAddr <- relativeSegmentAddr base
|
||||
| tgtAddr <- segoffAddr base
|
||||
& incAddr (extendDyn ext endianness bs)
|
||||
, Just tgt <- asSegmentOff mem (toIPAligned @arch tgtAddr)
|
||||
, Perm.isExecutable (segmentFlags (msegSegment tgt))
|
||||
, Perm.isExecutable (segmentFlags (segoffSegment tgt))
|
||||
-> Just tgt
|
||||
_ -> Nothing
|
||||
|
||||
@ -700,11 +700,11 @@ matchJumpTableRef mem aps ip
|
||||
| Just (arrayRead,idx) <- matchBoundedMemArray mem aps ip
|
||||
, isReadOnlyBoundedMemArray arrayRead
|
||||
, BVMemRepr _arByteCount endianness <- arEltType arrayRead = do
|
||||
let go :: [SegmentRange (ArchAddrWidth arch)] -> Maybe (MemSegmentOff (ArchAddrWidth arch))
|
||||
let go :: [MemChunk (ArchAddrWidth arch)] -> Maybe (MemSegmentOff (ArchAddrWidth arch))
|
||||
go contents = do
|
||||
addr <- resolveAsAbsoluteAddr mem endianness contents
|
||||
tgt <- asSegmentOff mem (toIPAligned @arch addr)
|
||||
unless (Perm.isExecutable (segmentFlags (msegSegment tgt))) $ Nothing
|
||||
unless (Perm.isExecutable (segmentFlags (segoffSegment tgt))) $ Nothing
|
||||
pure tgt
|
||||
tbl <- traverse go (arSlices arrayRead)
|
||||
pure (AbsoluteJumpTable arrayRead, tbl, idx)
|
||||
@ -913,7 +913,7 @@ parseFetchAndExecute ctx idx stmts regs s = do
|
||||
-- Jump to a block within this function.
|
||||
| Just tgt_mseg <- valueAsSegmentOff mem (s^.boundValue ip_reg)
|
||||
-- Check
|
||||
, segmentFlags (msegSegment tgt_mseg) `Perm.hasPerm` Perm.execute
|
||||
, segmentFlags (segoffSegment tgt_mseg) `Perm.hasPerm` Perm.execute
|
||||
|
||||
-- Check the target address is not the entry point of this function.
|
||||
-- N.B. These should instead decompile into calls or tail calls.
|
||||
@ -1142,20 +1142,18 @@ transfer addr = do
|
||||
nonceGen <- gets funNonceGen
|
||||
prev_block_map <- use $ curFunBlocks
|
||||
-- Get maximum number of bytes to disassemble
|
||||
let seg = msegSegment addr
|
||||
off = msegOffset addr
|
||||
let maxSize :: Int
|
||||
maxSize =
|
||||
case Map.lookupGT addr prev_block_map of
|
||||
Just (next,_) | Just o <- diffSegmentOff next addr -> fromInteger o
|
||||
_ -> fromIntegral $ segmentSize seg - off
|
||||
_ -> fromInteger (segoffBytesLeft addr)
|
||||
let ab = foundAbstractState finfo
|
||||
(bs0, sz, maybeError) <- liftST $ disassembleFn ainfo nonceGen addr maxSize ab
|
||||
|
||||
#ifdef USE_REWRITER
|
||||
bs1 <- do
|
||||
let archStmt = rewriteArchStmt ainfo
|
||||
let secAddrMap = memSectionAddrMap mem
|
||||
let secAddrMap = memSectionIndexMap mem
|
||||
liftST $ do
|
||||
ctx <- mkRewriteContext nonceGen (rewriteArchFn ainfo) archStmt secAddrMap
|
||||
traverse (rewriteBlock ainfo ctx) bs0
|
||||
@ -1291,8 +1289,8 @@ analyzeDiscoveredFunctions info =
|
||||
-- | This returns true if the address is writable and value is executable.
|
||||
isDataCodePointer :: MemSegmentOff w -> MemSegmentOff w -> Bool
|
||||
isDataCodePointer a v
|
||||
= segmentFlags (msegSegment a) `Perm.hasPerm` Perm.write
|
||||
&& segmentFlags (msegSegment v) `Perm.hasPerm` Perm.execute
|
||||
= segmentFlags (segoffSegment a) `Perm.hasPerm` Perm.write
|
||||
&& segmentFlags (segoffSegment v) `Perm.hasPerm` Perm.execute
|
||||
|
||||
addMemCodePointer :: (ArchSegmentOff arch, ArchSegmentOff arch)
|
||||
-> DiscoveryState arch
|
||||
|
@ -23,6 +23,7 @@ module Data.Macaw.Discovery.State
|
||||
, ParsedBlock(..)
|
||||
-- * The interpreter state
|
||||
, DiscoveryState
|
||||
, AddrSymMap
|
||||
, exploredFunctions
|
||||
, ppDiscoveryStateBlocks
|
||||
, emptyDiscoveryState
|
||||
@ -62,6 +63,12 @@ import Data.Macaw.Architecture.Info
|
||||
import Data.Macaw.CFG
|
||||
import Data.Macaw.Types
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- AddrSymMap
|
||||
|
||||
-- | Maps code addresses to the associated symbol name if any.
|
||||
type AddrSymMap w = Map.Map (MemSegmentOff w) BSC.ByteString
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- BlockExploreReason
|
||||
|
||||
@ -248,7 +255,7 @@ instance ArchConstraints arch
|
||||
=> Pretty (ParsedBlock arch ids) where
|
||||
pretty b =
|
||||
let sl = blockStatementList b
|
||||
ppOff o = text (show (incAddr (toInteger o) (relativeSegmentAddr (pblockAddr b))))
|
||||
ppOff o = text (show (incAddr (toInteger o) (segoffAddr (pblockAddr b))))
|
||||
in text (show (pblockAddr b)) PP.<> text ":" <$$>
|
||||
indent 2 (vcat (ppStmt ppOff <$> stmtsNonterm sl) <$$> ppTermStmt ppOff (stmtsTerm sl))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,15 +25,19 @@ module Data.Macaw.Memory.ElfLoader
|
||||
, resolveElfFuncSymbolsAny
|
||||
, resolveElfContents
|
||||
, elfAddrWidth
|
||||
-- * Symbols
|
||||
, MemSymbol(..)
|
||||
-- * Re-exports
|
||||
, module Data.Macaw.Memory.LoadCommon
|
||||
, module Data.Macaw.Memory
|
||||
, module Data.Macaw.Memory.Symbols
|
||||
) where
|
||||
|
||||
import Control.Lens
|
||||
import Control.Monad.Except
|
||||
import Control.Monad.State.Strict
|
||||
import Data.Bits
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Char8 as BSC
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import Data.Either
|
||||
@ -69,7 +73,6 @@ import Data.Map.Strict (Map)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Data.Maybe
|
||||
import Data.Monoid
|
||||
import Data.Parameterized.Some
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import qualified Data.Vector as V
|
||||
@ -80,6 +83,7 @@ import Data.Int
|
||||
import Data.Macaw.Memory
|
||||
import Data.Macaw.Memory.LoadCommon
|
||||
import qualified Data.Macaw.Memory.Permissions as Perm
|
||||
import Data.Macaw.Memory.Symbols
|
||||
|
||||
-- | Return a subrange of a bytestring.
|
||||
sliceL :: Integral w => Elf.Range w -> L.ByteString -> L.ByteString
|
||||
@ -122,7 +126,6 @@ flagsForSectionFlags f =
|
||||
where flagIf :: ElfSectionFlags w -> Perm.Flags -> Perm.Flags
|
||||
flagIf ef pf = if f `Elf.hasPermissions` ef then pf else Perm.none
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- RelocationError
|
||||
|
||||
@ -144,7 +147,7 @@ instance Show RelocationError where
|
||||
show (RelocationBadSymbolIndex idx) =
|
||||
"A relocation entry referred to invalid symbol index " ++ show idx ++ "."
|
||||
show (RelocationUnsupportedType tp) =
|
||||
"Do not yet support relocation type " ++ tp ++ "."
|
||||
"Unsupported relocation type " ++ tp ++ "."
|
||||
show RelocationFileUnsupported =
|
||||
"Do not support relocations referring to file entry."
|
||||
show (RelocationInvalidAddend tp v) =
|
||||
@ -153,7 +156,7 @@ instance Show RelocationError where
|
||||
------------------------------------------------------------------------
|
||||
-- MemLoader
|
||||
|
||||
type SectionName = B.ByteString
|
||||
type SectionName = BS.ByteString
|
||||
|
||||
data MemLoadWarning
|
||||
= SectionNotAlloc !SectionName
|
||||
@ -164,7 +167,7 @@ data MemLoadWarning
|
||||
| DynamicRelaAndRelPresent
|
||||
-- ^ Issued if the dynamic section contains table for DT_REL and
|
||||
-- DT_RELA.
|
||||
| SectionRelaAndRelPresent !B.ByteString
|
||||
| SectionRelaAndRelPresent !BS.ByteString
|
||||
-- ^ @SectionRelaAndRelPresent nm@ is issued if we encounter
|
||||
-- both section ".rela$nm" and ".rel$nm".
|
||||
| UnsupportedSection !SectionName
|
||||
@ -298,10 +301,7 @@ type ElfFileSectionMap v = IntervalMap v (ElfSection v)
|
||||
-- This drops the first symbol in Elf since that refers to no symbol
|
||||
newtype SymbolTable = SymbolTable (V.Vector SymbolInfo)
|
||||
|
||||
-- | Monad to use for reporting relocation failures.
|
||||
type RelocResolver = Either RelocationError
|
||||
|
||||
relocError :: RelocationError -> RelocResolver a
|
||||
relocError :: RelocationError -> Either RelocationError a
|
||||
relocError = Left
|
||||
|
||||
-- | Attempts to resolve a relocation entry into a specific target.
|
||||
@ -310,7 +310,7 @@ resolveSymbol :: SymbolTable
|
||||
-- associated symbol information.
|
||||
-> Word32
|
||||
-- ^ Offset of symbol
|
||||
-> RelocResolver SymbolInfo
|
||||
-> Either RelocationError SymbolInfo
|
||||
resolveSymbol (SymbolTable symtab) symIdx = do
|
||||
when (symIdx == 0) $
|
||||
relocError RelocationZeroSymbol
|
||||
@ -319,16 +319,26 @@ resolveSymbol (SymbolTable symtab) symIdx = do
|
||||
relocError $ RelocationBadSymbolIndex $ fromIntegral symIdx
|
||||
Just sym -> pure sym
|
||||
|
||||
data RelFlag = IsRel | IsRela
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
-- | A function that resolves the architecture-specific relocation-type
|
||||
-- into a symbol reference. The input
|
||||
type RelocationResolver tp
|
||||
= Maybe SegmentIndex
|
||||
-- ^ Index of segment index if this is a dynamic relocation.
|
||||
-- ^ Index of segment in which this relocation will be applied if this is
|
||||
-- a dynamic relocation, and `Nothing` otherwise.
|
||||
-> SymbolTable
|
||||
-> Elf.RelEntry tp
|
||||
-- ^ Relocation information
|
||||
-> MemWord (Elf.RelocationWidth tp)
|
||||
-- ^ Addend to add to symbol.
|
||||
-> RelocResolver (Relocation (Elf.RelocationWidth tp))
|
||||
-> RelFlag
|
||||
-- ^ Flag to indicate if this is a rela and rel relocation
|
||||
--
|
||||
-- Added because some relocations (i.e. PLT ones) will ignore
|
||||
-- Rel relocation addends.
|
||||
-> Either RelocationError (Relocation (Elf.RelocationWidth tp))
|
||||
|
||||
data SomeRelocationResolver w
|
||||
= forall tp
|
||||
@ -342,17 +352,17 @@ resolveRelocationSym :: SymbolTable
|
||||
-- associated symbol information.
|
||||
-> Word32
|
||||
-- ^ Index in the symbol table this refers to.
|
||||
-> RelocResolver SymbolIdentifier
|
||||
-> Either RelocationError SymbolIdentifier
|
||||
resolveRelocationSym symtab symIdx = do
|
||||
sym <- resolveSymbol symtab symIdx
|
||||
case symbolDef sym of
|
||||
DefinedSymbol{} ->
|
||||
DefinedSymbol{} ->
|
||||
pure $ SymbolRelocation (symbolName sym) (symbolVersion sym)
|
||||
SymbolSection idx ->
|
||||
SymbolSection idx ->
|
||||
pure $ SectionIdentifier idx
|
||||
SymbolFile _ ->
|
||||
SymbolFile _ ->
|
||||
relocError RelocationFileUnsupported
|
||||
UndefinedSymbol{} ->
|
||||
UndefinedSymbol{} ->
|
||||
pure $ SymbolRelocation (symbolName sym) (symbolVersion sym)
|
||||
|
||||
-- | Attempt to resolve an X86_64 specific symbol.
|
||||
@ -361,8 +371,9 @@ relaTargetX86_64 :: Maybe SegmentIndex
|
||||
-> Elf.RelEntry Elf.X86_64_RelocationType
|
||||
-> MemWord 64
|
||||
-- ^ Addend to add to symbol.
|
||||
-> RelocResolver (Relocation 64)
|
||||
relaTargetX86_64 _ symtab rel off =
|
||||
-> RelFlag
|
||||
-> Either RelocationError (Relocation 64)
|
||||
relaTargetX86_64 _ symtab rel off _isRel =
|
||||
case Elf.relType rel of
|
||||
Elf.R_X86_64_JUMP_SLOT -> do
|
||||
sym <- resolveRelocationSym symtab (Elf.relSym rel)
|
||||
@ -438,14 +449,16 @@ relaTargetARM :: Endianness
|
||||
-> Elf.RelEntry Elf.ARM_RelocationType -- ^ Relocaiton entry
|
||||
-> MemWord 32
|
||||
-- ^ Addend of symbol
|
||||
-> RelocResolver (Relocation 32)
|
||||
relaTargetARM end msegIndex symtab rel addend =
|
||||
-> RelFlag
|
||||
-> Either RelocationError (Relocation 32)
|
||||
relaTargetARM end msegIndex symtab rel addend relFlag =
|
||||
case Elf.relType rel of
|
||||
Elf.R_ARM_GLOB_DAT -> do
|
||||
sym <- resolveRelocationSym symtab (Elf.relSym rel)
|
||||
-- Check that addend is 0 so that we do not change thumb bit of symbol
|
||||
-- Check that least-significant bit of addend is 0 so that we do
|
||||
-- not change thumb bit of symbol.
|
||||
when (addend `testBit` 0) $ do
|
||||
relocError $RelocationInvalidAddend (show (Elf.relType rel)) (toInteger addend)
|
||||
relocError $ RelocationInvalidAddend (show (Elf.relType rel)) (toInteger addend)
|
||||
pure $! Relocation { relocationSym = sym
|
||||
, relocationOffset = addend
|
||||
, relocationIsRel = False
|
||||
@ -488,6 +501,23 @@ relaTargetARM end msegIndex symtab rel addend =
|
||||
, relocationIsSigned = False
|
||||
, relocationEndianness = end
|
||||
}
|
||||
Elf.R_ARM_JUMP_SLOT -> do
|
||||
-- This is a PLT relocation
|
||||
sym <- resolveRelocationSym symtab (Elf.relSym rel)
|
||||
let actualAddend =
|
||||
case relFlag of
|
||||
IsRel -> 0
|
||||
IsRela -> addend
|
||||
-- Check that addend is 0 so that we do not change thumb bit of symbol.
|
||||
when (actualAddend /= 0) $ do
|
||||
relocError $ RelocationInvalidAddend (show (Elf.relType rel)) (toInteger actualAddend)
|
||||
pure $! Relocation { relocationSym = sym
|
||||
, relocationOffset = actualAddend
|
||||
, relocationIsRel = False
|
||||
, relocationSize = 4
|
||||
, relocationIsSigned = False
|
||||
, relocationEndianness = end
|
||||
}
|
||||
tp -> do
|
||||
relocError $ RelocationUnsupportedType (show tp)
|
||||
|
||||
@ -497,7 +527,7 @@ toEndianness Elf.ELFDATA2MSB = BigEndian
|
||||
|
||||
-- | Creates a relocation map from the contents of a dynamic section.
|
||||
getRelocationResolver
|
||||
:: forall w
|
||||
:: forall w
|
||||
. Elf.ElfHeader w
|
||||
-> MemLoader w (SomeRelocationResolver w)
|
||||
getRelocationResolver hdr =
|
||||
@ -526,7 +556,7 @@ resolveRela :: ( MemWidth w
|
||||
-> Elf.RelaEntry tp
|
||||
-> ResolveFn (MemLoader w) w
|
||||
resolveRela symtab resolver rela msegIdx _ =
|
||||
case resolver msegIdx symtab (Elf.relaToRel rela) (fromIntegral (Elf.relaAddend rela)) of
|
||||
case resolver msegIdx symtab (Elf.relaToRel rela) (fromIntegral (Elf.relaAddend rela)) IsRela of
|
||||
Left e -> do
|
||||
addWarning (IgnoreRelocation e)
|
||||
pure Nothing
|
||||
@ -556,7 +586,7 @@ resolveRel end symtab resolver rel msegIdx bytes = do
|
||||
| otherwise =
|
||||
uaddend
|
||||
-- Update the resolver.
|
||||
case resolver msegIdx symtab rel (fromInteger saddend) of
|
||||
case resolver msegIdx symtab rel (fromInteger saddend) IsRel of
|
||||
Left e -> do
|
||||
addWarning (IgnoreRelocation e)
|
||||
pure Nothing
|
||||
@ -694,9 +724,9 @@ resolveDefinedSymbolDef sym = do
|
||||
case Elf.steType sym of
|
||||
Elf.STT_SECTION
|
||||
| idx < Elf.SHN_LOPROC -> do
|
||||
when (nm /= "") $
|
||||
when (nm /= "") $
|
||||
addWarning $ ExpectedSectionSymbolNameEmpty nm
|
||||
when (bnd /= Elf.STB_LOCAL) $
|
||||
when (bnd /= Elf.STB_LOCAL) $
|
||||
addWarning ExpectedSectionSymbolLocal
|
||||
pure $ SymbolSection (Elf.fromElfSectionIndex idx)
|
||||
| otherwise -> do
|
||||
@ -764,10 +794,10 @@ dynamicRelocationMap hdr ph contents =
|
||||
case filter (\p -> Elf.phdrSegmentType p == Elf.PT_DYNAMIC) ph of
|
||||
[] -> pure $ Map.empty
|
||||
dynPhdr:dynRest -> do
|
||||
when (not (null dynRest)) $
|
||||
when (not (null dynRest)) $
|
||||
addWarning MultipleDynamicSegments
|
||||
w <- uses mlsMemory memAddrWidth
|
||||
reprConstraints w $
|
||||
reprConstraints w $
|
||||
case Elf.virtAddrMap contents ph of
|
||||
Nothing -> do
|
||||
addWarning OverlappingLoadableSegments
|
||||
@ -842,12 +872,8 @@ memSegment relocMap regionIndex regionOff msegIdx linkBaseOff flags bytes sz
|
||||
error "Contents two large for base."
|
||||
| otherwise = do
|
||||
contents <- byteSegments relocMap msegIdx linkBaseOff bytes sz
|
||||
pure $
|
||||
MemSegment { segmentBase = regionIndex
|
||||
, segmentOffset = fromInteger regionOff + linkBaseOff
|
||||
, segmentFlags = flags
|
||||
, segmentContents = contentsFromList contents
|
||||
}
|
||||
let off = fromInteger regionOff + linkBaseOff
|
||||
pure $! mkMemSegment regionIndex off flags contents
|
||||
|
||||
-- | Load an elf file into memory.
|
||||
insertElfSegment :: RegionIndex
|
||||
@ -875,8 +901,7 @@ insertElfSegment regIdx addrOff shdrMap contents relocMap phdr = do
|
||||
let phdr_offset = Elf.fromFileOffset (Elf.phdrFileStart phdr)
|
||||
let phdr_end = phdr_offset + Elf.phdrFileSize phdr
|
||||
-- Add segment index to address mapping to memory object.
|
||||
do let Just segAddr = resolveSegmentOff seg 0
|
||||
mlsMemory %= memAddSegmentAddr segIdx segAddr
|
||||
mlsMemory %= memBindSegmentIndex segIdx seg
|
||||
-- Iterative through sections
|
||||
let l = IMap.toList $ IMap.intersecting shdrMap (IntervalCO phdr_offset phdr_end)
|
||||
forM_ l $ \(i, sec) -> do
|
||||
@ -887,7 +912,7 @@ insertElfSegment regIdx addrOff shdrMap contents relocMap phdr = do
|
||||
fail "Found section header that overlaps with program header."
|
||||
let sec_offset = fromIntegral $ shdr_start - phdr_offset
|
||||
let Just addr = resolveSegmentOff seg sec_offset
|
||||
mlsMemory %= memAddSectionAddr (fromElfSectionIndex elfIdx) addr
|
||||
mlsMemory %= memBindSectionIndex (fromElfSectionIndex elfIdx) addr
|
||||
mlsIndexMap %= Map.insert elfIdx (addr, sec)
|
||||
_ -> fail "Unexpected shdr interval"
|
||||
|
||||
@ -913,7 +938,7 @@ memoryForElfSegments regIndex addrOff e = do
|
||||
relocMap <- dynamicRelocationMap hdr ph contents
|
||||
|
||||
let intervals :: ElfFileSectionMap (ElfWordType w)
|
||||
intervals = IMap.fromList
|
||||
intervals = IMap.fromList
|
||||
[ (IntervalCO start end, sec)
|
||||
| shdr <- Map.elems (l ^. Elf.shdrs)
|
||||
, let start = shdr^._3
|
||||
@ -928,9 +953,9 @@ memoryForElfSegments regIndex addrOff e = do
|
||||
|
||||
-- | Contains the name of a section we allocate and whether
|
||||
-- relocations are used.
|
||||
type AllocatedSectionInfo = (B.ByteString, Bool)
|
||||
type AllocatedSectionInfo = (BS.ByteString, Bool)
|
||||
|
||||
allocatedNames :: AllocatedSectionInfo -> [B.ByteString]
|
||||
allocatedNames :: AllocatedSectionInfo -> [BS.ByteString]
|
||||
allocatedNames (nm,False) = [nm]
|
||||
allocatedNames (nm,True) = [nm, ".rela" <> nm]
|
||||
|
||||
@ -943,7 +968,7 @@ allocatedSectionInfo =
|
||||
, (,) ".rodata" True
|
||||
]
|
||||
|
||||
allowedSectionNames :: Set B.ByteString
|
||||
allowedSectionNames :: Set BS.ByteString
|
||||
allowedSectionNames = Set.fromList
|
||||
$ concatMap allocatedNames allocatedSectionInfo
|
||||
++ [ ""
|
||||
@ -1017,7 +1042,7 @@ insertAllocatedSection hdr symtab sectionMap regIdx nm = do
|
||||
-- Add entry to map elf section index to start in segment.
|
||||
let elfIdx = ElfSectionIndex (elfSectionIndex sec)
|
||||
let Just addr = resolveSegmentOff seg 0
|
||||
mlsMemory %= memAddSectionAddr (fromElfSectionIndex elfIdx) addr
|
||||
mlsMemory %= memBindSectionIndex (fromElfSectionIndex elfIdx) addr
|
||||
mlsIndexMap %= Map.insert elfIdx (addr, sec)
|
||||
|
||||
-- | Create the symbol vector from
|
||||
@ -1074,6 +1099,22 @@ adjustedLoadRegionIndex e loadOpt =
|
||||
Elf.ET_DYN -> 1
|
||||
_ -> 0
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Memory symbol
|
||||
|
||||
-- | Type for representing a symbol that has a defined location in
|
||||
-- this memory.
|
||||
data MemSymbol w = MemSymbol { memSymbolName :: !BS.ByteString
|
||||
-- ^ Name of symbol
|
||||
, memSymbolStart :: !(MemSegmentOff w)
|
||||
-- ^ Address that symbol starts up.
|
||||
, memSymbolSize :: !(MemWord w)
|
||||
-- ^ Size of symbol as defined in table.
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- memoryForElf
|
||||
|
||||
memoryForElf' :: ( Memory w
|
||||
-> SectionIndexMap w
|
||||
-> Elf w
|
||||
@ -1081,14 +1122,14 @@ memoryForElf' :: ( Memory w
|
||||
-> LoadOptions
|
||||
-> Elf w
|
||||
-> Either String ( Memory w
|
||||
, [MemSymbol w] -- Function symbols
|
||||
, [MemLoadWarning]
|
||||
, [SymbolResolutionError]
|
||||
)
|
||||
, [MemSymbol w] -- Function symbols
|
||||
, [MemLoadWarning]
|
||||
, [SymbolResolutionError]
|
||||
)
|
||||
memoryForElf' resolver opt e = reprConstraints (elfAddrWidth (elfClass e)) $ do
|
||||
let end = toEndianness (Elf.elfData e)
|
||||
(secMap, mem, warnings) <-
|
||||
runMemLoader end (emptyMemory (elfAddrWidth (elfClass e))) $
|
||||
runMemLoader end (emptyMemory (elfAddrWidth (elfClass e))) $
|
||||
case Elf.elfType e of
|
||||
Elf.ET_REL ->
|
||||
memoryForElfSections e
|
||||
@ -1160,7 +1201,7 @@ resolveElfSymbol mem secMap idx ste
|
||||
-- Lookup absolute symbol
|
||||
| Elf.steIndex ste == Elf.SHN_ABS = reprConstraints (memAddrWidth mem) $ do
|
||||
let val = Elf.steValue ste
|
||||
case resolveAddr mem 0 (fromIntegral val) of
|
||||
case resolveAbsoluteAddr mem (fromIntegral val) of
|
||||
Just addr -> Just $ Right $
|
||||
MemSymbol { memSymbolName = Elf.steName ste
|
||||
, memSymbolStart = addr
|
||||
@ -1227,11 +1268,11 @@ resolveElfFuncSymbolsAny mem secMap e =
|
||||
|
||||
-- | Return the segment offset of the elf file entry point or fail if undefined.
|
||||
getElfEntry :: LoadOptions -> Memory w -> Elf w -> ([String], Maybe (MemSegmentOff w))
|
||||
getElfEntry loadOpts mem e = addrWidthClass (memAddrWidth mem) $
|
||||
getElfEntry loadOpts mem e = addrWidthClass (memAddrWidth mem) $
|
||||
Elf.elfClassInstances (Elf.elfClass e) $ do
|
||||
let regIdx = adjustedLoadRegionIndex e loadOpts
|
||||
let adjAddr = loadRegionBaseOffset loadOpts + toInteger (Elf.elfEntry e)
|
||||
case resolveAddr mem regIdx (fromInteger adjAddr) of
|
||||
case resolveRegionOff mem regIdx (fromInteger adjAddr) of
|
||||
Nothing ->
|
||||
( ["Could not resolve entry point: " ++ showHex (Elf.elfEntry e) ""]
|
||||
, Nothing
|
||||
@ -1267,5 +1308,5 @@ resolveElfContents loadOpts e =
|
||||
pure (fmap show warnings ++ fmap show symErrs ++ entryWarn, mem, mentry, funcSymbols)
|
||||
Elf.ET_CORE ->
|
||||
Left "Reopt does not support loading core files."
|
||||
tp ->
|
||||
tp ->
|
||||
Left $ "Reopt does not support loading elf files with type " ++ show tp ++ "."
|
||||
|
116
base/src/Data/Macaw/Memory/Symbols.hs
Normal file
116
base/src/Data/Macaw/Memory/Symbols.hs
Normal file
@ -0,0 +1,116 @@
|
||||
{-|
|
||||
Copyright : (c) Galois Inc, 2015-2018
|
||||
Maintainer : jhendrix@galois.com
|
||||
|
||||
Defines constructors for precisely capturing symbol table information.
|
||||
-}
|
||||
module Data.Macaw.Memory.Symbols
|
||||
( -- * Symbols
|
||||
SymbolInfo(..)
|
||||
, SymbolBinding(..)
|
||||
, Data.BinarySymbols.SymbolVersion(..)
|
||||
-- ** Defined symbol information
|
||||
, SymbolPrecedence(..)
|
||||
, SymbolDefType(..)
|
||||
-- ** Undefined symbol infomration
|
||||
, SymbolRequirement(..)
|
||||
, SymbolUndefType(..)
|
||||
) where
|
||||
|
||||
import Data.BinarySymbols
|
||||
import qualified Data.ByteString as BS
|
||||
|
||||
-- | Describes symbol precedence
|
||||
data SymbolPrecedence
|
||||
= SymbolStrong
|
||||
-- ^ Symbol has high precedence
|
||||
| SymbolLocal
|
||||
-- ^ The symbol has high precedence, but only visible within the
|
||||
-- object file that created it.
|
||||
| SymbolWeak
|
||||
-- ^ Symbol has low precedence
|
||||
|
||||
-- | This denotes type information associated with a defined
|
||||
data SymbolDefType
|
||||
= SymbolDefUnknown
|
||||
-- ^ We do not know what type of object this refers to.
|
||||
| SymbolDefFunc
|
||||
-- ^ This symbol denotes a defined function.
|
||||
| SymbolDefObject
|
||||
-- ^ This symbol denotes a object.
|
||||
| SymbolDefThreadLocal
|
||||
-- ^ This symbol denotes a thread local identifier
|
||||
| SymbolDefIFunc
|
||||
-- ^ This symbol is a "IFUNC" (e.g., it calls a function to resolve the symbol)
|
||||
|
||||
-- | Describes whether an undefined symbol is required during linking.
|
||||
data SymbolRequirement
|
||||
= SymbolRequired
|
||||
-- ^ Undefined symbol must be found during linking
|
||||
| SymbolOptional
|
||||
-- ^ Undefined symbol treated as zero if not found during linking.
|
||||
|
||||
-- | Flags information about an undefined symbol.
|
||||
data SymbolUndefType
|
||||
= SymbolUndefThreadLocal
|
||||
-- ^ This symbol denotes data stored in a thread.
|
||||
| SymbolUndefNoType
|
||||
-- ^ This is stored globally for application, but otherwise has
|
||||
-- no type information.
|
||||
--
|
||||
-- Concretely we have seen this symbol type generated by gcc for
|
||||
-- external functions and data and _GLOBAL_OFFSET_TABLE_
|
||||
| SymbolUndefFunc
|
||||
-- ^ This symbol is intended to denote a function.
|
||||
| SymbolUndefObject
|
||||
-- ^ This symbol is intended to denote some data.
|
||||
|
||||
-- | This defines information about the symbol related to whether
|
||||
-- it is defined (and if so how it binds) or undefined (and if so what
|
||||
-- requiremens there are for a match).
|
||||
data SymbolBinding
|
||||
= DefinedSymbol !SymbolPrecedence !SymbolDefType
|
||||
-- ^ The symbol is defined and globally visible.
|
||||
--
|
||||
-- The strong symbol flag controls the precedence. If true, then
|
||||
-- this definition must be used for the symbol with that name,
|
||||
-- and the linker is not allowed to replace the symbol. Is
|
||||
-- false, then the linker will use a strong symbol if it exists,
|
||||
-- and one of the weak symbols if it does not.
|
||||
--
|
||||
-- The address is the address the symbol was loaded at. It may
|
||||
-- not be a valid segment offset if the original binary used
|
||||
-- symbols at unexpected addresses.
|
||||
| SymbolSection !SectionIndex
|
||||
-- ^ The symbol denotes a section in an object file with the
|
||||
-- given index. These are primarily intended for relocations.
|
||||
--
|
||||
-- The symbol version should be @UnversionedSymbol@ with this.
|
||||
| SymbolFile !BS.ByteString
|
||||
-- ^ This symbol denotes a file name with the given string
|
||||
--
|
||||
-- The symbol version should be @UnversionedSymbol@ with this.
|
||||
| UndefinedSymbol !SymbolRequirement !SymbolUndefType
|
||||
-- ^ An undefined symbol
|
||||
--
|
||||
-- The Boolean flag controls whether the symbol must be defined.
|
||||
-- If it is @False@ and the linker cannot find a definition, then
|
||||
-- it just treats the symbol address as @0@. If it is @True@ and
|
||||
-- the linker cannot find a definition, then it must throw an
|
||||
-- error.
|
||||
|
||||
-- | This provides information about a symbol in the file.
|
||||
data SymbolInfo =
|
||||
SymbolInfo { symbolName :: !SymbolName
|
||||
-- ^ The name of the symbol
|
||||
--
|
||||
-- Symbols are used for many purposes in a file.
|
||||
-- Symbol names may not be unique, and may even be
|
||||
-- empty. For example, Elf files uses the empty name
|
||||
-- for section symbols. On ARM, "$a", "$d" and "$t"
|
||||
-- are used to indicate regions of ARM code, data, thumb.
|
||||
, symbolVersion :: !SymbolVersion
|
||||
-- ^ Version information used to constrain when one
|
||||
-- symbol matches another.
|
||||
, symbolDef :: !SymbolBinding
|
||||
}
|
@ -194,7 +194,7 @@ doGetGlobal st mvar globs addr = do
|
||||
let sym = st^.stateSymInterface
|
||||
mem <- getMem st mvar
|
||||
regionNum <- natLit sym (fromIntegral (M.addrBase addr))
|
||||
offset <- bvLit sym (M.addrWidthNatRepr (M.addrWidthRepr addr)) (M.memWordInteger (M.addrOffset addr))
|
||||
offset <- bvLit sym (M.addrWidthNatRepr (M.addrWidthRepr addr)) (M.memWordToUnsigned (M.addrOffset addr))
|
||||
mptr <- globs sym mem regionNum offset
|
||||
case mptr of
|
||||
Nothing -> fail $ unlines
|
||||
|
@ -16,7 +16,7 @@ library
|
||||
containers,
|
||||
flexdis86 >= 0.1.2,
|
||||
lens >= 4.7,
|
||||
macaw-base >= 0.3.1,
|
||||
macaw-base >= 0.3.2,
|
||||
mtl,
|
||||
parameterized-utils,
|
||||
text,
|
||||
|
@ -128,7 +128,7 @@ rootLoc ip = ExploreLoc { loc_ip = ip
|
||||
initX86State :: ExploreLoc -- ^ Location to explore from.
|
||||
-> RegState X86Reg (Value X86_64 ids)
|
||||
initX86State loc = mkRegState Initial
|
||||
& curIP .~ RelocatableValue Addr64 (relativeSegmentAddr (loc_ip loc))
|
||||
& curIP .~ RelocatableValue Addr64 (segoffAddr (loc_ip loc))
|
||||
& boundValue X87_TopReg .~ mkLit knownNat (toInteger (loc_x87_top loc))
|
||||
& boundValue DF .~ BoolValue (loc_df_flag loc)
|
||||
|
||||
@ -146,7 +146,7 @@ initError loc err = do
|
||||
, blockStmts = []
|
||||
, blockTerm = TranslateError s (Text.pack (show err))
|
||||
}
|
||||
return (b, msegOffset addr, Just err)
|
||||
return (b, segoffOffset addr, Just err)
|
||||
|
||||
-- | Returns from the block translator with the preblock built so far
|
||||
-- and the current address
|
||||
@ -159,7 +159,7 @@ returnWithError pblock curIPAddr err = do
|
||||
, blockStmts = toList (pblock^.pBlockStmts)
|
||||
, blockTerm = TranslateError (pblock^.pBlockState) (Text.pack (show err))
|
||||
}
|
||||
return (b, msegOffset curIPAddr, Just err)
|
||||
return (b, segoffOffset curIPAddr, Just err)
|
||||
|
||||
-- | Translate block, returning blocks read, ending
|
||||
-- PC, and an optional error. and ending PC.
|
||||
@ -172,21 +172,21 @@ disassembleBlockImpl :: forall st_s ids
|
||||
-- ^ Address of next instruction to translate
|
||||
-> MemWord 64
|
||||
-- ^ Maximum offset for this addr.
|
||||
-> [SegmentRange 64]
|
||||
-- ^ List of contents to read next.
|
||||
-> [MemChunk 64]
|
||||
-- ^ Values to read next.
|
||||
-> ST st_s (Block X86_64 ids, MemWord 64, Maybe (X86TranslateError 64))
|
||||
disassembleBlockImpl nonceGen pblock curIPAddr max_offset contents = do
|
||||
case readInstruction curIPAddr contents of
|
||||
Left msg -> do
|
||||
returnWithError pblock curIPAddr msg
|
||||
Right (i, next_ip_off, nextContents) -> do
|
||||
let seg = msegSegment curIPAddr
|
||||
let off = msegOffset curIPAddr
|
||||
let seg = segoffSegment curIPAddr
|
||||
let off = segoffOffset curIPAddr
|
||||
-- Get size of instruction
|
||||
let instSize :: Int
|
||||
instSize = fromIntegral (next_ip_off - off)
|
||||
let next_ip :: MemAddr 64
|
||||
next_ip = relativeAddr seg next_ip_off
|
||||
next_ip = segmentOffAddr seg next_ip_off
|
||||
let next_ip_val :: BVValue X86_64 ids 64
|
||||
next_ip_val = RelocatableValue Addr64 next_ip
|
||||
case execInstruction (ValueExpr next_ip_val) i of
|
||||
@ -204,7 +204,7 @@ disassembleBlockImpl nonceGen pblock curIPAddr max_offset contents = do
|
||||
runExceptT $ runX86Generator gs $ do
|
||||
let line = show curIPAddr ++ ": " ++ show (F.ppInstruction i)
|
||||
addStmt (Comment (Text.pack line))
|
||||
asAtomicStateUpdate (MM.relativeSegmentAddr curIPAddr) exec
|
||||
asAtomicStateUpdate (MM.segoffAddr curIPAddr) exec
|
||||
case gsr of
|
||||
Left msg -> do
|
||||
returnWithError pblock curIPAddr (ExecInstructionError curIPAddr i msg)
|
||||
@ -232,16 +232,16 @@ disassembleBlock :: forall s
|
||||
-> ST s (Block X86_64 s, MemWord 64, Maybe (X86TranslateError 64))
|
||||
disassembleBlock nonce_gen loc max_size = do
|
||||
let addr = loc_ip loc
|
||||
let sz = msegOffset addr + max_size
|
||||
let sz = segoffOffset addr + max_size
|
||||
(b, next_ip_off, maybeError) <-
|
||||
case contentsAfterSegmentOff addr of
|
||||
case segoffContentsAfter addr of
|
||||
Left msg -> do
|
||||
initError loc (FlexdisMemoryError msg)
|
||||
Right contents -> do
|
||||
let pblock = emptyPreBlock (initX86State loc) 0
|
||||
disassembleBlockImpl nonce_gen pblock addr sz contents
|
||||
assert (next_ip_off > msegOffset addr) $ do
|
||||
let block_sz = next_ip_off - msegOffset addr
|
||||
assert (next_ip_off > segoffOffset addr) $ do
|
||||
let block_sz = next_ip_off - segoffOffset addr
|
||||
pure (b, block_sz, maybeError)
|
||||
|
||||
-- | The abstract state for a function begining at a given address.
|
||||
@ -249,7 +249,7 @@ initialX86AbsState :: MemSegmentOff 64 -> AbsBlockState X86Reg
|
||||
initialX86AbsState addr
|
||||
= top
|
||||
& setAbsIP addr
|
||||
& absRegState . boundValue sp_reg .~ concreteStackOffset (relativeSegmentAddr addr) 0
|
||||
& absRegState . boundValue sp_reg .~ concreteStackOffset (segoffAddr addr) 0
|
||||
-- x87 top register points to top of stack.
|
||||
& absRegState . boundValue X87_TopReg .~ FinSet (Set.singleton 7)
|
||||
-- Direction flag is initially zero.
|
||||
@ -345,10 +345,10 @@ tryDisassembleBlockFromAbsState nonceGen addr maxSize ab = do
|
||||
, loc_x87_top = fromInteger t
|
||||
, loc_df_flag = d /= 0
|
||||
}
|
||||
let off = msegOffset addr
|
||||
let off = segoffOffset addr
|
||||
let pblock = emptyPreBlock (initX86State loc) 0
|
||||
(b, nextIPOff, maybeError) <- lift $
|
||||
case contentsAfterSegmentOff addr of
|
||||
case segoffContentsAfter addr of
|
||||
Left msg -> do
|
||||
initError loc (FlexdisMemoryError msg)
|
||||
Right contents -> do
|
||||
@ -400,7 +400,7 @@ identifyX86Call mem stmts0 s = go (Seq.fromList stmts0) Seq.empty
|
||||
, Just val_a <- valueAsMemAddr val
|
||||
-- Check if segment of address is marked as executable.
|
||||
, Just ret_addr <- asSegmentOff mem val_a
|
||||
, segmentFlags (msegSegment ret_addr) `Perm.hasPerm` Perm.execute ->
|
||||
, segmentFlags (segoffSegment ret_addr) `Perm.hasPerm` Perm.execute ->
|
||||
Just (prev Seq.>< after, ret_addr)
|
||||
-- Stop if we hit any architecture specific instructions prior to
|
||||
-- identifying return address since they may have side effects.
|
||||
|
@ -34,7 +34,7 @@ import Flexdis86.ByteReader
|
||||
-- MemStream
|
||||
|
||||
-- | A stream of memory
|
||||
data MemStream w = MS { msInitial :: ![SegmentRange w]
|
||||
data MemStream w = MS { msInitial :: ![MemChunk w]
|
||||
-- ^ Initial memory contents. Used for error messages.
|
||||
, msSegment :: !(MemSegment w)
|
||||
-- ^ The current segment
|
||||
@ -42,15 +42,15 @@ data MemStream w = MS { msInitial :: ![SegmentRange w]
|
||||
-- ^ The initial offset for the stream.
|
||||
, msOffset :: !(MemWord w)
|
||||
-- ^ The current address
|
||||
, msNext :: ![SegmentRange w]
|
||||
, msNext :: ![MemChunk w]
|
||||
-- ^ The next bytes to read.
|
||||
}
|
||||
|
||||
msStartAddr :: MemWidth w => MemStream w -> MemAddr w
|
||||
msStartAddr ms = relativeAddr (msSegment ms) (msStart ms)
|
||||
msStartAddr ms = segmentOffAddr (msSegment ms) (msStart ms)
|
||||
|
||||
msAddr :: MemWidth w => MemStream w -> MemAddr w
|
||||
msAddr ms = relativeAddr (msSegment ms) (msOffset ms)
|
||||
msAddr ms = segmentOffAddr (msSegment ms) (msOffset ms)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- MemoryByteReader
|
||||
@ -59,7 +59,7 @@ msAddr ms = relativeAddr (msSegment ms) (msOffset ms)
|
||||
data X86TranslateError w
|
||||
= FlexdisMemoryError !(MemoryError w)
|
||||
-- ^ A memory error occured in decoding with Flexdis
|
||||
| InvalidInstruction !(MemAddr w) ![SegmentRange w]
|
||||
| InvalidInstruction !(MemAddr w) ![MemChunk w]
|
||||
-- ^ The memory reader could not parse the value starting at the given address
|
||||
-- the last byte read was at the offset.
|
||||
| UserMemoryError !(MemAddr w) !String
|
||||
@ -99,14 +99,14 @@ instance MemWidth w => Monad (MemoryByteReader w) where
|
||||
-- This returns either the translate error or the value read, the offset read to, and
|
||||
-- the next data.
|
||||
runMemoryByteReader :: MemSegmentOff w -- ^ Starting segment
|
||||
-> [SegmentRange w] -- ^ Data to read next.
|
||||
-> [MemChunk w] -- ^ Data to read next.
|
||||
-> MemoryByteReader w a -- ^ Byte reader to read values from.
|
||||
-> Either (X86TranslateError w) (a, MemWord w, [SegmentRange w])
|
||||
-> Either (X86TranslateError w) (a, MemWord w, [MemChunk w])
|
||||
runMemoryByteReader addr contents (MBR m) = do
|
||||
let ms0 = MS { msInitial = contents
|
||||
, msSegment = msegSegment addr
|
||||
, msStart = msegOffset addr
|
||||
, msOffset = msegOffset addr
|
||||
, msSegment = segoffSegment addr
|
||||
, msStart = segoffOffset addr
|
||||
, msOffset = segoffOffset addr
|
||||
, msNext = contents
|
||||
}
|
||||
case runState (runExceptT m) ms0 of
|
||||
@ -155,11 +155,11 @@ getJumpBytes s sz =
|
||||
updateMSByteString :: MemWidth w
|
||||
=> MemStream w
|
||||
-> BS.ByteString
|
||||
-> [SegmentRange w]
|
||||
-> [MemChunk w]
|
||||
-> MemWord w
|
||||
-> MemoryByteReader w ()
|
||||
updateMSByteString ms bs rest c = do
|
||||
let bs' = BS.drop (fromIntegral (memWordInteger c)) bs
|
||||
let bs' = BS.drop (fromIntegral (memWordToUnsigned c)) bs
|
||||
let ms' = ms { msOffset = msOffset ms + c
|
||||
, msNext =
|
||||
if BS.null bs' then
|
||||
@ -257,7 +257,7 @@ instance MemWidth w => ByteReader (MemoryByteReader w) where
|
||||
invalidInstruction = do
|
||||
ms <- MBR $ get
|
||||
throwError $ InvalidInstruction (msStartAddr ms)
|
||||
(takeSegmentPrefix (msInitial ms) (msOffset ms - msStart ms))
|
||||
(forcedTakeMemChunks (msInitial ms) (msOffset ms - msStart ms))
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- readInstruction
|
||||
@ -265,11 +265,11 @@ instance MemWidth w => ByteReader (MemoryByteReader w) where
|
||||
-- | Read instruction at a given memory address.
|
||||
readInstruction :: MemSegmentOff 64
|
||||
-- ^ Address to read from.
|
||||
-> [SegmentRange 64] -- ^ Data to read next.
|
||||
-> [MemChunk 64] -- ^ Data to read next.
|
||||
-> Either (X86TranslateError 64)
|
||||
(Flexdis.InstructionInstance
|
||||
( Flexdis.InstructionInstance
|
||||
, MemWord 64
|
||||
, [SegmentRange 64]
|
||||
, [MemChunk 64]
|
||||
)
|
||||
readInstruction addr contents = do
|
||||
runMemoryByteReader addr contents Flexdis.disassembleInstruction
|
||||
|
@ -368,7 +368,7 @@ resolveJumpOffset :: GenState st_s ids
|
||||
-> BVExpr ids 64
|
||||
resolveJumpOffset s (F.FixedOffset off) =
|
||||
ValueExpr $ RelocatableValue Addr64 $
|
||||
relativeSegmentAddr (genInitPCAddr s)
|
||||
segoffAddr (genInitPCAddr s)
|
||||
& incAddr (toInteger (genInstructionSize s) + toInteger off)
|
||||
resolveJumpOffset s (F.RelativeOffset insOff symId off)
|
||||
= ValueExpr (SymbolValue Addr64 symId)
|
||||
|
Loading…
Reference in New Issue
Block a user