- Look for the next function that needs to have its info table
- arranged to be before it and process it. This will print out
- any code before this function, then the info table, then the
- function. It will return the remainder of the assembly code
- to process.
-
- We rely here on the fact that LLVM prints all global variables
- at the end of the file, so an info table will always appear
- after its function.
-
- To try to help explain the string searches, here is some
- assembly code that would be processed by this program, with
- split markers placed in it like so, <split marker>:
-
- [ ...asm code... ]
- jmp *%eax
- <before|fheader>
- .def Main_main_info
- .section TEXT
- .globl _Main_main_info
- _Main_main<bl|al>_info:
- sub $12, %esp
- [ ...asm code... ]
- jmp *%eax
- <fun|after>
- .def .....
-
- [ ...asm code... ]
-
- .long 231231
- <bit'|itable_h>
- .section TEXT
- .global _Main_main_entry
- .align 4
- <bit|itable>_Main_main_entry:
- .long 0
- [ ...asm code... ]
- <itable'|ait>
- .section TEXT
+ Here we process the assembly file one function and data
+ definition at a time. When a function is encountered that
+ should have a info table we store it in a map. Otherwise
+ we print it. When an info table is found we retrieve its
+ function from the map and print them both.
+
+ For all functions we fix up the stack alignment. We also
+ fix up the section definition for functions and info tables.
+-}
+fixTables :: Handle -> Handle -> I.IntMap B.ByteString -> IO ()
+fixTables r w m = do
+ f <- getFun r B.empty
+ if B.null f
+ then return ()
+ else let fun = fixupStack f B.empty
+ (a,b) = B.breakSubstring infoSec fun
+ (a',s) = B.breakEnd eolPred a
+ -- We search for the section header in two parts as it makes
+ -- us portable across OS types and LLVM version types since
+ -- section names are wrapped differently.
+ secHdr = secStmt `B.isPrefixOf` s
+ (x,c) = B.break eolPred b
+ fun' = a' `B.append` newInfoSec `B.append` c
+ n = readInt $ B.takeWhile isDigit $ B.drop infoLen x
+ (bs, m') | B.null b || not secHdr = ([fun], m)
+ | even n = ([], I.insert n fun' m)
+ | otherwise = case I.lookup (n+1) m of
+ Just xf' -> ([fun',xf'], m)
+ Nothing -> ([fun'], m)
+ in mapM_ (B.hPut w) bs >> fixTables r w m'
+
+-- | Read in the next function/data defenition
+getFun :: Handle -> B.ByteString -> IO B.ByteString
+getFun r f = do
+ l <- (try (B.hGetLine r))::IO (Either IOError B.ByteString)
+ case l of
+ Right l' | B.null l' -> return f
+ | otherwise -> getFun r (f `B.append` newLine `B.append` l')
+ Left _ -> return B.empty
+
+{-|
+ Mac OS X requires that the stack be 16 byte aligned when making a function
+ call (only really required though when making a call that will pass through
+ the dynamic linker). The alignment isn't correctly generated by LLVM as
+ LLVM rightly assumes that the stack will be aligned to 16n + 12 on entry
+ (since the function call was 16 byte aligned and the return address should
+ have been pushed, so sub 4). GHC though since it always uses jumps keeps
+ the stack 16 byte aligned on both function calls and function entry.
+
+ We correct the alignment here.