module Bindings.Bfd.SymbolTable where
import Control.Monad
import Data.Char
import qualified Data.IntMap as IntMap
import Data.List
import Foreign.Marshal
import Foreign.Ptr
import Bindings.Bfd
import Bindings.Bfd.Disasm.I386.Insn
import Bindings.Bfd.Misc
import Bindings.Bfd.Section as Section
import Bindings.Bfd.Symbol as Symbol
data SymbolTable = SymbolTable {
tablePtr :: Ptr Symbol
, tableSize :: Int
}
deriving Show
mk
:: Ptr Symbol
-> Int
-> SymbolTable
mk = SymbolTable
toList
:: SymbolTable
-> IO [Symbol]
toList st = peekArray (tableSize st) (tablePtr st)
uniqifyNames
:: SymbolTable
-> IO SymbolTable
uniqifyNames symt =
do
x1 <- toList symt
x2 <- mapM (\s -> Symbol.getName s) x1
let
x3 = zip (x2 \\ nub x2) ([0..] :: [Int])
x4 = zip x2 ([0..] :: [Int])
x5 = sort $ intersectBy (\(a,_) (b,_) -> a == b) x4 x3
x6 = snd $ foldl f (("aa", ""),[]) x5
where
f ((post@(ch1:ch0:[]), match), xs) xi
| match == fst xi = ((post', match ), (fst xi ++ "_" ++ post, snd xi) : xs)
| otherwise = (("ab" , fst xi), (fst xi ++ "_aa" , snd xi) : xs)
where
post' =
case ch0 == 'z' of
True -> (chr $ ord ch1 + 1) : ['a' ]
False -> ch1 : [chr $ ord ch0 + 1]
f _ _ = error "f in uniqifyNames"
mapM_ (\(name,ix) -> setName (x1 !! ix) name) x6
return symt
resolveExterns
:: SymbolTable
-> Bfd
-> IO (SymbolTable, Section, IntMap.IntMap Insn)
resolveExterns symTab bfd =
do
let
align = 3
externsSect <- Section.mk externsName align
sects <- getSections bfd
let
lastSect = last sects
lastSectVma <- getVma lastSect
lastSectSize <- Section.getSize lastSect
let
externsVma = alignToPower (lastSectVma + lastSectSize) align
setVma externsSect externsVma
syms <- toList symTab
let
isUndef sym =
do
sect <- getSection sym
return $ isUndefined sect
undefs <- filterM isUndef syms
let
pointToExtern (vma, cs) sym =
do
setValue sym vma
setSection sym externsSect
name <- Symbol.getName sym
return (vma + externSpacing, (vma, Extern name) : cs)
(_,externs) <- foldM pointToExtern (externsVma,[]) undefs
return (symTab, externsSect, IntMap.fromList externs)
externSpacing
:: Int
externSpacing = 8