elf 0.22 → 0.23
raw patch · 2 files changed
+106/−11 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Elf: ElfSegment :: ElfSegmentType -> [ElfSegmentFlag] -> Word64 -> Word64 -> Word64 -> ByteString -> Word64 -> ElfSegment
+ Data.Elf: PF_Ext :: Int -> ElfSegmentFlag
+ Data.Elf: PF_R :: ElfSegmentFlag
+ Data.Elf: PF_W :: ElfSegmentFlag
+ Data.Elf: PF_X :: ElfSegmentFlag
+ Data.Elf: PT_DYNAMIC :: ElfSegmentType
+ Data.Elf: PT_INTERP :: ElfSegmentType
+ Data.Elf: PT_LOAD :: ElfSegmentType
+ Data.Elf: PT_NOTE :: ElfSegmentType
+ Data.Elf: PT_NULL :: ElfSegmentType
+ Data.Elf: PT_Other :: Word32 -> ElfSegmentType
+ Data.Elf: PT_PHDR :: ElfSegmentType
+ Data.Elf: PT_SHLIB :: ElfSegmentType
+ Data.Elf: data ElfSegment
+ Data.Elf: data ElfSegmentFlag
+ Data.Elf: data ElfSegmentType
+ Data.Elf: elfSegmentAlign :: ElfSegment -> Word64
+ Data.Elf: elfSegmentData :: ElfSegment -> ByteString
+ Data.Elf: elfSegmentFlags :: ElfSegment -> [ElfSegmentFlag]
+ Data.Elf: elfSegmentMemSize :: ElfSegment -> Word64
+ Data.Elf: elfSegmentPhysAddr :: ElfSegment -> Word64
+ Data.Elf: elfSegmentType :: ElfSegment -> ElfSegmentType
+ Data.Elf: elfSegmentVirtAddr :: ElfSegment -> Word64
+ Data.Elf: elfSegments :: Elf -> [ElfSegment]
+ Data.Elf: instance Eq ElfSegment
+ Data.Elf: instance Eq ElfSegmentFlag
+ Data.Elf: instance Eq ElfSegmentType
+ Data.Elf: instance Show ElfSegment
+ Data.Elf: instance Show ElfSegmentFlag
+ Data.Elf: instance Show ElfSegmentType
- Data.Elf: Elf :: ElfClass -> ElfData -> Int -> ElfOSABI -> Int -> ElfType -> ElfMachine -> Word64 -> [ElfSection] -> Elf
+ Data.Elf: Elf :: ElfClass -> ElfData -> Int -> ElfOSABI -> Int -> ElfType -> ElfMachine -> Word64 -> [ElfSection] -> [ElfSegment] -> Elf
Files
- elf.cabal +1/−1
- src/Data/Elf.hs +105/−10
elf.cabal view
@@ -1,5 +1,5 @@ Name: elf -Version: 0.22 +Version: 0.23 License: BSD3 License-file: LICENSE Category: Data
src/Data/Elf.hs view
@@ -4,6 +4,9 @@ , ElfSection(..) , ElfSectionType(..) , ElfSectionFlags(..) + , ElfSegment(..) + , ElfSegmentType(..) + , ElfSegmentFlag(..) , ElfClass(..) , ElfData(..) , ElfOSABI(..) @@ -30,6 +33,7 @@ , 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 @@ -432,7 +436,9 @@ , elfSectionData = B.take (fromIntegral sh_size) $ B.drop (fromIntegral sh_offset) elf_file } -getElf_Ehdr :: Get (Elf, Word64, Word16, Word16, Word16) +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 @@ -465,8 +471,11 @@ , elfType = e_type , elfMachine = e_machine , elfEntry = e_entry - , elfSections = [] } - , e_shoff, e_shentsize, e_shnum, e_shstrndx) + , 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 @@ -489,8 +498,11 @@ , elfType = e_type , elfMachine = e_machine , elfEntry = e_entry - , elfSections = [] } - , e_shoff, e_shentsize, e_shnum, e_shstrndx) + , 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 @@ -508,10 +520,93 @@ -- 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 (e, e_shoff, e_shentsize, e_shnum, e_shstrndx) = runGet getElf_Ehdr $ L.fromChunks [b] - sh = B.take (fromIntegral (e_shentsize * e_shnum)) $ B.drop (fromIntegral e_shoff) b - (shstroff, shstrsize) = runGet (getElf_Shdr_OffsetSize (elfClass e) (elfReader $ elfData e)) $ L.fromChunks [B.drop (fromIntegral (e_shentsize * e_shstrndx)) sh] + 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 - sections = filter (\sec -> elfSectionType sec /= SHT_NULL) $ map (runGet (getElf_Shdr (elfClass e) (elfReader $ elfData e) b sh_str) . (\x -> L.fromChunks [x])) (divide sh (fromIntegral e_shentsize) (fromIntegral e_shnum)) - in e { elfSections = sections } + 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 + + +