data-elf (empty) → 0.1
raw patch · 5 files changed
+1377/−0 lines, 5 filesdep +basedep +binarydep +bytestringsetup-changed
Dependencies added: base, binary, bytestring, data-endian, data-flags, data-sword, text-latin1
Files
- LICENSE +27/−0
- README.md +10/−0
- Setup.hs +2/−0
- data-elf.cabal +40/−0
- src/Data/Elf.hs +1298/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2014-2016 Mikhail Vorozhtsov+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 names of the copyright owners nor the names of the+ 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.+
+ README.md view
@@ -0,0 +1,10 @@+Data-Elf+========+This package provides Executable and Linkable Format (ELF) data structures.++Installation+------------+The usual:++ $ cabal install+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ data-elf.cabal view
@@ -0,0 +1,40 @@+Name: data-elf+Version: 0.1+Category: Data+Stability: experimental+Synopsis: Executable and Linkable Format (ELF) data structures.+Description:+ This package provides Executable and Linkable Format (ELF) data structures.++Homepage: https://github.com/mvv/data-elf+Bug-Reports: https://github.com/mvv/data-elf/issues++Author: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+Maintainer: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+Copyright: 2014-2016 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+License: BSD3+License-File: LICENSE++Extra-Source-Files:+ README.md++Cabal-Version: >= 1.10.0+Build-Type: Simple++Source-Repository head+ Type: git+ Location: https://github.com/mvv/data-elf.git++Library+ Default-Language: Haskell2010+ Build-Depends: base >= 4.7 && < 5+ , bytestring >= 0.10.2+ , binary >= 0.7+ , data-endian >= 0.1+ , data-sword >= 0.1.1+ , data-flags >= 0.0.3+ , text-latin1 >= 0.3+ Hs-Source-Dirs: src+ GHC-Options: -Wall+ Exposed-Modules:+ Data.Elf
+ src/Data/Elf.hs view
@@ -0,0 +1,1298 @@+{-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | This module provides ELF data structures and (de)serialization routines.+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)++-- | File class.+newtype FileClass = FileClass { unFileClass ∷ Word8 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Invalid class (@ELFCLASSNONE@).+invalidFileClass ∷ FileClass+invalidFileClass = FileClass 0++-- | ELF32 class (@ELFCLASS32@).+elf32FileClass ∷ FileClass+elf32FileClass = FileClass 1++-- | ELF64 class (@ELFCLASS64@).+elf64FileClass ∷ FileClass+elf64FileClass = FileClass 2++-- | File class type-level index.+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++-- | 32-bit ELF class type-level index.+data Elf32 = Elf32 deriving (Typeable, Data)++-- | 'Elf32' proxy value.+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++-- | 64-bit ELF class type-level index.+data Elf64 = Elf64 deriving (Typeable, Data)++-- | 'Elf64' proxy value.+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++-- | File type.+newtype FileType = FileType { unFileType ∷ Word16 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | No file type (@ET_NONE@).+noneFileType ∷ FileType+noneFileType = FileType 0++-- | Relocatable object file (@ET_REL@).+relFileType ∷ FileType+relFileType = FileType 1++-- | Executable file (@ET_EXEC@).+execFileType ∷ FileType+execFileType = FileType 2++-- | Shared object file (@ET_DYN@).+dynFileType ∷ FileType+dynFileType = FileType 3++-- | Core file (@ET_CORE@).+coreFileType ∷ FileType+coreFileType = FileType 4++-- | First environment-specific type (@ET_LOOS@).+loOsFileType ∷ FileType+loOsFileType = FileType 0xFE00++-- | Last environment-specific type (@ET_HIOS@).+hiOsFileType ∷ FileType+hiOsFileType = FileType 0xFEFF++-- | First processor-specific type (@ET_LOPROC@).+loProcFileType ∷ FileType+loProcFileType = FileType 0xFF00++-- | Last processor-specific type (@ET_HIPROC@).+hiProcFileType ∷ FileType+hiProcFileType = FileType 0xFFFF++-- | Machine architecture.+newtype Machine = Machine { unMachine ∷ Word16 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | No machine (@EM_NONE@).+undefMachine ∷ Machine+undefMachine = Machine 0++-- | Intel 80386 (@EM_386@).+i386Machine ∷ Machine+i386Machine = Machine 3++-- | AMD x86-64 (@EM_X86_64@).+amd64Machine ∷ Machine+amd64Machine = Machine 62++-- | Architecture-specific flags.+newtype MachFlags = MachFlags { unMachFlags ∷ Word32 }+ deriving (Typeable, Data, Show, Read,+ Eq, Flags, BoundedFlags)++-- | ELF version.+newtype Version = Version { unVersion ∷ Word8 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)+-- | Invalid version.+invalidVersion ∷ Version+invalidVersion = Version 0++-- | Version 1.+firstVersion ∷ Version+firstVersion = Version 1++-- | Data encoding.+newtype DataEnc = DataEnc { unDataEnc ∷ Word8 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Invalid data encoding.+invalidDataEnc ∷ DataEnc+invalidDataEnc = DataEnc 0++-- | Little-endian data encoding (@ELFDATA2LSB@).+lsbDataEnc ∷ DataEnc+lsbDataEnc = DataEnc 1++-- | Big-endian data encoding (@ELFDATA2MSB@).+msbDataEnc ∷ DataEnc+msbDataEnc = DataEnc 1++-- | System ABI.+newtype OsAbi = OsAbi { unOsAbi ∷ Word8 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | System V (@ELFOSABI_NONE@).+sysvOsAbi ∷ OsAbi+sysvOsAbi = OsAbi 0++-- | HP-UX (@ELFOSABI_HPUX@).+hpuxOsAbi ∷ OsAbi+hpuxOsAbi = OsAbi 1++-- | NetBSD (@ELFOSABI_NETBSD@).+netBsdOsAbi ∷ OsAbi+netBsdOsAbi = OsAbi 2++-- | GNU (@ELFOSABI_GNU@, @ELFOSABI_LINUX@).+gnuOsAbi ∷ OsAbi+gnuOsAbi = OsAbi 3++-- | Solaris (@ELFOSABI_SOLARIS@).+solarisOsAbi ∷ OsAbi+solarisOsAbi = OsAbi 6++-- | AIX (@ELFOSABI_AIX@).+aixOsAbi ∷ OsAbi+aixOsAbi = OsAbi 7++-- | IRIX (@ELFOSABI_IRIX@).+irixOsAbi ∷ OsAbi+irixOsAbi = OsAbi 8++-- | FreeBSD (@ELFOSABI_FREEBSD@).+freeBsdOsAbi ∷ OsAbi+freeBsdOsAbi = OsAbi 9++-- | Tru64 UNIX (@ELFOSABI_TRU64@).+tru64OsAbi ∷ OsAbi+tru64OsAbi = OsAbi 10++-- | Novell Modesto (@ELFOSABI_MODESTO@).+modestoOsAbi ∷ OsAbi+modestoOsAbi = OsAbi 11++-- | OpenBSD (@ELFOSABI_OPENBSD@).+openBsdOsAbi ∷ OsAbi+openBsdOsAbi = OsAbi 12++-- | OpenVMS (@ELFOSABI_OPENVMS@).+openVmsOsAbi ∷ OsAbi+openVmsOsAbi = OsAbi 13++-- | Hewlett-Packard Non-Stop Kernel (@ELFOSABI_NSK@).+nskOsAbi ∷ OsAbi+nskOsAbi = OsAbi 14++-- | Amiga Research OS (@ELFOSABI_AROS@).+arosOsAbi ∷ OsAbi+arosOsAbi = OsAbi 15++-- | FenixOS (@ELFOSABI_FENIXOS@).+fenixOsAbi ∷ OsAbi+fenixOsAbi = OsAbi 16++-- | Standalone (embedded) application.+embedOsAbi ∷ OsAbi+embedOsAbi = OsAbi 255++-- | ABI version.+newtype AbiVer = AbiVer { unAbiVer ∷ Word8 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Undefined ABI version.+undefAbiVer ∷ AbiVer+undefAbiVer = AbiVer 0++-- | Identification.+data Ident = Ident { idClass ∷ FileClass+ , idVersion ∷ Version+ , idDataEnc ∷ DataEnc+ , idOsAbi ∷ OsAbi+ , idAbiVer ∷ AbiVer }+ deriving (Typeable, Data)++-- | Identification serialized size.+identSize ∷ Int+identSize = 16+{-# INLINE identSize #-}++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 }++-- | Serialize identification via 'ByteString' builder.+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++-- | File header.+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)++-- | ELF32 file header.+type FileHdr32 = FileHdr Elf32++-- | ELF64 file header.+type FileHdr64 = FileHdr Elf64++-- | ELF32 file header size.+fileHdr32Size ∷ Int+fileHdr32Size = 36++-- | ELF64 file header size.+fileHdr64Size ∷ Int+fileHdr64Size = 56++-- | Serialize ELF32 file header via 'Bin.PutM' monad.+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++-- | Deserialize ELF32 file header via 'Bin.Get' monad.+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++-- | Serialize ELF32 file header via 'ByteString' builder.+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++-- | Serialize ELF64 file header via 'ByteString' builder.+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++-- | Segment type.+newtype SegType = SegType { unSegType ∷ Word32 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Unused program header entry (@PT_NULL@).+unusedSegType ∷ SegType+unusedSegType = SegType 0++-- | Loadable segment (@PT_LOAD@).+loadSegType ∷ SegType+loadSegType = SegType 1++-- | Dynamic linking tables (@PT_DYNAMIC@).+dynSegType ∷ SegType+dynSegType = SegType 2++-- | Program interpreter path name (@PT_INTERP@).+interpSegType ∷ SegType+interpSegType = SegType 3++-- | Note sections (@PT_NOTE@).+noteSegType ∷ SegType+noteSegType = SegType 4++-- | A reserved segment type (@PT_SHLIB@).+shlibSegType ∷ SegType+shlibSegType = SegType 5++-- | Program header table (@PT_PHDR@).+phdrSegType ∷ SegType+phdrSegType = SegType 6++-- | First environment-specific segment type (@PT_LOOS@).+loOsSegType ∷ SegType+loOsSegType = SegType 0x60000000++-- | Last environment-specific segment type (@PT_HIOS@).+hiOsSegType ∷ SegType+hiOsSegType = SegType 0x6FFFFFFF++-- | First processor-specific segment type (@PT_LOPROC@).+loProcSegType ∷ SegType+loProcSegType = SegType 0x70000000++-- | Last processor-specific segment type (@PT_HIPROC@).+hiProcSegType ∷ SegType+hiProcSegType = SegType 0x7FFFFFFF++-- | Segment flags.+newtype SegFlags = SegFlags { unSegFlags ∷ Word32 }+ deriving (Typeable, Data, Show, Read,+ Eq, Flags, BoundedFlags)++-- | Execute permission (@PF_X@).+execSegFlag ∷ SegFlags+execSegFlag = SegFlags 1++-- | Write permission (@PF_W@).+writeSegFlag ∷ SegFlags+writeSegFlag = SegFlags 2++-- | Read permission (@PF_R@).+readSegFlag ∷ SegFlags+readSegFlag = SegFlags 4++-- | Environment-specific flags mask (@PF_MASKOS@).+osSegFlags ∷ SegFlags+osSegFlags = SegFlags 0x00FF0000++-- | Processor-specific flags mask (@PF_MASKPROC@).+procSegFlags ∷ SegFlags+procSegFlags = SegFlags 0xFF000000++-- | Program header table entry.+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)++-- | ELF32 program header table entry.+type ProgHdr32 = ProgHdr Elf32++-- | ELF64 program header table entry.+type ProgHdr64 = ProgHdr Elf64++-- | ELF32 program header table entry size.+progHdr32Size ∷ Int+progHdr32Size = 32++-- | ELF64 program header table entry size.+progHdr64Size ∷ Int+progHdr64Size = 56++-- | Serialize ELF32 program header via 'Bin.PutM' monad.+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++-- | Deserialize ELF32 program header via 'Bin.Get' monad.+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++-- | Serialize ELF32 program header via 'ByteString' builder.+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++-- | Serialize ELF64 program header via 'ByteString' builder.+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++-- | String table index.+type StrIx = Word32++-- | Section header entry index.+newtype SecIx = SecIx { unSecIx ∷ Word16 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix, Num, Bits, FiniteBits,+ Integral, Real)++-- | Undefined section reference (@SHN_UNDEF@).+undefSecIx ∷ SecIx+undefSecIx = 0++-- | Last regular section index.+lastSecIx ∷ SecIx+lastSecIx = 0xFEFF++-- | First environment-specific section index (@SHN_LOOS@).+loOsSecIx ∷ SecIx+loOsSecIx = 0xFF20++-- | Last environment-specific section index (@SHN_HIOS@).+hiOsSecIx ∷ SecIx+hiOsSecIx = 0xFF3F++-- | First processor-specific section index (@SHN_LOPROC@).+loProcSecIx ∷ SecIx+loProcSecIx = 0xFF00++-- | Last processor-specific section index (@SHN_HIPROC@).+hiProcSecIx ∷ SecIx+hiProcSecIx = 0xFF1F++-- | Absolute value indicator (@SHN_ABS@).+absSecIx ∷ SecIx+absSecIx = 0xFFF1++-- | Common block indicator (@SHN_COMMON@).+commonSecIx ∷ SecIx+commonSecIx = 0xFFF2++-- | Escape value (@SHN_XINDEX@).+xIndexSecIx ∷ SecIx+xIndexSecIx = 0xFFFF++-- | Section type.+newtype SecType = SecType { unSecType ∷ Word32 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Unused section (@SHT_NULL@).+unusedSecType ∷ SecType+unusedSecType = SecType 0++-- | Program information (@SHT_PROGBITS@).+progBitsSecType ∷ SecType+progBitsSecType = SecType 1++-- | Symbol table (@SHT_SYMTAB@).+symSecType ∷ SecType+symSecType = SecType 2++-- | String table (@SHT_STRTAB@).+strSecType ∷ SecType+strSecType = SecType 3++-- | Relocation entries (@SHT_RELA@).+relaSecType ∷ SecType+relaSecType = SecType 4++-- | Symbol hash table (@SHT_HASH@).+hashSecType ∷ SecType+hashSecType = SecType 5++-- | Dynamic linking table (@SHT_DYNAMIC@).+dynSecType ∷ SecType+dynSecType = SecType 6++-- | Note information (@SHT_NOTE@).+noteSecType ∷ SecType+noteSecType = SecType 7++-- | Uninitialized space (@SHT_NOBITS@).+noBitsSecType ∷ SecType+noBitsSecType = SecType 8++-- | Relocation entries (@SHT_REL@).+relSecType ∷ SecType+relSecType = SecType 9++-- | A reserved section type (@SHT_SHLIB@).+shlibSecType ∷ SecType+shlibSecType = SecType 10++-- | Dynamic loader symbol table (@SHT_DYNSYM@).+dynSymSecType ∷ SecType+dynSymSecType = SecType 11++-- | First environment-specific section type (@SHT_LOOS@).+loOsSecType ∷ SecType+loOsSecType = SecType 0x60000000++-- | Last environment-specific section type (@SHT_HIOS@).+hiOsSecType ∷ SecType+hiOsSecType = SecType 0x6FFFFFFF++-- | First processor-specific section type (@SHT_LOPROC@).+loProcSecType ∷ SecType+loProcSecType = SecType 0x70000000++-- | Last processor-specific section type (@SHT_HIPROC@).+hiProcSecType ∷ SecType+hiProcSecType = SecType 0x7FFFFFFF++-- | Section flags.+newtype SecFlags = SecFlags { unSecFlags ∷ Word32 }+ deriving (Typeable, Data, Show, Read,+ Eq, Flags, BoundedFlags)++-- | Writable data (@SHF_WRITE@).+writeSecFlag ∷ SecFlags+writeSecFlag = SecFlags 1++-- | Allocated data (@SHF_ALLOC@).+allocSecFlag ∷ SecFlags+allocSecFlag = SecFlags 2++-- | Executable instructions (@SHF_EXECINSTR@).+execSecFlag ∷ SecFlags+execSecFlag = SecFlags 4++-- | Mergeable data (@SHF_MERGE@).+mergeSecFlag ∷ SecFlags+mergeSecFlag = SecFlags 0x10++-- | Flag that indicates that 'shInfo' is a section header table index.+-- (@SHF_INFO_LINK@)+infoLinkSecFlag ∷ SecFlags+infoLinkSecFlag = SecFlags 0x40++-- | Environment-specific flags mask (@SHF_MASKOS@).+osSecFlags ∷ SecFlags+osSecFlags = SecFlags 0x0F000000++-- | Processor-specific flags mask (@SHF_MASKOS@).+procSecFlags ∷ SecFlags+procSecFlags = SecFlags 0xF0000000++-- | Section header table entry.+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)++-- | ELF32 section header table entry.+type SecHdr32 = SecHdr Elf32++-- | ELF64 section header table entry.+type SecHdr64 = SecHdr Elf64++-- | ELF32 section header table entry size.+secHdr32Size ∷ Int+secHdr32Size = 40++-- | ELF64 section header table entry size.+secHdr64Size ∷ Int+secHdr64Size = 64++-- | Serialize ELF32 section header via 'ByteString' builder.+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++-- | Serialize ELF64 section header via 'ByteString' builder.+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++-- | Section header filled with zeros.+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 }++-- | Symbol type.+newtype SymType = SymType { unSymType ∷ Word4 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Undefined symbol type (@STT_NOTYPE@).+undefSymType ∷ SymType+undefSymType = SymType 0++-- | Object (@STT_OBJECT@).+objSymType ∷ SymType+objSymType = SymType 1++-- | Function (@STT_FUNC@).+funSymType ∷ SymType+funSymType = SymType 2++-- | Section (@STT_SECTION@).+secSymType ∷ SymType+secSymType = SymType 3++-- | Source file name (@STT_FILE@).+fileSymType ∷ SymType+fileSymType = SymType 4++-- | Common block label (@STT_COMMON@).+commonSymType ∷ SymType+commonSymType = SymType 5++-- | Thread-local storage (@STT_TLS@).+tlsSymType ∷ SymType+tlsSymType = SymType 6++-- | First environment-specific symbol type (@STT_LOOS@).+loOsSymType ∷ SymType+loOsSymType = SymType 10++-- | Last environment-specific symbol type (@STT_HIOS@).+hiOsSymType ∷ SymType+hiOsSymType = SymType 12++-- | First processor-specific symbol type (@STT_LOPROC@).+loProcSymType ∷ SymType+loProcSymType = SymType 13++-- | Last processor-specific symbol type (@STT_HIPROC@).+hiProcSymType ∷ SymType+hiProcSymType = SymType 15++-- | Symbol binding type.+newtype SymBind = SymBind { unSymBind ∷ Word4 }+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Local symbol (@STB_LOCAL@).+localSymBind ∷ SymBind+localSymBind = SymBind 0++-- | Global symbol (@STB_GLOBAL@).+globalSymBind ∷ SymBind+globalSymBind = SymBind 1++-- | Lower precedence global symbol (@STB_WEAK@).+weakSymBind ∷ SymBind+weakSymBind = SymBind 2++-- | First environment-specific symbol binding type (@STB_LOOS@).+loOsSymBind ∷ SymBind+loOsSymBind = SymBind 10++-- | Last environment-specific symbol binding type (@STB_HIOS@).+hiOsSymBind ∷ SymBind+hiOsSymBind = SymBind 12++-- | First processor-specific symbol binding type (@STB_LOPROC@).+loProcSymBind ∷ SymBind+loProcSymBind = SymBind 13++-- | Last processor-specific symbol binding type (@STB_HIPROC@).+hiProcSymBind ∷ SymBind+hiProcSymBind = SymBind 15++-- | Symbol visibility.+data SymVisi = DefSymVisi -- ^ Default (specified by the binding type)+ -- (@STV_DEFAULT@)+ | IntSymVisi -- ^ Internal (processor-specific hidden type)+ -- (@STV_INTERNAL@)+ | HiddenSymVisi -- ^ Hidden (@STV_HIDDEN@)+ | ProtSymVisi -- ^ Protected (@STV_PROTECTED@)+ deriving (Typeable, Data, Show, Read,+ Eq, Ord, Bounded, Enum, Ix)++-- | Symbol visibility code.+unSymVisi ∷ SymVisi → Word2+unSymVisi DefSymVisi = 0+unSymVisi IntSymVisi = 1+unSymVisi HiddenSymVisi = 2+unSymVisi ProtSymVisi = 3++-- | Symbol table index.+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)++-- | Undefined symbol table index.+undefSymIx ∷ IsFileClass c ⇒ SymIx c+undefSymIx = SymIx 0++-- | Symbol table entry.+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)++-- | ELF32 symbol table entry.+type SymEnt32 = SymEnt Elf32++-- | ELF64 symbol table entry.+type SymEnt64 = SymEnt Elf64++-- | ELF32 symbol table entry size.+symEnt32Size ∷ Int+symEnt32Size = 16++-- | ELF64 symbol table entry size.+symEnt64Size ∷ Int+symEnt64Size = 24++-- | Serialize ELF32 symbol table entry via 'ByteString' builder.+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++-- | Serialize ELF64 symbol table entry via 'ByteString' builder.+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++-- | Symbol table entry filled with zeros.+zeroSymEnt ∷ IsFileClass c ⇒ SymEnt c+zeroSymEnt = SymEnt { symName = 0+ , symBind = localSymBind+ , symType = undefSymType+ , symVisi = DefSymVisi+ , symSecIx = undefSecIx+ , symAddr = 0+ , symSize = 0 }++-- | Relocation type.+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)++-- | ELF32 relocation type.+type RelType32 = RelType Elf32++-- | ELF64 relocation type.+type RelType64 = RelType Elf64++-- | Relocation table entry (REL).+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)++-- | ELF32 relocation table entry (REL).+type RelEnt32 = RelEnt Elf32++-- | ELF64 relocation table entry (REL).+type RelEnt64 = RelEnt Elf64++-- | Relocation table entry (RELA).+data RelaEnt c = RelaEnt { relaOff ∷ Addr c+ , relaSymIx ∷ SymIx c+ , relaType ∷ RelType c+ , relaAddend ∷ Addr c }+ deriving Typeable++-- | ELF32 relocation table entry (RELA).+type RelaEnt32 = RelaEnt Elf32++-- | ELF64 relocation table entry (RELA).+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)++-- | ELF32 relocation table entry (RELA) size.+relaEnt32Size ∷ Int+relaEnt32Size = 12++-- | ELF64 relocation table entry (RELA) size.+relaEnt64Size ∷ Int+relaEnt64Size = 24++-- | Serialize ELF32 relocation table entry (RELA) via 'ByteString'+-- builder.+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++-- | Serialize ELF64 relocation table entry (RELA) via 'ByteString'+-- builder.+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