module GHC.SysTools.Elf (
readElfSectionByName,
readElfNoteAsString,
makeElfNote
) where
import GHC.Prelude
import GHC.Utils.Asm
import GHC.Utils.Exception
import GHC.Platform
import GHC.Utils.Error
import GHC.Data.Maybe (MaybeT(..),runMaybeT)
import GHC.Utils.Misc (charToC)
import GHC.Utils.Outputable (text,hcat)
import GHC.Utils.Logger
import Control.Monad (when)
import Data.Binary.Get
import Data.Word
import Data.Char (ord)
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as B8
data =
{ ElfHeader -> Get Word16
gw16 :: Get Word16
, ElfHeader -> Get Word32
gw32 :: Get Word32
, ElfHeader -> Get Word64
gwN :: Get Word64
, ElfHeader -> Int
wordSize :: Int
}
readElfHeader :: Logger -> ByteString -> IO (Maybe ElfHeader)
Logger
logger ByteString
bs = Get (Maybe ElfHeader) -> ByteString -> IO (Maybe ElfHeader)
forall a. Get a -> ByteString -> IO a
runGetOrThrow Get (Maybe ElfHeader)
getHeader ByteString
bs IO (Maybe ElfHeader)
-> (IOException -> IO (Maybe ElfHeader)) -> IO (Maybe ElfHeader)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF header")
Maybe ElfHeader -> IO (Maybe ElfHeader)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ElfHeader
forall a. Maybe a
Nothing
where
getHeader :: Get (Maybe ElfHeader)
getHeader = do
magic <- Get Word32
getWord32be
ws <- getWord8
endian <- getWord8
version <- getWord8
skip 9
when (magic /= 0x7F454C46 || version /= 1) $ fail "Invalid ELF header"
case (ws, endian) of
(Word8
1,Word8
1) -> Maybe ElfHeader -> Get (Maybe ElfHeader)
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ElfHeader -> Get (Maybe ElfHeader))
-> (ElfHeader -> Maybe ElfHeader)
-> ElfHeader
-> Get (Maybe ElfHeader)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElfHeader -> Maybe ElfHeader
forall a. a -> Maybe a
Just (ElfHeader -> Get (Maybe ElfHeader))
-> ElfHeader -> Get (Maybe ElfHeader)
forall a b. (a -> b) -> a -> b
$ Get Word16 -> Get Word32 -> Get Word64 -> Int -> ElfHeader
ElfHeader
Get Word16
getWord16le
Get Word32
getWord32le
((Word32 -> Word64) -> Get Word32 -> Get Word64
forall a b. (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Get Word32
getWord32le) Int
4
(Word8
1,Word8
2) -> Maybe ElfHeader -> Get (Maybe ElfHeader)
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ElfHeader -> Get (Maybe ElfHeader))
-> (ElfHeader -> Maybe ElfHeader)
-> ElfHeader
-> Get (Maybe ElfHeader)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElfHeader -> Maybe ElfHeader
forall a. a -> Maybe a
Just (ElfHeader -> Get (Maybe ElfHeader))
-> ElfHeader -> Get (Maybe ElfHeader)
forall a b. (a -> b) -> a -> b
$ Get Word16 -> Get Word32 -> Get Word64 -> Int -> ElfHeader
ElfHeader
Get Word16
getWord16be
Get Word32
getWord32be
((Word32 -> Word64) -> Get Word32 -> Get Word64
forall a b. (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Get Word32
getWord32be) Int
4
(Word8
2,Word8
1) -> Maybe ElfHeader -> Get (Maybe ElfHeader)
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ElfHeader -> Get (Maybe ElfHeader))
-> (ElfHeader -> Maybe ElfHeader)
-> ElfHeader
-> Get (Maybe ElfHeader)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElfHeader -> Maybe ElfHeader
forall a. a -> Maybe a
Just (ElfHeader -> Get (Maybe ElfHeader))
-> ElfHeader -> Get (Maybe ElfHeader)
forall a b. (a -> b) -> a -> b
$ Get Word16 -> Get Word32 -> Get Word64 -> Int -> ElfHeader
ElfHeader
Get Word16
getWord16le
Get Word32
getWord32le
((Word64 -> Word64) -> Get Word64 -> Get Word64
forall a b. (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Get Word64
getWord64le) Int
8
(Word8
2,Word8
2) -> Maybe ElfHeader -> Get (Maybe ElfHeader)
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ElfHeader -> Get (Maybe ElfHeader))
-> (ElfHeader -> Maybe ElfHeader)
-> ElfHeader
-> Get (Maybe ElfHeader)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElfHeader -> Maybe ElfHeader
forall a. a -> Maybe a
Just (ElfHeader -> Get (Maybe ElfHeader))
-> ElfHeader -> Get (Maybe ElfHeader)
forall a b. (a -> b) -> a -> b
$ Get Word16 -> Get Word32 -> Get Word64 -> Int -> ElfHeader
ElfHeader
Get Word16
getWord16be
Get Word32
getWord32be
((Word64 -> Word64) -> Get Word64 -> Get Word64
forall a b. (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Get Word64
getWord64be) Int
8
(Word8, Word8)
_ -> String -> Get (Maybe ElfHeader)
forall a. String -> Get a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid ELF header"
data SectionTable = SectionTable
{ SectionTable -> Word64
sectionTableOffset :: Word64
, SectionTable -> Word16
sectionEntrySize :: Word16
, SectionTable -> Word64
sectionEntryCount :: Word64
, SectionTable -> Word32
sectionNameIndex :: Word32
}
readElfSectionTable :: Logger
-> ElfHeader
-> ByteString
-> IO (Maybe SectionTable)
readElfSectionTable :: Logger -> ElfHeader -> ByteString -> IO (Maybe SectionTable)
readElfSectionTable Logger
logger ElfHeader
hdr ByteString
bs = IO (Maybe SectionTable)
action IO (Maybe SectionTable)
-> (IOException -> IO (Maybe SectionTable))
-> IO (Maybe SectionTable)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF section table")
Maybe SectionTable -> IO (Maybe SectionTable)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SectionTable
forall a. Maybe a
Nothing
where
getSectionTable :: Get SectionTable
getSectionTable :: Get SectionTable
getSectionTable = do
Int -> Get ()
skip (Int
24 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*ElfHeader -> Int
wordSize ElfHeader
hdr)
secTableOffset <- ElfHeader -> Get Word64
gwN ElfHeader
hdr
skip 10
entrySize <- gw16 hdr
entryCount <- gw16 hdr
secNameIndex <- gw16 hdr
return (SectionTable secTableOffset entrySize
(fromIntegral entryCount)
(fromIntegral secNameIndex))
action :: IO (Maybe SectionTable)
action = do
secTable <- Get SectionTable -> ByteString -> IO SectionTable
forall a. Get a -> ByteString -> IO a
runGetOrThrow Get SectionTable
getSectionTable ByteString
bs
let
offSize0 = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ SectionTable -> Word64
sectionTableOffset SectionTable
secTable Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
8
Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
3 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ElfHeader -> Int
wordSize ElfHeader
hdr)
offLink0 = Int64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int64) -> Int64 -> Int64
forall a b. (a -> b) -> a -> b
$ Int64
offSize0 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ElfHeader -> Int
wordSize ElfHeader
hdr)
entryCount' <- if sectionEntryCount secTable /= 0
then return (sectionEntryCount secTable)
else runGetOrThrow (gwN hdr) (LBS.drop offSize0 bs)
entryNameIndex' <- if sectionNameIndex secTable /= 0xffff
then return (sectionNameIndex secTable)
else runGetOrThrow (gw32 hdr) (LBS.drop offLink0 bs)
return (Just $ secTable
{ sectionEntryCount = entryCount'
, sectionNameIndex = entryNameIndex'
})
data Section = Section
{ Section -> ByteString
entryName :: ByteString
, Section -> ByteString
entryBS :: ByteString
}
readElfSectionByIndex :: Logger
-> ElfHeader
-> SectionTable
-> Word64
-> ByteString
-> IO (Maybe Section)
readElfSectionByIndex :: Logger
-> ElfHeader
-> SectionTable
-> Word64
-> ByteString
-> IO (Maybe Section)
readElfSectionByIndex Logger
logger ElfHeader
hdr SectionTable
secTable Word64
i ByteString
bs = IO (Maybe Section)
action IO (Maybe Section)
-> (IOException -> IO (Maybe Section)) -> IO (Maybe Section)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF section")
Maybe Section -> IO (Maybe Section)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Section
forall a. Maybe a
Nothing
where
getEntry :: Get (Word32, ByteString)
getEntry = do
nameIndex <- ElfHeader -> Get Word32
gw32 ElfHeader
hdr
skip (4+2*wordSize hdr)
offset <- fmap fromIntegral $ gwN hdr
size <- fmap fromIntegral $ gwN hdr
let bs' = Int64 -> ByteString -> ByteString
LBS.take Int64
size (Int64 -> ByteString -> ByteString
LBS.drop Int64
offset ByteString
bs)
return (nameIndex,bs')
getEntryByIndex :: Word64 -> IO (Word32, ByteString)
getEntryByIndex Word64
x = Get (Word32, ByteString) -> ByteString -> IO (Word32, ByteString)
forall a. Get a -> ByteString -> IO a
runGetOrThrow Get (Word32, ByteString)
getEntry ByteString
bs'
where
bs' :: ByteString
bs' = Int64 -> ByteString -> ByteString
LBS.drop Int64
off ByteString
bs
off :: Int64
off = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ SectionTable -> Word64
sectionTableOffset SectionTable
secTable Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+
Word64
x Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word16 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (SectionTable -> Word16
sectionEntrySize SectionTable
secTable)
getEntryName :: Int64 -> IO ByteString
getEntryName Int64
nameIndex = do
let idx :: Word64
idx = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (SectionTable -> Word32
sectionNameIndex SectionTable
secTable)
(_,nameTable) <- Word64 -> IO (Word32, ByteString)
getEntryByIndex Word64
idx
let bs' = Int64 -> ByteString -> ByteString
LBS.drop Int64
nameIndex ByteString
nameTable
runGetOrThrow getLazyByteStringNul bs'
action :: IO (Maybe Section)
action = do
(nameIndex,bs') <- Word64 -> IO (Word32, ByteString)
getEntryByIndex (Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
i)
name <- getEntryName (fromIntegral nameIndex)
return (Just $ Section name bs')
findSectionFromName :: Logger
-> ElfHeader
-> SectionTable
-> String
-> ByteString
-> IO (Maybe ByteString)
findSectionFromName :: Logger
-> ElfHeader
-> SectionTable
-> String
-> ByteString
-> IO (Maybe ByteString)
findSectionFromName Logger
logger ElfHeader
hdr SectionTable
secTable String
name ByteString
bs =
[Word64] -> IO (Maybe ByteString)
rec [Word64
0..SectionTable -> Word64
sectionEntryCount SectionTable
secTable Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1]
where
name' :: ByteString
name' = String -> ByteString
B8.pack String
name
rec :: [Word64] -> IO (Maybe ByteString)
rec [] = Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
rec (Word64
x:[Word64]
xs) = do
me <- Logger
-> ElfHeader
-> SectionTable
-> Word64
-> ByteString
-> IO (Maybe Section)
readElfSectionByIndex Logger
logger ElfHeader
hdr SectionTable
secTable Word64
x ByteString
bs
case me of
Just Section
e | Section -> ByteString
entryName Section
e ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
name' -> Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (Section -> ByteString
entryBS Section
e))
Maybe Section
_ -> [Word64] -> IO (Maybe ByteString)
rec [Word64]
xs
readElfSectionByName :: Logger
-> ByteString
-> String
-> IO (Maybe LBS.ByteString)
readElfSectionByName :: Logger -> ByteString -> String -> IO (Maybe ByteString)
readElfSectionByName Logger
logger ByteString
bs String
name = IO (Maybe ByteString)
action IO (Maybe ByteString)
-> (IOException -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF section \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"")
Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
where
action :: IO (Maybe ByteString)
action = MaybeT IO ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT IO ByteString -> IO (Maybe ByteString))
-> MaybeT IO ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ do
hdr <- IO (Maybe ElfHeader) -> MaybeT IO ElfHeader
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (IO (Maybe ElfHeader) -> MaybeT IO ElfHeader)
-> IO (Maybe ElfHeader) -> MaybeT IO ElfHeader
forall a b. (a -> b) -> a -> b
$ Logger -> ByteString -> IO (Maybe ElfHeader)
readElfHeader Logger
logger ByteString
bs
secTable <- MaybeT $ readElfSectionTable logger hdr bs
MaybeT $ findSectionFromName logger hdr secTable name bs
readElfNoteBS :: Logger
-> ByteString
-> String
-> String
-> IO (Maybe LBS.ByteString)
readElfNoteBS :: Logger -> ByteString -> String -> String -> IO (Maybe ByteString)
readElfNoteBS Logger
logger ByteString
bs String
sectionName String
noteId = IO (Maybe ByteString)
action IO (Maybe ByteString)
-> (IOException -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF note \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
noteId String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"\" in section \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
sectionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"")
Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
where
align :: Int64 -> Get ()
align Int64
n = do
m <- Get Int64
bytesRead
if m `mod` n == 0
then return ()
else skip 1 >> align n
noteId' :: ByteString
noteId' = String -> ByteString
B8.pack String
noteId
findNote :: ElfHeader -> Get (Maybe ByteString)
findNote ElfHeader
hdr = do
Int64 -> Get ()
align Int64
4
namesz <- ElfHeader -> Get Word32
gw32 ElfHeader
hdr
descsz <- gw32 hdr
_ <- gw32 hdr
name <- if namesz == 0
then return LBS.empty
else getLazyByteStringNul
align 4
desc <- if descsz == 0
then return LBS.empty
else getLazyByteString (fromIntegral descsz)
if name == noteId'
then return $ Just desc
else findNote hdr
action :: IO (Maybe ByteString)
action = MaybeT IO ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT IO ByteString -> IO (Maybe ByteString))
-> MaybeT IO ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ do
hdr <- IO (Maybe ElfHeader) -> MaybeT IO ElfHeader
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (IO (Maybe ElfHeader) -> MaybeT IO ElfHeader)
-> IO (Maybe ElfHeader) -> MaybeT IO ElfHeader
forall a b. (a -> b) -> a -> b
$ Logger -> ByteString -> IO (Maybe ElfHeader)
readElfHeader Logger
logger ByteString
bs
sec <- MaybeT $ readElfSectionByName logger bs sectionName
MaybeT $ runGetOrThrow (findNote hdr) sec
readElfNoteAsString :: Logger
-> FilePath
-> String
-> String
-> IO (Maybe String)
readElfNoteAsString :: Logger -> String -> String -> String -> IO (Maybe String)
readElfNoteAsString Logger
logger String
path String
sectionName String
noteId = IO (Maybe String)
action IO (Maybe String)
-> (IOException -> IO (Maybe String)) -> IO (Maybe String)
forall a. IO a -> (IOException -> IO a) -> IO a
`catchIO` \IOException
_ -> do
Logger -> Int -> SDoc -> IO ()
debugTraceMsg Logger
logger Int
3 (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String
"Unable to read ELF note \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
noteId String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"\" in section \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
sectionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"")
Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing
where
action :: IO (Maybe String)
action = do
bs <- String -> IO ByteString
LBS.readFile String
path
note <- readElfNoteBS logger bs sectionName noteId
return (fmap B8.unpack note)
makeElfNote :: Platform -> String -> String -> Word32 -> String -> SDoc
makeElfNote :: Platform -> String -> String -> Word32 -> String -> SDoc
makeElfNote Platform
platform String
sectionName String
noteName Word32
typ String
contents = [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.section ",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
sectionName,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
",\"\",",
Platform -> String -> SDoc
forall doc. IsLine doc => Platform -> String -> doc
sectionType Platform
platform String
"note",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\n",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.balign 4\n",
Int -> SDoc
forall a. Show a => a -> SDoc
asWord32 (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
noteName Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1),
Int -> SDoc
forall a. Show a => a -> SDoc
asWord32 (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
contents),
Word32 -> SDoc
forall a. Show a => a -> SDoc
asWord32 Word32
typ,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.asciz \"",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
noteName,
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\"\n",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.balign 4\n",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.ascii \"",
String -> SDoc
forall doc. IsLine doc => String -> doc
text (String -> String
escape String
contents),
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\"\n",
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.balign 4\n"]
where
escape :: String -> String
escape :: String -> String
escape = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Word8 -> String
charToC(Word8 -> String) -> (Char -> Word8) -> Char -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral(Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Char -> Int
ord)
asWord32 :: Show a => a -> SDoc
asWord32 :: forall a. Show a => a -> SDoc
asWord32 a
x = [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\t.4byte ",
String -> SDoc
forall doc. IsLine doc => String -> doc
text (a -> String
forall a. Show a => a -> String
show a
x),
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"\n"]
runGetOrThrow :: Get a -> LBS.ByteString -> IO a
runGetOrThrow :: forall a. Get a -> ByteString -> IO a
runGetOrThrow Get a
g ByteString
bs = case Get a
-> ByteString
-> Either (ByteString, Int64, String) (ByteString, Int64, a)
forall a.
Get a
-> ByteString
-> Either (ByteString, Int64, String) (ByteString, Int64, a)
runGetOrFail Get a
g ByteString
bs of
Left (ByteString, Int64, String)
_ -> String -> IO a
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Error while reading file"
Right (ByteString
_,Int64
_,a
a) -> a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a