module Data.Elf
(
FileClass(..)
, invalidFileClass
, elf32FileClass
, elf64FileClass
, IsFileClass(..)
, Elf32(..)
, anElf32
, Elf64(..)
, anElf64
, FileType(..)
, noneFileType
, relFileType
, execFileType
, dynFileType
, coreFileType
, loOsFileType
, hiOsFileType
, loProcFileType
, hiProcFileType
, Machine(..)
, undefMachine
, i386Machine
, amd64Machine
, MachFlags(..)
, Version(..)
, invalidVersion
, firstVersion
, DataEnc(..)
, invalidDataEnc
, lsbDataEnc
, msbDataEnc
, OsAbi(..)
, sysvOsAbi
, hpuxOsAbi
, netBsdOsAbi
, gnuOsAbi
, solarisOsAbi
, aixOsAbi
, irixOsAbi
, freeBsdOsAbi
, tru64OsAbi
, modestoOsAbi
, openBsdOsAbi
, openVmsOsAbi
, nskOsAbi
, arosOsAbi
, fenixOsAbi
, embedOsAbi
, AbiVer(..)
, undefAbiVer
, Ident(..)
, anIdent
, FileHdr(..)
, FileHdr32
, aFileHdr32
, FileHdr64
, aFileHdr64
, SegType(..)
, unusedSegType
, loadSegType
, dynSegType
, interpSegType
, noteSegType
, shlibSegType
, phdrSegType
, loOsSegType
, hiOsSegType
, loProcSegType
, hiProcSegType
, SegFlags(..)
, execSegFlag
, writeSegFlag
, readSegFlag
, osSegFlags
, procSegFlags
, ProgHdr(..)
, ProgHdr32
, aProgHdr32
, ProgHdr64
, aProgHdr64
, StrIx
, SecIx(..)
, undefSecIx
, lastSecIx
, loOsSecIx
, hiOsSecIx
, loProcSecIx
, hiProcSecIx
, absSecIx
, commonSecIx
, xIndexSecIx
, SecType(..)
, unusedSecType
, progBitsSecType
, symSecType
, strSecType
, relaSecType
, hashSecType
, dynSecType
, noteSecType
, noBitsSecType
, relSecType
, shlibSecType
, dynSymSecType
, loOsSecType
, hiOsSecType
, loProcSecType
, hiProcSecType
, SecFlags(..)
, writeSecFlag
, allocSecFlag
, execSecFlag
, mergeSecFlag
, infoLinkSecFlag
, osSecFlags
, procSecFlags
, SecHdr(..)
, SecHdr32
, aSecHdr32
, SecHdr64
, aSecHdr64
, zeroSecHdr
, SymType(..)
, undefSymType
, objSymType
, funSymType
, secSymType
, fileSymType
, commonSymType
, tlsSymType
, loOsSymType
, hiOsSymType
, loProcSymType
, hiProcSymType
, SymBind(..)
, localSymBind
, globalSymBind
, weakSymBind
, loOsSymBind
, hiOsSymBind
, loProcSymBind
, hiProcSymBind
, SymVisi(..)
, defSymVisi
, intSymVisi
, hiddenSymVisi
, protSymVisi
, exportSymVisi
, singSymVisi
, elimSymVisi
, SymIx(..)
, undefSymIx
, SymEnt(..)
, SymEnt32
, aSymEnt32
, SymEnt64
, aSymEnt64
, zeroSymEnt
, RelType(..)
, RelType32
, RelType64
, RelEnt(..)
, RelEnt32
, aRelEnt32
, RelEnt64
, aRelEnt64
, RelaEnt(..)
, RelaEnt32
, aRelaEnt32
, RelaEnt64
, aRelaEnt64
) where
import Data.Typeable (Typeable)
import Data.Data (Data)
import Data.Proxy (Proxy(..))
import Data.Ix (Ix)
import Data.Bits (Bits, shiftL, shiftR, (.|.), FiniteBits)
import Data.Flags (Flags(noFlags), BoundedFlags)
import Data.Word (Word8, Word16, Word32, Word64)
import Data.ShortWord (Word4, Word24)
import Data.Monoid ((<>))
import Data.Serializer (Serializable, SizedSerializable)
import qualified Data.Serializer as S
import Data.Deserializer (Deserializable, (<?>))
import qualified Data.Deserializer as D
import Control.Applicative ((<$>))
import Control.Monad (void, unless)
newtype FileClass = FileClass { unFileClass ∷ Word8 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
invalidFileClass ∷ FileClass
invalidFileClass = FileClass 0
elf32FileClass ∷ FileClass
elf32FileClass = FileClass 1
elf64FileClass ∷ FileClass
elf64FileClass = FileClass 2
class (Typeable c,
Typeable (Addr c), Data (Addr c),
Typeable (Off c), Data (Off c),
Typeable (UnSymIx c), Data (UnSymIx c),
Typeable (UnRelType c), Data (UnRelType c),
Show (Addr c), Read (Addr c),
Show (Off c), Read (Off c),
Show (UnSymIx c), Read (UnSymIx c),
Show (UnRelType c), Read (UnRelType c),
Eq (Addr c), Ord (Addr c), Bounded (Addr c), Enum (Addr c),
Num (Addr c), Integral (Addr c), Real (Addr c),
Bits (Addr c), FiniteBits (Addr c),
Eq (Off c), Ord (Off c), Bounded (Off c), Enum (Off c),
Num (Off c), Integral (Off c), Real (Off c),
Bits (Off c), FiniteBits (Off c),
Eq (UnSymIx c), Ord (UnSymIx c), Bounded (UnSymIx c), Enum (UnSymIx c),
Ix (UnSymIx c), Num (UnSymIx c), Integral (UnSymIx c),
Real (UnSymIx c), Bits (UnSymIx c), FiniteBits (UnSymIx c),
Eq (UnRelType c), Ord (UnRelType c), Bounded (UnRelType c),
Enum (UnRelType c), Ix (UnRelType c))
⇒ IsFileClass c where
type Addr c
type Off c
type UnSymIx c
type UnRelType c
fileClass ∷ Proxy c → FileClass
data Elf32 = Elf32 deriving (Typeable, Data)
anElf32 ∷ Proxy Elf32
anElf32 = Proxy
instance IsFileClass Elf32 where
type Addr Elf32 = Word32
type Off Elf32 = Word32
type UnSymIx Elf32 = Word24
type UnRelType Elf32 = Word8
fileClass _ = elf32FileClass
data Elf64 = Elf64 deriving (Typeable, Data)
anElf64 ∷ Proxy Elf64
anElf64 = Proxy
instance IsFileClass Elf64 where
type Addr Elf64 = Word64
type Off Elf64 = Word64
type UnSymIx Elf64 = Word32
type UnRelType Elf64 = Word32
fileClass _ = elf64FileClass
newtype FileType = FileType { unFileType ∷ Word16 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
noneFileType ∷ FileType
noneFileType = FileType 0
relFileType ∷ FileType
relFileType = FileType 1
execFileType ∷ FileType
execFileType = FileType 2
dynFileType ∷ FileType
dynFileType = FileType 3
coreFileType ∷ FileType
coreFileType = FileType 4
loOsFileType ∷ FileType
loOsFileType = FileType 0xFE00
hiOsFileType ∷ FileType
hiOsFileType = FileType 0xFEFF
loProcFileType ∷ FileType
loProcFileType = FileType 0xFF00
hiProcFileType ∷ FileType
hiProcFileType = FileType 0xFFFF
newtype Machine = Machine { unMachine ∷ Word16 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
undefMachine ∷ Machine
undefMachine = Machine 0
i386Machine ∷ Machine
i386Machine = Machine 3
amd64Machine ∷ Machine
amd64Machine = Machine 62
newtype MachFlags = MachFlags { unMachFlags ∷ Word32 }
deriving (Typeable, Data, Show, Read,
Eq, Flags, BoundedFlags)
newtype Version = Version { unVersion ∷ Word8 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
invalidVersion ∷ Version
invalidVersion = Version 0
firstVersion ∷ Version
firstVersion = Version 1
newtype DataEnc = DataEnc { unDataEnc ∷ Word8 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
invalidDataEnc ∷ DataEnc
invalidDataEnc = DataEnc 0
lsbDataEnc ∷ DataEnc
lsbDataEnc = DataEnc 1
msbDataEnc ∷ DataEnc
msbDataEnc = DataEnc 2
newtype OsAbi = OsAbi { unOsAbi ∷ Word8 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
sysvOsAbi ∷ OsAbi
sysvOsAbi = OsAbi 0
hpuxOsAbi ∷ OsAbi
hpuxOsAbi = OsAbi 1
netBsdOsAbi ∷ OsAbi
netBsdOsAbi = OsAbi 2
gnuOsAbi ∷ OsAbi
gnuOsAbi = OsAbi 3
solarisOsAbi ∷ OsAbi
solarisOsAbi = OsAbi 6
aixOsAbi ∷ OsAbi
aixOsAbi = OsAbi 7
irixOsAbi ∷ OsAbi
irixOsAbi = OsAbi 8
freeBsdOsAbi ∷ OsAbi
freeBsdOsAbi = OsAbi 9
tru64OsAbi ∷ OsAbi
tru64OsAbi = OsAbi 10
modestoOsAbi ∷ OsAbi
modestoOsAbi = OsAbi 11
openBsdOsAbi ∷ OsAbi
openBsdOsAbi = OsAbi 12
openVmsOsAbi ∷ OsAbi
openVmsOsAbi = OsAbi 13
nskOsAbi ∷ OsAbi
nskOsAbi = OsAbi 14
arosOsAbi ∷ OsAbi
arosOsAbi = OsAbi 15
fenixOsAbi ∷ OsAbi
fenixOsAbi = OsAbi 16
embedOsAbi ∷ OsAbi
embedOsAbi = OsAbi 255
newtype AbiVer = AbiVer { unAbiVer ∷ Word8 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
undefAbiVer ∷ AbiVer
undefAbiVer = AbiVer 0
data Ident = Ident { idClass ∷ FileClass
, idVersion ∷ Version
, idDataEnc ∷ DataEnc
, idOsAbi ∷ OsAbi
, idAbiVer ∷ AbiVer }
deriving (Typeable, Data, Show, Read, Eq)
anIdent ∷ Proxy Ident
anIdent = Proxy
instance Serializable Ident where
put (Ident {..})
= S.byteString "\127ELF"
<> S.word8 (unFileClass idClass)
<> S.word8 (unDataEnc idDataEnc)
<> S.word8 (unVersion idVersion)
<> S.word8 (unOsAbi idOsAbi)
<> S.word8 (unAbiVer idAbiVer)
<> S.byteString "\0\0\0\0\0\0\0"
instance SizedSerializable Ident where
size _ = 16
instance Deserializable Ident where
get = do
void $ D.bytes "\127ELF" <?> "ELF magic number"
fileCls ← FileClass <$> D.word8 <?> "file class"
dataEnc ← DataEnc <$> D.word8 <?> "data encoding"
version ← Version <$> D.word8 <?> "file version"
osAbi ← OsAbi <$> D.word8 <?> "OS ABI code"
abiVer ← AbiVer <$> D.word8 <?> "OS ABI version"
D.skip 7
return $ Ident { idClass = fileCls
, idDataEnc = dataEnc
, idVersion = version
, idOsAbi = osAbi
, idAbiVer = abiVer }
data FileHdr c = FileHdr { fhType ∷ FileType
, fhMachine ∷ Machine
, fhEntry ∷ Addr c
, fhFlags ∷ MachFlags
, fhPhOff ∷ Off c
, fhPhNum ∷ Word16
, fhShOff ∷ Off c
, fhShNum ∷ Word16
, fhSnStIx ∷ SecIx }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (FileHdr c)
deriving instance IsFileClass c ⇒ Show (FileHdr c)
deriving instance IsFileClass c ⇒ Read (FileHdr c)
deriving instance IsFileClass c ⇒ Eq (FileHdr c)
type FileHdr32 = FileHdr Elf32
aFileHdr32 ∷ Proxy FileHdr32
aFileHdr32 = Proxy
instance Serializable FileHdr32 where
put (FileHdr {..})
= S.word16 (unFileType fhType)
<> S.word16 (unMachine fhMachine)
<> S.word32 1
<> S.word32 fhEntry
<> S.word32 fhPhOff
<> S.word32 fhShOff
<> S.word32 (unMachFlags fhFlags)
<> S.word16 (fromIntegral $ S.size anIdent + S.size aFileHdr32)
<> S.word16 (fromIntegral $ S.size aProgHdr32)
<> S.word16 fhPhNum
<> S.word16 (fromIntegral $ S.size aSecHdr32)
<> S.word16 fhShNum
<> S.word16 (unSecIx fhSnStIx)
instance SizedSerializable FileHdr32 where
size _ = 36
instance Deserializable FileHdr32 where
get = do
fileType ← FileType <$> D.word16 <?> "file type"
machine ← Machine <$> D.word16 <?> "machine"
version ← D.word32 <?> "version"
unless (version == 1) $ D.unexpected "Unexpected ELF version"
entry ← D.word32 <?> "entry point address"
phOff ← D.word32 <?> "program header table offset"
shOff ← D.word32 <?> "section header table offset"
flags ← MachFlags <$> D.word32 <?> "machine flags"
fileHdrSize ← D.word16 <?> "file header size"
unless (fileHdrSize ==
fromIntegral (S.size anIdent + S.size aFileHdr32)) $
D.unexpected "Unexpected ELF file header size"
progHdrSize ← D.word16 <?> "program header size"
unless (progHdrSize == fromIntegral (S.size aProgHdr32)) $
D.unexpected "Unexpected ELF program header size"
phNum ← D.word16 <?> "program header table size"
secHdrSize ← D.word16 <?> "section header size"
unless (secHdrSize == fromIntegral (S.size aSecHdr32)) $
D.unexpected "Unexpected ELF section header size"
shNum ← D.word16 <?> "section header table size"
snStIx ← SecIx <$> D.word16 <?> "section name string table section index"
return $ FileHdr { fhType = fileType
, fhMachine = machine
, fhEntry = entry
, fhPhOff = phOff
, fhShOff = shOff
, fhFlags = flags
, fhPhNum = phNum
, fhShNum = shNum
, fhSnStIx = snStIx }
type FileHdr64 = FileHdr Elf64
aFileHdr64 ∷ Proxy FileHdr64
aFileHdr64 = Proxy
instance Serializable FileHdr64 where
put (FileHdr {..})
= S.word16 (unFileType fhType)
<> S.word16 (unMachine fhMachine)
<> S.word32 1
<> S.word64 fhEntry
<> S.word64 fhPhOff
<> S.word64 fhShOff
<> S.word32 (unMachFlags fhFlags)
<> S.word16 (fromIntegral $ S.size anIdent + S.size aFileHdr64)
<> S.word16 (fromIntegral $ S.size aProgHdr64)
<> S.word16 fhPhNum
<> S.word16 (fromIntegral $ S.size aSecHdr64)
<> S.word16 fhShNum
<> S.word16 (unSecIx fhSnStIx)
instance SizedSerializable FileHdr64 where
size _ = 56
instance Deserializable FileHdr64 where
get = do
fileType ← FileType <$> D.word16 <?> "file type"
machine ← Machine <$> D.word16 <?> "machine code"
version ← D.word32 <?> "version"
unless (version == 1) $ D.unexpected "Unexpected ELF version"
entry ← D.word64 <?> "entry point address"
phOff ← D.word64 <?> "program header table offset"
shOff ← D.word64 <?> "section header table offset"
flags ← MachFlags <$> D.word32 <?> "machine flags"
fileHdrSize ← D.word16 <?> "file header size"
unless (fileHdrSize ==
fromIntegral (S.size anIdent + S.size aFileHdr64)) $
D.unexpected "Unexpected ELF file header size"
progHdrSize ← D.word16 <?> "program header size"
unless (progHdrSize == fromIntegral (S.size aProgHdr64)) $
D.unexpected "Unexpected ELF program header size"
phNum ← D.word16 <?> "program header table size"
secHdrSize ← D.word16 <?> "section header size"
unless (secHdrSize == fromIntegral (S.size aSecHdr64)) $
D.unexpected "Unexpected ELF section header size"
shNum ← D.word16 <?> "section header table size"
snStIx ← SecIx <$> D.word16 <?> "section name string table section index"
return $ FileHdr { fhType = fileType
, fhMachine = machine
, fhEntry = entry
, fhPhOff = phOff
, fhShOff = shOff
, fhFlags = flags
, fhPhNum = phNum
, fhShNum = shNum
, fhSnStIx = snStIx }
newtype SegType = SegType { unSegType ∷ Word32 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
unusedSegType ∷ SegType
unusedSegType = SegType 0
loadSegType ∷ SegType
loadSegType = SegType 1
dynSegType ∷ SegType
dynSegType = SegType 2
interpSegType ∷ SegType
interpSegType = SegType 3
noteSegType ∷ SegType
noteSegType = SegType 4
shlibSegType ∷ SegType
shlibSegType = SegType 5
phdrSegType ∷ SegType
phdrSegType = SegType 6
loOsSegType ∷ SegType
loOsSegType = SegType 0x60000000
hiOsSegType ∷ SegType
hiOsSegType = SegType 0x6FFFFFFF
loProcSegType ∷ SegType
loProcSegType = SegType 0x70000000
hiProcSegType ∷ SegType
hiProcSegType = SegType 0x7FFFFFFF
newtype SegFlags = SegFlags { unSegFlags ∷ Word32 }
deriving (Typeable, Data, Show, Read,
Eq, Flags, BoundedFlags)
execSegFlag ∷ SegFlags
execSegFlag = SegFlags 1
writeSegFlag ∷ SegFlags
writeSegFlag = SegFlags 2
readSegFlag ∷ SegFlags
readSegFlag = SegFlags 4
osSegFlags ∷ SegFlags
osSegFlags = SegFlags 0x00FF0000
procSegFlags ∷ SegFlags
procSegFlags = SegFlags 0xFF000000
data ProgHdr c = ProgHdr { phType ∷ SegType
, phFlags ∷ SegFlags
, phOff ∷ Off c
, phVirtAddr ∷ Addr c
, phPhysAddr ∷ Addr c
, phFileSize ∷ Off c
, phMemSize ∷ Addr c
, phAlign ∷ Addr c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (ProgHdr c)
deriving instance IsFileClass c ⇒ Show (ProgHdr c)
deriving instance IsFileClass c ⇒ Read (ProgHdr c)
deriving instance IsFileClass c ⇒ Eq (ProgHdr c)
type ProgHdr32 = ProgHdr Elf32
aProgHdr32 ∷ Proxy ProgHdr32
aProgHdr32 = Proxy
instance Serializable ProgHdr32 where
put (ProgHdr {..})
= S.word32 (unSegType phType)
<> S.word32 phOff
<> S.word32 phVirtAddr
<> S.word32 phPhysAddr
<> S.word32 phFileSize
<> S.word32 phMemSize
<> S.word32 (unSegFlags phFlags)
<> S.word32 phAlign
instance SizedSerializable ProgHdr32 where
size _ = 32
instance Deserializable ProgHdr32 where
get = do
segType ← SegType <$> D.word32 <?> "type"
off ← D.word32 <?> "offset"
virtAddr ← D.word32 <?> "virtual address"
physAddr ← D.word32 <?> "physical address"
fileSize ← D.word32 <?> "in-file size"
memSize ← D.word32 <?> "in-memory size"
flags ← SegFlags <$> D.word32 <?> "flags"
align ← D.word32 <?> "alignment"
return $ ProgHdr { phType = segType
, phOff = off
, phVirtAddr = virtAddr
, phPhysAddr = physAddr
, phFileSize = fileSize
, phMemSize = memSize
, phFlags = flags
, phAlign = align }
type ProgHdr64 = ProgHdr Elf64
aProgHdr64 ∷ Proxy ProgHdr64
aProgHdr64 = Proxy
instance Serializable ProgHdr64 where
put (ProgHdr {..})
= S.word32 (unSegType phType)
<> S.word32 (unSegFlags phFlags)
<> S.word64 phOff
<> S.word64 phVirtAddr
<> S.word64 phPhysAddr
<> S.word64 phFileSize
<> S.word64 phMemSize
<> S.word64 phAlign
instance SizedSerializable ProgHdr64 where
size _ = 56
instance Deserializable ProgHdr64 where
get = do
segType ← SegType <$> D.word32 <?> "type"
flags ← SegFlags <$> D.word32 <?> "flags"
off ← D.word64 <?> "offset"
virtAddr ← D.word64 <?> "virtual address"
physAddr ← D.word64 <?> "physical address"
fileSize ← D.word64 <?> "in-file size"
memSize ← D.word64 <?> "in-memory size"
align ← D.word64 <?> "alignment"
return $ ProgHdr { phType = segType
, phOff = off
, phVirtAddr = virtAddr
, phPhysAddr = physAddr
, phFileSize = fileSize
, phMemSize = memSize
, phFlags = flags
, phAlign = align }
type StrIx = Word32
newtype SecIx = SecIx { unSecIx ∷ Word16 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix, Num, Bits, FiniteBits,
Integral, Real)
undefSecIx ∷ SecIx
undefSecIx = 0
lastSecIx ∷ SecIx
lastSecIx = 0xFEFF
loOsSecIx ∷ SecIx
loOsSecIx = 0xFF20
hiOsSecIx ∷ SecIx
hiOsSecIx = 0xFF3F
loProcSecIx ∷ SecIx
loProcSecIx = 0xFF00
hiProcSecIx ∷ SecIx
hiProcSecIx = 0xFF1F
absSecIx ∷ SecIx
absSecIx = 0xFFF1
commonSecIx ∷ SecIx
commonSecIx = 0xFFF2
xIndexSecIx ∷ SecIx
xIndexSecIx = 0xFFFF
newtype SecType = SecType { unSecType ∷ Word32 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
unusedSecType ∷ SecType
unusedSecType = SecType 0
progBitsSecType ∷ SecType
progBitsSecType = SecType 1
symSecType ∷ SecType
symSecType = SecType 2
strSecType ∷ SecType
strSecType = SecType 3
relaSecType ∷ SecType
relaSecType = SecType 4
hashSecType ∷ SecType
hashSecType = SecType 5
dynSecType ∷ SecType
dynSecType = SecType 6
noteSecType ∷ SecType
noteSecType = SecType 7
noBitsSecType ∷ SecType
noBitsSecType = SecType 8
relSecType ∷ SecType
relSecType = SecType 9
shlibSecType ∷ SecType
shlibSecType = SecType 10
dynSymSecType ∷ SecType
dynSymSecType = SecType 11
loOsSecType ∷ SecType
loOsSecType = SecType 0x60000000
hiOsSecType ∷ SecType
hiOsSecType = SecType 0x6FFFFFFF
loProcSecType ∷ SecType
loProcSecType = SecType 0x70000000
hiProcSecType ∷ SecType
hiProcSecType = SecType 0x7FFFFFFF
newtype SecFlags = SecFlags { unSecFlags ∷ Word32 }
deriving (Typeable, Data, Show, Read,
Eq, Flags, BoundedFlags)
writeSecFlag ∷ SecFlags
writeSecFlag = SecFlags 1
allocSecFlag ∷ SecFlags
allocSecFlag = SecFlags 2
execSecFlag ∷ SecFlags
execSecFlag = SecFlags 4
mergeSecFlag ∷ SecFlags
mergeSecFlag = SecFlags 0x10
infoLinkSecFlag ∷ SecFlags
infoLinkSecFlag = SecFlags 0x40
osSecFlags ∷ SecFlags
osSecFlags = SecFlags 0x0F000000
procSecFlags ∷ SecFlags
procSecFlags = SecFlags 0xF0000000
data SecHdr c = SecHdr { shName ∷ StrIx
, shType ∷ SecType
, shFlags ∷ SecFlags
, shAddr ∷ Addr c
, shOff ∷ Off c
, shSize ∷ Addr c
, shLink ∷ Word32
, shInfo ∷ Word32
, shAlign ∷ Addr c
, shEntSize ∷ Addr c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (SecHdr c)
deriving instance IsFileClass c ⇒ Show (SecHdr c)
deriving instance IsFileClass c ⇒ Read (SecHdr c)
deriving instance IsFileClass c ⇒ Eq (SecHdr c)
type SecHdr32 = SecHdr Elf32
aSecHdr32 ∷ Proxy SecHdr32
aSecHdr32 = Proxy
instance Serializable SecHdr32 where
put (SecHdr {..})
= S.word32 shName
<> S.word32 (unSecType shType)
<> S.word32 (unSecFlags shFlags)
<> S.word32 shAddr
<> S.word32 shOff
<> S.word32 shSize
<> S.word32 shLink
<> S.word32 shInfo
<> S.word32 shAlign
<> S.word32 shEntSize
instance SizedSerializable SecHdr32 where
size _ = 40
instance Deserializable SecHdr32 where
get = do
name ← D.word32 <?> "name"
tp ← SecType <$> D.word32 <?> "type"
flags ← SecFlags <$> D.word32 <?> "flags"
addr ← D.word32 <?> "address"
off ← D.word32 <?> "offset"
size ← D.word32 <?> "size"
link ← D.word32 <?> "link"
info ← D.word32 <?> "extra information"
align ← D.word32 <?> "alignment"
entSize ← D.word32 <?> "entry size"
return $ SecHdr { shName = name
, shType = tp
, shFlags = flags
, shAddr = addr
, shOff = off
, shSize = size
, shLink = link
, shInfo = info
, shAlign = align
, shEntSize = entSize }
type SecHdr64 = SecHdr Elf64
aSecHdr64 ∷ Proxy SecHdr64
aSecHdr64 = Proxy
instance Serializable SecHdr64 where
put (SecHdr {..})
= S.word32 shName
<> S.word32 (unSecType shType)
<> S.word64 (fromIntegral (unSecFlags shFlags))
<> S.word64 shAddr
<> S.word64 shOff
<> S.word64 shSize
<> S.word32 shLink
<> S.word32 shInfo
<> S.word64 shAlign
<> S.word64 shEntSize
instance SizedSerializable SecHdr64 where
size _ = 64
instance Deserializable SecHdr64 where
get = do
name ← D.word32 <?> "name"
tp ← SecType <$> D.word32 <?> "type"
flags ← SecFlags . fromIntegral <$> D.word64 <?> "flags"
addr ← D.word64 <?> "address"
off ← D.word64 <?> "offset"
size ← D.word64 <?> "size"
link ← D.word32 <?> "link"
info ← D.word32 <?> "extra information"
align ← D.word64 <?> "alignment"
entSize ← D.word64 <?> "entry size"
return $ SecHdr { shName = name
, shType = tp
, shFlags = flags
, shAddr = addr
, shOff = off
, shSize = size
, shLink = link
, shInfo = info
, shAlign = align
, shEntSize = entSize }
zeroSecHdr ∷ IsFileClass c ⇒ SecHdr c
zeroSecHdr = SecHdr { shName = 0
, shType = unusedSecType
, shFlags = noFlags
, shAddr = 0
, shOff = 0
, shSize = 0
, shLink = 0
, shInfo = 0
, shAlign = 0
, shEntSize = 0 }
newtype SymType = SymType { unSymType ∷ Word4 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
undefSymType ∷ SymType
undefSymType = SymType 0
objSymType ∷ SymType
objSymType = SymType 1
funSymType ∷ SymType
funSymType = SymType 2
secSymType ∷ SymType
secSymType = SymType 3
fileSymType ∷ SymType
fileSymType = SymType 4
commonSymType ∷ SymType
commonSymType = SymType 5
tlsSymType ∷ SymType
tlsSymType = SymType 6
loOsSymType ∷ SymType
loOsSymType = SymType 10
hiOsSymType ∷ SymType
hiOsSymType = SymType 12
loProcSymType ∷ SymType
loProcSymType = SymType 13
hiProcSymType ∷ SymType
hiProcSymType = SymType 15
newtype SymBind = SymBind { unSymBind ∷ Word4 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
localSymBind ∷ SymBind
localSymBind = SymBind 0
globalSymBind ∷ SymBind
globalSymBind = SymBind 1
weakSymBind ∷ SymBind
weakSymBind = SymBind 2
loOsSymBind ∷ SymBind
loOsSymBind = SymBind 10
hiOsSymBind ∷ SymBind
hiOsSymBind = SymBind 12
loProcSymBind ∷ SymBind
loProcSymBind = SymBind 13
hiProcSymBind ∷ SymBind
hiProcSymBind = SymBind 15
newtype SymVisi = SymVisi { unSymVisi ∷ Word4 }
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
defSymVisi ∷ SymVisi
defSymVisi = SymVisi 0
intSymVisi ∷ SymVisi
intSymVisi = SymVisi 1
hiddenSymVisi ∷ SymVisi
hiddenSymVisi = SymVisi 2
protSymVisi ∷ SymVisi
protSymVisi = SymVisi 3
exportSymVisi ∷ SymVisi
exportSymVisi = SymVisi 4
singSymVisi ∷ SymVisi
singSymVisi = SymVisi 5
elimSymVisi ∷ SymVisi
elimSymVisi = SymVisi 6
newtype SymIx c = SymIx { unSymIx ∷ UnSymIx c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (SymIx c)
deriving instance IsFileClass c ⇒ Show (SymIx c)
deriving instance IsFileClass c ⇒ Read (SymIx c)
deriving instance IsFileClass c ⇒ Eq (SymIx c)
deriving instance IsFileClass c ⇒ Ord (SymIx c)
deriving instance IsFileClass c ⇒ Bounded (SymIx c)
deriving instance IsFileClass c ⇒ Enum (SymIx c)
deriving instance IsFileClass c ⇒ Ix (SymIx c)
deriving instance IsFileClass c ⇒ Num (SymIx c)
deriving instance IsFileClass c ⇒ Bits (SymIx c)
deriving instance IsFileClass c ⇒ FiniteBits (SymIx c)
deriving instance IsFileClass c ⇒ Integral (SymIx c)
deriving instance IsFileClass c ⇒ Real (SymIx c)
undefSymIx ∷ IsFileClass c ⇒ SymIx c
undefSymIx = SymIx 0
data SymEnt c = SymEnt { symName ∷ StrIx
, symBind ∷ SymBind
, symType ∷ SymType
, symVisi ∷ SymVisi
, symSecIx ∷ SecIx
, symAddr ∷ Addr c
, symSize ∷ Addr c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (SymEnt c)
deriving instance IsFileClass c ⇒ Show (SymEnt c)
deriving instance IsFileClass c ⇒ Read (SymEnt c)
deriving instance IsFileClass c ⇒ Eq (SymEnt c)
type SymEnt32 = SymEnt Elf32
aSymEnt32 ∷ Proxy SymEnt32
aSymEnt32 = Proxy
instance Serializable SymEnt32 where
put (SymEnt {..})
= S.word32 symName
<> S.word32 symAddr
<> S.word32 symSize
<> S.word8 (shiftL (fromIntegral $ unSymBind symBind) 4 .|.
fromIntegral (unSymType symType))
<> S.word8 (fromIntegral (unSymVisi symVisi))
<> S.word16 (unSecIx symSecIx)
instance SizedSerializable SymEnt32 where
size _ = 16
instance Deserializable SymEnt32 where
get = do
name ← D.word32 <?> "name"
addr ← D.word32 <?> "address"
size ← D.word32 <?> "size"
info ← D.word8 <?> "info"
let bind = SymBind (fromIntegral $ shiftR info 4)
tp = SymType (fromIntegral info)
visi ← SymVisi . fromIntegral <$> D.word8 <?> "visibility"
secIx ← SecIx <$> D.word16 <?> "section index"
return $ SymEnt { symName = name
, symAddr = addr
, symSize = size
, symBind = bind
, symType = tp
, symVisi = visi
, symSecIx = secIx }
type SymEnt64 = SymEnt Elf64
aSymEnt64 ∷ Proxy SymEnt64
aSymEnt64 = Proxy
instance Serializable SymEnt64 where
put (SymEnt {..})
= S.word32 symName
<> S.word8 (shiftL (fromIntegral $ unSymBind symBind) 4 .|.
fromIntegral (unSymType symType))
<> S.word8 (fromIntegral (unSymVisi symVisi))
<> S.word16 (unSecIx symSecIx)
<> S.word64 symAddr
<> S.word64 symSize
instance SizedSerializable SymEnt64 where
size _ = 24
instance Deserializable SymEnt64 where
get = do
name ← D.word32 <?> "name"
info ← D.word8 <?> "info"
let bind = SymBind (fromIntegral $ shiftR info 4)
tp = SymType (fromIntegral info)
visi ← SymVisi . fromIntegral <$> D.word8 <?> "visibility"
secIx ← SecIx <$> D.word16 <?> "section index"
addr ← D.word64 <?> "address"
size ← D.word64 <?> "size"
return $ SymEnt { symName = name
, symAddr = addr
, symSize = size
, symBind = bind
, symType = tp
, symVisi = visi
, symSecIx = secIx }
zeroSymEnt ∷ IsFileClass c ⇒ SymEnt c
zeroSymEnt = SymEnt { symName = 0
, symBind = localSymBind
, symType = undefSymType
, symVisi = defSymVisi
, symSecIx = undefSecIx
, symAddr = 0
, symSize = 0 }
newtype RelType c = RelType { unRelType ∷ UnRelType c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (RelType c)
deriving instance IsFileClass c ⇒ Show (RelType c)
deriving instance IsFileClass c ⇒ Read (RelType c)
deriving instance IsFileClass c ⇒ Eq (RelType c)
deriving instance IsFileClass c ⇒ Ord (RelType c)
deriving instance IsFileClass c ⇒ Bounded (RelType c)
deriving instance IsFileClass c ⇒ Enum (RelType c)
deriving instance IsFileClass c ⇒ Ix (RelType c)
type RelType32 = RelType Elf32
type RelType64 = RelType Elf64
data RelEnt c = RelEnt { relOff ∷ Addr c
, relSymIx ∷ SymIx c
, relType ∷ RelType c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (RelEnt c)
deriving instance IsFileClass c ⇒ Show (RelEnt c)
deriving instance IsFileClass c ⇒ Read (RelEnt c)
deriving instance IsFileClass c ⇒ Eq (RelEnt c)
type RelEnt32 = RelEnt Elf32
aRelEnt32 ∷ Proxy RelEnt32
aRelEnt32 = Proxy
instance Serializable RelEnt32 where
put (RelEnt {..})
= S.word32 relOff
<> S.word32 (shiftL (fromIntegral relSymIx) 8 .|.
fromIntegral (unRelType relType))
instance SizedSerializable RelEnt32 where
size _ = 8
instance Deserializable RelEnt32 where
get = do
off ← D.word32 <?> "offset"
info ← D.word32 <?> "info"
let symIx = SymIx $ fromIntegral $ shiftR info 8
tp = RelType $ fromIntegral info
return $ RelEnt { relOff = off
, relSymIx = symIx
, relType = tp }
type RelEnt64 = RelEnt Elf64
aRelEnt64 ∷ Proxy RelEnt64
aRelEnt64 = Proxy
instance Serializable RelEnt64 where
put (RelEnt {..})
= S.word64 relOff
<> S.word64 (shiftL (fromIntegral relSymIx) 32 .|.
fromIntegral (unRelType relType))
instance SizedSerializable RelEnt64 where
size _ = 16
instance Deserializable RelEnt64 where
get = do
off ← D.word64 <?> "offset"
info ← D.word64 <?> "info"
let symIx = SymIx $ fromIntegral $ shiftR info 32
tp = RelType $ fromIntegral info
return $ RelEnt { relOff = off
, relSymIx = symIx
, relType = tp }
data RelaEnt c = RelaEnt { relaOff ∷ Addr c
, relaSymIx ∷ SymIx c
, relaType ∷ RelType c
, relaAddend ∷ Addr c }
deriving Typeable
deriving instance (Data c, IsFileClass c) ⇒ Data (RelaEnt c)
deriving instance IsFileClass c ⇒ Show (RelaEnt c)
deriving instance IsFileClass c ⇒ Read (RelaEnt c)
deriving instance IsFileClass c ⇒ Eq (RelaEnt c)
type RelaEnt32 = RelaEnt Elf32
aRelaEnt32 ∷ Proxy RelaEnt32
aRelaEnt32 = Proxy
instance Serializable RelaEnt32 where
put (RelaEnt {..})
= S.word32 relaOff
<> S.word32 (shiftL (fromIntegral relaSymIx) 8 .|.
fromIntegral (unRelType relaType))
<> S.word32 relaAddend
instance SizedSerializable RelaEnt32 where
size _ = 12
instance Deserializable RelaEnt32 where
get = do
off ← D.word32 <?> "offset"
info ← D.word32 <?> "info"
let symIx = SymIx $ fromIntegral $ shiftR info 8
tp = RelType $ fromIntegral info
addend ← D.word32 <?> "addend"
return $ RelaEnt { relaOff = off
, relaSymIx = symIx
, relaType = tp
, relaAddend = addend }
type RelaEnt64 = RelaEnt Elf64
aRelaEnt64 ∷ Proxy RelaEnt64
aRelaEnt64 = Proxy
instance Serializable RelaEnt64 where
put (RelaEnt {..})
= S.word64 relaOff
<> S.word64 (shiftL (fromIntegral relaSymIx) 32 .|.
fromIntegral (unRelType relaType))
<> S.word64 relaAddend
instance SizedSerializable RelaEnt64 where
size _ = 24
instance Deserializable RelaEnt64 where
get = do
off ← D.word64 <?> "offset"
info ← D.word64 <?> "info"
let symIx = SymIx $ fromIntegral $ shiftR info 32
tp = RelType $ fromIntegral info
addend ← D.word64 <?> "addend"
return $ RelaEnt { relaOff = off
, relaSymIx = symIx
, relaType = tp
, relaAddend = addend }