-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathElf.hs
45 lines (38 loc) · 1.58 KB
/
Elf.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module Utility.Elf where
import Control.Monad
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC8
import Data.Elf
import Data.Word
-- External functions
-- readElf returns the data loaded by an elf file as a list of tuples of byte
-- addresses and bytes of data.
readElf :: FilePath -> IO [(Int, Word8)]
readElf f = do
bytes <- B.readFile f
return $ translateElf $ parseElf bytes
-- readElfSymbol takes a symbol name and returns its address if that symbol
-- exists in the elf file.
readElfSymbol :: String -> FilePath -> IO (Maybe Word64)
readElfSymbol symbolName f = do
bytes <- B.readFile f
return $ findSymbolAddress symbolName $ parseElf bytes
-- Internal functions
translateElf :: Elf -> [(Int, Word8)]
translateElf e = concat $ map translateElfSegment $ elfSegments e
translateElfSegment :: ElfSegment -> [(Int, Word8)]
translateElfSegment s =
if elfSegmentType s == PT_LOAD
then addressEachByte ((fromIntegral:: Word64 -> Int) $ elfSegmentPhysAddr s) (B.unpack $ elfSegmentData s)
else []
addressEachByte :: Int -> [Word8] -> [(Int, Word8)]
addressEachByte addr (b:bs) = (addr, b) : (addressEachByte (addr+1) bs)
addressEachByte addr [] = []
findSymbolAddress :: String -> Elf -> Maybe Word64
findSymbolAddress symbolName elf =
foldl mplus Nothing $ map (symbolTableFilter symbolName) $ concat $ parseSymbolTables elf
symbolTableFilter :: String -> ElfSymbolTableEntry -> Maybe Word64
symbolTableFilter symbolName ste =
if (snd (steName ste)) == (Just $ BC8.pack symbolName)
then Just $ steValue ste
else Nothing