module Bindings.Bfd.SymbolTable where
import Control.Monad
import Data.Char
import Data.List
import qualified Data.Map as Map
import Foreign.Marshal
import Foreign.Ptr
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
-> [(Section, Vma)]
-> IO SymbolTable
resolveExterns symt sectList =
do
syms <- toList symt
undefs <- filterM getUndefs syms
let
(extSect, extVma) = last sectList
foldM_ pointToExtern (extSect, extVma) undefs
map' <- sectMap
mapM_ (sectSymValue map') syms
return symt
where
sectSymValue map0 sym =
do
sect <- getSection sym
case isAbsolute sect of
True -> return ()
False ->
do
name <- Section.getName sect
value <- getValue sym
let
t =
case Map.lookup name map0 of
Just v -> v
Nothing -> error $ "lookup on sect: " ++ show name ++ " " ++ show value ++ "\n" ++ show map0
setValue sym $ value + t
pointToExtern (es,ev) sym =
do
setValue sym ev
setSection sym es
return (es, ev + externSpacing)
getUndefs sym =
do
sect <- getSection sym
return $ isUndefined sect
sectMap =
do
sectList' <- mapM (\(s,v) -> Section.getName s >>= \n -> return (n,v)) sectList
return $ Map.fromList sectList'
externSpacing
:: Int
externSpacing = 8