module Data.PE.Parser (buildFile, buildFileFromBS) where
import Data.PE.Structures
import Data.PE.Utils
import qualified Data.ByteString.Lazy as B
import Data.Binary.Get
import Data.Maybe

-- |Supply a filename of a PE file in the form of a string.  Returns a PEFile structure

buildFile :: String -- ^The file name

             -> IO (PEFile) -- ^The resulting data structure in the IO monad

buildFile :: String -> IO PEFile
buildFile String
fName = do
                      ByteString
fbstring <- String -> IO ByteString
B.readFile String
fName
                      PEFile -> IO PEFile
forall (m :: * -> *) a. Monad m => a -> m a
return (PEFile -> IO PEFile) -> PEFile -> IO PEFile
forall a b. (a -> b) -> a -> b
$ ByteString -> PEFile
buildFileFromBS ByteString
fbstring 

-- |Supply a bytestring to be parsed as if it were a PE Binary.  Returns a PEFile structure

buildFileFromBS :: B.ByteString  -- ^ByteString representing a PE file

             -> PEFile -- ^The data structure returned

buildFileFromBS :: ByteString -> PEFile
buildFileFromBS ByteString
fbstring =
                            let peheader :: PEHeader
peheader = (Get PEHeader -> ByteString -> PEHeader
forall a. Get a -> ByteString -> a
runGet Get PEHeader
pheader ByteString
fbstring) in
                            let mapSections :: SectionTable -> (String, ByteString)
mapSections = \SectionTable
sections' -> (ByteString -> SectionTable -> (String, ByteString)
secBytes ByteString
fbstring SectionTable
sections') in
                            let secTables :: [(SectionTable, ByteString)]
secTables = PEHeader -> [(SectionTable, ByteString)]
sectionTables PEHeader
peheader in
                            let binsections :: [(String, ByteString)]
binsections = (SectionTable -> (String, ByteString))
-> [SectionTable] -> [(String, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map SectionTable -> (String, ByteString)
mapSections ([SectionTable] -> [(String, ByteString)])
-> [SectionTable] -> [(String, ByteString)]
forall a b. (a -> b) -> a -> b
$ ((SectionTable, ByteString) -> SectionTable)
-> [(SectionTable, ByteString)] -> [SectionTable]
forall a b. (a -> b) -> [a] -> [b]
map (SectionTable, ByteString) -> SectionTable
forall a b. (a, b) -> a
fst [(SectionTable, ByteString)]
secTables in
                            let fixsec :: SectionTable -> (SectionTable, ByteString)
fixsec = \SectionTable
x -> (SectionTable
x, Maybe ByteString -> ByteString
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ByteString -> ByteString) -> Maybe ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ String -> [(String, ByteString)] -> Maybe ByteString
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (SectionTable -> String
sectionHeaderName SectionTable
x) [(String, ByteString)]
binsections) in
                            let newsections :: [(SectionTable, ByteString)]
newsections = (SectionTable -> (SectionTable, ByteString))
-> [SectionTable] -> [(SectionTable, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map SectionTable -> (SectionTable, ByteString)
fixsec ([SectionTable] -> [(SectionTable, ByteString)])
-> [SectionTable] -> [(SectionTable, ByteString)]
forall a b. (a -> b) -> a -> b
$ ((SectionTable, ByteString) -> SectionTable)
-> [(SectionTable, ByteString)] -> [SectionTable]
forall a b. (a -> b) -> [a] -> [b]
map (SectionTable, ByteString) -> SectionTable
forall a b. (a, b) -> a
fst [(SectionTable, ByteString)]
secTables in
                             PEFile :: PEHeader -> PEFile
PEFile{peHeader :: PEHeader
peHeader=PEHeader
peheader{sectionTables :: [(SectionTable, ByteString)]
sectionTables=[(SectionTable, ByteString)]
newsections}}

pheader :: Get (PEHeader)
pheader :: Get PEHeader
pheader = do
                  MSDOSHeader
dosheader <- Get MSDOSHeader
buildMSDOSHead
                  Int64
bytes <- Get Int64
bytesRead
                  let peoffset :: Int
peoffset = (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (MSDOSHeader -> Word32
offset MSDOSHeader
dosheader)) Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
bytes)
                  Int -> Get ()
skip Int
peoffset
                  PESignature
peSig <- Get PESignature
buildPESignature
                  COFFHeader
coff <- Get COFFHeader
buildCOFFHeader
                  StandardFields
sfheader <- Get StandardFields
buildSFHeader
                  WindowsSpecFields
wsfheader <- if (StandardFields -> Word16
standardSig StandardFields
sfheader Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
== Word16
0x10B) then Get WindowsSpecFields
buildWSFHeader else Get WindowsSpecFields
buildWSFPlus
                  [DirectoryEntry]
datadirs <- Int -> Get [DirectoryEntry]
buildDataDirectories (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ WindowsSpecFields -> Word32
numberOfRVAandSizes WindowsSpecFields
wsfheader)
                  let numsections :: Int
numsections = Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (COFFHeader -> Word16
numberOfSections COFFHeader
coff)
                  [SectionTable]
sectables <- Int -> Get [SectionTable]
sections Int
numsections
                  let sectables' :: [(SectionTable, ByteString)]
sectables' = (SectionTable -> (SectionTable, ByteString))
-> [SectionTable] -> [(SectionTable, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map (\SectionTable
x -> (SectionTable
x,[Word8] -> ByteString
B.pack [])) [SectionTable]
sectables
                  PEHeader -> Get PEHeader
forall (m :: * -> *) a. Monad m => a -> m a
return PEHeader :: MSDOSHeader
-> PESignature
-> COFFHeader
-> StandardFields
-> WindowsSpecFields
-> [DirectoryEntry]
-> [(SectionTable, ByteString)]
-> PEHeader
PEHeader {msdosHeader :: MSDOSHeader
msdosHeader=MSDOSHeader
dosheader, peSignature :: PESignature
peSignature=PESignature
peSig, coffHeader :: COFFHeader
coffHeader=COFFHeader
coff, standardFields :: StandardFields
standardFields=StandardFields
sfheader,
                                  windowsSpecFields :: WindowsSpecFields
windowsSpecFields=WindowsSpecFields
wsfheader, dataDirectories :: [DirectoryEntry]
dataDirectories=[DirectoryEntry]
datadirs, sectionTables :: [(SectionTable, ByteString)]
sectionTables=[(SectionTable, ByteString)]
sectables'}

sections :: Int -> Get ([SectionTable])
sections :: Int -> Get [SectionTable]
sections Int
0 = [SectionTable] -> Get [SectionTable]
forall (m :: * -> *) a. Monad m => a -> m a
return []
sections Int
n = Int -> Get [SectionTable]
sections (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Get [SectionTable]
-> ([SectionTable] -> Get [SectionTable]) -> Get [SectionTable]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[SectionTable]
rest -> Get SectionTable
buildSectionTable Get SectionTable
-> (SectionTable -> Get [SectionTable]) -> Get [SectionTable]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \SectionTable
item -> [SectionTable] -> Get [SectionTable]
forall (m :: * -> *) a. Monad m => a -> m a
return (SectionTable
itemSectionTable -> [SectionTable] -> [SectionTable]
forall a. a -> [a] -> [a]
:[SectionTable]
rest)

secBytes :: B.ByteString -> SectionTable -> (String,B.ByteString)
secBytes :: ByteString -> SectionTable -> (String, ByteString)
secBytes ByteString
bs SectionTable
sec = let offset' :: Int64
offset' = (Word32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int64)
-> (SectionTable -> Word32) -> SectionTable -> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SectionTable -> Word32
pointerToRawData) SectionTable
sec in
                  let size :: Int64
size = (Word32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int64)
-> (SectionTable -> Word32) -> SectionTable -> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SectionTable -> Word32
sizeOfRawData) SectionTable
sec in
                  let name :: String
name = SectionTable -> String
sectionHeaderName SectionTable
sec in
                  let pbs :: ByteString
pbs = Int64 -> ByteString -> ByteString
B.drop Int64
offset' ByteString
bs in
                  let sbs :: ByteString
sbs = Int64 -> ByteString -> ByteString
B.take Int64
size ByteString
pbs in
                  (String
name, ByteString
sbs)

buildMSDOSHead :: Get (MSDOSHeader)
buildMSDOSHead :: Get MSDOSHeader
buildMSDOSHead = do
                    Word16
signature' <- Get Word16
getWord16le
                    Word16
lastsize' <- Get Word16
getWord16le
                    Word16
pagesInFile' <- Get Word16
getWord16le
                    Word16
relocations' <- Get Word16
getWord16le
                    Word16
headerSizeInParagraph' <- Get Word16
getWord16le
                    Word16
minExtraParagraphs' <- Get Word16
getWord16le
                    Word16
maxExtraParagraphs' <- Get Word16
getWord16le
                    Word16
ss' <- Get Word16
getWord16le
                    Word16
sp' <- Get Word16
getWord16le
                    Word16
checksum' <- Get Word16
getWord16le
                    Word16
ip' <- Get Word16
getWord16le
                    Word16
cs' <- Get Word16
getWord16le
                    Word16
relocTableOffset' <- Get Word16
getWord16le
                    Word16
overlayNumber' <- Get Word16
getWord16le
                    Word16
_ <- Get Word16
getWord16le -- chew through

                    Word16
_ <- Get Word16
getWord16le -- chew through

                    Word16
_ <- Get Word16
getWord16le -- chew through

                    Word16
_ <- Get Word16
getWord16le -- chew through

                    Word16
oemIdentifier' <- Get Word16
getWord16le
                    Word16
oemInformation' <- Get Word16
getWord16le
                    Word32
_ <- Get Word32
getWord32le -- chew through, there are actually 10 16-bit reserved slots, 32 here for brevity

                    Word32
_ <-Get Word32
getWord32le
                    Word32
_ <-Get Word32
getWord32le
                    Word32
_ <-Get Word32
getWord32le
                    Word32
_ <-Get Word32
getWord32le
                    Word32
offset' <- Get Word32
getWord32le -- this should be 0x80, we could check later if we wanted to

                    let header' :: MSDOSHeader
header' = MSDOSHeader :: Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word32
-> MSDOSHeader
MSDOSHeader {signature :: Word16
signature=Word16
signature', lastsize :: Word16
lastsize=Word16
lastsize', pagesInFile :: Word16
pagesInFile=Word16
pagesInFile',
                                              relocations :: Word16
relocations=Word16
relocations', headerSizeInParagraph :: Word16
headerSizeInParagraph=Word16
headerSizeInParagraph',
                                              minExtraParagraphs :: Word16
minExtraParagraphs=Word16
minExtraParagraphs', maxExtraParagraphs :: Word16
maxExtraParagraphs=Word16
maxExtraParagraphs',
                                              ss :: Word16
ss=Word16
ss', sp :: Word16
sp=Word16
sp', checksum :: Word16
checksum=Word16
checksum', ip :: Word16
ip=Word16
ip', cs :: Word16
cs=Word16
cs', 
                                              relocTableOffset :: Word16
relocTableOffset=Word16
relocTableOffset', overlayNumber :: Word16
overlayNumber=Word16
overlayNumber',
                                              oemIdentifier :: Word16
oemIdentifier=Word16
oemIdentifier', oemInformation :: Word16
oemInformation=Word16
oemInformation', offset :: Word32
offset=Word32
offset'}
                        
                    MSDOSHeader -> Get MSDOSHeader
forall (m :: * -> *) a. Monad m => a -> m a
return MSDOSHeader
header'

buildPESignature :: Get (PESignature)
buildPESignature :: Get PESignature
buildPESignature = do
                    Word32
sig <- Get Word32
getWord32le
                    PESignature -> Get PESignature
forall (m :: * -> *) a. Monad m => a -> m a
return PESignature :: Word32 -> PESignature
PESignature { pesignature :: Word32
pesignature=Word32
sig }

buildCOFFHeader :: Get (COFFHeader)
buildCOFFHeader :: Get COFFHeader
buildCOFFHeader = do
                    Word16
targetMachine' <- Get Word16
getWord16le
                    Word16
numberOfSections' <- Get Word16
getWord16le
                    Word32
timeDateStamp' <- Get Word32
getWord32le
                    Word32
pointerToSymbolTable' <- Get Word32
getWord32le
                    Word32
numberOfSymbols' <- Get Word32
getWord32le
                    Word16
sizeofOptionalHeaders' <- Get Word16
getWord16le
                    Word16
coffCharacteristics' <- Get Word16
getWord16le
                    let header' :: COFFHeader
header' = COFFHeader :: MachineType
-> Word16
-> Word32
-> Word32
-> Word32
-> Word16
-> Word16
-> COFFHeader
COFFHeader { targetMachine :: MachineType
targetMachine=(Word16 -> MachineType
mapMachine Word16
targetMachine'), numberOfSections :: Word16
numberOfSections=Word16
numberOfSections',
                                              timeDateStamp :: Word32
timeDateStamp=Word32
timeDateStamp', pointerToSymbolTable :: Word32
pointerToSymbolTable=Word32
pointerToSymbolTable',
                                              numberOfSymbols :: Word32
numberOfSymbols=Word32
numberOfSymbols', sizeofOptionalHeaders :: Word16
sizeofOptionalHeaders=Word16
sizeofOptionalHeaders',
                                              coffCharacteristics :: Word16
coffCharacteristics=Word16
coffCharacteristics'}
                    COFFHeader -> Get COFFHeader
forall (m :: * -> *) a. Monad m => a -> m a
return COFFHeader
header'





buildSFHeader :: Get (StandardFields)
buildSFHeader :: Get StandardFields
buildSFHeader = do
                   Word16
standardSig' <- Get Word16
getWord16le
                   Word8
lnMajorVersion' <- Get Word8
getWord8
                   Word8
lnMinorVersion' <- Get Word8
getWord8
                   Word32
sizeOfCode' <- Get Word32
getWord32le
                   Word32
sizeOfInitializedData' <- Get Word32
getWord32le
                   Word32
sizeOfUninitData' <- Get Word32
getWord32le
                   Word32
addressOfEntryPoint' <- Get Word32
getWord32le
                   Word32
baseOfCode' <- Get Word32
getWord32le
                   case (Word16
standardSig') of
                          Word16
0x10B -> do 
                                       Word32
baseOfData' <- Get Word32
getWord32le
                                       let header' :: StandardFields
header' = StandardFields :: Word16
-> Word8
-> Word8
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> StandardFields
StandardFields { standardSig :: Word16
standardSig=Word16
standardSig', lnMajorVersion :: Word8
lnMajorVersion=Word8
lnMajorVersion',
                                                                   lnMinorVersion :: Word8
lnMinorVersion=Word8
lnMinorVersion', sizeOfCode :: Word32
sizeOfCode=Word32
sizeOfCode', sizeOfInitializedData :: Word32
sizeOfInitializedData=Word32
sizeOfInitializedData',
                                                                   sizeOfUninitData :: Word32
sizeOfUninitData=Word32
sizeOfUninitData', addressOfEntryPoint :: Word32
addressOfEntryPoint=Word32
addressOfEntryPoint',
                                                                   baseOfCode :: Word32
baseOfCode=Word32
baseOfCode', baseOfData :: Word32
baseOfData=Word32
baseOfData'}
                                       StandardFields -> Get StandardFields
forall (m :: * -> *) a. Monad m => a -> m a
return StandardFields
header'
                          Word16
0x20B -> do
                                       let header' :: StandardFields
header' = SFPlus :: Word16
-> Word8
-> Word8
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> StandardFields
SFPlus { standardSig :: Word16
standardSig=Word16
standardSig', lnMajorVersion :: Word8
lnMajorVersion=Word8
lnMajorVersion',
                                                                   lnMinorVersion :: Word8
lnMinorVersion=Word8
lnMinorVersion', sizeOfCode :: Word32
sizeOfCode=Word32
sizeOfCode', sizeOfInitializedData :: Word32
sizeOfInitializedData=Word32
sizeOfInitializedData',
                                                                   sizeOfUninitData :: Word32
sizeOfUninitData=Word32
sizeOfUninitData', addressOfEntryPoint :: Word32
addressOfEntryPoint=Word32
addressOfEntryPoint',
                                                                   baseOfCode :: Word32
baseOfCode=Word32
baseOfCode'}
                                       StandardFields -> Get StandardFields
forall (m :: * -> *) a. Monad m => a -> m a
return StandardFields
header'
                          Word16
_ -> String -> Get StandardFields
forall a. HasCallStack => String -> a
error String
"Unrecognized PE format Magic Number"



buildWSFHeader :: Get (WindowsSpecFields)
buildWSFHeader :: Get WindowsSpecFields
buildWSFHeader = do
                    Word32
imageBase' <- Get Word32
getWord32le
                    Word32
sectionAlignment' <- Get Word32
getWord32le
                    Word32
fileAlignment' <- Get Word32
getWord32le
                    Word16
majorOSVersion' <- Get Word16
getWord16le
                    Word16
minorOSVersion' <- Get Word16
getWord16le
                    Word16
majorImageVersion' <- Get Word16
getWord16le
                    Word16
minorImageVersion' <- Get Word16
getWord16le
                    Word16
majorSubSystemVersion' <- Get Word16
getWord16le
                    Word16
minorSubSystemVersion' <- Get Word16
getWord16le
                    Word32
win32VersionValue' <- Get Word32
getWord32le
                    Word32
sizeOfImage' <- Get Word32
getWord32le
                    Word32
sizeOfHeaders' <- Get Word32
getWord32le
                    Word32
checkSum32' <- Get Word32
getWord32le
                    Word16
checkSum16' <- Get Word16
getWord16le
                    Word16
dllCharacteristics' <- Get Word16
getWord16le
                    Word32
sizeOfStackReserve' <- Get Word32
getWord32le
                    Word32
sizeOfStackCommit' <- Get Word32
getWord32le
                    Word32
sizeOfHeapReserve' <- Get Word32
getWord32le
                    Word32
sizeOfHeapCommit' <- Get Word32
getWord32le
                    Word32
loaderFlags' <- Get Word32
getWord32le
                    Word32
numberOfRVAandSizes' <- Get Word32
getWord32le
                    let header' :: WindowsSpecFields
header' = WindowsSpecFields :: Word32
-> Word32
-> Word32
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word32
-> Word32
-> Word32
-> Word32
-> Word16
-> Word16
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> WindowsSpecFields
WindowsSpecFields { imageBase :: Word32
imageBase=Word32
imageBase', sectionAlignment :: Word32
sectionAlignment=Word32
sectionAlignment',
                                                     fileAlignment :: Word32
fileAlignment=Word32
fileAlignment', majorOSVersion :: Word16
majorOSVersion=Word16
majorOSVersion',
                                                     minorOSVersion :: Word16
minorOSVersion=Word16
minorOSVersion', majorImageVersion :: Word16
majorImageVersion=Word16
majorImageVersion',
                                                     minorImageVersion :: Word16
minorImageVersion=Word16
minorImageVersion', majorSubSystemVersion :: Word16
majorSubSystemVersion=Word16
majorSubSystemVersion',
                                                     minorSubSystemVersion :: Word16
minorSubSystemVersion=Word16
minorSubSystemVersion', win32VersionValue :: Word32
win32VersionValue=Word32
win32VersionValue',
                                                     sizeOfImage :: Word32
sizeOfImage=Word32
sizeOfImage', sizeOfHeaders :: Word32
sizeOfHeaders=Word32
sizeOfHeaders', checkSum32 :: Word32
checkSum32=Word32
checkSum32',
                                                     checkSum16 :: Word16
checkSum16=Word16
checkSum16', dllCharacteristics :: Word16
dllCharacteristics=Word16
dllCharacteristics', sizeOfStackReserve :: Word32
sizeOfStackReserve=Word32
sizeOfStackReserve',
                                                     sizeOfStackCommit :: Word32
sizeOfStackCommit=Word32
sizeOfStackCommit', sizeOfHeapReserve :: Word32
sizeOfHeapReserve=Word32
sizeOfHeapReserve', 
                                                     sizeOfHeapCommit :: Word32
sizeOfHeapCommit=Word32
sizeOfHeapCommit', loaderFlags :: Word32
loaderFlags=Word32
loaderFlags', numberOfRVAandSizes :: Word32
numberOfRVAandSizes=Word32
numberOfRVAandSizes' }
                    WindowsSpecFields -> Get WindowsSpecFields
forall (m :: * -> *) a. Monad m => a -> m a
return WindowsSpecFields
header'

buildWSFPlus :: Get (WindowsSpecFields)
buildWSFPlus :: Get WindowsSpecFields
buildWSFPlus = do
                    Word64
imageBase' <- Get Word64
getWord64le
                    Word32
sectionAlignment' <- Get Word32
getWord32le
                    Word32
fileAlignment' <- Get Word32
getWord32le
                    Word16
majorOSVersion' <- Get Word16
getWord16le
                    Word16
minorOSVersion' <- Get Word16
getWord16le
                    Word16
majorImageVersion' <- Get Word16
getWord16le
                    Word16
minorImageVersion' <- Get Word16
getWord16le
                    Word16
majorSubSystemVersion' <- Get Word16
getWord16le
                    Word16
minorSubSystemVersion' <- Get Word16
getWord16le
                    Word32
win32VersionValue' <- Get Word32
getWord32le
                    Word32
sizeOfImage' <- Get Word32
getWord32le
                    Word32
sizeOfHeaders' <- Get Word32
getWord32le
                    Word32
checkSum32' <- Get Word32
getWord32le
                    Word16
checkSum16' <- Get Word16
getWord16le
                    Word16
dllCharacteristics' <- Get Word16
getWord16le
                    Word64
sizeOfStackReserve' <- Get Word64
getWord64le
                    Word64
sizeOfStackCommit' <- Get Word64
getWord64le
                    Word64
sizeOfHeapReserve' <- Get Word64
getWord64le
                    Word64
sizeOfHeapCommit' <- Get Word64
getWord64le
                    Word32
loaderFlags' <- Get Word32
getWord32le
                    Word32
numberOfRVAandSizes' <- Get Word32
getWord32le
                    let header' :: WindowsSpecFields
header' = WSFPlus :: Word64
-> Word32
-> Word32
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word16
-> Word32
-> Word32
-> Word32
-> Word32
-> Word16
-> Word16
-> Word64
-> Word64
-> Word64
-> Word64
-> Word32
-> Word32
-> WindowsSpecFields
WSFPlus { imgBase :: Word64
imgBase=Word64
imageBase', sectionAlignment :: Word32
sectionAlignment=Word32
sectionAlignment',
                                                     fileAlignment :: Word32
fileAlignment=Word32
fileAlignment', majorOSVersion :: Word16
majorOSVersion=Word16
majorOSVersion',
                                                     minorOSVersion :: Word16
minorOSVersion=Word16
minorOSVersion', majorImageVersion :: Word16
majorImageVersion=Word16
majorImageVersion',
                                                     minorImageVersion :: Word16
minorImageVersion=Word16
minorImageVersion', majorSubSystemVersion :: Word16
majorSubSystemVersion=Word16
majorSubSystemVersion',
                                                     minorSubSystemVersion :: Word16
minorSubSystemVersion=Word16
minorSubSystemVersion', win32VersionValue :: Word32
win32VersionValue=Word32
win32VersionValue',
                                                     sizeOfImage :: Word32
sizeOfImage=Word32
sizeOfImage', sizeOfHeaders :: Word32
sizeOfHeaders=Word32
sizeOfHeaders', checkSum32 :: Word32
checkSum32=Word32
checkSum32',
                                                     checkSum16 :: Word16
checkSum16=Word16
checkSum16', dllCharacteristics :: Word16
dllCharacteristics=Word16
dllCharacteristics', szOfStackReserve :: Word64
szOfStackReserve=Word64
sizeOfStackReserve',
                                                     szOfStackCommit :: Word64
szOfStackCommit=Word64
sizeOfStackCommit', szOfHeapReserve :: Word64
szOfHeapReserve=Word64
sizeOfHeapReserve', 
                                                     szOfHeapCommit :: Word64
szOfHeapCommit=Word64
sizeOfHeapCommit', loaderFlags :: Word32
loaderFlags=Word32
loaderFlags', numberOfRVAandSizes :: Word32
numberOfRVAandSizes=Word32
numberOfRVAandSizes' }
                    WindowsSpecFields -> Get WindowsSpecFields
forall (m :: * -> *) a. Monad m => a -> m a
return WindowsSpecFields
header'


buildDataDirectories :: Int -> Get ([DirectoryEntry])
buildDataDirectories :: Int -> Get [DirectoryEntry]
buildDataDirectories Int
0 = [DirectoryEntry] -> Get [DirectoryEntry]
forall (m :: * -> *) a. Monad m => a -> m a
return []
buildDataDirectories Int
i = do
                            Word32
addr <- Get Word32
getWord32le
                            Word32
size <- Get Word32
getWord32le
                            let entry :: DirectoryEntry
entry = DirEntry :: Word32 -> Word32 -> DirectoryEntry
DirEntry {virtualAddr :: Word32
virtualAddr=Word32
addr, entrySize :: Word32
entrySize=Word32
size}
                            [DirectoryEntry]
rest <- Int -> Get [DirectoryEntry]
buildDataDirectories (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
                            [DirectoryEntry] -> Get [DirectoryEntry]
forall (m :: * -> *) a. Monad m => a -> m a
return ([DirectoryEntry] -> Get [DirectoryEntry])
-> [DirectoryEntry] -> Get [DirectoryEntry]
forall a b. (a -> b) -> a -> b
$ DirectoryEntry
entry DirectoryEntry -> [DirectoryEntry] -> [DirectoryEntry]
forall a. a -> [a] -> [a]
: [DirectoryEntry]
rest


buildSectionTable :: Get (SectionTable)
buildSectionTable :: Get SectionTable
buildSectionTable = do
                       Word64
sectionHeaderName' <- Get Word64
getWord64le
                       Word32
virtualSize' <- Get Word32
getWord32le
                       Word32
virtualAddress' <- Get Word32
getWord32le
                       Word32
sizeOfRawData' <- Get Word32
getWord32le
                       Word32
pointerToRawData' <- Get Word32
getWord32le
                       Word32
pointerToRelocations' <- Get Word32
getWord32le
                       Word32
pointerToLineNumbers' <- Get Word32
getWord32le
                       Word16
numberOfRelocations' <- Get Word16
getWord16le
                       Word16
numberOfLineNumbers' <- Get Word16
getWord16le
                       Word32
secCharacteristics' <- Get Word32
getWord32le
                       let header :: SectionTable
header = SectionTable :: String
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word32
-> Word16
-> Word16
-> Word32
-> SectionTable
SectionTable { sectionHeaderName :: String
sectionHeaderName=(Word64 -> String
byte64String Word64
sectionHeaderName'), virtualSize :: Word32
virtualSize=Word32
virtualSize',
                                                   virtualAddress :: Word32
virtualAddress=Word32
virtualAddress', sizeOfRawData :: Word32
sizeOfRawData=Word32
sizeOfRawData',
                                                   pointerToRawData :: Word32
pointerToRawData=Word32
pointerToRawData', pointerToRelocations :: Word32
pointerToRelocations=Word32
pointerToRelocations',
                                                   pointerToLineNumbers :: Word32
pointerToLineNumbers=Word32
pointerToLineNumbers', numberOfRelocations :: Word16
numberOfRelocations=Word16
numberOfRelocations',
                                                   numberOfLineNumbers :: Word16
numberOfLineNumbers=Word16
numberOfLineNumbers', secCharacteristics :: Word32
secCharacteristics=Word32
secCharacteristics'}
                       SectionTable -> Get SectionTable
forall (m :: * -> *) a. Monad m => a -> m a
return SectionTable
header