content: {-|
  Copyright   : (c) Galois Inc, 2015-2018
  Maintainer  : jhendrix@galois.com
  
  Defines constructors for precisely capturing symbol table information.
  -}
  module Data.Macaw.Memory.Symbols
    ( -- * Symbols
      SymbolInfo(..)
    , SymbolBinding(..)
    , Data.BinarySymbols.SymbolVersion(..)
      -- ** Defined symbol information
    , SymbolPrecedence(..)
    , SymbolDefType(..)
      -- ** Undefined symbol infomration
    , SymbolRequirement(..)
    , SymbolUndefType(..)
    ) where
  
  import           Data.BinarySymbols
  import qualified Data.ByteString as BS
  
  -- | Describes symbol precedence
  data SymbolPrecedence
     = SymbolStrong
       -- ^ Symbol has high precedence
     | SymbolLocal
       -- ^ The symbol has high precedence, but only visible within the
       -- object file that created it.
     | SymbolWeak
       -- ^ Symbol has low precedence
  
  -- | This denotes type information associated with a defined
  data SymbolDefType
     = SymbolDefUnknown
       -- ^ We do not know what type of object this refers to.
     | SymbolDefFunc
       -- ^ This symbol denotes a defined function.
     | SymbolDefObject
       -- ^ This symbol denotes a object.
     | SymbolDefThreadLocal
       -- ^ This symbol denotes a thread local identifier
     | SymbolDefIFunc
       -- ^ This symbol is a "IFUNC" (e.g., it calls a function to resolve the symbol)
     | SymbolDefNoType
       -- ^ This symbol does not have a specified type.
  
  
  -- | Describes whether an undefined symbol is required during linking.
  data SymbolRequirement
     = SymbolRequired
       -- ^ Undefined symbol must be found during linking
     | SymbolOptional
       -- ^ Undefined symbol treated as zero if not found during linking.
  
  -- | Flags information about an undefined symbol.
  data SymbolUndefType
     = SymbolUndefThreadLocal
       -- ^ This symbol denotes data stored in a thread.
     | SymbolUndefNoType
       -- ^ This is stored globally for application, but otherwise has
       -- no type information.
       --
       -- Concretely we have seen this symbol type generated by gcc for
       -- external functions and data and _GLOBAL_OFFSET_TABLE_
     | SymbolUndefFunc
       -- ^ This symbol is intended to denote a function.
     | SymbolUndefObject
       -- ^ This symbol is intended to denote some data.
  
  -- | This defines information about the symbol related to whether
  -- it is defined (and if so how it binds) or undefined (and if so what
  -- requiremens there are for a match).
  data SymbolBinding
     = DefinedSymbol !SymbolPrecedence !SymbolDefType
       -- ^ The symbol is defined and globally visible.
       --
       -- The strong symbol flag controls the precedence.  If true, then
       -- this definition must be used for the symbol with that name,
       -- and the linker is not allowed to replace the symbol.  Is
       -- false, then the linker will use a strong symbol if it exists,
       -- and one of the weak symbols if it does not.
       --
       -- The address is the address the symbol was loaded at.  It may
       -- not be a valid segment offset if the original binary used
       -- symbols at unexpected addresses.
     | SymbolSection !SectionIndex
       -- ^ The symbol denotes a section in an object file with the
       -- given index.  These are primarily intended for relocations.
       --
       -- The symbol version should be @UnversionedSymbol@ with this.
     | SymbolFile !BS.ByteString
       -- ^ This symbol denotes a file name with the given string
       --
       -- The symbol version should be @UnversionedSymbol@ with this.
     | UndefinedSymbol !SymbolRequirement !SymbolUndefType
       -- ^ An undefined symbol
       --
       -- The Boolean flag controls whether the symbol must be defined.
       -- If it is @False@ and the linker cannot find a definition, then
       -- it just treats the symbol address as @0@.  If it is @True@ and
       -- the linker cannot find a definition, then it must throw an
       -- error.
  
  -- | This provides information about a symbol in the file.
  data SymbolInfo =
    SymbolInfo { symbolName :: !SymbolName
                 -- ^ The name of the symbol
                 --
                 -- Symbols are used for many purposes in a file.
                 -- Symbol names may not be unique, and may even be
                 -- empty.  For example, Elf files uses the empty name
                 -- for section symbols.  On ARM, "$a", "$d" and "$t"
                 -- are used to indicate regions of ARM code, data, thumb.
               , symbolVersion :: !SymbolVersion
                 -- ^ Version information used to constrain when one
                 -- symbol matches another.
               , symbolDef :: !SymbolBinding
               }
  