Skip to content

Commit

Permalink
Data.Macaw.PPC: finish block when link register equals the IP
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
danmatichuk committed Jan 4, 2024
1 parent 8d7d7d7 commit 2bb5a29
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
--
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 2bb5a29

Please sign in to comment.