{-# LANGUAGE DuplicateRecordFields #-}

module Binja.Symbol
  ( Binja.Symbol.create,
    Binja.Symbol.codeRefs,
    Binja.Symbol.print,
    Binja.Symbol.isFunction,
  )
where

import Binja.FFI
import Binja.ReferenceSource
import Binja.Types (BNBinaryViewPtr, BNReferenceSource, BNSymbolPtr, CInt, Symbol (..), SymbolBinding, SymbolType (..), Word64, peekCString)
import Binja.Utils

ty :: BNSymbolPtr -> IO SymbolType
ty :: BNSymbolPtr -> IO SymbolType
ty BNSymbolPtr
sym = do
  symTy <- BNSymbolPtr -> IO CInt
c_BNGetSymbolType BNSymbolPtr
sym
  pure $ toEnum $ fromIntegral symTy

binding :: BNSymbolPtr -> IO SymbolBinding
binding :: BNSymbolPtr -> IO SymbolBinding
binding BNSymbolPtr
sym = do
  symBinding <- BNSymbolPtr -> IO CInt
c_BNGetSymbolBinding BNSymbolPtr
sym
  pure $ toEnum $ fromIntegral symBinding

name :: BNSymbolPtr -> IO String
name :: BNSymbolPtr -> IO String
name BNSymbolPtr
sym = do
  rawName <- BNSymbolPtr -> IO CString
c_BNGetSymbolRawName BNSymbolPtr
sym
  peekCString rawName

shortName :: BNSymbolPtr -> IO String
shortName :: BNSymbolPtr -> IO String
shortName BNSymbolPtr
sym = do
  short <- BNSymbolPtr -> IO CString
c_BNGetSymbolShortName BNSymbolPtr
sym
  peekCString short

fullName :: BNSymbolPtr -> IO String
fullName :: BNSymbolPtr -> IO String
fullName BNSymbolPtr
sym = do
  full <- BNSymbolPtr -> IO CString
c_BNGetSymbolFullName BNSymbolPtr
sym
  peekCString full

address :: BNSymbolPtr -> IO Word64
address :: BNSymbolPtr -> IO Word64
address BNSymbolPtr
sym = do
  BNSymbolPtr -> IO Word64
c_BNGetSymbolAddress BNSymbolPtr
sym

ordinal :: BNSymbolPtr -> IO CInt
ordinal :: BNSymbolPtr -> IO CInt
ordinal BNSymbolPtr
sym = do
  BNSymbolPtr -> IO CInt
c_BNGetSymbolOrdinal BNSymbolPtr
sym

auto :: BNSymbolPtr -> IO Bool
auto :: BNSymbolPtr -> IO Bool
auto BNSymbolPtr
sym = do
  CBool -> Bool
toBool (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BNSymbolPtr -> IO CBool
c_BNIsSymbolAutoDefined BNSymbolPtr
sym

codeRefs :: BNBinaryViewPtr -> Symbol -> IO [BNReferenceSource]
codeRefs :: BNBinaryViewPtr -> Symbol -> IO [BNReferenceSource]
codeRefs BNBinaryViewPtr
view Symbol
sym = BNBinaryViewPtr -> Word64 -> IO [BNReferenceSource]
Binja.ReferenceSource.codeRefs BNBinaryViewPtr
view (Symbol -> Word64
Binja.Types.address Symbol
sym)

isFunction :: Symbol -> Bool
isFunction :: Symbol -> Bool
isFunction Symbol
sym =
  case Symbol -> SymbolType
Binja.Types.ty Symbol
sym of
    SymbolType
FunctionSymbol -> Bool
True
    SymbolType
ImportedFunctionSymbol -> Bool
True
    SymbolType
LibraryFunctionSymbol -> Bool
True
    SymbolType
_ -> Bool
False

create :: BNSymbolPtr -> IO Symbol
create :: BNSymbolPtr -> IO Symbol
create BNSymbolPtr
sym = do
  nameStr <- BNSymbolPtr -> IO String
Binja.Symbol.name BNSymbolPtr
sym
  t <- Binja.Symbol.ty sym
  b <- Binja.Symbol.binding sym
  addr <- Binja.Symbol.address sym
  a <- Binja.Symbol.auto sym
  pure
    Binja.Types.Symbol
      { name = nameStr,
        ty = t,
        binding = b,
        address = addr,
        auto = a
      }

print :: BNSymbolPtr -> IO ()
print :: BNSymbolPtr -> IO ()
print BNSymbolPtr
sym = do
  nameStr <- BNSymbolPtr -> IO String
Binja.Symbol.name BNSymbolPtr
sym
  t <- Binja.Symbol.ty sym
  b <- Binja.Symbol.binding sym
  sname <- Binja.Symbol.shortName sym
  fname <- Binja.Symbol.fullName sym
  addr <- Binja.Symbol.address sym
  ord <- Binja.Symbol.ordinal sym
  isAuto <- Binja.Symbol.auto sym
  putStrLn "==============================="
  putStrLn ("Name      : " ++ nameStr)
  putStrLn ("Type      : " ++ show t)
  putStrLn ("Binding   : " ++ show b)
  putStrLn ("ShortName : " ++ sname)
  putStrLn ("FullName  : " ++ fname)
  putStrLn ("Address   : " ++ show addr)
  putStrLn ("Ordinal   : " ++ show ord)
  putStrLn ("Auto      : " ++ show isAuto)