elf 0.23 → 0.24
raw patch · 2 files changed
+815/−613 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Elf: EST :: (Word32, Maybe ByteString) -> Maybe ElfSection -> ElfSymbolType -> ElfSymbolBinding -> Word8 -> ElfSectionIndex -> Word64 -> Word64 -> ElfSymbolTableEntry
+ Data.Elf: SHNAbs :: ElfSectionIndex
+ Data.Elf: SHNCommon :: ElfSectionIndex
+ Data.Elf: SHNCustomOS :: Word64 -> ElfSectionIndex
+ Data.Elf: SHNCustomProc :: Word64 -> ElfSectionIndex
+ Data.Elf: SHNHiOS :: ElfSectionIndex
+ Data.Elf: SHNHiProc :: ElfSectionIndex
+ Data.Elf: SHNIndex :: Word64 -> ElfSectionIndex
+ Data.Elf: SHNLoOS :: ElfSectionIndex
+ Data.Elf: SHNLoProc :: ElfSectionIndex
+ Data.Elf: SHNUndef :: ElfSectionIndex
+ Data.Elf: STBGlobal :: ElfSymbolBinding
+ Data.Elf: STBHiOS :: ElfSymbolBinding
+ Data.Elf: STBHiProc :: ElfSymbolBinding
+ Data.Elf: STBLoOS :: ElfSymbolBinding
+ Data.Elf: STBLoProc :: ElfSymbolBinding
+ Data.Elf: STBLocal :: ElfSymbolBinding
+ Data.Elf: STBWeak :: ElfSymbolBinding
+ Data.Elf: STTFile :: ElfSymbolType
+ Data.Elf: STTFunc :: ElfSymbolType
+ Data.Elf: STTHiOS :: ElfSymbolType
+ Data.Elf: STTHiProc :: ElfSymbolType
+ Data.Elf: STTLoOS :: ElfSymbolType
+ Data.Elf: STTLoProc :: ElfSymbolType
+ Data.Elf: STTNoType :: ElfSymbolType
+ Data.Elf: STTObject :: ElfSymbolType
+ Data.Elf: STTSection :: ElfSymbolType
+ Data.Elf: data ElfSectionIndex
+ Data.Elf: data ElfSymbolBinding
+ Data.Elf: data ElfSymbolTableEntry
+ Data.Elf: data ElfSymbolType
+ Data.Elf: findSymbolDefinition :: ElfSymbolTableEntry -> Maybe ByteString
+ Data.Elf: instance Enum ElfSectionIndex
+ Data.Elf: instance Enum ElfSymbolBinding
+ Data.Elf: instance Enum ElfSymbolType
+ Data.Elf: instance Eq ElfSectionIndex
+ Data.Elf: instance Eq ElfSymbolBinding
+ Data.Elf: instance Eq ElfSymbolTableEntry
+ Data.Elf: instance Eq ElfSymbolType
+ Data.Elf: instance Ord ElfSectionIndex
+ Data.Elf: instance Ord ElfSymbolBinding
+ Data.Elf: instance Ord ElfSymbolType
+ Data.Elf: instance Read ElfSectionIndex
+ Data.Elf: instance Read ElfSymbolBinding
+ Data.Elf: instance Read ElfSymbolType
+ Data.Elf: instance Show ElfSectionIndex
+ Data.Elf: instance Show ElfSymbolBinding
+ Data.Elf: instance Show ElfSymbolTableEntry
+ Data.Elf: instance Show ElfSymbolType
+ Data.Elf: parseSymbolTables :: Elf -> [[ElfSymbolTableEntry]]
+ Data.Elf: steBind :: ElfSymbolTableEntry -> ElfSymbolBinding
+ Data.Elf: steEnclosingSection :: ElfSymbolTableEntry -> Maybe ElfSection
+ Data.Elf: steIndex :: ElfSymbolTableEntry -> ElfSectionIndex
+ Data.Elf: steName :: ElfSymbolTableEntry -> (Word32, Maybe ByteString)
+ Data.Elf: steOther :: ElfSymbolTableEntry -> Word8
+ Data.Elf: steSize :: ElfSymbolTableEntry -> Word64
+ Data.Elf: steType :: ElfSymbolTableEntry -> ElfSymbolType
+ Data.Elf: steValue :: ElfSymbolTableEntry -> Word64
Files
- elf.cabal +1/−1
- src/Data/Elf.hs +814/−612
elf.cabal view
@@ -1,5 +1,5 @@ Name: elf -Version: 0.23 +Version: 0.24 License: BSD3 License-file: LICENSE Category: Data
src/Data/Elf.hs view
@@ -1,612 +1,814 @@--- | Data.Elf is a module for parsing a ByteString of an ELF file into an Elf record. -module Data.Elf (parseElf - , Elf(..) - , ElfSection(..) - , ElfSectionType(..) - , ElfSectionFlags(..) - , ElfSegment(..) - , ElfSegmentType(..) - , ElfSegmentFlag(..) - , ElfClass(..) - , ElfData(..) - , ElfOSABI(..) - , ElfType(..) - , ElfMachine(..)) where - -import Data.Binary -import Data.Binary.Get -import Data.Bits -import Data.Word -import Numeric -import Control.Monad -import qualified Data.ByteString as B -import qualified Data.ByteString.Internal as B -import qualified Data.ByteString.Lazy as L - -data Elf = Elf - { elfClass :: ElfClass -- ^ Identifies the class of the object file. - , elfData :: ElfData -- ^ Identifies the data encoding of the object file. - , elfVersion :: Int -- ^ Identifies the version of the object file format. - , elfOSABI :: ElfOSABI -- ^ Identifies the operating system and ABI for which the object is prepared. - , elfABIVersion :: Int -- ^ Identifies the ABI version for which the object is prepared. - , elfType :: ElfType -- ^ Identifies the object file type. - , elfMachine :: ElfMachine -- ^ Identifies the target architecture. - , elfEntry :: Word64 -- ^ Virtual address of the program entry point. 0 for non-executable Elfs. - , elfSections :: [ElfSection] -- ^ List of sections in the file. - , elfSegments :: [ElfSegment] -- ^ List of segments in the file. - } deriving (Eq, Show) - -data ElfSection = ElfSection - { elfSectionName :: String -- ^ Identifies the name of the section. - , elfSectionType :: ElfSectionType -- ^ Identifies the type of the section. - , elfSectionFlags :: [ElfSectionFlags] -- ^ Identifies the attributes of the section. - , elfSectionAddr :: Word64 -- ^ The virtual address of the beginning of the section in memory. 0 for sections that are not loaded into target memory. - , elfSectionSize :: Word64 -- ^ The size of the section. Except for SHT_NOBITS sections, this is the size of elfSectionData. - , elfSectionLink :: Word32 -- ^ Contains a section index of an associated section, depending on section type. - , elfSectionInfo :: Word32 -- ^ Contains extra information for the index, depending on type. - , elfSectionAddrAlign :: Word64 -- ^ Contains the required alignment of the section. Must be a power of two. - , elfSectionEntSize :: Word64 -- ^ Size of entries if section has a table. - , elfSectionData :: B.ByteString -- ^ The raw data for the section. - } deriving (Eq, Show) - -getElfMagic = do - ei_magic <- liftM (map B.w2c) $ sequence [getWord8, getWord8, getWord8, getWord8] - if ei_magic /= "\DELELF" then - fail "Invalid magic number for ELF" - else - return ei_magic - -getElfVersion = do - ei_version <- getWord8 - if ei_version /= 1 then - fail "Invalid version number for ELF" - else - return ei_version - -data ElfSectionType - = SHT_NULL -- ^ Identifies an empty section header. - | SHT_PROGBITS -- ^ Contains information defined by the program - | SHT_SYMTAB -- ^ Contains a linker symbol table - | SHT_STRTAB -- ^ Contains a string table - | SHT_RELA -- ^ Contains "Rela" type relocation entries - | SHT_HASH -- ^ Contains a symbol hash table - | SHT_DYNAMIC -- ^ Contains dynamic linking tables - | SHT_NOTE -- ^ Contains note information - | SHT_NOBITS -- ^ Contains uninitialized space; does not occupy any space in the file - | SHT_REL -- ^ Contains "Rel" type relocation entries - | SHT_SHLIB -- ^ Reserved - | SHT_DYNSYM -- ^ Contains a dynamic loader symbol table - | SHT_EXT Word32 -- ^ Processor- or environment-specific type - deriving (Eq, Show) -getElfSectionType er = liftM getElfSectionType_ $ getWord32 er - where getElfSectionType_ 0 = SHT_NULL - getElfSectionType_ 1 = SHT_PROGBITS - getElfSectionType_ 2 = SHT_SYMTAB - getElfSectionType_ 3 = SHT_STRTAB - getElfSectionType_ 4 = SHT_RELA - getElfSectionType_ 5 = SHT_HASH - getElfSectionType_ 6 = SHT_DYNAMIC - getElfSectionType_ 7 = SHT_NOTE - getElfSectionType_ 8 = SHT_NOBITS - getElfSectionType_ 9 = SHT_REL - getElfSectionType_ 10 = SHT_SHLIB - getElfSectionType_ 11 = SHT_DYNSYM - getElfSectionType_ n = SHT_EXT n - -data ElfSectionFlags - = SHF_WRITE -- ^ Section contains writable data - | SHF_ALLOC -- ^ Section is allocated in memory image of program - | SHF_EXECINSTR -- ^ Section contains executable instructions - | SHF_EXT Int -- ^ Processor- or environment-specific flag - deriving (Eq, Show) -getElfSectionFlags 0 word = [] -getElfSectionFlags 1 word | testBit word 0 = SHF_WRITE : getElfSectionFlags 0 word -getElfSectionFlags 2 word | testBit word 1 = SHF_ALLOC : getElfSectionFlags 1 word -getElfSectionFlags 3 word | testBit word 2 = SHF_EXECINSTR : getElfSectionFlags 2 word -getElfSectionFlags n word | testBit word (n-1) = SHF_EXT (n-1) : getElfSectionFlags (n-1) word -getElfSectionFlags n word = getElfSectionFlags (n-1) word -getElfSectionFlags32 = liftM (getElfSectionFlags 32) . getWord32 -getElfSectionFlags64 = liftM (getElfSectionFlags 64) . getWord64 - -data ElfClass - = ELFCLASS32 -- ^ 32-bit ELF format - | ELFCLASS64 -- ^ 64-bit ELF format - deriving (Eq, Show) -getElfClass = getWord8 >>= getElfClass_ - where getElfClass_ 1 = return ELFCLASS32 - getElfClass_ 2 = return ELFCLASS64 - getElfClass_ _ = fail "Invalid ELF class" - -data ElfData - = ELFDATA2LSB -- ^ Little-endian ELF format - | ELFDATA2MSB -- ^ Big-endian ELF format - deriving (Eq, Show) -getElfData = getWord8 >>= getElfData_ - where getElfData_ 1 = return ELFDATA2LSB - getElfData_ 2 = return ELFDATA2MSB - getElfData_ _ = fail "Invalid ELF data" - -data ElfOSABI - = ELFOSABI_SYSV -- ^ No extensions or unspecified - | ELFOSABI_HPUX -- ^ Hewlett-Packard HP-UX - | ELFOSABI_NETBSD -- ^ NetBSD - | ELFOSABI_LINUX -- ^ Linux - | ELFOSABI_SOLARIS -- ^ Sun Solaris - | ELFOSABI_AIX -- ^ AIX - | ELFOSABI_IRIX -- ^ IRIX - | ELFOSABI_FREEBSD -- ^ FreeBSD - | ELFOSABI_TRU64 -- ^ Compaq TRU64 UNIX - | ELFOSABI_MODESTO -- ^ Novell Modesto - | ELFOSABI_OPENBSD -- ^ Open BSD - | ELFOSABI_OPENVMS -- ^ Open VMS - | ELFOSABI_NSK -- ^ Hewlett-Packard Non-Stop Kernel - | ELFOSABI_AROS -- ^ Amiga Research OS - | ELFOSABI_ARM -- ^ ARM - | ELFOSABI_STANDALONE -- ^ Standalone (embedded) application - | ELFOSABI_EXT Word8 -- ^ Other - deriving (Eq, Show) -getElfOsabi = liftM getElfOsabi_ getWord8 - where getElfOsabi_ 0 = ELFOSABI_SYSV - getElfOsabi_ 1 = ELFOSABI_HPUX - getElfOsabi_ 2 = ELFOSABI_NETBSD - getElfOsabi_ 3 = ELFOSABI_LINUX - getElfOsabi_ 6 = ELFOSABI_SOLARIS - getElfOsabi_ 7 = ELFOSABI_AIX - getElfOsabi_ 8 = ELFOSABI_IRIX - getElfOsabi_ 9 = ELFOSABI_FREEBSD - getElfOsabi_ 10 = ELFOSABI_TRU64 - getElfOsabi_ 11 = ELFOSABI_MODESTO - getElfOsabi_ 12 = ELFOSABI_OPENBSD - getElfOsabi_ 13 = ELFOSABI_OPENVMS - getElfOsabi_ 14 = ELFOSABI_NSK - getElfOsabi_ 15 = ELFOSABI_AROS - getElfOsabi_ 97 = ELFOSABI_ARM - getElfOsabi_ 255 = ELFOSABI_STANDALONE - getElfOsabi_ n = ELFOSABI_EXT n - -data ElfType - = ET_NONE -- ^ Unspecified type - | ET_REL -- ^ Relocatable object file - | ET_EXEC -- ^ Executable object file - | ET_DYN -- ^ Shared object file - | ET_CORE -- ^ Core dump object file - | ET_EXT Word16 -- ^ Other - deriving (Eq, Show) -getElfType = liftM getElfType_ . getWord16 - where getElfType_ 0 = ET_NONE - getElfType_ 1 = ET_REL - getElfType_ 2 = ET_EXEC - getElfType_ 3 = ET_DYN - getElfType_ 4 = ET_CORE - getElfType_ n = ET_EXT n - -data ElfMachine - = EM_NONE -- ^ No machine - | EM_M32 -- ^ AT&T WE 32100 - | EM_SPARC -- ^ SPARC - | EM_386 -- ^ Intel 80386 - | EM_68K -- ^ Motorola 68000 - | EM_88K -- ^ Motorola 88000 - | EM_486 -- ^ Intel i486 (DO NOT USE THIS ONE) - | EM_860 -- ^ Intel 80860 - | EM_MIPS -- ^ MIPS I Architecture - | EM_S370 -- ^ IBM System/370 Processor - | EM_MIPS_RS3_LE -- ^ MIPS RS3000 Little-endian - | EM_SPARC64 -- ^ SPARC 64-bit - | EM_PARISC -- ^ Hewlett-Packard PA-RISC - | EM_VPP500 -- ^ Fujitsu VPP500 - | EM_SPARC32PLUS -- ^ Enhanced instruction set SPARC - | EM_960 -- ^ Intel 80960 - | EM_PPC -- ^ PowerPC - | EM_PPC64 -- ^ 64-bit PowerPC - | EM_S390 -- ^ IBM System/390 Processor - | EM_SPU -- ^ Cell SPU - | EM_V800 -- ^ NEC V800 - | EM_FR20 -- ^ Fujitsu FR20 - | EM_RH32 -- ^ TRW RH-32 - | EM_RCE -- ^ Motorola RCE - | EM_ARM -- ^ Advanced RISC Machines ARM - | EM_ALPHA -- ^ Digital Alpha - | EM_SH -- ^ Hitachi SH - | EM_SPARCV9 -- ^ SPARC Version 9 - | EM_TRICORE -- ^ Siemens TriCore embedded processor - | EM_ARC -- ^ Argonaut RISC Core, Argonaut Technologies Inc. - | EM_H8_300 -- ^ Hitachi H8/300 - | EM_H8_300H -- ^ Hitachi H8/300H - | EM_H8S -- ^ Hitachi H8S - | EM_H8_500 -- ^ Hitachi H8/500 - | EM_IA_64 -- ^ Intel IA-64 processor architecture - | EM_MIPS_X -- ^ Stanford MIPS-X - | EM_COLDFIRE -- ^ Motorola ColdFire - | EM_68HC12 -- ^ Motorola M68HC12 - | EM_MMA -- ^ Fujitsu MMA Multimedia Accelerator - | EM_PCP -- ^ Siemens PCP - | EM_NCPU -- ^ Sony nCPU embedded RISC processor - | EM_NDR1 -- ^ Denso NDR1 microprocessor - | EM_STARCORE -- ^ Motorola Star*Core processor - | EM_ME16 -- ^ Toyota ME16 processor - | EM_ST100 -- ^ STMicroelectronics ST100 processor - | EM_TINYJ -- ^ Advanced Logic Corp. TinyJ embedded processor family - | EM_X86_64 -- ^ AMD x86-64 architecture - | EM_PDSP -- ^ Sony DSP Processor - | EM_FX66 -- ^ Siemens FX66 microcontroller - | EM_ST9PLUS -- ^ STMicroelectronics ST9+ 8/16 bit microcontroller - | EM_ST7 -- ^ STMicroelectronics ST7 8-bit microcontroller - | EM_68HC16 -- ^ Motorola MC68HC16 Microcontroller - | EM_68HC11 -- ^ Motorola MC68HC11 Microcontroller - | EM_68HC08 -- ^ Motorola MC68HC08 Microcontroller - | EM_68HC05 -- ^ Motorola MC68HC05 Microcontroller - | EM_SVX -- ^ Silicon Graphics SVx - | EM_ST19 -- ^ STMicroelectronics ST19 8-bit microcontroller - | EM_VAX -- ^ Digital VAX - | EM_CRIS -- ^ Axis Communications 32-bit embedded processor - | EM_JAVELIN -- ^ Infineon Technologies 32-bit embedded processor - | EM_FIREPATH -- ^ Element 14 64-bit DSP Processor - | EM_ZSP -- ^ LSI Logic 16-bit DSP Processor - | EM_MMIX -- ^ Donald Knuth's educational 64-bit processor - | EM_HUANY -- ^ Harvard University machine-independent object files - | EM_PRISM -- ^ SiTera Prism - | EM_AVR -- ^ Atmel AVR 8-bit microcontroller - | EM_FR30 -- ^ Fujitsu FR30 - | EM_D10V -- ^ Mitsubishi D10V - | EM_D30V -- ^ Mitsubishi D30V - | EM_V850 -- ^ NEC v850 - | EM_M32R -- ^ Mitsubishi M32R - | EM_MN10300 -- ^ Matsushita MN10300 - | EM_MN10200 -- ^ Matsushita MN10200 - | EM_PJ -- ^ picoJava - | EM_OPENRISC -- ^ OpenRISC 32-bit embedded processor - | EM_ARC_A5 -- ^ ARC Cores Tangent-A5 - | EM_XTENSA -- ^ Tensilica Xtensa Architecture - | EM_VIDEOCORE -- ^ Alphamosaic VideoCore processor - | EM_TMM_GPP -- ^ Thompson Multimedia General Purpose Processor - | EM_NS32K -- ^ National Semiconductor 32000 series - | EM_TPC -- ^ Tenor Network TPC processor - | EM_SNP1K -- ^ Trebia SNP 1000 processor - | EM_ST200 -- ^ STMicroelectronics (www.st.com) ST200 microcontroller - | EM_IP2K -- ^ Ubicom IP2xxx microcontroller family - | EM_MAX -- ^ MAX Processor - | EM_CR -- ^ National Semiconductor CompactRISC microprocessor - | EM_F2MC16 -- ^ Fujitsu F2MC16 - | EM_MSP430 -- ^ Texas Instruments embedded microcontroller msp430 - | EM_BLACKFIN -- ^ Analog Devices Blackfin (DSP) processor - | EM_SE_C33 -- ^ S1C33 Family of Seiko Epson processors - | EM_SEP -- ^ Sharp embedded microprocessor - | EM_ARCA -- ^ Arca RISC Microprocessor - | EM_UNICORE -- ^ Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University - | EM_EXT Word16 -- ^ Other - deriving (Eq, Show) -getElfMachine = liftM getElfMachine_ . getWord16 - where getElfMachine_ 0 = EM_NONE - getElfMachine_ 1 = EM_M32 - getElfMachine_ 2 = EM_SPARC - getElfMachine_ 3 = EM_386 - getElfMachine_ 4 = EM_68K - getElfMachine_ 5 = EM_88K - getElfMachine_ 6 = EM_486 - getElfMachine_ 7 = EM_860 - getElfMachine_ 8 = EM_MIPS - getElfMachine_ 9 = EM_S370 - getElfMachine_ 10 = EM_MIPS_RS3_LE - getElfMachine_ 11 = EM_SPARC64 - getElfMachine_ 15 = EM_PARISC - getElfMachine_ 17 = EM_VPP500 - getElfMachine_ 18 = EM_SPARC32PLUS - getElfMachine_ 19 = EM_960 - getElfMachine_ 20 = EM_PPC - getElfMachine_ 21 = EM_PPC64 - getElfMachine_ 22 = EM_S390 - getElfMachine_ 23 = EM_SPU - getElfMachine_ 36 = EM_V800 - getElfMachine_ 37 = EM_FR20 - getElfMachine_ 38 = EM_RH32 - getElfMachine_ 39 = EM_RCE - getElfMachine_ 40 = EM_ARM - getElfMachine_ 41 = EM_ALPHA - getElfMachine_ 42 = EM_SH - getElfMachine_ 43 = EM_SPARCV9 - getElfMachine_ 44 = EM_TRICORE - getElfMachine_ 45 = EM_ARC - getElfMachine_ 46 = EM_H8_300 - getElfMachine_ 47 = EM_H8_300H - getElfMachine_ 48 = EM_H8S - getElfMachine_ 49 = EM_H8_500 - getElfMachine_ 50 = EM_IA_64 - getElfMachine_ 51 = EM_MIPS_X - getElfMachine_ 52 = EM_COLDFIRE - getElfMachine_ 53 = EM_68HC12 - getElfMachine_ 54 = EM_MMA - getElfMachine_ 55 = EM_PCP - getElfMachine_ 56 = EM_NCPU - getElfMachine_ 57 = EM_NDR1 - getElfMachine_ 58 = EM_STARCORE - getElfMachine_ 59 = EM_ME16 - getElfMachine_ 60 = EM_ST100 - getElfMachine_ 61 = EM_TINYJ - getElfMachine_ 62 = EM_X86_64 - getElfMachine_ 63 = EM_PDSP - getElfMachine_ 66 = EM_FX66 - getElfMachine_ 67 = EM_ST9PLUS - getElfMachine_ 68 = EM_ST7 - getElfMachine_ 69 = EM_68HC16 - getElfMachine_ 70 = EM_68HC11 - getElfMachine_ 71 = EM_68HC08 - getElfMachine_ 72 = EM_68HC05 - getElfMachine_ 73 = EM_SVX - getElfMachine_ 74 = EM_ST19 - getElfMachine_ 75 = EM_VAX - getElfMachine_ 76 = EM_CRIS - getElfMachine_ 77 = EM_JAVELIN - getElfMachine_ 78 = EM_FIREPATH - getElfMachine_ 79 = EM_ZSP - getElfMachine_ 80 = EM_MMIX - getElfMachine_ 81 = EM_HUANY - getElfMachine_ 82 = EM_PRISM - getElfMachine_ 83 = EM_AVR - getElfMachine_ 84 = EM_FR30 - getElfMachine_ 85 = EM_D10V - getElfMachine_ 86 = EM_D30V - getElfMachine_ 87 = EM_V850 - getElfMachine_ 88 = EM_M32R - getElfMachine_ 89 = EM_MN10300 - getElfMachine_ 90 = EM_MN10200 - getElfMachine_ 91 = EM_PJ - getElfMachine_ 92 = EM_OPENRISC - getElfMachine_ 93 = EM_ARC_A5 - getElfMachine_ 94 = EM_XTENSA - getElfMachine_ 95 = EM_VIDEOCORE - getElfMachine_ 96 = EM_TMM_GPP - getElfMachine_ 97 = EM_NS32K - getElfMachine_ 98 = EM_TPC - getElfMachine_ 99 = EM_SNP1K - getElfMachine_ 100 = EM_ST200 - getElfMachine_ 101 = EM_IP2K - getElfMachine_ 102 = EM_MAX - getElfMachine_ 103 = EM_CR - getElfMachine_ 104 = EM_F2MC16 - getElfMachine_ 105 = EM_MSP430 - getElfMachine_ 106 = EM_BLACKFIN - getElfMachine_ 107 = EM_SE_C33 - getElfMachine_ 108 = EM_SEP - getElfMachine_ 109 = EM_ARCA - getElfMachine_ 110 = EM_UNICORE - getElfMachine_ n = EM_EXT n - -getElf_Shdr_OffsetSize :: ElfClass -> ElfReader -> Get (Word64, Word64) -getElf_Shdr_OffsetSize ei_class er = - case ei_class of - ELFCLASS32 -> do - skip 16 - sh_offset <- liftM fromIntegral $ getWord32 er - sh_size <- liftM fromIntegral $ getWord32 er - return (sh_offset, sh_size) - ELFCLASS64 -> do - skip 24 - sh_offset <- getWord64 er - sh_size <- getWord64 er - return (sh_offset, sh_size) - -getElf_Shdr :: ElfClass -> ElfReader -> B.ByteString -> B.ByteString -> Get ElfSection -getElf_Shdr ei_class er elf_file string_section = - case ei_class of - ELFCLASS32 -> do - sh_name <- getWord32 er - sh_type <- getElfSectionType er - sh_flags <- getElfSectionFlags32 er - sh_addr <- getWord32 er - sh_offset <- getWord32 er - sh_size <- getWord32 er - sh_link <- getWord32 er - sh_info <- getWord32 er - sh_addralign <- getWord32 er - sh_entsize <- getWord32 er - return ElfSection - { elfSectionName = map B.w2c $ B.unpack $ B.takeWhile (/= 0) $ B.drop (fromIntegral sh_name) string_section - , elfSectionType = sh_type - , elfSectionFlags = sh_flags - , elfSectionAddr = fromIntegral sh_addr - , elfSectionSize = fromIntegral sh_size - , elfSectionLink = sh_link - , elfSectionInfo = sh_info - , elfSectionAddrAlign = fromIntegral sh_addralign - , elfSectionEntSize = fromIntegral sh_entsize - , elfSectionData = B.take (fromIntegral sh_size) $ B.drop (fromIntegral sh_offset) elf_file - } - ELFCLASS64 -> do - sh_name <- getWord32 er - sh_type <- getElfSectionType er - sh_flags <- getElfSectionFlags64 er - sh_addr <- getWord64 er - sh_offset <- getWord64 er - sh_size <- getWord64 er - sh_link <- getWord32 er - sh_info <- getWord32 er - sh_addralign <- getWord64 er - sh_entsize <- getWord64 er - return ElfSection - { elfSectionName = map B.w2c $ B.unpack $ B.takeWhile (/= 0) $ B.drop (fromIntegral sh_name) string_section - , elfSectionType = sh_type - , elfSectionFlags = sh_flags - , elfSectionAddr = sh_addr - , elfSectionSize = sh_size - , elfSectionLink = sh_link - , elfSectionInfo = sh_info - , elfSectionAddrAlign = sh_addralign - , elfSectionEntSize = sh_entsize - , elfSectionData = B.take (fromIntegral sh_size) $ B.drop (fromIntegral sh_offset) elf_file - } - -data TableInfo = TableInfo { tableOffset :: Int, entrySize :: Int, entryNum :: Int } - -getElf_Ehdr :: Get (Elf, TableInfo, TableInfo, Word16) -getElf_Ehdr = do - ei_magic <- getElfMagic - ei_class <- getElfClass - ei_data <- getElfData - ei_version <- liftM fromIntegral getElfVersion - ei_osabi <- getElfOsabi - ei_abiver <- liftM fromIntegral getWord8 - skip 7 - er <- return $ elfReader ei_data - case ei_class of - ELFCLASS32 -> do - e_type <- getElfType er - e_machine <- getElfMachine er - e_version <- getWord32 er - e_entry <- liftM fromIntegral $ getWord32 er - e_phoff <- getWord32 er - e_shoff <- liftM fromIntegral $ getWord32 er - e_flags <- getWord32 er - e_ehsize <- getWord16 er - e_phentsize <- getWord16 er - e_phnum <- getWord16 er - e_shentsize <- getWord16 er - e_shnum <- getWord16 er - e_shstrndx <- getWord16 er - return (Elf { elfClass = ei_class - , elfData = ei_data - , elfVersion = ei_version - , elfOSABI = ei_osabi - , elfABIVersion = ei_abiver - , elfType = e_type - , elfMachine = e_machine - , elfEntry = e_entry - , elfSections = [] - , elfSegments = [] } - , TableInfo { tableOffset = fromIntegral e_phoff, entrySize = fromIntegral e_phentsize, entryNum = fromIntegral e_phnum } - , TableInfo { tableOffset = fromIntegral e_shoff, entrySize = fromIntegral e_shentsize, entryNum = fromIntegral e_shnum } - , e_shstrndx) - ELFCLASS64 -> do - e_type <- getElfType er - e_machine <- getElfMachine er - e_version <- getWord32 er - e_entry <- getWord64 er - e_phoff <- getWord64 er - e_shoff <- getWord64 er - e_flags <- getWord32 er - e_ehsize <- getWord16 er - e_phentsize <- getWord16 er - e_phnum <- getWord16 er - e_shentsize <- getWord16 er - e_shnum <- getWord16 er - e_shstrndx <- getWord16 er - return (Elf { elfClass = ei_class - , elfData = ei_data - , elfVersion = ei_version - , elfOSABI = ei_osabi - , elfABIVersion = ei_abiver - , elfType = e_type - , elfMachine = e_machine - , elfEntry = e_entry - , elfSections = [] - , elfSegments = [] } - , TableInfo { tableOffset = fromIntegral e_phoff, entrySize = fromIntegral e_phentsize, entryNum = fromIntegral e_phnum } - , TableInfo { tableOffset = fromIntegral e_shoff, entrySize = fromIntegral e_shentsize, entryNum = fromIntegral e_shnum } - , e_shstrndx) - -data ElfReader = ElfReader - { getWord16 :: Get Word16 - , getWord32 :: Get Word32 - , getWord64 :: Get Word64 - } -elfReader ELFDATA2LSB = ElfReader { getWord16 = getWord16le, getWord32 = getWord32le, getWord64 = getWord64le } -elfReader ELFDATA2MSB = ElfReader { getWord16 = getWord16be, getWord32 = getWord32be, getWord64 = getWord64be } - -divide :: B.ByteString -> Int -> Int -> [B.ByteString] -divide bs s 0 = [] -divide bs s n = let (x,y) = B.splitAt s bs in x : divide y s (n-1) - --- | Parses a ByteString into an Elf record. Parse failures call error. 32-bit ELF objects have their --- fields promoted to 64-bit so that the 32- and 64-bit ELF records can be the same. -parseElf :: B.ByteString -> Elf -parseElf b = - let ph = table segTab - sh = table secTab - (shstroff, shstrsize) = parseEntry getElf_Shdr_OffsetSize $ head $ drop (fromIntegral e_shstrndx) sh - sh_str = B.take (fromIntegral shstrsize) $ B.drop (fromIntegral shstroff) b - segments = filter (\seg -> elfSegmentType seg /= PT_NULL) $ map (parseEntry (\c r -> parseElfSegmentEntry c r b)) ph - sections = filter (\sec -> elfSectionType sec /= SHT_NULL) $ map (parseEntry (\c r -> getElf_Shdr c r b sh_str)) sh - in e { elfSections = sections, elfSegments = segments } - - where table i = divide (B.drop (tableOffset i) b) (entrySize i) (entryNum i) - parseEntry p x = runGet (p (elfClass e) (elfReader (elfData e))) (L.fromChunks [x]) - (e, segTab, secTab, e_shstrndx) = runGet getElf_Ehdr $ L.fromChunks [b] - - -data ElfSegment = ElfSegment - { elfSegmentType :: ElfSegmentType -- ^ Segment type - , elfSegmentFlags :: [ElfSegmentFlag] -- ^ Segment flags - , elfSegmentVirtAddr :: Word64 -- ^ Virtual address for the segment - , elfSegmentPhysAddr :: Word64 -- ^ Physical address for the segment - , elfSegmentAlign :: Word64 -- ^ Segment alignment - , elfSegmentData :: B.ByteString -- ^ Data for the segment - , elfSegmentMemSize :: Word64 -- ^ Size in memory (may be larger then the segment's data) - } deriving (Eq,Show) - --- | Segment Types. -data ElfSegmentType - = PT_NULL -- ^ Unused entry - | PT_LOAD -- ^ Loadable segment - | PT_DYNAMIC -- ^ Dynamic linking tables - | PT_INTERP -- ^ Program interpreter path name - | PT_NOTE -- ^ Note sectionks - | PT_SHLIB -- ^ Reserved - | PT_PHDR -- ^ Program header table - | PT_Other Word32 -- ^ Some other type - deriving (Eq,Show) - -parseElfSegmentType :: Word32 -> ElfSegmentType -parseElfSegmentType x = - case x of - 0 -> PT_NULL - 1 -> PT_LOAD - 2 -> PT_DYNAMIC - 3 -> PT_INTERP - 4 -> PT_NOTE - 5 -> PT_SHLIB - 6 -> PT_PHDR - _ -> PT_Other x - - -parseElfSegmentEntry :: ElfClass -> ElfReader -> B.ByteString -> Get ElfSegment -parseElfSegmentEntry elf_class er elf_file = - do p_type <- parseElfSegmentType `fmap` getWord32 er - p_flags <- parseElfSegmentFlags `fmap` getWord32 er - p_offset <- getWord - p_vaddr <- getWord - p_paddr <- getWord - p_filesz <- getWord - p_memsz <- getWord - p_align <- getWord - return ElfSegment - { elfSegmentType = p_type - , elfSegmentFlags = p_flags - , elfSegmentVirtAddr = p_vaddr - , elfSegmentPhysAddr = p_paddr - , elfSegmentAlign = p_align - , elfSegmentData = B.take (fromIntegral p_filesz) $ B.drop (fromIntegral p_offset) elf_file - , elfSegmentMemSize = p_memsz - } - - where getWord = case elf_class of - ELFCLASS64 -> getWord64 er - ELFCLASS32 -> fromIntegral `fmap` getWord32 er - - -data ElfSegmentFlag - = PF_X -- ^ Execute permission - | PF_W -- ^ Write permission - | PF_R -- ^ Read permission - | PF_Ext Int -- ^ Some other flag, the Int is the bit number for the flag. - deriving (Eq,Show) - -parseElfSegmentFlags :: Word32 -> [ElfSegmentFlag] -parseElfSegmentFlags word = [ cvt bit | bit <- [ 0 .. 31 ], testBit word bit ] - where cvt 0 = PF_X - cvt 1 = PF_W - cvt 2 = PF_R - cvt n = PF_Ext n - - - - +-- | Data.Elf is a module for parsing a ByteString of an ELF file into an Elf record.+module Data.Elf ( parseElf+ , parseSymbolTables+ , findSymbolDefinition+ , Elf(..)+ , ElfSection(..)+ , ElfSectionType(..)+ , ElfSectionFlags(..)+ , ElfSegment(..)+ , ElfSegmentType(..)+ , ElfSegmentFlag(..)+ , ElfClass(..)+ , ElfData(..)+ , ElfOSABI(..)+ , ElfType(..)+ , ElfMachine(..)+ , ElfSymbolTableEntry(..)+ , ElfSymbolType(..)+ , ElfSymbolBinding(..)+ , ElfSectionIndex(..)) where++import Data.Binary+import Data.Binary.Get as G+import Data.Bits+import Data.Maybe+import Data.Word+import Numeric+import Control.Monad+import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B+import qualified Data.ByteString.Lazy as L++data Elf = Elf+ { elfClass :: ElfClass -- ^ Identifies the class of the object file.+ , elfData :: ElfData -- ^ Identifies the data encoding of the object file.+ , elfVersion :: Int -- ^ Identifies the version of the object file format.+ , elfOSABI :: ElfOSABI -- ^ Identifies the operating system and ABI for which the object is prepared.+ , elfABIVersion :: Int -- ^ Identifies the ABI version for which the object is prepared.+ , elfType :: ElfType -- ^ Identifies the object file type.+ , elfMachine :: ElfMachine -- ^ Identifies the target architecture.+ , elfEntry :: Word64 -- ^ Virtual address of the program entry point. 0 for non-executable Elfs.+ , elfSections :: [ElfSection] -- ^ List of sections in the file.+ , elfSegments :: [ElfSegment] -- ^ List of segments in the file.+ } deriving (Eq, Show)++data ElfSection = ElfSection+ { elfSectionName :: String -- ^ Identifies the name of the section.+ , elfSectionType :: ElfSectionType -- ^ Identifies the type of the section.+ , elfSectionFlags :: [ElfSectionFlags] -- ^ Identifies the attributes of the section.+ , elfSectionAddr :: Word64 -- ^ The virtual address of the beginning of the section in memory. 0 for sections that are not loaded into target memory.+ , elfSectionSize :: Word64 -- ^ The size of the section. Except for SHT_NOBITS sections, this is the size of elfSectionData.+ , elfSectionLink :: Word32 -- ^ Contains a section index of an associated section, depending on section type.+ , elfSectionInfo :: Word32 -- ^ Contains extra information for the index, depending on type.+ , elfSectionAddrAlign :: Word64 -- ^ Contains the required alignment of the section. Must be a power of two.+ , elfSectionEntSize :: Word64 -- ^ Size of entries if section has a table.+ , elfSectionData :: B.ByteString -- ^ The raw data for the section.+ } deriving (Eq, Show)++getElfMagic = do+ ei_magic <- liftM (map B.w2c) $ sequence [getWord8, getWord8, getWord8, getWord8]+ if ei_magic /= "\DELELF" then+ fail "Invalid magic number for ELF"+ else+ return ei_magic++getElfVersion = do+ ei_version <- getWord8+ if ei_version /= 1 then+ fail "Invalid version number for ELF"+ else+ return ei_version++data ElfSectionType+ = SHT_NULL -- ^ Identifies an empty section header.+ | SHT_PROGBITS -- ^ Contains information defined by the program+ | SHT_SYMTAB -- ^ Contains a linker symbol table+ | SHT_STRTAB -- ^ Contains a string table+ | SHT_RELA -- ^ Contains "Rela" type relocation entries+ | SHT_HASH -- ^ Contains a symbol hash table+ | SHT_DYNAMIC -- ^ Contains dynamic linking tables+ | SHT_NOTE -- ^ Contains note information+ | SHT_NOBITS -- ^ Contains uninitialized space; does not occupy any space in the file+ | SHT_REL -- ^ Contains "Rel" type relocation entries+ | SHT_SHLIB -- ^ Reserved+ | SHT_DYNSYM -- ^ Contains a dynamic loader symbol table+ | SHT_EXT Word32 -- ^ Processor- or environment-specific type+ deriving (Eq, Show)+getElfSectionType er = liftM getElfSectionType_ $ getWord32 er+ where getElfSectionType_ 0 = SHT_NULL+ getElfSectionType_ 1 = SHT_PROGBITS+ getElfSectionType_ 2 = SHT_SYMTAB+ getElfSectionType_ 3 = SHT_STRTAB+ getElfSectionType_ 4 = SHT_RELA+ getElfSectionType_ 5 = SHT_HASH+ getElfSectionType_ 6 = SHT_DYNAMIC+ getElfSectionType_ 7 = SHT_NOTE+ getElfSectionType_ 8 = SHT_NOBITS+ getElfSectionType_ 9 = SHT_REL+ getElfSectionType_ 10 = SHT_SHLIB+ getElfSectionType_ 11 = SHT_DYNSYM+ getElfSectionType_ n = SHT_EXT n++data ElfSectionFlags+ = SHF_WRITE -- ^ Section contains writable data+ | SHF_ALLOC -- ^ Section is allocated in memory image of program+ | SHF_EXECINSTR -- ^ Section contains executable instructions+ | SHF_EXT Int -- ^ Processor- or environment-specific flag+ deriving (Eq, Show)+getElfSectionFlags 0 word = []+getElfSectionFlags 1 word | testBit word 0 = SHF_WRITE : getElfSectionFlags 0 word+getElfSectionFlags 2 word | testBit word 1 = SHF_ALLOC : getElfSectionFlags 1 word+getElfSectionFlags 3 word | testBit word 2 = SHF_EXECINSTR : getElfSectionFlags 2 word+getElfSectionFlags n word | testBit word (n-1) = SHF_EXT (n-1) : getElfSectionFlags (n-1) word+getElfSectionFlags n word = getElfSectionFlags (n-1) word+getElfSectionFlags32 = liftM (getElfSectionFlags 32) . getWord32 +getElfSectionFlags64 = liftM (getElfSectionFlags 64) . getWord64+ +data ElfClass+ = ELFCLASS32 -- ^ 32-bit ELF format+ | ELFCLASS64 -- ^ 64-bit ELF format+ deriving (Eq, Show)+getElfClass = getWord8 >>= getElfClass_+ where getElfClass_ 1 = return ELFCLASS32+ getElfClass_ 2 = return ELFCLASS64+ getElfClass_ _ = fail "Invalid ELF class"++data ElfData+ = ELFDATA2LSB -- ^ Little-endian ELF format+ | ELFDATA2MSB -- ^ Big-endian ELF format+ deriving (Eq, Show)+getElfData = getWord8 >>= getElfData_+ where getElfData_ 1 = return ELFDATA2LSB+ getElfData_ 2 = return ELFDATA2MSB+ getElfData_ _ = fail "Invalid ELF data"++data ElfOSABI+ = ELFOSABI_SYSV -- ^ No extensions or unspecified+ | ELFOSABI_HPUX -- ^ Hewlett-Packard HP-UX+ | ELFOSABI_NETBSD -- ^ NetBSD+ | ELFOSABI_LINUX -- ^ Linux+ | ELFOSABI_SOLARIS -- ^ Sun Solaris+ | ELFOSABI_AIX -- ^ AIX+ | ELFOSABI_IRIX -- ^ IRIX+ | ELFOSABI_FREEBSD -- ^ FreeBSD+ | ELFOSABI_TRU64 -- ^ Compaq TRU64 UNIX+ | ELFOSABI_MODESTO -- ^ Novell Modesto+ | ELFOSABI_OPENBSD -- ^ Open BSD+ | ELFOSABI_OPENVMS -- ^ Open VMS+ | ELFOSABI_NSK -- ^ Hewlett-Packard Non-Stop Kernel+ | ELFOSABI_AROS -- ^ Amiga Research OS+ | ELFOSABI_ARM -- ^ ARM+ | ELFOSABI_STANDALONE -- ^ Standalone (embedded) application+ | ELFOSABI_EXT Word8 -- ^ Other+ deriving (Eq, Show)+getElfOsabi = liftM getElfOsabi_ getWord8+ where getElfOsabi_ 0 = ELFOSABI_SYSV+ getElfOsabi_ 1 = ELFOSABI_HPUX+ getElfOsabi_ 2 = ELFOSABI_NETBSD+ getElfOsabi_ 3 = ELFOSABI_LINUX+ getElfOsabi_ 6 = ELFOSABI_SOLARIS+ getElfOsabi_ 7 = ELFOSABI_AIX+ getElfOsabi_ 8 = ELFOSABI_IRIX+ getElfOsabi_ 9 = ELFOSABI_FREEBSD+ getElfOsabi_ 10 = ELFOSABI_TRU64+ getElfOsabi_ 11 = ELFOSABI_MODESTO+ getElfOsabi_ 12 = ELFOSABI_OPENBSD+ getElfOsabi_ 13 = ELFOSABI_OPENVMS+ getElfOsabi_ 14 = ELFOSABI_NSK+ getElfOsabi_ 15 = ELFOSABI_AROS+ getElfOsabi_ 97 = ELFOSABI_ARM+ getElfOsabi_ 255 = ELFOSABI_STANDALONE+ getElfOsabi_ n = ELFOSABI_EXT n++data ElfType+ = ET_NONE -- ^ Unspecified type+ | ET_REL -- ^ Relocatable object file+ | ET_EXEC -- ^ Executable object file+ | ET_DYN -- ^ Shared object file+ | ET_CORE -- ^ Core dump object file+ | ET_EXT Word16 -- ^ Other+ deriving (Eq, Show)+getElfType = liftM getElfType_ . getWord16+ where getElfType_ 0 = ET_NONE+ getElfType_ 1 = ET_REL+ getElfType_ 2 = ET_EXEC+ getElfType_ 3 = ET_DYN+ getElfType_ 4 = ET_CORE+ getElfType_ n = ET_EXT n++data ElfMachine+ = EM_NONE -- ^ No machine+ | EM_M32 -- ^ AT&T WE 32100+ | EM_SPARC -- ^ SPARC+ | EM_386 -- ^ Intel 80386+ | EM_68K -- ^ Motorola 68000+ | EM_88K -- ^ Motorola 88000+ | EM_486 -- ^ Intel i486 (DO NOT USE THIS ONE)+ | EM_860 -- ^ Intel 80860+ | EM_MIPS -- ^ MIPS I Architecture+ | EM_S370 -- ^ IBM System/370 Processor+ | EM_MIPS_RS3_LE -- ^ MIPS RS3000 Little-endian+ | EM_SPARC64 -- ^ SPARC 64-bit+ | EM_PARISC -- ^ Hewlett-Packard PA-RISC+ | EM_VPP500 -- ^ Fujitsu VPP500+ | EM_SPARC32PLUS -- ^ Enhanced instruction set SPARC+ | EM_960 -- ^ Intel 80960+ | EM_PPC -- ^ PowerPC+ | EM_PPC64 -- ^ 64-bit PowerPC+ | EM_S390 -- ^ IBM System/390 Processor+ | EM_SPU -- ^ Cell SPU+ | EM_V800 -- ^ NEC V800+ | EM_FR20 -- ^ Fujitsu FR20+ | EM_RH32 -- ^ TRW RH-32+ | EM_RCE -- ^ Motorola RCE+ | EM_ARM -- ^ Advanced RISC Machines ARM+ | EM_ALPHA -- ^ Digital Alpha+ | EM_SH -- ^ Hitachi SH+ | EM_SPARCV9 -- ^ SPARC Version 9+ | EM_TRICORE -- ^ Siemens TriCore embedded processor+ | EM_ARC -- ^ Argonaut RISC Core, Argonaut Technologies Inc.+ | EM_H8_300 -- ^ Hitachi H8/300+ | EM_H8_300H -- ^ Hitachi H8/300H+ | EM_H8S -- ^ Hitachi H8S+ | EM_H8_500 -- ^ Hitachi H8/500+ | EM_IA_64 -- ^ Intel IA-64 processor architecture+ | EM_MIPS_X -- ^ Stanford MIPS-X+ | EM_COLDFIRE -- ^ Motorola ColdFire+ | EM_68HC12 -- ^ Motorola M68HC12+ | EM_MMA -- ^ Fujitsu MMA Multimedia Accelerator+ | EM_PCP -- ^ Siemens PCP+ | EM_NCPU -- ^ Sony nCPU embedded RISC processor+ | EM_NDR1 -- ^ Denso NDR1 microprocessor+ | EM_STARCORE -- ^ Motorola Star*Core processor+ | EM_ME16 -- ^ Toyota ME16 processor+ | EM_ST100 -- ^ STMicroelectronics ST100 processor+ | EM_TINYJ -- ^ Advanced Logic Corp. TinyJ embedded processor family+ | EM_X86_64 -- ^ AMD x86-64 architecture+ | EM_PDSP -- ^ Sony DSP Processor+ | EM_FX66 -- ^ Siemens FX66 microcontroller+ | EM_ST9PLUS -- ^ STMicroelectronics ST9+ 8/16 bit microcontroller+ | EM_ST7 -- ^ STMicroelectronics ST7 8-bit microcontroller+ | EM_68HC16 -- ^ Motorola MC68HC16 Microcontroller+ | EM_68HC11 -- ^ Motorola MC68HC11 Microcontroller+ | EM_68HC08 -- ^ Motorola MC68HC08 Microcontroller+ | EM_68HC05 -- ^ Motorola MC68HC05 Microcontroller+ | EM_SVX -- ^ Silicon Graphics SVx+ | EM_ST19 -- ^ STMicroelectronics ST19 8-bit microcontroller+ | EM_VAX -- ^ Digital VAX+ | EM_CRIS -- ^ Axis Communications 32-bit embedded processor+ | EM_JAVELIN -- ^ Infineon Technologies 32-bit embedded processor+ | EM_FIREPATH -- ^ Element 14 64-bit DSP Processor+ | EM_ZSP -- ^ LSI Logic 16-bit DSP Processor+ | EM_MMIX -- ^ Donald Knuth's educational 64-bit processor+ | EM_HUANY -- ^ Harvard University machine-independent object files+ | EM_PRISM -- ^ SiTera Prism+ | EM_AVR -- ^ Atmel AVR 8-bit microcontroller+ | EM_FR30 -- ^ Fujitsu FR30+ | EM_D10V -- ^ Mitsubishi D10V+ | EM_D30V -- ^ Mitsubishi D30V+ | EM_V850 -- ^ NEC v850+ | EM_M32R -- ^ Mitsubishi M32R+ | EM_MN10300 -- ^ Matsushita MN10300+ | EM_MN10200 -- ^ Matsushita MN10200+ | EM_PJ -- ^ picoJava+ | EM_OPENRISC -- ^ OpenRISC 32-bit embedded processor+ | EM_ARC_A5 -- ^ ARC Cores Tangent-A5+ | EM_XTENSA -- ^ Tensilica Xtensa Architecture+ | EM_VIDEOCORE -- ^ Alphamosaic VideoCore processor+ | EM_TMM_GPP -- ^ Thompson Multimedia General Purpose Processor+ | EM_NS32K -- ^ National Semiconductor 32000 series+ | EM_TPC -- ^ Tenor Network TPC processor+ | EM_SNP1K -- ^ Trebia SNP 1000 processor+ | EM_ST200 -- ^ STMicroelectronics (www.st.com) ST200 microcontroller+ | EM_IP2K -- ^ Ubicom IP2xxx microcontroller family+ | EM_MAX -- ^ MAX Processor+ | EM_CR -- ^ National Semiconductor CompactRISC microprocessor+ | EM_F2MC16 -- ^ Fujitsu F2MC16+ | EM_MSP430 -- ^ Texas Instruments embedded microcontroller msp430+ | EM_BLACKFIN -- ^ Analog Devices Blackfin (DSP) processor+ | EM_SE_C33 -- ^ S1C33 Family of Seiko Epson processors+ | EM_SEP -- ^ Sharp embedded microprocessor+ | EM_ARCA -- ^ Arca RISC Microprocessor+ | EM_UNICORE -- ^ Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University+ | EM_EXT Word16 -- ^ Other+ deriving (Eq, Show)+getElfMachine = liftM getElfMachine_ . getWord16+ where getElfMachine_ 0 = EM_NONE+ getElfMachine_ 1 = EM_M32+ getElfMachine_ 2 = EM_SPARC+ getElfMachine_ 3 = EM_386+ getElfMachine_ 4 = EM_68K+ getElfMachine_ 5 = EM_88K+ getElfMachine_ 6 = EM_486+ getElfMachine_ 7 = EM_860+ getElfMachine_ 8 = EM_MIPS+ getElfMachine_ 9 = EM_S370+ getElfMachine_ 10 = EM_MIPS_RS3_LE+ getElfMachine_ 11 = EM_SPARC64+ getElfMachine_ 15 = EM_PARISC+ getElfMachine_ 17 = EM_VPP500+ getElfMachine_ 18 = EM_SPARC32PLUS+ getElfMachine_ 19 = EM_960+ getElfMachine_ 20 = EM_PPC+ getElfMachine_ 21 = EM_PPC64+ getElfMachine_ 22 = EM_S390+ getElfMachine_ 23 = EM_SPU+ getElfMachine_ 36 = EM_V800+ getElfMachine_ 37 = EM_FR20+ getElfMachine_ 38 = EM_RH32+ getElfMachine_ 39 = EM_RCE+ getElfMachine_ 40 = EM_ARM+ getElfMachine_ 41 = EM_ALPHA+ getElfMachine_ 42 = EM_SH+ getElfMachine_ 43 = EM_SPARCV9+ getElfMachine_ 44 = EM_TRICORE+ getElfMachine_ 45 = EM_ARC+ getElfMachine_ 46 = EM_H8_300+ getElfMachine_ 47 = EM_H8_300H+ getElfMachine_ 48 = EM_H8S+ getElfMachine_ 49 = EM_H8_500+ getElfMachine_ 50 = EM_IA_64+ getElfMachine_ 51 = EM_MIPS_X+ getElfMachine_ 52 = EM_COLDFIRE+ getElfMachine_ 53 = EM_68HC12+ getElfMachine_ 54 = EM_MMA+ getElfMachine_ 55 = EM_PCP+ getElfMachine_ 56 = EM_NCPU+ getElfMachine_ 57 = EM_NDR1+ getElfMachine_ 58 = EM_STARCORE+ getElfMachine_ 59 = EM_ME16+ getElfMachine_ 60 = EM_ST100+ getElfMachine_ 61 = EM_TINYJ+ getElfMachine_ 62 = EM_X86_64+ getElfMachine_ 63 = EM_PDSP+ getElfMachine_ 66 = EM_FX66+ getElfMachine_ 67 = EM_ST9PLUS+ getElfMachine_ 68 = EM_ST7+ getElfMachine_ 69 = EM_68HC16+ getElfMachine_ 70 = EM_68HC11+ getElfMachine_ 71 = EM_68HC08+ getElfMachine_ 72 = EM_68HC05+ getElfMachine_ 73 = EM_SVX+ getElfMachine_ 74 = EM_ST19+ getElfMachine_ 75 = EM_VAX+ getElfMachine_ 76 = EM_CRIS+ getElfMachine_ 77 = EM_JAVELIN+ getElfMachine_ 78 = EM_FIREPATH+ getElfMachine_ 79 = EM_ZSP+ getElfMachine_ 80 = EM_MMIX+ getElfMachine_ 81 = EM_HUANY+ getElfMachine_ 82 = EM_PRISM+ getElfMachine_ 83 = EM_AVR+ getElfMachine_ 84 = EM_FR30+ getElfMachine_ 85 = EM_D10V+ getElfMachine_ 86 = EM_D30V+ getElfMachine_ 87 = EM_V850+ getElfMachine_ 88 = EM_M32R+ getElfMachine_ 89 = EM_MN10300+ getElfMachine_ 90 = EM_MN10200+ getElfMachine_ 91 = EM_PJ+ getElfMachine_ 92 = EM_OPENRISC+ getElfMachine_ 93 = EM_ARC_A5+ getElfMachine_ 94 = EM_XTENSA+ getElfMachine_ 95 = EM_VIDEOCORE+ getElfMachine_ 96 = EM_TMM_GPP+ getElfMachine_ 97 = EM_NS32K+ getElfMachine_ 98 = EM_TPC+ getElfMachine_ 99 = EM_SNP1K+ getElfMachine_ 100 = EM_ST200+ getElfMachine_ 101 = EM_IP2K+ getElfMachine_ 102 = EM_MAX+ getElfMachine_ 103 = EM_CR+ getElfMachine_ 104 = EM_F2MC16+ getElfMachine_ 105 = EM_MSP430+ getElfMachine_ 106 = EM_BLACKFIN+ getElfMachine_ 107 = EM_SE_C33+ getElfMachine_ 108 = EM_SEP+ getElfMachine_ 109 = EM_ARCA+ getElfMachine_ 110 = EM_UNICORE+ getElfMachine_ n = EM_EXT n++getElf_Shdr_OffsetSize :: ElfClass -> ElfReader -> Get (Word64, Word64)+getElf_Shdr_OffsetSize ei_class er =+ case ei_class of+ ELFCLASS32 -> do+ skip 16+ sh_offset <- liftM fromIntegral $ getWord32 er+ sh_size <- liftM fromIntegral $ getWord32 er+ return (sh_offset, sh_size)+ ELFCLASS64 -> do+ skip 24+ sh_offset <- getWord64 er+ sh_size <- getWord64 er+ return (sh_offset, sh_size)++getElf_Shdr :: ElfClass -> ElfReader -> B.ByteString -> B.ByteString -> Get ElfSection+getElf_Shdr ei_class er elf_file string_section =+ case ei_class of+ ELFCLASS32 -> do+ sh_name <- getWord32 er+ sh_type <- getElfSectionType er+ sh_flags <- getElfSectionFlags32 er+ sh_addr <- getWord32 er+ sh_offset <- getWord32 er+ sh_size <- getWord32 er+ sh_link <- getWord32 er+ sh_info <- getWord32 er+ sh_addralign <- getWord32 er+ sh_entsize <- getWord32 er+ return ElfSection+ { elfSectionName = map B.w2c $ B.unpack $ B.takeWhile (/= 0) $ B.drop (fromIntegral sh_name) string_section+ , elfSectionType = sh_type+ , elfSectionFlags = sh_flags+ , elfSectionAddr = fromIntegral sh_addr+ , elfSectionSize = fromIntegral sh_size+ , elfSectionLink = sh_link+ , elfSectionInfo = sh_info+ , elfSectionAddrAlign = fromIntegral sh_addralign+ , elfSectionEntSize = fromIntegral sh_entsize+ , elfSectionData = B.take (fromIntegral sh_size) $ B.drop (fromIntegral sh_offset) elf_file+ }+ ELFCLASS64 -> do+ sh_name <- getWord32 er+ sh_type <- getElfSectionType er+ sh_flags <- getElfSectionFlags64 er+ sh_addr <- getWord64 er+ sh_offset <- getWord64 er+ sh_size <- getWord64 er+ sh_link <- getWord32 er+ sh_info <- getWord32 er+ sh_addralign <- getWord64 er+ sh_entsize <- getWord64 er+ return ElfSection+ { elfSectionName = map B.w2c $ B.unpack $ B.takeWhile (/= 0) $ B.drop (fromIntegral sh_name) string_section+ , elfSectionType = sh_type+ , elfSectionFlags = sh_flags+ , elfSectionAddr = sh_addr+ , elfSectionSize = sh_size+ , elfSectionLink = sh_link+ , elfSectionInfo = sh_info+ , elfSectionAddrAlign = sh_addralign+ , elfSectionEntSize = sh_entsize+ , elfSectionData = B.take (fromIntegral sh_size) $ B.drop (fromIntegral sh_offset) elf_file+ }++data TableInfo = TableInfo { tableOffset :: Int, entrySize :: Int, entryNum :: Int }++getElf_Ehdr :: Get (Elf, TableInfo, TableInfo, Word16)+getElf_Ehdr = do+ ei_magic <- getElfMagic+ ei_class <- getElfClass+ ei_data <- getElfData+ ei_version <- liftM fromIntegral getElfVersion+ ei_osabi <- getElfOsabi+ ei_abiver <- liftM fromIntegral getWord8+ skip 7+ er <- return $ elfReader ei_data+ case ei_class of+ ELFCLASS32 -> do+ e_type <- getElfType er+ e_machine <- getElfMachine er+ e_version <- getWord32 er+ e_entry <- liftM fromIntegral $ getWord32 er+ e_phoff <- getWord32 er+ e_shoff <- liftM fromIntegral $ getWord32 er+ e_flags <- getWord32 er+ e_ehsize <- getWord16 er+ e_phentsize <- getWord16 er+ e_phnum <- getWord16 er+ e_shentsize <- getWord16 er+ e_shnum <- getWord16 er+ e_shstrndx <- getWord16 er+ return (Elf { elfClass = ei_class+ , elfData = ei_data+ , elfVersion = ei_version+ , elfOSABI = ei_osabi+ , elfABIVersion = ei_abiver+ , elfType = e_type+ , elfMachine = e_machine+ , elfEntry = e_entry+ , elfSections = []+ , elfSegments = [] }+ , TableInfo { tableOffset = fromIntegral e_phoff, entrySize = fromIntegral e_phentsize, entryNum = fromIntegral e_phnum }+ , TableInfo { tableOffset = fromIntegral e_shoff, entrySize = fromIntegral e_shentsize, entryNum = fromIntegral e_shnum }+ , e_shstrndx)+ ELFCLASS64 -> do+ e_type <- getElfType er+ e_machine <- getElfMachine er+ e_version <- getWord32 er+ e_entry <- getWord64 er+ e_phoff <- getWord64 er+ e_shoff <- getWord64 er+ e_flags <- getWord32 er+ e_ehsize <- getWord16 er+ e_phentsize <- getWord16 er+ e_phnum <- getWord16 er+ e_shentsize <- getWord16 er+ e_shnum <- getWord16 er+ e_shstrndx <- getWord16 er+ return (Elf { elfClass = ei_class+ , elfData = ei_data+ , elfVersion = ei_version+ , elfOSABI = ei_osabi+ , elfABIVersion = ei_abiver+ , elfType = e_type+ , elfMachine = e_machine+ , elfEntry = e_entry+ , elfSections = []+ , elfSegments = [] }+ , TableInfo { tableOffset = fromIntegral e_phoff, entrySize = fromIntegral e_phentsize, entryNum = fromIntegral e_phnum }+ , TableInfo { tableOffset = fromIntegral e_shoff, entrySize = fromIntegral e_shentsize, entryNum = fromIntegral e_shnum }+ , e_shstrndx)++data ElfReader = ElfReader+ { getWord16 :: Get Word16+ , getWord32 :: Get Word32+ , getWord64 :: Get Word64+ }+elfReader ELFDATA2LSB = ElfReader { getWord16 = getWord16le, getWord32 = getWord32le, getWord64 = getWord64le }+elfReader ELFDATA2MSB = ElfReader { getWord16 = getWord16be, getWord32 = getWord32be, getWord64 = getWord64be }++divide :: B.ByteString -> Int -> Int -> [B.ByteString]+divide bs s 0 = []+divide bs s n = let (x,y) = B.splitAt s bs in x : divide y s (n-1)++-- | Parses a ByteString into an Elf record. Parse failures call error. 32-bit ELF objects have their+-- fields promoted to 64-bit so that the 32- and 64-bit ELF records can be the same.+parseElf :: B.ByteString -> Elf+parseElf b =+ let ph = table segTab+ sh = table secTab+ (shstroff, shstrsize) = parseEntry getElf_Shdr_OffsetSize $ head $ drop (fromIntegral e_shstrndx) sh+ sh_str = B.take (fromIntegral shstrsize) $ B.drop (fromIntegral shstroff) b+ segments = filter (\seg -> elfSegmentType seg /= PT_NULL) $ map (parseEntry (\c r -> parseElfSegmentEntry c r b)) ph+ sections = filter (\sec -> elfSectionType sec /= SHT_NULL) $ map (parseEntry (\c r -> getElf_Shdr c r b sh_str)) sh+ in e { elfSections = sections, elfSegments = segments }++ where table i = divide (B.drop (tableOffset i) b) (entrySize i) (entryNum i)+ parseEntry p x = runGet (p (elfClass e) (elfReader (elfData e))) (L.fromChunks [x])+ (e, segTab, secTab, e_shstrndx) = runGet getElf_Ehdr $ L.fromChunks [b]+++data ElfSegment = ElfSegment+ { elfSegmentType :: ElfSegmentType -- ^ Segment type+ , elfSegmentFlags :: [ElfSegmentFlag] -- ^ Segment flags+ , elfSegmentVirtAddr :: Word64 -- ^ Virtual address for the segment+ , elfSegmentPhysAddr :: Word64 -- ^ Physical address for the segment+ , elfSegmentAlign :: Word64 -- ^ Segment alignment+ , elfSegmentData :: B.ByteString -- ^ Data for the segment+ , elfSegmentMemSize :: Word64 -- ^ Size in memory (may be larger then the segment's data)+ } deriving (Eq,Show)++-- | Segment Types.+data ElfSegmentType+ = PT_NULL -- ^ Unused entry+ | PT_LOAD -- ^ Loadable segment+ | PT_DYNAMIC -- ^ Dynamic linking tables+ | PT_INTERP -- ^ Program interpreter path name+ | PT_NOTE -- ^ Note sectionks+ | PT_SHLIB -- ^ Reserved+ | PT_PHDR -- ^ Program header table+ | PT_Other Word32 -- ^ Some other type+ deriving (Eq,Show)++parseElfSegmentType :: Word32 -> ElfSegmentType+parseElfSegmentType x =+ case x of+ 0 -> PT_NULL+ 1 -> PT_LOAD+ 2 -> PT_DYNAMIC+ 3 -> PT_INTERP+ 4 -> PT_NOTE+ 5 -> PT_SHLIB+ 6 -> PT_PHDR+ _ -> PT_Other x+++parseElfSegmentEntry :: ElfClass -> ElfReader -> B.ByteString -> Get ElfSegment+parseElfSegmentEntry elf_class er elf_file =+ do p_type <- parseElfSegmentType `fmap` getWord32 er+ p_flags <- parseElfSegmentFlags `fmap` getWord32 er+ p_offset <- getWord+ p_vaddr <- getWord+ p_paddr <- getWord+ p_filesz <- getWord+ p_memsz <- getWord+ p_align <- getWord+ return ElfSegment+ { elfSegmentType = p_type+ , elfSegmentFlags = p_flags+ , elfSegmentVirtAddr = p_vaddr+ , elfSegmentPhysAddr = p_paddr+ , elfSegmentAlign = p_align+ , elfSegmentData = B.take (fromIntegral p_filesz) $ B.drop (fromIntegral p_offset) elf_file+ , elfSegmentMemSize = p_memsz+ }++ where getWord = case elf_class of+ ELFCLASS64 -> getWord64 er+ ELFCLASS32 -> fromIntegral `fmap` getWord32 er+++data ElfSegmentFlag+ = PF_X -- ^ Execute permission+ | PF_W -- ^ Write permission+ | PF_R -- ^ Read permission+ | PF_Ext Int -- ^ Some other flag, the Int is the bit number for the flag.+ deriving (Eq,Show)++parseElfSegmentFlags :: Word32 -> [ElfSegmentFlag]+parseElfSegmentFlags word = [ cvt bit | bit <- [ 0 .. 31 ], testBit word bit ]+ where cvt 0 = PF_X+ cvt 1 = PF_W+ cvt 2 = PF_R+ cvt n = PF_Ext n++-- | The symbol table entries consist of index information to be read from other+-- parts of the ELF file. Some of this information is automatically retrieved+-- for your convenience (including symbol name, description of the enclosing+-- section, and definition).+data ElfSymbolTableEntry = EST+ { steName :: (Word32,Maybe B.ByteString)+ , steEnclosingSection :: Maybe ElfSection -- ^ Section from steIndex+ , steType :: ElfSymbolType+ , steBind :: ElfSymbolBinding+ , steOther :: Word8+ , steIndex :: ElfSectionIndex -- ^ Section in which the def is held+ , steValue :: Word64+ , steSize :: Word64+ } deriving (Eq, Show)++-- | Parse the symbol table section into a list of symbol table entries. If+-- no symbol table is found then an empty list is returned.+-- This function does not consult flags to look for SHT_STRTAB (when naming symbols),+-- it just looks for particular sections of ".strtab" and ".shstrtab".+parseSymbolTables :: Elf -> [[ElfSymbolTableEntry]]+parseSymbolTables e =+ let secs = symbolTableSections e+ in map (getSymbolTableEntries e) secs++-- | Assumes the given section is a symbol table, type SHT_SYMTAB+-- (guaranteed by parseSymbolTables).+getSymbolTableEntries :: Elf -> ElfSection -> [ElfSymbolTableEntry]+getSymbolTableEntries e s =+ let link = elfSectionLink s+ strtab = lookup (fromIntegral link) (zip [1..] (elfSections e))+ in runGetMany (getSymbolTableEntry e strtab) (L.fromChunks [elfSectionData s])++-- | Use the symbol offset and size to extract its definition+-- (in the form of a ByteString).+-- If the size is zero, or the offset larger than the 'elfSectionData',+-- then 'Nothing' is returned.+findSymbolDefinition :: ElfSymbolTableEntry -> Maybe B.ByteString+findSymbolDefinition e =+ let enclosingData = fmap elfSectionData (steEnclosingSection e)+ start = fromIntegral (steValue e)+ len = fromIntegral (steSize e)+ def = fmap (B.take len . B.drop start) enclosingData+ in if def == Just B.empty then Nothing else def++runGetMany :: Get a -> L.ByteString -> [a]+runGetMany g bs+ | L.length bs == 0 = []+ | otherwise = let (v,bs',_) = runGetState g bs 0 in v: runGetMany g bs'++symbolTableSections :: Elf -> [ElfSection]+symbolTableSections e = filter ((== SHT_SYMTAB) . elfSectionType) (elfSections e)++-- | Gets a single entry from the symbol table, use with runGetMany.+getSymbolTableEntry :: Elf -> Maybe ElfSection -> Get ElfSymbolTableEntry+getSymbolTableEntry e strtlb =+ if elfClass e == ELFCLASS32 then getSymbolTableEntry32 else getSymbolTableEntry64+ where+ strs = fromMaybe B.empty (fmap elfSectionData strtlb)+ er = elfReader (elfData e)+ getSymbolTableEntry32 = do+ nameIdx <- liftM fromIntegral (getWord32 er)+ value <- liftM fromIntegral (getWord32 er)+ size <- liftM fromIntegral (getWord32 er)+ info <- getWord8+ other <- getWord8+ sTlbIdx <- liftM (toEnum . fromIntegral) (getWord16 er)+ let name = stringByIndex nameIdx strs+ (typ,bind) = infoToTypeAndBind info+ sec = sectionByIndex e sTlbIdx+ return $ EST (nameIdx,name) sec typ bind other sTlbIdx value size+ getSymbolTableEntry64 = do+ nameIdx <- liftM fromIntegral (getWord32 er)+ info <- getWord8+ other <- getWord8+ sTlbIdx <- liftM (toEnum . fromIntegral) (getWord16 er)+ symVal <- getWord64 er+ size <- getWord64 er+ let name = stringByIndex nameIdx strs+ (typ,bind) = infoToTypeAndBind info+ sec = sectionByIndex e sTlbIdx+ return $ EST (nameIdx,name) sec typ bind other sTlbIdx symVal size++sectionByIndex :: Elf -> ElfSectionIndex -> Maybe ElfSection+sectionByIndex e (SHNIndex i) = lookup i . zip [1..] $ (elfSections e)+sectionByIndex _ _ = Nothing++infoToTypeAndBind :: Word8 -> (ElfSymbolType,ElfSymbolBinding)+infoToTypeAndBind i =+ let t = fromIntegral $ i .&. 0x0F+ b = fromIntegral $ (i .&. 0xF) `shiftR` 4+ in (toEnum t, toEnum b)++data ElfSymbolBinding+ = STBLocal+ | STBGlobal+ | STBWeak+ | STBLoOS+ | STBHiOS+ | STBLoProc+ | STBHiProc+ deriving (Eq, Ord, Show, Read)++instance Enum ElfSymbolBinding where+ fromEnum STBLocal = 0+ fromEnum STBGlobal = 1+ fromEnum STBWeak = 2+ fromEnum STBLoOS = 10+ fromEnum STBHiOS = 12+ fromEnum STBLoProc = 13+ fromEnum STBHiProc = 15+ toEnum 0 = STBLocal+ toEnum 1 = STBGlobal+ toEnum 2 = STBWeak+ toEnum 10 = STBLoOS+ toEnum 12 = STBHiOS+ toEnum 13 = STBLoProc+ toEnum 15 = STBHiProc++data ElfSymbolType+ = STTNoType+ | STTObject+ | STTFunc+ | STTSection+ | STTFile+ | STTLoOS+ | STTHiOS+ | STTLoProc+ | STTHiProc+ deriving (Eq, Ord, Show, Read)++instance Enum ElfSymbolType where+ fromEnum STTNoType = 0+ fromEnum STTObject = 1+ fromEnum STTFunc = 2+ fromEnum STTSection = 3+ fromEnum STTFile = 4+ fromEnum STTLoOS = 10+ fromEnum STTHiOS = 12+ fromEnum STTLoProc = 13+ fromEnum STTHiProc = 15+ toEnum 0 = STTNoType+ toEnum 1 = STTObject+ toEnum 2 = STTFunc+ toEnum 3 = STTSection+ toEnum 4 = STTFile+ toEnum 10 = STTLoOS+ toEnum 12 = STTHiOS+ toEnum 13 = STTLoProc+ toEnum 15 = STTHiProc++data ElfSectionIndex+ = SHNUndef+ | SHNLoProc+ | SHNCustomProc Word64+ | SHNHiProc+ | SHNLoOS+ | SHNCustomOS Word64+ | SHNHiOS+ | SHNAbs+ | SHNCommon+ | SHNIndex Word64+ deriving (Eq, Ord, Show, Read)++instance Enum ElfSectionIndex where+ fromEnum SHNUndef = 0+ fromEnum SHNLoProc = 0xFF00+ fromEnum SHNHiProc = 0xFF1F+ fromEnum SHNLoOS = 0xFF20+ fromEnum SHNHiOS = 0xFF3F+ fromEnum SHNAbs = 0xFFF1+ fromEnum SHNCommon = 0xFFF2+ fromEnum (SHNCustomProc x) = fromIntegral x+ fromEnum (SHNCustomOS x) = fromIntegral x+ fromEnum (SHNIndex x) = fromIntegral x+ toEnum 0 = SHNUndef+ toEnum 0xff00 = SHNLoProc+ toEnum 0xFF1F = SHNHiProc+ toEnum 0xFF20 = SHNLoOS+ toEnum 0xFF3F = SHNHiOS+ toEnum 0xFFF1 = SHNAbs+ toEnum 0xFFF2 = SHNCommon+ toEnum x+ | x > fromEnum SHNLoProc && x < fromEnum SHNHiProc = SHNCustomProc (fromIntegral x)+ | x > fromEnum SHNLoOS && x < fromEnum SHNHiOS = SHNCustomOS (fromIntegral x)+ | x < fromEnum SHNLoProc || x > 0xFFFF = SHNIndex (fromIntegral x)+ | otherwise = error "Section index number is in a reserved range but we don't recognize the value from any standard."++-- | Given a section name, extract the ElfSection.+findSectionByName :: String -> Elf -> Maybe ElfSection+findSectionByName name = listToMaybe . filter ((==) name . elfSectionName) . elfSections++-- Get a string from a strtab ByteString.+stringByIndex :: Integral n => n -> B.ByteString -> Maybe B.ByteString+stringByIndex n strtab =+ let str = (B.takeWhile (/=0) . B.drop (fromIntegral n)) strtab+ in if B.length str == 0 then Nothing else Just str++