Skip to content

Commit

Permalink
x86: refactor mode/extensions/context modules
Browse files Browse the repository at this point in the history
- change names
- split into several modules
  • Loading branch information
hsyl20 committed Sep 6, 2024
1 parent eaadf4e commit b1d1942
Show file tree
Hide file tree
Showing 15 changed files with 325 additions and 308 deletions.
11 changes: 2 additions & 9 deletions haskus-system-tools/src/disassembler/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import System.Environment
import Control.Monad (forM_)

import Haskus.Binary.Buffer
import Haskus.Arch.X86_64.ISA.Mode
import Haskus.Arch.X86_64.ISA.Context
import Haskus.Arch.X86_64.ISA.Insn
import Haskus.Arch.X86_64.Disassembler
import qualified Data.Set as Set
Expand All @@ -17,13 +17,6 @@ main = do
bs <- bufferReadFile f

let
m = ExecMode
{ x86Mode = Mode64
, csDescriptorFlagD = False
, ssDescriptorFlagB = False
, extensions = allExtensions
}

showInsn o b cmt = putStrLn str
where
o' = show o
Expand All @@ -36,7 +29,7 @@ main = do
++ cmt

let
ds = linearDisass m bs
ds = linearDisass defaultContext64 bs
showDisass = \case
RawBytes offset buf errs -> showInsn offset buf ("; Failed: " ++ show errs)
Instruction offset buf ins -> showInsn offset buf d
Expand Down
11 changes: 3 additions & 8 deletions haskus-system-tools/src/elf/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Haskus.Format.Elf.GHC

import Haskus.Format.Dwarf

import Haskus.Arch.X86_64.ISA.Mode
import Haskus.Arch.X86_64.ISA.Context
import Haskus.Arch.X86_64.ISA.Size
import Haskus.Arch.X86_64.ISA.Insn
import Haskus.Arch.X86_64.ISA.Encoding
Expand Down Expand Up @@ -430,20 +430,15 @@ showSectionAsm elf s = do
-- TODO: add configuration for default operand/address size in 32-bit case
let
bs = getSectionContentBuffer elf s
m = ExecMode
{ x86Mode = Mode64
, csDescriptorFlagD = False
, ssDescriptorFlagB = False
, extensions = allExtensions
}
ctx = defaultContext64

table_ $ do
tr_ $ do
th_ "Offset"
th_ "Binary"
th_ "Instruction"
th_ "Comment"
forM_ (linearDisass m bs) $ \d -> tr_ $ do
forM_ (linearDisass ctx bs) $ \d -> tr_ $ do
case d of
RawBytes offset buf errs -> do
td_ (toHtml (show offset))
Expand Down
4 changes: 2 additions & 2 deletions haskus-system-tools/src/system-info/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import qualified Haskus.Arch.X86_64.ISA.Memory as X86
import qualified Haskus.Arch.X86_64.ISA.Size as X86
import qualified Haskus.Arch.X86_64.ISA.Solver as X86
import qualified Haskus.Arch.X86_64.ISA.Immediate as X86
import Haskus.Arch.X86_64.ISA.Mode
import Haskus.Arch.X86_64.ISA.Context
import Haskus.Arch.X86_64.ISA.Solver
import Haskus.Arch.Common.Register
import Haskus.Arch.Common.Memory
Expand Down Expand Up @@ -491,7 +491,7 @@ showRegs = do
h1_ "Registers"

let
showMode :: X86Mode -> Html ()
showMode :: Mode -> Html ()
showMode mode = do
h2_ (toHtml (show mode))
let
Expand Down
4 changes: 3 additions & 1 deletion haskus-system/haskus-system.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ library

Haskus.Arch.X86_64.ISA.Operand
Haskus.Arch.X86_64.ISA.Memory
Haskus.Arch.X86_64.ISA.Extension
Haskus.Arch.X86_64.ISA.Immediate
Haskus.Arch.X86_64.ISA.Solver
Haskus.Arch.X86_64.ISA.MicroArch
Haskus.Arch.X86_64.ISA.Mode
Haskus.Arch.X86_64.ISA.Context
Haskus.Arch.X86_64.ISA.Register
Haskus.Arch.X86_64.ISA.OpcodeMaps
Haskus.Arch.X86_64.ISA.OperatingMode
Haskus.Arch.X86_64.ISA.Size
Haskus.Arch.X86_64.ISA.Decoder
Haskus.Arch.X86_64.ISA.Insns
Expand Down
13 changes: 4 additions & 9 deletions haskus-system/src/lib/Haskus/Apps/Disassembler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Prelude hiding (replicate,length)
import qualified Haskus.Utils.Text as Text
import Haskus.Utils.Text (Text)
import Haskus.Binary.Buffer
import Haskus.Arch.X86_64.ISA.Mode
import Haskus.Arch.X86_64.ISA.Context
import Haskus.Arch.X86_64.ISA.Size
import Haskus.Arch.X86_64.ISA.Insn
import Haskus.Arch.X86_64.ISA.Encoding
Expand All @@ -34,15 +34,10 @@ disassX86_64 :: Maybe Word -> Buffer -> Text
disassX86_64 initOffset buffer = LT.toStrict (toLazyText bld)
where
-- disassembled buffer
ds = linearDisass m buffer
ds = linearDisass ctx buffer

-- arch mode
m = ExecMode
{ x86Mode = Mode64
, csDescriptorFlagD = False
, ssDescriptorFlagB = False
, extensions = allExtensions
}
-- context
ctx = defaultContext64

-- builder
bld = mconcat (fmap (fromText . showDisass) ds)
Expand Down
8 changes: 4 additions & 4 deletions haskus-system/src/lib/Haskus/Arch/X86_64/Disassembler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Haskus.Arch.X86_64.Disassembler
import Haskus.Binary.Get as G
import Haskus.Binary.Buffer
import Haskus.Arch.X86_64.ISA.Insn
import Haskus.Arch.X86_64.ISA.Mode
import Haskus.Arch.X86_64.ISA.Context
import Haskus.Arch.X86_64.ISA.Decoder
import Haskus.Utils.List (intersect)

Expand All @@ -21,11 +21,11 @@ data Disass
deriving (Show)

-- | Disassemble a whole buffer linearly
linearDisass :: ExecMode -> Buffer -> [Disass]
linearDisass m = go 0 emptyBuffer []
linearDisass :: Context -> Buffer -> [Disass]
linearDisass ctx = go 0 emptyBuffer []

where
g = G.countBytes $ getInstruction m
g = G.countBytes $ getInstruction ctx

go offset fb fbs b
| isBufferEmpty b && isBufferEmpty fb = []
Expand Down
123 changes: 123 additions & 0 deletions haskus-system/src/lib/Haskus/Arch/X86_64/ISA/Context.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
-- | Execution context for some code.
module Haskus.Arch.X86_64.ISA.Context
( module Haskus.Arch.X86_64.ISA.OperatingMode
, module Haskus.Arch.X86_64.ISA.Extension
-- * Execution context
, Context (..)
, context64
, defaultContext64
, defaultOperationSize
, defaultAddressSize
, overriddenOperationSize
, overriddenAddressSize
, overriddenOperationSize64
, defaultStackSize
, extensionAvailable
)
where

import Haskus.Arch.X86_64.ISA.Size
import Haskus.Arch.X86_64.ISA.OperatingMode
import Haskus.Arch.X86_64.ISA.Extension

-- | Execution context
--
-- This is useful to know which instructions are available, which registers,
-- etc. and how to encode some instructions.
data Context = Context
{ ctxMode :: !Mode
-- ^ Operating mode
, ctxCS_D :: !Bool
-- ^ CS.D flag: used in 32-bit mode to enable 32-bit operand/address size
-- by default
, ctxSS_B :: !Bool
-- ^ SS.B flag: used in 32-bit mode to enable 32-bit stack size by default
, ctxExtensions :: !ExtensionSet
-- ^ Enabled extensions
}


-- | 64-bit context
context64 :: ExtensionSet -> Context
context64 = Context Mode64 False False

-- | 64-bit context with all extensions enabled
defaultContext64 :: Context
defaultContext64 = context64 allExtensions


-- | Indicate if an extension is enabled
extensionAvailable :: Context -> Extension -> Bool
extensionAvailable ctx ext = hasExtension (ctxExtensions ctx) ext

-- | Default address size
defaultAddressSize :: Context -> AddressSize
defaultAddressSize ctx = case ctxMode ctx of
Mode64 -> AddrSize64
Mode64_32
| ctxCS_D ctx -> AddrSize32
| otherwise -> AddrSize16
Mode32
| ctxCS_D ctx -> AddrSize32
| otherwise -> AddrSize16
Mode32_16 -> AddrSize16
Mode16 -> AddrSize16

-- | Default operation size
defaultOperationSize :: Context -> OperandSize
defaultOperationSize ctx = case ctxMode ctx of
Mode64 -> OpSize32
Mode64_32
| ctxCS_D ctx -> OpSize32
| otherwise -> OpSize16
Mode32
| ctxCS_D ctx -> OpSize32
| otherwise -> OpSize16
Mode32_16 -> OpSize16
Mode16 -> OpSize16

-- | Default stack size
defaultStackSize :: Context -> AddressSize
defaultStackSize ctx = case ctxMode ctx of
Mode64 -> AddrSize32
Mode64_32
| ctxSS_B ctx -> AddrSize32
| otherwise -> AddrSize16
Mode32
| ctxSS_B ctx -> AddrSize32
| otherwise -> AddrSize16
Mode32_16 -> AddrSize16
Mode16 -> AddrSize16

-- | Compute the overridden address size, given the presence or not of the 0x67
-- prefix
overriddenAddressSize :: Bool -> Context -> AddressSize
overriddenAddressSize False ctx = defaultAddressSize ctx
overriddenAddressSize True ctx =
case defaultAddressSize ctx of
AddrSize16 -> AddrSize32
AddrSize32 -> AddrSize16
AddrSize64 -> AddrSize32

-- | Compute the overridden operation size, given the presence or not of the
-- 0x66 prefix
overriddenOperationSize :: Bool -> Context -> OperandSize
overriddenOperationSize False ctx = defaultOperationSize ctx
overriddenOperationSize True ctx =
case defaultOperationSize ctx of
OpSize16 -> OpSize32
_ -> OpSize16

-- | Compute the overridden operation size in 64-bit, given the presence or not
-- of the 0x66 prefix, the presence of the W prefix and whether the instruction
-- defaults to 64-bit operation size
overriddenOperationSize64 :: Bool -> Bool -> Bool -> Context -> OperandSize
overriddenOperationSize64 p66 pW p64 ctx =
case ctxMode ctx of
-- in 64-bit mode, most 64-bit instructions default to 32-bit operand
-- size, except those with the DefaultOperandSize64 property.
-- REX.W/VEX.W/XOP.W can be used to set a 64-bit operand size (it has
-- precedence over the 0x66 legacy prefix)
Mode64
| p64 || pW -> OpSize64
_ -> overriddenOperationSize p66 ctx
Loading

0 comments on commit b1d1942

Please sign in to comment.