You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.3 KiB
129 lines
4.3 KiB
{-|
|
|
Module : Keystone
|
|
Description : The Keystone assembler engine.
|
|
Copyright : (c) Adrian Herrera, 2016
|
|
License : GPL-2
|
|
|
|
Keystone is a lightweight multi-platform, multi-architecture assembler
|
|
framework.
|
|
|
|
Further information is available at <http://www.keystone-engine.org>.
|
|
-}
|
|
module Keystone
|
|
( -- * Assembler control
|
|
Assembler
|
|
, Engine
|
|
, Architecture(..)
|
|
, Mode(..)
|
|
, OptionType(..)
|
|
, OptionValue(..)
|
|
, runAssembler
|
|
, open
|
|
, option
|
|
, assemble
|
|
|
|
-- * Error handling
|
|
, Error(..)
|
|
, errno
|
|
, strerror
|
|
|
|
-- * Misc.
|
|
, version
|
|
) where
|
|
|
|
import Control.Monad.Trans.Class (lift)
|
|
import Control.Monad.Trans.Either (left, right, runEitherT)
|
|
import Data.ByteString (ByteString, packCStringLen)
|
|
import Data.List (intercalate)
|
|
import Foreign
|
|
|
|
import Keystone.Internal.Core
|
|
import Keystone.Internal.Keystone
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Assembler control
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- | Run the Keystone assembler and return a result on success, or an 'Error'
|
|
-- on failure.
|
|
runAssembler :: Assembler a -- ^ The assembler code to execute
|
|
-> IO (Either Error a) -- ^ A result on success, or an 'Error' on
|
|
-- failure
|
|
runAssembler =
|
|
runEitherT
|
|
|
|
-- | Create a new instance of the Keystone assembler.
|
|
open :: Architecture -- ^ CPU architecture
|
|
-> [Mode] -- ^ CPU hardware mode
|
|
-> Assembler Engine -- ^ A 'Keystone' engine on success, or an 'Error'
|
|
-- on failure
|
|
open arch mode = do
|
|
(err, ksPtr) <- lift $ ksOpen arch mode
|
|
if err == ErrOk then
|
|
-- Return a pointer to the Keystone engine if ksOpen completed
|
|
-- successfully
|
|
lift $ mkEngine ksPtr
|
|
else
|
|
-- Otherwise return an error
|
|
left err
|
|
|
|
option :: Engine -- ^ 'Keystone' engine handle
|
|
-> OptionType -- ^ Type of option to set
|
|
-> OptionValue -- ^ Option value corresponding with the type
|
|
-> Assembler () -- ^ An 'Error' on failure
|
|
option ks optType optValue = do
|
|
err <- lift $ ksOption ks optType optValue
|
|
if err == ErrOk then
|
|
right ()
|
|
else
|
|
left err
|
|
|
|
-- | Assemble a list of statements.
|
|
assemble :: Engine -- ^ 'Keystone' engine handle
|
|
-> [String] -- ^ List of statements to assemble.
|
|
-> Maybe Word64 -- ^ Optional address of the first
|
|
-- assembly instruction
|
|
-> Assembler (ByteString, Int) -- ^ Returns the encoded input assembly
|
|
-- string and the number of statements
|
|
-- successfully processed. Returns an
|
|
-- 'Error' on failure
|
|
assemble ks stmts addr = do
|
|
let string = intercalate ";" stmts
|
|
(res, encPtr, encSize, statCount) <- lift $ ksAsm ks string (maybeZ addr)
|
|
if res == 0 then do
|
|
-- If ksAsm completed successfully, pack the encoded bytes into a
|
|
-- ByteString. Once the encoded bytes have been packed the original
|
|
-- encoded bytes can be freed. The ByteString is returned with the
|
|
-- statement count
|
|
bs <- lift $ packCStringLen (castPtr encPtr, encSize)
|
|
lift $ ksFree encPtr
|
|
right (bs, statCount)
|
|
else do
|
|
-- On failure, call errno for error code
|
|
err <- errno ks
|
|
left err
|
|
where maybeZ = maybe 0 id
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Misc.
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- | Combined API version & major and minor version numbers. Returns a
|
|
-- hexadecimal number as (major << 8 | minor), which encodes both major and
|
|
-- minor versions.
|
|
version :: Int
|
|
version =
|
|
ksVersion nullPtr nullPtr
|
|
|
|
-- | Report the 'Error' number when some API function failed.
|
|
errno :: Engine -- ^ 'Keystone' engine handle
|
|
-> Assembler Error -- ^ The last 'Error' code
|
|
errno =
|
|
lift . ksErrno
|
|
|
|
-- | Return a string describing the given 'Error'.
|
|
strerror :: Error -- ^ The 'Error' code
|
|
-> String -- ^ Description of the error code
|
|
strerror =
|
|
ksStrerror
|