summaryrefslogtreecommitdiff
path: root/lib/Language/Elna/Object/Elf.hs
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2024-09-05 23:18:48 +0200
committerEugen Wissner <belka@caraus.de>2024-09-05 23:18:48 +0200
commit042e4e8714263fe0568e1e382232dae56afa2ed1 (patch)
treef7c0b9d68a44565fac4903bf7447fdf20628c4b8 /lib/Language/Elna/Object/Elf.hs
parentbe73032b939486c6207b441fb7bdfb0bda172b5d (diff)
downloadelna-042e4e8714263fe0568e1e382232dae56afa2ed1.tar.gz
Add command line parser
Diffstat (limited to 'lib/Language/Elna/Object/Elf.hs')
-rw-r--r--lib/Language/Elna/Object/Elf.hs73
1 files changed, 51 insertions, 22 deletions
diff --git a/lib/Language/Elna/Object/Elf.hs b/lib/Language/Elna/Object/Elf.hs
index 1a4bcc8..4328f56 100644
--- a/lib/Language/Elna/Object/Elf.hs
+++ b/lib/Language/Elna/Object/Elf.hs
@@ -30,17 +30,23 @@ module Language.Elna.Object.Elf
, elf32Rel
, elf32Rela
, elf32Sym
+ , elfHeaderSize
, elfIdentification
+ , elfObject
, rInfo
, stInfo
) where
-import Control.Exception (Exception(..))
+import Control.Exception (Exception(..), throwIO)
import Data.Bits (Bits(..))
import qualified Data.ByteString.Builder as ByteString.Builder
import Data.Int (Int32)
import Data.Word (Word8, Word16, Word32)
import qualified Data.ByteString as ByteString
+import Data.Vector (Vector)
+import qualified Data.Vector as Vector
+import System.IO (Handle, IOMode(..), SeekMode(..), hSeek, withFile)
+import Data.Foldable (traverse_)
-- * Data types.
@@ -345,27 +351,6 @@ instance Enum ElfSectionType
fromEnum SHT_HIUSER = 0xffffffff
fromEnum (ElfSectionType x) = fromIntegral x
--- * Help types and functions.
-
-data ByteOrder = LSB | MSB
- deriving Eq
-
-data ElfEncodingError
- = ElfInvalidByteOrderError
- | ElfUnsupportedClassError ElfClass
- deriving Eq
-
-instance Show ElfEncodingError
- where
- show ElfInvalidByteOrderError = "Invalid byte order."
- show (ElfUnsupportedClassError class') =
- concat ["Elf class \"", show class', "\" is not supported."]
-
-instance Exception ElfEncodingError
-
-fromIntegralEnum :: (Enum a, Num b) => a -> b
-fromIntegralEnum = fromIntegral . fromEnum
-
-- * Encoding functions.
elf32Addr :: ByteOrder -> Elf32_Addr -> ByteString.Builder.Builder
@@ -462,3 +447,47 @@ stInfo binding type' = fromIntegralEnum binding `shiftL` 4
rInfo :: Elf32_Word -> Word8 -> Elf32_Word
rInfo symbol type' = symbol `shiftL` 8
.|. fromIntegralEnum type'
+
+-- * Help types and functions.
+
+data ByteOrder = LSB | MSB
+ deriving Eq
+
+data ElfEncodingError
+ = ElfInvalidByteOrderError
+ | ElfUnsupportedClassError ElfClass
+ deriving Eq
+
+instance Show ElfEncodingError
+ where
+ show ElfInvalidByteOrderError = "Invalid byte order."
+ show (ElfUnsupportedClassError class') =
+ concat ["Elf class \"", show class', "\" is not supported."]
+
+instance Exception ElfEncodingError
+
+fromIntegralEnum :: (Enum a, Num b) => a -> b
+fromIntegralEnum = fromIntegral . fromEnum
+
+elfHeaderSize :: Elf32_Off
+elfHeaderSize = 52
+
+-- Writes an ELF object with the given header to the provided file path.
+-- The callback writes the sections and returns headers for those sections.
+elfObject :: FilePath -> Elf32_Ehdr -> (Handle -> IO (Vector Elf32_Shdr)) -> IO ()
+elfObject outFile header putContents = withFile outFile WriteMode withObjectFile
+ where
+ withObjectFile objectHandle
+ = hSeek objectHandle AbsoluteSeek (fromIntegral elfHeaderSize)
+ >> putContents objectHandle
+ >>= afterContents objectHandle
+ afterContents objectHandle headers =
+ let headerEncodingResult = elf32Ehdr
+ $ header
+ { e_shoff = elfHeaderSize + Vector.foldr ((+) . sh_size) 0 headers
+ }
+ in traverse_ (ByteString.Builder.hPutBuilder objectHandle . elf32Shdr LSB) headers
+ >> either throwIO (putHeaders objectHandle) headerEncodingResult
+ putHeaders objectHandle encodedHeader
+ = hSeek objectHandle AbsoluteSeek 0
+ >> ByteString.Builder.hPutBuilder objectHandle encodedHeader