{-# LANGUAGE PartialTypeSignatures , FlexibleContexts, Strict, DeriveGeneric, StandaloneDeriving #-}
module Instantiation.BinaryElf (elf_read_file) where
import Base
import Generic.Binary
import Data.Elf
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import Data.Word
import Data.List
import Data.Bits
import Data.Maybe (fromJust)
import Data.List.Extra (firstJust)
import qualified Data.ByteString as BS
import GHC.Generics
import qualified Data.Serialize as Cereal hiding (get,put)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
deriving instance Generic ElfMachine
deriving instance Generic ElfSegmentType
deriving instance Generic ElfSegmentFlag
deriving instance Generic ElfSegment
deriving instance Generic ElfType
deriving instance Generic ElfOSABI
deriving instance Generic ElfClass
deriving instance Generic ElfData
deriving instance Generic ElfSectionFlags
deriving instance Generic ElfSectionType
deriving instance Generic ElfSection
deriving instance Generic Elf
instance Cereal.Serialize ElfMachine
instance Cereal.Serialize ElfSegmentType
instance Cereal.Serialize ElfSegmentFlag
instance Cereal.Serialize ElfSegment
instance Cereal.Serialize ElfType
instance Cereal.Serialize ElfOSABI
instance Cereal.Serialize ElfClass
instance Cereal.Serialize ElfData
instance Cereal.Serialize ElfSectionFlags
instance Cereal.Serialize ElfSectionType
instance Cereal.Serialize ElfSection
instance Cereal.Serialize Elf
sections_ro_data :: [([Char], [Char])]
sections_ro_data = [
([Char]
"",[Char]
".text"),
([Char]
"",[Char]
".init"),
([Char]
"",[Char]
".fini"),
([Char]
"",[Char]
".rodata"),
([Char]
"",[Char]
".plt"),
([Char]
"",[Char]
".plt.got"),
([Char]
"",[Char]
".plt.sec"),
([Char]
"",[Char]
".data.rel.ro"),
([Char]
"",[Char]
".init_array"),
([Char]
"",[Char]
".fini_array")
]
sections_data :: [([Char], [Char])]
sections_data = [
([Char]
"",[Char]
".data")
]
sections_bss :: [([Char], [Char])]
sections_bss = [
([Char]
"",[Char]
".bss")
]
sections_text :: [([Char], [Char])]
sections_text = [
([Char]
"",[Char]
".text")
]
isRelevantElfSection :: ElfSection -> Bool
isRelevantElfSection ElfSection
section = ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
section) ([Char], [Char]) -> [([Char], [Char])] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [([Char], [Char])]
sections_ro_data [([Char], [Char])] -> [([Char], [Char])] -> [([Char], [Char])]
forall a. [a] -> [a] -> [a]
++ [([Char], [Char])]
sections_data [([Char], [Char])] -> [([Char], [Char])] -> [([Char], [Char])]
forall a. [a] -> [a] -> [a]
++ [([Char], [Char])]
sections_bss
isAllocated :: ElfSection -> Bool
isAllocated ElfSection
section = ElfSectionFlags
SHF_ALLOC ElfSectionFlags -> [ElfSectionFlags] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ElfSection -> [ElfSectionFlags]
elfSectionFlags ElfSection
section
read_bytes_section :: Word64 -> Int -> ElfSection -> [Word8]
read_bytes_section Word64
a Int
si ElfSection
section = ByteString -> [Word8]
BS.unpack (ByteString -> [Word8]) -> ByteString -> [Word8]
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.take Int
si (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.drop (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> Word64 -> Int
forall a b. (a -> b) -> a -> b
$ Word64
a Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- ElfSection -> Word64
elfSectionAddr ElfSection
section) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ElfSection -> ByteString
elfSectionData ElfSection
section
contains_address :: Word64 -> p -> ElfSection -> Bool
contains_address Word64
a p
si ElfSection
section =
let a0 :: Word64
a0 = ElfSection -> Word64
elfSectionAddr ElfSection
section
si0 :: Word64
si0 = ElfSection -> Word64
elfSectionSize ElfSection
section in
Word64
a0 Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word64
a Bool -> Bool -> Bool
&& Word64
a Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
a0 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
si0
elf_read_ro_data :: Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_ro_data :: Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_ro_data Elf
elf Word64
a Int
si =
case (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isRelevant ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter (Word64 -> Int -> ElfSection -> Bool
forall p. Word64 -> p -> ElfSection -> Bool
contains_address Word64
a Int
si) ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf of
[] -> Maybe [Word8]
forall a. Maybe a
Nothing
[ElfSection
section] -> [Word8] -> Maybe [Word8]
forall a. a -> Maybe a
Just ([Word8] -> Maybe [Word8]) -> [Word8] -> Maybe [Word8]
forall a b. (a -> b) -> a -> b
$ Word64 -> Int -> ElfSection -> [Word8]
read_bytes_section Word64
a Int
si ElfSection
section
where
isRelevant :: ElfSection -> Bool
isRelevant ElfSection
section
| ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
section) ([Char], [Char]) -> [([Char], [Char])] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [([Char], [Char])]
sections_ro_data = Bool
True
| Bool
otherwise = Bool
False
elf_read_data :: Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_data :: Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_data Elf
elf Word64
a Int
si =
case (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isBss ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter (Word64 -> Int -> ElfSection -> Bool
forall p. Word64 -> p -> ElfSection -> Bool
contains_address Word64
a Int
si) ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf of
[ElfSection
section] -> [Word8] -> Maybe [Word8]
forall a. a -> Maybe a
Just ([Word8] -> Maybe [Word8]) -> [Word8] -> Maybe [Word8]
forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> [Word8]
forall a. Int -> a -> [a]
replicate Int
si Word8
0
[] -> Maybe [Word8]
try_read_data
where
try_read_data :: Maybe [Word8]
try_read_data =
case (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isData ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter (Word64 -> Int -> ElfSection -> Bool
forall p. Word64 -> p -> ElfSection -> Bool
contains_address Word64
a Int
si) ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf of
[] -> Maybe [Word8]
forall a. Maybe a
Nothing
[ElfSection
section] -> [Word8] -> Maybe [Word8]
forall a. a -> Maybe a
Just ([Word8] -> Maybe [Word8]) -> [Word8] -> Maybe [Word8]
forall a b. (a -> b) -> a -> b
$ Word64 -> Int -> ElfSection -> [Word8]
read_bytes_section Word64
a Int
si ElfSection
section
isData :: ElfSection -> Bool
isData ElfSection
section
| ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
section) ([Char], [Char]) -> [([Char], [Char])] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [([Char], [Char])]
sections_data = Bool
True
| Bool
otherwise = Bool
False
isBss :: ElfSection -> Bool
isBss ElfSection
section
| ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
section) ([Char], [Char]) -> [([Char], [Char])] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [([Char], [Char])]
sections_bss = Bool
True
| Bool
otherwise = Bool
False
elf_get_relocs :: Elf -> Set Relocation
elf_get_relocs Elf
elf = [Relocation] -> Set Relocation
forall a. Ord a => [a] -> Set a
S.fromList ([Relocation] -> Set Relocation) -> [Relocation] -> Set Relocation
forall a b. (a -> b) -> a -> b
$ [Relocation]
mk_relocs
where
mk_relocs :: [Relocation]
mk_relocs = (ElfRelocationSection -> [Relocation])
-> [ElfRelocationSection] -> [Relocation]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ElfRelocationSection -> [Relocation]
mk_reloc ([ElfRelocationSection] -> [Relocation])
-> [ElfRelocationSection] -> [Relocation]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfRelocationSection]
parseRelocations Elf
elf
mk_reloc :: ElfRelocationSection -> [Relocation]
mk_reloc ElfRelocationSection
sec = (ElfRel -> [Relocation]) -> [ElfRel] -> [Relocation]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ElfRelocationSection -> ElfRel -> [Relocation]
forall p. p -> ElfRel -> [Relocation]
try_mk_reloc ElfRelocationSection
sec) (ElfRelocationSection -> [ElfRel]
elfRelSectRelocations ElfRelocationSection
sec)
try_mk_reloc :: p -> ElfRel -> [Relocation]
try_mk_reloc p
sec ElfRel
reloc
| ElfRel -> Word8
elfRelType ElfRel
reloc Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
8 =
[Word64 -> Word64 -> Relocation
Relocation (Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word64) -> Word64 -> Word64
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelOffset ElfRel
reloc) (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Word64) -> Int64 -> Word64
forall a b. (a -> b) -> a -> b
$ Maybe Int64 -> Int64
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Int64 -> Int64) -> Maybe Int64 -> Int64
forall a b. (a -> b) -> a -> b
$ ElfRel -> Maybe Int64
elfRelSymAddend ElfRel
reloc)]
| Bool
otherwise = []
elf_get_symbol_table :: Elf -> SymbolTable
elf_get_symbol_table Elf
elf = IntMap Symbol -> SymbolTable
SymbolTable (IntMap Symbol -> SymbolTable) -> IntMap Symbol -> SymbolTable
forall a b. (a -> b) -> a -> b
$ [(Int, Symbol)] -> IntMap Symbol
forall a. [(Int, a)] -> IntMap a
IM.fromList ([(Int, Symbol)] -> IntMap Symbol)
-> [(Int, Symbol)] -> IntMap Symbol
forall a b. (a -> b) -> a -> b
$ ((Int, Symbol) -> Bool) -> [(Int, Symbol)] -> [(Int, Symbol)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe [Char] -> Maybe [Char] -> Bool
forall a. Eq a => a -> a -> Bool
(/=) ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"") (Maybe [Char] -> Bool)
-> ((Int, Symbol) -> Maybe [Char]) -> (Int, Symbol) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Symbol -> Maybe [Char]
symbol_to_name (Symbol -> Maybe [Char])
-> ((Int, Symbol) -> Symbol) -> (Int, Symbol) -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Symbol) -> Symbol
forall a b. (a, b) -> b
snd) ([(Int, Symbol)] -> [(Int, Symbol)])
-> [(Int, Symbol)] -> [(Int, Symbol)]
forall a b. (a -> b) -> a -> b
$ [(Int, Symbol)]
symbols_from_ELF_symbol_tables [(Int, Symbol)] -> [(Int, Symbol)] -> [(Int, Symbol)]
forall a. [a] -> [a] -> [a]
++ [(Int, Symbol)]
symbols_from_relocations
where
symbols_from_relocations :: [(Int, Symbol)]
symbols_from_relocations = (ElfRelocationSection -> [(Int, Symbol)])
-> [ElfRelocationSection] -> [(Int, Symbol)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ElfRelocationSection -> [(Int, Symbol)]
forall a. Num a => ElfRelocationSection -> [(a, Symbol)]
mk_symbol_table_for_reloc_section ([ElfRelocationSection] -> [(Int, Symbol)])
-> [ElfRelocationSection] -> [(Int, Symbol)]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfRelocationSection]
parseRelocations Elf
elf
mk_symbol_table_for_reloc_section :: ElfRelocationSection -> [(a, Symbol)]
mk_symbol_table_for_reloc_section ElfRelocationSection
sec = (ElfRel -> [(a, Symbol)]) -> [ElfRel] -> [(a, Symbol)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ElfRelocationSection -> ElfRel -> [(a, Symbol)]
forall a. Num a => ElfRelocationSection -> ElfRel -> [(a, Symbol)]
try_mk_symbol_entry ElfRelocationSection
sec) (ElfRelocationSection -> [ElfRel]
elfRelSectRelocations ElfRelocationSection
sec)
try_mk_symbol_entry :: ElfRelocationSection -> ElfRel -> [(a, Symbol)]
try_mk_symbol_entry ElfRelocationSection
sec ElfRel
reloc
| ElfRel -> Word8
elfRelType ElfRel
reloc Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
7 =
[(Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> a) -> Word64 -> a
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelOffset ElfRel
reloc, [Char] -> Symbol
Relocated_Function ([Char] -> Symbol) -> [Char] -> Symbol
forall a b. (a -> b) -> a -> b
$ ElfRelocationSection -> ElfRel -> [Char]
get_name_from_reloc ElfRelocationSection
sec ElfRel
reloc)]
| ElfRel -> Word8
elfRelType ElfRel
reloc Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
6 =
let typ :: [Char] -> Symbol
typ = if ElfRelocationSection -> ElfRel -> ElfSymbolType
get_symbol_type_of_reloc ElfRelocationSection
sec ElfRel
reloc ElfSymbolType -> [ElfSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ElfSymbolType
STTObject,ElfSymbolType
STTCommon] then [Char] -> Symbol
Relocated_Label else [Char] -> Symbol
Relocated_Function in
[(Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> a) -> Word64 -> a
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelOffset ElfRel
reloc, [Char] -> Symbol
typ ([Char] -> Symbol) -> [Char] -> Symbol
forall a b. (a -> b) -> a -> b
$ ElfRelocationSection -> ElfRel -> [Char]
get_name_from_reloc ElfRelocationSection
sec ElfRel
reloc)]
| ElfRel -> Word8
elfRelType ElfRel
reloc Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
5 =
[(Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> a) -> Word64 -> a
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelOffset ElfRel
reloc, [Char] -> Symbol
Relocated_Label ([Char] -> Symbol) -> [Char] -> Symbol
forall a b. (a -> b) -> a -> b
$ ElfRelocationSection -> ElfRel -> [Char]
get_name_from_reloc ElfRelocationSection
sec ElfRel
reloc)]
| Bool
otherwise = []
symbols_from_ELF_symbol_tables :: [(Int, Symbol)]
symbols_from_ELF_symbol_tables = (ElfSymbolTableEntry -> [(Int, Symbol)])
-> [ElfSymbolTableEntry] -> [(Int, Symbol)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ElfSymbolTableEntry -> [(Int, Symbol)]
forall a. Num a => ElfSymbolTableEntry -> [(a, Symbol)]
mk_symbol_entry ([ElfSymbolTableEntry] -> [(Int, Symbol)])
-> [ElfSymbolTableEntry] -> [(Int, Symbol)]
forall a b. (a -> b) -> a -> b
$ [[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry])
-> [[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry]
forall a b. (a -> b) -> a -> b
$ Elf -> [[ElfSymbolTableEntry]]
parseSymbolTables Elf
elf
mk_symbol_entry :: ElfSymbolTableEntry -> [(a, Symbol)]
mk_symbol_entry ElfSymbolTableEntry
sym_entry
| ElfSymbolTableEntry -> Bool
is_internal_symbol_entry ElfSymbolTableEntry
sym_entry = [(Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> a) -> Word64 -> a
forall a b. (a -> b) -> a -> b
$ ElfSymbolTableEntry -> Word64
steValue ElfSymbolTableEntry
sym_entry, [Char] -> Symbol
Internal_Label ([Char] -> Symbol) -> [Char] -> Symbol
forall a b. (a -> b) -> a -> b
$ (Word32, Maybe ByteString) -> [Char]
forall a. (a, Maybe ByteString) -> [Char]
get_string_from_steName ((Word32, Maybe ByteString) -> [Char])
-> (Word32, Maybe ByteString) -> [Char]
forall a b. (a -> b) -> a -> b
$ ElfSymbolTableEntry -> (Word32, Maybe ByteString)
steName ElfSymbolTableEntry
sym_entry)]
| Bool
otherwise = []
is_external_var_symbol_entry :: ElfSymbolTableEntry -> Bool
is_external_var_symbol_entry ElfSymbolTableEntry
sym_entry = ElfSymbolTableEntry -> ElfSymbolType
steType ElfSymbolTableEntry
sym_entry ElfSymbolType -> [ElfSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ElfSymbolType
STTObject,ElfSymbolType
STTCommon] Bool -> Bool -> Bool
&& ElfSymbolTableEntry -> ElfSymbolBinding
steBind ElfSymbolTableEntry
sym_entry ElfSymbolBinding -> [ElfSymbolBinding] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ElfSymbolBinding
STBGlobal, ElfSymbolBinding
STBWeak] Bool -> Bool -> Bool
&& Bool -> Bool
not (ElfSymbolTableEntry -> Bool
isHiddenSymEntry ElfSymbolTableEntry
sym_entry)
is_internal_symbol_entry :: ElfSymbolTableEntry -> Bool
is_internal_symbol_entry ElfSymbolTableEntry
sym_entry = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or
[ ElfSymbolTableEntry -> Maybe ElfSection
steEnclosingSection ElfSymbolTableEntry
sym_entry Maybe ElfSection -> Maybe ElfSection -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe ElfSection
forall a. Maybe a
Nothing Bool -> Bool -> Bool
&& ElfSymbolTableEntry -> ElfSymbolType
steType ElfSymbolTableEntry
sym_entry ElfSymbolType -> [ElfSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [ElfSymbolType
STTObject,ElfSymbolType
STTCommon]
, ElfSymbolTableEntry -> Bool
is_hidden ElfSymbolTableEntry
sym_entry ]
get_name_from_reloc :: ElfRelocationSection -> ElfRel -> [Char]
get_name_from_reloc ElfRelocationSection
sec ElfRel
reloc = (Word32, Maybe ByteString) -> [Char]
forall a. (a, Maybe ByteString) -> [Char]
get_string_from_steName ((Word32, Maybe ByteString) -> [Char])
-> (Word32, Maybe ByteString) -> [Char]
forall a b. (a -> b) -> a -> b
$ ElfSymbolTableEntry -> (Word32, Maybe ByteString)
steName (ElfSymbolTableEntry -> (Word32, Maybe ByteString))
-> ElfSymbolTableEntry -> (Word32, Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ (ElfRelocationSection -> [ElfSymbolTableEntry]
elfRelSectSymbolTable ElfRelocationSection
sec) [ElfSymbolTableEntry] -> Int -> ElfSymbolTableEntry
forall a. [a] -> Int -> a
!! (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> Word64 -> Int
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelSymbol ElfRel
reloc)
get_symbol_type_of_reloc :: ElfRelocationSection -> ElfRel -> ElfSymbolType
get_symbol_type_of_reloc ElfRelocationSection
sec ElfRel
reloc = ElfSymbolTableEntry -> ElfSymbolType
steType (ElfSymbolTableEntry -> ElfSymbolType)
-> ElfSymbolTableEntry -> ElfSymbolType
forall a b. (a -> b) -> a -> b
$ (ElfRelocationSection -> [ElfSymbolTableEntry]
elfRelSectSymbolTable ElfRelocationSection
sec) [ElfSymbolTableEntry] -> Int -> ElfSymbolTableEntry
forall a. [a] -> Int -> a
!! (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> Word64 -> Int
forall a b. (a -> b) -> a -> b
$ ElfRel -> Word64
elfRelSymbol ElfRel
reloc)
isHiddenSymEntry :: ElfSymbolTableEntry -> Bool
isHiddenSymEntry ElfSymbolTableEntry
sym_entry = ElfSymbolTableEntry -> Word8
steOther ElfSymbolTableEntry
sym_entry Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x3 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x2
is_hidden :: ElfSymbolTableEntry -> Bool
is_hidden ElfSymbolTableEntry
sym_entry = ElfSymbolTableEntry -> ElfSymbolType
steType ElfSymbolTableEntry
sym_entry ElfSymbolType -> [ElfSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ElfSymbolType
STTObject,ElfSymbolType
STTCommon] Bool -> Bool -> Bool
&& ElfSymbolTableEntry -> ElfSymbolBinding
steBind ElfSymbolTableEntry
sym_entry ElfSymbolBinding -> [ElfSymbolBinding] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ElfSymbolBinding
STBGlobal, ElfSymbolBinding
STBWeak] Bool -> Bool -> Bool
&& ElfSymbolTableEntry -> Bool
isHiddenSymEntry ElfSymbolTableEntry
sym_entry
get_string_from_steName :: (a, Maybe ByteString) -> [Char]
get_string_from_steName (a
_, Just ByteString
name) = Text -> [Char]
T.unpack (Text -> [Char]) -> Text -> [Char]
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
T.decodeUtf8 ByteString
name
get_string_from_steName (a, Maybe ByteString)
_ = [Char]
""
elf_min_address :: Elf -> Word64
elf_min_address Elf
elf = [Word64] -> Word64
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Word64] -> Word64) -> [Word64] -> Word64
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Word64) -> [ElfSection] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map ElfSection -> Word64
elfSectionAddr ([ElfSection] -> [Word64]) -> [ElfSection] -> [Word64]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isRelevantElfSection ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf
elf_max_address :: Elf -> Word64
elf_max_address Elf
elf = [Word64] -> Word64
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Word64] -> Word64) -> [Word64] -> Word64
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Word64) -> [ElfSection] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map ElfSection -> Word64
get_max_address ([ElfSection] -> [Word64]) -> [ElfSection] -> [Word64]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isRelevantElfSection ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf
where
get_max_address :: ElfSection -> Word64
get_max_address ElfSection
section = ElfSection -> Word64
elfSectionAddr ElfSection
section Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ ElfSection -> Word64
elfSectionSize ElfSection
section Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1
elf_read_file :: ByteString -> Elf
elf_read_file = ByteString -> Elf
parseElf
pp_elf_section :: ElfSection -> [Char]
pp_elf_section ElfSection
section = [Char]
"[" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " [ElfSection -> [Char]
elfSectionName ElfSection
section, ElfSectionType -> [Char]
forall a. Show a => a -> [Char]
show (ElfSectionType -> [Char]) -> ElfSectionType -> [Char]
forall a b. (a -> b) -> a -> b
$ ElfSection -> ElfSectionType
elfSectionType ElfSection
section, Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (ElfSection -> Word64
elfSectionAddr ElfSection
section), Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (ElfSection -> Word64
elfSectionSize ElfSection
section)] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
pp_elf :: Elf -> [Char]
pp_elf Elf
elf = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"\n" ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ [[Char]]
pp_sections [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_boundaries [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_symbols [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_relocs [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_all_relocs [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_all_symbols [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
pp_entry
where
pp_sections :: [[Char]]
pp_sections = (ElfSection -> [Char]) -> [ElfSection] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ElfSection -> [Char]
pp_elf_section ([ElfSection] -> [[Char]]) -> [ElfSection] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf
pp_boundaries :: [[Char]]
pp_boundaries = [[Char]
"Address range: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (Elf -> Word64
elf_min_address Elf
elf) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" --> " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (Elf -> Word64
elf_max_address Elf
elf)]
pp_symbols :: [[Char]]
pp_symbols = [[Char]
"Symbol table:\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ SymbolTable -> [Char]
forall a. Show a => a -> [Char]
show (Elf -> SymbolTable
elf_get_symbol_table Elf
elf)]
pp_relocs :: [[Char]]
pp_relocs = [[Char]
"Relocations:\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Set Relocation -> [Char]
forall a. Show a => a -> [Char]
show (Elf -> Set Relocation
elf_get_relocs Elf
elf)]
pp_all_relocs :: [[Char]]
pp_all_relocs = [Char]
"Complete relocation list:" [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: (ElfRel -> [Char]) -> [ElfRel] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ElfRel -> [Char]
forall a. Show a => a -> [Char]
show ((ElfRelocationSection -> [ElfRel])
-> [ElfRelocationSection] -> [ElfRel]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ElfRelocationSection -> [ElfRel]
elfRelSectRelocations ([ElfRelocationSection] -> [ElfRel])
-> [ElfRelocationSection] -> [ElfRel]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfRelocationSection]
parseRelocations Elf
elf)
pp_all_symbols :: [[Char]]
pp_all_symbols = [Char]
"Complete symbol table:" [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: (ElfSymbolTableEntry -> [Char])
-> [ElfSymbolTableEntry] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ElfSymbolTableEntry -> [Char]
show_symbol_entry ([[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry])
-> [[ElfSymbolTableEntry]] -> [ElfSymbolTableEntry]
forall a b. (a -> b) -> a -> b
$ Elf -> [[ElfSymbolTableEntry]]
parseSymbolTables Elf
elf)
show_symbol_entry :: ElfSymbolTableEntry -> [Char]
show_symbol_entry ElfSymbolTableEntry
sym_entry = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"; " [ (Word32, Maybe ByteString) -> [Char]
forall a. Show a => a -> [Char]
show (ElfSymbolTableEntry -> (Word32, Maybe ByteString)
steName ElfSymbolTableEntry
sym_entry), ElfSymbolType -> [Char]
forall a. Show a => a -> [Char]
show (ElfSymbolTableEntry -> ElfSymbolType
steType ElfSymbolTableEntry
sym_entry) , Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (ElfSymbolTableEntry -> Word64
steValue ElfSymbolTableEntry
sym_entry), ElfSectionIndex -> [Char]
forall a. Show a => a -> [Char]
show (ElfSectionIndex -> [Char]) -> ElfSectionIndex -> [Char]
forall a b. (a -> b) -> a -> b
$ ElfSymbolTableEntry -> ElfSectionIndex
steIndex ElfSymbolTableEntry
sym_entry, ElfSymbolBinding -> [Char]
forall a. Show a => a -> [Char]
show (ElfSymbolBinding -> [Char]) -> ElfSymbolBinding -> [Char]
forall a b. (a -> b) -> a -> b
$ ElfSymbolTableEntry -> ElfSymbolBinding
steBind ElfSymbolTableEntry
sym_entry ]
pp_entry :: [[Char]]
pp_entry = [[Char]
"Entry: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Word64 -> [Char]
forall a. (Integral a, Show a) => a -> [Char]
showHex (Word64 -> [Char]) -> Word64 -> [Char]
forall a b. (a -> b) -> a -> b
$ Elf -> Word64
elfEntry Elf
elf)]
elf_get_sections_info :: Elf -> SectionsInfo
elf_get_sections_info Elf
elf = [([Char], [Char], Word64, Word64)]
-> Word64 -> Word64 -> SectionsInfo
SectionsInfo ((ElfSection -> ([Char], [Char], Word64, Word64))
-> [ElfSection] -> [([Char], [Char], Word64, Word64)]
forall a b. (a -> b) -> [a] -> [b]
map ElfSection -> ([Char], [Char], Word64, Word64)
mk_section_info ([ElfSection] -> [([Char], [Char], Word64, Word64)])
-> [ElfSection] -> [([Char], [Char], Word64, Word64)]
forall a b. (a -> b) -> a -> b
$ (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isRelevantElfSection ([ElfSection] -> [ElfSection]) -> [ElfSection] -> [ElfSection]
forall a b. (a -> b) -> a -> b
$ Elf -> [ElfSection]
elfSections Elf
elf) (Elf -> Word64
elf_min_address Elf
elf) (Elf -> Word64
elf_max_address Elf
elf)
where
mk_section_info :: ElfSection -> ([Char], [Char], Word64, Word64)
mk_section_info ElfSection
section = ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
section,ElfSection -> Word64
elfSectionAddr ElfSection
section,ElfSection -> Word64
elfSectionSize ElfSection
section)
elf_text_section_size :: Elf -> Int
elf_text_section_size = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> (Elf -> [Int]) -> Elf -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ElfSection -> Int) -> [ElfSection] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> (ElfSection -> Word64) -> ElfSection -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElfSection -> Word64
elfSectionSize) ([ElfSection] -> [Int]) -> (Elf -> [ElfSection]) -> Elf -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ElfSection -> Bool) -> [ElfSection] -> [ElfSection]
forall a. (a -> Bool) -> [a] -> [a]
filter ElfSection -> Bool
isTextSection ([ElfSection] -> [ElfSection])
-> (Elf -> [ElfSection]) -> Elf -> [ElfSection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Elf -> [ElfSection]
elfSections
where
isTextSection :: ElfSection -> Bool
isTextSection ElfSection
sec = ([Char]
"",ElfSection -> [Char]
elfSectionName ElfSection
sec) ([Char], [Char]) -> [([Char], [Char])] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [([Char], [Char])]
sections_text
instance BinaryClass Elf
where
binary_read_ro_data :: Elf -> Word64 -> Int -> Maybe [Word8]
binary_read_ro_data = Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_ro_data
binary_read_data :: Elf -> Word64 -> Int -> Maybe [Word8]
binary_read_data = Elf -> Word64 -> Int -> Maybe [Word8]
elf_read_data
binary_get_sections_info :: Elf -> SectionsInfo
binary_get_sections_info = Elf -> SectionsInfo
elf_get_sections_info
binary_get_symbols :: Elf -> SymbolTable
binary_get_symbols = Elf -> SymbolTable
elf_get_symbol_table
binary_get_relocations :: Elf -> Set Relocation
binary_get_relocations = Elf -> Set Relocation
elf_get_relocs
binary_pp :: Elf -> [Char]
binary_pp = Elf -> [Char]
pp_elf
binary_entry :: Elf -> Word64
binary_entry = Elf -> Word64
elfEntry
binary_text_section_size :: Elf -> Int
binary_text_section_size = Elf -> Int
elf_text_section_size