mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-11-29 21:44:11 +03:00
Merge branch 'master' of github.com:GaloisInc/macaw
This commit is contained in:
commit
5959bfc6f0
@ -260,6 +260,9 @@ data FoundAddr arch
|
||||
-- ^ The abstract state formed from post-states that reach this address.
|
||||
}
|
||||
|
||||
foundReasonL :: Lens' (FoundAddr arch) (CodeAddrReason (ArchAddrWidth arch))
|
||||
foundReasonL = lens foundReason (\old new -> old { foundReason = new })
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- FunState
|
||||
|
||||
@ -291,6 +294,27 @@ curFunBlocks = lens _curFunBlocks (\s v -> s { _curFunBlocks = v })
|
||||
foundAddrs :: Simple Lens (FunState arch s ids) (Map (ArchSegmentOff arch) (FoundAddr arch))
|
||||
foundAddrs = lens _foundAddrs (\s v -> s { _foundAddrs = v })
|
||||
|
||||
-- | Add a block to the current function blocks. If this overlaps with an
|
||||
-- existing block, split them so that there's no overlap.
|
||||
addFunBlock ::
|
||||
MemWidth (RegAddrWidth (ArchReg arch)) =>
|
||||
ArchSegmentOff arch ->
|
||||
ParsedBlock arch ids ->
|
||||
FunState arch s ids ->
|
||||
FunState arch s ids
|
||||
addFunBlock segment block s = case Map.lookupLT segment (s ^. curFunBlocks) of
|
||||
Just (bSegment, bBlock)
|
||||
-- very sneaky way to check that they are in the same segment (a
|
||||
-- Nothing result from diffSegmentOff will never be greater than a
|
||||
-- Just) and that they are overlapping (the block size is bigger than
|
||||
-- you'd expect given the address difference)
|
||||
| diffSegmentOff bSegment segment > Just (-toInteger (blockSize bBlock))
|
||||
-- put the overlapped segment back in the frontier
|
||||
-> s & curFunBlocks %~ (Map.insert segment block . Map.delete bSegment)
|
||||
& foundAddrs.at bSegment._Just.foundReasonL %~ SplitAt segment
|
||||
& frontier %~ Set.insert bSegment
|
||||
_ -> s & curFunBlocks %~ Map.insert segment block
|
||||
|
||||
type ReverseEdgeMap arch = Map (ArchSegmentOff arch) (Set (ArchSegmentOff arch))
|
||||
|
||||
-- | Maps each code address to the list of predecessors that
|
||||
@ -758,7 +782,8 @@ parseBlock ctx b regs = do
|
||||
|
||||
-- | This evalutes the statements in a block to expand the information known
|
||||
-- about control flow targets of this block.
|
||||
transferBlocks :: ArchSegmentOff arch
|
||||
transferBlocks :: MemWidth (RegAddrWidth (ArchReg arch))
|
||||
=> ArchSegmentOff arch
|
||||
-- ^ Address of theze blocks
|
||||
-> FoundAddr arch
|
||||
-- ^ State leading to explore block
|
||||
@ -801,7 +826,7 @@ transferBlocks src finfo sz block_map =
|
||||
, blockAbstractState = foundAbstractState finfo
|
||||
, blockStatementList = pblock
|
||||
}
|
||||
curFunBlocks %= Map.insert src pb
|
||||
id %= addFunBlock src pb
|
||||
curFunCtx %= markAddrsAsFunction (InWrite src) (ps^.writtenCodeAddrs)
|
||||
. markAddrsAsFunction (CallTarget src) (ps^.newFunctionAddrs)
|
||||
mapM_ (\(addr, abs_state) -> mergeIntraJump src abs_state addr) (ps^.intraJumpTargets)
|
||||
@ -848,7 +873,7 @@ transfer addr = do
|
||||
, blockAbstractState = foundAbstractState finfo
|
||||
, blockStatementList = stmts
|
||||
}
|
||||
curFunBlocks %= Map.insert addr pb
|
||||
id %= addFunBlock addr pb
|
||||
else do
|
||||
-- Rewrite returned blocks to simplify expressions
|
||||
|
||||
|
@ -76,8 +76,8 @@ data CodeAddrReason w
|
||||
-- ^ Identified as an entry point from initial information
|
||||
| CodePointerInMem !(MemSegmentOff w)
|
||||
-- ^ A code pointer that was stored at the given address.
|
||||
| SplitAt !(MemAddr w)
|
||||
-- ^ Added because the address split this block after it had been disassembled.
|
||||
| SplitAt !(MemSegmentOff w) !(CodeAddrReason w)
|
||||
-- ^ Added because the address split this block after it had been disassembled. Also includes the reason we thought the block should be there before we split it.
|
||||
| UserRequest
|
||||
-- ^ The user requested that we analyze this address as a function.
|
||||
deriving (Eq, Show)
|
||||
|
@ -27,6 +27,7 @@ import qualified Data.Parameterized.Some as PU
|
||||
import qualified Data.Macaw.Memory as MM
|
||||
import qualified Data.Macaw.Memory.ElfLoader as MM
|
||||
import qualified Data.Macaw.Discovery as MD
|
||||
import qualified Data.Macaw.Discovery.State as MD
|
||||
import qualified Data.Macaw.X86 as RO
|
||||
|
||||
elfX64LinuxTests :: [FilePath] -> T.TestTree
|
||||
@ -34,7 +35,7 @@ elfX64LinuxTests = T.testGroup "ELF x64 Linux" . map mkTest
|
||||
|
||||
-- | The type of expected results for test cases
|
||||
data ExpectedResult =
|
||||
R { funcs :: [(Word64, [Word64])]
|
||||
R { funcs :: [(Word64, [(Word64, Integer)])]
|
||||
-- ^ The first element of the pair is the address of entry point
|
||||
-- of the function. The list is a list of the addresses of the
|
||||
-- basic blocks in the function (including the first block).
|
||||
@ -57,7 +58,7 @@ mkTest fp = T.testCase fp $ withELF exeFilename (testDiscovery fp)
|
||||
testDiscovery :: FilePath -> E.Elf 64 -> IO ()
|
||||
testDiscovery expectedFilename elf =
|
||||
withMemory MM.Addr64 elf $ \mem -> do
|
||||
let Just entryPoint = MM.asSegmentOff mem (MM.absoluteAddr (MM.memWord (fromIntegral (E.elfEntry elf))))
|
||||
let Just entryPoint = MM.asSegmentOff mem (MM.absoluteAddr (MM.memWord (E.elfEntry elf)))
|
||||
di = MD.cfgFromAddrs RO.x86_64_linux_info mem M.empty [entryPoint] []
|
||||
expectedString <- readFile expectedFilename
|
||||
case readMaybe expectedString of
|
||||
@ -65,17 +66,23 @@ testDiscovery expectedFilename elf =
|
||||
Just er -> do
|
||||
let expectedEntries = M.fromList [ (entry, S.fromList starts) | (entry, starts) <- funcs er ]
|
||||
ignoredBlocks = S.fromList (ignoreBlocks er)
|
||||
absoluteFromSegOff = fromIntegral . fromJust . MM.asAbsoluteAddr . MM.relativeSegmentAddr
|
||||
T.assertEqual "Collection of discovered function starting points"
|
||||
(M.keysSet expectedEntries `S.difference` ignoredBlocks)
|
||||
(S.map absoluteFromSegOff (M.keysSet (di ^. MD.funInfo)))
|
||||
F.forM_ (M.elems (di ^. MD.funInfo)) $ \(PU.Some dfi) -> do
|
||||
let actualEntry = fromIntegral (fromJust (MM.asAbsoluteAddr (MM.relativeSegmentAddr (MD.discoveredFunAddr dfi))))
|
||||
let actualEntry = absoluteFromSegOff (MD.discoveredFunAddr dfi)
|
||||
-- actualEntry = fromIntegral (MM.addrValue (MD.discoveredFunAddr dfi))
|
||||
actualBlockStarts = S.fromList [ fromIntegral (fromJust (MM.asAbsoluteAddr (MM.relativeSegmentAddr (MD.pblockAddr pbr))))
|
||||
actualBlockStarts = S.fromList [ (addr, toInteger (MD.blockSize pbr))
|
||||
| pbr <- M.elems (dfi ^. MD.parsedBlocks)
|
||||
, let addr = absoluteFromSegOff (MD.pblockAddr pbr)
|
||||
, addr `S.notMember` ignoredBlocks
|
||||
]
|
||||
case (S.member actualEntry ignoredBlocks, M.lookup actualEntry expectedEntries) of
|
||||
(True, _) -> return ()
|
||||
(_, Nothing) -> T.assertFailure (printf "Unexpected entry point: 0x%x" actualEntry)
|
||||
(_, Just expectedBlockStarts) ->
|
||||
T.assertEqual (printf "Block starts for 0x%x" actualEntry) expectedBlockStarts (actualBlockStarts `S.difference` ignoredBlocks)
|
||||
T.assertEqual (printf "Block starts for 0x%x" actualEntry) expectedBlockStarts actualBlockStarts
|
||||
|
||||
withELF :: FilePath -> (E.Elf 64 -> IO ()) -> IO ()
|
||||
withELF fp k = do
|
||||
|
@ -1,3 +1,3 @@
|
||||
R { funcs = [(0x2b1, [0x2b1, 0x2ce, 0x2bf])]
|
||||
R { funcs = [(0x2b1, [(0x2b1, 14), (0x2ce, 16), (0x2bf, 15)])]
|
||||
, ignoreBlocks = [0x2de]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
R { funcs = [ (0x336, [0x336, 0x376])
|
||||
, (0x2be, [0x2be, 0x318])
|
||||
, (0x2b1, [0x2b1])
|
||||
R { funcs = [ (0x336, [(0x336, 64), (0x376, 22)])
|
||||
, (0x2be, [(0x2be, 90), (0x318, 30)])
|
||||
, (0x2b1, [(0x2b1, 13)])
|
||||
]
|
||||
, ignoreBlocks = [0x38c]
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
R { funcs = [ (0x2b1, [0x2b1])
|
||||
, (0x2bf, [0x2bf, 0x2e2])
|
||||
R { funcs = [ (0x2b1, [(0x2b1, 14)])
|
||||
, (0x2bf, [(0x2bf, 35), (0x2e2, 22)])
|
||||
]
|
||||
, ignoreBlocks = [0x2f8]
|
||||
}
|
||||
}
|
||||
|
13
x86/tests/x64/test-jump-into-instruction.c
Normal file
13
x86/tests/x64/test-jump-into-instruction.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "util.h"
|
||||
|
||||
void _start() {
|
||||
long long x;
|
||||
here:
|
||||
// This makes an instruction with a short 0x90 nop slide.
|
||||
x = 0x9090909090909090;
|
||||
// The +4 is completely ignored by gcc. You have to modify the assembly by
|
||||
// hand after compiling to make this jump into the middle of an emitted
|
||||
// instruction.
|
||||
goto *(&&here + 4);
|
||||
EXIT();
|
||||
}
|
BIN
x86/tests/x64/test-jump-into-instruction.exe
Executable file
BIN
x86/tests/x64/test-jump-into-instruction.exe
Executable file
Binary file not shown.
22
x86/tests/x64/test-jump-into-instruction.s
Normal file
22
x86/tests/x64/test-jump-into-instruction.s
Normal file
@ -0,0 +1,22 @@
|
||||
.file "test-jump-into-instruction.c"
|
||||
.text
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
.L2:
|
||||
movabsq $-8029759185026510704, %rax
|
||||
movq %rax, -8(%rbp)
|
||||
nop
|
||||
jmp .L2+4
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size _start, .-_start
|
||||
.ident "GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)"
|
||||
.section .note.GNU-stack,"",@progbits
|
3
x86/tests/x64/test-jump-into-instruction.s.expected
Normal file
3
x86/tests/x64/test-jump-into-instruction.s.expected
Normal file
@ -0,0 +1,3 @@
|
||||
R { funcs = [(0x400144, [(0x400144, 14), (0x40014c, 6), (0x400152, 7)])]
|
||||
, ignoreBlocks = []
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
R { funcs = [(0x2b1, [0x2b1])]
|
||||
R { funcs = [(0x2b1, [(0x2b1, 20)])]
|
||||
, ignoreBlocks = [0x2c5]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
R { funcs = [ (0x2c0, [0x2c0])
|
||||
, (0x2d0, [0x2d0, 0x2c0])
|
||||
, (0x2e0, [0x2e0, 0x2eb])
|
||||
R { funcs = [ (0x2d0, [(0x2d0, 11), (0x2c0, 7)])
|
||||
, (0x2e0, [(0x2e0, 11), (0x2eb, 16)])
|
||||
]
|
||||
, ignoreBlocks = [0x2fb]
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user