{-# LANGUAGE PartialTypeSignatures , FlexibleContexts, Strict, DeriveGeneric, StandaloneDeriving #-}


module Data.Symbol where

import Data.Word 
import GHC.Generics
import qualified Data.Serialize as Cereal hiding (get,put)
import qualified Numeric (showHex)

-- | An address a0 can have a symbol.
--
-- PointerToFunction:
-- E.g:
-- 		0xcfe0 --> malloc
-- Means that reading 8 bytes from address 0xcfe0 produces a pointer to malloc.
-- Thus an instruction: "CALL qword ptr [0xcfe0]" can be seen as "CALL malloc".
--
-- PointerToObject:
-- E.g.:
--    0xd0a8 --> stdout
-- Means that "mov rdi,QWORD PTR [0xd0a8]" can be seen as "mov rdi, QWORD PTR [stdout]"
--
-- Relocated_ResolvedObject
-- E.g.:
--    0xc0fc0 "environ" -> 0xc1340
-- Sometimes, a relocation has been resolved during linking. In that case, it is no longer an external object.
-- For example, there may be a relocation that maps address 0xc0fc0 to symbol "environ".
-- However, that symbol is an object with an address (e.g., 0xc1340) that itself has been relocated.
-- Symbol "environ" now no longer is an external symbol.
-- Instead, we have *environ = &object, where "object" is the object that 0xc1340 is relocated to.
data Symbol = 
    PointerToLabel            String Bool -- ^ Address a0 is a pointer to memory storing the entry of a function
  | PointerToObject           String Bool -- ^ Address a0 can be replaced by the GOT entry of the string, e.g., "stdout wrt ..got" or "optind wrt ..got"
  | AddressOfObject           String Bool -- ^ Address a0 can be replaced by the string, e.g., "stdout" or "optind"
  | AddressOfLabel            String Bool -- ^ Address a0 can be replaced by the string.
  | Relocated_ResolvedObject  String Word64 -- ^ At linking time internally resolved relocation
  deriving ((forall x. Symbol -> Rep Symbol x)
-> (forall x. Rep Symbol x -> Symbol) -> Generic Symbol
forall x. Rep Symbol x -> Symbol
forall x. Symbol -> Rep Symbol x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Symbol -> Rep Symbol x
from :: forall x. Symbol -> Rep Symbol x
$cto :: forall x. Rep Symbol x -> Symbol
to :: forall x. Rep Symbol x -> Symbol
Generic,Symbol -> Symbol -> Bool
(Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool) -> Eq Symbol
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Symbol -> Symbol -> Bool
== :: Symbol -> Symbol -> Bool
$c/= :: Symbol -> Symbol -> Bool
/= :: Symbol -> Symbol -> Bool
Eq,Eq Symbol
Eq Symbol =>
(Symbol -> Symbol -> Ordering)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Bool)
-> (Symbol -> Symbol -> Symbol)
-> (Symbol -> Symbol -> Symbol)
-> Ord Symbol
Symbol -> Symbol -> Bool
Symbol -> Symbol -> Ordering
Symbol -> Symbol -> Symbol
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Symbol -> Symbol -> Ordering
compare :: Symbol -> Symbol -> Ordering
$c< :: Symbol -> Symbol -> Bool
< :: Symbol -> Symbol -> Bool
$c<= :: Symbol -> Symbol -> Bool
<= :: Symbol -> Symbol -> Bool
$c> :: Symbol -> Symbol -> Bool
> :: Symbol -> Symbol -> Bool
$c>= :: Symbol -> Symbol -> Bool
>= :: Symbol -> Symbol -> Bool
$cmax :: Symbol -> Symbol -> Symbol
max :: Symbol -> Symbol -> Symbol
$cmin :: Symbol -> Symbol -> Symbol
min :: Symbol -> Symbol -> Symbol
Ord)

instance Show Symbol where
  show :: Symbol -> String
show (PointerToLabel  String
l Bool
ex)         = String
"&" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
show_ex Bool
ex
  show (PointerToObject String
o Bool
ex)         = String
"&" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
show_ex Bool
ex
  show (AddressOfObject String
o Bool
ex)         = String
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
show_ex Bool
ex
  show (AddressOfLabel  String
l Bool
ex)         = String
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
show_ex Bool
ex
  show (Relocated_ResolvedObject String
o Word64
a) = String
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"@0x" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (if Word64
a Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0 then Word64 -> ShowS
forall a. Integral a => a -> ShowS
Numeric.showHex (Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a :: Word64) String
"" else Word64 -> ShowS
forall a. Integral a => a -> ShowS
Numeric.showHex Word64
a String
"")

show_ex :: Bool -> String
show_ex Bool
True  = String
"ex"
show_ex Bool
False = String
"in"



instance Cereal.Serialize Symbol