{-# LANGUAGE DuplicateRecordFields #-}
module Binja.AnalysisContext
( Binja.AnalysisContext.create,
Binja.AnalysisContext.symbolAt,
Binja.AnalysisContext.callers,
Binja.AnalysisContext.extractCallDestSymbol,
Binja.AnalysisContext.summary,
Binja.AnalysisContext.close,
)
where
import Binja.BinaryView
import Binja.ControlFlowGraph
import Binja.FFI (c_BNGetEntryPoint, c_BNGetImageBase)
import Binja.Function
import Binja.Mlil
import Binja.Types.Core
import Binja.Utils
import Data.Map as Map
import Data.Maybe (catMaybes)
import Data.Set as Set
import Numeric (showHex)
create ::
String ->
String ->
IO AnalysisContext
create :: String -> String -> IO AnalysisContext
create String
filename' String
options = do
viewHandle' <- String -> String -> IO BNBinaryViewPtr
Binja.BinaryView.load String
filename' String
options
functions' <- Binja.BinaryView.functions viewHandle'
functionContexts <- mapM createFunctionContext functions'
entryFunction' <- Binja.BinaryView.entryFunction viewHandle'
entryFunctionContext <- traverse createFunctionContext entryFunction'
entryFunctions' <- Binja.BinaryView.entryFunctions viewHandle'
entryFunctionContexts <- mapM createFunctionContext entryFunctions'
symbols' <- Binja.BinaryView.symbols viewHandle'
strings' <- catMaybes <$> Binja.BinaryView.strings viewHandle'
imageBase' <- c_BNGetImageBase viewHandle'
entryPoint' <- c_BNGetEntryPoint viewHandle'
segments' <- Binja.BinaryView.segments viewHandle'
sections' <- Binja.BinaryView.sections viewHandle'
dataVars' <- Prelude.filter (\DataVariable {typeConfidence :: DataVariable -> Word8
typeConfidence = Word8
tc} -> Word8
tc Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
255) <$> Binja.BinaryView.dataVars viewHandle'
pure
AnalysisContext
{ viewHandle = viewHandle',
filename = filename',
functions = functionContexts,
entryFunction = entryFunctionContext,
entryFunctions = entryFunctionContexts,
symbols = symbols',
strings = strings',
imageBase = imageBase',
entryPoint = entryPoint',
dataVars = dataVars',
segments = segments',
sections = sections'
}
createFunctionContext :: BNFunctionPtr -> IO FunctionContext
createFunctionContext :: BNFunctionPtr -> IO FunctionContext
createFunctionContext BNFunctionPtr
handle' = do
mlilSSAHandle <- BNFunctionPtr -> IO BNMlilSSAFunctionPtr
Binja.Function.mlilSSA BNFunctionPtr
handle'
start' <- Binja.Function.start handle'
symbol' <- Binja.Function.symbol handle'
auto' <- Binja.Function.auto handle'
instructions' <- Binja.Mlil.instructionsFromFuncNoChildren mlilSSAHandle
ssaVariables' <- Binja.Function.ssaVars mlilSSAHandle
ssaVarContext' <- Map.fromList <$> mapM (\BNSSAVariable
l -> BNSSAVariable
-> BNMlilSSAFunctionPtr -> IO (BNSSAVariable, SSAVariableContext)
createSSAVariableContext BNSSAVariable
l BNMlilSSAFunctionPtr
mlilSSAHandle) ssaVariables'
aliasedVars' <- Binja.Function.aliasedVars mlilSSAHandle
parameterVars' <- Binja.Function.parameterVars mlilSSAHandle
architecture' <- Binja.Function.architecture mlilSSAHandle
cfg' <- Binja.ControlFlowGraph.create mlilSSAHandle
pure
FunctionContext
{ handle = mlilSSAHandle,
start = start',
symbol = symbol',
auto = auto',
ssaVars = ssaVarContext',
parameterVars = parameterVars',
aliasedVars = aliasedVars',
instructions = instructions',
architecture = architecture',
cfg = cfg'
}
createSSAVariableContext :: BNSSAVariable -> BNMlilSSAFunctionPtr -> IO (BNSSAVariable, SSAVariableContext)
createSSAVariableContext :: BNSSAVariable
-> BNMlilSSAFunctionPtr -> IO (BNSSAVariable, SSAVariableContext)
createSSAVariableContext BNSSAVariable
var' BNMlilSSAFunctionPtr
func = do
defSite' <- BNSSAVariable
-> BNMlilSSAFunctionPtr -> IO (Maybe MediumLevelILSSAInstruction)
Binja.Mlil.defSite BNSSAVariable
var' BNMlilSSAFunctionPtr
func
useSites' <- Binja.Mlil.useSites var' func
pure $ (var', SSAVariableContext {defSite = defSite', useSites = useSites'})
symbolAt :: AnalysisContext -> Word64 -> Maybe Symbol
symbolAt :: AnalysisContext -> Word64 -> Maybe Symbol
symbolAt AnalysisContext {symbols :: AnalysisContext -> [Symbol]
symbols = [Symbol]
syms} Word64
requestAddr =
case (Symbol -> Bool) -> [Symbol] -> [Symbol]
forall a. (a -> Bool) -> [a] -> [a]
Prelude.filter (\Symbol {address :: Symbol -> Word64
address = Word64
addr} -> (Word64
requestAddr Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
==) Word64
addr) [Symbol]
syms of
[] -> Maybe Symbol
forall a. Maybe a
Nothing
[Symbol
sym] -> Symbol -> Maybe Symbol
forall a. a -> Maybe a
Just Symbol
sym
[Symbol]
_ -> String -> Maybe Symbol
forall a. HasCallStack => String -> a
error (String -> Maybe Symbol) -> String -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ String
"Binja.AnalysisContext.symbolAt: Multiple symbols at: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show Word64
requestAddr
constantToSymbol :: AnalysisContext -> Constant -> Maybe Symbol
constantToSymbol :: AnalysisContext -> Constant -> Maybe Symbol
constantToSymbol AnalysisContext
context (MediumLevelILConstPtr (MediumLevelILConstPtrRec {constant :: MediumLevelILConstPtrRec -> Int
constant = Int
c})) = do
AnalysisContext -> Word64 -> Maybe Symbol
Binja.AnalysisContext.symbolAt AnalysisContext
context (Word64 -> Maybe Symbol) -> Word64 -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
c
constantToSymbol AnalysisContext
context (MediumLevelILImport (MediumLevelILImportRec {constant :: MediumLevelILImportRec -> Int
constant = Int
c})) = do
AnalysisContext -> Word64 -> Maybe Symbol
Binja.AnalysisContext.symbolAt AnalysisContext
context (Word64 -> Maybe Symbol) -> Word64 -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
c
constantToSymbol AnalysisContext
_ (MediumLevelILConst (MediumLevelILConstRec {constant :: MediumLevelILConstRec -> Int
constant = Int
c})) = do
String -> Maybe Symbol
forall a. HasCallStack => String -> a
error (String -> Maybe Symbol) -> String -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ String
"Unhandled constant: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
c
constantToSymbol AnalysisContext
_ (MediumLevelILFloatConst MediumLevelILFloatConstRec {constant :: MediumLevelILFloatConstRec -> Double
constant = Double
c}) = do
String -> Maybe Symbol
forall a. HasCallStack => String -> a
error (String -> Maybe Symbol) -> String -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ String
"Unhandled float constant: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
c
constantToSymbol AnalysisContext
_ (MediumLevelILConstData MediumLevelILConstDataRec {constant :: MediumLevelILConstDataRec -> BNDataBufferPtr
constant = BNDataBufferPtr
c}) = do
String -> Maybe Symbol
forall a. HasCallStack => String -> a
error (String -> Maybe Symbol) -> String -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ String
"Unhandled constant data: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ BNDataBufferPtr -> String
forall a. Show a => a -> String
show BNDataBufferPtr
c
constantToSymbol AnalysisContext
context (MediumLevelILExternPtr MediumLevelILExternPtrRec {constant :: MediumLevelILExternPtrRec -> Int
constant = Int
c}) = do
AnalysisContext -> Word64 -> Maybe Symbol
Binja.AnalysisContext.symbolAt AnalysisContext
context (Word64 -> Maybe Symbol) -> Word64 -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
c
extractCallDestSymbol :: AnalysisContext -> MediumLevelILSSAInstruction -> Maybe Symbol
AnalysisContext
context MediumLevelILSSAInstruction
callInst =
case MediumLevelILSSAInstruction
callInst of
Localcall Localcall
lc ->
case Localcall
lc of
(MediumLevelILCallSsa MediumLevelILCallSsaRec {dest :: MediumLevelILCallSsaRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
(MediumLevelILCallUntypedSsa MediumLevelILCallUntypedSsaRec {dest :: MediumLevelILCallUntypedSsaRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
Tailcall Tailcall
tc ->
case Tailcall
tc of
(MediumLevelILTailcallUntyped MediumLevelILTailcallUntypedRec {dest :: MediumLevelILTailcallUntypedRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
(MediumLevelILTailcall MediumLevelILTailcallRec {dest :: MediumLevelILTailcallRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
(MediumLevelILTailcallSsa MediumLevelILTailcallSsaRec {dest :: MediumLevelILTailcallSsaRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
(MediumLevelILTailcallUntypedSsa MediumLevelILTailcallUntypedSsaRec {dest :: MediumLevelILTailcallUntypedSsaRec -> MediumLevelILSSAInstruction
dest = MediumLevelILSSAInstruction
d}) -> MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
d
MediumLevelILSSAInstruction
_ -> String -> Maybe Symbol
forall a. HasCallStack => String -> a
error (String -> Maybe Symbol) -> String -> Maybe Symbol
forall a b. (a -> b) -> a -> b
$ String
"Binja.AnalysisContext.extractCallDestSymbol: unhandled instruction: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ MediumLevelILSSAInstruction -> String
forall a. Show a => a -> String
show MediumLevelILSSAInstruction
callInst
where
processDest :: MediumLevelILSSAInstruction -> Maybe Symbol
processDest :: MediumLevelILSSAInstruction -> Maybe Symbol
processDest MediumLevelILSSAInstruction
dest' =
case MediumLevelILSSAInstruction
dest' of
Constant Constant
c -> AnalysisContext -> Constant -> Maybe Symbol
Binja.AnalysisContext.constantToSymbol AnalysisContext
context Constant
c
MediumLevelILSSAInstruction
_ -> Maybe Symbol
forall a. Maybe a
Nothing
callers :: AnalysisContext -> FunctionContext -> Set.Set Symbol
callers :: AnalysisContext -> FunctionContext -> Set Symbol
callers AnalysisContext
analysisContext FunctionContext {instructions :: FunctionContext -> [MediumLevelILSSAInstruction]
instructions = [MediumLevelILSSAInstruction]
insts} =
[Symbol] -> Set Symbol
forall a. Ord a => [a] -> Set a
Set.fromList ([Symbol] -> Set Symbol) -> [Symbol] -> Set Symbol
forall a b. (a -> b) -> a -> b
$
[Maybe Symbol] -> [Symbol]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Symbol] -> [Symbol]) -> [Maybe Symbol] -> [Symbol]
forall a b. (a -> b) -> a -> b
$
(MediumLevelILSSAInstruction -> Maybe Symbol)
-> [MediumLevelILSSAInstruction] -> [Maybe Symbol]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map (AnalysisContext -> MediumLevelILSSAInstruction -> Maybe Symbol
Binja.AnalysisContext.extractCallDestSymbol AnalysisContext
analysisContext) ([MediumLevelILSSAInstruction] -> [Maybe Symbol])
-> [MediumLevelILSSAInstruction] -> [Maybe Symbol]
forall a b. (a -> b) -> a -> b
$
(MediumLevelILSSAInstruction -> Bool)
-> [MediumLevelILSSAInstruction] -> [MediumLevelILSSAInstruction]
forall a. (a -> Bool) -> [a] -> [a]
Prelude.filter MediumLevelILSSAInstruction -> Bool
isCall ([MediumLevelILSSAInstruction] -> [MediumLevelILSSAInstruction])
-> [MediumLevelILSSAInstruction] -> [MediumLevelILSSAInstruction]
forall a b. (a -> b) -> a -> b
$
[[MediumLevelILSSAInstruction]] -> [MediumLevelILSSAInstruction]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[MediumLevelILSSAInstruction]] -> [MediumLevelILSSAInstruction])
-> [[MediumLevelILSSAInstruction]] -> [MediumLevelILSSAInstruction]
forall a b. (a -> b) -> a -> b
$
(MediumLevelILSSAInstruction -> [MediumLevelILSSAInstruction])
-> [MediumLevelILSSAInstruction] -> [[MediumLevelILSSAInstruction]]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map MediumLevelILSSAInstruction -> [MediumLevelILSSAInstruction]
Binja.Mlil.children [MediumLevelILSSAInstruction]
insts
where
isCall :: MediumLevelILSSAInstruction -> Bool
isCall :: MediumLevelILSSAInstruction -> Bool
isCall (Localcall Localcall
_) = Bool
True
isCall (Tailcall Tailcall
_) = Bool
True
isCall (Syscall Syscall
_) = Bool
True
isCall MediumLevelILSSAInstruction
_ = Bool
False
close :: AnalysisContext -> IO ()
close :: AnalysisContext -> IO ()
close = BNBinaryViewPtr -> IO ()
Binja.BinaryView.close (BNBinaryViewPtr -> IO ())
-> (AnalysisContext -> BNBinaryViewPtr) -> AnalysisContext -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnalysisContext -> BNBinaryViewPtr
viewHandle
summary :: AnalysisContext -> IO String
summary :: AnalysisContext -> IO String
summary AnalysisContext
analysisContext = do
colors <- IO Colors
Binja.Utils.getColors
let functionCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [FunctionContext] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([FunctionContext] -> Int) -> [FunctionContext] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [FunctionContext]
Binja.Types.Core.functions AnalysisContext
analysisContext
bbCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (FunctionContext -> Int) -> [FunctionContext] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map ([BasicBlockMlilSSA] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([BasicBlockMlilSSA] -> Int)
-> (FunctionContext -> [BasicBlockMlilSSA])
-> FunctionContext
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFGContext -> [BasicBlockMlilSSA]
blocks (CFGContext -> [BasicBlockMlilSSA])
-> (FunctionContext -> CFGContext)
-> FunctionContext
-> [BasicBlockMlilSSA]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FunctionContext -> CFGContext
cfg) ([FunctionContext] -> [Int]) -> [FunctionContext] -> [Int]
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [FunctionContext]
Binja.Types.Core.functions AnalysisContext
analysisContext
entryFunction' =
case AnalysisContext -> Maybe FunctionContext
Binja.Types.Core.entryFunction AnalysisContext
analysisContext of
Maybe FunctionContext
Nothing -> Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"No entry function."
Just FunctionContext
f -> String
"Entry function: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Symbol -> String
forall a. Show a => a -> String
show (Symbol -> String) -> Symbol -> String
forall a b. (a -> b) -> a -> b
$ FunctionContext -> Symbol
Binja.Types.Core.symbol FunctionContext
f)
entryFunctions' = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [FunctionContext] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([FunctionContext] -> Int) -> [FunctionContext] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [FunctionContext]
Binja.Types.Core.entryFunctions AnalysisContext
analysisContext
stringCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> [String] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [String]
Binja.Types.Core.strings AnalysisContext
analysisContext
symbolCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [Symbol] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Symbol] -> Int) -> [Symbol] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [Symbol]
Binja.Types.Core.symbols AnalysisContext
analysisContext
dataVarCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [DataVariable] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([DataVariable] -> Int) -> [DataVariable] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [DataVariable]
Binja.Types.Core.dataVars AnalysisContext
analysisContext
imageBase' = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (String
"0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (Word64 -> String -> String) -> String -> Word64 -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word64 -> String -> String
forall a. Integral a => a -> String -> String
showHex String
"" (Word64 -> String) -> Word64 -> String
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> Word64
Binja.Types.Core.imageBase AnalysisContext
analysisContext
entryPoint' = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (String
"0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (Word64 -> String -> String) -> String -> Word64 -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word64 -> String -> String
forall a. Integral a => a -> String -> String
showHex String
"" (Word64 -> String) -> Word64 -> String
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> Word64
Binja.Types.Core.entryPoint AnalysisContext
analysisContext
segmentCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [Segment] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Segment] -> Int) -> [Segment] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [Segment]
Binja.Types.Core.segments AnalysisContext
analysisContext
sectionCount = Colors -> String -> String
magenta Colors
colors (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [Section] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Section] -> Int) -> [Section] -> Int
forall a b. (a -> b) -> a -> b
$ AnalysisContext -> [Section]
Binja.Types.Core.sections AnalysisContext
analysisContext
pure $
" ["
++ (green colors) "+"
++ "] Filename: "
++ (magenta colors $ filename analysisContext)
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Function count: "
++ functionCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Mlil basic block count: "
++ bbCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Entry Function: "
++ entryFunction'
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Entry Functions count: "
++ entryFunctions'
++ "\n"
++ " ["
++ (green colors) "+"
++ "] String count: "
++ stringCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Symbol count: "
++ symbolCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Full confidence DataVariable count: "
++ dataVarCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Image base address: "
++ imageBase'
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Entry point address: "
++ entryPoint'
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Segment count: "
++ segmentCount
++ "\n"
++ " ["
++ (green colors) "+"
++ "] Section count: "
++ sectionCount
++ "\n"