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(..)
, identSize
, buildIdent
, FileHdr(..)
, FileHdr32
, FileHdr64
, fileHdr32Size
, fileHdr64Size
, putFileHdr32
, getFileHdr32
, buildFileHdr32
, buildFileHdr64
, SegType(..)
, unusedSegType
, loadSegType
, dynSegType
, interpSegType
, noteSegType
, shlibSegType
, phdrSegType
, loOsSegType
, hiOsSegType
, loProcSegType
, hiProcSegType
, SegFlags(..)
, execSegFlag
, writeSegFlag
, readSegFlag
, osSegFlags
, procSegFlags
, ProgHdr(..)
, ProgHdr32
, ProgHdr64
, progHdr32Size
, progHdr64Size
, putProgHdr32
, getProgHdr32
, buildProgHdr32
, buildProgHdr64
, 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
, SecHdr64
, secHdr32Size
, secHdr64Size
, buildSecHdr32
, buildSecHdr64
, zeroSecHdr
, SymType(..)
, undefSymType
, objSymType
, funSymType
, secSymType
, fileSymType
, commonSymType
, tlsSymType
, loOsSymType
, hiOsSymType
, loProcSymType
, hiProcSymType
, SymBind(..)
, localSymBind
, globalSymBind
, weakSymBind
, loOsSymBind
, hiOsSymBind
, loProcSymBind
, hiProcSymBind
, SymVisi(..)
, unSymVisi
, SymIx(..)
, undefSymIx
, SymEnt(..)
, SymEnt32
, SymEnt64
, symEnt32Size
, symEnt64Size
, buildSymEnt32
, buildSymEnt64
, zeroSymEnt
, RelType(..)
, RelType32
, RelType64
, RelEnt(..)
, RelEnt32
, RelEnt64
, RelaEnt(..)
, RelaEnt32
, RelaEnt64
, relaEnt32Size
, relaEnt64Size
, buildRelaEnt32
, buildRelaEnt64
) where
import Data.Typeable (Typeable)
import Data.Data (Data)
import Data.Proxy (Proxy(..))
import Data.Ix (Ix)
import Data.Endian
import Data.Bits (Bits, shiftL, (.|.), FiniteBits)
import Data.Flags (Flags(noFlags), BoundedFlags)
import Data.Word (Word8, Word16, Word32, Word64)
import Data.ShortWord (Word2, Word4, Word24)
import Data.Monoid ((<>))
import qualified Data.ByteString.Builder as BB
import Data.Binary (Binary)
import qualified Data.Binary as Bin
import qualified Data.Binary.Put as Bin
import qualified Data.Binary.Get as Bin
import Text.Ascii (ascii)
import Control.Applicative ((<$>))
import Control.Monad (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)
identSize ∷ Int
identSize = 16
instance Binary Ident where
put (Ident {..}) = do
Bin.putWord8 0x7F
Bin.putWord8 (ascii 'E')
Bin.putWord8 (ascii 'L')
Bin.putWord8 (ascii 'F')
Bin.putWord8 (unFileClass idClass)
Bin.putWord8 (unDataEnc idDataEnc)
Bin.putWord8 (unVersion idVersion)
Bin.putWord8 (unOsAbi idOsAbi)
Bin.putWord8 (unAbiVer idAbiVer)
Bin.putWord8 0
Bin.putWord8 0
Bin.putWord8 0
Bin.putWord8 0
Bin.putWord8 0
Bin.putWord8 0
Bin.putWord8 0
get = do
b₀ ← Bin.getWord8
unless (b₀ == 0x7F) $ fail "Invalid ELF magic number"
b₁ ← Bin.getWord8
unless (b₁ == ascii 'E') $ fail "Invalid ELF magic number"
b₂ ← Bin.getWord8
unless (b₂ == ascii 'L') $ fail "Invalid ELF magic number"
b₃ ← Bin.getWord8
unless (b₃ == ascii 'F') $ fail "Invalid ELF magic number"
fileCls ← FileClass <$> Bin.getWord8
dataEnc ← DataEnc <$> Bin.getWord8
version ← Version <$> Bin.getWord8
osAbi ← OsAbi <$> Bin.getWord8
abiVer ← AbiVer <$> Bin.getWord8
Bin.skip 7
return $ Ident { idClass = fileCls
, idDataEnc = dataEnc
, idVersion = version
, idOsAbi = osAbi
, idAbiVer = abiVer }
buildIdent ∷ Ident → BB.Builder
buildIdent (Ident {..}) = BB.word8 0x7F
<> BB.word8 (ascii 'E')
<> BB.word8 (ascii 'L')
<> BB.word8 (ascii 'F')
<> BB.word8 (unFileClass idClass)
<> BB.word8 (unDataEnc idDataEnc)
<> BB.word8 (unVersion idVersion)
<> BB.word8 (unOsAbi idOsAbi)
<> BB.word8 (unAbiVer idAbiVer)
<> BB.word8 0
<> BB.word8 0
<> BB.word8 0
<> BB.word8 0
<> BB.word8 0
<> BB.word8 0
<> BB.word8 0
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)
type FileHdr32 = FileHdr Elf32
type FileHdr64 = FileHdr Elf64
fileHdr32Size ∷ Int
fileHdr32Size = 36
fileHdr64Size ∷ Int
fileHdr64Size = 56
putFileHdr32 ∷ Endian → FileHdr32 → Bin.Put
putFileHdr32 endian (FileHdr {..}) = do
word16 (unFileType fhType)
word16 (unMachine fhMachine)
word32 1
word32 fhEntry
word32 fhPhOff
word32 fhShOff
word32 (unMachFlags fhFlags)
word16 (fromIntegral $ identSize + fileHdr32Size)
word16 (fromIntegral progHdr32Size)
word16 fhPhNum
word16 (fromIntegral secHdr32Size)
word16 fhShNum
word16 (unSecIx fhSnStIx)
where word16 | isLittleEndian endian = Bin.putWord16le
| otherwise = Bin.putWord16be
word32 | isLittleEndian endian = Bin.putWord32le
| otherwise = Bin.putWord32be
getFileHdr32 ∷ Endian → Bin.Get FileHdr32
getFileHdr32 endian = do
fileType ← FileType <$> word16
machine ← Machine <$> word16
version ← word32
unless (version == 1) $ fail "Unexpected ELF version"
entry ← word32
phOff ← word32
shOff ← word32
flags ← MachFlags <$> word32
fileHdrSize ← word16
unless (fileHdrSize == fromIntegral (identSize + fileHdr32Size)) $
fail "Unexpected ELF file header size"
progHdrSize ← word16
unless (progHdrSize == fromIntegral progHdr32Size) $
fail "Unexpected ELF program header size"
phNum ← word16
secHdrSize ← word16
unless (secHdrSize == fromIntegral secHdr32Size) $
fail "Unexpected ELF section header size"
shNum ← word16
snStIx ← SecIx <$> word16
return $ FileHdr { fhType = fileType
, fhMachine = machine
, fhEntry = entry
, fhPhOff = phOff
, fhShOff = shOff
, fhFlags = flags
, fhPhNum = phNum
, fhShNum = shNum
, fhSnStIx = snStIx }
where word16 | isLittleEndian endian = Bin.getWord16le
| otherwise = Bin.getWord16be
word32 | isLittleEndian endian = Bin.getWord32le
| otherwise = Bin.getWord32be
buildFileHdr32 ∷ Endian → FileHdr32 → BB.Builder
buildFileHdr32 endian (FileHdr {..})
= word16 (unFileType fhType)
<> word16 (unMachine fhMachine)
<> word32 1
<> word32 fhEntry
<> word32 fhPhOff
<> word32 fhShOff
<> word32 (unMachFlags fhFlags)
<> word16 (fromIntegral $ identSize + fileHdr32Size)
<> word16 (fromIntegral progHdr32Size)
<> word16 fhPhNum
<> word16 (fromIntegral secHdr32Size)
<> word16 fhShNum
<> word16 (unSecIx fhSnStIx)
where word16 = if isLittleEndian endian then BB.word16LE else BB.word16BE
word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
buildFileHdr64 ∷ Endian → FileHdr64 → BB.Builder
buildFileHdr64 endian (FileHdr {..})
= word16 (unFileType fhType)
<> word16 (unMachine fhMachine)
<> word32 1
<> word64 fhEntry
<> word64 fhPhOff
<> word64 fhShOff
<> word32 (unMachFlags fhFlags)
<> word16 (fromIntegral $ identSize + fileHdr64Size)
<> word16 (fromIntegral progHdr64Size)
<> word16 fhPhNum
<> word16 (fromIntegral secHdr64Size)
<> word16 fhShNum
<> word16 (unSecIx fhSnStIx)
where word16 = if isLittleEndian endian then BB.word16LE else BB.word16BE
word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
word64 = if isLittleEndian endian then BB.word64LE else BB.word64BE
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)
type ProgHdr32 = ProgHdr Elf32
type ProgHdr64 = ProgHdr Elf64
progHdr32Size ∷ Int
progHdr32Size = 32
progHdr64Size ∷ Int
progHdr64Size = 56
putProgHdr32 ∷ Endian → ProgHdr32 → Bin.Put
putProgHdr32 endian (ProgHdr {..}) = do
word32 (unSegType phType)
word32 phOff
word32 phVirtAddr
word32 phPhysAddr
word32 phFileSize
word32 phMemSize
word32 (unSegFlags phFlags)
word32 phAlign
where word32 | isLittleEndian endian = Bin.putWord32le
| otherwise = Bin.putWord32be
getProgHdr32 ∷ Endian → Bin.Get ProgHdr32
getProgHdr32 endian = do
segType ← SegType <$> word32
off ← word32
virtAddr ← word32
physAddr ← word32
fileSize ← word32
memSize ← word32
flags ← SegFlags <$> word32
align ← word32
return $ ProgHdr { phType = segType
, phOff = off
, phVirtAddr = virtAddr
, phPhysAddr = physAddr
, phFileSize = fileSize
, phMemSize = memSize
, phFlags = flags
, phAlign = align }
where word32 | isLittleEndian endian = Bin.getWord32le
| otherwise = Bin.getWord32be
buildProgHdr32 ∷ Endian → ProgHdr32 → BB.Builder
buildProgHdr32 endian (ProgHdr {..})
= word32 (unSegType phType)
<> word32 phOff
<> word32 phVirtAddr
<> word32 phPhysAddr
<> word32 phFileSize
<> word32 phMemSize
<> word32 (unSegFlags phFlags)
<> word32 phAlign
where word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
buildProgHdr64 ∷ Endian → ProgHdr64 → BB.Builder
buildProgHdr64 endian (ProgHdr {..})
= word32 (unSegType phType)
<> word32 (unSegFlags phFlags)
<> word64 phOff
<> word64 phVirtAddr
<> word64 phPhysAddr
<> word64 phFileSize
<> word64 phMemSize
<> word64 phAlign
where word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
word64 = if isLittleEndian endian then BB.word64LE else BB.word64BE
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)
type SecHdr32 = SecHdr Elf32
type SecHdr64 = SecHdr Elf64
secHdr32Size ∷ Int
secHdr32Size = 40
secHdr64Size ∷ Int
secHdr64Size = 64
buildSecHdr32 ∷ Endian → SecHdr32 → BB.Builder
buildSecHdr32 endian (SecHdr {..})
= word32 shName
<> word32 (unSecType shType)
<> word32 (unSecFlags shFlags)
<> word32 shAddr
<> word32 shOff
<> word32 shSize
<> word32 shLink
<> word32 shInfo
<> word32 shAlign
<> word32 shEntSize
where word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
buildSecHdr64 ∷ Endian → SecHdr64 → BB.Builder
buildSecHdr64 endian (SecHdr {..})
= word32 shName
<> word32 (unSecType shType)
<> word64 (fromIntegral (unSecFlags shFlags))
<> word64 shAddr
<> word64 shOff
<> word64 shSize
<> word32 shLink
<> word32 shInfo
<> word64 shAlign
<> word64 shEntSize
where word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
word64 = if isLittleEndian endian then BB.word64LE else BB.word64BE
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
data SymVisi = DefSymVisi
| IntSymVisi
| HiddenSymVisi
| ProtSymVisi
deriving (Typeable, Data, Show, Read,
Eq, Ord, Bounded, Enum, Ix)
unSymVisi ∷ SymVisi → Word2
unSymVisi DefSymVisi = 0
unSymVisi IntSymVisi = 1
unSymVisi HiddenSymVisi = 2
unSymVisi ProtSymVisi = 3
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)
type SymEnt32 = SymEnt Elf32
type SymEnt64 = SymEnt Elf64
symEnt32Size ∷ Int
symEnt32Size = 16
symEnt64Size ∷ Int
symEnt64Size = 24
buildSymEnt32 ∷ Endian → SymEnt32 → BB.Builder
buildSymEnt32 endian (SymEnt {..})
= word32 symName
<> word32 symAddr
<> word32 symSize
<> BB.word8 (shiftL (fromIntegral $ unSymBind symBind) 4 .|.
fromIntegral (unSymType symType))
<> BB.word8 (fromIntegral (unSymVisi symVisi))
<> word16 (unSecIx symSecIx)
where word16 = if isLittleEndian endian then BB.word16LE else BB.word16BE
word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
buildSymEnt64 ∷ Endian → SymEnt64 → BB.Builder
buildSymEnt64 endian (SymEnt {..})
= word32 symName
<> BB.word8 (shiftL (fromIntegral $ unSymBind symBind) 4 .|.
fromIntegral (unSymType symType))
<> BB.word8 (fromIntegral $ unSymVisi symVisi)
<> word16 (unSecIx symSecIx)
<> word64 symAddr
<> word64 symSize
where word16 = if isLittleEndian endian then BB.word16LE else BB.word16BE
word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
word64 = if isLittleEndian endian then BB.word64LE else BB.word64BE
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
type RelEnt64 = RelEnt Elf64
data RelaEnt c = RelaEnt { relaOff ∷ Addr c
, relaSymIx ∷ SymIx c
, relaType ∷ RelType c
, relaAddend ∷ Addr c }
deriving Typeable
type RelaEnt32 = RelaEnt Elf32
type RelaEnt64 = RelaEnt Elf64
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)
relaEnt32Size ∷ Int
relaEnt32Size = 12
relaEnt64Size ∷ Int
relaEnt64Size = 24
buildRelaEnt32 ∷ Endian → RelaEnt32 → BB.Builder
buildRelaEnt32 endian (RelaEnt {..})
= word32 relaOff
<> word32 (shiftL (fromIntegral relaSymIx) 8 .|.
fromIntegral (unRelType relaType))
<> word32 relaAddend
where word32 = if isLittleEndian endian then BB.word32LE else BB.word32BE
buildRelaEnt64 ∷ Endian → RelaEnt64 → BB.Builder
buildRelaEnt64 endian (RelaEnt {..})
= word64 relaOff
<> word64 (shiftL (fromIntegral relaSymIx) 32 .|.
fromIntegral (unRelType relaType))
<> word64 relaAddend
where word64 = if isLittleEndian endian then BB.word64LE else BB.word64BE