module Bindings.Bfd.Section (
Section
, Section'
, SectionName
, Bindings.Bfd.Section.mk
, getAlignment
, setAlignment
, Bindings.Bfd.Section.getContents
, Bindings.Bfd.Section.getFlags
, getLimit
, getLma
, Bindings.Bfd.Section.getName
, Bindings.Bfd.Section.setName
, getNext
, getRawsize
, Bindings.Bfd.Section.getOutputSection
, setOutputSection
, getRelocatedContents
, getRelocations
, Bindings.Bfd.Section.getSize
, Bindings.Bfd.Section.getSymbol
, getVma
, setVma
, isAbsolute
, isCommon
, isExterns
, isUndefined
) where
import Data.Bits
import Foreign.C
import Foreign.Marshal
import Foreign.Ptr
import Foreign.Storable
import Bindings.Bfd
import Bindings.Bfd.LinkInfo as LinkInfo
import Bindings.Bfd.LinkOrder as LinkOrder
import Bindings.Bfd.Misc
import Bindings.Bfd.Relocation
import Bindings.Bfd.Section.Flags
import Bindings.Bfd.Symbol
import Bindings.Bfd.SymbolTable
type SectionName = String
type Contents = String
type Contents' = Ptr CChar
type Section = Ptr Section'
data Section' = Name SectionName
| Next Section
| Flags Int
| Vma Vma
| Lma Vma
| Size Size
| Rawsize Int
| OutputSection Section
| AlignmentPower Int
| Symbol Symbol
deriving (Show)
instance Storable Section' where
sizeOf _ = (184)
alignment = sizeOf
peekByteOff buf off
| off == ((0)) =
do
name <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
name' <- peekCString name
return $ Bindings.Bfd.Section.Name name'
| off == ((12)) =
do
next <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf
return $ Next next
| off == ((20)) =
do
flags <- ((\hsc_ptr -> peekByteOff hsc_ptr 20)) buf :: IO CUInt
return $ Bindings.Bfd.Section.Flags $ fromIntegral flags
| off == ((28)) =
do
vma <- ((\hsc_ptr -> peekByteOff hsc_ptr 28)) buf :: IO Vma'
return $ Vma $ fromIntegral vma
| off == ((36)) =
do
lma <- ((\hsc_ptr -> peekByteOff hsc_ptr 36)) buf :: IO Vma'
return $ Lma $ fromIntegral lma
| off == ((44)) =
do
size <- ((\hsc_ptr -> peekByteOff hsc_ptr 44)) buf :: IO Size'
return $ Size $ fromIntegral size
| off == ((52)) =
do
rawsize <- ((\hsc_ptr -> peekByteOff hsc_ptr 52)) buf :: IO Size'
return $ Rawsize $ fromIntegral rawsize
| off == ((80)) =
do
ap <- ((\hsc_ptr -> peekByteOff hsc_ptr 80)) buf
return $ AlignmentPower ap
| off == ((168)) =
do
sym <- ((\hsc_ptr -> peekByteOff hsc_ptr 168)) buf
return $ Bindings.Bfd.Section.Symbol sym
| otherwise = error $ "internal error: Bfd.Section'.peekByteOff " ++ show off
pokeByteOff buf off val
| off == ((0)) =
do
cs <- newCString $ unSection'Name val
((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf cs
| off == ((28)) =
((\hsc_ptr -> pokeByteOff hsc_ptr 28)) buf (unSection'Vma val)
| off == ((80)) =
((\hsc_ptr -> pokeByteOff hsc_ptr 80)) buf (unSection'AlignmentPower val)
| off == ((76)) =
((\hsc_ptr -> pokeByteOff hsc_ptr 76)) buf (unSection'OutputSection val)
| otherwise = error $ "internal error: Bfd.Section'.peekByteOff " ++ show off
mk
:: SectionName
-> Int
-> IO Section
mk name align =
do
sect <- malloc :: IO Section
Bindings.Bfd.Section.setName sect name
setAlignment sect align
setVma sect 0
return sect
getAlignment
:: Section
-> IO Int
getAlignment sect =
do
ap <- peekByteOff sect ((80))
return $ unSection'AlignmentPower ap
setAlignment
:: Section
-> Int
-> IO ()
setAlignment sect align = pokeByteOff sect ((80)) (AlignmentPower align)
getContents
:: Section
-> Bfd
-> FilePtr
-> Size
-> IO Contents
getContents sect bfd offset count = allocaArray count f
where
f ptr =
do
let
offset' = fromIntegral offset
count' = fromIntegral count
_ <- c_bfd_get_section_contents bfd sect ptr offset' count'
peekCAStringLen (ptr, count)
getFlags
:: Section
-> IO [Flags]
getFlags sect =
do
flags <- peekByteOff sect ((20))
let
flags' = filter f $ enumFrom Alloc
where
f e = unSection'Flags flags .&. (bit $ fromEnum e) /= 0
return flags'
getLimit
:: Section
-> Bfd
-> IO Int
getLimit sect bfd =
do
rs <- getRawsize sect
case rs == 0 of
True ->
do
sz <- Bindings.Bfd.Section.getSize sect
opb <- getOctetsPerByte bfd
return $ sz `quot` opb
False -> return rs
getLma
:: Section
-> IO Vma
getLma sect =
do
lma <- peekByteOff sect ((36))
return $ unSection'Lma lma
getName
:: Section
-> IO SectionName
getName sect =
do
n <- peekByteOff sect ((0))
return $ unSection'Name n
setName
:: Section
-> SectionName
-> IO ()
setName sect name = pokeByteOff sect ((0)) (Bindings.Bfd.Section.Name name)
getNext
:: Section
-> IO Section
getNext sect =
do
s <- peekByteOff sect ((12))
return $ unSection'Next s
getRawsize
:: Section
-> IO Size
getRawsize sect =
do
rs <- peekByteOff sect ((52))
return $ unSection'Rawsize rs
getOutputSection
:: Section
-> IO Section
getOutputSection sect =
do
os <- peekByteOff sect ((76))
return $ unSection'OutputSection os
setOutputSection
:: Section
-> Section
-> IO ()
setOutputSection sect1 sect2 = pokeByteOff sect1 ((76)) (OutputSection sect2)
getRelocations
:: Section
-> Bfd
-> SymbolTable
-> IO [Relocation]
getRelocations sect bfd st =
do
bound <- c_bfd_get_reloc_upper_bound bfd sect
let
ptrs = fromIntegral bound `quot` (4)
ppr <- mallocArray ptrs
count <- c_bfd_canonicalize_reloc bfd sect ppr $ tablePtr st
prs <- peekArray (fromIntegral count) ppr
mapM peek prs
getRelocatedContents
:: Section
-> Bfd
-> SymbolTable
-> IO Contents
getRelocatedContents sect bfd syms =
do
count <- Bindings.Bfd.Section.getSize sect
allocaArray count (f count)
where
f count ptr =
do
let
li = nullPtr
isR = fromBool False
lo <- LinkOrder.mk sect
setOutputSection sect sect
buf <- c_bfd_get_relocated_section_contents bfd li lo ptr isR $ tablePtr syms
case buf == nullPtr of
True -> error "bfd_get_relocated_section_contents failed"
False -> peekCAStringLen (buf, count)
getSize
:: Section
-> IO Size
getSize sect =
do
s <- peekByteOff sect ((44))
return $ unSection'Size s
getSymbol
:: Section
-> IO Symbol
getSymbol sect =
do
sym <- peekByteOff sect ((168))
return $ unSection'Symbol sym
getVma
:: Section
-> IO Vma
getVma sect =
do
s <- peekByteOff sect ((28))
return $ unSection'Vma s
setVma
:: Section
-> Vma
-> IO ()
setVma sect vma = pokeByteOff sect ((28)) (Vma vma)
isAbsolute
:: Section
-> Bool
isAbsolute sect = sect == c_bfd_abs_section
isCommon
:: Section
-> IO Bool
isCommon sect =
do
flags <- Bindings.Bfd.Section.getFlags sect
return $ IsCommon `elem` flags
isExterns
:: Section
-> IO Bool
isExterns sect =
do
n <- Bindings.Bfd.Section.getName sect
return $ n == "externs"
isUndefined
:: Section
-> Bool
isUndefined sect = sect == c_bfd_und_section
createSection
:: Section
-> Vma
-> IO (Vma, (Section, Vma))
createSection sect vma =
do
origVma <- getVma sect
size <- Bindings.Bfd.Section.getSize sect
case origVma of
0 ->
do
align <- getAlignment sect
let
vma' = alignToPower vma align
setVma sect vma'
return (vma' + size, (sect, vma'))
_ -> return (origVma + size, (sect, origVma))
unSection'Name
:: Section'
-> SectionName
unSection'Name (Bindings.Bfd.Section.Name n) = n
unSection'Name x = error $ "internal error: unSection'Name " ++ show x
unSection'Next
:: Section'
-> Section
unSection'Next (Next n) = n
unSection'Next x = error $ "internal error: unSection'Next " ++ show x
unSection'Flags
:: Section'
-> Int
unSection'Flags (Bindings.Bfd.Section.Flags f) = f
unSection'Flags x = error $ "internal error: unSection'Flags " ++ show x
unSection'Vma
:: Section'
-> Vma
unSection'Vma (Vma v) = v
unSection'Vma x = error $ "internal error: unSection'Vma " ++ show x
unSection'Lma
:: Section'
-> Vma
unSection'Lma (Lma l) = l
unSection'Lma _ = error "unSection'Lma"
unSection'Size
:: Section'
-> Size
unSection'Size (Size s) = s
unSection'Size x = error $ "internal error: unSection'Size " ++ show x
unSection'Rawsize
:: Section'
-> Size
unSection'Rawsize (Rawsize rs) = rs
unSection'Rawsize _ = error "unSection'Rawsize"
unSection'OutputSection
:: Section'
-> Section
unSection'OutputSection (OutputSection s) = s
unSection'OutputSection x = error $ "internal error: unSection'OutputSection " ++ show x
unSection'AlignmentPower
:: Section'
-> Int
unSection'AlignmentPower (AlignmentPower ap) = ap
unSection'AlignmentPower x = error $ "internal error: unSection'AlignmentPower " ++ show x
unSection'Symbol
:: Section'
-> Symbol
unSection'Symbol (Bindings.Bfd.Section.Symbol s) = s
unSection'Symbol x = error $ "internal error: unSection'Symbol " ++ show x
foreign import ccall unsafe "bfd.h bfd_get_section_contents" c_bfd_get_section_contents
:: Bfd
-> Section
-> Contents'
-> FilePtr'
-> Size'
-> IO Bool
foreign import ccall unsafe "bfd.h bfd_get_reloc_upper_bound" c_bfd_get_reloc_upper_bound
:: Bfd
-> Section
-> IO CLong
foreign import ccall unsafe "bfd.h bfd_canonicalize_reloc" c_bfd_canonicalize_reloc
:: Bfd
-> Section
-> Ptr (Ptr Relocation)
-> Ptr Symbol
-> IO CLong
foreign import ccall unsafe "bfd.h bfd_get_relocated_section_contents" c_bfd_get_relocated_section_contents
:: Bfd
-> LinkInfo
-> LinkOrder
-> Contents'
-> Bool'
-> Ptr Symbol
-> IO Contents'
foreign import ccall unsafe "bfd.h &bfd_und_section" c_bfd_und_section
:: Section
foreign import ccall unsafe "bfd.h &bfd_abs_section" c_bfd_abs_section
:: Section