From 2bb5a2990a460f4eef9a81521cc402b2d9827992 Mon Sep 17 00:00:00 2001 From: Daniel Matichuk Date: Thu, 4 Jan 2024 15:32:50 -0800 Subject: [PATCH] Data.Macaw.PPC: finish block when link register equals the IP To ensure that PC-relative reads are classified properly, the disassembler needs to (prematurely) end a block when the IP is the same as the link register. Normally, a `bl` instruction to the next address is not considered a terminal statement (contrary to what is described in the previous commit). Without this change, a pc-relative load followed by a direct jump would be erroneously classifed as a function call (that returns to where the pc-relative load happens), since the call classifier defines a call as any jump where the link register has been modified. This change handles this exact pattern by ensuring that the link register update ends the block, preventing subsequent direct jumps from deciding that the link register has been modified and classifying them as calls. --- macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs | 25 ++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs b/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs index d0da8a76..87648601 100644 --- a/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs +++ b/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs @@ -43,6 +43,7 @@ import qualified SemMC.Architecture.PPC as SP import Data.Macaw.SemMC.Generator import Data.Macaw.SemMC.Simplify ( simplifyValue ) import Data.Macaw.PPC.Arch ( PPCArchConstraints ) +import Data.Macaw.PPC.PPCReg ( PPCReg(..) ) -- | Read one instruction from the 'MM.Memory' at the given segmented offset. -- @@ -152,16 +153,20 @@ disassembleBlock lookupSemantics gs curIPAddr blockOff maxOffset = do , Just simplifiedIP <- simplifyValue v , simplifiedIP == nextIPVal , nextIPOffset < maxOffset - , Just nextIPSegAddr <- MM.incSegmentOff curIPAddr (fromIntegral bytesRead) -> do - let preBlock' = (pBlockState . curIP .~ simplifiedIP) preBlock - let gs2 = GenState { assignIdGen = assignIdGen gs - , _blockState = preBlock' - , genAddr = nextIPSegAddr - , genRegUpdates = MapF.empty - , appCache = appCache gs - , _blockStateSnapshot = preBlock' ^. pBlockState - } - disassembleBlock lookupSemantics gs2 nextIPSegAddr (blockOff + 4) maxOffset + , Just nextIPSegAddr <- MM.incSegmentOff curIPAddr (fromIntegral bytesRead) -> + case simplifyValue (preBlock ^. (pBlockState . boundValue PPC_LNK )) of + Just simplifiedLNK | simplifiedLNK == simplifiedIP -> + return (nextIPOffset, finishBlock' preBlock FetchAndExecute) + _ -> do + let preBlock' = (pBlockState . curIP .~ simplifiedIP) preBlock + let gs2 = GenState { assignIdGen = assignIdGen gs + , _blockState = preBlock' + , genAddr = nextIPSegAddr + , genRegUpdates = MapF.empty + , appCache = appCache gs + , _blockStateSnapshot = preBlock' ^. pBlockState + } + disassembleBlock lookupSemantics gs2 nextIPSegAddr (blockOff + 4) maxOffset | otherwise -> return (nextIPOffset, finishBlock' preBlock FetchAndExecute) FinishedPartialBlock b -> return (nextIPOffset, b)