{-# LANGUAGE Strict #-}


{-# OPTIONS_HADDOCK hide #-}

-- Parser that can be used to read section info supplied by bash script "dump_macho.sh"
--
-- Example input:
--
-- (__TEXT,__text)
--   addr = 0x0000000100002a94
--   size = 0x0000000000000f69
--
-- | (__DATA,__common)
-- |   addr = 0x00000001000041d0
-- |   size = 0x0000000000000010

module Parser.ParserSections where

import Binary.Generic

import Text.Parsec.Token
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Number

isWhiteSpace :: Char -> Bool
isWhiteSpace Char
'\t' = Bool
True
isWhiteSpace Char
'\f' = Bool
True
isWhiteSpace Char
'\v' = Bool
True
isWhiteSpace Char
' ' = Bool
True
isWhiteSpace Char
_ = Bool
False 

whitespace :: ParsecT [Char] u Identity Char
whitespace = (Char -> Bool) -> ParsecT [Char] u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy Char -> Bool
isWhiteSpace ParsecT [Char] u Identity Char
-> [Char] -> ParsecT [Char] u Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> [Char] -> ParsecT s u m a
<?> [Char]
"white space"
whitespaces :: ParsecT [Char] u Identity ()
whitespaces = ParsecT [Char] u Identity Char -> ParsecT [Char] u Identity ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
skipMany ParsecT [Char] u Identity Char
forall {u}. ParsecT [Char] u Identity Char
whitespace ParsecT [Char] u Identity ()
-> [Char] -> ParsecT [Char] u Identity ()
forall s u (m :: * -> *) a.
ParsecT s u m a -> [Char] -> ParsecT s u m a
<?> [Char]
"white spaces"


hexnum_with_0x :: ParsecT [Char] u Identity Word64
hexnum_with_0x = do
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"0x"
  ParsecT [Char] u Identity Word64
forall i st. Integral i => CharParser st i
hexnum


section_info :: ParsecT [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
section_info = do
  ParsecT [Char] u Identity Char -> ParsecT [Char] u Identity [Char]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many ParsecT [Char] u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline

  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"("
  [Char]
segname <- ParsecT [Char] u Identity Char -> ParsecT [Char] u Identity [Char]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many ([Char] -> ParsecT [Char] u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
noneOf [Char]
",")
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
","
  [Char]
sectname <- ParsecT [Char] u Identity Char -> ParsecT [Char] u Identity [Char]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many ([Char] -> ParsecT [Char] u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
noneOf [Char]
")")
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
")"
  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  ParsecT [Char] u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline

  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"addr"
  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"="
  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  Word64
addr <- ParsecT [Char] u Identity Word64
forall {u}. ParsecT [Char] u Identity Word64
hexnum_with_0x
  ParsecT [Char] u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline

  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"size"
  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  [Char] -> ParsecT [Char] u Identity [Char]
forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
string [Char]
"="
  ParsecT [Char] u Identity ()
forall {u}. ParsecT [Char] u Identity ()
whitespaces
  Word64
size <- ParsecT [Char] u Identity Word64
forall {u}. ParsecT [Char] u Identity Word64
hexnum_with_0x
  ParsecT [Char] u Identity Char -> ParsecT [Char] u Identity [Char]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many ParsecT [Char] u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline
  ([Char], [Char], Word64, Word64, Word64)
-> ParsecT
     [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
forall a. a -> ParsecT [Char] u Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (([Char], [Char], Word64, Word64, Word64)
 -> ParsecT
      [Char] u Identity ([Char], [Char], Word64, Word64, Word64))
-> ([Char], [Char], Word64, Word64, Word64)
-> ParsecT
     [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
forall a b. (a -> b) -> a -> b
$ ([Char]
segname,[Char]
sectname,Word64
addr,Word64
size,Word64
16)

sections_info :: ParsecT [Char] u Identity SectionsInfo
sections_info = do
  [([Char], [Char], Word64, Word64, Word64)]
sis <- ParsecT [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
-> ParsecT
     [Char] u Identity [([Char], [Char], Word64, Word64, Word64)]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many ParsecT [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
forall {u}.
ParsecT [Char] u Identity ([Char], [Char], Word64, Word64, Word64)
section_info
  ParsecT [Char] u Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof
  let min :: Word64
min = [Word64] -> Word64
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Word64] -> Word64) -> [Word64] -> Word64
forall a b. (a -> b) -> a -> b
$ (([Char], [Char], Word64, Word64, Word64) -> Word64)
-> [([Char], [Char], Word64, Word64, Word64)] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char], Word64, Word64, Word64) -> Word64
forall {a} {b} {c} {d} {e}. (a, b, c, d, e) -> c
get_min_address [([Char], [Char], Word64, Word64, Word64)]
sis
  let max :: Word64
max = [Word64] -> Word64
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Word64] -> Word64) -> [Word64] -> Word64
forall a b. (a -> b) -> a -> b
$ (([Char], [Char], Word64, Word64, Word64) -> Word64)
-> [([Char], [Char], Word64, Word64, Word64)] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char], Word64, Word64, Word64) -> Word64
forall {a} {a} {b} {e}. Num a => (a, b, a, a, e) -> a
get_max_address [([Char], [Char], Word64, Word64, Word64)]
sis
  SectionsInfo -> ParsecT [Char] u Identity SectionsInfo
forall a. a -> ParsecT [Char] u Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SectionsInfo -> ParsecT [Char] u Identity SectionsInfo)
-> SectionsInfo -> ParsecT [Char] u Identity SectionsInfo
forall a b. (a -> b) -> a -> b
$ [([Char], [Char], Word64, Word64, Word64)]
-> Word64 -> Word64 -> SectionsInfo
SectionsInfo [([Char], [Char], Word64, Word64, Word64)]
sis Word64
min Word64
max
 where
  get_min_address :: (a, b, c, d, e) -> c
get_min_address (a
_,b
_,c
a,d
_,e
_)  = c
a
  get_max_address :: (a, b, a, a, e) -> a
get_max_address (a
_,b
_,a
a,a
si,e
_) = a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
si a -> a -> a
forall a. Num a => a -> a -> a
- a
1

-- The parse function.
-- Takes as input a filename f and produces a list of instructions
-- to lists of instructions.
parse_sections  :: String -> IO (Either ParseError SectionsInfo)
parse_sections :: [Char] -> IO (Either ParseError SectionsInfo)
parse_sections = Parser SectionsInfo
-> [Char] -> IO (Either ParseError SectionsInfo)
forall a. Parser a -> [Char] -> IO (Either ParseError a)
parseFromFile Parser SectionsInfo
forall {u}. ParsecT [Char] u Identity SectionsInfo
sections_info