packages feed

bindings-bfd-1.2.0.0: src/Bindings/Bfd.hsc

-- This file is part of Bindings-bfd.
--
-- Copyright (C) 2010,2011 Mick Nelso
--
-- Bindings-bfd is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- Bindings-bfd is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU Lesser General Public License for more details.

-- You should have received a copy of the GNU Lesser General Public License
-- along with Bindings-bfd.  If not, see <http://www.gnu.org/licenses/>.

-- | This is the top-level module containing operations that can be performed
-- on a Binary Format Descriptor (BFD).  One BFD is opened for every binary file
-- to be queried\/manipulated and serves an opaque handle.  The usual workflow
-- is to 'open' a binary file (returning a 'Bfd'), perform operations on the
-- 'Bfd' handle, then 'close' the 'Bfd'. 

module Bindings.Bfd (
   -- * Types
     Bfd (ptr)
   -- * Library Initialization
   , initialize
   -- * File Operations
   , targetsAndFormats
   , open
   , close
   , closeAllDone
   -- * Setting the Format
   , checkFormat
   -- * Attributes
   , getDisasm
   , getFilename
   , Bindings.Bfd.getFlags
   , getFormat
   , getHasMap
   , getIsCacheable
   , getIsTargetDefaulted
   , getIsThinArchive
   , getMachine
   , getMyArchive
   , getOctetsPerByte
   , getTarget
   -- ** For Object Files
   , getStartAddress
   , getSymbolCount
   -- ** Sections
   , getSectionCount
   , getSectionByName
   , getSectionByVma
   , getSections
   -- ** Symbol Tables
   , getSymbolTable
   , getDynamicSymbolTable
   -- ** Relocations
   , getDynamicRelocations
   -- *
   , demangle
   , getPrintSymbol
   -- * Internal
   , Bfd'
   , Bindings.Bfd.mk
) where

import Control.Exception ( catch )
import Control.Monad     ( foldM )

import Data.Bits  ( (.&.), bit )
import Data.Word  ( Word )

import Foreign.C        ( CInt, CLong, CString, CUInt, newCString, peekCString
                        , withCString )
import Foreign.Marshal  ( free, mallocArray, peekArray, toBool )
import Foreign.Ptr      ( FunPtr, Ptr, nullPtr, wordPtrToPtr )
import Foreign.Storable ( Storable, alignment, peek, peekByteOff, poke, sizeOf )

import Prelude hiding ( catch )

import Bindings.Bfd.Disasm                        ( Disasm )
import Bindings.Bfd.Exception                     ( BfdException
                                                  , throwExceptionIfFalse
                                                  , throwExceptionIfNull )
import Bindings.Bfd.Flags         as BfdFlags     ( Flags ( HasReloc ) )
import Bindings.Bfd.Format                        ( Format ( Object ) )
import Bindings.Bfd.Misc                          ( File, Vma, Vma' )
import Bindings.Bfd.Relocation                    ( Relocation )
import Bindings.Bfd.Section       as Section      ( Section, SectionName
                                                  , getNext, getSize, getVma )
import Bindings.Bfd.Symbol                        ( Symbol )
import Bindings.Bfd.SymbolTable   as SymbolTable  ( SymbolTable, mk, tablePtr )
import Bindings.Bfd.Target        as Target       ( Target, TargetName, find
                                                  , getName, listSupported
                                                  , unTarget'CanonicalizeDynamicReloc
                                                  , unTarget'CanonicalizeDynamicSymtab
                                                  , unTarget'CanonicalizeSymtab
                                                  , unTarget'GetDynamicRelocUpperBound
                                                  , unTarget'GetDynamicSymtabUpperBound
                                                  , unTarget'GetSymtabUpperBound 
                                                  , unTarget'PrintSymbol )

#include <bfd.h>


-- ### PUBLIC ##################################################################

-- === Types ===================================================================

-- | The opaque handle to the Binary File Descriptor.  One 'Bfd' handle is
-- associated with exactly one binary file to be queried\/manipulated.
data Bfd = Bfd {
                       ptr       :: Ptr Bfd'
                     , filePath  :: CString
                     , target    :: CString
                     , mode      :: CString
           }
     deriving (Show)


-- === Library Initialization ==================================================

-- | Initialize the library.  You need to call 'initialize' once, before using 
-- any of the functions in this library.
initialize
   :: IO ()
initialize = c_bfd_init


-- === File Operations =========================================================

-- | Returns a list of tuples representing the possible combinations of 
-- 'TargetName' and 'Format' that are valid for the 'FilePath' on this platform
-- (see 'listSupported').
--
-- /Possible Exceptions:/  Same as 'open'.
targetsAndFormats 
   :: FilePath                   -- ^ file to query
   -> IO [(TargetName, Format)]
targetsAndFormats file =
   do
      ts <- Target.listSupported
      let
         perms = [ (t,f) | t <- ts, f <- enumFrom Object ]
      foldM g [] perms
   where
      g xs r@(t,f) =
         do
            bfd   <- open file (Just t) "r"
            xvec1 <- getTarget bfd
            tn1   <- Target.getName xvec1
            ok    <- catch (checkFormat bfd f) ((\_ -> return False) :: BfdException -> IO Bool)
            _     <- close bfd
            case ok of
               True  -> 
                  do
                     xvec2 <- getTarget bfd
                     tn2   <- Target.getName xvec2
                     if tn1 == tn2 
                         then return $ r : xs
                         else return xs
               False -> return xs

-- | Opens the 'FilePath' with the given 'TargetName' and /open mode/ as defined 
-- by the Unix fopen(3) function, and returns a 'Bfd' handle on success.
-- FIXME: and marks it cacheable.
--
-- Calls 'find'.  Refer to 'find' for a description of how the 'Target' is
-- selected.
--
-- /Important:/ Before using the returned 'Bfd' handle a call must be made to 
-- 'checkFormat' to 1) validate that the associated 'TargetName' is appropriate
-- for the file; and, 2) set the 'Format'.  So for most intents and purposes, 
-- opening a file is a two-step process:  'open' followed by 'checkFormat'.
--
-- /Possible Exceptions:/  'NoMemory' (if any allocation fails), 'SystemCall' 
-- (if open failed), and 'InvalidTarget' (if supplied target is unknown).
open
   :: FilePath          -- ^ file to open
   -> Maybe TargetName  -- ^ target
   -> String            -- ^ open mode (\"r\", \"r+\", \"w\", \"w+\", \"a\", \"a+\")
   -> IO Bfd
open fp targ mode0 =
   do
      fp'   <- newCString fp
      targ' <- 
         case targ of
            Just t  -> newCString t
            Nothing -> return nullPtr
      mode' <- newCString mode0
      let
         cmd = c_bfd_fopen fp' targ' mode' (-1)
      bfd <- throwExceptionIfNull "open" fp (show targ) cmd
      return $ Bfd bfd fp' targ' mode'

-- | Close a 'Bfd' handle and if all went well return 'True'.  Otherwise 
-- 'False'.
--
-- If the 'Bfd' was open for writing then pending operations are completed and
-- the file written out and closed.  If the created file is executable then 
-- /chmod(3)/ is called to mark it as such.
close
   :: Bfd
   -> IO Bool
close bfd = 
   do
      r <- c_bfd_close $ ptr bfd
      free $ filePath bfd
      free $ target bfd
      free $ mode bfd
      return $ toBool r

-- | Close a 'Bfd' handle and if all went well, return 'True'.  Otherwise 
-- 'False'.
--
-- Differs from 'close' in that it does not complete any pending operations.  
-- This function is used if the application had just used a 'Bfd' for swapping 
-- and didn't want to use any of the written code.  If the created file is
-- executable, then /chmod(3)/ is called to mark it as such.
closeAllDone
   :: Bfd
   -> IO Bool
closeAllDone bfd =
   do
      r <- c_bfd_close_all_done $ ptr bfd
      free $ filePath bfd
      free $ target bfd
      free $ mode bfd
      return $ toBool r


-- === Setting the Format ======================================================

-- | Before a 'Bfd' handle can be used, its 'Format' must be set exactly once.
--
-- This function also validates that the 'TargetName' used in the 'open' call is
-- appropriate for the file and if not silently picks a more suitable 
-- 'TargetName' from the available targets on the platform (see 'listSupported').
--
-- /Important:/ You must call this function before using the vast majority of
-- functions operating on the 'Bfd' handle as it updates critical data
-- structures.
--
-- /Possible Exceptions:/ 'InvalidOperation' (if the file was opened write-only),
checkFormat
   :: Bfd
   -> Format
   -> IO Bool
checkFormat bfd format =
   do
      res <- c_bfd_check_format (ptr bfd) $ fromIntegral $ fromEnum format
      throwExceptionIfFalse "checkFormat" (show format) (return $ toBool res)
{-
checkFormatMatches
   :: Bfd
   -> Format
   -> IO [TargetName]
-}


-- === Attributes ==============================================================

-- | Returns the disassembler associated with the 'Bfd'.
getDisasm
   :: Bfd
   -> IO Disasm
getDisasm bfd = c_disassembler $ ptr bfd

-- | Returns the 'FilePath' of the file associated with the 'Bfd'. 
getFilename
   :: Bfd
   -> IO FilePath
getFilename bfd =
   do
      fn <- peekByteOff (ptr bfd) (#offset struct bfd, filename)
      return $ unBfd'Filename fn

-- | Returns a 'List' of the 'Flags' set for the 'Bfd'.
getFlags
   :: Bfd
   -> IO [BfdFlags.Flags]
getFlags bfd =
   do
      flags <- peekByteOff (ptr bfd) (#offset struct bfd, flags)
      let
         flags' = filter f $ enumFrom HasReloc
            where
               f e = unBfd'Flags flags .&. (bit $ fromEnum e) /= 0
      return flags'

-- | Returns the 'Format' of the 'Bfd'.
getFormat
   :: Bfd
   -> IO Format
getFormat bfd =
   do
      format <- peekByteOff (ptr bfd) (#offset struct bfd, format)
      return $ unBfd'Format format

-- | Returns 'True' if the 'Bfd' has an archive map.  Otherwise 'False'.
getHasMap
   :: Bfd
   -> IO Bool
getHasMap bfd =
   do
      hm <- c__bfd_peek_has_armap $ ptr bfd
      return $ toBool hm

-- | Returns 'True' if the 'Bfd' is cacheable.  Otherwise 'False'.
getIsCacheable
   :: Bfd
   -> IO Bool
getIsCacheable bfd =
   do
      c <- c__bfd_peek_cacheable $ ptr bfd
      return $ toBool c

getIsTargetDefaulted
   :: Bfd
   -> IO Bool
getIsTargetDefaulted bfd =
   do
      td <- c__bfd_peek_target_defaulted $ ptr bfd
      return $ toBool td

-- | Returns 'True' if the 'Bfd' is a thin archive.  Otherwise 'False'.
getIsThinArchive
   :: Bfd
   -> IO Bool
getIsThinArchive bfd =
   do
      ita <- c__bfd_peek_is_thin_archive $ ptr bfd
      return $ toBool ita

getMachine
   :: Bfd
   -> IO Int
getMachine bfd = 
   do
      m <- c_bfd_get_mach $ ptr bfd
      return $ fromIntegral m

-- | Returns either a 'Bfd' or 'Nothing'.  FIXME
--
-- /Note:/ Do not pass the returned 'Bfd' to 'close' or 'closeAllDone' or a 
-- memory leak will occur.
getMyArchive
   :: Bfd
   -> IO (Maybe Bfd)
getMyArchive bfd =
   do
      ma <- peekByteOff (ptr bfd) (#offset struct bfd, my_archive)
      return $ case unBfd'MyArchive ma == nullPtr of
         True  -> Nothing
         False -> Just $ Bfd (unBfd'MyArchive ma) nullPtr nullPtr nullPtr

getOctetsPerByte
   :: Bfd
   -> IO Int
getOctetsPerByte bfd =
   do
      opb <- c_bfd_octets_per_byte $ ptr bfd
      return $ fromIntegral opb

-- | Returns the 'Target' of the 'Bfd'.
getTarget
   :: Bfd
   -> IO Target
getTarget bfd = 
   do
      xv <- peekByteOff (ptr bfd) (#offset struct bfd, xvec)
      return $ unBfd'XVec xv

-- For Object Files ------------------------------------------------------------

-- | Return the start address.  Only valid for 'Object' files.
getStartAddress
   :: Bfd
   -> IO Vma
getStartAddress bfd =
   do
      addr <- peekByteOff (ptr bfd) (#offset struct bfd, start_address)
      return $ unBfd'StartAddress addr

-- | Return the symbol count used for input and output.  Only valid for 'Object'
-- files.
-- FIXME:  returns 0 when there are symbols and in main/main too!
getSymbolCount
   :: Bfd
   -> IO Int
getSymbolCount bfd =
   do
      sc <- peekByteOff (ptr bfd) (#offset struct bfd, symcount)
      return $ unBfd'SymbolCount sc

-- Sections --------------------------------------------------------------------

-- | Returns the number of 'Section's in the 'Bfd'.
getSectionCount
   :: Bfd
   -> IO Int
getSectionCount bfd =
   do 
      c <- peekByteOff (ptr bfd) (#offset struct bfd, section_count)
      return $ unBfd'SectionCount c

getSectionByName
   :: Bfd
   -> SectionName
   -> IO Section
getSectionByName bfd sn = withCString sn (\s -> c_bfd_get_section_by_name (ptr bfd) s) 

getSectionByVma
   :: Bfd
   -> Int
   -> IO (Maybe Section)
getSectionByVma bfd vma =
   do
      sects <- getSections bfd
      foldM f Nothing sects
   where
      f xs@(Just _ ) _  = return xs
      f    (Nothing) xi =
         do
            sectVma  <- getVma xi
            sectSize <- getSize xi
            case vma >= sectVma && vma < sectVma + sectSize of
               True  -> return $ Just xi
               False -> return $ Nothing

getSections
   :: Bfd
   -> IO [Section]
getSections bfd =
   do
      (Sections first) <- peekByteOff (ptr bfd) (#offset struct bfd, sections)
      getSections' first []
   where
      getSections' sect rs
         | sect == nullPtr = return $ reverse rs
         | otherwise       =
              do
                 next <- getNext sect
                 getSections' next (sect : rs)

#if 0
createSections
   :: Bfd
   -> IO [(Section, Vma)]
createSections bfd = 
   do
      sects         <- getSections bfd
      extSect       <- Section.mk "externs" 5
      (_, sectList) <- foldM f (0,[]) $ sects ++ [extSect]
      return $ reverse sectList
   where
      f (vma,xs') sect =
         do
            (vma',snvma) <- createSection sect vma
            return (vma', snvma : xs')
#endif

-- Symbol Tables ---------------------------------------------------------------

getSymbolTable
   :: Bfd
   -> IO SymbolTable
getSymbolTable bfd =
   do
      bound <- getSymtabUpperBound bfd
      let
         ptrs = bound `quot` (#const sizeof(struct bfd_symbol *))
      pps <- mallocArray ptrs
      count <- canonicalizeSymtab bfd pps
      return $ SymbolTable.mk pps count

getDynamicSymbolTable
   :: Bfd
   -> IO SymbolTable
getDynamicSymbolTable bfd =
   do
      bound <- getDynamicSymtabUpperBound bfd
      let
         ptrs = fromIntegral bound `quot` (#const sizeof(struct bfd_symbol *))
      pps <- mallocArray ptrs
      count <- canonicalizeDynamicSymtab bfd pps
      return $ SymbolTable.mk pps count

#if 0
getSyntheticSymbolTable
   :: Bfd
   -> SymbolTable    -- static
   -> SymbolTable    -- dynamic
   -> IO SymbolTable
getSyntheticSymbolTable bfd sst dst =
   do
      xvec  <- getTarget bfd
      ssyms <- malloc
      count <- getSyntheticSymtab xvec bfd sst dst ssyms
      return $ SymbolTable.mk ssyms count
#endif

-- Relocations -----------------------------------------------------------------

getDynamicRelocations
   :: Bfd
   -> SymbolTable
   -> IO [Relocation]
getDynamicRelocations bfd st =
   do
      bound <- getDynamicRelocUpperBound bfd
      let
         ptrs = fromIntegral bound `quot` (#const sizeof(arelent *))
      ppr <- mallocArray ptrs
      count <- canonicalizeDynamicReloc bfd ppr $ tablePtr st
      prs <- peekArray count ppr
      mapM peek prs

-- =============================================================================

demangle
   :: Bfd
   -> String
   -> IO String
demangle bfd str =
   do
      s <- withCString str (\s -> c_bfd_demangle (ptr bfd) s 3)
      case s == nullPtr of
         True  -> return ""
         False ->
            do
               s' <- peekCString s
               return s'

getPrintSymbol
   :: Bfd
   -> File
   -> Symbol
   -> IO (IO ())
getPrintSymbol bfd file sym =
   do 
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_print_symbol)
      let
         f = d_Bfd_File_Symbol_CUInt_Void (unTarget'PrintSymbol fn) (ptr bfd) file sym 2
      return f

-- Internal ====================================================================

data Bfd' = Filename      String
          | XVec          Target
          | Format        Format
          | Flags         Int
          | Sections      Section
          | SectionCount  Int
          | StartAddress  Int
          | SymbolCount   Int
          | MyArchive    (Ptr Bfd')
     deriving (Show)

instance Storable Bfd' where
   sizeOf _ = #size struct bfd
   alignment = sizeOf
   peekByteOff buf off
      | off == (#offset struct bfd, filename) =
         do
            val <- (#peek struct bfd, filename) buf :: IO CString
            str <- peekCString val
            return $ Filename str
      | off == (#offset struct bfd, xvec) = 
         do
            val <- (#peek struct bfd, xvec) buf :: IO Word
            return $ XVec $ wordPtrToPtr $ fromIntegral val
      | off == (#offset struct bfd, format) =
         do
            val <- (#peek struct bfd, format) buf :: IO CUInt
            return $ Format $ toEnum $ fromIntegral val
      | off == (#offset struct bfd, flags) =
         do
            val <- (#peek struct bfd, flags) buf :: IO CUInt
            return $ Bindings.Bfd.Flags $ fromIntegral val
      | off == (#offset struct bfd, sections) =
         do
            val <- (#peek struct bfd, sections) buf
            return $ Sections val
      | off == (#offset struct bfd, section_count) =
         do
            val <- (#peek struct bfd, section_count) buf :: IO CUInt
            return $ SectionCount $ fromIntegral val
      | off == (#offset struct bfd, start_address) =
         do
            val <- (#peek struct bfd, start_address) buf :: IO Vma'
            return $ StartAddress $ fromIntegral val
      | off == (#offset struct bfd, symcount) =
         do
            val <- (#peek struct bfd, symcount) buf :: IO CUInt
            return $ SymbolCount $ fromIntegral val
      | off == (#offset struct bfd, my_archive) =
         do
            val <- (#peek struct bfd, my_archive) buf :: IO (Ptr Bfd')
            return $ MyArchive val
      | otherwise = error $ "internal error: Bfd.peekByteOff " ++ show off
   poke _ _ = return ()

mk
   :: Ptr Bfd'
   -> Bfd
mk p = Bfd p nullPtr nullPtr nullPtr

-- PRIVATE #####################################################################

canonicalizeDynamicReloc
   :: Bfd
   -> Ptr (Ptr Relocation)
   -> Ptr Symbol
   -> IO Int
canonicalizeDynamicReloc bfd rels syms =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_canonicalize_dynamic_reloc)
      r <- d_Bfd_PtrPtrRelocation_PtrSymbol_CLong (unTarget'CanonicalizeDynamicReloc fn) (ptr bfd) rels syms
      return $ fromIntegral r

canonicalizeDynamicSymtab
   :: Bfd
   -> Ptr Symbol
   -> IO Int
canonicalizeDynamicSymtab bfd ps =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_canonicalize_dynamic_symtab)
      r <- d_Bfd_PtrSymbol_CLong (unTarget'CanonicalizeDynamicSymtab fn) (ptr bfd) ps
      return $ fromIntegral r

canonicalizeSymtab
   :: Bfd
   -> Ptr Symbol
   -> IO Int
canonicalizeSymtab bfd ps =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_canonicalize_symtab)
      r <- d_Bfd_PtrSymbol_CLong (unTarget'CanonicalizeSymtab fn) (ptr bfd) ps
      return $ fromIntegral r

getDynamicRelocUpperBound
   :: Bfd
   -> IO Int
getDynamicRelocUpperBound bfd =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_get_dynamic_reloc_upper_bound)
      r <- d_Bfd_CLong (unTarget'GetDynamicRelocUpperBound fn) (ptr bfd)
      return $ fromIntegral r

getDynamicSymtabUpperBound
   :: Bfd
   -> IO Int
getDynamicSymtabUpperBound bfd =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_get_dynamic_symtab_upper_bound)
      r <- d_Bfd_CLong (unTarget'GetDynamicSymtabUpperBound fn) (ptr bfd)
      return $ fromIntegral r

getSymtabUpperBound
   :: Bfd
   -> IO Int
getSymtabUpperBound bfd =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_get_symtab_upper_bound)
      r <- d_Bfd_CLong (unTarget'GetSymtabUpperBound fn) $ ptr bfd
      return $ fromIntegral r

#if 0
getSyntheticSymtab
   :: Bfd
   -> SymbolTable
   -> SymbolTable
   -> Ptr Symbol
   -> IO Int
getSyntheticSymtab bfd sst dst synth =
   do
      targ <- getTarget bfd
      fn <- peekByteOff targ (#offset struct bfd_target, _bfd_get_synthetic_symtab)
      r <- d_Bfd_CLong_PtrSymbol_CLong_PtrSymbol_PtrSymbol_CLong (fn' fn) (ptr bfd) sts stp dts dtp synth
      return $ fromIntegral r
   where
      fn' = unTarget'GetSyntheticSymtab
      sts = fromIntegral $ tableSize sst
      stp = tablePtr sst
      dts = fromIntegral $ tableSize dst
      dtp = tablePtr dst
#endif

unBfd'Filename
   :: Bfd'
   -> String
unBfd'Filename (Filename fn) = fn
unBfd'Filename _             = error "unBfd'Filename"

unBfd'XVec
   :: Bfd'
   -> Target
unBfd'XVec (XVec p) = p
unBfd'XVec _        = error "unBfd'XVec"

unBfd'Format
   :: Bfd'
   -> Format
unBfd'Format (Format f) = f
unBfd'Format _          = error "unBfd'Format"

unBfd'Flags
   :: Bfd'
   -> Int
unBfd'Flags (Bindings.Bfd.Flags m) = m
unBfd'Flags _                      = error "unBfd'Flags"

unBfd'SectionCount
   :: Bfd'
   -> Int
unBfd'SectionCount (SectionCount c) = c
unBfd'SectionCount _                = error "unBfd'SectionCount"

unBfd'StartAddress
   :: Bfd'
   -> Vma
unBfd'StartAddress (StartAddress a) = a
unBfd'StartAddress _                = error "unBfd'StartAddress"

unBfd'SymbolCount
   :: Bfd'
   -> Int
unBfd'SymbolCount (SymbolCount c) = c
unBfd'SymbolCount _               = error "unBfd'SymbolCount"

unBfd'MyArchive
   :: Bfd'
   -> (Ptr Bfd')
unBfd'MyArchive (MyArchive ma) = ma
unBfd'MyArchive _              = error "unBfd'MyArchive"


foreign import ccall unsafe "bfd.h bfd_init" c_bfd_init
   :: IO ()

foreign import ccall unsafe "bfd.h bfd_fopen" c_bfd_fopen
   :: CString
   -> CString
   -> CString
   -> CInt
   -> IO (Ptr Bfd')

foreign import ccall unsafe "bfd.h bfd_close" c_bfd_close
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h bfd_close_all_done" c_bfd_close_all_done
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h bfd_check_format" c_bfd_check_format
   :: Ptr Bfd'
   -> CInt
   -> IO CInt

foreign import ccall unsafe "bfd.h bfd_get_mach" c_bfd_get_mach
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h bfd_octets_per_byte" c_bfd_octets_per_byte
   :: Ptr Bfd'
   -> IO CUInt

foreign import ccall unsafe "bfd.h bfd_get_section_by_name" c_bfd_get_section_by_name
   :: Ptr Bfd'
   -> CString
   -> IO Section

foreign import ccall unsafe "bfd.h bfd_demangle" c_bfd_demangle
   :: Ptr Bfd'
   -> CString
   -> CInt
   -> IO CString

foreign import ccall unsafe "dis-asm.h disassembler" c_disassembler
   :: Ptr Bfd'
   -> IO Disasm

foreign import ccall unsafe "bfd.h _bfd_peek_target_defaulted" c__bfd_peek_target_defaulted
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h _bfd_peek_cacheable" c__bfd_peek_cacheable
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h _bfd_peek_has_armap" c__bfd_peek_has_armap
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "bfd.h _bfd_peek_is_thin_archive" c__bfd_peek_is_thin_archive
   :: Ptr Bfd'
   -> IO CInt

foreign import ccall unsafe "dynamic" d_Bfd_CLong
   :: FunPtr (Ptr Bfd' -> IO CLong)
   -> (Ptr Bfd' -> IO CLong)

#if 0
foreign import ccall unsafe "dynamic" d_Bfd_CLong_PtrSymbol_CLong_PtrSymbol_PtrSymbol_CLong
   :: FunPtr (Ptr Bfd' -> CLong -> Ptr Symbol -> CLong -> Ptr Symbol -> Ptr Symbol -> IO CLong) 
   -> (Ptr Bfd' -> CLong -> Ptr Symbol -> CLong -> Ptr Symbol -> Ptr Symbol -> IO CLong)
#endif

foreign import ccall unsafe "dynamic" d_Bfd_File_Symbol_CUInt_Void
   :: FunPtr (Ptr Bfd' -> File -> Symbol -> CUInt -> IO ()) 
   -> (Ptr Bfd' -> File -> Symbol -> CUInt -> IO ())

foreign import ccall unsafe "dynamic" d_Bfd_PtrPtrRelocation_PtrSymbol_CLong
   :: FunPtr (Ptr Bfd' -> Ptr (Ptr Relocation) -> Ptr Symbol -> IO CLong) 
   -> (Ptr Bfd' -> Ptr (Ptr Relocation) -> Ptr Symbol -> IO CLong)

foreign import ccall unsafe "dynamic" d_Bfd_PtrSymbol_CLong
   :: FunPtr (Ptr Bfd' -> Ptr Symbol -> IO CLong)
   -> (Ptr Bfd' -> Ptr Symbol -> IO CLong)