mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-11-22 14:27:51 +03:00
Add x86 specific code.
This commit is contained in:
parent
0242a88fa6
commit
4dcb26ebee
30
LICENSE
Normal file
30
LICENSE
Normal file
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2014-2017 Galois Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Galois, Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1
x86/.gitignore
vendored
Normal file
1
x86/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.stack-work
|
64
x86/macaw-x86.cabal
Normal file
64
x86/macaw-x86.cabal
Normal file
@ -0,0 +1,64 @@
|
||||
name: macaw-x86
|
||||
version: 0.0.1
|
||||
author: Galois, Inc.
|
||||
maintainer: jhendrix@galois.com
|
||||
build-type: Simple
|
||||
cabal-version: >= 1.9.2
|
||||
|
||||
library
|
||||
build-depends:
|
||||
base >= 4,
|
||||
ansi-wl-pprint,
|
||||
bytestring,
|
||||
containers,
|
||||
flexdis86 >= 0.1.1,
|
||||
lens >= 4.7,
|
||||
macaw-base,
|
||||
mtl,
|
||||
parameterized-utils,
|
||||
text,
|
||||
vector
|
||||
|
||||
hs-source-dirs: src
|
||||
|
||||
exposed-modules:
|
||||
Data.Macaw.X86
|
||||
Data.Macaw.X86.ArchTypes
|
||||
Data.Macaw.X86.Conditions
|
||||
Data.Macaw.X86.Flexdis
|
||||
Data.Macaw.X86.Getters
|
||||
Data.Macaw.X86.InstructionDef
|
||||
Data.Macaw.X86.Monad
|
||||
Data.Macaw.X86.Semantics
|
||||
Data.Macaw.X86.SyscallInfo.FreeBSD
|
||||
Data.Macaw.X86.SyscallInfo.Linux
|
||||
Data.Macaw.X86.X86Flag
|
||||
Data.Macaw.X86.X86Reg
|
||||
Data.Macaw.X86.X87ControlReg
|
||||
|
||||
ghc-options: -Wall -Werror
|
||||
ghc-options: -fno-warn-unticked-promoted-constructors
|
||||
ghc-prof-options: -O2 -fprof-auto-top
|
||||
|
||||
test-suite macaw-x86-tests
|
||||
type: exitcode-stdio-1.0
|
||||
default-language: Haskell2010
|
||||
ghc-options: -Wall
|
||||
main-is: Main.hs
|
||||
other-modules: ElfX64Linux
|
||||
hs-source-dirs: tests
|
||||
build-depends:
|
||||
base,
|
||||
bytestring,
|
||||
containers,
|
||||
elf-edit,
|
||||
exceptions,
|
||||
filemanip,
|
||||
filepath,
|
||||
lens,
|
||||
macaw,
|
||||
parameterized-utils,
|
||||
macaw-x86,
|
||||
temporary,
|
||||
tasty,
|
||||
tasty-hunit
|
1510
x86/src/Data/Macaw/X86.hs
Normal file
1510
x86/src/Data/Macaw/X86.hs
Normal file
File diff suppressed because it is too large
Load Diff
404
x86/src/Data/Macaw/X86/ArchTypes.hs
Normal file
404
x86/src/Data/Macaw/X86/ArchTypes.hs
Normal file
@ -0,0 +1,404 @@
|
||||
{-
|
||||
Copyright : (c) Galois, Inc 2015-2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>, Simon Winwood <sjw@galois.com>
|
||||
|
||||
This defines the X86_64 architecture type and the supporting definitions.
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE EmptyDataDecls #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
module Data.Macaw.X86.ArchTypes
|
||||
( -- * Architecture
|
||||
X86_64
|
||||
, X86PrimFn(..)
|
||||
, valuesInX86Fn
|
||||
, rewriteX86PrimFn
|
||||
, x86PrimFnHasSideEffects
|
||||
, X86Stmt(..)
|
||||
, valuesInX86Stmt
|
||||
, rewriteX86Stmt
|
||||
, X86TermStmt(..)
|
||||
, rewriteX86TermStmt
|
||||
, X86PrimLoc(..)
|
||||
) where
|
||||
|
||||
import Data.Bits
|
||||
import Data.Foldable
|
||||
import Data.Parameterized.NatRepr
|
||||
import Data.Parameterized.Some
|
||||
import Data.Parameterized.TraversableFC
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import qualified Flexdis86 as F
|
||||
import Text.PrettyPrint.ANSI.Leijen as PP hiding ((<$>))
|
||||
|
||||
import Data.Macaw.CFG
|
||||
import Data.Macaw.CFG.Rewriter
|
||||
import Data.Macaw.Types
|
||||
|
||||
import Data.Macaw.X86.Monad (SIMDWidth(..), RepValSize(..), repValSizeMemRepr)
|
||||
import Data.Macaw.X86.X86Reg
|
||||
import Data.Macaw.X86.X87ControlReg
|
||||
|
||||
assignIdSetFromValues :: [Some (Value arch ids)] -> Set (Some (AssignId ids))
|
||||
assignIdSetFromValues = foldl' f Set.empty
|
||||
where f s (Some v) = Set.union s (refsInValue v)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86TermStmt
|
||||
|
||||
data X86TermStmt ids = X86Syscall
|
||||
|
||||
instance PrettyF X86TermStmt where
|
||||
prettyF X86Syscall = text "x86_syscall"
|
||||
|
||||
rewriteX86TermStmt :: X86TermStmt src -> Rewriter X86_64 src tgt (X86TermStmt tgt)
|
||||
rewriteX86TermStmt f =
|
||||
case f of
|
||||
X86Syscall -> pure X86Syscall
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86_64 specific declarations
|
||||
|
||||
data X86_64
|
||||
|
||||
type instance ArchReg X86_64 = X86Reg
|
||||
type instance ArchFn X86_64 = X86PrimFn
|
||||
type instance ArchStmt X86_64 = X86Stmt
|
||||
type instance ArchTermStmt X86_64 = X86TermStmt
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86PrimLoc
|
||||
|
||||
-- | This describes a primitive location that can be read or written to in the
|
||||
-- X86 architecture model.
|
||||
-- Primitive locations are not modeled as registers, but rather as implicit state.
|
||||
data X86PrimLoc tp
|
||||
= (tp ~ BVType 64) => ControlLoc !F.ControlReg
|
||||
| (tp ~ BVType 64) => DebugLoc !F.DebugReg
|
||||
| (tp ~ BVType 16) => FS
|
||||
-- ^ This refers to the selector of the 'FS' register.
|
||||
| (tp ~ BVType 16) => GS
|
||||
-- ^ This refers to the se lector of the 'GS' register.
|
||||
| forall w . (tp ~ BVType w) => X87_ControlLoc !(X87_ControlReg w)
|
||||
-- ^ One of the x87 control registers
|
||||
|
||||
instance HasRepr X86PrimLoc TypeRepr where
|
||||
typeRepr ControlLoc{} = knownType
|
||||
typeRepr DebugLoc{} = knownType
|
||||
typeRepr FS = knownType
|
||||
typeRepr GS = knownType
|
||||
typeRepr (X87_ControlLoc r) =
|
||||
case x87ControlRegWidthIsPos r of
|
||||
LeqProof -> BVTypeRepr (typeRepr r)
|
||||
|
||||
instance Pretty (X86PrimLoc tp) where
|
||||
pretty (ControlLoc r) = text (show r)
|
||||
pretty (DebugLoc r) = text (show r)
|
||||
pretty FS = text "fs"
|
||||
pretty GS = text "gs"
|
||||
pretty (X87_ControlLoc r) = text (show r)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86PrimFn
|
||||
|
||||
-- | Defines primitive functions in the X86 format.
|
||||
data X86PrimFn f tp
|
||||
= ReadLoc !(X86PrimLoc tp)
|
||||
-- ^ Read from a primitive X86 location
|
||||
| (tp ~ BVType 64) => ReadFSBase
|
||||
-- ^ Read the 'FS' base address
|
||||
| (tp ~ BVType 64) => ReadGSBase
|
||||
-- ^ Read the 'GS' base address
|
||||
| (tp ~ BVType 128) => CPUID (f (BVType 32))
|
||||
-- ^ The CPUID instruction
|
||||
--
|
||||
-- Given value in eax register, this returns the concatenation of eax:ebx:ecx:edx.
|
||||
| (tp ~ BVType 64) => RDTSC
|
||||
-- ^ The RDTSC instruction
|
||||
--
|
||||
-- This returns the current time stamp counter a 64-bit value that will
|
||||
-- be stored in edx:eax
|
||||
| (tp ~ BVType 64) => XGetBV (f (BVType 32))
|
||||
-- ^ The XGetBV instruction primitive
|
||||
--
|
||||
-- This returns the extended control register defined in the given value
|
||||
-- as a 64-bit value that will be stored in edx:eax
|
||||
| forall w
|
||||
. (tp ~ BVType w, 1 <= w)
|
||||
=> PShufb !(SIMDWidth w) !(f (BVType w)) !(f (BVType w))
|
||||
-- ^ @PShufb w x s@ returns a value @res@ generated from the bytes of @x@
|
||||
-- based on indices defined in the corresponding bytes of @s@.
|
||||
--
|
||||
-- Let @n@ be the number of bytes in the width @w@, and let @l = log2(n)@.
|
||||
-- Given a byte index @i@, the value of byte @res[i]@, is defined by
|
||||
-- @res[i] = 0 if msb(s[i]) == 1@
|
||||
-- @res[i] = x[j] where j = s[i](0..l)
|
||||
-- where @msb(y)@ returns the most-significant bit in byte @y@.
|
||||
| (tp ~ BVType 64)
|
||||
=> MemCmp !Integer
|
||||
-- /\ Number of bytes per value.
|
||||
!(f (BVType 64))
|
||||
-- /\ Number of values to compare
|
||||
!(f (BVType 64))
|
||||
-- /\ Pointer to first buffer.
|
||||
!(f (BVType 64))
|
||||
-- /\ Pointer to second buffer.
|
||||
!(f BoolType)
|
||||
-- /\ Direction flag, False means increasing
|
||||
-- ^ Compares to memory regions
|
||||
| forall n
|
||||
. (tp ~ BVType 64)
|
||||
=> RepnzScas !(RepValSize n)
|
||||
!(f (BVType n))
|
||||
!(f (BVType 64))
|
||||
!(f (BVType 64))
|
||||
-- ^ `RepnzScas sz val base cnt` searchs through a buffer starting at
|
||||
-- `base` to find an element `i` such that base[i] = val.
|
||||
-- Each step it increments `i` by 1 and decrements `cnt` by `1`. It returns
|
||||
-- the final value of `cnt`.
|
||||
| (tp ~ BVType 80)
|
||||
=> MMXExtend !(f (BVType 64))
|
||||
-- ^ This returns a 80-bit value where the high 16-bits are all
|
||||
-- 1s, and the low 64-bits are the given register.
|
||||
| forall w
|
||||
. (tp ~ BVType w)
|
||||
=> X86IDiv !(RepValSize w)
|
||||
!(f (BVType (w+w)))
|
||||
!(f (BVType w))
|
||||
-- ^ This performs a signed quotient for idiv.
|
||||
-- The dividend is rounded to zero.
|
||||
-- It raises a #DE exception if the divisor is 0 or the result overflows.
|
||||
| forall w
|
||||
. (tp ~ BVType w)
|
||||
=> X86IRem !(RepValSize w)
|
||||
!(f (BVType (w+w)))
|
||||
!(f (BVType w))
|
||||
-- ^ This performs a signed remainder for idiv.
|
||||
-- The dividend is rounded to zero.
|
||||
-- It raises a #DE exception if the divisor is 0 or the result overflows.
|
||||
|
||||
instance HasRepr (X86PrimFn f) TypeRepr where
|
||||
typeRepr f =
|
||||
case f of
|
||||
ReadLoc loc -> typeRepr loc
|
||||
ReadFSBase -> knownType
|
||||
ReadGSBase -> knownType
|
||||
CPUID{} -> knownType
|
||||
RDTSC{} -> knownType
|
||||
XGetBV{} -> knownType
|
||||
PShufb w _ _ -> BVTypeRepr (typeRepr w)
|
||||
MemCmp{} -> knownType
|
||||
RepnzScas{} -> knownType
|
||||
MMXExtend{} -> knownType
|
||||
X86IDiv w _ _ -> typeRepr (repValSizeMemRepr w)
|
||||
X86IRem w _ _ -> typeRepr (repValSizeMemRepr w)
|
||||
|
||||
-- | An operation for pretty printing a 'X86PrimFn' using a pretty printer
|
||||
-- for values that is implemented as a 'Applicative' action to allow side
|
||||
-- effects.
|
||||
ppX86PrimFn :: Applicative m
|
||||
=> (forall u . f u -> m Doc)
|
||||
-- ^ Function for pretty printing vlaue.
|
||||
-> X86PrimFn f tp
|
||||
-> m Doc
|
||||
ppX86PrimFn pp f =
|
||||
case f of
|
||||
ReadLoc loc -> pure $ pretty loc
|
||||
ReadFSBase -> pure $ text "fs.base"
|
||||
ReadGSBase -> pure $ text "gs.base"
|
||||
CPUID code -> sexprA "cpuid" [ pp code ]
|
||||
RDTSC -> pure $ text "rdtsc"
|
||||
XGetBV code -> sexprA "xgetbv" [ pp code ]
|
||||
PShufb _ x s -> sexprA "pshufb" [ pp x, pp s ]
|
||||
MemCmp sz cnt src dest rev -> sexprA "memcmp" args
|
||||
where args = [pure (pretty sz), pp cnt, pp dest, pp src, pp rev]
|
||||
RepnzScas _ val buf cnt -> sexprA "first_byte_offset" args
|
||||
where args = [pp val, pp buf, pp cnt]
|
||||
MMXExtend e -> sexprA "mmx_extend" [ pp e ]
|
||||
X86IDiv w n d -> sexprA "idiv" [ pure (text $ show $ typeWidth $ repValSizeMemRepr w), pp n, pp d ]
|
||||
X86IRem w n d -> sexprA "irem" [ pure (text $ show $ typeWidth $ repValSizeMemRepr w), pp n, pp d ]
|
||||
|
||||
|
||||
rewriteX86PrimFn :: X86PrimFn (Value X86_64 src) tp
|
||||
-> Rewriter X86_64 src tgt (Value X86_64 tgt tp)
|
||||
rewriteX86PrimFn f =
|
||||
case f of
|
||||
ReadLoc loc -> evalRewrittenArchFn $ ReadLoc loc
|
||||
ReadFSBase -> evalRewrittenArchFn ReadFSBase
|
||||
ReadGSBase -> evalRewrittenArchFn ReadGSBase
|
||||
CPUID code -> do
|
||||
tgtFn <- CPUID <$> rewriteValue code
|
||||
evalRewrittenArchFn tgtFn
|
||||
RDTSC -> evalRewrittenArchFn RDTSC
|
||||
XGetBV code -> do
|
||||
tgtFn <- XGetBV <$> rewriteValue code
|
||||
evalRewrittenArchFn tgtFn
|
||||
PShufb w x s -> do
|
||||
tgtFn <- PShufb w <$> rewriteValue x
|
||||
<*> rewriteValue s
|
||||
evalRewrittenArchFn tgtFn
|
||||
MemCmp sz cnt src dest rev -> do
|
||||
tgtFn <- MemCmp sz <$> rewriteValue cnt
|
||||
<*> rewriteValue src
|
||||
<*> rewriteValue dest
|
||||
<*> rewriteValue rev
|
||||
evalRewrittenArchFn tgtFn
|
||||
RepnzScas sz val buf cnt -> do
|
||||
tgtFn <- RepnzScas sz <$> rewriteValue val
|
||||
<*> rewriteValue buf
|
||||
<*> rewriteValue cnt
|
||||
evalRewrittenArchFn tgtFn
|
||||
MMXExtend e -> do
|
||||
tgtExpr <- rewriteValue e
|
||||
case tgtExpr of
|
||||
BVValue _ i -> do
|
||||
pure $ BVValue (knownNat :: NatRepr 80) $ 0xffff `shiftL` 64 .|. i
|
||||
_ ->
|
||||
evalRewrittenArchFn (MMXExtend tgtExpr)
|
||||
X86IDiv w n d -> do
|
||||
tgtFn <- X86IDiv w <$> rewriteValue n
|
||||
<*> rewriteValue d
|
||||
evalRewrittenArchFn tgtFn
|
||||
X86IRem w n d -> do
|
||||
tgtFn <- X86IRem w <$> rewriteValue n
|
||||
<*> rewriteValue d
|
||||
evalRewrittenArchFn tgtFn
|
||||
|
||||
-- | This returns true if evaluating the primitive function implicitly
|
||||
-- changes the processor state in some way.
|
||||
x86PrimFnHasSideEffects :: X86PrimFn f tp -> Bool
|
||||
x86PrimFnHasSideEffects f =
|
||||
case f of
|
||||
ReadLoc{} -> False
|
||||
ReadFSBase -> False
|
||||
ReadGSBase -> False
|
||||
CPUID{} -> False
|
||||
RDTSC -> False
|
||||
XGetBV{} -> False
|
||||
PShufb{} -> False
|
||||
MemCmp{} -> False
|
||||
RepnzScas{} -> True
|
||||
MMXExtend{} -> False
|
||||
X86IDiv{} -> True -- To be conservative we treat the floating point exceptions as side effects.
|
||||
X86IRem{} -> True -- To be conservative we treat the floating point exceptions as side effects.
|
||||
|
||||
instance FunctorFC X86PrimFn where
|
||||
fmapFC = fmapFCDefault
|
||||
|
||||
instance FoldableFC X86PrimFn where
|
||||
foldMapFC = foldMapFCDefault
|
||||
|
||||
instance TraversableFC X86PrimFn where
|
||||
traverseFC go f =
|
||||
case f of
|
||||
ReadLoc l -> pure (ReadLoc l)
|
||||
ReadFSBase -> pure ReadFSBase
|
||||
ReadGSBase -> pure ReadGSBase
|
||||
CPUID v -> CPUID <$> go v
|
||||
RDTSC -> pure RDTSC
|
||||
XGetBV v -> XGetBV <$> go v
|
||||
PShufb w x y -> PShufb w <$> go x <*> go y
|
||||
MemCmp sz cnt src dest rev ->
|
||||
MemCmp sz <$> go cnt <*> go src <*> go dest <*> go rev
|
||||
RepnzScas sz val buf cnt ->
|
||||
RepnzScas sz <$> go val <*> go buf <*> go cnt
|
||||
MMXExtend v -> MMXExtend <$> go v
|
||||
X86IDiv w n d -> X86IDiv w <$> go n <*> go d
|
||||
X86IRem w n d -> X86IRem w <$> go n <*> go d
|
||||
|
||||
instance IsArchFn X86PrimFn where
|
||||
ppArchFn = ppX86PrimFn
|
||||
|
||||
valuesInX86Fn :: X86PrimFn v tp -> [Some v]
|
||||
valuesInX86Fn = foldMapFC (\v -> [Some v])
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86Stmt
|
||||
|
||||
-- | An X86 specific statement.
|
||||
data X86Stmt ids
|
||||
= forall tp .
|
||||
WriteLoc !(X86PrimLoc tp) !(Value X86_64 ids tp)
|
||||
| StoreX87Control !(BVValue X86_64 ids 64)
|
||||
-- ^ Store the X87 control register in the given location.
|
||||
| MemCopy !Integer
|
||||
!(Value X86_64 ids (BVType 64))
|
||||
!(Value X86_64 ids (BVType 64))
|
||||
!(Value X86_64 ids (BVType 64))
|
||||
!(Value X86_64 ids BoolType)
|
||||
-- ^ Copy a region of memory from a source buffer to a destination buffer.
|
||||
--
|
||||
-- In an expression @MemCopy bc v src dest dir@
|
||||
-- * @bc@ is the number of bytes to copy at a time (1,2,4,8)
|
||||
-- * @v@ is the number of values to move.
|
||||
-- * @src@ is the start of source buffer.
|
||||
-- * @dest@ is the start of destination buffer.
|
||||
-- * @dir@ is a flag that indicates whether direction of move:
|
||||
-- * 'True' means we should decrement buffer pointers after each copy.
|
||||
-- * 'False' means we should increment the buffer pointers after each copy.
|
||||
| forall n .
|
||||
MemSet !(Value X86_64 ids (BVType 64))
|
||||
-- /\ Number of values to assign
|
||||
!(Value X86_64 ids (BVType n))
|
||||
-- /\ Value to assign
|
||||
!(Value X86_64 ids (BVType 64))
|
||||
-- /\ Address to start assigning from.
|
||||
!(Value X86_64 ids BoolType)
|
||||
-- /\ Direction flag
|
||||
|
||||
instance PrettyF X86Stmt where
|
||||
prettyF (WriteLoc loc rhs) = pretty loc <+> text ":=" <+> ppValue 0 rhs
|
||||
prettyF (StoreX87Control addr) = pretty addr <+> text ":= x87_control"
|
||||
prettyF (MemCopy sz cnt src dest rev) =
|
||||
text "memcopy" <+> parens (hcat $ punctuate comma args)
|
||||
where args = [pretty sz, pretty cnt, pretty src, pretty dest, pretty rev]
|
||||
prettyF (MemSet cnt val dest d) =
|
||||
text "memset" <+> parens (hcat $ punctuate comma args)
|
||||
where args = [pretty cnt, pretty val, pretty dest, pretty d]
|
||||
|
||||
rewriteX86Stmt :: X86Stmt src -> Rewriter X86_64 src tgt ()
|
||||
rewriteX86Stmt f =
|
||||
case f of
|
||||
WriteLoc loc rhs -> do
|
||||
tgtStmt <-
|
||||
WriteLoc loc
|
||||
<$> rewriteValue rhs
|
||||
appendRewrittenArchStmt tgtStmt
|
||||
StoreX87Control addr -> do
|
||||
tgtStmt <-
|
||||
StoreX87Control
|
||||
<$> rewriteValue addr
|
||||
appendRewrittenArchStmt tgtStmt
|
||||
MemCopy bc cnt src dest dir -> do
|
||||
tgtStmt <-
|
||||
MemCopy bc
|
||||
<$> rewriteValue cnt
|
||||
<*> rewriteValue src
|
||||
<*> rewriteValue dest
|
||||
<*> rewriteValue dir
|
||||
appendRewrittenArchStmt tgtStmt
|
||||
MemSet cnt val dest dir -> do
|
||||
tgtStmt <-
|
||||
MemSet
|
||||
<$> rewriteValue cnt
|
||||
<*> rewriteValue val
|
||||
<*> rewriteValue dest
|
||||
<*> rewriteValue dir
|
||||
appendRewrittenArchStmt tgtStmt
|
||||
|
||||
valuesInX86Stmt :: X86Stmt ids -> [Some (Value X86_64 ids)]
|
||||
valuesInX86Stmt (WriteLoc _ rhs) = [Some rhs]
|
||||
valuesInX86Stmt (StoreX87Control addr) = [Some addr]
|
||||
valuesInX86Stmt (MemCopy _ cnt src dest d) = [ Some cnt, Some src, Some dest, Some d ]
|
||||
valuesInX86Stmt (MemSet cnt val dest d) = [ Some cnt, Some val, Some dest, Some d ]
|
||||
|
||||
refsInX86Stmt :: X86Stmt ids -> Set (Some (AssignId ids))
|
||||
refsInX86Stmt = assignIdSetFromValues . valuesInX86Stmt
|
||||
|
||||
instance StmtHasRefs X86Stmt where
|
||||
refsInStmt = refsInX86Stmt
|
64
x86/src/Data/Macaw/X86/Conditions.hs
Normal file
64
x86/src/Data/Macaw/X86/Conditions.hs
Normal file
@ -0,0 +1,64 @@
|
||||
{-|
|
||||
Copyright : (c) Galois, Inc 2015-2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This defines the semantics of the different condition code.
|
||||
-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
module Data.Macaw.X86.Conditions
|
||||
( ConditionalDef(..)
|
||||
, conditionalDefs
|
||||
) where
|
||||
|
||||
import Data.Macaw.Types (BoolType)
|
||||
|
||||
import Data.Macaw.X86.Monad
|
||||
|
||||
-- Constants for defining semantics of different condition flags.
|
||||
cond_a, cond_ae, cond_b, cond_be, cond_g, cond_ge, cond_l, cond_le, cond_o, cond_p, cond_s, cond_z,
|
||||
cond_no, cond_np, cond_ns, cond_nz :: Semantics m => m (Value m BoolType)
|
||||
|
||||
cond_a = (\c z -> boolAnd (boolNot c) (boolNot z)) <$> get cf_loc <*> get zf_loc
|
||||
cond_ae = boolNot <$> get cf_loc
|
||||
cond_b = get cf_loc
|
||||
cond_be = boolOr <$> get cf_loc <*> get zf_loc
|
||||
cond_g = (\z s o -> boolAnd (boolNot z) (boolEq s o)) <$> get zf_loc <*> get sf_loc <*> get of_loc
|
||||
cond_le = (\z s o -> boolOr z (boolXor s o)) <$> get zf_loc <*> get sf_loc <*> get of_loc
|
||||
cond_ge = (\s o -> boolEq s o) <$> get sf_loc <*> get of_loc
|
||||
cond_l = (\s o -> boolXor s o) <$> get sf_loc <*> get of_loc
|
||||
cond_o = get of_loc
|
||||
cond_p = get pf_loc
|
||||
cond_s = get sf_loc
|
||||
cond_z = get zf_loc
|
||||
cond_no = boolNot <$> cond_o
|
||||
cond_np = boolNot <$> cond_p
|
||||
cond_ns = boolNot <$> cond_s
|
||||
cond_nz = boolNot <$> cond_z
|
||||
|
||||
newtype ConditionalDef = ConditionalDef (forall m . Semantics m => m (Value m BoolType))
|
||||
|
||||
-- conditional instruction support (cmovcc, jcc)
|
||||
conditionalDefs :: [(String, ConditionalDef)]
|
||||
conditionalDefs = [ mk "a" cond_a
|
||||
, mk "ae" cond_ae
|
||||
, mk "b" cond_b
|
||||
, mk "be" cond_be
|
||||
, mk "g" cond_g
|
||||
, mk "ge" cond_ge
|
||||
, mk "l" cond_l
|
||||
, mk "le" cond_le
|
||||
, mk "o" cond_o
|
||||
, mk "p" cond_p
|
||||
, mk "s" cond_s
|
||||
, mk "z" cond_z
|
||||
, mk "e" cond_z
|
||||
, mk "ne" cond_nz
|
||||
, mk "no" cond_no
|
||||
, mk "np" cond_np
|
||||
, mk "ns" cond_ns
|
||||
, mk "nz" cond_nz
|
||||
]
|
||||
where mk :: String
|
||||
-> (forall m . Semantics m => m (Value m BoolType))
|
||||
-> (String, ConditionalDef)
|
||||
mk k v = (k, ConditionalDef v)
|
143
x86/src/Data/Macaw/X86/Flexdis.hs
Normal file
143
x86/src/Data/Macaw/X86/Flexdis.hs
Normal file
@ -0,0 +1,143 @@
|
||||
{-
|
||||
Copyright : (c) Galois, Inc 2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This provides a facility for disassembling x86 instructions from a
|
||||
Macaw memory objec.t
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
module Data.Macaw.X86.Flexdis
|
||||
( MemoryByteReader
|
||||
, runMemoryByteReader
|
||||
, readInstruction
|
||||
) where
|
||||
|
||||
import Control.Monad.Except
|
||||
import Control.Monad.State.Strict
|
||||
import qualified Data.ByteString as BS
|
||||
import Data.Word
|
||||
|
||||
import Data.Macaw.Memory
|
||||
import qualified Data.Macaw.Memory.Permissions as Perm
|
||||
|
||||
import qualified Flexdis86 as Flexdis
|
||||
import Flexdis86.ByteReader
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- MemStream
|
||||
|
||||
data PrevData w = PrevData { prevBytes :: [Word8]
|
||||
, prevRanges :: [SegmentRange w]
|
||||
}
|
||||
|
||||
emptyPrevData :: PrevData w
|
||||
emptyPrevData = PrevData { prevBytes = [], prevRanges = [] }
|
||||
|
||||
consByte :: Word8 -> PrevData w -> PrevData w
|
||||
consByte w pd = pd { prevBytes = w:prevBytes pd
|
||||
}
|
||||
|
||||
prevSegments :: PrevData w -> [SegmentRange w]
|
||||
prevSegments pd | null (prevBytes pd) = reverse (prevRanges pd)
|
||||
| otherwise = reverse (prevRanges pd) ++ [ByteRegion (BS.pack (prevBytes pd))]
|
||||
|
||||
-- | A stream of memory
|
||||
data MemStream w = MS { msSegment :: !(MemSegment w)
|
||||
-- ^ The current segment
|
||||
, msStart :: !(MemWord w)
|
||||
-- ^ The initial offset for the stream.
|
||||
, msPrev :: !(PrevData w)
|
||||
-- ^ The values read so far.
|
||||
, msOffset :: !(MemWord w)
|
||||
-- ^ The current address
|
||||
, msNext :: ![SegmentRange w]
|
||||
-- ^ The next bytes to read.
|
||||
}
|
||||
|
||||
msStartAddr :: MemWidth w => MemStream w -> MemAddr w
|
||||
msStartAddr ms = relativeSegmentAddr segOff
|
||||
where Just segOff = resolveSegmentOff (msSegment ms) (msStart ms)
|
||||
|
||||
msAddr :: MemWidth w => MemStream w -> MemAddr w
|
||||
msAddr ms = relativeSegmentAddr segOff
|
||||
where Just segOff = resolveSegmentOff (msSegment ms) (msOffset ms)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- MemoryByteReader
|
||||
|
||||
newtype MemoryByteReader w a = MBR { unMBR :: ExceptT (MemoryError w) (State (MemStream w)) a }
|
||||
deriving (Functor, Applicative, MonadError (MemoryError w))
|
||||
|
||||
instance MemWidth w => Monad (MemoryByteReader w) where
|
||||
return = MBR . return
|
||||
MBR m >>= f = MBR $ m >>= unMBR . f
|
||||
fail msg = do
|
||||
addr <- MBR $ gets msAddr
|
||||
throwError $ UserMemoryError addr msg
|
||||
|
||||
-- | Create a memory stream pointing to given address, and return pair whose
|
||||
-- first element is the value read or an error, and whose second element is
|
||||
-- the address of the next value to read.
|
||||
runMemoryByteReader :: Memory w
|
||||
-> Perm.Flags
|
||||
-- ^ Permissions that memory accesses are expected to
|
||||
-- satisfy.
|
||||
-- Added so we can check for read and/or execute permission.
|
||||
-> MemSegmentOff w -- ^ Starting segment
|
||||
-> MemoryByteReader w a -- ^ Byte reader to read values from.
|
||||
-> Either (MemoryError w) (a, MemWord w)
|
||||
runMemoryByteReader mem reqPerm addr (MBR m) = do
|
||||
addrWidthClass (memAddrWidth mem) $ do
|
||||
let seg = msegSegment addr
|
||||
if not (segmentFlags seg `Perm.hasPerm` reqPerm) then
|
||||
Left $ PermissionsError (relativeSegmentAddr addr)
|
||||
else do
|
||||
contents <- addrContentsAfter mem (relativeSegmentAddr addr)
|
||||
let ms0 = MS { msSegment = seg
|
||||
, msStart = msegOffset addr
|
||||
, msPrev = emptyPrevData
|
||||
, msOffset = msegOffset addr
|
||||
, msNext = contents
|
||||
}
|
||||
case runState (runExceptT m) ms0 of
|
||||
(Left e, _) -> Left e
|
||||
(Right v, ms) -> Right (v, msOffset ms)
|
||||
|
||||
instance MemWidth w => ByteReader (MemoryByteReader w) where
|
||||
readByte = do
|
||||
ms <- MBR get
|
||||
-- If remaining bytes are empty
|
||||
case msNext ms of
|
||||
[] ->
|
||||
MBR $ throwError $ AccessViolation (msAddr ms)
|
||||
-- Throw error if we try to read a relocation as a symbolic reference
|
||||
SymbolicRef{}:_ -> do
|
||||
MBR $ throwError $ UnexpectedRelocation (msAddr ms)
|
||||
ByteRegion bs:rest -> do
|
||||
if BS.null bs then do
|
||||
throwError $ AccessViolation (msAddr ms)
|
||||
else do
|
||||
let v = BS.head bs
|
||||
let ms' = ms { msPrev = consByte v (msPrev ms)
|
||||
, msOffset = msOffset ms + 1
|
||||
, msNext = ByteRegion (BS.tail bs) : rest
|
||||
}
|
||||
MBR $ v <$ put ms'
|
||||
invalidInstruction = do
|
||||
ms <- MBR $ get
|
||||
throwError $ InvalidInstruction (msStartAddr ms) (prevSegments (msPrev ms))
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- readInstruction
|
||||
|
||||
-- | Read instruction at a given memory address.
|
||||
readInstruction :: Memory 64
|
||||
-> MemSegmentOff 64
|
||||
-- ^ Address to read from.
|
||||
-> Either (MemoryError 64)
|
||||
(Flexdis.InstructionInstance, MemWord 64)
|
||||
readInstruction mem addr = runMemoryByteReader mem Perm.execute addr m
|
||||
where m = Flexdis.disassembleInstruction
|
357
x86/src/Data/Macaw/X86/Getters.hs
Normal file
357
x86/src/Data/Macaw/X86/Getters.hs
Normal file
@ -0,0 +1,357 @@
|
||||
{-|
|
||||
Copyright : (c) Galois, Inc 2015-2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This defines operations for mapping flexdis values to Macaw values.
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
module Data.Macaw.X86.Getters
|
||||
( SomeBV(..)
|
||||
, getBVAddress
|
||||
, readBVAddress
|
||||
, getSomeBVLocation
|
||||
, getBVLocation
|
||||
, getSomeBVValue
|
||||
, getBVValue
|
||||
, getSignExtendedValue
|
||||
, truncateBVValue
|
||||
, getJumpTarget
|
||||
, FPLocation(..)
|
||||
, getFPLocation
|
||||
, FPValue(..)
|
||||
, getFPValue
|
||||
, HasRepSize(..)
|
||||
, getAddrRegOrSegment
|
||||
, getAddrRegSegmentOrImm
|
||||
, readXMMValue
|
||||
-- * Reprs
|
||||
, byteMemRepr
|
||||
, wordMemRepr
|
||||
, dwordMemRepr
|
||||
, qwordMemRepr
|
||||
, xmmMemRepr
|
||||
, floatMemRepr
|
||||
, doubleMemRepr
|
||||
) where
|
||||
|
||||
import Data.Parameterized.NatRepr
|
||||
import Data.Parameterized.Some
|
||||
import qualified Flexdis86 as F
|
||||
import GHC.TypeLits (KnownNat)
|
||||
|
||||
import Data.Macaw.CFG (MemRepr(..))
|
||||
import Data.Macaw.Memory (Endianness(..))
|
||||
import Data.Macaw.Types (FloatType, BVType, n8, n16, n32, n64, typeWidth)
|
||||
import Data.Macaw.X86.Monad
|
||||
import Data.Macaw.X86.X86Reg (X86Reg(..))
|
||||
|
||||
byteMemRepr :: MemRepr (BVType 8)
|
||||
byteMemRepr = BVMemRepr (knownNat :: NatRepr 1) LittleEndian
|
||||
|
||||
wordMemRepr :: MemRepr (BVType 16)
|
||||
wordMemRepr = BVMemRepr (knownNat :: NatRepr 2) LittleEndian
|
||||
|
||||
dwordMemRepr :: MemRepr (BVType 32)
|
||||
dwordMemRepr = BVMemRepr (knownNat :: NatRepr 4) LittleEndian
|
||||
|
||||
qwordMemRepr :: MemRepr (BVType 64)
|
||||
qwordMemRepr = BVMemRepr (knownNat :: NatRepr 8) LittleEndian
|
||||
|
||||
floatMemRepr :: MemRepr (BVType 32)
|
||||
floatMemRepr = BVMemRepr (knownNat :: NatRepr 4) LittleEndian
|
||||
|
||||
doubleMemRepr :: MemRepr (BVType 64)
|
||||
doubleMemRepr = BVMemRepr (knownNat :: NatRepr 8) LittleEndian
|
||||
|
||||
x87MemRepr :: MemRepr (BVType 80)
|
||||
x87MemRepr = BVMemRepr (knownNat :: NatRepr 10) LittleEndian
|
||||
|
||||
xmmMemRepr :: MemRepr (BVType 128)
|
||||
xmmMemRepr = BVMemRepr (knownNat :: NatRepr 16) LittleEndian
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Getters
|
||||
|
||||
-- | Calculates the address corresponding to an AddrRef
|
||||
getBVAddress :: forall m. Semantics m => F.AddrRef -> m (Value m (BVType 64))
|
||||
getBVAddress ar =
|
||||
case ar of
|
||||
-- FIXME: It seems that there is no sign extension here ...
|
||||
F.Addr_32 seg m_r32 m_int_r32 i32 -> do
|
||||
base <- case m_r32 of
|
||||
Nothing -> return $! bvKLit 0
|
||||
Just r -> get (reg_low32 (X86_GP $ F.reg32_reg r))
|
||||
scale <- case m_int_r32 of
|
||||
Nothing -> return $! bvKLit 0
|
||||
Just (i, r) -> bvTrunc n32 . bvMul (bvLit n32 (toInteger i))
|
||||
<$> get (reg_low32 (X86_GP $ F.reg32_reg r))
|
||||
let offset = uext n64 (base `bvAdd` scale `bvAdd` bvLit n32 (toInteger (F.displacementInt i32)))
|
||||
mk_absolute seg offset
|
||||
F.IP_Offset_32 _seg _i32 -> fail "IP_Offset_32"
|
||||
F.Offset_32 _seg _w32 -> fail "Offset_32"
|
||||
F.Offset_64 seg w64 -> do
|
||||
mk_absolute seg (bvLit n64 (toInteger w64))
|
||||
F.Addr_64 seg m_r64 m_int_r64 i32 -> do
|
||||
base <- case m_r64 of
|
||||
Nothing -> return v0_64
|
||||
Just r -> get (fullRegister $ X86_GP r)
|
||||
scale <- case m_int_r64 of
|
||||
Nothing -> return v0_64
|
||||
Just (i, r) -> bvTrunc n64 . bvMul (bvLit n64 (toInteger i))
|
||||
<$> get (fullRegister $ X86_GP r)
|
||||
let offset = base `bvAdd` scale `bvAdd` bvLit n64 (toInteger i32)
|
||||
mk_absolute seg offset
|
||||
F.IP_Offset_64 seg i32 -> do
|
||||
ip_val <- get rip
|
||||
mk_absolute seg (bvAdd (bvLit n64 (toInteger i32)) ip_val)
|
||||
where
|
||||
v0_64 = bvLit n64 0
|
||||
-- | Add the segment base to compute an absolute address.
|
||||
mk_absolute :: F.Segment -> Value m (BVType 64) -> m (Value m (BVType 64))
|
||||
mk_absolute seg offset
|
||||
-- In 64-bit mode the CS, DS, ES, and SS segment registers
|
||||
-- are forced to zero, and so segmentation is a nop.
|
||||
--
|
||||
-- We could nevertheless call 'getSegmentBase' in all cases
|
||||
-- here, but that adds a lot of noise to the AST in the common
|
||||
-- case of segments other than FS or GS.
|
||||
| seg == F.CS || seg == F.DS || seg == F.ES || seg == F.SS = return offset
|
||||
-- The FS and GS segments can be non-zero based in 64-bit mode.
|
||||
| otherwise = do
|
||||
base <- getSegmentBase seg
|
||||
return $ base `bvAdd` offset
|
||||
|
||||
readBVAddress :: Semantics m => F.AddrRef -> MemRepr tp -> m (Value m tp)
|
||||
readBVAddress ar repr =
|
||||
get . (`MemoryAddr` repr) =<< getBVAddress ar
|
||||
|
||||
-- | A bitvector value with a width that satisfies `SupportedBVWidth`.
|
||||
data SomeBV v where
|
||||
SomeBV :: SupportedBVWidth n => v (BVType n) -> SomeBV v
|
||||
|
||||
|
||||
-- | Extract the location of a bitvector value.
|
||||
getSomeBVLocation :: Semantics m => F.Value -> m (SomeBV (MLocation m))
|
||||
getSomeBVLocation v =
|
||||
case v of
|
||||
F.ControlReg cr -> pure $ SomeBV $ ControlReg cr
|
||||
F.DebugReg dr -> pure $ SomeBV $ DebugReg dr
|
||||
F.MMXReg mmx -> pure $ SomeBV $ x87reg_mmx $ X87_FPUReg mmx
|
||||
F.XMMReg xmm -> pure $ SomeBV $ fullRegister $ X86_XMMReg xmm
|
||||
F.SegmentValue s -> pure $ SomeBV $ SegmentReg s
|
||||
F.X87Register i -> mk (X87StackRegister i)
|
||||
F.FarPointer _ -> fail "FarPointer"
|
||||
-- SomeBV . (`MemoryAddr` byteMemRepr) <$> getBVAddress ar -- FIXME: what size here?
|
||||
F.VoidMem _ -> fail "VoidMem"
|
||||
F.Mem8 ar -> SomeBV . (`MemoryAddr` byteMemRepr) <$> getBVAddress ar
|
||||
F.Mem16 ar -> SomeBV . (`MemoryAddr` wordMemRepr) <$> getBVAddress ar
|
||||
F.Mem32 ar -> SomeBV . (`MemoryAddr` dwordMemRepr) <$> getBVAddress ar
|
||||
F.Mem64 ar -> SomeBV . (`MemoryAddr` qwordMemRepr) <$> getBVAddress ar
|
||||
F.Mem128 ar -> SomeBV . (`MemoryAddr` xmmMemRepr) <$> getBVAddress ar
|
||||
F.FPMem32 ar -> getBVAddress ar >>= mk . (`MemoryAddr` floatMemRepr)
|
||||
F.FPMem64 ar -> getBVAddress ar >>= mk . (`MemoryAddr` doubleMemRepr)
|
||||
F.FPMem80 ar -> getBVAddress ar >>= mk . (`MemoryAddr` x87MemRepr)
|
||||
F.ByteReg r
|
||||
| Just r64 <- F.is_low_reg r -> mk (reg_low8 $ X86_GP r64)
|
||||
| Just r64 <- F.is_high_reg r -> mk (reg_high8 $ X86_GP r64)
|
||||
| otherwise -> fail "unknown r8"
|
||||
F.WordReg r -> mk (reg_low16 (X86_GP $ F.reg16_reg r))
|
||||
F.DWordReg r -> mk (reg_low32 (X86_GP $ F.reg32_reg r))
|
||||
F.QWordReg r -> mk (fullRegister $ X86_GP r)
|
||||
F.ByteImm _ -> noImm
|
||||
F.WordImm _ -> noImm
|
||||
F.DWordImm _ -> noImm
|
||||
F.QWordImm _ -> noImm
|
||||
F.JumpOffset{} -> fail "Jump Offset is not a location."
|
||||
where
|
||||
noImm :: Monad m => m a
|
||||
noImm = fail "Immediate is not a location"
|
||||
mk :: (Applicative m, SupportedBVWidth n) => f (BVType n) -> m (SomeBV f)
|
||||
mk = pure . SomeBV
|
||||
|
||||
-- | Translate a flexdis value to a location with a particular width.
|
||||
getBVLocation :: Semantics m => F.Value -> NatRepr n -> m (MLocation m (BVType n))
|
||||
getBVLocation l expected = do
|
||||
SomeBV v <- getSomeBVLocation l
|
||||
case testEquality (typeWidth v) expected of
|
||||
Just Refl ->
|
||||
return v
|
||||
Nothing ->
|
||||
fail $ "Widths aren't equal: " ++ show (typeWidth v) ++ " and " ++ show expected
|
||||
|
||||
-- | Return a bitvector value.
|
||||
getSomeBVValue :: Semantics m => F.Value -> m (SomeBV (Value m))
|
||||
getSomeBVValue v =
|
||||
case v of
|
||||
F.ByteImm w -> return $ SomeBV $ bvLit n8 $ toInteger w
|
||||
F.WordImm w -> return $ SomeBV $ bvLit n16 $ toInteger w
|
||||
F.DWordImm w -> return $ SomeBV $ bvLit n32 $ toInteger w
|
||||
F.QWordImm w -> return $ SomeBV $ bvLit n64 $ toInteger w
|
||||
F.JumpOffset _ off -> return $ SomeBV $ bvLit n64 $ toInteger off
|
||||
_ -> do
|
||||
SomeBV l <- getSomeBVLocation v
|
||||
SomeBV <$> get l
|
||||
|
||||
-- | Translate a flexdis value to a value with a particular width.
|
||||
getBVValue :: Semantics m
|
||||
=> F.Value
|
||||
-> NatRepr n
|
||||
-> m (Value m (BVType n))
|
||||
getBVValue val expected = do
|
||||
SomeBV v <- getSomeBVValue val
|
||||
case testEquality (bv_width v) expected of
|
||||
Just Refl -> return v
|
||||
Nothing ->
|
||||
fail $ "Widths aren't equal: " ++ show (bv_width v) ++ " and " ++ show expected
|
||||
|
||||
-- | Get a value with the given width, sign extending as necessary.
|
||||
getSignExtendedValue :: forall m w
|
||||
. (Semantics m, 1 <= w)
|
||||
=> F.Value
|
||||
-> NatRepr w
|
||||
-> m (Value m (BVType w))
|
||||
getSignExtendedValue v out_w =
|
||||
case v of
|
||||
-- If an instruction can take a VoidMem, it needs to get it explicitly
|
||||
F.VoidMem _ar -> fail "VoidMem"
|
||||
F.Mem8 ar -> mk . (`MemoryAddr` byteMemRepr) =<< getBVAddress ar
|
||||
F.Mem16 ar -> mk . (`MemoryAddr` wordMemRepr) =<< getBVAddress ar
|
||||
F.Mem32 ar -> mk . (`MemoryAddr` dwordMemRepr) =<< getBVAddress ar
|
||||
F.Mem64 ar -> mk . (`MemoryAddr` qwordMemRepr) =<< getBVAddress ar
|
||||
F.Mem128 ar -> mk . (`MemoryAddr` xmmMemRepr) =<< getBVAddress ar
|
||||
|
||||
F.ByteReg r
|
||||
| Just r64 <- F.is_low_reg r -> mk (reg_low8 $ X86_GP r64)
|
||||
| Just r64 <- F.is_high_reg r -> mk (reg_high8 $ X86_GP r64)
|
||||
| otherwise -> fail "unknown r8"
|
||||
F.WordReg r -> mk (reg_low16 (X86_GP $ F.reg16_reg r))
|
||||
F.DWordReg r -> mk (reg_low32 (X86_GP $ F.reg32_reg r))
|
||||
F.QWordReg r -> mk (fullRegister $ X86_GP r)
|
||||
F.XMMReg r -> mk (fullRegister $ X86_XMMReg r)
|
||||
|
||||
F.ByteImm i -> return $! bvLit out_w (toInteger i)
|
||||
F.WordImm i -> return $! bvLit out_w (toInteger i)
|
||||
F.DWordImm i -> return $! bvLit out_w (toInteger i)
|
||||
F.QWordImm i -> return $! bvLit out_w (toInteger i)
|
||||
|
||||
_ -> fail $ "getSignExtendedValue given unexpected width: " ++ show v
|
||||
where
|
||||
-- FIXME: what happens with signs etc?
|
||||
mk :: forall u
|
||||
. (1 <= u, KnownNat u)
|
||||
=> Location (Value m (BVType 64)) (BVType u)
|
||||
-> m (Value m (BVType w))
|
||||
mk l
|
||||
| Just LeqProof <- testLeq (knownNat :: NatRepr u) out_w =
|
||||
sext out_w <$> get l
|
||||
| otherwise =
|
||||
fail $ "getSignExtendedValue given bad value."
|
||||
|
||||
truncateBVValue :: (Monad m, IsValue v, 1 <= n)
|
||||
=> NatRepr n
|
||||
-> SomeBV v
|
||||
-> m (v (BVType n))
|
||||
truncateBVValue n (SomeBV v)
|
||||
| Just LeqProof <- testLeq n (bv_width v) = do
|
||||
return (bvTrunc n v)
|
||||
| otherwise =
|
||||
fail $ "Widths isn't >=: " ++ show (bv_width v) ++ " and " ++ show n
|
||||
|
||||
-- | Return the target of a call or jump instruction.
|
||||
getJumpTarget :: Semantics m
|
||||
=> F.Value
|
||||
-> m (Value m (BVType 64))
|
||||
getJumpTarget v =
|
||||
case v of
|
||||
F.Mem64 ar -> do
|
||||
a <- getBVAddress ar
|
||||
get (MemoryAddr a qwordMemRepr)
|
||||
F.QWordReg r -> get (fullRegister $ X86_GP r)
|
||||
F.JumpOffset _ off -> bvAdd (bvLit n64 (toInteger off)) <$> get rip
|
||||
_ -> fail "Unexpected argument"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Floating point
|
||||
|
||||
-- | This describes a floating point value including the type.
|
||||
data FPLocation m flt = FPLocation (FloatInfoRepr flt) (MLocation m (FloatType flt))
|
||||
|
||||
-- | This describes a floating point value including the type.
|
||||
data FPValue m flt = FPValue (FloatInfoRepr flt) (Value m (FloatType flt))
|
||||
|
||||
readFPLocation :: Semantics m => FPLocation m flt -> m (FPValue m flt)
|
||||
readFPLocation (FPLocation repr l) = FPValue repr <$> get l
|
||||
|
||||
-- | Read an address as a floating point vlaue
|
||||
getFPAddrLoc :: Semantics m => FloatInfoRepr flt -> F.AddrRef -> m (FPLocation m flt)
|
||||
getFPAddrLoc repr f_addr = do
|
||||
addr <- getBVAddress f_addr
|
||||
pure $ FPLocation repr (mkFPAddr repr addr)
|
||||
|
||||
-- | Get a floating point value from the argument.
|
||||
getFPLocation :: Semantics m => F.Value -> m (Some (FPLocation m))
|
||||
getFPLocation v =
|
||||
case v of
|
||||
F.FPMem32 ar -> Some <$> getFPAddrLoc SingleFloatRepr ar
|
||||
F.FPMem64 ar -> Some <$> getFPAddrLoc DoubleFloatRepr ar
|
||||
F.FPMem80 ar -> Some <$> getFPAddrLoc X86_80FloatRepr ar
|
||||
F.X87Register n -> pure $ Some $ FPLocation X86_80FloatRepr (X87StackRegister n)
|
||||
_ -> fail $ "Bad floating point argument."
|
||||
|
||||
-- | Get a floating point value from the argument.
|
||||
getFPValue :: Semantics m => F.Value -> m (Some (FPValue m))
|
||||
getFPValue v = getFPLocation v >>= \(Some l) -> Some <$> readFPLocation l
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Standard memory values
|
||||
|
||||
data HasRepSize f w = HasRepSize { _ppvWidth :: !(RepValSize w)
|
||||
, _ppvValue :: !(f (BVType w))
|
||||
}
|
||||
|
||||
-- | Gets the location to store the value poped from.
|
||||
-- These functions only support general purpose registers/addresses and segments.
|
||||
getAddrRegOrSegment :: forall m . Semantics m => F.Value -> m (Some (HasRepSize (MLocation m)))
|
||||
getAddrRegOrSegment v =
|
||||
case v of
|
||||
F.SegmentValue s -> pure $ Some $ HasRepSize WordRepVal (SegmentReg s)
|
||||
F.Mem8 ar -> Some . HasRepSize ByteRepVal . (`MemoryAddr` byteMemRepr) <$> getBVAddress ar
|
||||
F.Mem16 ar -> Some . HasRepSize WordRepVal . (`MemoryAddr` wordMemRepr) <$> getBVAddress ar
|
||||
F.Mem32 ar -> Some . HasRepSize DWordRepVal . (`MemoryAddr` dwordMemRepr) <$> getBVAddress ar
|
||||
F.Mem64 ar -> Some . HasRepSize QWordRepVal . (`MemoryAddr` qwordMemRepr) <$> getBVAddress ar
|
||||
|
||||
F.ByteReg r
|
||||
| Just r64 <- F.is_low_reg r -> pure $ Some $ HasRepSize ByteRepVal (reg_low8 $ X86_GP r64)
|
||||
| Just r64 <- F.is_high_reg r -> pure $ Some $ HasRepSize ByteRepVal (reg_high8 $ X86_GP r64)
|
||||
| otherwise -> fail "unknown r8"
|
||||
F.WordReg r -> pure $ Some $ HasRepSize WordRepVal (reg_low16 (X86_GP $ F.reg16_reg r))
|
||||
F.DWordReg r -> pure $ Some $ HasRepSize DWordRepVal (reg_low32 (X86_GP $ F.reg32_reg r))
|
||||
F.QWordReg r -> pure $ Some $ HasRepSize QWordRepVal (fullRegister $ X86_GP r)
|
||||
_ -> fail $ "Argument " ++ show v ++ " not supported."
|
||||
|
||||
-- | Gets a value that can be pushed.
|
||||
-- These functions only support general purpose registers/addresses and segments.
|
||||
getAddrRegSegmentOrImm :: forall m . Semantics m => F.Value -> m (Some (HasRepSize (Value m)))
|
||||
getAddrRegSegmentOrImm v =
|
||||
case v of
|
||||
F.ByteImm w -> return $ Some $ HasRepSize ByteRepVal $ bvLit n8 (toInteger w)
|
||||
F.WordImm w -> return $ Some $ HasRepSize WordRepVal $ bvLit n16 (toInteger w)
|
||||
F.DWordImm w -> return $ Some $ HasRepSize DWordRepVal $ bvLit n32 (toInteger w)
|
||||
F.QWordImm w -> return $ Some $ HasRepSize QWordRepVal $ bvLit n64 (toInteger w)
|
||||
_ -> do
|
||||
Some (HasRepSize rep l) <- getAddrRegOrSegment v
|
||||
Some . HasRepSize rep <$> get l
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- SSE
|
||||
|
||||
-- | Get a XMM value
|
||||
readXMMValue :: Semantics m => F.Value -> m (Value m (BVType 128))
|
||||
readXMMValue (F.XMMReg r) = get $ fullRegister $ X86_XMMReg r
|
||||
readXMMValue (F.Mem128 a) = readBVAddress a xmmMemRepr
|
||||
readXMMValue _ = fail "XMM Instruction given unexpected value."
|
261
x86/src/Data/Macaw/X86/InstructionDef.hs
Normal file
261
x86/src/Data/Macaw/X86/InstructionDef.hs
Normal file
@ -0,0 +1,261 @@
|
||||
{-|
|
||||
Copyright : (c) Galois, Inc 2015-2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This defines the instruction def type, which contains the
|
||||
semantic definition of a function.
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
module Data.Macaw.X86.InstructionDef
|
||||
( InstructionDef
|
||||
, InstructionSemantics(..)
|
||||
, defVariadic
|
||||
, defConditionals
|
||||
-- * Nullary function helper
|
||||
, defNullary
|
||||
, defNullaryPrefix
|
||||
-- * Unary instruction helpers
|
||||
, defUnary
|
||||
, defUnaryLoc
|
||||
, defUnaryKnown
|
||||
, defUnaryV
|
||||
, defUnaryFPL
|
||||
, defUnaryFPV
|
||||
-- * Binary instruction helpers
|
||||
, defBinary
|
||||
, defBinaryLV
|
||||
, defBinaryLVpoly
|
||||
, defBinaryLVge
|
||||
, defBinaryKnown
|
||||
, defBinaryXMMV
|
||||
, defBinaryLL
|
||||
, defFPBinaryImplicit
|
||||
-- * Ternary instruction helpers
|
||||
, defTernary
|
||||
, defTernaryLVV
|
||||
) where
|
||||
|
||||
import qualified Flexdis86 as F
|
||||
import Data.Macaw.Types
|
||||
import Data.Parameterized.NatRepr
|
||||
import Data.Parameterized.Some
|
||||
import GHC.TypeLits (KnownNat)
|
||||
|
||||
import Data.Macaw.X86.Conditions
|
||||
import Data.Macaw.X86.Getters
|
||||
import Data.Macaw.X86.Monad
|
||||
|
||||
-- This is a wrapper around the semantics of an instruction.
|
||||
newtype InstructionSemantics
|
||||
= InstructionSemantics { _unInstructionSemantics
|
||||
:: forall m. Semantics m
|
||||
=> F.InstructionInstance
|
||||
-> m ()
|
||||
}
|
||||
|
||||
-- | The information needed to define an instruction semantics.
|
||||
type InstructionDef = (String, InstructionSemantics)
|
||||
|
||||
-- | Create a instruction that potentially takes any number of arguments.
|
||||
defVariadic :: String
|
||||
-> (forall m. Semantics m => F.LockPrefix -> [F.Value] -> m ())
|
||||
-> InstructionDef
|
||||
defVariadic mnemonic f =
|
||||
(mnemonic, InstructionSemantics (\ii -> f (F.iiLockPrefix ii) (fst <$> F.iiArgs ii)))
|
||||
|
||||
-- | Define an instruction that expects no arguments.
|
||||
defNullary :: String
|
||||
-> (forall m . Semantics m => m ())
|
||||
-> InstructionDef
|
||||
defNullary mnem f = defVariadic mnem (\_ _ -> f)
|
||||
|
||||
-- | Define an instruction that expects no arguments other than a prefix
|
||||
defNullaryPrefix :: String
|
||||
-> (forall m. Semantics m => F.LockPrefix -> m ())
|
||||
-> InstructionDef
|
||||
defNullaryPrefix mnem f = defVariadic mnem (\pfx _ -> f pfx)
|
||||
|
||||
-- | Define an instruction that expects a single argument
|
||||
defUnary :: String
|
||||
-- ^ Instruction mnemonic
|
||||
-> (forall m . Semantics m => F.LockPrefix -> F.Value -> m ())
|
||||
-- ^ Sementic definition
|
||||
-> InstructionDef
|
||||
defUnary mnem f = defVariadic mnem $ \pfx vs ->
|
||||
case vs of
|
||||
[v] -> f pfx v
|
||||
_ -> fail $ "defUnary: " ++ mnem ++ " expecting 1 arguments, got " ++ show (length vs)
|
||||
|
||||
-- | Defines an instruction that expects a single bitvec location as an argument.
|
||||
defUnaryLoc :: String
|
||||
-> (forall m n. IsLocationBV m n => MLocation m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defUnaryLoc s f = defUnary s $ \_ val -> do
|
||||
SomeBV v <- getSomeBVLocation val
|
||||
f v
|
||||
|
||||
-- | Defines an instruction that expects a bitvector location with a known fixed width.
|
||||
defUnaryKnown :: KnownNat n
|
||||
=> String
|
||||
-> (forall m . Semantics m => MLocation m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defUnaryKnown s f = defUnary s $ \_ loc -> f =<< getBVLocation loc knownNat
|
||||
|
||||
-- | Defines an instruction that expects a single bitvec value as an argument.
|
||||
defUnaryV :: String
|
||||
-> (forall m n. IsLocationBV m n => Value m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defUnaryV s f = defUnary s $ \_ val -> do
|
||||
SomeBV v <- getSomeBVValue val
|
||||
f v
|
||||
|
||||
defUnaryFPL :: String
|
||||
-> (forall m flt. Semantics m => FloatInfoRepr flt -> MLocation m (FloatType flt) -> m ())
|
||||
-> InstructionDef
|
||||
defUnaryFPL mnem f = defUnary mnem $ \_ v -> do
|
||||
Some (FPLocation repr loc) <- getFPLocation v
|
||||
f repr loc
|
||||
|
||||
defUnaryFPV :: String
|
||||
-> (forall m flt. Semantics m => FloatInfoRepr flt -> Value m (FloatType flt) -> m ())
|
||||
-> InstructionDef
|
||||
defUnaryFPV mnem f = defUnary mnem $ \_ v -> do
|
||||
Some (FPValue repr val) <- getFPValue v
|
||||
f repr val
|
||||
|
||||
-- | Define an instruction that expects two arguments.
|
||||
defBinary :: String
|
||||
-> (forall m . Semantics m => F.LockPrefix -> F.Value -> F.Value -> m ())
|
||||
-> InstructionDef
|
||||
defBinary mnem f = defVariadic mnem $ \pfx vs ->
|
||||
case vs of
|
||||
[v, v'] -> f pfx v v'
|
||||
_ -> fail $ "defBinary: " ++ mnem ++ ": expecting 2 arguments, got " ++ show (length vs)
|
||||
|
||||
defBinaryLV :: String
|
||||
-> (forall m n. IsLocationBV m n => MLocation m (BVType n) -> Value m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defBinaryLV mnem f = defBinary mnem $ \_ loc val -> do
|
||||
SomeBV l <- getSomeBVLocation loc
|
||||
v <- getSignExtendedValue val (typeWidth l)
|
||||
f l v
|
||||
|
||||
-- | This defines a instruction that expects a location and a value that may have
|
||||
-- differing widths
|
||||
defBinaryLVpoly :: String
|
||||
-> (forall m n n'
|
||||
. (IsLocationBV m n, 1 <= n')
|
||||
=> MLocation m (BVType n) -> Value m (BVType n') -> m ())
|
||||
-> InstructionDef
|
||||
defBinaryLVpoly mnem f = defBinary mnem $ \_ loc val -> do
|
||||
SomeBV l <- getSomeBVLocation loc
|
||||
SomeBV v <- getSomeBVValue val
|
||||
f l v
|
||||
|
||||
-- | This defines a instruction that expects a location and a value that may have
|
||||
-- differing widths, but the location must be larger than the value.
|
||||
defBinaryLVge :: String
|
||||
-> (forall m n n'
|
||||
. (IsLocationBV m n, 1 <= n', n' <= n)
|
||||
=> MLocation m (BVType n)
|
||||
-> Value m (BVType n')
|
||||
-> m ())
|
||||
-> InstructionDef
|
||||
defBinaryLVge mnem f = defBinaryLVpoly mnem $ \l v -> do
|
||||
Just LeqProof <- return $ testLeq (bv_width v) (typeWidth l)
|
||||
f l v
|
||||
|
||||
-- | Define an instruction from a function with fixed widths kmown at compile time/.
|
||||
defBinaryKnown :: (KnownNat n, KnownNat n')
|
||||
=> String
|
||||
-> (forall m . Semantics m => MLocation m (BVType n) -> Value m (BVType n') -> m ())
|
||||
-> InstructionDef
|
||||
defBinaryKnown mnem f = defBinary mnem $ \_ loc val -> do
|
||||
l <- getBVLocation loc knownNat
|
||||
v <- getBVValue val knownNat
|
||||
f l v
|
||||
|
||||
defBinaryXMMV :: ( KnownNat n
|
||||
, 1 <= n
|
||||
)
|
||||
=> String
|
||||
-> (forall m . Semantics m => MLocation m XMMType -> Value m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defBinaryXMMV mnem f = defBinary mnem $ \_ loc val -> do
|
||||
l <- getBVLocation loc n128
|
||||
v <- truncateBVValue knownNat =<< getSomeBVValue val
|
||||
f l v
|
||||
|
||||
defBinaryLL :: String
|
||||
-> (forall m n. (IsLocationBV m n, 1 <= n)
|
||||
=> F.LockPrefix
|
||||
-> MLocation m (BVType n) -> MLocation m (BVType n) -> m ())
|
||||
-> InstructionDef
|
||||
defBinaryLL mnem f = defBinary mnem $ \pfx loc loc' -> do
|
||||
SomeBV l <- getSomeBVLocation loc
|
||||
l' <- getBVLocation loc' (typeWidth l)
|
||||
f pfx l l'
|
||||
|
||||
-- | Define a function that takes either two floating point arguments.
|
||||
--
|
||||
-- If only one argument is provided, it is used as the second argument,
|
||||
-- and the first argument is implicitly the top of the floating point stack.
|
||||
defFPBinaryImplicit :: String
|
||||
-> (forall m flt_d flt_s
|
||||
. Semantics m
|
||||
=> FloatInfoRepr flt_d
|
||||
-> MLocation m (FloatType flt_d)
|
||||
-> FloatInfoRepr flt_s
|
||||
-> Value m (FloatType flt_s)
|
||||
-> m ())
|
||||
-> InstructionDef
|
||||
defFPBinaryImplicit mnem f = defVariadic mnem $ \_ vs -> do
|
||||
case vs of
|
||||
[v] -> do
|
||||
Some (FPValue repr val) <- getFPValue v
|
||||
f X86_80FloatRepr (X87StackRegister 0) repr val
|
||||
[loc, val] -> do
|
||||
l <- getBVLocation loc knownNat
|
||||
v <- getBVValue val knownNat
|
||||
f X86_80FloatRepr l X86_80FloatRepr v
|
||||
_ -> do
|
||||
fail $ "deFPBinImplicit " ++ mnem ++ ": expecting 2 arguments, got " ++ show (length vs)
|
||||
|
||||
-- | Define an instruction that expects three arguments.
|
||||
defTernary :: String
|
||||
-> (forall m . Semantics m => F.LockPrefix -> F.Value -> F.Value -> F.Value -> m ())
|
||||
-> InstructionDef
|
||||
defTernary mnem f = defVariadic mnem $ \pfx vs -> do
|
||||
case vs of
|
||||
[v, v', v''] -> f pfx v v' v''
|
||||
_ ->
|
||||
fail $ "defTernary: " ++ mnem ++ ": expecting 3 arguments, got " ++ show (length vs)
|
||||
|
||||
defTernaryLVV :: String
|
||||
-> (forall m k n
|
||||
. (IsLocationBV m n, 1 <= k, k <= n)
|
||||
=> MLocation m (BVType n)
|
||||
-> Value m (BVType n)
|
||||
-> Value m (BVType k)
|
||||
-> m ())
|
||||
-> InstructionDef
|
||||
defTernaryLVV mnem f = defTernary mnem $ \_ loc val1 val2 -> do
|
||||
SomeBV l <- getSomeBVLocation loc
|
||||
v1 <- getBVValue val1 (typeWidth l)
|
||||
SomeBV v2 <- getSomeBVValue val2
|
||||
Just LeqProof <- return $ testLeq (bv_width v2) (bv_width v1)
|
||||
f l v1 v2
|
||||
|
||||
-- | This generates a list of instruction definitinos -- one for each conditional predicate.
|
||||
defConditionals :: String
|
||||
-> (String
|
||||
-> (forall m. Semantics m => m (Value m BoolType))
|
||||
-> InstructionDef)
|
||||
-> [InstructionDef]
|
||||
defConditionals pfx mkop = mk <$> conditionalDefs
|
||||
where
|
||||
mk :: (String, ConditionalDef) -> InstructionDef
|
||||
mk (suffix, ConditionalDef sop) = mkop (pfx ++ suffix) sop
|
1528
x86/src/Data/Macaw/X86/Monad.hs
Normal file
1528
x86/src/Data/Macaw/X86/Monad.hs
Normal file
File diff suppressed because it is too large
Load Diff
2644
x86/src/Data/Macaw/X86/Semantics.hs
Normal file
2644
x86/src/Data/Macaw/X86/Semantics.hs
Normal file
File diff suppressed because it is too large
Load Diff
1946
x86/src/Data/Macaw/X86/SyscallInfo/FreeBSD.hs
Normal file
1946
x86/src/Data/Macaw/X86/SyscallInfo/FreeBSD.hs
Normal file
File diff suppressed because it is too large
Load Diff
1635
x86/src/Data/Macaw/X86/SyscallInfo/Linux.hs
Normal file
1635
x86/src/Data/Macaw/X86/SyscallInfo/Linux.hs
Normal file
File diff suppressed because it is too large
Load Diff
72
x86/src/Data/Macaw/X86/X86Flag.hs
Normal file
72
x86/src/Data/Macaw/X86/X86Flag.hs
Normal file
@ -0,0 +1,72 @@
|
||||
{-
|
||||
Copyright : (c) Galois, Inc 2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This contains a type for modeling the X86 flags
|
||||
-}
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
module Data.Macaw.X86.X86Flag
|
||||
( X86Flag
|
||||
, flagIndex
|
||||
, pattern CF
|
||||
, pattern PF
|
||||
, pattern AF
|
||||
, pattern ZF
|
||||
, pattern SF
|
||||
, pattern TF
|
||||
, pattern IF
|
||||
, pattern DF
|
||||
, pattern OF
|
||||
, flagList
|
||||
) where
|
||||
|
||||
import qualified Data.Vector as V
|
||||
import Data.Word
|
||||
|
||||
-- | X86 flag
|
||||
newtype X86Flag = X86Flag { flagIndex :: Word8 }
|
||||
deriving (Eq, Ord)
|
||||
|
||||
flagNames :: V.Vector String
|
||||
flagNames = V.fromList
|
||||
[ "cf", "RESERVED", "pf", "RESERVED", "af", "RESERVED"
|
||||
, "zf", "sf", "tf", "if", "df", "of"
|
||||
, "iopl", "nt", "SBZ", "rf", "vm", "ac", "vif", "vip", "id"
|
||||
]
|
||||
|
||||
instance Show X86Flag where
|
||||
show (X86Flag i) =
|
||||
case flagNames V.!? fromIntegral i of
|
||||
Just nm -> nm
|
||||
Nothing -> "Unknown" ++ show i
|
||||
|
||||
pattern CF :: X86Flag
|
||||
pattern CF = X86Flag 0
|
||||
|
||||
pattern PF :: X86Flag
|
||||
pattern PF = X86Flag 2
|
||||
|
||||
pattern AF :: X86Flag
|
||||
pattern AF = X86Flag 4
|
||||
|
||||
pattern ZF :: X86Flag
|
||||
pattern ZF = X86Flag 6
|
||||
|
||||
pattern SF :: X86Flag
|
||||
pattern SF = X86Flag 7
|
||||
|
||||
pattern TF :: X86Flag
|
||||
pattern TF = X86Flag 8
|
||||
|
||||
pattern IF :: X86Flag
|
||||
pattern IF = X86Flag 9
|
||||
|
||||
pattern DF :: X86Flag
|
||||
pattern DF = X86Flag 10
|
||||
|
||||
pattern OF :: X86Flag
|
||||
pattern OF = X86Flag 11
|
||||
|
||||
-- | Return list of x86 flags
|
||||
flagList :: [X86Flag]
|
||||
flagList = X86Flag <$> [0,2,4,6,7,8,9,10,11]
|
451
x86/src/Data/Macaw/X86/X86Reg.hs
Normal file
451
x86/src/Data/Macaw/X86/X86Reg.hs
Normal file
@ -0,0 +1,451 @@
|
||||
{-
|
||||
Copyright : (c) Galois, Inc 2015-2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>, Simon Winwood <sjw@galois.com>
|
||||
|
||||
This defines a type for representing what Reopt considers registers on
|
||||
X86_64.
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE ExistentialQuantification #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE KindSignatures #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
module Data.Macaw.X86.X86Reg
|
||||
( ProgramCounter
|
||||
, GP
|
||||
, Flag
|
||||
, Segment
|
||||
, Control
|
||||
, Debug
|
||||
|
||||
, X87_FPU
|
||||
, X87_Status
|
||||
, X87_Top
|
||||
, X87_Tag
|
||||
, X87_ControlMask
|
||||
, X87_Control
|
||||
, XMM
|
||||
|
||||
-- * X86Reg
|
||||
, X86Reg(..)
|
||||
|
||||
, BitConversion(..)
|
||||
, BitPacking(..)
|
||||
-- , registerWidth
|
||||
|
||||
, x87StatusNames
|
||||
-- * General purpose registers
|
||||
, pattern RAX
|
||||
, pattern RBX
|
||||
, pattern RCX
|
||||
, pattern RDX
|
||||
, pattern RSI
|
||||
, pattern RDI
|
||||
, pattern RSP
|
||||
, pattern RBP
|
||||
, pattern R8
|
||||
, pattern R9
|
||||
, pattern R10
|
||||
, pattern R11
|
||||
, pattern R12
|
||||
, pattern R13
|
||||
, pattern R14
|
||||
, pattern R15
|
||||
-- * X86 Flags
|
||||
, pattern CF
|
||||
, pattern PF
|
||||
, pattern AF
|
||||
, pattern ZF
|
||||
, pattern SF
|
||||
, pattern TF
|
||||
, pattern IF
|
||||
, pattern DF
|
||||
, pattern OF
|
||||
-- * X87 status flags
|
||||
, pattern X87_IE
|
||||
, pattern X87_DE
|
||||
, pattern X87_ZE
|
||||
, pattern X87_OE
|
||||
, pattern X87_UE
|
||||
, pattern X87_PE
|
||||
, pattern X87_EF
|
||||
, pattern X87_ES
|
||||
, pattern X87_C0
|
||||
, pattern X87_C1
|
||||
, pattern X87_C2
|
||||
, pattern X87_C3
|
||||
-- * Register lists
|
||||
, gpRegList
|
||||
, flagRegList
|
||||
, xmmRegList
|
||||
, x87FPURegList
|
||||
, x86StateRegs
|
||||
, x86CalleeSavedRegs
|
||||
, x86ArgumentRegs
|
||||
, x86FloatArgumentRegs
|
||||
, x86ResultRegs
|
||||
, x86FloatResultRegs
|
||||
) where
|
||||
|
||||
import Data.Macaw.CFG (RegAddrWidth, RegisterInfo(..), PrettyF(..))
|
||||
import Data.Macaw.Types
|
||||
import Data.Parameterized.Classes
|
||||
import Data.Parameterized.NatRepr
|
||||
import Data.Parameterized.Some
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import qualified Data.Vector as V
|
||||
import qualified Flexdis86 as F
|
||||
import Text.PrettyPrint.ANSI.Leijen as PP hiding ((<$>))
|
||||
|
||||
import qualified Data.Macaw.X86.X86Flag as R
|
||||
|
||||
-- Widths of common types
|
||||
type ProgramCounter = BVType 64
|
||||
type GP = BVType 64
|
||||
type Flag = BoolType
|
||||
type Segment = BVType 16
|
||||
type Control = BVType 64
|
||||
type Debug = BVType 64
|
||||
type X87_FPU = BVType 80
|
||||
type X87_Status = BoolType
|
||||
type X87_Top = BVType 3
|
||||
type X87_Tag = BVType 2
|
||||
type X87_ControlMask = BVType 1
|
||||
type X87_Control = BVType 2
|
||||
type XMM = BVType 128
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- X86Reg
|
||||
|
||||
-- The datatype for x86 registers.
|
||||
data X86Reg tp
|
||||
= (tp ~ BVType 64) => X86_IP
|
||||
| (tp ~ BVType 64) => X86_GP {-# UNPACK #-} !F.Reg64
|
||||
-- ^ One of 16 general purpose registers
|
||||
| (tp ~ BoolType) => X86_FlagReg {-# UNPACK #-} !R.X86Flag
|
||||
-- ^ One of 32 initial flag registers.
|
||||
| (tp ~ BoolType) => X87_StatusReg {-# UNPACK #-} !Int
|
||||
-- ^ One of 16 x87 status registers
|
||||
| (tp ~ BVType 3) => X87_TopReg
|
||||
-- X87 tag register.
|
||||
| (tp ~ BVType 2) => X87_TagReg {-# UNPACK #-} !Int
|
||||
-- One of 8 fpu/mmx registers.
|
||||
| (tp ~ BVType 80) => X87_FPUReg {-#UNPACK #-} !F.MMXReg
|
||||
-- One of 8 XMM registers
|
||||
| (tp ~ BVType 128) => X86_XMMReg !F.XMMReg
|
||||
|
||||
instance Show (X86Reg tp) where
|
||||
show X86_IP = "rip"
|
||||
show (X86_GP r) = show r
|
||||
show (X86_FlagReg r) = show r
|
||||
show (X87_StatusReg r) = nm
|
||||
where Just nm = x87StatusNames V.!? r
|
||||
show X87_TopReg = "x87top"
|
||||
show (X87_TagReg n) = "tag" ++ show n
|
||||
show (X87_FPUReg r) = show r
|
||||
show (X86_XMMReg r) = show r
|
||||
|
||||
instance ShowF X86Reg where
|
||||
showF = show
|
||||
|
||||
instance PrettyF X86Reg where
|
||||
prettyF = text . show
|
||||
|
||||
instance TestEquality X86Reg where
|
||||
testEquality x y = orderingIsEqual (compareF x y)
|
||||
where
|
||||
-- FIXME: copied from Representation.hs, move
|
||||
orderingIsEqual :: OrderingF (x :: k) (y :: k) -> Maybe (x :~: y)
|
||||
orderingIsEqual o =
|
||||
case o of
|
||||
LTF -> Nothing
|
||||
EQF -> Just Refl
|
||||
GTF -> Nothing
|
||||
|
||||
instance Eq (X86Reg tp) where
|
||||
r == r'
|
||||
| Just _ <- testEquality r r' = True
|
||||
| otherwise = False
|
||||
|
||||
instance OrdF X86Reg where
|
||||
compareF X86_IP X86_IP = EQF
|
||||
compareF X86_IP _ = LTF
|
||||
compareF _ X86_IP = GTF
|
||||
|
||||
compareF (X86_GP n) (X86_GP n') = fromOrdering (compare n n')
|
||||
compareF X86_GP{} _ = LTF
|
||||
compareF _ X86_GP{} = GTF
|
||||
|
||||
compareF (X86_FlagReg n) (X86_FlagReg n') = fromOrdering (compare n n')
|
||||
compareF X86_FlagReg{} _ = LTF
|
||||
compareF _ X86_FlagReg{} = GTF
|
||||
|
||||
compareF (X87_StatusReg n) (X87_StatusReg n') = fromOrdering (compare n n')
|
||||
compareF X87_StatusReg{} _ = LTF
|
||||
compareF _ X87_StatusReg{} = GTF
|
||||
|
||||
compareF X87_TopReg X87_TopReg = EQF
|
||||
compareF X87_TopReg _ = LTF
|
||||
compareF _ X87_TopReg = GTF
|
||||
|
||||
compareF (X87_TagReg n) (X87_TagReg n') = fromOrdering (compare n n')
|
||||
compareF X87_TagReg{} _ = LTF
|
||||
compareF _ X87_TagReg{} = GTF
|
||||
|
||||
compareF (X87_FPUReg n) (X87_FPUReg n') = fromOrdering (compare n n')
|
||||
compareF X87_FPUReg{} _ = LTF
|
||||
compareF _ X87_FPUReg{} = GTF
|
||||
|
||||
compareF (X86_XMMReg n) (X86_XMMReg n') = fromOrdering (compare n n')
|
||||
|
||||
instance Ord (X86Reg cl) where
|
||||
a `compare` b = case a `compareF` b of
|
||||
GTF -> GT
|
||||
EQF -> EQ
|
||||
LTF -> LT
|
||||
|
||||
instance HasRepr X86Reg TypeRepr where
|
||||
typeRepr r =
|
||||
case r of
|
||||
X86_IP -> knownType
|
||||
X86_GP{} -> knownType
|
||||
X86_FlagReg{} -> knownType
|
||||
X87_StatusReg{} -> knownType
|
||||
X87_TopReg -> knownType
|
||||
X87_TagReg{} -> knownType
|
||||
X87_FPUReg{} -> knownType
|
||||
X86_XMMReg{} -> knownType
|
||||
|
||||
{-
|
||||
registerWidth :: X86Reg tp -> NatRepr (TypeBits tp)
|
||||
registerWidth X86_IP = knownNat
|
||||
registerWidth X86_GP{} = knownNat
|
||||
registerWidth X86_FlagReg{} = knownNat
|
||||
registerWidth X87_StatusReg{} = knownNat
|
||||
registerWidth X87_TopReg = knownNat
|
||||
registerWidth X87_TagReg{} = knownNat
|
||||
registerWidth X87_FPUReg{} = knownNat
|
||||
registerWidth X86_XMMReg{} = knownNat
|
||||
-}
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Exported constructors and their conversion to words
|
||||
|
||||
-- | A description of how a sub-word may be extracted from a word. If a bit isn't
|
||||
-- constant or from a register it is reserved.
|
||||
data BitConversion n = forall m n'. (1 <= n', n' <= n)
|
||||
=> RegisterBit (X86Reg (BVType n')) (NatRepr m)
|
||||
| forall m. (m + 1 <= n) => ConstantBit Bool (NatRepr m)
|
||||
|
||||
-- | A description of how a particular status word is packed/unpacked into sub-bits
|
||||
data BitPacking (n :: Nat) = BitPacking (NatRepr n) [BitConversion n]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- General purpose register aliases.
|
||||
|
||||
pattern RAX :: X86Reg GP
|
||||
pattern RAX = X86_GP F.RAX
|
||||
|
||||
pattern RBX :: X86Reg GP
|
||||
pattern RBX = X86_GP F.RBX
|
||||
|
||||
pattern RCX :: X86Reg GP
|
||||
pattern RCX = X86_GP F.RCX
|
||||
|
||||
pattern RDX :: X86Reg GP
|
||||
pattern RDX = X86_GP F.RDX
|
||||
|
||||
pattern RSI :: X86Reg GP
|
||||
pattern RSI = X86_GP F.RSI
|
||||
|
||||
pattern RDI :: X86Reg GP
|
||||
pattern RDI = X86_GP F.RDI
|
||||
|
||||
pattern RSP :: X86Reg GP
|
||||
pattern RSP = X86_GP F.RSP
|
||||
|
||||
pattern RBP :: X86Reg GP
|
||||
pattern RBP = X86_GP F.RBP
|
||||
|
||||
pattern R8 :: X86Reg GP
|
||||
pattern R8 = X86_GP F.R8
|
||||
|
||||
pattern R9 :: X86Reg GP
|
||||
pattern R9 = X86_GP F.R9
|
||||
|
||||
pattern R10 :: X86Reg GP
|
||||
pattern R10 = X86_GP F.R10
|
||||
|
||||
pattern R11 :: X86Reg GP
|
||||
pattern R11 = X86_GP F.R11
|
||||
|
||||
pattern R12 :: X86Reg GP
|
||||
pattern R12 = X86_GP F.R12
|
||||
|
||||
pattern R13 :: X86Reg GP
|
||||
pattern R13 = X86_GP F.R13
|
||||
|
||||
pattern R14 :: X86Reg GP
|
||||
pattern R14 = X86_GP F.R14
|
||||
|
||||
pattern R15 :: X86Reg GP
|
||||
pattern R15 = X86_GP F.R15
|
||||
|
||||
pattern CF :: X86Reg Flag
|
||||
pattern CF = X86_FlagReg R.CF
|
||||
|
||||
pattern PF :: X86Reg Flag
|
||||
pattern PF = X86_FlagReg R.PF
|
||||
|
||||
pattern AF :: X86Reg Flag
|
||||
pattern AF = X86_FlagReg R.AF
|
||||
|
||||
pattern ZF :: X86Reg Flag
|
||||
pattern ZF = X86_FlagReg R.ZF
|
||||
|
||||
pattern SF :: X86Reg Flag
|
||||
pattern SF = X86_FlagReg R.SF
|
||||
|
||||
pattern TF :: X86Reg Flag
|
||||
pattern TF = X86_FlagReg R.TF
|
||||
|
||||
pattern IF :: X86Reg Flag
|
||||
pattern IF = X86_FlagReg R.IF
|
||||
|
||||
pattern DF :: X86Reg Flag
|
||||
pattern DF = X86_FlagReg R.DF
|
||||
|
||||
pattern OF :: X86Reg Flag
|
||||
pattern OF = X86_FlagReg R.OF
|
||||
|
||||
-- | x87 flags
|
||||
pattern X87_IE :: X86Reg X87_Status
|
||||
pattern X87_IE = X87_StatusReg 0
|
||||
|
||||
pattern X87_DE :: X86Reg X87_Status
|
||||
pattern X87_DE = X87_StatusReg 1
|
||||
|
||||
pattern X87_ZE :: X86Reg X87_Status
|
||||
pattern X87_ZE = X87_StatusReg 2
|
||||
|
||||
pattern X87_OE :: X86Reg X87_Status
|
||||
pattern X87_OE = X87_StatusReg 3
|
||||
|
||||
pattern X87_UE :: X86Reg X87_Status
|
||||
pattern X87_UE = X87_StatusReg 4
|
||||
|
||||
pattern X87_PE :: X86Reg X87_Status
|
||||
pattern X87_PE = X87_StatusReg 5
|
||||
|
||||
pattern X87_EF :: X86Reg X87_Status
|
||||
pattern X87_EF = X87_StatusReg 6
|
||||
|
||||
pattern X87_ES :: X86Reg X87_Status
|
||||
pattern X87_ES = X87_StatusReg 7
|
||||
|
||||
pattern X87_C0 :: X86Reg X87_Status
|
||||
pattern X87_C0 = X87_StatusReg 8
|
||||
|
||||
pattern X87_C1 :: X86Reg X87_Status
|
||||
pattern X87_C1 = X87_StatusReg 9
|
||||
|
||||
pattern X87_C2 :: X86Reg X87_Status
|
||||
pattern X87_C2 = X87_StatusReg 10
|
||||
|
||||
pattern X87_C3 :: X86Reg X87_Status
|
||||
pattern X87_C3 = X87_StatusReg 14
|
||||
|
||||
x87StatusNames :: V.Vector String
|
||||
x87StatusNames = V.fromList $
|
||||
[ "ie", "de", "ze", "oe", "ue", "pe", "ef", "es"
|
||||
, "c0", "c1", "c2", "RESERVED", "RESERVED", "RESERVED", "c3", "RESERVED"
|
||||
]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- RegisterInfo instance
|
||||
|
||||
-- | The ABI defines these (http://www.x86-64.org/documentation/abi.pdf)
|
||||
-- Syscalls clobber rcx and r11, but we don't really care about these anyway.
|
||||
x86SyscallArgumentRegs :: [ X86Reg (BVType 64) ]
|
||||
x86SyscallArgumentRegs = [ RDI, RSI, RDX, R10, R8, R9 ]
|
||||
|
||||
gpRegList :: [X86Reg (BVType 64)]
|
||||
gpRegList = [X86_GP (F.reg64 i) | i <- [0..15]]
|
||||
|
||||
flagRegList :: [X86Reg BoolType]
|
||||
flagRegList = X86_FlagReg <$> R.flagList
|
||||
|
||||
x87StatusRegList :: [X86Reg BoolType]
|
||||
x87StatusRegList = [X87_StatusReg i | i <- [0..15]]
|
||||
|
||||
x87TagRegList :: [X86Reg (BVType 2)]
|
||||
x87TagRegList = [X87_TagReg i | i <- [0..7]]
|
||||
|
||||
x87FPURegList :: [X86Reg (BVType 80)]
|
||||
x87FPURegList = [X87_FPUReg (F.mmxReg i) | i <- [0..7]]
|
||||
|
||||
xmmRegList :: [X86Reg (BVType 128)]
|
||||
xmmRegList = [X86_XMMReg (F.xmmReg i) | i <- [0..15]]
|
||||
|
||||
-- | List of registers stored in X86State
|
||||
x86StateRegs :: [Some X86Reg]
|
||||
x86StateRegs
|
||||
= [Some X86_IP]
|
||||
++ (Some <$> gpRegList)
|
||||
++ (Some <$> flagRegList)
|
||||
++ (Some <$> x87StatusRegList)
|
||||
++ [Some X87_TopReg]
|
||||
++ (Some <$> x87TagRegList)
|
||||
++ (Some <$> x87FPURegList)
|
||||
++ (Some <$> xmmRegList)
|
||||
|
||||
type instance RegAddrWidth X86Reg = 64
|
||||
|
||||
instance RegisterInfo X86Reg where
|
||||
archRegs = x86StateRegs
|
||||
|
||||
ip_reg = X86_IP
|
||||
sp_reg = RSP
|
||||
|
||||
-- The register used to store system call numbers.
|
||||
syscall_num_reg = RAX
|
||||
|
||||
-- The ABI defines these (http://www.x86-64.org/documentation/abi.pdf)
|
||||
-- Syscalls clobber rcx and r11, but we don't really care about these
|
||||
-- anyway.
|
||||
syscallArgumentRegs = x86SyscallArgumentRegs
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Register information
|
||||
|
||||
-- | List of registers that a callee must save.
|
||||
x86CalleeSavedRegs :: Set (Some X86Reg)
|
||||
x86CalleeSavedRegs = Set.fromList $
|
||||
[ -- Some rsp sjw: rsp is special
|
||||
Some RBP
|
||||
, Some RBX
|
||||
, Some R12
|
||||
, Some R13
|
||||
, Some R14
|
||||
, Some R15
|
||||
, Some DF
|
||||
, Some X87_TopReg
|
||||
]
|
||||
|
||||
x86ArgumentRegs :: [X86Reg (BVType 64)]
|
||||
x86ArgumentRegs = [ RDI, RSI, RDX, RCX, R8, R9 ]
|
||||
|
||||
x86FloatArgumentRegs :: [X86Reg (BVType 128)]
|
||||
x86FloatArgumentRegs = X86_XMMReg . F.xmmReg <$> [0..7]
|
||||
|
||||
x86ResultRegs :: [X86Reg (BVType 64)]
|
||||
x86ResultRegs = [ RAX, RDX ]
|
||||
|
||||
x86FloatResultRegs :: [X86Reg (BVType 128)]
|
||||
x86FloatResultRegs = [ X86_XMMReg (F.xmmReg 0) ]
|
115
x86/src/Data/Macaw/X86/X87ControlReg.hs
Normal file
115
x86/src/Data/Macaw/X86/X87ControlReg.hs
Normal file
@ -0,0 +1,115 @@
|
||||
{-
|
||||
Copyright : (c) Galois, Inc 2017
|
||||
Maintainer : Joe Hendrix <jhendrix@galois.com>
|
||||
|
||||
This contains a type for modeling the X87 control register
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
module Data.Macaw.X86.X87ControlReg
|
||||
( X87_ControlReg
|
||||
, x87_IM
|
||||
, x87_DM
|
||||
, x87_ZM
|
||||
, x87_OM
|
||||
, x87_UM
|
||||
, x87_PM
|
||||
, x87_PC
|
||||
, x87_RC
|
||||
, x87_X
|
||||
, x87ControlRegWidthIsPos
|
||||
) where
|
||||
|
||||
import Data.Macaw.Types
|
||||
import Data.Parameterized.Classes
|
||||
import Data.Parameterized.NatRepr
|
||||
|
||||
-- | One of the X87 control registrs
|
||||
data X87_ControlReg w = (1 <= w) => X87_ControlReg !Int !(NatRepr w)
|
||||
|
||||
instance TestEquality X87_ControlReg where
|
||||
testEquality (X87_ControlReg xi xw) (X87_ControlReg yi yw) =
|
||||
if xi == yi then
|
||||
testEquality xw yw
|
||||
else
|
||||
Nothing
|
||||
|
||||
instance OrdF X87_ControlReg where
|
||||
compareF (X87_ControlReg xi xw) (X87_ControlReg yi yw) =
|
||||
case compare xi yi of
|
||||
LT -> LTF
|
||||
GT -> GTF
|
||||
EQ -> compareF xw yw
|
||||
|
||||
instance HasRepr X87_ControlReg NatRepr where
|
||||
typeRepr (X87_ControlReg _ w) = w
|
||||
|
||||
instance Show (X87_ControlReg w) where
|
||||
show (X87_ControlReg i _) =
|
||||
case i of
|
||||
0 -> "im"
|
||||
1 -> "dm"
|
||||
2 -> "zm"
|
||||
3 -> "om"
|
||||
4 -> "um"
|
||||
5 -> "pm"
|
||||
8 -> "pc"
|
||||
10 -> "rc"
|
||||
12 -> "x"
|
||||
_ -> "reserved"
|
||||
|
||||
x87_IM :: X87_ControlReg 1
|
||||
x87_IM = X87_ControlReg 0 n1
|
||||
|
||||
x87_DM :: X87_ControlReg 1
|
||||
x87_DM = X87_ControlReg 1 n1
|
||||
|
||||
x87_ZM :: X87_ControlReg 1
|
||||
x87_ZM = X87_ControlReg 2 n1
|
||||
|
||||
x87_OM :: X87_ControlReg 1
|
||||
x87_OM = X87_ControlReg 3 n1
|
||||
|
||||
x87_UM :: X87_ControlReg 1
|
||||
x87_UM = X87_ControlReg 4 n1
|
||||
|
||||
x87_PM :: X87_ControlReg 1
|
||||
x87_PM = X87_ControlReg 5 n1
|
||||
|
||||
-- | X87 precision control field.
|
||||
--
|
||||
-- Values are:
|
||||
-- 00 Single Precision (24 bits)
|
||||
-- 01 Reserved
|
||||
-- 10 Double Precision (53 bits)
|
||||
-- 11 Double Extended Precision (64 bits)
|
||||
x87_PC :: X87_ControlReg 2
|
||||
x87_PC = X87_ControlReg 8 knownNat
|
||||
|
||||
-- | X87 rounding control field. Values are:
|
||||
--
|
||||
-- 00 Round to nearest (even)
|
||||
-- Rounded result is the closest to the infinitely precise result. If two
|
||||
-- values are equally close, the result is the even value (that is, the one
|
||||
-- with the least-significant bit of zero). Default
|
||||
--
|
||||
-- 01 Round down (toward −∞)
|
||||
-- Rounded result is closest to but no greater than the infinitely precise result.
|
||||
--
|
||||
-- 10 Round up (toward +∞)
|
||||
-- Rounded result is closest to but no less than the infinitely precise result.
|
||||
--
|
||||
-- 11 Round toward zero (Truncate)
|
||||
-- Rounded result is closest to but no greater in absolute value than the
|
||||
-- infinitely precise result.
|
||||
x87_RC :: X87_ControlReg 2
|
||||
x87_RC = X87_ControlReg 10 knownNat
|
||||
|
||||
x87_X :: X87_ControlReg 1
|
||||
x87_X = X87_ControlReg 12 n1
|
||||
|
||||
|
||||
x87ControlRegWidthIsPos :: X87_ControlReg w -> LeqProof 1 w
|
||||
x87ControlRegWidthIsPos (X87_ControlReg _ _) = LeqProof
|
2
x86/support/README.md
Normal file
2
x86/support/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
This directory contains a cabal file with utilities for automatically
|
||||
generating the system call definitions from the include files.
|
33
x86/support/macaw-x86-support.cabal
Normal file
33
x86/support/macaw-x86-support.cabal
Normal file
@ -0,0 +1,33 @@
|
||||
name: macaw-x86-support
|
||||
version: 0.0.1
|
||||
author: Galois, Inc.
|
||||
maintainer: jhendrix@galois.com
|
||||
build-type: Simple
|
||||
cabal-version: >= 1.9.2
|
||||
|
||||
executable make_bsd_syscalls
|
||||
|
||||
build-depends:
|
||||
base >= 4,
|
||||
bytestring,
|
||||
language-c <= 0.5.0,
|
||||
lens,
|
||||
pretty,
|
||||
containers,
|
||||
pretty-show,
|
||||
attoparsec
|
||||
hs-source-dirs: make_bsd_syscalls
|
||||
main-is: Main.hs
|
||||
|
||||
executable make_linux_syscalls
|
||||
build-depends:
|
||||
base >= 4,
|
||||
bytestring,
|
||||
language-c <= 0.5.0,
|
||||
lens,
|
||||
pretty,
|
||||
containers,
|
||||
pretty-show,
|
||||
attoparsec
|
||||
hs-source-dirs: make_linux_syscalls
|
||||
main-is: Main.hs
|
257
x86/support/make_bsd_syscalls/Main.hs
Normal file
257
x86/support/make_bsd_syscalls/Main.hs
Normal file
@ -0,0 +1,257 @@
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Attoparsec.ByteString.Char8 (Parser)
|
||||
import qualified Data.Attoparsec.ByteString.Char8 as P
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString.Char8 as BS
|
||||
import Data.Either (either)
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import Data.Maybe (catMaybes, maybe)
|
||||
import Language.C
|
||||
import Language.C.Analysis.AstAnalysis
|
||||
import Language.C.Analysis.SemRep
|
||||
import Language.C.Analysis.TravMonad
|
||||
import Language.C.Data.Ident
|
||||
import Language.C.Data.Name (newNameSupply)
|
||||
import Language.C.Data.Position (position)
|
||||
import System.Environment (getArgs)
|
||||
import System.Exit
|
||||
import System.IO
|
||||
import Text.PrettyPrint
|
||||
import Text.Show.Pretty
|
||||
|
||||
import Debug.Trace
|
||||
|
||||
-- FIXME: clag from Data.Macaw.Architecture.Syscall
|
||||
data SyscallArgType = VoidArgType | WordArgType
|
||||
deriving (Eq, Show, Read)
|
||||
|
||||
|
||||
-- | The syscall.master file looks like (after pre-processing)
|
||||
--
|
||||
-- # <line no> filename
|
||||
-- ... c header stuff
|
||||
-- # <line no> "syscalls.master"
|
||||
-- ; comment line
|
||||
-- ...
|
||||
-- <syscall no.>\t<audit>\t<syscall type>\t<prototype> ... ignored stuff ...
|
||||
--
|
||||
-- for example
|
||||
--
|
||||
-- 538 43207 STD { int bindat(int fd, int s, caddr_t name, int namelen); }
|
||||
--
|
||||
-- This file then does the following:
|
||||
-- 1. Divide the file into two parts: the C headers and the syscall defs
|
||||
-- 2. Parse each line in the syscall defs to extract the propotype
|
||||
-- 3. Extract the argument types from the C prototype.
|
||||
|
||||
data SyscallInfo =
|
||||
SyscallInfo { syscallNo :: Integer
|
||||
, syscallAudit :: Integer
|
||||
, syscallType :: ByteString
|
||||
, syscallProto :: Maybe CExtDecl
|
||||
}
|
||||
deriving Show
|
||||
|
||||
|
||||
syscallLine :: [Ident] -> Parser (Maybe SyscallInfo)
|
||||
syscallLine idents =
|
||||
P.choice [ P.char ';' >> return Nothing
|
||||
, parseLine
|
||||
]
|
||||
where
|
||||
parseLine = do
|
||||
num <- P.decimal
|
||||
P.skipSpace
|
||||
audit <- P.decimal
|
||||
P.skipSpace
|
||||
cl <- P.takeWhile (not . P.isSpace)
|
||||
P.skipSpace
|
||||
cdecl <- P.choice [ P.char '{' >> P.takeTill ((==) '}') >>= return . parseDecl
|
||||
, P.takeWhile1 (not . P.isSpace) >> return Nothing
|
||||
]
|
||||
return (Just (SyscallInfo num audit cl cdecl))
|
||||
|
||||
parseDecl bytes =
|
||||
-- FIXME: we should maybe chain through newNameSupply? I don't think it is ever used ...
|
||||
case execParser extDeclP bytes (position 0 "" 0 0) idents newNameSupply of
|
||||
Left _err -> Nothing
|
||||
Right (cdecl, _unusedNames) -> Just cdecl
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Haskell generation
|
||||
|
||||
-- A bit hacky, but no less than using TH to read in a text file
|
||||
generateHSFile :: CTranslUnit -> [SyscallInfo] -> Doc
|
||||
generateHSFile tunit sis =
|
||||
vcat [ text "-- DO NOT EDIT. Generated from make_bsd_syscalls/Main.hs"
|
||||
, text "module Data.Macaw.X86.SyscallInfo.FreeBSD (syscallInfo) where"
|
||||
, text "import Data.Macaw.Architecture.Syscall"
|
||||
, text "import Data.Map (Map, fromList)"
|
||||
, text "import Data.Word"
|
||||
, text ""
|
||||
, text "syscallInfo :: Map Word64 SyscallTypeInfo"
|
||||
, text "syscallInfo =" <+> ppDoc syscallMap ]
|
||||
where
|
||||
syscallMap = Map.fromList [ (syscallNo si, info)
|
||||
| si <- sis
|
||||
, Just d <- [ syscallProto si ]
|
||||
, Right (info, _) <- [ syscallInfo d ] ]
|
||||
-- syscallInfo :: CExtDecl -> Maybe (String, SyscallArgType, [SyscallArgType])
|
||||
syscallInfo cdecl =
|
||||
runTrav (error "no decl") $ do
|
||||
_ <- analyseAST tunit
|
||||
let handler (DeclEvent idecl) = modifyUserState (const $ summariseDeclEvent idecl)
|
||||
handler _ = return ()
|
||||
withExtDeclHandler (analyseExt cdecl) handler
|
||||
getUserState
|
||||
|
||||
-- summariseDeclEvent idecl = pretty idecl
|
||||
|
||||
summariseDeclEvent (getVarDecl -> VarDecl vname _ (FunctionType (FunType rettyp params _) _)) =
|
||||
( identToString (identOfVarName vname)
|
||||
, typeToArgType rettyp
|
||||
, map (typeToArgType . declType) params )
|
||||
|
||||
-- syscallInfo (CDeclExt (CDecl [CTypeSpec spec] [(Just declr, _, _)] _))
|
||||
-- | CDeclr (Just ident) [CFunDeclr (Right (decls, _)) _ _] _ _ _ <- declr
|
||||
-- = Just (identToString ident, typeSpecToArgType spec, map declToArgType decls)
|
||||
-- syscallInfo d = error ("unhandled decl" ++ show d)
|
||||
|
||||
-- declToArgType (CDecl [CTypeSpec spec] _) = typeSpecToArgType spec
|
||||
-- declToArgType d = error ("unhandled decl (in type) " ++ show d)
|
||||
|
||||
typeToArgType :: Type -> SyscallArgType
|
||||
typeToArgType typ =
|
||||
case typ of
|
||||
DirectType typ' _ _ ->
|
||||
case typ' of
|
||||
TyVoid -> VoidArgType
|
||||
TyIntegral _ -> WordArgType
|
||||
TyFloating TyLDouble -> unhandled
|
||||
TyFloating _ -> unhandled -- XMMFloatType
|
||||
TyComplex _ -> unhandled
|
||||
TyComp comp -> unhandled -- compTypeToArgType comp
|
||||
TyEnum _ -> WordArgType -- FIXME: ???
|
||||
TyBuiltin _ -> unhandled
|
||||
PtrType _ _ _ -> WordArgType
|
||||
ArrayType _ _ _ _ -> WordArgType
|
||||
FunctionType _ _ -> unhandled
|
||||
TypeDefType (TypeDefRef _ (Just typ) _) _ _ -> typeToArgType typ
|
||||
where
|
||||
unhandled = error ("Unhandled type: " ++ show (pretty typ))
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- File preprocessing
|
||||
|
||||
cppLinePragma :: Parser (Integer, String)
|
||||
cppLinePragma = do
|
||||
_ <- P.string "# "
|
||||
n <- P.decimal
|
||||
_ <- P.space
|
||||
_ <- P.char '"'
|
||||
filename <- P.many1 (P.satisfy ((/=) '"'))
|
||||
_ <- P.char '"'
|
||||
-- .. other stuff until end of line, we don't really care though
|
||||
return (n, filename)
|
||||
|
||||
-- | This attempts to parses a bytestring line of the form:
|
||||
--
|
||||
-- "# ?decimal "?filename".*
|
||||
--
|
||||
-- If it matches this, then it returns the decimal value and
|
||||
-- filenumber. If it does not, then it returns nothing.
|
||||
isCPPLinePragma :: BS.ByteString
|
||||
-> Maybe (Integer, String)
|
||||
isCPPLinePragma str =
|
||||
case P.parseOnly cppLinePragma str of
|
||||
Left _ -> Nothing
|
||||
Right r -> Just r
|
||||
|
||||
-- | This takes the lines in a file, and returns a pair of lines.
|
||||
-- The first contains those lines between a pragma of the form
|
||||
--
|
||||
-- # XX "syscalls.master"
|
||||
--
|
||||
-- and a pragma with any other filename.
|
||||
--
|
||||
-- The second contains the other lines.
|
||||
splitFile :: [BS.ByteString] -> ([BS.ByteString], [BS.ByteString])
|
||||
splitFile = go False mempty
|
||||
where
|
||||
go :: Bool
|
||||
-- ^ This flag is true if the last CPP line pragma had the filemname
|
||||
-- syscalls.master"
|
||||
-> ([BS.ByteString], [BS.ByteString])
|
||||
-- ^ This contains the lines outside the system call
|
||||
-- contents and the lines inside of respectively.
|
||||
-> [BS.ByteString]
|
||||
-> ([BS.ByteString], [BS.ByteString])
|
||||
go _ acc [] = acc
|
||||
go inSyscalls acc (l : ls)
|
||||
| Just (_, filename) <- isCPPLinePragma l
|
||||
= go (filename == "syscalls.master") acc ls
|
||||
-- Add lines in the system
|
||||
| otherwise =
|
||||
go inSyscalls (acc & (if inSyscalls then _1 else _2) %~ (++ [l])) ls
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Parsing
|
||||
|
||||
translUnitToIdents :: CTranslUnit -> [Ident]
|
||||
translUnitToIdents (CTranslUnit decls _) =
|
||||
[ ident | CDeclExt (CDecl _ tdecls _) <- decls
|
||||
, (Just (CDeclr (Just ident) _ _ _ _), _, _) <- tdecls ]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Main
|
||||
|
||||
parseSyscallLine :: [Ident] -> BS.ByteString -> IO (Maybe SyscallInfo)
|
||||
parseSyscallLine idents l =
|
||||
case P.parseOnly (syscallLine idents) l of
|
||||
Left err -> do
|
||||
hPutStrLn stderr $ "Could not parse system call:"
|
||||
hPutStrLn stderr $ " " ++ show err
|
||||
hPutStrLn stderr $ " Input: " ++ BS.unpack l
|
||||
exitFailure
|
||||
Right i ->
|
||||
return i
|
||||
|
||||
showUsageAndExit :: IO a
|
||||
showUsageAndExit = do
|
||||
hPutStrLn stderr $ unlines
|
||||
[ "This program generates the Haskell module that maps system call ids"
|
||||
, "in FreeBSD to the name, argument types, and result type."
|
||||
, ""
|
||||
, "Please specify the system.master.h file as the first argument."
|
||||
, "The resulting Haskell module will be written to standard out."
|
||||
]
|
||||
exitFailure
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
input <-
|
||||
case args of
|
||||
[input] -> pure input
|
||||
_ -> showUsageAndExit
|
||||
|
||||
-- Get contents and split into lines.
|
||||
ls <- BS.split '\n' <$> BS.readFile input
|
||||
|
||||
let (syscalls, split_headers) = splitFile (filter (not . BS.null) ls)
|
||||
headers = BS.intercalate "\n" split_headers
|
||||
Right tunit = parseC headers (position 0 "" 0 0)
|
||||
idents = translUnitToIdents tunit
|
||||
|
||||
ms <- mapM (parseSyscallLine idents) (tail syscalls)
|
||||
putStrLn "Got ms"
|
||||
-- mapM_ pp (catMaybes ms)
|
||||
print $ generateHSFile tunit $ catMaybes ms
|
927
x86/support/make_bsd_syscalls/syscalls.master
Normal file
927
x86/support/make_bsd_syscalls/syscalls.master
Normal file
@ -0,0 +1,927 @@
|
||||
$FreeBSD: src/sys/kern/syscalls.master,v 1.259.2.3.2.1 2010/06/14 02:09:06 kensmith Exp $
|
||||
; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
|
||||
;
|
||||
; System call name/number master file.
|
||||
; Processed to created init_sysent.c, syscalls.c and syscall.h.
|
||||
|
||||
; Columns: number audit type name alt{name,tag,rtyp}/comments
|
||||
; number system call number, must be in order
|
||||
; audit the audit event associated with the system call
|
||||
; A value of AUE_NULL means no auditing, but it also means that
|
||||
; there is no audit event for the call at this time. For the
|
||||
; case where the event exists, but we don't want auditing, the
|
||||
; event should be #defined to AUE_NULL in audit_kevents.h.
|
||||
; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6,
|
||||
; COMPAT7, LIBCOMPAT, NODEF, NOARGS, NOPROTO, NOSTD
|
||||
; The COMPAT* options may be combined with one or more NO*
|
||||
; options separated by '|' with no spaces (e.g. COMPAT|NOARGS)
|
||||
; name psuedo-prototype of syscall routine
|
||||
; If one of the following alts is different, then all appear:
|
||||
; altname name of system call if different
|
||||
; alttag name of args struct tag if different from [o]`name'"_args"
|
||||
; altrtyp return type if not int (bogus - syscalls always return int)
|
||||
; for UNIMPL/OBSOL, name continues with comments
|
||||
|
||||
; types:
|
||||
; STD always included
|
||||
; COMPAT included on COMPAT #ifdef
|
||||
; COMPAT4 included on COMPAT4 #ifdef (FreeBSD 4 compat)
|
||||
; COMPAT6 included on COMPAT6 #ifdef (FreeBSD 6 compat)
|
||||
; COMPAT7 included on COMPAT7 #ifdef (FreeBSD 7 compat)
|
||||
; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h
|
||||
; OBSOL obsolete, not included in system, only specifies name
|
||||
; UNIMPL not implemented, placeholder only
|
||||
; NOSTD implemented but as a lkm that can be statically
|
||||
; compiled in; sysent entry will be filled with lkmressys
|
||||
; so the SYSCALL_MODULE macro works
|
||||
; NOARGS same as STD except do not create structure in sys/sysproto.h
|
||||
; NODEF same as STD except only have the entry in the syscall table
|
||||
; added. Meaning - do not create structure or function
|
||||
; prototype in sys/sysproto.h
|
||||
; NOPROTO same as STD except do not create structure or
|
||||
; function prototype in sys/sysproto.h. Does add a
|
||||
; definition to syscall.h besides adding a sysent.
|
||||
|
||||
;
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/compat/freebsd32/syscalls.master
|
||||
|
||||
; #ifdef's, etc. may be included, and are copied to the output files.
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
|
||||
; Reserved/unimplemented system calls in the range 0-150 inclusive
|
||||
; are reserved for use in future Berkeley releases.
|
||||
; Additional system calls implemented in vendor and other
|
||||
; redistributions should be placed in the reserved range at the end
|
||||
; of the current calls.
|
||||
|
||||
0 AUE_NULL STD { int nosys(void); } syscall nosys_args int
|
||||
1 AUE_EXIT STD { void sys_exit(int rval); } exit \
|
||||
sys_exit_args void
|
||||
2 AUE_FORK STD { int fork(void); }
|
||||
3 AUE_NULL STD { ssize_t read(int fd, void *buf, \
|
||||
size_t nbyte); }
|
||||
4 AUE_NULL STD { ssize_t write(int fd, const void *buf, \
|
||||
size_t nbyte); }
|
||||
5 AUE_OPEN_RWTC STD { int open(char *path, int flags, int mode); }
|
||||
; XXX should be { int open(const char *path, int flags, ...); }
|
||||
; but we're not ready for `const' or varargs.
|
||||
; XXX man page says `mode_t mode'.
|
||||
6 AUE_CLOSE STD { int close(int fd); }
|
||||
7 AUE_WAIT4 STD { int wait4(int pid, int *status, \
|
||||
int options, struct rusage *rusage); } \
|
||||
wait4 wait_args int
|
||||
8 AUE_CREAT COMPAT { int creat(char *path, int mode); }
|
||||
9 AUE_LINK STD { int link(char *path, char *link); }
|
||||
10 AUE_UNLINK STD { int unlink(char *path); }
|
||||
11 AUE_NULL OBSOL execv
|
||||
12 AUE_CHDIR STD { int chdir(char *path); }
|
||||
13 AUE_FCHDIR STD { int fchdir(int fd); }
|
||||
14 AUE_MKNOD STD { int mknod(char *path, int mode, int dev); }
|
||||
15 AUE_CHMOD STD { int chmod(char *path, int mode); }
|
||||
16 AUE_CHOWN STD { int chown(char *path, int uid, int gid); }
|
||||
17 AUE_NULL STD { int obreak(char *nsize); } break \
|
||||
obreak_args int
|
||||
18 AUE_GETFSSTAT COMPAT4 { int getfsstat(struct ostatfs *buf, \
|
||||
long bufsize, int flags); }
|
||||
19 AUE_LSEEK COMPAT { long lseek(int fd, long offset, \
|
||||
int whence); }
|
||||
20 AUE_GETPID STD { pid_t getpid(void); }
|
||||
21 AUE_MOUNT STD { int mount(char *type, char *path, \
|
||||
int flags, caddr_t data); }
|
||||
; XXX `path' should have type `const char *' but we're not ready for that.
|
||||
22 AUE_UMOUNT STD { int unmount(char *path, int flags); }
|
||||
23 AUE_SETUID STD { int setuid(uid_t uid); }
|
||||
24 AUE_GETUID STD { uid_t getuid(void); }
|
||||
25 AUE_GETEUID STD { uid_t geteuid(void); }
|
||||
26 AUE_PTRACE STD { int ptrace(int req, pid_t pid, \
|
||||
caddr_t addr, int data); }
|
||||
27 AUE_RECVMSG STD { int recvmsg(int s, struct msghdr *msg, \
|
||||
int flags); }
|
||||
28 AUE_SENDMSG STD { int sendmsg(int s, struct msghdr *msg, \
|
||||
int flags); }
|
||||
29 AUE_RECVFROM STD { int recvfrom(int s, caddr_t buf, \
|
||||
size_t len, int flags, \
|
||||
struct sockaddr * __restrict from, \
|
||||
__socklen_t * __restrict fromlenaddr); }
|
||||
30 AUE_ACCEPT STD { int accept(int s, \
|
||||
struct sockaddr * __restrict name, \
|
||||
__socklen_t * __restrict anamelen); }
|
||||
31 AUE_GETPEERNAME STD { int getpeername(int fdes, \
|
||||
struct sockaddr * __restrict asa, \
|
||||
__socklen_t * __restrict alen); }
|
||||
32 AUE_GETSOCKNAME STD { int getsockname(int fdes, \
|
||||
struct sockaddr * __restrict asa, \
|
||||
__socklen_t * __restrict alen); }
|
||||
33 AUE_ACCESS STD { int access(char *path, int flags); }
|
||||
34 AUE_CHFLAGS STD { int chflags(char *path, int flags); }
|
||||
35 AUE_FCHFLAGS STD { int fchflags(int fd, int flags); }
|
||||
36 AUE_SYNC STD { int sync(void); }
|
||||
37 AUE_KILL STD { int kill(int pid, int signum); }
|
||||
38 AUE_STAT COMPAT { int stat(char *path, struct ostat *ub); }
|
||||
39 AUE_GETPPID STD { pid_t getppid(void); }
|
||||
40 AUE_LSTAT COMPAT { int lstat(char *path, struct ostat *ub); }
|
||||
41 AUE_DUP STD { int dup(u_int fd); }
|
||||
42 AUE_PIPE STD { int pipe(void); }
|
||||
43 AUE_GETEGID STD { gid_t getegid(void); }
|
||||
44 AUE_PROFILE STD { int profil(caddr_t samples, size_t size, \
|
||||
size_t offset, u_int scale); }
|
||||
45 AUE_KTRACE STD { int ktrace(const char *fname, int ops, \
|
||||
int facs, int pid); }
|
||||
46 AUE_SIGACTION COMPAT { int sigaction(int signum, \
|
||||
struct osigaction *nsa, \
|
||||
struct osigaction *osa); }
|
||||
47 AUE_GETGID STD { gid_t getgid(void); }
|
||||
48 AUE_SIGPROCMASK COMPAT { int sigprocmask(int how, osigset_t mask); }
|
||||
; XXX note nonstandard (bogus) calling convention - the libc stub passes
|
||||
; us the mask, not a pointer to it, and we return the old mask as the
|
||||
; (int) return value.
|
||||
49 AUE_GETLOGIN STD { int getlogin(char *namebuf, u_int \
|
||||
namelen); }
|
||||
50 AUE_SETLOGIN STD { int setlogin(char *namebuf); }
|
||||
51 AUE_ACCT STD { int acct(char *path); }
|
||||
52 AUE_SIGPENDING COMPAT { int sigpending(void); }
|
||||
53 AUE_SIGALTSTACK STD { int sigaltstack(stack_t *ss, \
|
||||
stack_t *oss); }
|
||||
54 AUE_IOCTL STD { int ioctl(int fd, u_long com, \
|
||||
caddr_t data); }
|
||||
55 AUE_REBOOT STD { int reboot(int opt); }
|
||||
56 AUE_REVOKE STD { int revoke(char *path); }
|
||||
57 AUE_SYMLINK STD { int symlink(char *path, char *link); }
|
||||
58 AUE_READLINK STD { ssize_t readlink(char *path, char *buf, \
|
||||
size_t count); }
|
||||
59 AUE_EXECVE STD { int execve(char *fname, char **argv, \
|
||||
char **envv); }
|
||||
60 AUE_UMASK STD { int umask(int newmask); } umask umask_args \
|
||||
int
|
||||
61 AUE_CHROOT STD { int chroot(char *path); }
|
||||
62 AUE_FSTAT COMPAT { int fstat(int fd, struct ostat *sb); }
|
||||
63 AUE_NULL COMPAT { int getkerninfo(int op, char *where, \
|
||||
size_t *size, int arg); } getkerninfo \
|
||||
getkerninfo_args int
|
||||
64 AUE_NULL COMPAT { int getpagesize(void); } getpagesize \
|
||||
getpagesize_args int
|
||||
65 AUE_MSYNC STD { int msync(void *addr, size_t len, \
|
||||
int flags); }
|
||||
66 AUE_VFORK STD { int vfork(void); }
|
||||
67 AUE_NULL OBSOL vread
|
||||
68 AUE_NULL OBSOL vwrite
|
||||
69 AUE_SBRK STD { int sbrk(int incr); }
|
||||
70 AUE_SSTK STD { int sstk(int incr); }
|
||||
71 AUE_MMAP COMPAT { int mmap(void *addr, int len, int prot, \
|
||||
int flags, int fd, long pos); }
|
||||
72 AUE_O_VADVISE STD { int ovadvise(int anom); } vadvise \
|
||||
ovadvise_args int
|
||||
73 AUE_MUNMAP STD { int munmap(void *addr, size_t len); }
|
||||
74 AUE_MPROTECT STD { int mprotect(const void *addr, size_t len, \
|
||||
int prot); }
|
||||
75 AUE_MADVISE STD { int madvise(void *addr, size_t len, \
|
||||
int behav); }
|
||||
76 AUE_NULL OBSOL vhangup
|
||||
77 AUE_NULL OBSOL vlimit
|
||||
78 AUE_MINCORE STD { int mincore(const void *addr, size_t len, \
|
||||
char *vec); }
|
||||
79 AUE_GETGROUPS STD { int getgroups(u_int gidsetsize, \
|
||||
gid_t *gidset); }
|
||||
80 AUE_SETGROUPS STD { int setgroups(u_int gidsetsize, \
|
||||
gid_t *gidset); }
|
||||
81 AUE_GETPGRP STD { int getpgrp(void); }
|
||||
82 AUE_SETPGRP STD { int setpgid(int pid, int pgid); }
|
||||
83 AUE_SETITIMER STD { int setitimer(u_int which, struct \
|
||||
itimerval *itv, struct itimerval *oitv); }
|
||||
84 AUE_WAIT4 COMPAT { int wait(void); }
|
||||
85 AUE_SWAPON STD { int swapon(char *name); }
|
||||
86 AUE_GETITIMER STD { int getitimer(u_int which, \
|
||||
struct itimerval *itv); }
|
||||
87 AUE_SYSCTL COMPAT { int gethostname(char *hostname, \
|
||||
u_int len); } gethostname \
|
||||
gethostname_args int
|
||||
88 AUE_SYSCTL COMPAT { int sethostname(char *hostname, \
|
||||
u_int len); } sethostname \
|
||||
sethostname_args int
|
||||
89 AUE_GETDTABLESIZE STD { int getdtablesize(void); }
|
||||
90 AUE_DUP2 STD { int dup2(u_int from, u_int to); }
|
||||
91 AUE_NULL UNIMPL getdopt
|
||||
92 AUE_FCNTL STD { int fcntl(int fd, int cmd, long arg); }
|
||||
; XXX should be { int fcntl(int fd, int cmd, ...); }
|
||||
; but we're not ready for varargs.
|
||||
93 AUE_SELECT STD { int select(int nd, fd_set *in, fd_set *ou, \
|
||||
fd_set *ex, struct timeval *tv); }
|
||||
94 AUE_NULL UNIMPL setdopt
|
||||
95 AUE_FSYNC STD { int fsync(int fd); }
|
||||
96 AUE_SETPRIORITY STD { int setpriority(int which, int who, \
|
||||
int prio); }
|
||||
97 AUE_SOCKET STD { int socket(int domain, int type, \
|
||||
int protocol); }
|
||||
98 AUE_CONNECT STD { int connect(int s, caddr_t name, \
|
||||
int namelen); }
|
||||
99 AUE_ACCEPT COMPAT|NOARGS { int accept(int s, caddr_t name, \
|
||||
int *anamelen); } accept accept_args int
|
||||
100 AUE_GETPRIORITY STD { int getpriority(int which, int who); }
|
||||
101 AUE_SEND COMPAT { int send(int s, caddr_t buf, int len, \
|
||||
int flags); }
|
||||
102 AUE_RECV COMPAT { int recv(int s, caddr_t buf, int len, \
|
||||
int flags); }
|
||||
103 AUE_SIGRETURN COMPAT { int sigreturn( \
|
||||
struct osigcontext *sigcntxp); }
|
||||
104 AUE_BIND STD { int bind(int s, caddr_t name, \
|
||||
int namelen); }
|
||||
105 AUE_SETSOCKOPT STD { int setsockopt(int s, int level, int name, \
|
||||
caddr_t val, int valsize); }
|
||||
106 AUE_LISTEN STD { int listen(int s, int backlog); }
|
||||
107 AUE_NULL OBSOL vtimes
|
||||
108 AUE_NULL COMPAT { int sigvec(int signum, struct sigvec *nsv, \
|
||||
struct sigvec *osv); }
|
||||
109 AUE_NULL COMPAT { int sigblock(int mask); }
|
||||
110 AUE_NULL COMPAT { int sigsetmask(int mask); }
|
||||
111 AUE_NULL COMPAT { int sigsuspend(osigset_t mask); }
|
||||
; XXX note nonstandard (bogus) calling convention - the libc stub passes
|
||||
; us the mask, not a pointer to it.
|
||||
112 AUE_NULL COMPAT { int sigstack(struct sigstack *nss, \
|
||||
struct sigstack *oss); }
|
||||
113 AUE_RECVMSG COMPAT { int recvmsg(int s, struct omsghdr *msg, \
|
||||
int flags); }
|
||||
114 AUE_SENDMSG COMPAT { int sendmsg(int s, caddr_t msg, \
|
||||
int flags); }
|
||||
115 AUE_NULL OBSOL vtrace
|
||||
116 AUE_GETTIMEOFDAY STD { int gettimeofday(struct timeval *tp, \
|
||||
struct timezone *tzp); }
|
||||
117 AUE_GETRUSAGE STD { int getrusage(int who, \
|
||||
struct rusage *rusage); }
|
||||
118 AUE_GETSOCKOPT STD { int getsockopt(int s, int level, int name, \
|
||||
caddr_t val, int *avalsize); }
|
||||
119 AUE_NULL UNIMPL resuba (BSD/OS 2.x)
|
||||
120 AUE_READV STD { int readv(int fd, struct iovec *iovp, \
|
||||
u_int iovcnt); }
|
||||
121 AUE_WRITEV STD { int writev(int fd, struct iovec *iovp, \
|
||||
u_int iovcnt); }
|
||||
122 AUE_SETTIMEOFDAY STD { int settimeofday(struct timeval *tv, \
|
||||
struct timezone *tzp); }
|
||||
123 AUE_FCHOWN STD { int fchown(int fd, int uid, int gid); }
|
||||
124 AUE_FCHMOD STD { int fchmod(int fd, int mode); }
|
||||
125 AUE_RECVFROM COMPAT|NOARGS { int recvfrom(int s, caddr_t buf, \
|
||||
size_t len, int flags, caddr_t from, int \
|
||||
*fromlenaddr); } recvfrom recvfrom_args \
|
||||
int
|
||||
126 AUE_SETREUID STD { int setreuid(int ruid, int euid); }
|
||||
127 AUE_SETREGID STD { int setregid(int rgid, int egid); }
|
||||
128 AUE_RENAME STD { int rename(char *from, char *to); }
|
||||
129 AUE_TRUNCATE COMPAT { int truncate(char *path, long length); }
|
||||
130 AUE_FTRUNCATE COMPAT { int ftruncate(int fd, long length); }
|
||||
131 AUE_FLOCK STD { int flock(int fd, int how); }
|
||||
132 AUE_MKFIFO STD { int mkfifo(char *path, int mode); }
|
||||
133 AUE_SENDTO STD { int sendto(int s, caddr_t buf, size_t len, \
|
||||
int flags, caddr_t to, int tolen); }
|
||||
134 AUE_SHUTDOWN STD { int shutdown(int s, int how); }
|
||||
135 AUE_SOCKETPAIR STD { int socketpair(int domain, int type, \
|
||||
int protocol, int *rsv); }
|
||||
136 AUE_MKDIR STD { int mkdir(char *path, int mode); }
|
||||
137 AUE_RMDIR STD { int rmdir(char *path); }
|
||||
138 AUE_UTIMES STD { int utimes(char *path, \
|
||||
struct timeval *tptr); }
|
||||
139 AUE_NULL OBSOL 4.2 sigreturn
|
||||
140 AUE_ADJTIME STD { int adjtime(struct timeval *delta, \
|
||||
struct timeval *olddelta); }
|
||||
141 AUE_GETPEERNAME COMPAT { int getpeername(int fdes, caddr_t asa, \
|
||||
int *alen); }
|
||||
142 AUE_SYSCTL COMPAT { long gethostid(void); }
|
||||
143 AUE_SYSCTL COMPAT { int sethostid(long hostid); }
|
||||
144 AUE_GETRLIMIT COMPAT { int getrlimit(u_int which, struct \
|
||||
orlimit *rlp); }
|
||||
145 AUE_SETRLIMIT COMPAT { int setrlimit(u_int which, \
|
||||
struct orlimit *rlp); }
|
||||
146 AUE_KILLPG COMPAT { int killpg(int pgid, int signum); }
|
||||
147 AUE_SETSID STD { int setsid(void); }
|
||||
148 AUE_QUOTACTL STD { int quotactl(char *path, int cmd, int uid, \
|
||||
caddr_t arg); }
|
||||
149 AUE_O_QUOTA COMPAT { int quota(void); }
|
||||
150 AUE_GETSOCKNAME COMPAT|NOARGS { int getsockname(int fdec, \
|
||||
caddr_t asa, int *alen); } getsockname \
|
||||
getsockname_args int
|
||||
|
||||
; Syscalls 151-180 inclusive are reserved for vendor-specific
|
||||
; system calls. (This includes various calls added for compatibity
|
||||
; with other Unix variants.)
|
||||
; Some of these calls are now supported by BSD...
|
||||
151 AUE_NULL UNIMPL sem_lock (BSD/OS 2.x)
|
||||
152 AUE_NULL UNIMPL sem_wakeup (BSD/OS 2.x)
|
||||
153 AUE_NULL UNIMPL asyncdaemon (BSD/OS 2.x)
|
||||
; 154 is initialised by the NLM code, if present.
|
||||
154 AUE_NULL NOSTD { int nlm_syscall(int debug_level, int grace_period, int addr_count, char **addrs); }
|
||||
; 155 is initialized by the NFS code, if present.
|
||||
155 AUE_NFS_SVC NOSTD { int nfssvc(int flag, caddr_t argp); }
|
||||
156 AUE_GETDIRENTRIES COMPAT { int getdirentries(int fd, char *buf, \
|
||||
u_int count, long *basep); }
|
||||
157 AUE_STATFS COMPAT4 { int statfs(char *path, \
|
||||
struct ostatfs *buf); }
|
||||
158 AUE_FSTATFS COMPAT4 { int fstatfs(int fd, \
|
||||
struct ostatfs *buf); }
|
||||
159 AUE_NULL UNIMPL nosys
|
||||
160 AUE_LGETFH STD { int lgetfh(char *fname, \
|
||||
struct fhandle *fhp); }
|
||||
161 AUE_NFS_GETFH STD { int getfh(char *fname, \
|
||||
struct fhandle *fhp); }
|
||||
162 AUE_SYSCTL COMPAT4 { int getdomainname(char *domainname, \
|
||||
int len); }
|
||||
163 AUE_SYSCTL COMPAT4 { int setdomainname(char *domainname, \
|
||||
int len); }
|
||||
164 AUE_NULL COMPAT4 { int uname(struct utsname *name); }
|
||||
165 AUE_SYSARCH STD { int sysarch(int op, char *parms); }
|
||||
166 AUE_RTPRIO STD { int rtprio(int function, pid_t pid, \
|
||||
struct rtprio *rtp); }
|
||||
167 AUE_NULL UNIMPL nosys
|
||||
168 AUE_NULL UNIMPL nosys
|
||||
169 AUE_SEMSYS NOSTD { int semsys(int which, int a2, int a3, \
|
||||
int a4, int a5); }
|
||||
; XXX should be { int semsys(int which, ...); }
|
||||
170 AUE_MSGSYS NOSTD { int msgsys(int which, int a2, int a3, \
|
||||
int a4, int a5, int a6); }
|
||||
; XXX should be { int msgsys(int which, ...); }
|
||||
171 AUE_SHMSYS NOSTD { int shmsys(int which, int a2, int a3, \
|
||||
int a4); }
|
||||
; XXX should be { int shmsys(int which, ...); }
|
||||
172 AUE_NULL UNIMPL nosys
|
||||
173 AUE_PREAD STD { ssize_t freebsd6_pread(int fd, void *buf, \
|
||||
size_t nbyte, int pad, off_t offset); }
|
||||
174 AUE_PWRITE STD { ssize_t freebsd6_pwrite(int fd, \
|
||||
const void *buf, \
|
||||
size_t nbyte, int pad, off_t offset); }
|
||||
175 AUE_NULL STD { int setfib(int fibnum); }
|
||||
176 AUE_NTP_ADJTIME STD { int ntp_adjtime(struct timex *tp); }
|
||||
177 AUE_NULL UNIMPL sfork (BSD/OS 2.x)
|
||||
178 AUE_NULL UNIMPL getdescriptor (BSD/OS 2.x)
|
||||
179 AUE_NULL UNIMPL setdescriptor (BSD/OS 2.x)
|
||||
180 AUE_NULL UNIMPL nosys
|
||||
|
||||
; Syscalls 181-199 are used by/reserved for BSD
|
||||
181 AUE_SETGID STD { int setgid(gid_t gid); }
|
||||
182 AUE_SETEGID STD { int setegid(gid_t egid); }
|
||||
183 AUE_SETEUID STD { int seteuid(uid_t euid); }
|
||||
184 AUE_NULL UNIMPL lfs_bmapv
|
||||
185 AUE_NULL UNIMPL lfs_markv
|
||||
186 AUE_NULL UNIMPL lfs_segclean
|
||||
187 AUE_NULL UNIMPL lfs_segwait
|
||||
188 AUE_STAT STD { int stat(char *path, struct stat *ub); }
|
||||
189 AUE_FSTAT STD { int fstat(int fd, struct stat *sb); }
|
||||
190 AUE_LSTAT STD { int lstat(char *path, struct stat *ub); }
|
||||
191 AUE_PATHCONF STD { int pathconf(char *path, int name); }
|
||||
192 AUE_FPATHCONF STD { int fpathconf(int fd, int name); }
|
||||
193 AUE_NULL UNIMPL nosys
|
||||
194 AUE_GETRLIMIT STD { int getrlimit(u_int which, \
|
||||
struct rlimit *rlp); } getrlimit \
|
||||
__getrlimit_args int
|
||||
195 AUE_SETRLIMIT STD { int setrlimit(u_int which, \
|
||||
struct rlimit *rlp); } setrlimit \
|
||||
__setrlimit_args int
|
||||
196 AUE_GETDIRENTRIES STD { int getdirentries(int fd, char *buf, \
|
||||
u_int count, long *basep); }
|
||||
197 AUE_MMAP STD { caddr_t freebsd6_mmap(caddr_t addr, \
|
||||
size_t len, int prot, int flags, int fd, \
|
||||
int pad, off_t pos); }
|
||||
198 AUE_NULL NOPROTO { int nosys(void); } __syscall \
|
||||
__syscall_args int
|
||||
199 AUE_LSEEK STD { off_t freebsd6_lseek(int fd, int pad, \
|
||||
off_t offset, int whence); }
|
||||
200 AUE_TRUNCATE STD { int freebsd6_truncate(char *path, int pad, \
|
||||
off_t length); }
|
||||
201 AUE_FTRUNCATE STD { int freebsd6_ftruncate(int fd, int pad, \
|
||||
off_t length); }
|
||||
202 AUE_SYSCTL STD { int __sysctl(int *name, u_int namelen, \
|
||||
void *old, size_t *oldlenp, void *new, \
|
||||
size_t newlen); } __sysctl sysctl_args int
|
||||
203 AUE_MLOCK STD { int mlock(const void *addr, size_t len); }
|
||||
204 AUE_MUNLOCK STD { int munlock(const void *addr, size_t len); }
|
||||
205 AUE_UNDELETE STD { int undelete(char *path); }
|
||||
206 AUE_FUTIMES STD { int futimes(int fd, struct timeval *tptr); }
|
||||
207 AUE_GETPGID STD { int getpgid(pid_t pid); }
|
||||
208 AUE_NULL UNIMPL newreboot (NetBSD)
|
||||
209 AUE_POLL STD { int poll(struct pollfd *fds, u_int nfds, \
|
||||
int timeout); }
|
||||
|
||||
;
|
||||
; The following are reserved for loadable syscalls
|
||||
;
|
||||
210 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
211 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
212 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
213 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
214 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
215 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
216 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
217 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
218 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
219 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int
|
||||
|
||||
;
|
||||
; The following were introduced with NetBSD/4.4Lite-2
|
||||
220 AUE_SEMCTL COMPAT7|NOSTD { int __semctl(int semid, int semnum, \
|
||||
int cmd, union semun_old *arg); }
|
||||
221 AUE_SEMGET NOSTD { int semget(key_t key, int nsems, \
|
||||
int semflg); }
|
||||
222 AUE_SEMOP NOSTD { int semop(int semid, struct sembuf *sops, \
|
||||
size_t nsops); }
|
||||
223 AUE_NULL UNIMPL semconfig
|
||||
224 AUE_MSGCTL COMPAT7|NOSTD { int msgctl(int msqid, int cmd, \
|
||||
struct msqid_ds_old *buf); }
|
||||
225 AUE_MSGGET NOSTD { int msgget(key_t key, int msgflg); }
|
||||
226 AUE_MSGSND NOSTD { int msgsnd(int msqid, const void *msgp, \
|
||||
size_t msgsz, int msgflg); }
|
||||
227 AUE_MSGRCV NOSTD { int msgrcv(int msqid, void *msgp, \
|
||||
size_t msgsz, long msgtyp, int msgflg); }
|
||||
228 AUE_SHMAT NOSTD { int shmat(int shmid, const void *shmaddr, \
|
||||
int shmflg); }
|
||||
229 AUE_SHMCTL COMPAT7|NOSTD { int shmctl(int shmid, int cmd, \
|
||||
struct shmid_ds_old *buf); }
|
||||
230 AUE_SHMDT NOSTD { int shmdt(const void *shmaddr); }
|
||||
231 AUE_SHMGET NOSTD { int shmget(key_t key, size_t size, \
|
||||
int shmflg); }
|
||||
;
|
||||
232 AUE_NULL STD { int clock_gettime(clockid_t clock_id, \
|
||||
struct timespec *tp); }
|
||||
233 AUE_CLOCK_SETTIME STD { int clock_settime( \
|
||||
clockid_t clock_id, \
|
||||
const struct timespec *tp); }
|
||||
234 AUE_NULL STD { int clock_getres(clockid_t clock_id, \
|
||||
struct timespec *tp); }
|
||||
235 AUE_NULL STD { int ktimer_create(clockid_t clock_id, \
|
||||
struct sigevent *evp, int *timerid); }
|
||||
236 AUE_NULL STD { int ktimer_delete(int timerid); }
|
||||
237 AUE_NULL STD { int ktimer_settime(int timerid, int flags, \
|
||||
const struct itimerspec *value, \
|
||||
struct itimerspec *ovalue); }
|
||||
238 AUE_NULL STD { int ktimer_gettime(int timerid, struct \
|
||||
itimerspec *value); }
|
||||
239 AUE_NULL STD { int ktimer_getoverrun(int timerid); }
|
||||
240 AUE_NULL STD { int nanosleep(const struct timespec *rqtp, \
|
||||
struct timespec *rmtp); }
|
||||
241 AUE_NULL UNIMPL nosys
|
||||
242 AUE_NULL UNIMPL nosys
|
||||
243 AUE_NULL UNIMPL nosys
|
||||
244 AUE_NULL UNIMPL nosys
|
||||
245 AUE_NULL UNIMPL nosys
|
||||
246 AUE_NULL UNIMPL nosys
|
||||
247 AUE_NULL UNIMPL nosys
|
||||
248 AUE_NULL STD { int ntp_gettime(struct ntptimeval *ntvp); }
|
||||
249 AUE_NULL UNIMPL nosys
|
||||
; syscall numbers initially used in OpenBSD
|
||||
250 AUE_MINHERIT STD { int minherit(void *addr, size_t len, \
|
||||
int inherit); }
|
||||
251 AUE_RFORK STD { int rfork(int flags); }
|
||||
252 AUE_POLL STD { int openbsd_poll(struct pollfd *fds, \
|
||||
u_int nfds, int timeout); }
|
||||
253 AUE_ISSETUGID STD { int issetugid(void); }
|
||||
254 AUE_LCHOWN STD { int lchown(char *path, int uid, int gid); }
|
||||
255 AUE_NULL NOSTD { int aio_read(struct aiocb *aiocbp); }
|
||||
256 AUE_NULL NOSTD { int aio_write(struct aiocb *aiocbp); }
|
||||
257 AUE_NULL NOSTD { int lio_listio(int mode, \
|
||||
struct aiocb * const *acb_list, \
|
||||
int nent, struct sigevent *sig); }
|
||||
258 AUE_NULL UNIMPL nosys
|
||||
259 AUE_NULL UNIMPL nosys
|
||||
260 AUE_NULL UNIMPL nosys
|
||||
261 AUE_NULL UNIMPL nosys
|
||||
262 AUE_NULL UNIMPL nosys
|
||||
263 AUE_NULL UNIMPL nosys
|
||||
264 AUE_NULL UNIMPL nosys
|
||||
265 AUE_NULL UNIMPL nosys
|
||||
266 AUE_NULL UNIMPL nosys
|
||||
267 AUE_NULL UNIMPL nosys
|
||||
268 AUE_NULL UNIMPL nosys
|
||||
269 AUE_NULL UNIMPL nosys
|
||||
270 AUE_NULL UNIMPL nosys
|
||||
271 AUE_NULL UNIMPL nosys
|
||||
272 AUE_O_GETDENTS STD { int getdents(int fd, char *buf, \
|
||||
size_t count); }
|
||||
273 AUE_NULL UNIMPL nosys
|
||||
274 AUE_LCHMOD STD { int lchmod(char *path, mode_t mode); }
|
||||
275 AUE_LCHOWN NOPROTO { int lchown(char *path, uid_t uid, \
|
||||
gid_t gid); } netbsd_lchown lchown_args \
|
||||
int
|
||||
276 AUE_LUTIMES STD { int lutimes(char *path, \
|
||||
struct timeval *tptr); }
|
||||
277 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
|
||||
int flags); } netbsd_msync msync_args int
|
||||
278 AUE_STAT STD { int nstat(char *path, struct nstat *ub); }
|
||||
279 AUE_FSTAT STD { int nfstat(int fd, struct nstat *sb); }
|
||||
280 AUE_LSTAT STD { int nlstat(char *path, struct nstat *ub); }
|
||||
281 AUE_NULL UNIMPL nosys
|
||||
282 AUE_NULL UNIMPL nosys
|
||||
283 AUE_NULL UNIMPL nosys
|
||||
284 AUE_NULL UNIMPL nosys
|
||||
285 AUE_NULL UNIMPL nosys
|
||||
286 AUE_NULL UNIMPL nosys
|
||||
287 AUE_NULL UNIMPL nosys
|
||||
288 AUE_NULL UNIMPL nosys
|
||||
; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
|
||||
289 AUE_PREADV STD { ssize_t preadv(int fd, struct iovec *iovp, \
|
||||
u_int iovcnt, off_t offset); }
|
||||
290 AUE_PWRITEV STD { ssize_t pwritev(int fd, struct iovec *iovp, \
|
||||
u_int iovcnt, off_t offset); }
|
||||
291 AUE_NULL UNIMPL nosys
|
||||
292 AUE_NULL UNIMPL nosys
|
||||
293 AUE_NULL UNIMPL nosys
|
||||
294 AUE_NULL UNIMPL nosys
|
||||
295 AUE_NULL UNIMPL nosys
|
||||
296 AUE_NULL UNIMPL nosys
|
||||
; XXX 297 is 300 in NetBSD
|
||||
297 AUE_FHSTATFS COMPAT4 { int fhstatfs( \
|
||||
const struct fhandle *u_fhp, \
|
||||
struct ostatfs *buf); }
|
||||
298 AUE_FHOPEN STD { int fhopen(const struct fhandle *u_fhp, \
|
||||
int flags); }
|
||||
299 AUE_FHSTAT STD { int fhstat(const struct fhandle *u_fhp, \
|
||||
struct stat *sb); }
|
||||
; syscall numbers for FreeBSD
|
||||
300 AUE_NULL STD { int modnext(int modid); }
|
||||
301 AUE_NULL STD { int modstat(int modid, \
|
||||
struct module_stat *stat); }
|
||||
302 AUE_NULL STD { int modfnext(int modid); }
|
||||
303 AUE_NULL STD { int modfind(const char *name); }
|
||||
304 AUE_MODLOAD STD { int kldload(const char *file); }
|
||||
305 AUE_MODUNLOAD STD { int kldunload(int fileid); }
|
||||
306 AUE_NULL STD { int kldfind(const char *file); }
|
||||
307 AUE_NULL STD { int kldnext(int fileid); }
|
||||
308 AUE_NULL STD { int kldstat(int fileid, struct \
|
||||
kld_file_stat* stat); }
|
||||
309 AUE_NULL STD { int kldfirstmod(int fileid); }
|
||||
310 AUE_GETSID STD { int getsid(pid_t pid); }
|
||||
311 AUE_SETRESUID STD { int setresuid(uid_t ruid, uid_t euid, \
|
||||
uid_t suid); }
|
||||
312 AUE_SETRESGID STD { int setresgid(gid_t rgid, gid_t egid, \
|
||||
gid_t sgid); }
|
||||
313 AUE_NULL OBSOL signanosleep
|
||||
314 AUE_NULL NOSTD { int aio_return(struct aiocb *aiocbp); }
|
||||
315 AUE_NULL NOSTD { int aio_suspend( \
|
||||
struct aiocb * const * aiocbp, int nent, \
|
||||
const struct timespec *timeout); }
|
||||
316 AUE_NULL NOSTD { int aio_cancel(int fd, \
|
||||
struct aiocb *aiocbp); }
|
||||
317 AUE_NULL NOSTD { int aio_error(struct aiocb *aiocbp); }
|
||||
318 AUE_NULL NOSTD { int oaio_read(struct oaiocb *aiocbp); }
|
||||
319 AUE_NULL NOSTD { int oaio_write(struct oaiocb *aiocbp); }
|
||||
320 AUE_NULL NOSTD { int olio_listio(int mode, \
|
||||
struct oaiocb * const *acb_list, \
|
||||
int nent, struct osigevent *sig); }
|
||||
321 AUE_NULL STD { int yield(void); }
|
||||
322 AUE_NULL OBSOL thr_sleep
|
||||
323 AUE_NULL OBSOL thr_wakeup
|
||||
324 AUE_MLOCKALL STD { int mlockall(int how); }
|
||||
325 AUE_MUNLOCKALL STD { int munlockall(void); }
|
||||
326 AUE_GETCWD STD { int __getcwd(u_char *buf, u_int buflen); }
|
||||
|
||||
327 AUE_NULL STD { int sched_setparam (pid_t pid, \
|
||||
const struct sched_param *param); }
|
||||
328 AUE_NULL STD { int sched_getparam (pid_t pid, struct \
|
||||
sched_param *param); }
|
||||
|
||||
329 AUE_NULL STD { int sched_setscheduler (pid_t pid, int \
|
||||
policy, const struct sched_param \
|
||||
*param); }
|
||||
330 AUE_NULL STD { int sched_getscheduler (pid_t pid); }
|
||||
|
||||
331 AUE_NULL STD { int sched_yield (void); }
|
||||
332 AUE_NULL STD { int sched_get_priority_max (int policy); }
|
||||
333 AUE_NULL STD { int sched_get_priority_min (int policy); }
|
||||
334 AUE_NULL STD { int sched_rr_get_interval (pid_t pid, \
|
||||
struct timespec *interval); }
|
||||
335 AUE_NULL STD { int utrace(const void *addr, size_t len); }
|
||||
336 AUE_SENDFILE COMPAT4 { int sendfile(int fd, int s, \
|
||||
off_t offset, size_t nbytes, \
|
||||
struct sf_hdtr *hdtr, off_t *sbytes, \
|
||||
int flags); }
|
||||
337 AUE_NULL STD { int kldsym(int fileid, int cmd, \
|
||||
void *data); }
|
||||
338 AUE_JAIL STD { int jail(struct jail *jail); }
|
||||
339 AUE_NULL UNIMPL pioctl
|
||||
340 AUE_SIGPROCMASK STD { int sigprocmask(int how, \
|
||||
const sigset_t *set, sigset_t *oset); }
|
||||
341 AUE_SIGSUSPEND STD { int sigsuspend(const sigset_t *sigmask); }
|
||||
342 AUE_SIGACTION COMPAT4 { int sigaction(int sig, const \
|
||||
struct sigaction *act, \
|
||||
struct sigaction *oact); }
|
||||
343 AUE_SIGPENDING STD { int sigpending(sigset_t *set); }
|
||||
344 AUE_SIGRETURN COMPAT4 { int sigreturn( \
|
||||
const struct ucontext4 *sigcntxp); }
|
||||
345 AUE_SIGWAIT STD { int sigtimedwait(const sigset_t *set, \
|
||||
siginfo_t *info, \
|
||||
const struct timespec *timeout); }
|
||||
346 AUE_NULL STD { int sigwaitinfo(const sigset_t *set, \
|
||||
siginfo_t *info); }
|
||||
347 AUE_NULL STD { int __acl_get_file(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
348 AUE_NULL STD { int __acl_set_file(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
349 AUE_NULL STD { int __acl_get_fd(int filedes, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
350 AUE_NULL STD { int __acl_set_fd(int filedes, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
351 AUE_NULL STD { int __acl_delete_file(const char *path, \
|
||||
acl_type_t type); }
|
||||
352 AUE_NULL STD { int __acl_delete_fd(int filedes, \
|
||||
acl_type_t type); }
|
||||
353 AUE_NULL STD { int __acl_aclcheck_file(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
354 AUE_NULL STD { int __acl_aclcheck_fd(int filedes, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
355 AUE_EXTATTRCTL STD { int extattrctl(const char *path, int cmd, \
|
||||
const char *filename, int attrnamespace, \
|
||||
const char *attrname); }
|
||||
356 AUE_EXTATTR_SET_FILE STD { int extattr_set_file( \
|
||||
const char *path, int attrnamespace, \
|
||||
const char *attrname, void *data, \
|
||||
size_t nbytes); }
|
||||
357 AUE_EXTATTR_GET_FILE STD { ssize_t extattr_get_file( \
|
||||
const char *path, int attrnamespace, \
|
||||
const char *attrname, void *data, \
|
||||
size_t nbytes); }
|
||||
358 AUE_EXTATTR_DELETE_FILE STD { int extattr_delete_file(const char *path, \
|
||||
int attrnamespace, \
|
||||
const char *attrname); }
|
||||
359 AUE_NULL NOSTD { int aio_waitcomplete( \
|
||||
struct aiocb **aiocbp, \
|
||||
struct timespec *timeout); }
|
||||
360 AUE_GETRESUID STD { int getresuid(uid_t *ruid, uid_t *euid, \
|
||||
uid_t *suid); }
|
||||
361 AUE_GETRESGID STD { int getresgid(gid_t *rgid, gid_t *egid, \
|
||||
gid_t *sgid); }
|
||||
362 AUE_KQUEUE STD { int kqueue(void); }
|
||||
363 AUE_NULL STD { int kevent(int fd, \
|
||||
struct kevent *changelist, int nchanges, \
|
||||
struct kevent *eventlist, int nevents, \
|
||||
const struct timespec *timeout); }
|
||||
364 AUE_NULL UNIMPL __cap_get_proc
|
||||
365 AUE_NULL UNIMPL __cap_set_proc
|
||||
366 AUE_NULL UNIMPL __cap_get_fd
|
||||
367 AUE_NULL UNIMPL __cap_get_file
|
||||
368 AUE_NULL UNIMPL __cap_set_fd
|
||||
369 AUE_NULL UNIMPL __cap_set_file
|
||||
370 AUE_NULL UNIMPL nosys
|
||||
371 AUE_EXTATTR_SET_FD STD { int extattr_set_fd(int fd, \
|
||||
int attrnamespace, const char *attrname, \
|
||||
void *data, size_t nbytes); }
|
||||
372 AUE_EXTATTR_GET_FD STD { ssize_t extattr_get_fd(int fd, \
|
||||
int attrnamespace, const char *attrname, \
|
||||
void *data, size_t nbytes); }
|
||||
373 AUE_EXTATTR_DELETE_FD STD { int extattr_delete_fd(int fd, \
|
||||
int attrnamespace, \
|
||||
const char *attrname); }
|
||||
374 AUE_NULL STD { int __setugid(int flag); }
|
||||
375 AUE_NULL UNIMPL nfsclnt
|
||||
376 AUE_EACCESS STD { int eaccess(char *path, int flags); }
|
||||
377 AUE_NULL UNIMPL afs_syscall
|
||||
378 AUE_NMOUNT STD { int nmount(struct iovec *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
379 AUE_NULL UNIMPL kse_exit
|
||||
380 AUE_NULL UNIMPL kse_wakeup
|
||||
381 AUE_NULL UNIMPL kse_create
|
||||
382 AUE_NULL UNIMPL kse_thr_interrupt
|
||||
383 AUE_NULL UNIMPL kse_release
|
||||
384 AUE_NULL STD { int __mac_get_proc(struct mac *mac_p); }
|
||||
385 AUE_NULL STD { int __mac_set_proc(struct mac *mac_p); }
|
||||
386 AUE_NULL STD { int __mac_get_fd(int fd, \
|
||||
struct mac *mac_p); }
|
||||
387 AUE_NULL STD { int __mac_get_file(const char *path_p, \
|
||||
struct mac *mac_p); }
|
||||
388 AUE_NULL STD { int __mac_set_fd(int fd, \
|
||||
struct mac *mac_p); }
|
||||
389 AUE_NULL STD { int __mac_set_file(const char *path_p, \
|
||||
struct mac *mac_p); }
|
||||
390 AUE_NULL STD { int kenv(int what, const char *name, \
|
||||
char *value, int len); }
|
||||
391 AUE_LCHFLAGS STD { int lchflags(const char *path, int flags); }
|
||||
392 AUE_NULL STD { int uuidgen(struct uuid *store, \
|
||||
int count); }
|
||||
393 AUE_SENDFILE STD { int sendfile(int fd, int s, off_t offset, \
|
||||
size_t nbytes, struct sf_hdtr *hdtr, \
|
||||
off_t *sbytes, int flags); }
|
||||
394 AUE_NULL STD { int mac_syscall(const char *policy, \
|
||||
int call, void *arg); }
|
||||
395 AUE_GETFSSTAT STD { int getfsstat(struct statfs *buf, \
|
||||
long bufsize, int flags); }
|
||||
396 AUE_STATFS STD { int statfs(char *path, \
|
||||
struct statfs *buf); }
|
||||
397 AUE_FSTATFS STD { int fstatfs(int fd, struct statfs *buf); }
|
||||
398 AUE_FHSTATFS STD { int fhstatfs(const struct fhandle *u_fhp, \
|
||||
struct statfs *buf); }
|
||||
399 AUE_NULL UNIMPL nosys
|
||||
400 AUE_NULL NOSTD { int ksem_close(semid_t id); }
|
||||
401 AUE_NULL NOSTD { int ksem_post(semid_t id); }
|
||||
402 AUE_NULL NOSTD { int ksem_wait(semid_t id); }
|
||||
403 AUE_NULL NOSTD { int ksem_trywait(semid_t id); }
|
||||
404 AUE_NULL NOSTD { int ksem_init(semid_t *idp, \
|
||||
unsigned int value); }
|
||||
405 AUE_NULL NOSTD { int ksem_open(semid_t *idp, \
|
||||
const char *name, int oflag, \
|
||||
mode_t mode, unsigned int value); }
|
||||
406 AUE_NULL NOSTD { int ksem_unlink(const char *name); }
|
||||
407 AUE_NULL NOSTD { int ksem_getvalue(semid_t id, int *val); }
|
||||
408 AUE_NULL NOSTD { int ksem_destroy(semid_t id); }
|
||||
409 AUE_NULL STD { int __mac_get_pid(pid_t pid, \
|
||||
struct mac *mac_p); }
|
||||
410 AUE_NULL STD { int __mac_get_link(const char *path_p, \
|
||||
struct mac *mac_p); }
|
||||
411 AUE_NULL STD { int __mac_set_link(const char *path_p, \
|
||||
struct mac *mac_p); }
|
||||
412 AUE_EXTATTR_SET_LINK STD { int extattr_set_link( \
|
||||
const char *path, int attrnamespace, \
|
||||
const char *attrname, void *data, \
|
||||
size_t nbytes); }
|
||||
413 AUE_EXTATTR_GET_LINK STD { ssize_t extattr_get_link( \
|
||||
const char *path, int attrnamespace, \
|
||||
const char *attrname, void *data, \
|
||||
size_t nbytes); }
|
||||
414 AUE_EXTATTR_DELETE_LINK STD { int extattr_delete_link( \
|
||||
const char *path, int attrnamespace, \
|
||||
const char *attrname); }
|
||||
415 AUE_NULL STD { int __mac_execve(char *fname, char **argv, \
|
||||
char **envv, struct mac *mac_p); }
|
||||
416 AUE_SIGACTION STD { int sigaction(int sig, \
|
||||
const struct sigaction *act, \
|
||||
struct sigaction *oact); }
|
||||
417 AUE_SIGRETURN STD { int sigreturn( \
|
||||
const struct __ucontext *sigcntxp); }
|
||||
418 AUE_NULL UNIMPL __xstat
|
||||
419 AUE_NULL UNIMPL __xfstat
|
||||
420 AUE_NULL UNIMPL __xlstat
|
||||
421 AUE_NULL STD { int getcontext(struct __ucontext *ucp); }
|
||||
422 AUE_NULL STD { int setcontext( \
|
||||
const struct __ucontext *ucp); }
|
||||
423 AUE_NULL STD { int swapcontext(struct __ucontext *oucp, \
|
||||
const struct __ucontext *ucp); }
|
||||
424 AUE_SWAPOFF STD { int swapoff(const char *name); }
|
||||
425 AUE_NULL STD { int __acl_get_link(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
426 AUE_NULL STD { int __acl_set_link(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
427 AUE_NULL STD { int __acl_delete_link(const char *path, \
|
||||
acl_type_t type); }
|
||||
428 AUE_NULL STD { int __acl_aclcheck_link(const char *path, \
|
||||
acl_type_t type, struct acl *aclp); }
|
||||
429 AUE_SIGWAIT STD { int sigwait(const sigset_t *set, \
|
||||
int *sig); }
|
||||
430 AUE_NULL STD { int thr_create(ucontext_t *ctx, long *id, \
|
||||
int flags); }
|
||||
431 AUE_NULL STD { void thr_exit(long *state); }
|
||||
432 AUE_NULL STD { int thr_self(long *id); }
|
||||
433 AUE_NULL STD { int thr_kill(long id, int sig); }
|
||||
434 AUE_NULL STD { int _umtx_lock(struct umtx *umtx); }
|
||||
435 AUE_NULL STD { int _umtx_unlock(struct umtx *umtx); }
|
||||
436 AUE_NULL STD { int jail_attach(int jid); }
|
||||
437 AUE_EXTATTR_LIST_FD STD { ssize_t extattr_list_fd(int fd, \
|
||||
int attrnamespace, void *data, \
|
||||
size_t nbytes); }
|
||||
438 AUE_EXTATTR_LIST_FILE STD { ssize_t extattr_list_file( \
|
||||
const char *path, int attrnamespace, \
|
||||
void *data, size_t nbytes); }
|
||||
439 AUE_EXTATTR_LIST_LINK STD { ssize_t extattr_list_link( \
|
||||
const char *path, int attrnamespace, \
|
||||
void *data, size_t nbytes); }
|
||||
440 AUE_NULL UNIMPL kse_switchin
|
||||
441 AUE_NULL NOSTD { int ksem_timedwait(semid_t id, \
|
||||
const struct timespec *abstime); }
|
||||
442 AUE_NULL STD { int thr_suspend( \
|
||||
const struct timespec *timeout); }
|
||||
443 AUE_NULL STD { int thr_wake(long id); }
|
||||
444 AUE_MODUNLOAD STD { int kldunloadf(int fileid, int flags); }
|
||||
445 AUE_AUDIT STD { int audit(const void *record, \
|
||||
u_int length); }
|
||||
446 AUE_AUDITON STD { int auditon(int cmd, void *data, \
|
||||
u_int length); }
|
||||
447 AUE_GETAUID STD { int getauid(uid_t *auid); }
|
||||
448 AUE_SETAUID STD { int setauid(uid_t *auid); }
|
||||
449 AUE_GETAUDIT STD { int getaudit(struct auditinfo *auditinfo); }
|
||||
450 AUE_SETAUDIT STD { int setaudit(struct auditinfo *auditinfo); }
|
||||
451 AUE_GETAUDIT_ADDR STD { int getaudit_addr( \
|
||||
struct auditinfo_addr *auditinfo_addr, \
|
||||
u_int length); }
|
||||
452 AUE_SETAUDIT_ADDR STD { int setaudit_addr( \
|
||||
struct auditinfo_addr *auditinfo_addr, \
|
||||
u_int length); }
|
||||
453 AUE_AUDITCTL STD { int auditctl(char *path); }
|
||||
454 AUE_NULL STD { int _umtx_op(void *obj, int op, \
|
||||
u_long val, void *uaddr1, void *uaddr2); }
|
||||
455 AUE_NULL STD { int thr_new(struct thr_param *param, \
|
||||
int param_size); }
|
||||
456 AUE_NULL STD { int sigqueue(pid_t pid, int signum, void *value); }
|
||||
457 AUE_NULL NOSTD { int kmq_open(const char *path, int flags, \
|
||||
mode_t mode, const struct mq_attr *attr); }
|
||||
458 AUE_NULL NOSTD { int kmq_setattr(int mqd, \
|
||||
const struct mq_attr *attr, \
|
||||
struct mq_attr *oattr); }
|
||||
459 AUE_NULL NOSTD { int kmq_timedreceive(int mqd, \
|
||||
char *msg_ptr, size_t msg_len, \
|
||||
unsigned *msg_prio, \
|
||||
const struct timespec *abs_timeout); }
|
||||
460 AUE_NULL NOSTD { int kmq_timedsend(int mqd, \
|
||||
const char *msg_ptr, size_t msg_len,\
|
||||
unsigned msg_prio, \
|
||||
const struct timespec *abs_timeout);}
|
||||
461 AUE_NULL NOSTD { int kmq_notify(int mqd, \
|
||||
const struct sigevent *sigev); }
|
||||
462 AUE_NULL NOSTD { int kmq_unlink(const char *path); }
|
||||
463 AUE_NULL STD { int abort2(const char *why, int nargs, void **args); }
|
||||
464 AUE_NULL STD { int thr_set_name(long id, const char *name); }
|
||||
465 AUE_NULL NOSTD { int aio_fsync(int op, struct aiocb *aiocbp); }
|
||||
466 AUE_RTPRIO STD { int rtprio_thread(int function, \
|
||||
lwpid_t lwpid, struct rtprio *rtp); }
|
||||
467 AUE_NULL UNIMPL nosys
|
||||
468 AUE_NULL UNIMPL nosys
|
||||
469 AUE_NULL UNIMPL __getpath_fromfd
|
||||
470 AUE_NULL UNIMPL __getpath_fromaddr
|
||||
471 AUE_NULL STD { int sctp_peeloff(int sd, uint32_t name); }
|
||||
472 AUE_NULL STD { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
|
||||
caddr_t to, __socklen_t tolen, \
|
||||
struct sctp_sndrcvinfo *sinfo, int flags); }
|
||||
473 AUE_NULL STD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
|
||||
caddr_t to, __socklen_t tolen, \
|
||||
struct sctp_sndrcvinfo *sinfo, int flags); }
|
||||
474 AUE_NULL STD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
|
||||
struct sockaddr * from, __socklen_t *fromlenaddr, \
|
||||
struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
|
||||
475 AUE_PREAD STD { ssize_t pread(int fd, void *buf, \
|
||||
size_t nbyte, off_t offset); }
|
||||
476 AUE_PWRITE STD { ssize_t pwrite(int fd, const void *buf, \
|
||||
size_t nbyte, off_t offset); }
|
||||
477 AUE_MMAP STD { caddr_t mmap(caddr_t addr, size_t len, \
|
||||
int prot, int flags, int fd, off_t pos); }
|
||||
478 AUE_LSEEK STD { off_t lseek(int fd, off_t offset, \
|
||||
int whence); }
|
||||
479 AUE_TRUNCATE STD { int truncate(char *path, off_t length); }
|
||||
480 AUE_FTRUNCATE STD { int ftruncate(int fd, off_t length); }
|
||||
481 AUE_KILL STD { int thr_kill2(pid_t pid, long id, int sig); }
|
||||
482 AUE_SHMOPEN STD { int shm_open(const char *path, int flags, \
|
||||
mode_t mode); }
|
||||
483 AUE_SHMUNLINK STD { int shm_unlink(const char *path); }
|
||||
484 AUE_NULL STD { int cpuset(cpusetid_t *setid); }
|
||||
485 AUE_NULL STD { int cpuset_setid(cpuwhich_t which, id_t id, \
|
||||
cpusetid_t setid); }
|
||||
486 AUE_NULL STD { int cpuset_getid(cpulevel_t level, \
|
||||
cpuwhich_t which, id_t id, \
|
||||
cpusetid_t *setid); }
|
||||
487 AUE_NULL STD { int cpuset_getaffinity(cpulevel_t level, \
|
||||
cpuwhich_t which, id_t id, size_t cpusetsize, \
|
||||
cpuset_t *mask); }
|
||||
488 AUE_NULL STD { int cpuset_setaffinity(cpulevel_t level, \
|
||||
cpuwhich_t which, id_t id, size_t cpusetsize, \
|
||||
const cpuset_t *mask); }
|
||||
489 AUE_FACCESSAT STD { int faccessat(int fd, char *path, int mode, \
|
||||
int flag); }
|
||||
490 AUE_FCHMODAT STD { int fchmodat(int fd, char *path, mode_t mode, \
|
||||
int flag); }
|
||||
491 AUE_FCHOWNAT STD { int fchownat(int fd, char *path, uid_t uid, \
|
||||
gid_t gid, int flag); }
|
||||
492 AUE_FEXECVE STD { int fexecve(int fd, char **argv, \
|
||||
char **envv); }
|
||||
493 AUE_FSTATAT STD { int fstatat(int fd, char *path, \
|
||||
struct stat *buf, int flag); }
|
||||
494 AUE_FUTIMESAT STD { int futimesat(int fd, char *path, \
|
||||
struct timeval *times); }
|
||||
495 AUE_LINKAT STD { int linkat(int fd1, char *path1, int fd2, \
|
||||
char *path2, int flag); }
|
||||
496 AUE_MKDIRAT STD { int mkdirat(int fd, char *path, mode_t mode); }
|
||||
497 AUE_MKFIFOAT STD { int mkfifoat(int fd, char *path, mode_t mode); }
|
||||
498 AUE_MKNODAT STD { int mknodat(int fd, char *path, mode_t mode, \
|
||||
dev_t dev); }
|
||||
; XXX: see the comment for open
|
||||
499 AUE_OPENAT_RWTC STD { int openat(int fd, char *path, int flag, \
|
||||
mode_t mode); }
|
||||
500 AUE_READLINKAT STD { int readlinkat(int fd, char *path, char *buf, \
|
||||
size_t bufsize); }
|
||||
501 AUE_RENAMEAT STD { int renameat(int oldfd, char *old, int newfd, \
|
||||
char *new); }
|
||||
502 AUE_SYMLINKAT STD { int symlinkat(char *path1, int fd, \
|
||||
char *path2); }
|
||||
503 AUE_UNLINKAT STD { int unlinkat(int fd, char *path, int flag); }
|
||||
504 AUE_POSIX_OPENPT STD { int posix_openpt(int flags); }
|
||||
; 505 is initialised by the kgssapi code, if present.
|
||||
505 AUE_NULL NOSTD { int gssd_syscall(char *path); }
|
||||
506 AUE_NULL STD { int jail_get(struct iovec *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
507 AUE_NULL STD { int jail_set(struct iovec *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
508 AUE_NULL STD { int jail_remove(int jid); }
|
||||
509 AUE_CLOSEFROM STD { int closefrom(int lowfd); }
|
||||
510 AUE_SEMCTL NOSTD { int __semctl(int semid, int semnum, \
|
||||
int cmd, union semun *arg); }
|
||||
511 AUE_MSGCTL NOSTD { int msgctl(int msqid, int cmd, \
|
||||
struct msqid_ds *buf); }
|
||||
512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \
|
||||
struct shmid_ds *buf); }
|
||||
513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); }
|
||||
514 AUE_CAP_NEW UNIMPL cap_new
|
||||
515 AUE_CAP_GETRIGHTS UNIMPL cap_getrights
|
||||
516 AUE_CAP_ENTER UNIMPL cap_enter
|
||||
517 AUE_CAP_GETMODE UNIMPL cap_getmode
|
||||
518 AUE_PDFORK UNIMPL pdfork
|
||||
519 AUE_PDKILL UNIMPL pdkill
|
||||
520 AUE_PDGETPID UNIMPL pdgetpid
|
||||
521 AUE_PDWAIT UNIMPL pdwait
|
||||
522 AUE_SELECT STD { int pselect(int nd, fd_set *in, \
|
||||
fd_set *ou, fd_set *ex, \
|
||||
const struct timespec *ts, \
|
||||
const sigset_t *sm); }
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/compat/freebsd32/syscalls.master
|
4688
x86/support/make_bsd_syscalls/syscalls.master.h
Normal file
4688
x86/support/make_bsd_syscalls/syscalls.master.h
Normal file
File diff suppressed because it is too large
Load Diff
220
x86/support/make_linux_syscalls/Main.hs
Normal file
220
x86/support/make_linux_syscalls/Main.hs
Normal file
@ -0,0 +1,220 @@
|
||||
{-
|
||||
The driver for creating SyscallInfo.Linux
|
||||
-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
module Main (main) where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Attoparsec.ByteString.Char8 (Parser)
|
||||
import qualified Data.Attoparsec.ByteString.Char8 as P
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString.Char8 as BS
|
||||
import Data.Either (either)
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import Data.Maybe (catMaybes, maybe, isNothing, listToMaybe)
|
||||
import Language.C
|
||||
import Language.C.Analysis.AstAnalysis
|
||||
import Language.C.Analysis.SemRep
|
||||
import Language.C.Analysis.TravMonad
|
||||
import Language.C.Data.Ident
|
||||
import Language.C.Data.Name (newNameSupply)
|
||||
import Language.C.Data.Position (position)
|
||||
import Language.C.System.GCC (newGCC)
|
||||
import System.Environment (getArgs)
|
||||
import System.Exit
|
||||
import System.IO
|
||||
import Text.PrettyPrint
|
||||
import Text.Show.Pretty
|
||||
|
||||
import Debug.Trace
|
||||
|
||||
-- FIXME: clag from Data.Macaw.Architecture.Syscall
|
||||
data SyscallArgType = VoidArgType | WordArgType | XMMFloatType
|
||||
deriving (Eq, Show, Read)
|
||||
|
||||
|
||||
-- | The syscall_64.tbl file looks like (after pre-processing)
|
||||
--
|
||||
-- # comment1
|
||||
-- ... more comments
|
||||
-- # commentn
|
||||
-- <syscall no.>\t+<abi>\t+<syscall name>\t<entry point>
|
||||
--
|
||||
-- for example
|
||||
--
|
||||
-- 5 common fstat sys_newfstat
|
||||
--
|
||||
-- entry point is optional -- if it is not present, syscall name is used.
|
||||
|
||||
data SyscallInfo =
|
||||
SyscallInfo { syscallNo :: Integer
|
||||
, syscallABI :: ByteString
|
||||
, syscallName :: ByteString
|
||||
, syscallProto :: Either ByteString IdentDecl
|
||||
}
|
||||
-- deriving Show
|
||||
|
||||
pp si = print $ integer (syscallNo si) <+> text (show $ syscallName si)
|
||||
<+> text "->"
|
||||
<+> either (const "???") pretty (syscallProto si)
|
||||
|
||||
-- A bit hacky, but no less than using TH to read in a text file
|
||||
generateHSFile :: [SyscallInfo] -> Doc
|
||||
generateHSFile sis =
|
||||
vcat $ [ text "-- DO NOT EDIT. Generated from make_linux_syscalls/Main.hs"
|
||||
, text "module Data.Macaw.X86.SyscallInfo.Linux (syscallInfo) where"
|
||||
, text "import Data.Macaw.Architecture.Syscall"
|
||||
, text "import Data.Map (Map, fromList)"
|
||||
, text "import Data.Word"
|
||||
, text ""
|
||||
, text "syscallInfo :: Map Word64 SyscallTypeInfo"
|
||||
, text "syscallInfo =" <+> ppDoc syscallMap ]
|
||||
++ unknownSyscalls
|
||||
where
|
||||
syscallMap = Map.fromList [ (syscallNo si, syscallInfo idecl)
|
||||
| si <- sis
|
||||
, Right idecl <- [ syscallProto si ] ]
|
||||
unknownSyscalls =
|
||||
text "-- Unknown system calls: " :
|
||||
[ text "--" <+> integer (syscallNo si) <+> text (BS.unpack str)
|
||||
| si <- sis
|
||||
, Left str <- [ syscallProto si ] ]
|
||||
|
||||
-- syscallInfo :: CExtDecl -> Maybe (String, SyscallArgType, [SyscallArgType])
|
||||
syscallInfo (getVarDecl -> VarDecl vname _ (FunctionType (FunType rettyp params _) _)) =
|
||||
( identToString (identOfVarName vname)
|
||||
, typeToArgType rettyp
|
||||
, map (typeToArgType . declType) params )
|
||||
|
||||
-- syscallInfo (CDeclExt (CDecl [CTypeSpec spec] [(Just declr, _, _)] _))
|
||||
-- | CDeclr (Just ident) [CFunDeclr (Right (decls, _)) _ _] _ _ _ <- declr
|
||||
-- = Just (identToString ident, typeSpecToArgType spec, map declToArgType decls)
|
||||
-- syscallInfo d = error ("unhandled decl" ++ show d)
|
||||
|
||||
-- declToArgType (CDecl [CTypeSpec spec] _) = typeSpecToArgType spec
|
||||
-- declToArgType d = error ("unhandled decl (in type) " ++ show d)
|
||||
|
||||
typeToArgType :: Type -> SyscallArgType
|
||||
typeToArgType typ =
|
||||
case typ of
|
||||
DirectType typ' _ _ ->
|
||||
case typ' of
|
||||
TyVoid -> VoidArgType
|
||||
TyIntegral _ -> WordArgType
|
||||
TyFloating TyLDouble -> unhandled
|
||||
TyFloating _ -> XMMFloatType
|
||||
TyComplex _ -> unhandled
|
||||
TyComp comp -> unhandled -- compTypeToArgType comp
|
||||
TyEnum _ -> WordArgType -- FIXME: ???
|
||||
TyBuiltin _ -> unhandled
|
||||
PtrType _ _ _ -> WordArgType
|
||||
ArrayType _ _ _ _ -> WordArgType
|
||||
FunctionType _ _ -> unhandled
|
||||
TypeDefType (TypeDefRef _ (Just typ) _) _ _ -> typeToArgType typ
|
||||
where
|
||||
unhandled = error ("Unhandled type: " ++ show (pretty typ))
|
||||
|
||||
compTypeToArgType :: CompTypeRef -> SyscallArgType
|
||||
compTypeToArgType ctyp = trace ("Comp type: " ++ show (pretty ctyp)) WordArgType
|
||||
|
||||
-- We support as little as possible here ...
|
||||
-- typeSpecToArgType :: Show a => CTypeSpecifier a -> SyscallArgType
|
||||
-- typeSpecToArgType tspec =
|
||||
-- case tspec of
|
||||
-- CVoidType _ -> VoidArgType
|
||||
-- CCharType _ -> WordArgType
|
||||
-- CShortType _ -> WordArgType
|
||||
-- CIntType _ -> WordArgType
|
||||
-- CLongType _ -> WordArgType
|
||||
-- CFloatType _ -> XMMFloatType
|
||||
-- CDoubleType _ -> XMMFloatType
|
||||
-- CSignedType _ -> WordArgType
|
||||
-- CUnsigType _ -> WordArgType
|
||||
-- CBoolType _ -> WordArgType
|
||||
-- CSUType _ _ -> unhandled
|
||||
-- CEnumType _ _ -> WordArgType -- FIXME: does it fit in a word?
|
||||
-- CComplexType _ -> unhandled
|
||||
-- CTypeDef __dent _ -> unhandled
|
||||
-- CTypeOfExpr _ _ -> unhandled
|
||||
-- CTypeOfType _ _ -> unhandled
|
||||
-- where
|
||||
-- unhandled = error ("Unhandled type specifier: " ++ show tspec)
|
||||
|
||||
readOneCFile :: FilePath -> IO (Map ByteString IdentDecl)
|
||||
readOneCFile f = do
|
||||
r <- parseCFile (newGCC "gcc") Nothing [] f
|
||||
tunit <- case r of
|
||||
Right v -> return v
|
||||
Left err -> error (show err)
|
||||
|
||||
let gdecls = case runTrav_ (analyseAST tunit) of
|
||||
Left err -> error $ "Error: " ++ (show err)
|
||||
Right (gdecls, _) -> gdecls
|
||||
|
||||
return (Map.mapKeys (\(Ident name _ _) -> BS.pack name) $ gObjs gdecls)
|
||||
|
||||
syscallLine :: Map ByteString IdentDecl -> Parser (Maybe SyscallInfo)
|
||||
syscallLine idents = do
|
||||
P.skipSpace
|
||||
P.choice [ P.char '#' >> return Nothing
|
||||
, P.endOfInput >> return Nothing
|
||||
, parseLine
|
||||
]
|
||||
where
|
||||
parseLine = do
|
||||
num <- P.decimal
|
||||
P.skipSpace
|
||||
abi <- P.takeWhile (not . P.isSpace)
|
||||
P.skipSpace
|
||||
name <- P.takeWhile (not . P.isSpace)
|
||||
P.skipSpace
|
||||
ident <- P.choice [ P.takeWhile1 (not . P.isSpace)
|
||||
, return name ]
|
||||
if abi == "x32"
|
||||
then return Nothing
|
||||
else return (Just (SyscallInfo num abi name (findIdent ident)))
|
||||
|
||||
findIdent bytes =
|
||||
case (Map.lookup bytes idents) of
|
||||
Nothing -> Left bytes
|
||||
Just v -> Right v
|
||||
-- -- FIXME: we should maybe chain through newNameSupply? I don't think it is ever used ...
|
||||
-- case execParser expressionP bytes (position 0 "" 0 0) idents newNameSupply of
|
||||
-- Right (CVar ident _, _unusedNames) -> Just ident
|
||||
-- Right (e, _) -> trace ("Unknown expr: " ++ show e) Nothing
|
||||
-- _ -> trace ("Couldn't find '" ++ show bytes ++ "'") Nothing
|
||||
|
||||
|
||||
showUsageAndExit :: IO a
|
||||
showUsageAndExit = do
|
||||
hPutStrLn stderr $ unlines
|
||||
[ "This program generates the Haskell module that maps system call ids"
|
||||
, "in Linux to the name, argument types, and result type."
|
||||
, ""
|
||||
, "Please specify the syscals_tbl file and header files arguments."
|
||||
, "The resulting Haskell module will be written to standard out."
|
||||
]
|
||||
exitFailure
|
||||
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
|
||||
(syscalls_tbl_file, h_files) <-
|
||||
case args of
|
||||
tbl_file : h_files -> pure (tbl_file, h_files)
|
||||
[] -> showUsageAndExit
|
||||
|
||||
syscalls <- BS.lines <$> BS.readFile syscalls_tbl_file
|
||||
gdecls <- mconcat <$> mapM readOneCFile h_files
|
||||
|
||||
ms <- case mapM (P.parseOnly (syscallLine gdecls)) syscalls of
|
||||
Left err -> error $ "Error: " ++ err
|
||||
Right ms -> return ms
|
||||
|
||||
-- mapM_ pp (catMaybes ms)
|
||||
print (generateHSFile $ catMaybes ms)
|
10
x86/support/make_linux_syscalls/README
Normal file
10
x86/support/make_linux_syscalls/README
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
This directory contains a script to scrape the Linux header files to
|
||||
produce types for most system calls.
|
||||
|
||||
From the build directory, run the following for FILE in {source/arch/x86/include/asm/syscalls.h, source/include/linux/syscalls.h}
|
||||
|
||||
sed -i 's/#define CONFIG_ARCH_SUPPORTS_INT128.*//' include/generated/autoconf.h && gcc -Wp,-MD,init/.main.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.9/include -I/usr/src/linux-headers-lbm- -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/include -Iinclude -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/include/uapi -Iinclude/generated/uapi -include /usr/src/linux-source-3.19.0/linux-source-3.19.0/include/linux/kconfig.h -Iubuntu/include -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/ubuntu/include -I/usr/src/linux-source-3.19.0/linux-source-3.19.0/init -Iinit -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -m64 -mno-80387 -mno-fp-ret-in-387 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fno-delete-null-pointer-checks -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -gdwarf-4 -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(main)" -D"KBUILD_MODNAME=KBUILD_STR(main)" -E FILE > FILE.cpp
|
||||
|
||||
sed 's/stub_/sys_/' source/arch/x86/syscall_64.tbl > syscall_64.tbl
|
||||
|
9041
x86/support/make_linux_syscalls/asm_syscalls.h.cpp
Normal file
9041
x86/support/make_linux_syscalls/asm_syscalls.h.cpp
Normal file
File diff suppressed because one or more lines are too long
370
x86/support/make_linux_syscalls/syscall_64.tbl
Normal file
370
x86/support/make_linux_syscalls/syscall_64.tbl
Normal file
@ -0,0 +1,370 @@
|
||||
#
|
||||
# 64-bit system call numbers and entry vectors
|
||||
#
|
||||
# The format is:
|
||||
# <number> <abi> <name> <entry point>
|
||||
#
|
||||
# The abi is "common", "64" or "x32" for this file.
|
||||
#
|
||||
0 common read sys_read
|
||||
1 common write sys_write
|
||||
2 common open sys_open
|
||||
3 common close sys_close
|
||||
4 common stat sys_newstat
|
||||
5 common fstat sys_newfstat
|
||||
6 common lstat sys_newlstat
|
||||
7 common poll sys_poll
|
||||
8 common lseek sys_lseek
|
||||
9 common mmap sys_mmap
|
||||
10 common mprotect sys_mprotect
|
||||
11 common munmap sys_munmap
|
||||
12 common brk sys_brk
|
||||
13 64 rt_sigaction sys_rt_sigaction
|
||||
14 common rt_sigprocmask sys_rt_sigprocmask
|
||||
15 64 rt_sigreturn sys_rt_sigreturn
|
||||
16 64 ioctl sys_ioctl
|
||||
17 common pread64 sys_pread64
|
||||
18 common pwrite64 sys_pwrite64
|
||||
19 64 readv sys_readv
|
||||
20 64 writev sys_writev
|
||||
21 common access sys_access
|
||||
22 common pipe sys_pipe
|
||||
23 common select sys_select
|
||||
24 common sched_yield sys_sched_yield
|
||||
25 common mremap sys_mremap
|
||||
26 common msync sys_msync
|
||||
27 common mincore sys_mincore
|
||||
28 common madvise sys_madvise
|
||||
29 common shmget sys_shmget
|
||||
30 common shmat sys_shmat
|
||||
31 common shmctl sys_shmctl
|
||||
32 common dup sys_dup
|
||||
33 common dup2 sys_dup2
|
||||
34 common pause sys_pause
|
||||
35 common nanosleep sys_nanosleep
|
||||
36 common getitimer sys_getitimer
|
||||
37 common alarm sys_alarm
|
||||
38 common setitimer sys_setitimer
|
||||
39 common getpid sys_getpid
|
||||
40 common sendfile sys_sendfile64
|
||||
41 common socket sys_socket
|
||||
42 common connect sys_connect
|
||||
43 common accept sys_accept
|
||||
44 common sendto sys_sendto
|
||||
45 64 recvfrom sys_recvfrom
|
||||
46 64 sendmsg sys_sendmsg
|
||||
47 64 recvmsg sys_recvmsg
|
||||
48 common shutdown sys_shutdown
|
||||
49 common bind sys_bind
|
||||
50 common listen sys_listen
|
||||
51 common getsockname sys_getsockname
|
||||
52 common getpeername sys_getpeername
|
||||
53 common socketpair sys_socketpair
|
||||
54 64 setsockopt sys_setsockopt
|
||||
55 64 getsockopt sys_getsockopt
|
||||
56 common clone sys_clone
|
||||
57 common fork sys_fork
|
||||
58 common vfork sys_vfork
|
||||
59 64 execve sys_execve
|
||||
60 common exit sys_exit
|
||||
61 common wait4 sys_wait4
|
||||
62 common kill sys_kill
|
||||
63 common uname sys_newuname
|
||||
64 common semget sys_semget
|
||||
65 common semop sys_semop
|
||||
66 common semctl sys_semctl
|
||||
67 common shmdt sys_shmdt
|
||||
68 common msgget sys_msgget
|
||||
69 common msgsnd sys_msgsnd
|
||||
70 common msgrcv sys_msgrcv
|
||||
71 common msgctl sys_msgctl
|
||||
72 common fcntl sys_fcntl
|
||||
73 common flock sys_flock
|
||||
74 common fsync sys_fsync
|
||||
75 common fdatasync sys_fdatasync
|
||||
76 common truncate sys_truncate
|
||||
77 common ftruncate sys_ftruncate
|
||||
78 common getdents sys_getdents
|
||||
79 common getcwd sys_getcwd
|
||||
80 common chdir sys_chdir
|
||||
81 common fchdir sys_fchdir
|
||||
82 common rename sys_rename
|
||||
83 common mkdir sys_mkdir
|
||||
84 common rmdir sys_rmdir
|
||||
85 common creat sys_creat
|
||||
86 common link sys_link
|
||||
87 common unlink sys_unlink
|
||||
88 common symlink sys_symlink
|
||||
89 common readlink sys_readlink
|
||||
90 common chmod sys_chmod
|
||||
91 common fchmod sys_fchmod
|
||||
92 common chown sys_chown
|
||||
93 common fchown sys_fchown
|
||||
94 common lchown sys_lchown
|
||||
95 common umask sys_umask
|
||||
96 common gettimeofday sys_gettimeofday
|
||||
97 common getrlimit sys_getrlimit
|
||||
98 common getrusage sys_getrusage
|
||||
99 common sysinfo sys_sysinfo
|
||||
100 common times sys_times
|
||||
101 64 ptrace sys_ptrace
|
||||
102 common getuid sys_getuid
|
||||
103 common syslog sys_syslog
|
||||
104 common getgid sys_getgid
|
||||
105 common setuid sys_setuid
|
||||
106 common setgid sys_setgid
|
||||
107 common geteuid sys_geteuid
|
||||
108 common getegid sys_getegid
|
||||
109 common setpgid sys_setpgid
|
||||
110 common getppid sys_getppid
|
||||
111 common getpgrp sys_getpgrp
|
||||
112 common setsid sys_setsid
|
||||
113 common setreuid sys_setreuid
|
||||
114 common setregid sys_setregid
|
||||
115 common getgroups sys_getgroups
|
||||
116 common setgroups sys_setgroups
|
||||
117 common setresuid sys_setresuid
|
||||
118 common getresuid sys_getresuid
|
||||
119 common setresgid sys_setresgid
|
||||
120 common getresgid sys_getresgid
|
||||
121 common getpgid sys_getpgid
|
||||
122 common setfsuid sys_setfsuid
|
||||
123 common setfsgid sys_setfsgid
|
||||
124 common getsid sys_getsid
|
||||
125 common capget sys_capget
|
||||
126 common capset sys_capset
|
||||
127 64 rt_sigpending sys_rt_sigpending
|
||||
128 64 rt_sigtimedwait sys_rt_sigtimedwait
|
||||
129 64 rt_sigqueueinfo sys_rt_sigqueueinfo
|
||||
130 common rt_sigsuspend sys_rt_sigsuspend
|
||||
131 64 sigaltstack sys_sigaltstack
|
||||
132 common utime sys_utime
|
||||
133 common mknod sys_mknod
|
||||
134 64 uselib
|
||||
135 common personality sys_personality
|
||||
136 common ustat sys_ustat
|
||||
137 common statfs sys_statfs
|
||||
138 common fstatfs sys_fstatfs
|
||||
139 common sysfs sys_sysfs
|
||||
140 common getpriority sys_getpriority
|
||||
141 common setpriority sys_setpriority
|
||||
142 common sched_setparam sys_sched_setparam
|
||||
143 common sched_getparam sys_sched_getparam
|
||||
144 common sched_setscheduler sys_sched_setscheduler
|
||||
145 common sched_getscheduler sys_sched_getscheduler
|
||||
146 common sched_get_priority_max sys_sched_get_priority_max
|
||||
147 common sched_get_priority_min sys_sched_get_priority_min
|
||||
148 common sched_rr_get_interval sys_sched_rr_get_interval
|
||||
149 common mlock sys_mlock
|
||||
150 common munlock sys_munlock
|
||||
151 common mlockall sys_mlockall
|
||||
152 common munlockall sys_munlockall
|
||||
153 common vhangup sys_vhangup
|
||||
154 common modify_ldt sys_modify_ldt
|
||||
155 common pivot_root sys_pivot_root
|
||||
156 64 _sysctl sys_sysctl
|
||||
157 common prctl sys_prctl
|
||||
158 common arch_prctl sys_arch_prctl
|
||||
159 common adjtimex sys_adjtimex
|
||||
160 common setrlimit sys_setrlimit
|
||||
161 common chroot sys_chroot
|
||||
162 common sync sys_sync
|
||||
163 common acct sys_acct
|
||||
164 common settimeofday sys_settimeofday
|
||||
165 common mount sys_mount
|
||||
166 common umount2 sys_umount
|
||||
167 common swapon sys_swapon
|
||||
168 common swapoff sys_swapoff
|
||||
169 common reboot sys_reboot
|
||||
170 common sethostname sys_sethostname
|
||||
171 common setdomainname sys_setdomainname
|
||||
172 common iopl sys_iopl
|
||||
173 common ioperm sys_ioperm
|
||||
174 64 create_module
|
||||
175 common init_module sys_init_module
|
||||
176 common delete_module sys_delete_module
|
||||
177 64 get_kernel_syms
|
||||
178 64 query_module
|
||||
179 common quotactl sys_quotactl
|
||||
180 64 nfsservctl
|
||||
181 common getpmsg
|
||||
182 common putpmsg
|
||||
183 common afs_syscall
|
||||
184 common tuxcall
|
||||
185 common security
|
||||
186 common gettid sys_gettid
|
||||
187 common readahead sys_readahead
|
||||
188 common setxattr sys_setxattr
|
||||
189 common lsetxattr sys_lsetxattr
|
||||
190 common fsetxattr sys_fsetxattr
|
||||
191 common getxattr sys_getxattr
|
||||
192 common lgetxattr sys_lgetxattr
|
||||
193 common fgetxattr sys_fgetxattr
|
||||
194 common listxattr sys_listxattr
|
||||
195 common llistxattr sys_llistxattr
|
||||
196 common flistxattr sys_flistxattr
|
||||
197 common removexattr sys_removexattr
|
||||
198 common lremovexattr sys_lremovexattr
|
||||
199 common fremovexattr sys_fremovexattr
|
||||
200 common tkill sys_tkill
|
||||
201 common time sys_time
|
||||
202 common futex sys_futex
|
||||
203 common sched_setaffinity sys_sched_setaffinity
|
||||
204 common sched_getaffinity sys_sched_getaffinity
|
||||
205 64 set_thread_area
|
||||
206 64 io_setup sys_io_setup
|
||||
207 common io_destroy sys_io_destroy
|
||||
208 common io_getevents sys_io_getevents
|
||||
209 64 io_submit sys_io_submit
|
||||
210 common io_cancel sys_io_cancel
|
||||
211 64 get_thread_area
|
||||
212 common lookup_dcookie sys_lookup_dcookie
|
||||
213 common epoll_create sys_epoll_create
|
||||
214 64 epoll_ctl_old
|
||||
215 64 epoll_wait_old
|
||||
216 common remap_file_pages sys_remap_file_pages
|
||||
217 common getdents64 sys_getdents64
|
||||
218 common set_tid_address sys_set_tid_address
|
||||
219 common restart_syscall sys_restart_syscall
|
||||
220 common semtimedop sys_semtimedop
|
||||
221 common fadvise64 sys_fadvise64
|
||||
222 64 timer_create sys_timer_create
|
||||
223 common timer_settime sys_timer_settime
|
||||
224 common timer_gettime sys_timer_gettime
|
||||
225 common timer_getoverrun sys_timer_getoverrun
|
||||
226 common timer_delete sys_timer_delete
|
||||
227 common clock_settime sys_clock_settime
|
||||
228 common clock_gettime sys_clock_gettime
|
||||
229 common clock_getres sys_clock_getres
|
||||
230 common clock_nanosleep sys_clock_nanosleep
|
||||
231 common exit_group sys_exit_group
|
||||
232 common epoll_wait sys_epoll_wait
|
||||
233 common epoll_ctl sys_epoll_ctl
|
||||
234 common tgkill sys_tgkill
|
||||
235 common utimes sys_utimes
|
||||
236 64 vserver
|
||||
237 common mbind sys_mbind
|
||||
238 common set_mempolicy sys_set_mempolicy
|
||||
239 common get_mempolicy sys_get_mempolicy
|
||||
240 common mq_open sys_mq_open
|
||||
241 common mq_unlink sys_mq_unlink
|
||||
242 common mq_timedsend sys_mq_timedsend
|
||||
243 common mq_timedreceive sys_mq_timedreceive
|
||||
244 64 mq_notify sys_mq_notify
|
||||
245 common mq_getsetattr sys_mq_getsetattr
|
||||
246 64 kexec_load sys_kexec_load
|
||||
247 64 waitid sys_waitid
|
||||
248 common add_key sys_add_key
|
||||
249 common request_key sys_request_key
|
||||
250 common keyctl sys_keyctl
|
||||
251 common ioprio_set sys_ioprio_set
|
||||
252 common ioprio_get sys_ioprio_get
|
||||
253 common inotify_init sys_inotify_init
|
||||
254 common inotify_add_watch sys_inotify_add_watch
|
||||
255 common inotify_rm_watch sys_inotify_rm_watch
|
||||
256 common migrate_pages sys_migrate_pages
|
||||
257 common openat sys_openat
|
||||
258 common mkdirat sys_mkdirat
|
||||
259 common mknodat sys_mknodat
|
||||
260 common fchownat sys_fchownat
|
||||
261 common futimesat sys_futimesat
|
||||
262 common newfstatat sys_newfstatat
|
||||
263 common unlinkat sys_unlinkat
|
||||
264 common renameat sys_renameat
|
||||
265 common linkat sys_linkat
|
||||
266 common symlinkat sys_symlinkat
|
||||
267 common readlinkat sys_readlinkat
|
||||
268 common fchmodat sys_fchmodat
|
||||
269 common faccessat sys_faccessat
|
||||
270 common pselect6 sys_pselect6
|
||||
271 common ppoll sys_ppoll
|
||||
272 common unshare sys_unshare
|
||||
273 64 set_robust_list sys_set_robust_list
|
||||
274 64 get_robust_list sys_get_robust_list
|
||||
275 common splice sys_splice
|
||||
276 common tee sys_tee
|
||||
277 common sync_file_range sys_sync_file_range
|
||||
278 64 vmsplice sys_vmsplice
|
||||
279 64 move_pages sys_move_pages
|
||||
280 common utimensat sys_utimensat
|
||||
281 common epoll_pwait sys_epoll_pwait
|
||||
282 common signalfd sys_signalfd
|
||||
283 common timerfd_create sys_timerfd_create
|
||||
284 common eventfd sys_eventfd
|
||||
285 common fallocate sys_fallocate
|
||||
286 common timerfd_settime sys_timerfd_settime
|
||||
287 common timerfd_gettime sys_timerfd_gettime
|
||||
288 common accept4 sys_accept4
|
||||
289 common signalfd4 sys_signalfd4
|
||||
290 common eventfd2 sys_eventfd2
|
||||
291 common epoll_create1 sys_epoll_create1
|
||||
292 common dup3 sys_dup3
|
||||
293 common pipe2 sys_pipe2
|
||||
294 common inotify_init1 sys_inotify_init1
|
||||
295 64 preadv sys_preadv
|
||||
296 64 pwritev sys_pwritev
|
||||
297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
|
||||
298 common perf_event_open sys_perf_event_open
|
||||
299 64 recvmmsg sys_recvmmsg
|
||||
300 common fanotify_init sys_fanotify_init
|
||||
301 common fanotify_mark sys_fanotify_mark
|
||||
302 common prlimit64 sys_prlimit64
|
||||
303 common name_to_handle_at sys_name_to_handle_at
|
||||
304 common open_by_handle_at sys_open_by_handle_at
|
||||
305 common clock_adjtime sys_clock_adjtime
|
||||
306 common syncfs sys_syncfs
|
||||
307 64 sendmmsg sys_sendmmsg
|
||||
308 common setns sys_setns
|
||||
309 common getcpu sys_getcpu
|
||||
310 64 process_vm_readv sys_process_vm_readv
|
||||
311 64 process_vm_writev sys_process_vm_writev
|
||||
312 common kcmp sys_kcmp
|
||||
313 common finit_module sys_finit_module
|
||||
314 common sched_setattr sys_sched_setattr
|
||||
315 common sched_getattr sys_sched_getattr
|
||||
316 common renameat2 sys_renameat2
|
||||
317 common seccomp sys_seccomp
|
||||
318 common getrandom sys_getrandom
|
||||
319 common memfd_create sys_memfd_create
|
||||
320 common kexec_file_load sys_kexec_file_load
|
||||
321 common bpf sys_bpf
|
||||
322 64 execveat sys_execveat
|
||||
|
||||
#
|
||||
# x32-specific system call numbers start at 512 to avoid cache impact
|
||||
# for native 64-bit operation.
|
||||
#
|
||||
512 x32 rt_sigaction compat_sys_rt_sigaction
|
||||
513 x32 rt_sigreturn sys_x32_rt_sigreturn
|
||||
514 x32 ioctl compat_sys_ioctl
|
||||
515 x32 readv compat_sys_readv
|
||||
516 x32 writev compat_sys_writev
|
||||
517 x32 recvfrom compat_sys_recvfrom
|
||||
518 x32 sendmsg compat_sys_sendmsg
|
||||
519 x32 recvmsg compat_sys_recvmsg
|
||||
520 x32 execve sys_x32_execve
|
||||
521 x32 ptrace compat_sys_ptrace
|
||||
522 x32 rt_sigpending compat_sys_rt_sigpending
|
||||
523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
|
||||
524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo
|
||||
525 x32 sigaltstack compat_sys_sigaltstack
|
||||
526 x32 timer_create compat_sys_timer_create
|
||||
527 x32 mq_notify compat_sys_mq_notify
|
||||
528 x32 kexec_load compat_sys_kexec_load
|
||||
529 x32 waitid compat_sys_waitid
|
||||
530 x32 set_robust_list compat_sys_set_robust_list
|
||||
531 x32 get_robust_list compat_sys_get_robust_list
|
||||
532 x32 vmsplice compat_sys_vmsplice
|
||||
533 x32 move_pages compat_sys_move_pages
|
||||
534 x32 preadv compat_sys_preadv64
|
||||
535 x32 pwritev compat_sys_pwritev64
|
||||
536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
|
||||
537 x32 recvmmsg compat_sys_recvmmsg
|
||||
538 x32 sendmmsg compat_sys_sendmmsg
|
||||
539 x32 process_vm_readv compat_sys_process_vm_readv
|
||||
540 x32 process_vm_writev compat_sys_process_vm_writev
|
||||
541 x32 setsockopt compat_sys_setsockopt
|
||||
542 x32 getsockopt compat_sys_getsockopt
|
||||
543 x32 io_setup compat_sys_io_setup
|
||||
544 x32 io_submit compat_sys_io_submit
|
||||
545 x32 execveat sys_x32_execveat
|
37485
x86/support/make_linux_syscalls/syscalls.h.cpp
Normal file
37485
x86/support/make_linux_syscalls/syscalls.h.cpp
Normal file
File diff suppressed because one or more lines are too long
105
x86/tests/ElfX64Linux.hs
Normal file
105
x86/tests/ElfX64Linux.hs
Normal file
@ -0,0 +1,105 @@
|
||||
{-# LANGUAGE DeriveDataTypeable #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
module ElfX64Linux (
|
||||
elfX64LinuxTests
|
||||
) where
|
||||
|
||||
import Control.Lens ( (^.) )
|
||||
import qualified Control.Monad.Catch as C
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.Foldable as F
|
||||
import qualified Data.Map as M
|
||||
import qualified Data.Set as S
|
||||
import Data.Typeable ( Typeable )
|
||||
import Data.Word ( Word64 )
|
||||
import System.FilePath ( dropExtension, replaceExtension )
|
||||
import qualified Test.Tasty as T
|
||||
import qualified Test.Tasty.HUnit as T
|
||||
import Text.Printf ( printf )
|
||||
import Text.Read ( readMaybe )
|
||||
|
||||
import qualified Data.ElfEdit as E
|
||||
|
||||
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
|
||||
elfX64LinuxTests = T.testGroup "ELF x64 Linux" . map mkTest
|
||||
|
||||
-- | The type of expected results for test cases
|
||||
data ExpectedResult =
|
||||
R { funcs :: [(Word64, [Word64])]
|
||||
-- ^ 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).
|
||||
, ignoreBlocks :: [Word64]
|
||||
-- ^ This is a list of discovered blocks to ignore. This is
|
||||
-- basically just the address of the instruction after the exit
|
||||
-- syscall, as macaw doesn't know that exit never returns and
|
||||
-- discovers a false block after exit.
|
||||
}
|
||||
deriving (Read, Show, Eq)
|
||||
|
||||
mkTest :: FilePath -> T.TestTree
|
||||
mkTest fp = T.testCase fp $ withELF exeFilename (testDiscovery fp)
|
||||
where
|
||||
asmFilename = dropExtension fp
|
||||
exeFilename = replaceExtension asmFilename "exe"
|
||||
|
||||
-- | Run a test over a given expected result filename and the ELF file
|
||||
-- associated with it
|
||||
testDiscovery :: FilePath -> E.Elf 64 -> IO ()
|
||||
testDiscovery expectedFilename elf =
|
||||
withMemory MM.Addr64 elf $ \mem -> do
|
||||
let Just entryPoint = MM.absoluteAddrSegment mem (fromIntegral (E.elfEntry elf))
|
||||
di = MD.cfgFromAddrs RO.x86_64_linux_info mem MD.emptySymbolAddrMap [entryPoint] []
|
||||
expectedString <- readFile expectedFilename
|
||||
case readMaybe expectedString of
|
||||
Nothing -> T.assertFailure ("Invalid expected result: " ++ show expectedString)
|
||||
Just er -> do
|
||||
let expectedEntries = M.fromList [ (entry, S.fromList starts) | (entry, starts) <- funcs er ]
|
||||
ignoredBlocks = S.fromList (ignoreBlocks er)
|
||||
F.forM_ (M.elems (di ^. MD.funInfo)) $ \(PU.Some dfi) -> do
|
||||
let actualEntry = fromIntegral (MM.addrValue (MD.discoveredFunAddr dfi))
|
||||
actualBlockStarts = S.fromList [ fromIntegral (MM.addrValue (MD.blockAddr pbr))
|
||||
| pbr <- M.elems (dfi ^. MD.parsedBlocks)
|
||||
]
|
||||
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)
|
||||
|
||||
withELF :: FilePath -> (E.Elf 64 -> IO ()) -> IO ()
|
||||
withELF fp k = do
|
||||
bytes <- B.readFile fp
|
||||
case E.parseElf bytes of
|
||||
E.ElfHeaderError off msg ->
|
||||
error ("Error parsing ELF header at offset " ++ show off ++ ": " ++ msg)
|
||||
E.Elf32Res [] _e32 -> error "ELF32 is unsupported in the test suite"
|
||||
E.Elf64Res [] e64 -> k e64
|
||||
E.Elf32Res errs _ -> error ("Errors while parsing ELF file: " ++ show errs)
|
||||
E.Elf64Res errs _ -> error ("Errors while parsing ELF file: " ++ show errs)
|
||||
|
||||
withMemory :: forall w m a
|
||||
. (C.MonadThrow m, MM.MemWidth w, Integral (E.ElfWordType w))
|
||||
=> MM.AddrWidthRepr w
|
||||
-> E.Elf w
|
||||
-> (MM.Memory w -> m a)
|
||||
-> m a
|
||||
withMemory relaWidth e k =
|
||||
case MM.memoryForElf (MM.LoadOptions MM.LoadBySegment False) e of
|
||||
-- case MM.memoryForElfSegments relaWidth e of
|
||||
Left err -> C.throwM (MemoryLoadError err)
|
||||
Right (_sim, mem) -> k mem
|
||||
|
||||
data ElfException = MemoryLoadError String
|
||||
deriving (Typeable, Show)
|
||||
|
||||
instance C.Exception ElfException
|
14
x86/tests/Main.hs
Normal file
14
x86/tests/Main.hs
Normal file
@ -0,0 +1,14 @@
|
||||
module Main ( main ) where
|
||||
|
||||
import System.FilePath.Glob ( namesMatching )
|
||||
import qualified Test.Tasty as T
|
||||
|
||||
import qualified ElfX64Linux as T
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
x64AsmTests <- namesMatching "tests/x64/*.s.expected"
|
||||
T.defaultMain $ T.testGroup "ReoptTests" [
|
||||
T.elfX64LinuxTests x64AsmTests
|
||||
]
|
||||
|
27
x86/tests/README.rst
Normal file
27
x86/tests/README.rst
Normal file
@ -0,0 +1,27 @@
|
||||
This directory contains some automated tests for macaw-x86_.
|
||||
The macaw tests currently live in this repository because this is
|
||||
where our x86_64 semantics are defined. Separating those semantics
|
||||
out is difficult at this point. The tests currently cover the code
|
||||
discovery implementation in macaw. Specifically, they check:
|
||||
|
||||
1) That the correct number of functions are found,
|
||||
2) Each function starts at the expected address,
|
||||
3) Each function contains the correct number of basic blocks,
|
||||
4) Each basic block starts at the expected address
|
||||
|
||||
The ``Makefile`` in the tests directory rebuilds the test files from
|
||||
source. The resulting binaries are checked in to the repository so
|
||||
that Mac OS users can run the tests without having to have a Linux
|
||||
build toolchain available. Additionally, having the binaries in the
|
||||
repository keeps the code layout stable. Expected addresses are
|
||||
hard-coded into the expected results of the test suite; regenerating
|
||||
the binaries on a different system or with a different compiler could
|
||||
change the offsets in the test binaries, which would require the
|
||||
expected results to be tweaked. This is unfortunate, but difficult to
|
||||
avoid in a robust way.
|
||||
|
||||
Note that the tests are bare-bones and do not link against libc. They
|
||||
issue the exit system call directly to terminate. This lets us get
|
||||
small and comprehensible test cases.
|
||||
|
||||
.. _macaw-86: https://gitlab-ext.galois.com/macaw/macaw-x86
|
20
x86/tests/x64/Makefile
Normal file
20
x86/tests/x64/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
all: $(patsubst %c,%exe, $(wildcard *.c))
|
||||
|
||||
# We have a special rule for the tail call test case because we need
|
||||
# -O2 to convince gcc to emit a tail call, but we'd rather not have
|
||||
# that much aggressive optimization for the other tests because it
|
||||
# usually makes them trivial.
|
||||
test-tail-call.exe: test-tail-call.c
|
||||
gcc -fno-stack-protector -O2 -fno-inline -S -c $< -o test-tail-call.s
|
||||
gcc -fno-stack-protector -O2 -fno-inline -nostdlib $< -o $@
|
||||
|
||||
%.exe: %.s
|
||||
gcc -fno-stack-protector -nostdlib $< -o $@
|
||||
|
||||
%.s: %.c
|
||||
gcc -fno-stack-protector -foptimize-sibling-calls -S -c $< -o $@
|
||||
|
||||
.PRECIOUS: %.s
|
||||
|
||||
clean:
|
||||
rm *.s *.exe
|
11
x86/tests/x64/test-conditional.c
Normal file
11
x86/tests/x64/test-conditional.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "util.h"
|
||||
|
||||
int g = -11;
|
||||
|
||||
void _start() {
|
||||
if(g > 0) {
|
||||
g = g + 1;
|
||||
}
|
||||
|
||||
EXIT();
|
||||
}
|
BIN
x86/tests/x64/test-conditional.exe
Executable file
BIN
x86/tests/x64/test-conditional.exe
Executable file
Binary file not shown.
42
x86/tests/x64/test-conditional.s
Normal file
42
x86/tests/x64/test-conditional.s
Normal file
@ -0,0 +1,42 @@
|
||||
.file "test2.c"
|
||||
.globl g
|
||||
.data
|
||||
.align 4
|
||||
.type g, @object
|
||||
.size g, 4
|
||||
g:
|
||||
.long -11
|
||||
.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
|
||||
movl g(%rip), %eax
|
||||
testl %eax, %eax
|
||||
jle .L2
|
||||
movl g(%rip), %eax
|
||||
addl $1, %eax
|
||||
movl %eax, g(%rip)
|
||||
.L2:
|
||||
#APP
|
||||
# 10 "test2.c" 1
|
||||
movq $60,%rax
|
||||
movq $0,%rdi
|
||||
syscall
|
||||
# 0 "" 2
|
||||
#NO_APP
|
||||
nop
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size _start, .-_start
|
||||
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
|
||||
.section .note.GNU-stack,"",@progbits
|
3
x86/tests/x64/test-conditional.s.expected
Normal file
3
x86/tests/x64/test-conditional.s.expected
Normal file
@ -0,0 +1,3 @@
|
||||
R { funcs = [(0x2b1, [0x2b1, 0x2ce, 0x2bf])]
|
||||
, ignoreBlocks = [0x2de]
|
||||
}
|
27
x86/tests/x64/test-direct-calls.c
Normal file
27
x86/tests/x64/test-direct-calls.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "util.h"
|
||||
|
||||
int g1;
|
||||
int g2;
|
||||
int g3;
|
||||
int g4;
|
||||
|
||||
int f2() {
|
||||
return (int)&g2;
|
||||
}
|
||||
|
||||
int f1(long l1, long l2, long l3) {
|
||||
long i1 = (long)&g1;
|
||||
i1 = l1 + i1 + l2 + l3;
|
||||
i1 += l3 * 2;
|
||||
i1 = i1 / (l2 - 100 + f2());
|
||||
return (int)i1;
|
||||
}
|
||||
|
||||
void _start() {
|
||||
long i1 = (long)&g1;
|
||||
long i2 = (long)&g2;
|
||||
long i3 = (long)&g3;
|
||||
g1 = f1(i1, i2, i3);
|
||||
EXIT();
|
||||
}
|
||||
|
BIN
x86/tests/x64/test-direct-calls.exe
Executable file
BIN
x86/tests/x64/test-direct-calls.exe
Executable file
Binary file not shown.
111
x86/tests/x64/test-direct-calls.s
Normal file
111
x86/tests/x64/test-direct-calls.s
Normal file
@ -0,0 +1,111 @@
|
||||
.file "shadow.c"
|
||||
.comm g1,4,4
|
||||
.comm g2,4,4
|
||||
.comm g3,4,4
|
||||
.comm g4,4,4
|
||||
.text
|
||||
.globl f2
|
||||
.type f2, @function
|
||||
f2:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
leaq g2(%rip), %rax
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size f2, .-f2
|
||||
.globl f1
|
||||
.type f1, @function
|
||||
f1:
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
pushq %rbx
|
||||
subq $40, %rsp
|
||||
.cfi_offset 3, -24
|
||||
movq %rdi, -32(%rbp)
|
||||
movq %rsi, -40(%rbp)
|
||||
movq %rdx, -48(%rbp)
|
||||
leaq g1(%rip), %rax
|
||||
movq %rax, -16(%rbp)
|
||||
movq -32(%rbp), %rdx
|
||||
movq -16(%rbp), %rax
|
||||
addq %rax, %rdx
|
||||
movq -40(%rbp), %rax
|
||||
addq %rax, %rdx
|
||||
movq -48(%rbp), %rax
|
||||
addq %rdx, %rax
|
||||
movq %rax, -16(%rbp)
|
||||
movq -48(%rbp), %rax
|
||||
addq %rax, %rax
|
||||
addq %rax, -16(%rbp)
|
||||
movq -40(%rbp), %rax
|
||||
leaq -100(%rax), %rbx
|
||||
movl $0, %eax
|
||||
call f2
|
||||
cltq
|
||||
leaq (%rbx,%rax), %rcx
|
||||
movq -16(%rbp), %rax
|
||||
cqto
|
||||
idivq %rcx
|
||||
movq %rax, -16(%rbp)
|
||||
movq -16(%rbp), %rax
|
||||
addq $40, %rsp
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE1:
|
||||
.size f1, .-f1
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
.LFB2:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
subq $32, %rsp
|
||||
leaq g1(%rip), %rax
|
||||
movq %rax, -8(%rbp)
|
||||
leaq g2(%rip), %rax
|
||||
movq %rax, -16(%rbp)
|
||||
leaq g3(%rip), %rax
|
||||
movq %rax, -24(%rbp)
|
||||
movq -24(%rbp), %rdx
|
||||
movq -16(%rbp), %rcx
|
||||
movq -8(%rbp), %rax
|
||||
movq %rcx, %rsi
|
||||
movq %rax, %rdi
|
||||
call f1
|
||||
movl %eax, g1(%rip)
|
||||
#APP
|
||||
# 25 "shadow.c" 1
|
||||
movq $60,%rax
|
||||
movq $0,%rdi
|
||||
syscall
|
||||
# 0 "" 2
|
||||
#NO_APP
|
||||
nop
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE2:
|
||||
.size _start, .-_start
|
||||
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
|
||||
.section .note.GNU-stack,"",@progbits
|
6
x86/tests/x64/test-direct-calls.s.expected
Normal file
6
x86/tests/x64/test-direct-calls.s.expected
Normal file
@ -0,0 +1,6 @@
|
||||
R { funcs = [ (0x336, [0x336, 0x376])
|
||||
, (0x2be, [0x2be, 0x318])
|
||||
, (0x2b1, [0x2b1])
|
||||
]
|
||||
, ignoreBlocks = [0x38c]
|
||||
}
|
16
x86/tests/x64/test-indirect-call.c
Normal file
16
x86/tests/x64/test-indirect-call.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "util.h"
|
||||
|
||||
int g = -11;
|
||||
|
||||
int (*fptr)(int);
|
||||
|
||||
int callee(int x) {
|
||||
return x * 2;
|
||||
}
|
||||
|
||||
void _start() {
|
||||
fptr = callee;
|
||||
g = fptr(g);
|
||||
|
||||
EXIT();
|
||||
}
|
BIN
x86/tests/x64/test-indirect-call.exe
Executable file
BIN
x86/tests/x64/test-indirect-call.exe
Executable file
Binary file not shown.
62
x86/tests/x64/test-indirect-call.s
Normal file
62
x86/tests/x64/test-indirect-call.s
Normal file
@ -0,0 +1,62 @@
|
||||
.file "test-indirect-call.c"
|
||||
.globl g
|
||||
.data
|
||||
.align 4
|
||||
.type g, @object
|
||||
.size g, 4
|
||||
g:
|
||||
.long -11
|
||||
.comm fptr,8,8
|
||||
.text
|
||||
.globl callee
|
||||
.type callee, @function
|
||||
callee:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
movl %edi, -4(%rbp)
|
||||
movl -4(%rbp), %eax
|
||||
addl %eax, %eax
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size callee, .-callee
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
leaq callee(%rip), %rax
|
||||
movq %rax, fptr(%rip)
|
||||
movq fptr(%rip), %rax
|
||||
movl g(%rip), %edx
|
||||
movl %edx, %edi
|
||||
call *%rax
|
||||
movl %eax, g(%rip)
|
||||
#APP
|
||||
# 15 "test-indirect-call.c" 1
|
||||
movq $60,%rax
|
||||
movq $0,%rdi
|
||||
syscall
|
||||
# 0 "" 2
|
||||
#NO_APP
|
||||
nop
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE1:
|
||||
.size _start, .-_start
|
||||
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
|
||||
.section .note.GNU-stack,"",@progbits
|
5
x86/tests/x64/test-indirect-call.s.expected
Normal file
5
x86/tests/x64/test-indirect-call.s.expected
Normal file
@ -0,0 +1,5 @@
|
||||
R { funcs = [ (0x2b1, [0x2b1])
|
||||
, (0x2bf, [0x2bf, 0x2e2])
|
||||
]
|
||||
, ignoreBlocks = [0x2f8]
|
||||
}
|
5
x86/tests/x64/test-just-exit.c
Normal file
5
x86/tests/x64/test-just-exit.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "util.h"
|
||||
|
||||
void _start() {
|
||||
EXIT();
|
||||
}
|
BIN
x86/tests/x64/test-just-exit.exe
Executable file
BIN
x86/tests/x64/test-just-exit.exe
Executable file
Binary file not shown.
28
x86/tests/x64/test-just-exit.s
Normal file
28
x86/tests/x64/test-just-exit.s
Normal file
@ -0,0 +1,28 @@
|
||||
.file "test1.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
|
||||
#APP
|
||||
# 4 "test1.c" 1
|
||||
movq $60,%rax
|
||||
movq $0,%rdi
|
||||
syscall
|
||||
# 0 "" 2
|
||||
#NO_APP
|
||||
nop
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size _start, .-_start
|
||||
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
|
||||
.section .note.GNU-stack,"",@progbits
|
3
x86/tests/x64/test-just-exit.s.expected
Normal file
3
x86/tests/x64/test-just-exit.s.expected
Normal file
@ -0,0 +1,3 @@
|
||||
R { funcs = [(0x2b1, [0x2b1])]
|
||||
, ignoreBlocks = [0x2c5]
|
||||
}
|
29
x86/tests/x64/test-tail-call.c
Normal file
29
x86/tests/x64/test-tail-call.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
|
||||
This test case makes sure that macaw can find functions only
|
||||
reachable via tail call.
|
||||
|
||||
callee1 issues a tail call to callee2. Note that macaw identifies
|
||||
callee2 as a function, but also includes its body as a block in
|
||||
callee1 (so that block appears in two function definitions). That
|
||||
seems fine.
|
||||
|
||||
*/
|
||||
#include "util.h"
|
||||
|
||||
int g = -11;
|
||||
|
||||
void callee2(int x) {
|
||||
g += x;
|
||||
}
|
||||
|
||||
void callee1(int x) {
|
||||
g += x * 2;
|
||||
callee2(x);
|
||||
}
|
||||
|
||||
void _start() {
|
||||
callee1(g);
|
||||
|
||||
EXIT();
|
||||
}
|
BIN
x86/tests/x64/test-tail-call.exe
Executable file
BIN
x86/tests/x64/test-tail-call.exe
Executable file
Binary file not shown.
53
x86/tests/x64/test-tail-call.s
Normal file
53
x86/tests/x64/test-tail-call.s
Normal file
@ -0,0 +1,53 @@
|
||||
.file "test-tail-call.c"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
.globl callee2
|
||||
.type callee2, @function
|
||||
callee2:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
addl %edi, g(%rip)
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size callee2, .-callee2
|
||||
.p2align 4,,15
|
||||
.globl callee1
|
||||
.type callee1, @function
|
||||
callee1:
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
leal (%rdi,%rdi), %eax
|
||||
addl %eax, g(%rip)
|
||||
jmp callee2
|
||||
.cfi_endproc
|
||||
.LFE1:
|
||||
.size callee1, .-callee1
|
||||
.p2align 4,,15
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
.LFB2:
|
||||
.cfi_startproc
|
||||
movl g(%rip), %edi
|
||||
call callee1
|
||||
#APP
|
||||
# 18 "test-tail-call.c" 1
|
||||
movq $60,%rax
|
||||
movq $0,%rdi
|
||||
syscall
|
||||
# 0 "" 2
|
||||
#NO_APP
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE2:
|
||||
.size _start, .-_start
|
||||
.globl g
|
||||
.data
|
||||
.align 4
|
||||
.type g, @object
|
||||
.size g, 4
|
||||
g:
|
||||
.long -11
|
||||
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
|
||||
.section .note.GNU-stack,"",@progbits
|
6
x86/tests/x64/test-tail-call.s.expected
Normal file
6
x86/tests/x64/test-tail-call.s.expected
Normal file
@ -0,0 +1,6 @@
|
||||
R { funcs = [ (0x2c0, [0x2c0])
|
||||
, (0x2d0, [0x2d0, 0x2c0])
|
||||
, (0x2e0, [0x2e0, 0x2eb])
|
||||
]
|
||||
, ignoreBlocks = [0x2fb]
|
||||
}
|
4
x86/tests/x64/util.h
Normal file
4
x86/tests/x64/util.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define EXIT() \
|
||||
asm("movq $60,%rax\n" \
|
||||
"movq $0,%rdi\n" \
|
||||
"syscall")
|
Loading…
Reference in New Issue
Block a user