diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,11 @@
+1.0.1
+=====
+
+- Rename Aarch64 -> AArch64
+- Rework examples: fuse `MkObj` into `AsmAArch64`, rewrite `MkExe` as `DummyLd`
+- Implement `elfFindSectionByName`
+- Add test data into the hackage tarball
+
 1.0.0
 =====
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -5,19 +5,15 @@
 
 ## Related work
 
-- [elf](https://github.com/wangbj/elf) - does not write ELF, only parses it
-- [data-elf](https://github.com/mvv/data-elf) - parses just headers/tables; depends on a library that fails to build with modern GHCs
+- [elf](https://github.com/wangbj/elf)
+- [data-elf](https://github.com/mvv/data-elf)
 
+These just parse/serialize ELF header and table entries but not the whole ELF files.
+
 ## History
 
 For the early history look at the branch "[amakarov](https://github.com/aleksey-makarov/elf/tree/amakarov)" of
 the my copy of the [elf](https://github.com/aleksey-makarov/elf) repo.
-
-## How to build
-
-- [Install](https://nixos.org/manual/nix/stable/#chap-installation) Nix
-- `nix-shell`
-- `cabal new-configure; cabal new-build`
 
 ## Tests
 
diff --git a/examples/AsmAArch64.hs b/examples/AsmAArch64.hs
new file mode 100644
--- /dev/null
+++ b/examples/AsmAArch64.hs
@@ -0,0 +1,326 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneKindSignatures #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+
+{-# OPTIONS_GHC -Wno-unused-top-binds #-}
+
+module AsmAArch64
+    ( CodeState
+    , Register
+    , RelativeRef
+    , adr
+    , b
+    , mov
+    , ldr
+    , svc
+    , ascii
+    , label
+    , exportSymbol
+    , assemble
+    , x0, x1, x2, x8
+    , w0, w1
+    ) where
+
+import Prelude as P
+
+import Control.Exception.ChainedException
+import Control.Monad.Catch
+import Control.Monad.State as MS
+import Data.Bits
+import Data.ByteString.Builder
+import Data.ByteString.Lazy as BSL
+import Data.ByteString.Lazy.Char8 as BSLC
+import Data.Int
+import Data.Kind
+import Data.Singletons.Sigma
+import Data.Singletons.TH
+import Data.Word
+
+import Data.Elf
+import Data.Elf.Constants
+import Data.Elf.Headers
+
+$(singletons [d| data RegisterWidth = X | W |])
+
+type Register :: RegisterWidth -> Type
+newtype Register c = R Word32
+
+newtype CodeOffset  = CodeOffset  { getCodeOffset  :: Int64 }  deriving (Eq, Show, Ord, Num, Enum, Real, Integral, Bits, FiniteBits)
+newtype Instruction = Instruction { getInstruction :: Word32 } deriving (Eq, Show, Ord, Num, Enum, Real, Integral, Bits, FiniteBits)
+
+data RelativeRef = CodeRef !CodeOffset
+                 | PoolRef !CodeOffset
+
+-- Args:
+-- Offset of the instruction
+-- Offset of the pool
+type InstructionGen = CodeOffset -> CodeOffset -> Either String Instruction
+
+data CodeState = CodeState
+    { offsetInPool    :: CodeOffset
+    , poolReversed    :: [Builder]
+    , codeReversed    :: [InstructionGen]
+    , symbolsRefersed :: [(String, RelativeRef)]
+    }
+
+emit' :: MonadState CodeState m => InstructionGen -> m ()
+emit' g = modify f where
+    f CodeState {..} = CodeState { codeReversed = g : codeReversed
+                                 , ..
+                                 }
+
+emit :: MonadState CodeState m => Instruction -> m ()
+emit i = emit' $ \ _ _ -> Right i
+
+emitPool :: MonadState CodeState m => Word -> ByteString -> m RelativeRef
+emitPool a bs = state f where
+    f CodeState {..} =
+        let
+            offsetInPool' = align a offsetInPool
+            o = builderRepeatZero $ fromIntegral $ offsetInPool' - offsetInPool
+        in
+            ( PoolRef offsetInPool'
+            , CodeState { offsetInPool = fromIntegral (BSL.length bs) + offsetInPool'
+                        , poolReversed = lazyByteString bs : o : poolReversed
+                        , ..
+                        }
+            )
+
+label :: MonadState CodeState m => m RelativeRef
+label = gets (CodeRef . (* instructionSize) . fromIntegral . P.length . codeReversed)
+
+x0, x1, x2, x8 :: Register 'X
+x0 = R 0
+x1 = R 1
+x2 = R 2
+x8 = R 8
+
+w0, w1 :: Register 'W
+w0 = R 0
+w1 = R 1
+
+isPower2 :: (Bits i, Num i) => i -> Bool
+isPower2 n = n .&. (n - 1) == 0
+
+align :: Word -> CodeOffset -> CodeOffset
+align a _ | not (isPower2 a) = error "align is not a power of 2"
+align 0 n = n
+align a n = (n + a' - 1) .&. complement (a' - 1)
+    where a' = fromIntegral a
+
+builderRepeatZero :: Int -> Builder
+builderRepeatZero n = mconcat $ P.replicate n (word8 0)
+
+b64 :: forall w . SingI w => Register w -> Word32
+b64 _ = case sing @ w of
+    SX -> 1
+    SW -> 0
+
+-- | C6.2.10 ADR
+adr :: MonadState CodeState m => Register 'X -> RelativeRef -> m ()
+adr (R n) rr =  emit' f where
+
+    offsetToImm :: CodeOffset -> Either String Word32
+    offsetToImm (CodeOffset o) =
+        if not $ isBitN 19 o
+                then Left "offset is too big"
+                else
+                    let
+                        immlo = o .&. 3
+                        immhi = (o `shiftR` 2)  .&. 0x7ffff
+                    in
+                        Right $ fromIntegral $ (immhi `shift` 5) .|. (immlo `shift` 29)
+
+    f :: InstructionGen
+    f instrAddr poolOffset = do
+        imm <- offsetToImm $ findOffset poolOffset rr - instrAddr
+        return $ Instruction $  0x10000000
+                            .|. imm
+                            .|. n
+
+-- | C6.2.26 B
+b :: MonadState CodeState m => RelativeRef -> m ()
+b rr = emit' f where
+
+    offsetToImm26 :: CodeOffset -> Either String Word32
+    offsetToImm26 (CodeOffset o)
+      | o .&. 0x3 /= 0    = Left $ "offset is not aligned: " ++ show o
+      | not $ isBitN 28 o = Left "offset is too big"
+      | otherwise         = Right $ fromIntegral $ o `shiftR` 2
+
+    f :: InstructionGen
+    f instrAddr poolOffset = do
+        imm26 <- offsetToImm26 $ findOffset poolOffset rr - instrAddr
+        return $ Instruction $  0x14000000 .|. imm26
+
+-- | C6.2.187 MOV (wide immediate)
+mov :: (MonadState CodeState m, SingI w) => Register w -> Word16 -> m ()
+mov r@(R n) imm = emit $ Instruction $ (b64 r `shift` 31)
+                                    .|. 0x52800000
+                                    .|. (fromIntegral imm `shift` 5)
+                                    .|. n
+
+-- | The number can be represented with bitN bits
+isBitN ::(Num b, Bits b, Ord b) => Int -> b -> Bool
+isBitN bitN w =
+    let
+        m = complement $ (1 `shift` bitN) - 1
+        h = w .&. m
+    in if w >= 0 then h == 0 else h == m
+
+findOffset :: CodeOffset -> RelativeRef -> CodeOffset
+findOffset _poolOffset (CodeRef codeOffset)   = codeOffset
+findOffset  poolOffset (PoolRef offsetInPool) = poolOffset + offsetInPool
+
+-- | C6.2.132 LDR (literal)
+ldr :: (MonadState CodeState m, SingI w) => Register w -> RelativeRef -> m ()
+ldr r@(R n) rr = emit' f where
+
+    offsetToImm19 :: CodeOffset -> Either String Word32
+    offsetToImm19 (CodeOffset o)
+      | o .&. 0x3 /= 0    = Left "offset is not aligned"
+      | not $ isBitN 21 o = Left "offset is too big"
+      | otherwise         = Right $ fromIntegral $ o `shiftR` 2
+
+    f :: InstructionGen
+    f instrAddr poolOffset = do
+        imm19 <- offsetToImm19 $ findOffset poolOffset rr - instrAddr
+        return $ Instruction $ (b64 r `shift` 30)
+                            .|. 0x18000000
+                            .|. (imm19 `shift` 5)
+                            .|. n
+
+-- | C6.2.317 SVC
+svc :: MonadState CodeState m => Word16 -> m ()
+svc imm = emit $ 0xd4000001 .|. (fromIntegral imm `shift` 5)
+
+ascii :: MonadState CodeState m => String -> m RelativeRef
+ascii s = emitPool 1 $ BSLC.pack s
+
+exportSymbol :: MonadState CodeState m => String -> RelativeRef -> m ()
+exportSymbol s r = modify f where
+    f (CodeState {..}) = CodeState { symbolsRefersed = (s, r) : symbolsRefersed
+                                   , ..
+                                   }
+
+instructionSize :: Num b => b
+instructionSize = 4
+
+zeroIndexStringItem :: ElfSymbolXX 'ELFCLASS64
+zeroIndexStringItem = ElfSymbolXX "" 0 0 0 0 0
+
+textSecN, shstrtabSecN, strtabSecN, symtabSecN :: ElfSectionIndex
+textSecN     = 1
+shstrtabSecN = 2
+strtabSecN   = 3
+symtabSecN   = 4
+
+assemble :: MonadCatch m => StateT CodeState m () -> m Elf
+assemble m = do
+
+    CodeState {..} <- execStateT m (CodeState 0 [] [] [])
+
+    -- resolve txt
+
+    let
+        poolOffset = instructionSize * fromIntegral (P.length codeReversed)
+        poolOffsetAligned = align 8 poolOffset
+
+        f :: (InstructionGen, CodeOffset) -> Either String Instruction
+        f (ff, n) = ff n poolOffsetAligned
+
+    code <- $eitherAddContext' $ mapM f $ P.zip (P.reverse codeReversed) (fmap (instructionSize *) [CodeOffset 0 .. ])
+
+    let
+        codeBuilder = mconcat $ fmap (word32LE . getInstruction) code
+        txt = toLazyByteString $ codeBuilder
+                              <> builderRepeatZero (fromIntegral $ poolOffsetAligned - poolOffset)
+                              <> mconcat (P.reverse poolReversed)
+
+    -- resolve symbolTable
+
+    let
+        ff :: (String, RelativeRef) -> ElfSymbolXX 'ELFCLASS64
+        ff (s, r) =
+            let
+                steName  = s
+                steBind  = STB_Global
+                steType  = STT_NoType
+                steShNdx = textSecN
+                steValue = fromIntegral $ findOffset poolOffset r
+                steSize  = 0
+            in
+                ElfSymbolXX{..}
+
+        symbolTable = ff <$> P.reverse symbolsRefersed
+
+    (symbolTableData, stringTableData) <- serializeSymbolTable ELFDATA2LSB (zeroIndexStringItem : symbolTable)
+
+    return $ SELFCLASS64 :&: ElfList
+        [ ElfHeader
+            { ehData       = ELFDATA2LSB
+            , ehOSABI      = ELFOSABI_SYSV
+            , ehABIVersion = 0
+            , ehType       = ET_REL
+            , ehMachine    = EM_AARCH64
+            , ehEntry      = 0
+            , ehFlags      = 0
+            }
+        , ElfSection
+            { esName      = ".text"
+            , esType      = SHT_PROGBITS
+            , esFlags     = SHF_EXECINSTR .|. SHF_ALLOC
+            , esAddr      = 0
+            , esAddrAlign = 8
+            , esEntSize   = 0
+            , esN         = textSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionData txt
+            }
+        , ElfSection
+            { esName      = ".shstrtab"
+            , esType      = SHT_STRTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 1
+            , esEntSize   = 0
+            , esN         = shstrtabSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionDataStringTable
+            }
+        , ElfSection
+            { esName      = ".symtab"
+            , esType      = SHT_SYMTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 8
+            , esEntSize   = symbolTableEntrySize ELFCLASS64
+            , esN         = symtabSecN
+            , esLink      = fromIntegral strtabSecN
+            , esInfo      = 1
+            , esData      = ElfSectionData symbolTableData
+            }
+        , ElfSection
+            { esName      = ".strtab"
+            , esType      = SHT_STRTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 1
+            , esEntSize   = 0
+            , esN         = strtabSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionData stringTableData
+            }
+        , ElfSectionTable
+        ]
diff --git a/examples/AsmAarch64.hs b/examples/AsmAarch64.hs
deleted file mode 100644
--- a/examples/AsmAarch64.hs
+++ /dev/null
@@ -1,258 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneKindSignatures #-}
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-
-{-# OPTIONS_GHC -Wno-unused-top-binds #-}
-
-module AsmAarch64
-    ( CodeState
-    , Register
-    , RelativeRef
-    , adr
-    , b
-    , mov
-    , ldr
-    , svc
-    , ascii
-    , label
-    , exportSymbol
-    , assemble
-    , x0, x1, x2, x8
-    , w0, w1
-    ) where
-
-import Prelude as P
-
-import Control.Exception.ChainedException
-import Control.Monad.Catch
-import Control.Monad.State as MS
-import Data.Bits
-import Data.ByteString.Builder
-import Data.ByteString.Lazy as BSL
-import Data.ByteString.Lazy.Char8 as BSLC
-import Data.Int
-import Data.Kind
-import Data.Singletons.TH
-import Data.Word
-
-import Data.Elf
-import Data.Elf.Constants
-import Data.Elf.Headers
-
-$(singletons [d| data RegisterWidth = X | W |])
-
-type Register :: RegisterWidth -> Type
-newtype Register c = R Word32
-
-newtype CodeOffset  = CodeOffset  { getCodeOffset  :: Int64 }  deriving (Eq, Show, Ord, Num, Enum, Real, Integral, Bits, FiniteBits)
-newtype Instruction = Instruction { getInstruction :: Word32 } deriving (Eq, Show, Ord, Num, Enum, Real, Integral, Bits, FiniteBits)
-
-data RelativeRef = CodeRef !CodeOffset
-                 | PoolRef !CodeOffset
-
--- Args:
--- Offset of the instruction
--- Offset of the pool
-type InstructionGen = CodeOffset -> CodeOffset -> Either String Instruction
-
-data CodeState = CodeState
-    { offsetInPool    :: CodeOffset
-    , poolReversed    :: [Builder]
-    , codeReversed    :: [InstructionGen]
-    , symbolsRefersed :: [(String, RelativeRef)]
-    }
-
-emit' :: MonadState CodeState m => InstructionGen -> m ()
-emit' g = modify f where
-    f CodeState {..} = CodeState { codeReversed = g : codeReversed
-                                 , ..
-                                 }
-
-emit :: MonadState CodeState m => Instruction -> m ()
-emit i = emit' $ \ _ _ -> Right i
-
-emitPool :: MonadState CodeState m => Word -> ByteString -> m RelativeRef
-emitPool a bs = state f where
-    f CodeState {..} =
-        let
-            offsetInPool' = align a offsetInPool
-            o = builderRepeatZero $ fromIntegral $ offsetInPool' - offsetInPool
-        in
-            ( PoolRef offsetInPool'
-            , CodeState { offsetInPool = fromIntegral (BSL.length bs) + offsetInPool'
-                        , poolReversed = lazyByteString bs : o : poolReversed
-                        , ..
-                        }
-            )
-
-label :: MonadState CodeState m => m RelativeRef
-label = gets (CodeRef . (* instructionSize) . fromIntegral . P.length . codeReversed)
-
-x0, x1, x2, x8 :: Register 'X
-x0 = R 0
-x1 = R 1
-x2 = R 2
-x8 = R 8
-
-w0, w1 :: Register 'W
-w0 = R 0
-w1 = R 1
-
-isPower2 :: (Bits i, Num i) => i -> Bool
-isPower2 n = n .&. (n - 1) == 0
-
-align :: Word -> CodeOffset -> CodeOffset
-align a _ | not (isPower2 a) = error "align is not a power of 2"
-align 0 n = n
-align a n = (n + a' - 1) .&. complement (a' - 1)
-    where a' = fromIntegral a
-
-builderRepeatZero :: Int -> Builder
-builderRepeatZero n = mconcat $ P.replicate n (word8 0)
-
-b64 :: forall w . SingI w => Register w -> Word32
-b64 _ = case sing @ w of
-    SX -> 1
-    SW -> 0
-
--- | C6.2.10 ADR
-adr :: MonadState CodeState m => Register 'X -> RelativeRef -> m ()
-adr (R n) rr =  emit' f where
-
-    offsetToImm :: CodeOffset -> Either String Word32
-    offsetToImm (CodeOffset o) =
-        if not $ isBitN 19 o
-                then Left "offset is too big"
-                else
-                    let
-                        immlo = o .&. 3
-                        immhi = (o `shiftR` 2)  .&. 0x7ffff
-                    in
-                        Right $ fromIntegral $ (immhi `shift` 5) .|. (immlo `shift` 29)
-
-    f :: InstructionGen
-    f instrAddr poolOffset = do
-        imm <- offsetToImm $ findOffset poolOffset rr - instrAddr
-        return $ Instruction $  0x10000000
-                            .|. imm
-                            .|. n
-
--- | C6.2.26 B
-b :: MonadState CodeState m => RelativeRef -> m ()
-b rr = emit' f where
-
-    offsetToImm26 :: CodeOffset -> Either String Word32
-    offsetToImm26 (CodeOffset o)
-      | o .&. 0x3 /= 0    = Left $ "offset is not aligned: " ++ show o
-      | not $ isBitN 28 o = Left "offset is too big"
-      | otherwise         = Right $ fromIntegral $ o `shiftR` 2
-
-    f :: InstructionGen
-    f instrAddr poolOffset = do
-        imm26 <- offsetToImm26 $ findOffset poolOffset rr - instrAddr
-        return $ Instruction $  0x14000000 .|. imm26
-
--- | C6.2.187 MOV (wide immediate)
-mov :: (MonadState CodeState m, SingI w) => Register w -> Word16 -> m ()
-mov r@(R n) imm = emit $ Instruction $ (b64 r `shift` 31)
-                                    .|. 0x52800000
-                                    .|. (fromIntegral imm `shift` 5)
-                                    .|. n
-
--- | The number can be represented with bitN bits
-isBitN ::(Num b, Bits b, Ord b) => Int -> b -> Bool
-isBitN bitN w =
-    let
-        m = complement $ (1 `shift` bitN) - 1
-        h = w .&. m
-    in if w >= 0 then h == 0 else h == m
-
-findOffset :: CodeOffset -> RelativeRef -> CodeOffset
-findOffset _poolOffset (CodeRef codeOffset)   = codeOffset
-findOffset  poolOffset (PoolRef offsetInPool) = poolOffset + offsetInPool
-
--- | C6.2.132 LDR (literal)
-ldr :: (MonadState CodeState m, SingI w) => Register w -> RelativeRef -> m ()
-ldr r@(R n) rr = emit' f where
-
-    offsetToImm19 :: CodeOffset -> Either String Word32
-    offsetToImm19 (CodeOffset o)
-      | o .&. 0x3 /= 0    = Left "offset is not aligned"
-      | not $ isBitN 21 o = Left "offset is too big"
-      | otherwise         = Right $ fromIntegral $ o `shiftR` 2
-
-    f :: InstructionGen
-    f instrAddr poolOffset = do
-        imm19 <- offsetToImm19 $ findOffset poolOffset rr - instrAddr
-        return $ Instruction $ (b64 r `shift` 30)
-                            .|. 0x18000000
-                            .|. (imm19 `shift` 5)
-                            .|. n
-
--- | C6.2.317 SVC
-svc :: MonadState CodeState m => Word16 -> m ()
-svc imm = emit $ 0xd4000001 .|. (fromIntegral imm `shift` 5)
-
-ascii :: MonadState CodeState m => String -> m RelativeRef
-ascii s = emitPool 1 $ BSLC.pack s
-
-exportSymbol :: MonadState CodeState m => String -> RelativeRef -> m ()
-exportSymbol s r = modify f where
-    f (CodeState {..}) = CodeState { symbolsRefersed = (s, r) : symbolsRefersed
-                                   , ..
-                                   }
-
-instructionSize :: Num b => b
-instructionSize = 4
-
-zeroIndexStringItem :: ElfSymbolXX 'ELFCLASS64
-zeroIndexStringItem = ElfSymbolXX "" 0 0 0 0 0
-
-assemble :: MonadCatch m => ElfSectionIndex -> StateT CodeState m () -> m (BSL.ByteString, [ElfSymbolXX 'ELFCLASS64])
-assemble textSecN m = do
-
-    CodeState {..} <- execStateT m (CodeState 0 [] [] [])
-
-    -- resolve txt
-
-    let
-        poolOffset = instructionSize * fromIntegral (P.length codeReversed)
-        poolOffsetAligned = align 8 poolOffset
-
-        f :: (InstructionGen, CodeOffset) -> Either String Instruction
-        f (ff, n) = ff n poolOffsetAligned
-
-    code <- $eitherAddContext' $ mapM f $ P.zip (P.reverse codeReversed) (fmap (instructionSize *) [CodeOffset 0 .. ])
-
-    let
-        codeBuilder = mconcat $ fmap (word32LE . getInstruction) code
-        txt = toLazyByteString $ codeBuilder
-                              <> builderRepeatZero (fromIntegral $ poolOffsetAligned - poolOffset)
-                              <> mconcat (P.reverse poolReversed)
-
-    -- resolve symbolTable
-
-    let
-        ff :: (String, RelativeRef) -> ElfSymbolXX 'ELFCLASS64
-        ff (s, r) =
-            let
-                steName  = s
-                steBind  = STB_Global
-                steType  = STT_NoType
-                steShNdx = textSecN
-                steValue = fromIntegral $ findOffset poolOffset r
-                steSize  = 0
-            in
-                ElfSymbolXX{..}
-
-        symbolTable = ff <$> P.reverse symbolsRefersed
-
-    return (txt, zeroIndexStringItem : symbolTable)
diff --git a/examples/DummyLd.hs b/examples/DummyLd.hs
new file mode 100644
--- /dev/null
+++ b/examples/DummyLd.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module DummyLd (dummyLd) where
+
+import Control.Monad.Catch
+import Data.Bits
+import Data.ByteString.Lazy as BSL
+import Data.Word
+import Data.Singletons.Sigma
+
+import Data.Elf
+import Data.Elf.Constants
+import Data.Elf.Headers
+import Control.Exception.ChainedException
+
+addr :: Word64
+addr = 0x400000
+
+mkExe :: MonadThrow m => BSL.ByteString -> m (ElfList 'ELFCLASS64)
+mkExe txt = return $ ElfList [ segment ]
+    where
+        segment = ElfSegment
+            { epType       = PT_LOAD
+            , epFlags      = PF_X .|. PF_R
+            , epVirtAddr   = addr
+            , epPhysAddr   = addr
+            , epAddMemSize = 0
+            , epAlign      = 0x10000
+            , epData       =
+                [ ElfHeader
+                    { ehData       = ELFDATA2LSB
+                    , ehOSABI      = ELFOSABI_SYSV
+                    , ehABIVersion = 0
+                    , ehType       = ET_EXEC
+                    , ehMachine    = EM_AARCH64
+                    , ehEntry      = addr + headerSize ELFCLASS64
+                    , ehFlags      = 0
+                    }
+                , ElfRawData
+                    { edData = txt
+                    }
+                , ElfSegmentTable
+                ]
+            }
+
+dummyLd' :: MonadThrow m => ElfList 'ELFCLASS64 -> m (ElfList 'ELFCLASS64)
+dummyLd' (ElfList es) = do
+
+    txtSection <- elfFindSectionByName es ".text"
+
+    case txtSection of
+        ElfSection{esData = ElfSectionData textData} -> mkExe textData
+        _ -> $chainedError "could not find correct \".text\" section"
+
+-- | It places the content of ".text" section of the input ELF into the
+--   loadable segment of the resulting ELF.
+--   It could work if there are no relocations or references to external symbols
+dummyLd :: MonadThrow m => Elf -> m Elf
+dummyLd (SELFCLASS32 :&: _)  = $chainedError "AArch64 arch object expected"
+dummyLd (SELFCLASS64 :&: es) = (SELFCLASS64 :&:) <$> dummyLd' es
diff --git a/examples/Examples.hs b/examples/Examples.hs
--- a/examples/Examples.hs
+++ b/examples/Examples.hs
@@ -13,8 +13,8 @@
 import Data.Elf
 import Data.Elf.PrettyPrint
 
-import MkObj
-import MkExe
+import DummyLd
+import AsmAArch64
 import HelloWorld
 import ForwardLabel
 
@@ -24,13 +24,13 @@
     setFileMode path $ m .|. ownerExecuteMode
 
 helloWorldExe :: MonadCatch m => m Elf
-helloWorldExe = mkExe helloWorld
+helloWorldExe = assemble helloWorld >>= dummyLd
 
 forwardLabelExe :: (MonadCatch m, MonadFix m) => m Elf
-forwardLabelExe = mkExe forwardLabel
+forwardLabelExe = assemble forwardLabel >>= dummyLd
 
 helloWorldObj :: MonadCatch m => m Elf
-helloWorldObj = mkObj helloWorld
+helloWorldObj = assemble helloWorld
 
 fixTargetName :: String -> String
 fixTargetName = fmap f
diff --git a/examples/ForwardLabel.hs b/examples/ForwardLabel.hs
--- a/examples/ForwardLabel.hs
+++ b/examples/ForwardLabel.hs
@@ -9,7 +9,7 @@
 import Control.Monad.Fix
 import Control.Monad.State
 
-import AsmAarch64
+import AsmAArch64
 
 ok :: String
 ok = "ok\n"
diff --git a/examples/HelloWorld.hs b/examples/HelloWorld.hs
--- a/examples/HelloWorld.hs
+++ b/examples/HelloWorld.hs
@@ -8,7 +8,7 @@
 import Control.Monad.State
 import Data.Word
 
-import AsmAarch64
+import AsmAArch64
 
 msg :: String
 msg = "Hello World!\n"
diff --git a/examples/MkExe.hs b/examples/MkExe.hs
deleted file mode 100644
--- a/examples/MkExe.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-module MkExe (mkExe) where
-
-import Control.Monad.Catch
-import Control.Monad.State
-import Data.Bits
-import Data.Word
-import Data.Singletons.Sigma
-
-import Data.Elf
-import Data.Elf.Constants
-import Data.Elf.Headers
-
-import AsmAarch64
-
-addr :: Word64
-addr = 0x400000
-
-mkExe :: MonadCatch m => StateT CodeState m () -> m Elf
-mkExe m = do
-    (txt, _) <- assemble 1 m
-    let
-        segment = ElfSegment
-            { epType       = PT_LOAD
-            , epFlags      = PF_X .|. PF_R
-            , epVirtAddr   = addr
-            , epPhysAddr   = addr
-            , epAddMemSize = 0
-            , epAlign      = 0x10000
-            , epData       =
-                [ ElfHeader
-                    { ehData       = ELFDATA2LSB
-                    , ehOSABI      = ELFOSABI_SYSV
-                    , ehABIVersion = 0
-                    , ehType       = ET_EXEC
-                    , ehMachine    = EM_AARCH64
-                    , ehEntry      = addr + headerSize ELFCLASS64
-                    , ehFlags      = 0
-                    }
-                , ElfRawData
-                    { edData = txt
-                    }
-                , ElfSegmentTable
-                ]
-            }
-    return $ SELFCLASS64 :&: ElfList [ segment ]
diff --git a/examples/MkObj.hs b/examples/MkObj.hs
deleted file mode 100644
--- a/examples/MkObj.hs
+++ /dev/null
@@ -1,89 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-
-module MkObj (mkObj) where
-
-import Prelude as P
-
-import Control.Monad.Catch
-import Control.Monad.State
-import Data.Bits
-import Data.Singletons.Sigma
-
-import Data.Elf
-import Data.Elf.Constants
-import Data.Elf.Headers
-
-import AsmAarch64
-
-textSecN, shstrtabSecN, strtabSecN, symtabSecN :: ElfSectionIndex
-textSecN     = 1
-shstrtabSecN = 2
-strtabSecN   = 3
-symtabSecN   = 4
-
-mkObj :: MonadCatch m => StateT CodeState m () -> m Elf
-mkObj m = do
-
-    (txt, symbolTable) <- assemble textSecN m
-    (symbolTableData, stringTableData) <- serializeSymbolTable ELFDATA2LSB symbolTable
-
-    return $ SELFCLASS64 :&: ElfList
-        [ ElfHeader
-            { ehData       = ELFDATA2LSB
-            , ehOSABI      = ELFOSABI_SYSV
-            , ehABIVersion = 0
-            , ehType       = ET_REL
-            , ehMachine    = EM_AARCH64
-            , ehEntry      = 0
-            , ehFlags      = 0
-            }
-        , ElfSection
-            { esName      = ".text"
-            , esType      = SHT_PROGBITS
-            , esFlags     = SHF_EXECINSTR .|. SHF_ALLOC
-            , esAddr      = 0
-            , esAddrAlign = 8
-            , esEntSize   = 0
-            , esN         = textSecN
-            , esLink      = 0
-            , esInfo      = 0
-            , esData      = ElfSectionData txt
-            }
-        , ElfSection
-            { esName      = ".shstrtab"
-            , esType      = SHT_STRTAB
-            , esFlags     = 0
-            , esAddr      = 0
-            , esAddrAlign = 1
-            , esEntSize   = 0
-            , esN         = shstrtabSecN
-            , esLink      = 0
-            , esInfo      = 0
-            , esData      = ElfSectionDataStringTable
-            }
-        , ElfSection
-            { esName      = ".symtab"
-            , esType      = SHT_SYMTAB
-            , esFlags     = 0
-            , esAddr      = 0
-            , esAddrAlign = 8
-            , esEntSize   = symbolTableEntrySize ELFCLASS64
-            , esN         = symtabSecN
-            , esLink      = fromIntegral strtabSecN
-            , esInfo      = 1
-            , esData      = ElfSectionData symbolTableData
-            }
-        , ElfSection
-            { esName      = ".strtab"
-            , esType      = SHT_STRTAB
-            , esFlags     = 0
-            , esAddr      = 0
-            , esAddrAlign = 1
-            , esEntSize   = 0
-            , esN         = strtabSecN
-            , esLink      = 0
-            , esInfo      = 0
-            , esData      = ElfSectionData stringTableData
-            }
-        , ElfSectionTable
-        ]
diff --git a/examples/README_ru.md b/examples/README_ru.md
new file mode 100644
--- /dev/null
+++ b/examples/README_ru.md
@@ -0,0 +1,706 @@
+---
+title: Работа с файлами формата ELF из Хаскела
+date: November 17, 2021
+---
+
+Работа с файлами формата ELF -- популярная тема на Хабре.
+(["Введение в ELF-файлы в Linux: понимание и анализ"](https://habr.com/ru/post/480642/),
+["Минимизация файла ELF – попробуем в 2021?"](https://habr.com/ru/company/ruvds/blog/583576/) и т. д.)
+
+Существуют библиотеки для Хаскела для работы с этими файлами: `elf`
+([Hackage](https://hackage.haskell.org/package/elf)) и `data-elf`
+([Hackage](https://hackage.haskell.org/package/data-elf)).
+Эти библиотеки работают только с заголовками и элементами таблиц и не дают возможности
+сгенерировать объектный файл.
+
+Я написал библиотеку для работы с файлами формата ELF на Хаскеле
+([GitHub](https://github.com/aleksey-makarov/melf),
+ [Hackage](https://hackage.haskell.org/package/melf))
+и хочу показать как её использовать.
+
+## Внутреннее устройство ELF
+
+Первые несколько байт файла занимает заголовок ELF.
+В нём, в частности, указано, где в файле расположены таблица секций и таблица сегментов.
+
+Сегменты и секции -- непрерывные участки файла.
+Сегменты описывают, что нужно поместить в память при загрузки программы,
+а секции я бы описал как неделимые результаты работы
+компилятора.
+В секциях размещены исполняемый код, таблицы символов, инициализированные данные.
+
+Файл формата ELF можно представлять как список деревьев.
+Деревьями могуть быть секции, сегменты, заголовок файла, таблица секций, таблица сегментов.
+Поддеревья могут содержаться только в сегментах.
+Узлы дерева выравниваются в файле, например, сегменты обычно выравниваются на размер страницы,
+а секции с данными -- на размер слова.
+Вполне валидным может быть файл, где сегмент содержит данные, не размеченные как какая-либо секция.
+
+## Базовый уровень
+
+В модуле
+[`Data.Elf.Headers`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html)
+реализованы разбор и сериализация заголовка файла ELF и
+элементов таблиц секций и сегментов.  Для различения 64- и 32-битных структур 
+определён тип
+[`ElfClass`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:ElfClass)
+
+``` Haskell
+data ElfClass
+    = ELFCLASS32 -- ^ 32-bit ELF format
+    | ELFCLASS64 -- ^ 64-bit ELF format
+    deriving (Eq, Show)
+```
+
+Некоторые поля заголовка и элементов таблиц секций и сегментов имеют разную ширину в битах, зависящую от
+`ElfClass`, поэтому нужен тип
+[`WordXX a`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:WordXX),
+который был позаимствован из пакета `data-elf`:
+
+``` Haskell
+-- | @IsElfClass a@ is defined for each constructor of `ElfClass`.
+--   It defines @WordXX a@, which is `Word32` for `ELFCLASS32`
+--   and `Word64` for `ELFCLASS64`.
+type IsElfClass :: ElfClass -> Constraint
+class ( SingI c
+      , Typeable c
+      , Typeable (WordXX c)
+      , Data (WordXX c)
+      , Show (WordXX c)
+      , Read (WordXX c)
+      , Eq (WordXX c)
+      , Ord (WordXX c)
+      , Bounded (WordXX c)
+      , Enum (WordXX c)
+      , Num (WordXX c)
+      , Integral (WordXX c)
+      , Real (WordXX c)
+      , Bits (WordXX c)
+      , FiniteBits (WordXX c)
+      , Binary (Be (WordXX c))
+      , Binary (Le (WordXX c))
+      ) => IsElfClass c where
+    type WordXX c = r | r -> c
+
+instance IsElfClass 'ELFCLASS32 where
+    type WordXX 'ELFCLASS32 = Word32
+
+instance IsElfClass 'ELFCLASS64 where
+    type WordXX 'ELFCLASS64 = Word64
+```
+
+Заголовок файла ELF представлен с помощью типа
+[`HeaderXX a`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:HeaderXX):
+
+``` Haskell
+-- | Parsed ELF header
+type HeaderXX :: ElfClass -> Type
+data HeaderXX c =
+    HeaderXX
+        { hData       :: ElfData    -- ^ Data encoding (big- or little-endian)
+        , hOSABI      :: ElfOSABI   -- ^ OS/ABI identification
+        , hABIVersion :: Word8      -- ^ ABI version
+        , hType       :: ElfType    -- ^ Object file type
+        , hMachine    :: ElfMachine -- ^ Machine type
+        , hEntry      :: WordXX c   -- ^ Entry point address
+        , hPhOff      :: WordXX c   -- ^ Program header offset
+        , hShOff      :: WordXX c   -- ^ Section header offset
+        , hFlags      :: Word32     -- ^ Processor-specific flags
+        , hPhEntSize  :: Word16     -- ^ Size of program header entry
+        , hPhNum      :: Word16     -- ^ Number of program header entries
+        , hShEntSize  :: Word16     -- ^ Size of section header entry
+        , hShNum      :: Word16     -- ^ Number of section header entries
+        , hShStrNdx   :: ElfSectionIndex -- ^ Section name string table index
+        }
+```
+
+Но это разные типы для 64- и 32-битных форматов.
+Для однообразной работы с форматами с разной шириной слова определён тип
+[`Header`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:Header):
+
+``` Haskell
+-- | Sigma type where `ElfClass` defines the type of `HeaderXX`
+type Header = Sigma ElfClass (TyCon1 HeaderXX)
+```
+
+`Header` это пара, первый элемент которой -- объект типа `ElfClass`, определяющий ширину слова,
+второй -- `HeaderXX`, параметризованный первым элементом ($\Sigma$-тип из языков с зависимыми типами).
+Для симуляции $\Sigma$-типов использована библиотека `singletons`
+([Hackage](https://hackage.haskell.org/package/singletons),
+ ["Introduction to singletons"](https://blog.jle.im/entry/introduction-to-singletons-1.html)).
+
+Для `Header` определён экземпляр класса
+[`Binary`](https://hackage.haskell.org/package/binary-0.10.0.0/docs/Data-Binary.html#t:Binary).
+
+Таким образом, имея ленивую строку байт, содержащую достаточно длинный начальный отрезок файла ELF,
+можно получить заголовок этого файла, например, следующей функцией:
+
+``` Haskell
+withHeader ::                     BSL.ByteString ->
+    (forall a . IsElfClass a => HeaderXX a -> b) -> Either String b
+withHeader bs f =
+    case decodeOrFail bs of
+        Left (_, _, err) -> Left err
+        Right (_, _, (classS :&: hxx) :: Header) ->
+            Right $ withElfClass classS f hxx
+```
+
+Здесь
+[`decodeOrFail`](https://hackage.haskell.org/package/binary-0.10.0.0/docs/Data-Binary.html#v:decodeOrFail) определена в пакете
+[`binary`](https://hackage.haskell.org/package/binary), а
+[`withElfClass`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#v:withElfClass)
+похожа на
+[`withSing`](https://hackage.haskell.org/package/singletons-3.0.1/docs/Data-Singletons.html#v:withSing):
+
+``` Haskell
+-- | Convenience function for creating a
+-- context with an implicit ElfClass available.
+withElfClass :: Sing c -> (IsElfClass c => a) -> a
+withElfClass SELFCLASS64 x = x
+withElfClass SELFCLASS32 x = x
+```
+
+В `Data.Elf.Headers` определены также типы
+[`SectionXX`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:SectionXX),
+[`SegmentXX`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:SegmentXX) и
+[`SymbolXX`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf-Headers.html#t:SymbolXX)
+для элементов таблиц секций, сегментов и символов.
+
+## Верхний уровень
+
+В модуле
+[`Data.Elf`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf.html)
+реализованы полные разбор и сериализация файлов формата ELF.
+Чтобы разобрать такой файл читаются заголовок ELF, таблицa секций и таблица сегментов и
+на основании этой информации создаётся список элементов типа
+[`ElfXX`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf.html#t:ElfXX),
+отображающий рекурсивную
+структуру файла ELF.  Кроме восстановления структуры в процессе разбора, например, по номерам
+секций восстанавливаются их имена.  В результате получается объект типа
+[`Elf`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf.html#t:Elf):
+
+``` Haskell
+-- | `Elf` is a forrest of trees of type `ElfXX`.
+-- Trees are composed of `ElfXX` nodes, `ElfSegment` can contain subtrees
+newtype ElfList c = ElfList [ElfXX c]
+
+-- | Elf is a sigma type where `ElfClass` defines the type of `ElfList`
+type Elf = Sigma ElfClass (TyCon1 ElfList)
+
+-- | Section data may contain a string table.
+-- If a section contains a string table with section names, the data
+-- for such a section is generated and `esData` should contain `ElfSectionDataStringTable`
+data ElfSectionData
+    = ElfSectionData BSL.ByteString -- ^ Regular section data
+    | ElfSectionDataStringTable     -- ^ Section data will be generated from section names
+
+-- | The type of node that defines Elf structure.
+data ElfXX (c :: ElfClass)
+    = ElfHeader
+        { ehData       :: ElfData    -- ^ Data encoding (big- or little-endian)
+        , ehOSABI      :: ElfOSABI   -- ^ OS/ABI identification
+        , ehABIVersion :: Word8      -- ^ ABI version
+        , ehType       :: ElfType    -- ^ Object file type
+        , ehMachine    :: ElfMachine -- ^ Machine type
+        , ehEntry      :: WordXX c   -- ^ Entry point address
+        , ehFlags      :: Word32     -- ^ Processor-specific flags
+        }
+    | ElfSectionTable
+    | ElfSegmentTable
+    | ElfSection
+        { esName      :: String         -- ^ Section name (NB: string, not offset in the string table)
+        , esType      :: ElfSectionType -- ^ Section type
+        , esFlags     :: ElfSectionFlag -- ^ Section attributes
+        , esAddr      :: WordXX c       -- ^ Virtual address in memory
+        , esAddrAlign :: WordXX c       -- ^ Address alignment boundary
+        , esEntSize   :: WordXX c       -- ^ Size of entries, if section has table
+        , esN         :: ElfSectionIndex -- ^ Section number
+        , esInfo      :: Word32         -- ^ Miscellaneous information
+        , esLink      :: Word32         -- ^ Link to other section
+        , esData      :: ElfSectionData -- ^ The content of the section
+        }
+    | ElfSegment
+        { epType       :: ElfSegmentType -- ^ Type of segment
+        , epFlags      :: ElfSegmentFlag -- ^ Segment attributes
+        , epVirtAddr   :: WordXX c       -- ^ Virtual address in memory
+        , epPhysAddr   :: WordXX c       -- ^ Physical address
+        , epAddMemSize :: WordXX c       -- ^ Add this amount of memory after the section when the section is loaded to memory by execution system.
+                                         --   Or, in other words this is how much `pMemSize` is bigger than `pFileSize`
+        , epAlign      :: WordXX c       -- ^ Alignment of segment
+        , epData       :: [ElfXX c]      -- ^ Content of the segment
+        }
+    | ElfRawData -- ^ Some ELF files (some executables) don't bother to define
+                 -- sections for linking and have just raw data in segments.
+        { edData :: BSL.ByteString -- ^ Raw data in ELF file
+        }
+    | ElfRawAlign -- ^ Align the next data in the ELF file.
+                  -- The offset of the next data in the ELF file
+                  -- will be the minimal @x@ such that
+                  -- @x mod eaAlign == eaOffset mod eaAlign @
+        { eaOffset :: WordXX c -- ^ Align value
+        , eaAlign  :: WordXX c -- ^ Align module
+        }
+
+```
+
+Не каждый объект такого типа может быть сериализован.
+
+  * В конструкторе `ElfSection`
+остался номер секции.  Он нужен, так как таблица символов и некоторые другие структуры
+ссылаются на секци по их номерам.  Поэтому при построении объекта такого типа нужно убедиться,
+что секции пронумерованы корректно, т. е. последовательными целыми от 1 до количества секций.
+Секция с номером 0 всегда пустая и она добавляется автоматически.
+
+  * В структуре должен быть единственный `ElfHeader`, он должен быть самым первым непустым
+    узлом в дереве.
+
+  * Если есть хотя бы один узел `ElfSection`, то должен присутсвовать в точности один узел `ElfSectionTable`
+    и в точности одна секция, поле `esData` которой равно `ElfSectionDataStringTable` (таблица строк для имён секций).
+
+  * Если есть хотя бы один узел с конструктором `ElfSegment`, то должен присутсвовать в точности один узел `ElfSegmentTable`.
+
+Корректно сформированный объект можно сериализовать с помощью функции
+[`serializeElf`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf.html#v:serializeElf)
+и разобрать с помощью функции
+[`parseElf`](https://hackage.haskell.org/package/melf-1.0.0/docs/Data-Elf.html#v:parseElf):
+
+``` Haskell
+serializeElf :: MonadThrow m => Elf -> m ByteString
+parseElf :: MonadCatch m => ByteString -> m Elf
+```
+
+Экземпляр класса `Binary` для `ELF` не определён, так как
+[`Put`](https://hackage.haskell.org/package/binary-0.10.0.0/docs/Data-Binary.html#t:Put)
+не является экземпляром класса `MonadFail`.
+
+## Ассемблер как EDSL для Хаскела
+
+Для использования в демонстрационных приложениях написан модуль, 
+генерирующий машинный код для AArch64
+(файл [`AsmAarch64.hs`](https://github.com/aleksey-makarov/melf/blob/v1.0.0/examples/AsmAarch64.hs)).
+Сгенерированный код использует системные вызовы чтобы вывести на стандартный вывод "Hello World!" и завершить приложение.
+Идея позаимствована из вдохновляющей статьи Стивена Дила "От монад к машинному коду"
+([Stephen Diehl "Monads to Machine Code"](https://www.stephendiehl.com/posts/monads_machine_code.html)).
+Так же как в статье, используется монада состояния, в нашем случае `CodeState`.
+
+Инициализированные, в частности, константные данные часто размещаются в отдельных секциях.
+В нашем случае для константной строки использованы массивы литералов (literal pools).
+При этом данные размещаются в той же секции, что и машинный код, в месте,
+недоступном потоку исполнения, например, после команды возвращения из подпрограммы.
+При этом оказывается легко обращаться к таким данным с помощью команд,
+вычисляющих адрес данных с использованием счётчика команд.
+Код, обращающийся к таким данным, не требует использования таблицы перемещений.
+`CodeState` содержит размер массива литералов, сам массив литералов, массив машинных кодов и массив символов:
+
+``` Haskell
+data CodeState = CodeState
+    { offsetInPool    :: CodeOffset
+    , poolReversed    :: [Builder]
+    , codeReversed    :: [InstructionGen]
+    , symbolsRefersed :: [(String, RelativeRef)]
+    }
+```
+
+Для создания меток и ссылок на данные в массиве литералов введён тип `RelativeRef`
+
+``` Haskell
+newtype CodeOffset  = CodeOffset  { getCodeOffset  :: Int64 }
+    deriving (Eq, Show, Ord, Num, Enum, Real, Integral,
+    Bits, FiniteBits)
+
+data RelativeRef = CodeRef CodeOffset
+                 | PoolRef CodeOffset
+```
+
+Конструктор `CodeRef` используется для ссылки на код (для создания меток):
+
+``` Haskell
+label :: MonadState CodeState m => m RelativeRef
+label = gets (CodeRef . (* instructionSize)
+                      . fromIntegral
+                      . P.length
+                      . codeReversed)
+```
+
+Конструктор `PoolRef` хранит смещение данных от начала массива литералов.
+
+Фактически в массиве машинных кодов хранятся функции для генерации машинного кода
+из смещения команды от начала секции и смещения массива литералов (которое будет
+известно только после обработки всех ассемблерных команд, так как массив литералов
+располагается после кода):
+
+```Haskell
+type InstructionGen = CodeOffset ->
+                      CodeOffset -> Either String Instruction
+```
+
+Для добавления в массив машинных кодов используется функция `emit'`:
+
+```Haskell
+emit' :: MonadState CodeState m => InstructionGen -> m ()
+emit' g = modify f where
+    f CodeState {..} = CodeState { codeReversed = g : codeReversed
+                                 , ..
+                                 }
+
+emit :: MonadState CodeState m => Instruction -> m ()
+emit i = emit' $ \ _ _ -> Right i
+```
+
+Каждая встретившаяся ассемблерная команда добавляет в этот массив очередной машинный код,
+например:
+
+``` Haskell
+-- | C6.2.317 SVC
+svc :: MonadState CodeState m => Word16 -> m ()
+svc imm = emit $ 0xd4000001 .|. (fromIntegral imm `shift` 5)
+```
+
+Как и многие другие команды архитектуры AArch64, команда `mov` может работать с регистрами
+как с 64-битными или как с 32-битными значениями.
+Для указания разрядности регистров для них используются разные имена:
+`x0`, `x1`... -- для 64-битных, `w0`, `w1`... -- для 32-битных.
+Регистры определены с помощью [фантомного](https://wiki.haskell.org/Phantom_type) типа:
+
+
+``` Haskell
+data RegisterWidth = X | W
+
+type Register :: RegisterWidth -> Type
+newtype Register c = R Word32
+
+x0, x1 :: Register 'X
+x0 = R 0
+x1 = R 1
+
+w0, w1 :: Register 'W
+w0 = R 0
+w1 = R 1
+
+-- | C6.2.187 MOV (wide immediate)
+mov :: (MonadState CodeState m, SingI w) =>
+                              Register w ->
+                                  Word16 -> m ()
+```
+
+В системе команд AArch64 есть несколько вариантов команды `mov`.
+Реализована только команда с непосредственным широким аргументом (wide immediate).
+
+Команда `adr` работает с регистрами только как с 64-битными значениями:
+
+``` Haskell
+-- | C6.2.10 ADR
+adr :: MonadState CodeState m =>
+                  Register 'X ->
+                  RelativeRef -> m ()
+```
+
+Для добавления данных в массив литералов используется функция `emitPool`:
+
+``` Haskell
+emitPool :: MonadState CodeState m =>
+                              Word ->
+                        ByteString -> m RelativeRef
+```
+
+Здесь первый аргумент -- необходимое выравнивание, второй -- данные, которые нужно
+разместить в массиве.  Функция вычисляет, сколько нужно добавить байт чтобы выравнять
+данные, заносит соответствующую нулевую последовательность байт в массив `poolReversed`,
+добавляет в этот же массив данные и корректирует `offsetInPool`.
+
+С помощью этой функции можно, например, реализовать аналог ассемблерной директивы `.ascii`:
+
+``` Haskell
+ascii :: MonadState CodeState m => String -> m RelativeRef
+ascii s = emitPool 1 $ BSLC.pack s
+```
+
+Кроме того, есть массив символов.  Символы создаются из меток:
+
+``` Haskell
+exportSymbol :: MonadState CodeState m => String -> RelativeRef -> m ()
+exportSymbol s r = modify f where
+    f (CodeState {..}) = CodeState { symbolsRefersed = (s, r) : symbolsRefersed
+                                   , ..
+                                   }
+```
+
+Функция `assemble` генерирует код из `CodeState`:
+
+``` Haskell
+assemble :: MonadCatch m =>
+         ElfSectionIndex ->
+   StateT CodeState m () -> m (BSL.ByteString, [ElfSymbolXX 'ELFCLASS64])
+```
+
+Первый аргумент -- номер секции, которая будет содержать код,
+второй -- программа, которую нужно преобразовать в код.
+Функция возвращает пару, первый элемент которой -- содержание
+секции ".text", второй -- таблица символов.
+
+Для простоты не реализовано обращение к внешним символам и размещение данных в
+отдельных секциях.
+Всё это требует реализации таблиц перемещений, с другой стороры, сгенерированный код
+получается позиционно-независимым.
+
+Код для вывода "Hello World!" на встроенном в Хаскелл DSL выглядит так
+([файл `HelloWordl.hs`](https://github.com/aleksey-makarov/melf/blob/v1.0.0/examples/HelloWorld.hs)):
+
+``` Haskell
+{-# LANGUAGE DataKinds #-}
+
+module HelloWorld (helloWorld) where
+
+import Prelude as P
+
+import Control.Monad.Catch
+import Control.Monad.State
+import Data.Word
+
+import AsmAarch64
+
+msg :: String
+msg = "Hello World!\n"
+
+sys_exit, sys_write :: Word16
+sys_write = 64
+sys_exit = 93
+
+helloWorld :: MonadCatch m => StateT CodeState m ()
+helloWorld = do
+
+    start <- label
+    exportSymbol "_start" start
+    mov x0 1
+    helloString <- ascii msg
+    adr x1 helloString
+    mov x2 $ fromIntegral $ P.length msg
+    mov x8 sys_write
+    svc 0
+
+    mov x0 0
+    mov x8 sys_exit
+    svc 0
+```
+Если нужно сослаться на метку, сформированную ниже по коду, нужно работать в монаде `MonadFix`
+и использовать ключевое слово `mdo` вместо `do`
+(см. файл [`ForwardLabel.hs`](https://github.com/aleksey-makarov/melf/blob/v1.0.0/examples/ForwardLabel.hs)).
+
+## Генерация объектных файлов
+
+Используем библиотеку `melf` для генерации объектных файлов
+([файл `MkObj.hs`](https://github.com/aleksey-makarov/melf/blob/v1.0.0/examples/MkObj.hs)):
+
+``` Haskell
+{-# LANGUAGE DataKinds #-}
+
+module MkObj (mkObj) where
+
+import Prelude as P
+
+import Control.Monad.Catch
+import Control.Monad.State
+import Data.Bits
+import Data.Singletons.Sigma
+
+import Data.Elf
+import Data.Elf.Constants
+import Data.Elf.Headers
+
+import AsmAarch64
+
+textSecN, shstrtabSecN, strtabSecN, symtabSecN :: ElfSectionIndex
+textSecN     = 1
+shstrtabSecN = 2
+strtabSecN   = 3
+symtabSecN   = 4
+
+mkObj :: MonadCatch m => StateT CodeState m () -> m Elf
+mkObj m = do
+
+    (txt, symbolTable) <- assemble textSecN m
+    (symbolTableData, stringTableData) <- serializeSymbolTable ELFDATA2LSB symbolTable
+
+    return $ SELFCLASS64 :&: ElfList
+        [ ElfHeader
+            { ehData       = ELFDATA2LSB
+            , ehOSABI      = ELFOSABI_SYSV
+            , ehABIVersion = 0
+            , ehType       = ET_REL
+            , ehMachine    = EM_AARCH64
+            , ehEntry      = 0
+            , ehFlags      = 0
+            }
+        , ElfSection
+            { esName      = ".text"
+            , esType      = SHT_PROGBITS
+            , esFlags     = SHF_EXECINSTR .|. SHF_ALLOC
+            , esAddr      = 0
+            , esAddrAlign = 8
+            , esEntSize   = 0
+            , esN         = textSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionData txt
+            }
+        , ElfSection
+            { esName      = ".shstrtab"
+            , esType      = SHT_STRTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 1
+            , esEntSize   = 0
+            , esN         = shstrtabSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionDataStringTable
+            }
+        , ElfSection
+            { esName      = ".symtab"
+            , esType      = SHT_SYMTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 8
+            , esEntSize   = symbolTableEntrySize ELFCLASS64
+            , esN         = symtabSecN
+            , esLink      = fromIntegral strtabSecN
+            , esInfo      = 1
+            , esData      = ElfSectionData symbolTableData
+            }
+        , ElfSection
+            { esName      = ".strtab"
+            , esType      = SHT_STRTAB
+            , esFlags     = 0
+            , esAddr      = 0
+            , esAddrAlign = 1
+            , esEntSize   = 0
+            , esN         = strtabSecN
+            , esLink      = 0
+            , esInfo      = 0
+            , esData      = ElfSectionData stringTableData
+            }
+        , ElfSectionTable
+        ]
+```
+
+Сгенерируем с помощью этого модуля объектный файл и попробуем его слинковать:
+
+```
+[nix-shell:examples]$ ghci 
+GHCi, version 8.10.4: https://www.haskell.org/ghc/  :? for help
+Prelude> :l MkObj.hs HelloWorld.hs
+[1 of 3] Compiling AsmAarch64       ( AsmAarch64.hs, interpreted )
+[2 of 3] Compiling HelloWorld       ( HelloWorld.hs, interpreted )
+[3 of 3] Compiling MkObj            ( MkObj.hs, interpreted )
+Ok, three modules loaded.
+*MkObj> import MkObj 
+*MkObj MkObj> import HelloWorld 
+*MkObj MkObj HelloWorld> elf <- mkObj helloWorld
+*MkObj MkObj HelloWorld> import Data.Elf
+*MkObj MkObj HelloWorld Data.Elf> bs <- serializeElf elf
+*MkObj MkObj HelloWorld Data.Elf> import Data.ByteString.Lazy as BSL
+*MkObj MkObj HelloWorld Data.Elf BSL> BSL.writeFile "hello.o" bs
+*MkObj MkObj HelloWorld Data.Elf BSL> 
+Leaving GHCi.
+
+[nix-shell:examples]$ aarch64-unknown-linux-gnu-gcc -nostdlib hello.o -o hello 
+
+[nix-shell:examples]$ 
+```
+
+Как видим, линковщик благополучно принял сгенерированный объектный файл.
+Попробуем запустить результат:
+
+```
+[nix-shell:examples]$ qemu-aarch64 hello
+Hello World!
+
+[nix-shell:examples]$ 
+```
+
+Работает.
+
+## Генерация исполняемых файлов
+
+Так как сгенерированный код для распечатки "Hello World!" является позиционно-независимым
+и не ссылается на другие секции, то его можно без изменений использовать для получения
+исполняемого файла
+([файл `MkExe.hs`](https://github.com/aleksey-makarov/melf/blob/v1.0.0/examples/MkExe.hs)):
+
+``` Haskell
+module MkExe (mkExe) where
+
+import Control.Monad.Catch
+import Control.Monad.State
+import Data.Bits
+import Data.Word
+import Data.Singletons.Sigma
+
+import Data.Elf
+import Data.Elf.Constants
+import Data.Elf.Headers
+
+import AsmAarch64
+
+addr :: Word64
+addr = 0x400000
+
+mkExe :: MonadCatch m => StateT CodeState m () -> m Elf
+mkExe m = do
+    (txt, _) <- assemble 1 m
+    let
+        segment = ElfSegment
+            { epType       = PT_LOAD
+            , epFlags      = PF_X .|. PF_R
+            , epVirtAddr   = addr
+            , epPhysAddr   = addr
+            , epAddMemSize = 0
+            , epAlign      = 0x10000
+            , epData       =
+                [ ElfHeader
+                    { ehData       = ELFDATA2LSB
+                    , ehOSABI      = ELFOSABI_SYSV
+                    , ehABIVersion = 0
+                    , ehType       = ET_EXEC
+                    , ehMachine    = EM_AARCH64
+                    , ehEntry      = addr + headerSize ELFCLASS64
+                    , ehFlags      = 0
+                    }
+                , ElfRawData
+                    { edData = txt
+                    }
+                , ElfSegmentTable
+                ]
+            }
+    return $ SELFCLASS64 :&: ElfList [ segment ]
+```
+
+Попробуем его сгенерировать и запустить:
+
+```
+[nix-shell:examples]$ ghci 
+GHCi, version 8.10.4: https://www.haskell.org/ghc/  :? for help
+Prelude> :l MkExe.hs HelloWorld.hs
+[1 of 3] Compiling AsmAarch64       ( AsmAarch64.hs, interpreted )
+[2 of 3] Compiling HelloWorld       ( HelloWorld.hs, interpreted )
+[3 of 3] Compiling MkExe            ( MkExe.hs, interpreted )
+Ok, three modules loaded.
+*MkExe> import MkExe
+*MkExe MkExe> import HelloWorld
+*MkExe MkExe HelloWorld> elf <- mkExe helloWorld 
+*MkExe MkExe HelloWorld> import Data.Elf
+*MkExe MkExe HelloWorld Data.Elf> bs <- serializeElf elf
+*MkExe MkExe HelloWorld Data.Elf> import Data.ByteString.Lazy as BSL
+*MkExe MkExe HelloWorld Data.Elf BSL> BSL.writeFile "hellox" bs
+*MkExe MkExe HelloWorld Data.Elf BSL> 
+Leaving GHCi.
+
+[nix-shell:examples]$ chmod +x hellox
+
+[nix-shell:examples]$ qemu-aarch64 hellox
+Hello World!
+
+[nix-shell:examples]$ 
+```
+
+Работает.
diff --git a/examples/forwardLabelExe.dump.golden b/examples/forwardLabelExe.dump.golden
new file mode 100644
--- /dev/null
+++ b/examples/forwardLabelExe.dump.golden
@@ -0,0 +1,27 @@
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_X,PF_R]
+    VirtAddr:   0x0000000000400000
+    PhysAddr:   0x0000000000400000
+    AddMemSize: 0x0000000000000000
+    Align:      0x0000000000010000
+    Data:       
+        header {
+            Class:      ELFCLASS64
+            Data:       ELFDATA2LSB
+            OSABI:      ELFOSABI_SYSV
+            ABIVersion: 0
+            Type:       ET_EXEC
+            Machine:    EM_AARCH64
+            Entry:      0x0000000000400040
+            Flags:      0x00000000
+        }
+        raw data {
+            Data: 20 00 80 d2 61 01 00 10 62 00 80 d2 03 00 00 14 #  ...a...b.......
+                  01 01 00 70 82 00 80 d2 08 08 80 d2 01 00 00 d4 # ...p............
+                  ...
+                  01 00 00 d4 00 00 00 00 6f 6b 0a 62 61 64 0a 00 # ........ok.bad..
+                  total: 56
+        }
+        segment table
+}
diff --git a/examples/forwardLabelExe.layout.golden b/examples/forwardLabelExe.layout.golden
new file mode 100644
--- /dev/null
+++ b/examples/forwardLabelExe.layout.golden
@@ -0,0 +1,8 @@
+┌─ 0x00000000 P PT_LOAD [PF_X,PF_R]
+│┎ 0x00000000 H
+│┖ 0x0000003f
+│╓ 0x00000040 R
+│╙ 0x00000077
+│┎ 0x00000078 PT (1)
+│┖ 0x000000af
+└─ 0x000000af
diff --git a/examples/helloWorldExe.dump.golden b/examples/helloWorldExe.dump.golden
new file mode 100644
--- /dev/null
+++ b/examples/helloWorldExe.dump.golden
@@ -0,0 +1,25 @@
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_X,PF_R]
+    VirtAddr:   0x0000000000400000
+    PhysAddr:   0x0000000000400000
+    AddMemSize: 0x0000000000000000
+    Align:      0x0000000000010000
+    Data:       
+        header {
+            Class:      ELFCLASS64
+            Data:       ELFDATA2LSB
+            OSABI:      ELFOSABI_SYSV
+            ABIVersion: 0
+            Type:       ET_EXEC
+            Machine:    EM_AARCH64
+            Entry:      0x0000000000400040
+            Flags:      0x00000000
+        }
+        raw data {
+            Data: 20 00 80 d2 e1 00 00 10 a2 01 80 d2 08 08 80 d2 #  ...............
+                  01 00 00 d4 00 00 80 d2 a8 0b 80 d2 01 00 00 d4 # ................
+                  48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0a 00 00 00 # Hello World!....
+        }
+        segment table
+}
diff --git a/examples/helloWorldExe.layout.golden b/examples/helloWorldExe.layout.golden
new file mode 100644
--- /dev/null
+++ b/examples/helloWorldExe.layout.golden
@@ -0,0 +1,8 @@
+┌─ 0x00000000 P PT_LOAD [PF_X,PF_R]
+│┎ 0x00000000 H
+│┖ 0x0000003f
+│╓ 0x00000040 R
+│╙ 0x0000006f
+│┎ 0x00000070 PT (1)
+│┖ 0x000000a7
+└─ 0x000000a7
diff --git a/examples/helloWorldObj.o.dump.golden b/examples/helloWorldObj.o.dump.golden
new file mode 100644
--- /dev/null
+++ b/examples/helloWorldObj.o.dump.golden
@@ -0,0 +1,58 @@
+header {
+    Class:      ELFCLASS64
+    Data:       ELFDATA2LSB
+    OSABI:      ELFOSABI_SYSV
+    ABIVersion: 0
+    Type:       ET_REL
+    Machine:    EM_AARCH64
+    Entry:      0x0000000000000000
+    Flags:      0x00000000
+}
+section 1 ".text" {
+    Type:      SHT_PROGBITS
+    Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+    Addr:      0x0000000000000000
+    AddrAlign: 0x0000000000000008
+    EntSize:   0x0000000000000000
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      20 00 80 d2 e1 00 00 10 a2 01 80 d2 08 08 80 d2 #  ...............
+               01 00 00 d4 00 00 80 d2 a8 0b 80 d2 01 00 00 d4 # ................
+               48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0a          # Hello World!.
+}
+string table section 2 ".shstrtab"
+symbol table section 4 ".symtab" {
+    Type:      SHT_SYMTAB
+    Flags:     []
+    Addr:      0x0000000000000000
+    AddrAlign: 0x0000000000000008
+    EntSize:   0x0000000000000018
+    Info:      0x00000001
+    Link:      0x00000003
+    Data:      
+        symbol "" {
+            Bind:  STB_Local
+            Type:  STT_NoType
+            ShNdx: SHN_Undef
+            Value: 0x0000000000000000
+            Size:  0x0000000000000000
+        }
+        symbol "_start" {
+            Bind:  STB_Global
+            Type:  STT_NoType
+            ShNdx: SHN_EXT 1
+            Value: 0x0000000000000000
+            Size:  0x0000000000000000
+        }
+}
+section 3 ".strtab" {
+    Type:      SHT_STRTAB
+    Flags:     []
+    Addr:      0x0000000000000000
+    AddrAlign: 0x0000000000000001
+    EntSize:   0x0000000000000000
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      00 5f 73 74 61 72 74 00                         # ._start.
+}
+section table
diff --git a/examples/helloWorldObj.o.layout.golden b/examples/helloWorldObj.o.layout.golden
new file mode 100644
--- /dev/null
+++ b/examples/helloWorldObj.o.layout.golden
@@ -0,0 +1,12 @@
+┎ 0x00000000 H
+┖ 0x0000003f
+╓ 0x00000040 S1 ".text" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+╙ 0x0000006c
+╓ 0x0000006d S2 ".shstrtab" SHT_STRTAB []
+╙ 0x0000008d
+╓ 0x00000090 S4 ".symtab" SHT_SYMTAB []
+╙ 0x000000bf
+╓ 0x000000c0 S3 ".strtab" SHT_STRTAB []
+╙ 0x000000c7
+┎ 0x000000c8 ST (5)
+┖ 0x00000207
diff --git a/melf.cabal b/melf.cabal
--- a/melf.cabal
+++ b/melf.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           melf
-version:        1.0.0
+version:        1.0.1
 synopsis:       An Elf parser
 description:    Parser for ELF object format
 category:       Data
@@ -18,10 +18,36 @@
 license-file:   LICENSE
 build-type:     Simple
 tested-with:
-    GHC == 8.10.4
+    GHC == 8.10.7
 extra-doc-files:
     ChangeLog.md
     README.md
+    examples/README_ru.md
+data-files:
+    tests/testdata/orig/bloated.elf.golden
+    tests/testdata/orig/bloated.elf_header.golden
+    tests/testdata/orig/bloated.header.golden
+    tests/testdata/orig/bloated.layout.golden
+    tests/testdata/orig/bloated.strtable.golden
+    tests/testdata/orig/tiny.elf.golden
+    tests/testdata/orig/tiny.elf_header.golden
+    tests/testdata/orig/tiny.header.golden
+    tests/testdata/orig/tiny.layout.golden
+    tests/testdata/orig/tiny.strtable.golden
+    tests/testdata/orig/vdso.elf.golden
+    tests/testdata/orig/vdso.elf_header.golden
+    tests/testdata/orig/vdso.header.golden
+    tests/testdata/orig/vdso.layout.golden
+    tests/testdata/orig/vdso.strtable.golden
+    examples/forwardLabelExe.dump.golden
+    examples/forwardLabelExe.layout.golden
+    examples/helloWorldExe.dump.golden
+    examples/helloWorldExe.layout.golden
+    examples/helloWorldObj.o.dump.golden
+    examples/helloWorldObj.o.layout.golden
+    testdata/orig/bloated
+    testdata/orig/tiny
+    testdata/orig/vdso
 
 source-repository head
   type: git
@@ -91,11 +117,10 @@
   type: exitcode-stdio-1.0
   main-is: Examples.hs
   other-modules:
-      AsmAarch64
+      AsmAArch64
+      DummyLd
       ForwardLabel
       HelloWorld
-      MkExe
-      MkObj
       Paths_melf
   hs-source-dirs:
       examples
diff --git a/src/Data/Elf.hs b/src/Data/Elf.hs
--- a/src/Data/Elf.hs
+++ b/src/Data/Elf.hs
@@ -19,9 +19,10 @@
     , serializeElf
 
     -- * Misc
-    , getSectionData
-    , getString
+    , getSectionData -- FIXME: Should be moved to Data.Elf.Headers (requires bumping major version)
+    , getString      -- FIXME: ...
     , elfFindSection
+    , elfFindSectionByName
     , elfFindHeader
 
     -- * Symbol table
diff --git a/src/Data/Elf/PrettyPrint.hs b/src/Data/Elf/PrettyPrint.hs
--- a/src/Data/Elf/PrettyPrint.hs
+++ b/src/Data/Elf/PrettyPrint.hs
@@ -99,6 +99,7 @@
 printWordXX :: SingI a => WordXX a -> Doc ()
 printWordXX = withSing printWordXXS
 
+-- | Print ELF header.  It's used in golden tests
 printHeader :: forall a . SingI a => HeaderXX a -> Doc ()
 printHeader HeaderXX{..} =
     formatPairs
@@ -149,7 +150,8 @@
         , ("Align",    printWordXX pAlign    ) -- WordXX c
         ]
 
--- | Print parsed headers.  It's used in golden tests
+-- | Print parsed header, section table and segment table.
+--   It's used in golden tests
 printHeaders :: SingI a => HeaderXX a -> [SectionXX a] -> [SegmentXX a] -> Doc ()
 printHeaders hdr ss ps =
     let
diff --git a/src/Data/Internal/Elf.hs b/src/Data/Internal/Elf.hs
--- a/src/Data/Internal/Elf.hs
+++ b/src/Data/Internal/Elf.hs
@@ -370,6 +370,17 @@
             f s@ElfSection{..} | esN == fromIntegral n = First $ Just s
             f _ = First Nothing
 
+-- | Find section with a given name
+elfFindSectionByName :: forall a m . (SingI a, MonadThrow m)
+                     => [ElfXX a]   -- ^ Structured ELF data
+                     -> String      -- ^ Section name
+                     -> m (ElfXX a) -- ^ The section in question
+elfFindSectionByName elfs n = $maybeAddContext ("no section \"" ++ show n ++ "\"") maybeSection
+    where
+        maybeSection = getFirst $ foldMapElfList f elfs
+        f s@ElfSection{..} | esName == n = First $ Just s
+        f _ = First Nothing
+
 -- | Find ELF header
 elfFindHeader :: forall a m . (SingI a, MonadThrow m)
               => [ElfXX a]   -- ^ Structured ELF data
diff --git a/testdata/orig/bloated b/testdata/orig/bloated
new file mode 100644
Binary files /dev/null and b/testdata/orig/bloated differ
diff --git a/testdata/orig/tiny b/testdata/orig/tiny
new file mode 100644
Binary files /dev/null and b/testdata/orig/tiny differ
diff --git a/testdata/orig/vdso b/testdata/orig/vdso
new file mode 100644
Binary files /dev/null and b/testdata/orig/vdso differ
diff --git a/tests/Golden.hs b/tests/Golden.hs
--- a/tests/Golden.hs
+++ b/tests/Golden.hs
@@ -241,7 +241,10 @@
                                        ]
 
 elfsForHeader :: [String]
-elfsForHeader = [ "testdata/ppc/64/du", "testdata/arm_32_lsb/arp" ]
+elfsForHeader = [ "testdata/orig/bloated"
+                , "testdata/orig/tiny"
+                , "testdata/orig/vdso"
+                ]
 
 main :: IO ()
 main = do
diff --git a/tests/testdata/orig/bloated.elf.golden b/tests/testdata/orig/bloated.elf.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/bloated.elf.golden
@@ -0,0 +1,483 @@
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_X,PF_R]
+    VirtAddr:   0x08048000
+    PhysAddr:   0x08048000
+    AddMemSize: 0x00000000
+    Align:      0x00001000
+    Data:       
+        segment {
+            Type:       PT_EXT 1685382481
+            Flags:      [PF_W,PF_R]
+            VirtAddr:   0x00000000
+            PhysAddr:   0x00000000
+            AddMemSize: 0x00000000
+            Align:      0x00000010
+            Data:       
+        }
+        header {
+            Class:      ELFCLASS32
+            Data:       ELFDATA2LSB
+            OSABI:      ELFOSABI_SYSV
+            ABIVersion: 0
+            Type:       ET_EXEC
+            Machine:    EM_386
+            Entry:      0x08048610
+            Flags:      0x00000000
+        }
+        segment {
+            Type:       PT_PHDR
+            Flags:      [PF_X,PF_R]
+            VirtAddr:   0x08048034
+            PhysAddr:   0x08048034
+            AddMemSize: 0x00000000
+            Align:      0x00000004
+            Data:       
+                segment table
+        }
+        segment {
+            Type:       PT_INTERP
+            Flags:      [PF_R]
+            VirtAddr:   0x08048154
+            PhysAddr:   0x08048154
+            AddMemSize: 0x00000000
+            Align:      0x00000001
+            Data:       
+                section 1 ".interp" {
+                    Type:      SHT_PROGBITS
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x08048154
+                    AddrAlign: 0x00000001
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      2f 6c 69 62 2f 6c 64 2d 6c 69 6e 75 78 2e 73 6f # /lib/ld-linux.so
+                               2e 32 00                                        # .2.
+                }
+        }
+        segment {
+            Type:       PT_NOTE
+            Flags:      [PF_R]
+            VirtAddr:   0x08048168
+            PhysAddr:   0x08048168
+            AddMemSize: 0x00000000
+            Align:      0x00000004
+            Data:       
+                section 2 ".note.ABI-tag" {
+                    Type:      SHT_NOTE
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x08048168
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      04 00 00 00 10 00 00 00 01 00 00 00 47 4e 55 00 # ............GNU.
+                               00 00 00 00 02 00 00 00 06 00 00 00 20 00 00 00 # ............ ...
+                }
+                section 3 ".note.gnu.build-id" {
+                    Type:      SHT_NOTE
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x08048188
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      04 00 00 00 14 00 00 00 03 00 00 00 47 4e 55 00 # ............GNU.
+                               58 e3 4f e8 bc 03 f9 db 4b 07 fa e5 03 1e fd d0 # X.O.....K.......
+                               88 97 6f 88                                     # ..o.
+                }
+        }
+        section 4 ".gnu.hash" {
+            Type:      SHT_EXT 1879048182
+            Flags:     [SHF_ALLOC]
+            Addr:      0x080481ac
+            AddrAlign: 0x00000004
+            EntSize:   0x00000004
+            Info:      0x00000000
+            Link:      0x00000005
+            Data:      03 00 00 00 0a 00 00 00 01 00 00 00 05 00 00 00 # ................
+                       01 23 10 20 00 00 00 00 0a 00 00 00 0c 00 00 00 # .#. ............
+                       ac 4b e3 c0 21 fd f4 09 28 45 d5 4c 15 98 0c 43 # .K..!...(E.L...C
+        }
+        symbol table section 5 ".dynsym" {
+            Type:      SHT_DYNSYM
+            Flags:     [SHF_ALLOC]
+            Addr:      0x080481dc
+            AddrAlign: 0x00000004
+            EntSize:   0x00000010
+            Info:      0x00000001
+            Link:      0x00000006
+            Data:      
+                symbol "" {
+                    Bind:  STB_Local
+                    Type:  STT_NoType
+                    ShNdx: SHN_Undef
+                    Value: 0x00000000
+                    Size:  0x00000000
+                }
+                symbol "__cxa_atexit" {
+                    Bind:  STB_Global
+                    Type:  STT_Func
+                    ShNdx: SHN_Undef
+                    Value: 0x00000000
+                    Size:  0x00000000
+                }
+                ...
+                symbol "_ZSt4cout" {
+                    Bind:  STB_Global
+                    Type:  STT_Object
+                    ShNdx: SHN_EXT 26
+                    Value: 0x0804a040
+                    Size:  0x0000008c
+                }
+                total: 14
+        }
+        section 6 ".dynstr" {
+            Type:      SHT_STRTAB
+            Flags:     [SHF_ALLOC]
+            Addr:      0x080482bc
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      00 6c 69 62 73 74 64 63 2b 2b 2e 73 6f 2e 36 00 # .libstdc++.so.6.
+                       5f 5f 67 6d 6f 6e 5f 73 74 61 72 74 5f 5f 00 5f # __gmon_start__._
+                       ...
+                       32 2e 30 00 47 4c 49 42 43 5f 32 2e 31 2e 33 00 # 2.0.GLIBC_2.1.3.
+                       total: 409
+        }
+        section 7 ".gnu.version" {
+            Type:      SHT_EXT 1879048191
+            Flags:     [SHF_ALLOC]
+            Addr:      0x08048456
+            AddrAlign: 0x00000002
+            EntSize:   0x00000002
+            Info:      0x00000000
+            Link:      0x00000005
+            Data:      00 00 02 00 00 00 00 00 03 00 04 00 00 00 03 00 # ................
+                       00 00 03 00 01 00 03 00 03 00 03 00             # ............
+        }
+        section 8 ".gnu.version_r" {
+            Type:      SHT_EXT 1879048190
+            Flags:     [SHF_ALLOC]
+            Addr:      0x08048474
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+            Info:      0x00000002
+            Link:      0x00000006
+            Data:      01 00 01 00 01 00 00 00 10 00 00 00 20 00 00 00 # ............ ...
+                       74 29 92 08 00 00 03 00 77 01 00 00 00 00 00 00 # t)......w.......
+                       ...
+                       73 1f 69 09 00 00 02 00 8d 01 00 00 00 00 00 00 # s.i.............
+                       total: 80
+        }
+        section 9 ".rel.dyn" {
+            Type:      SHT_REL
+            Flags:     [SHF_ALLOC]
+            Addr:      0x080484c4
+            AddrAlign: 0x00000004
+            EntSize:   0x00000008
+            Info:      0x00000000
+            Link:      0x00000005
+            Data:      fc 9f 04 08 06 02 00 00 40 a0 04 08 05 0d 00 00 # ........@.......
+        }
+        section 10 ".rel.plt" {
+            Type:      SHT_REL
+            Flags:     [SHF_ALLOC,SHF_EXT 64]
+            Addr:      0x080484d4
+            AddrAlign: 0x00000004
+            EntSize:   0x00000008
+            Info:      0x00000018
+            Link:      0x00000005
+            Data:      0c a0 04 08 07 01 00 00 10 a0 04 08 07 04 00 00 # ................
+                       14 a0 04 08 07 05 00 00 18 a0 04 08 07 0c 00 00 # ................
+                       ...
+                       20 a0 04 08 07 09 00 00 24 a0 04 08 07 0b 00 00 #  .......$.......
+                       total: 56
+        }
+        section 11 ".init" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x0804850c
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      53 83 ec 08 e8 2b 01 00 00 81 c3 eb 1a 00 00 8b # S....+..........
+                       83 fc ff ff ff 85 c0 74 05 e8 86 00 00 00 83 c4 # .......t........
+                       08 5b c3                                        # .[.
+        }
+        section 12 ".plt" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x08048530
+            AddrAlign: 0x00000010
+            EntSize:   0x00000004
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      ff 35 04 a0 04 08 ff 25 08 a0 04 08 00 00 00 00 # .5.....%........
+                       ff 25 0c a0 04 08 68 00 00 00 00 e9 e0 ff ff ff # .%....h.........
+                       ...
+                       ff 25 24 a0 04 08 68 30 00 00 00 e9 80 ff ff ff # .%$...h0........
+                       total: 128
+        }
+        section 13 ".plt.got" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x080485b0
+            AddrAlign: 0x00000008
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      ff 25 fc 9f 04 08 66 90                         # .%....f.
+        }
+        section 14 ".text" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x080485c0
+            AddrAlign: 0x00000010
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      55 89 e5 83 ec 18 8d 05 cd a0 04 08 89 04 24 e8 # U.............$.
+                       7c ff ff ff 8d 05 70 85 04 08 8d 0d cd a0 04 08 # |.....p.........
+                       ...
+                       fe 75 e3 83 c4 0c 5b 5e 5f 5d c3 8d 76 00 f3 c3 # .u....[^_]..v...
+                       total: 530
+        }
+        section 15 ".fini" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x080487d4
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      53 83 ec 08 e8 63 fe ff ff 81 c3 23 18 00 00 83 # S....c.....#....
+                       c4 08 5b c3                                     # ..[.
+        }
+        section 16 ".rodata" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC]
+            Addr:      0x080487e8
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      03 00 00 00 01 00 02 00 00 00 00 00 48 65 6c 6c # ............Hell
+                       6f 20 77 6f 72 6c 64 21 00                      # o world!.
+        }
+        segment {
+            Type:       PT_EXT 1685382480
+            Flags:      [PF_R]
+            VirtAddr:   0x08048804
+            PhysAddr:   0x08048804
+            AddMemSize: 0x00000000
+            Align:      0x00000004
+            Data:       
+                section 17 ".eh_frame_hdr" {
+                    Type:      SHT_PROGBITS
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x08048804
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      01 1b 03 3b 38 00 00 00 06 00 00 00 2c fd ff ff # ...;8.......,...
+                               54 00 00 00 bc fd ff ff 78 00 00 00 fc fd ff ff # T.......x.......
+                               ...
+                               6c ff ff ff cc 00 00 00 cc ff ff ff 18 01 00 00 # l...............
+                               total: 60
+                }
+        }
+        section 18 ".eh_frame" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC]
+            Addr:      0x08048840
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      14 00 00 00 00 00 00 00 01 7a 52 00 01 7c 08 01 # .........zR..|..
+                       1b 0c 04 04 88 01 00 00 20 00 00 00 1c 00 00 00 # ........ .......
+                       ...
+                       ac fe ff ff 02 00 00 00 00 00 00 00 00 00 00 00 # ................
+                       total: 244
+        }
+}
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_W,PF_R]
+    VirtAddr:   0x08049eec
+    PhysAddr:   0x08049eec
+    AddMemSize: 0x000000a4
+    Align:      0x00001000
+    Data:       
+        segment {
+            Type:       PT_EXT 1685382482
+            Flags:      [PF_R]
+            VirtAddr:   0x08049eec
+            PhysAddr:   0x08049eec
+            AddMemSize: 0x00000000
+            Align:      0x00000001
+            Data:       
+                section 19 ".init_array" {
+                    Type:      SHT_EXT 14
+                    Flags:     [SHF_WRITE,SHF_ALLOC]
+                    Addr:      0x08049eec
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      e0 86 04 08 00 86 04 08                         # ........
+                }
+                section 20 ".fini_array" {
+                    Type:      SHT_EXT 15
+                    Flags:     [SHF_WRITE,SHF_ALLOC]
+                    Addr:      0x08049ef4
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      c0 86 04 08                                     # ....
+                }
+                section 21 ".jcr" {
+                    Type:      SHT_PROGBITS
+                    Flags:     [SHF_WRITE,SHF_ALLOC]
+                    Addr:      0x08049ef8
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      00 00 00 00                                     # ....
+                }
+                segment {
+                    Type:       PT_DYNAMIC
+                    Flags:      [PF_W,PF_R]
+                    VirtAddr:   0x08049efc
+                    PhysAddr:   0x08049efc
+                    AddMemSize: 0x00000000
+                    Align:      0x00000004
+                    Data:       
+                        section 22 ".dynamic" {
+                            Type:      SHT_DYNAMIC
+                            Flags:     [SHF_WRITE,SHF_ALLOC]
+                            Addr:      0x08049efc
+                            AddrAlign: 0x00000004
+                            EntSize:   0x00000008
+                            Info:      0x00000000
+                            Link:      0x00000006
+                            Data:      01 00 00 00 01 00 00 00 01 00 00 00 27 01 00 00 # ............'...
+                                       01 00 00 00 31 01 00 00 01 00 00 00 3f 01 00 00 # ....1.......?...
+                                       ...
+                                       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                                       total: 256
+                        }
+                }
+                section 23 ".got" {
+                    Type:      SHT_PROGBITS
+                    Flags:     [SHF_WRITE,SHF_ALLOC]
+                    Addr:      0x08049ffc
+                    AddrAlign: 0x00000004
+                    EntSize:   0x00000004
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      00 00 00 00                                     # ....
+                }
+        }
+        section 24 ".got.plt" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_WRITE,SHF_ALLOC]
+            Addr:      0x0804a000
+            AddrAlign: 0x00000004
+            EntSize:   0x00000004
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      fc 9e 04 08 00 00 00 00 00 00 00 00 46 85 04 08 # ............F...
+                       56 85 04 08 66 85 04 08 76 85 04 08 86 85 04 08 # V...f...v.......
+                       96 85 04 08 a6 85 04 08                         # ........
+        }
+        section 25 ".data" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_WRITE,SHF_ALLOC]
+            Addr:      0x0804a028
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      00 00 00 00                                     # ....
+        }
+}
+section 26 ".bss" {
+    Type:      SHT_NOBITS
+    Flags:     [SHF_WRITE,SHF_ALLOC]
+    Addr:      0x0804a040
+    AddrAlign: 0x00000020
+    EntSize:   0x00000000
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      
+}
+section 27 ".comment" {
+    Type:      SHT_PROGBITS
+    Flags:     [SHF_EXT 16,SHF_EXT 32]
+    Addr:      0x00000000
+    AddrAlign: 0x00000001
+    EntSize:   0x00000001
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      47 43 43 3a 20 28 47 4e 55 29 20 36 2e 33 2e 31 # GCC: (GNU) 6.3.1
+               20 32 30 31 36 31 32 32 31 20 28 52 65 64 20 48 #  20161221 (Red H
+               ...
+               45 41 53 45 5f 33 38 31 2f 66 69 6e 61 6c 29 00 # EASE_381/final).
+               total: 89
+}
+symbol table section 29 ".symtab" {
+    Type:      SHT_SYMTAB
+    Flags:     []
+    Addr:      0x00000000
+    AddrAlign: 0x00000004
+    EntSize:   0x00000010
+    Info:      0x00000032
+    Link:      0x0000001e
+    Data:      
+        symbol "" {
+            Bind:  STB_Local
+            Type:  STT_NoType
+            ShNdx: SHN_Undef
+            Value: 0x00000000
+            Size:  0x00000000
+        }
+        symbol "" {
+            Bind:  STB_Local
+            Type:  STT_Section
+            ShNdx: SHN_EXT 1
+            Value: 0x08048154
+            Size:  0x00000000
+        }
+        ...
+        symbol "_init" {
+            Bind:  STB_Global
+            Type:  STT_Func
+            ShNdx: SHN_EXT 11
+            Value: 0x0804850c
+            Size:  0x00000000
+        }
+        total: 78
+}
+section 30 ".strtab" {
+    Type:      SHT_STRTAB
+    Flags:     []
+    Addr:      0x00000000
+    AddrAlign: 0x00000001
+    EntSize:   0x00000000
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      00 5f 47 4c 4f 42 41 4c 5f 5f 73 75 62 5f 49 5f # ._GLOBAL__sub_I_
+               62 6c 6f 61 74 65 64 2e 63 70 70 00 5f 5a 53 74 # bloated.cpp._ZSt
+               ...
+               33 2e 34 00 5f 65 64 61 74 61 00 6d 61 69 6e 00 # 3.4._edata.main.
+               total: 891
+}
+string table section 28 ".shstrtab"
+section table
diff --git a/tests/testdata/orig/bloated.elf_header.golden b/tests/testdata/orig/bloated.elf_header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/bloated.elf_header.golden
@@ -0,0 +1,15 @@
+Class:      ELFCLASS32
+Data:       ELFDATA2LSB
+OSABI:      ELFOSABI_SYSV
+ABIVersion: 0
+Type:       ET_EXEC
+Machine:    EM_386
+Entry:      0x08048610
+PhOff:      0x00000034
+ShOff:      0x000019f0
+Flags:      0x00000000
+PhEntSize:  0x0020
+PhNum:      9
+ShEntSize:  0x0028
+ShNum:      31
+ShStrNdx:   SHN_EXT 28
diff --git a/tests/testdata/orig/bloated.header.golden b/tests/testdata/orig/bloated.header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/bloated.header.golden
@@ -0,0 +1,437 @@
+Header:   Class:      ELFCLASS32
+          Data:       ELFDATA2LSB
+          OSABI:      ELFOSABI_SYSV
+          ABIVersion: 0
+          Type:       ET_EXEC
+          Machine:    EM_386
+          Entry:      0x08048610
+          PhOff:      0x00000034
+          ShOff:      0x000019f0
+          Flags:      0x00000000
+          PhEntSize:  0x0020
+          PhNum:      9
+          ShEntSize:  0x0028
+          ShNum:      31
+          ShStrNdx:   SHN_EXT 28
+Sections: - N:         0
+            Name:      0
+            Type:      SHT_NULL
+            Flags:     0x00000000
+            Addr:      0x00000000
+            Offset:    0x00000000
+            Size:      0x00000000
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000000
+            EntSize:   0x00000000
+          - N:         1
+            Name:      27
+            Type:      SHT_PROGBITS
+            Flags:     0x00000002
+            Addr:      0x08048154
+            Offset:    0x00000154
+            Size:      0x00000013
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+          - N:         2
+            Name:      35
+            Type:      SHT_NOTE
+            Flags:     0x00000002
+            Addr:      0x08048168
+            Offset:    0x00000168
+            Size:      0x00000020
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         3
+            Name:      49
+            Type:      SHT_NOTE
+            Flags:     0x00000002
+            Addr:      0x08048188
+            Offset:    0x00000188
+            Size:      0x00000024
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         4
+            Name:      68
+            Type:      SHT_EXT 1879048182
+            Flags:     0x00000002
+            Addr:      0x080481ac
+            Offset:    0x000001ac
+            Size:      0x00000030
+            Link:      5
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000004
+          - N:         5
+            Name:      78
+            Type:      SHT_DYNSYM
+            Flags:     0x00000002
+            Addr:      0x080481dc
+            Offset:    0x000001dc
+            Size:      0x000000e0
+            Link:      6
+            Info:      1
+            AddrAlign: 0x00000004
+            EntSize:   0x00000010
+          - N:         6
+            Name:      86
+            Type:      SHT_STRTAB
+            Flags:     0x00000002
+            Addr:      0x080482bc
+            Offset:    0x000002bc
+            Size:      0x00000199
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+          - N:         7
+            Name:      94
+            Type:      SHT_EXT 1879048191
+            Flags:     0x00000002
+            Addr:      0x08048456
+            Offset:    0x00000456
+            Size:      0x0000001c
+            Link:      5
+            Info:      0
+            AddrAlign: 0x00000002
+            EntSize:   0x00000002
+          - N:         8
+            Name:      107
+            Type:      SHT_EXT 1879048190
+            Flags:     0x00000002
+            Addr:      0x08048474
+            Offset:    0x00000474
+            Size:      0x00000050
+            Link:      6
+            Info:      2
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         9
+            Name:      122
+            Type:      SHT_REL
+            Flags:     0x00000002
+            Addr:      0x080484c4
+            Offset:    0x000004c4
+            Size:      0x00000010
+            Link:      5
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000008
+          - N:         10
+            Name:      131
+            Type:      SHT_REL
+            Flags:     0x00000042
+            Addr:      0x080484d4
+            Offset:    0x000004d4
+            Size:      0x00000038
+            Link:      5
+            Info:      24
+            AddrAlign: 0x00000004
+            EntSize:   0x00000008
+          - N:         11
+            Name:      140
+            Type:      SHT_PROGBITS
+            Flags:     0x00000006
+            Addr:      0x0804850c
+            Offset:    0x0000050c
+            Size:      0x00000023
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         12
+            Name:      135
+            Type:      SHT_PROGBITS
+            Flags:     0x00000006
+            Addr:      0x08048530
+            Offset:    0x00000530
+            Size:      0x00000080
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000010
+            EntSize:   0x00000004
+          - N:         13
+            Name:      146
+            Type:      SHT_PROGBITS
+            Flags:     0x00000006
+            Addr:      0x080485b0
+            Offset:    0x000005b0
+            Size:      0x00000008
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000008
+            EntSize:   0x00000000
+          - N:         14
+            Name:      155
+            Type:      SHT_PROGBITS
+            Flags:     0x00000006
+            Addr:      0x080485c0
+            Offset:    0x000005c0
+            Size:      0x00000212
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000010
+            EntSize:   0x00000000
+          - N:         15
+            Name:      161
+            Type:      SHT_PROGBITS
+            Flags:     0x00000006
+            Addr:      0x080487d4
+            Offset:    0x000007d4
+            Size:      0x00000014
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         16
+            Name:      167
+            Type:      SHT_PROGBITS
+            Flags:     0x00000002
+            Addr:      0x080487e8
+            Offset:    0x000007e8
+            Size:      0x00000019
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         17
+            Name:      175
+            Type:      SHT_PROGBITS
+            Flags:     0x00000002
+            Addr:      0x08048804
+            Offset:    0x00000804
+            Size:      0x0000003c
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         18
+            Name:      189
+            Type:      SHT_PROGBITS
+            Flags:     0x00000002
+            Addr:      0x08048840
+            Offset:    0x00000840
+            Size:      0x000000f4
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         19
+            Name:      199
+            Type:      SHT_EXT 14
+            Flags:     0x00000003
+            Addr:      0x08049eec
+            Offset:    0x00000eec
+            Size:      0x00000008
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         20
+            Name:      211
+            Type:      SHT_EXT 15
+            Flags:     0x00000003
+            Addr:      0x08049ef4
+            Offset:    0x00000ef4
+            Size:      0x00000004
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         21
+            Name:      223
+            Type:      SHT_PROGBITS
+            Flags:     0x00000003
+            Addr:      0x08049ef8
+            Offset:    0x00000ef8
+            Size:      0x00000004
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000000
+          - N:         22
+            Name:      228
+            Type:      SHT_DYNAMIC
+            Flags:     0x00000003
+            Addr:      0x08049efc
+            Offset:    0x00000efc
+            Size:      0x00000100
+            Link:      6
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000008
+          - N:         23
+            Name:      150
+            Type:      SHT_PROGBITS
+            Flags:     0x00000003
+            Addr:      0x08049ffc
+            Offset:    0x00000ffc
+            Size:      0x00000004
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000004
+          - N:         24
+            Name:      237
+            Type:      SHT_PROGBITS
+            Flags:     0x00000003
+            Addr:      0x0804a000
+            Offset:    0x00001000
+            Size:      0x00000028
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000004
+            EntSize:   0x00000004
+          - N:         25
+            Name:      246
+            Type:      SHT_PROGBITS
+            Flags:     0x00000003
+            Addr:      0x0804a028
+            Offset:    0x00001028
+            Size:      0x00000004
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+          - N:         26
+            Name:      252
+            Type:      SHT_NOBITS
+            Flags:     0x00000003
+            Addr:      0x0804a040
+            Offset:    0x0000102c
+            Size:      0x00000090
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000020
+            EntSize:   0x00000000
+          - N:         27
+            Name:      257
+            Type:      SHT_PROGBITS
+            Flags:     0x00000030
+            Addr:      0x00000000
+            Offset:    0x0000102c
+            Size:      0x00000059
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000001
+          - N:         28
+            Name:      17
+            Type:      SHT_STRTAB
+            Flags:     0x00000000
+            Addr:      0x00000000
+            Offset:    0x000018e3
+            Size:      0x0000010a
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+          - N:         29
+            Name:      1
+            Type:      SHT_SYMTAB
+            Flags:     0x00000000
+            Addr:      0x00000000
+            Offset:    0x00001088
+            Size:      0x000004e0
+            Link:      30
+            Info:      50
+            AddrAlign: 0x00000004
+            EntSize:   0x00000010
+          - N:         30
+            Name:      9
+            Type:      SHT_STRTAB
+            Flags:     0x00000000
+            Addr:      0x00000000
+            Offset:    0x00001568
+            Size:      0x0000037b
+            Link:      0
+            Info:      0
+            AddrAlign: 0x00000001
+            EntSize:   0x00000000
+Segments: - N:        0
+            Type:     PT_PHDR
+            Flags:    [PF_X,PF_R]
+            Offset:   0x00000034
+            VirtAddr: 0x08048034
+            PhysAddr: 0x08048034
+            FileSize: 0x00000120
+            MemSize:  0x00000120
+            Align:    0x00000004
+          - N:        1
+            Type:     PT_INTERP
+            Flags:    [PF_R]
+            Offset:   0x00000154
+            VirtAddr: 0x08048154
+            PhysAddr: 0x08048154
+            FileSize: 0x00000013
+            MemSize:  0x00000013
+            Align:    0x00000001
+          - N:        2
+            Type:     PT_LOAD
+            Flags:    [PF_X,PF_R]
+            Offset:   0x00000000
+            VirtAddr: 0x08048000
+            PhysAddr: 0x08048000
+            FileSize: 0x00000934
+            MemSize:  0x00000934
+            Align:    0x00001000
+          - N:        3
+            Type:     PT_LOAD
+            Flags:    [PF_W,PF_R]
+            Offset:   0x00000eec
+            VirtAddr: 0x08049eec
+            PhysAddr: 0x08049eec
+            FileSize: 0x00000140
+            MemSize:  0x000001e4
+            Align:    0x00001000
+          - N:        4
+            Type:     PT_DYNAMIC
+            Flags:    [PF_W,PF_R]
+            Offset:   0x00000efc
+            VirtAddr: 0x08049efc
+            PhysAddr: 0x08049efc
+            FileSize: 0x00000100
+            MemSize:  0x00000100
+            Align:    0x00000004
+          - N:        5
+            Type:     PT_NOTE
+            Flags:    [PF_R]
+            Offset:   0x00000168
+            VirtAddr: 0x08048168
+            PhysAddr: 0x08048168
+            FileSize: 0x00000044
+            MemSize:  0x00000044
+            Align:    0x00000004
+          - N:        6
+            Type:     PT_EXT 1685382480
+            Flags:    [PF_R]
+            Offset:   0x00000804
+            VirtAddr: 0x08048804
+            PhysAddr: 0x08048804
+            FileSize: 0x0000003c
+            MemSize:  0x0000003c
+            Align:    0x00000004
+          - N:        7
+            Type:     PT_EXT 1685382481
+            Flags:    [PF_W,PF_R]
+            Offset:   0x00000000
+            VirtAddr: 0x00000000
+            PhysAddr: 0x00000000
+            FileSize: 0x00000000
+            MemSize:  0x00000000
+            Align:    0x00000010
+          - N:        8
+            Type:     PT_EXT 1685382482
+            Flags:    [PF_R]
+            Offset:   0x00000eec
+            VirtAddr: 0x08049eec
+            PhysAddr: 0x08049eec
+            FileSize: 0x00000114
+            MemSize:  0x00000114
+            Align:    0x00000001
diff --git a/tests/testdata/orig/bloated.layout.golden b/tests/testdata/orig/bloated.layout.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/bloated.layout.golden
@@ -0,0 +1,82 @@
+ ┌── 0x00000000 P PT_LOAD [PF_X,PF_R]
+ │ - 0x00000000 P PT_EXT 1685382481 [PF_W,PF_R]
+ │ ┎ 0x00000000 H
+ │ ┖ 0x00000033
+ │┌─ 0x00000034 P PT_PHDR [PF_X,PF_R]
+ ││┎ 0x00000034 PT (9)
+ ││┖ 0x00000153
+ │└─ 0x00000153
+ │┌─ 0x00000154 P PT_INTERP [PF_R]
+ ││╓ 0x00000154 S1 ".interp" SHT_PROGBITS [SHF_ALLOC]
+ ││╙ 0x00000166
+ │└─ 0x00000166
+ │┌─ 0x00000168 P PT_NOTE [PF_R]
+ ││╓ 0x00000168 S2 ".note.ABI-tag" SHT_NOTE [SHF_ALLOC]
+ ││╙ 0x00000187
+ ││╓ 0x00000188 S3 ".note.gnu.build-id" SHT_NOTE [SHF_ALLOC]
+ ││╙ 0x000001ab
+ │└─ 0x000001ab
+ │ ╓ 0x000001ac S4 ".gnu.hash" SHT_EXT 1879048182 [SHF_ALLOC]
+ │ ╙ 0x000001db
+ │ ╓ 0x000001dc S5 ".dynsym" SHT_DYNSYM [SHF_ALLOC]
+ │ ╙ 0x000002bb
+ │ ╓ 0x000002bc S6 ".dynstr" SHT_STRTAB [SHF_ALLOC]
+ │ ╙ 0x00000454
+ │ ╓ 0x00000456 S7 ".gnu.version" SHT_EXT 1879048191 [SHF_ALLOC]
+ │ ╙ 0x00000471
+ │ ╓ 0x00000474 S8 ".gnu.version_r" SHT_EXT 1879048190 [SHF_ALLOC]
+ │ ╙ 0x000004c3
+ │ ╓ 0x000004c4 S9 ".rel.dyn" SHT_REL [SHF_ALLOC]
+ │ ╙ 0x000004d3
+ │ ╓ 0x000004d4 S10 ".rel.plt" SHT_REL [SHF_ALLOC,SHF_EXT 64]
+ │ ╙ 0x0000050b
+ │ ╓ 0x0000050c S11 ".init" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+ │ ╙ 0x0000052e
+ │ ╓ 0x00000530 S12 ".plt" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+ │ ╙ 0x000005af
+ │ ╓ 0x000005b0 S13 ".plt.got" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+ │ ╙ 0x000005b7
+ │ ╓ 0x000005c0 S14 ".text" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+ │ ╙ 0x000007d1
+ │ ╓ 0x000007d4 S15 ".fini" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+ │ ╙ 0x000007e7
+ │ ╓ 0x000007e8 S16 ".rodata" SHT_PROGBITS [SHF_ALLOC]
+ │ ╙ 0x00000800
+ │┌─ 0x00000804 P PT_EXT 1685382480 [PF_R]
+ ││╓ 0x00000804 S17 ".eh_frame_hdr" SHT_PROGBITS [SHF_ALLOC]
+ ││╙ 0x0000083f
+ │└─ 0x0000083f
+ │ ╓ 0x00000840 S18 ".eh_frame" SHT_PROGBITS [SHF_ALLOC]
+ │ ╙ 0x00000933
+ └── 0x00000933
+┌─── 0x00000eec P PT_LOAD [PF_W,PF_R]
+│┌── 0x00000eec P PT_EXT 1685382482 [PF_R]
+││ ╓ 0x00000eec S19 ".init_array" SHT_EXT 14 [SHF_WRITE,SHF_ALLOC]
+││ ╙ 0x00000ef3
+││ ╓ 0x00000ef4 S20 ".fini_array" SHT_EXT 15 [SHF_WRITE,SHF_ALLOC]
+││ ╙ 0x00000ef7
+││ ╓ 0x00000ef8 S21 ".jcr" SHT_PROGBITS [SHF_WRITE,SHF_ALLOC]
+││ ╙ 0x00000efb
+││┌─ 0x00000efc P PT_DYNAMIC [PF_W,PF_R]
+│││╓ 0x00000efc S22 ".dynamic" SHT_DYNAMIC [SHF_WRITE,SHF_ALLOC]
+│││╙ 0x00000ffb
+││└─ 0x00000ffb
+││ ╓ 0x00000ffc S23 ".got" SHT_PROGBITS [SHF_WRITE,SHF_ALLOC]
+││ ╙ 0x00000fff
+│└── 0x00000fff
+│  ╓ 0x00001000 S24 ".got.plt" SHT_PROGBITS [SHF_WRITE,SHF_ALLOC]
+│  ╙ 0x00001027
+│  ╓ 0x00001028 S25 ".data" SHT_PROGBITS [SHF_WRITE,SHF_ALLOC]
+│  ╙ 0x0000102b
+└─── 0x0000102b
+   - 0x0000102c S26 ".bss" SHT_NOBITS [SHF_WRITE,SHF_ALLOC]
+   ╓ 0x0000102c S27 ".comment" SHT_PROGBITS [SHF_EXT 16,SHF_EXT 32]
+   ╙ 0x00001084
+   ╓ 0x00001088 S29 ".symtab" SHT_SYMTAB []
+   ╙ 0x00001567
+   ╓ 0x00001568 S30 ".strtab" SHT_STRTAB []
+   ╙ 0x000018e2
+   ╓ 0x000018e3 S28 ".shstrtab" SHT_STRTAB []
+   ╙ 0x000019ec
+   ┎ 0x000019f0 ST (31)
+   ┖ 0x00001ec7
diff --git a/tests/testdata/orig/bloated.strtable.golden b/tests/testdata/orig/bloated.strtable.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/bloated.strtable.golden
@@ -0,0 +1,29 @@
+<>
+<.bss>
+<.comment>
+<.data>
+<.dynamic>
+<.dynstr>
+<.dynsym>
+<.eh_frame>
+<.eh_frame_hdr>
+<.fini>
+<.fini_array>
+<.gnu.hash>
+<.gnu.version>
+<.gnu.version_r>
+<.got.plt>
+<.init>
+<.init_array>
+<.interp>
+<.jcr>
+<.note.ABI-tag>
+<.note.gnu.build-id>
+<.plt.got>
+<.rel.dyn>
+<.rel.plt>
+<.rodata>
+<.shstrtab>
+<.strtab>
+<.symtab>
+<.text>
diff --git a/tests/testdata/orig/tiny.elf.golden b/tests/testdata/orig/tiny.elf.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/tiny.elf.golden
@@ -0,0 +1,45 @@
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_X,PF_R]
+    VirtAddr:   0x0000000000400000
+    PhysAddr:   0x0000000000400000
+    AddMemSize: 0x0000000000000000
+    Align:      0x0000000000200000
+    Data:       
+        segment {
+            Type:       PT_NOTE
+            Flags:      [PF_R]
+            VirtAddr:   0x0000000000000000
+            PhysAddr:   0x0000000000000000
+            AddMemSize: 0x0000000000000000
+            Align:      0x0000000000000008
+            Data:       
+        }
+        header {
+            Class:      ELFCLASS64
+            Data:       ELFDATA2LSB
+            OSABI:      ELFOSABI_SYSV
+            ABIVersion: 0
+            Type:       ET_EXEC
+            Machine:    EM_X86_64
+            Entry:      0x00000000004000e0
+            Flags:      0x00000000
+        }
+        segment table
+        raw align {
+            Offset: 0x00000000000000e0
+            Align:  0x0000000000200000
+        }
+        section 1 ".text" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x00000000004000e0
+            AddrAlign: 0x0000000000000010
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      bb 00 00 00 00 b8 01 00 00 00 cd 80             # ............
+        }
+}
+string table section 2 ".shstrtab"
+section table
diff --git a/tests/testdata/orig/tiny.elf_header.golden b/tests/testdata/orig/tiny.elf_header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/tiny.elf_header.golden
@@ -0,0 +1,15 @@
+Class:      ELFCLASS64
+Data:       ELFDATA2LSB
+OSABI:      ELFOSABI_SYSV
+ABIVersion: 0
+Type:       ET_EXEC
+Machine:    EM_X86_64
+Entry:      0x00000000004000e0
+PhOff:      0x0000000000000040
+ShOff:      0x0000000000000100
+Flags:      0x00000000
+PhEntSize:  0x0038
+PhNum:      2
+ShEntSize:  0x0040
+ShNum:      3
+ShStrNdx:   SHN_EXT 2
diff --git a/tests/testdata/orig/tiny.header.golden b/tests/testdata/orig/tiny.header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/tiny.header.golden
@@ -0,0 +1,66 @@
+Header:   Class:      ELFCLASS64
+          Data:       ELFDATA2LSB
+          OSABI:      ELFOSABI_SYSV
+          ABIVersion: 0
+          Type:       ET_EXEC
+          Machine:    EM_X86_64
+          Entry:      0x00000000004000e0
+          PhOff:      0x0000000000000040
+          ShOff:      0x0000000000000100
+          Flags:      0x00000000
+          PhEntSize:  0x0038
+          PhNum:      2
+          ShEntSize:  0x0040
+          ShNum:      3
+          ShStrNdx:   SHN_EXT 2
+Sections: - N:         0
+            Name:      0
+            Type:      SHT_NULL
+            Flags:     0x0000000000000000
+            Addr:      0x0000000000000000
+            Offset:    0x0000000000000000
+            Size:      0x0000000000000000
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000000
+            EntSize:   0x0000000000000000
+          - N:         1
+            Name:      11
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000006
+            Addr:      0x00000000004000e0
+            Offset:    0x00000000000000e0
+            Size:      0x000000000000000c
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000010
+            EntSize:   0x0000000000000000
+          - N:         2
+            Name:      1
+            Type:      SHT_STRTAB
+            Flags:     0x0000000000000000
+            Addr:      0x0000000000000000
+            Offset:    0x00000000000000ec
+            Size:      0x0000000000000011
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+Segments: - N:        0
+            Type:     PT_LOAD
+            Flags:    [PF_X,PF_R]
+            Offset:   0x0000000000000000
+            VirtAddr: 0x0000000000400000
+            PhysAddr: 0x0000000000400000
+            FileSize: 0x00000000000000ec
+            MemSize:  0x00000000000000ec
+            Align:    0x0000000000200000
+          - N:        1
+            Type:     PT_NOTE
+            Flags:    [PF_R]
+            Offset:   0x0000000000000000
+            VirtAddr: 0x0000000000000000
+            PhysAddr: 0x0000000000000000
+            FileSize: 0x0000000000000000
+            MemSize:  0x0000000000000000
+            Align:    0x0000000000000008
diff --git a/tests/testdata/orig/tiny.layout.golden b/tests/testdata/orig/tiny.layout.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/tiny.layout.golden
@@ -0,0 +1,13 @@
+┌─ 0x00000000 P PT_LOAD [PF_X,PF_R]
+│- 0x00000000 P PT_NOTE [PF_R]
+│┎ 0x00000000 H
+│┖ 0x0000003f
+│┎ 0x00000040 PT (2)
+│┖ 0x000000af
+│╓ 0x000000e0 S1 ".text" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+│╙ 0x000000eb
+└─ 0x000000eb
+ ╓ 0x000000ec S2 ".shstrtab" SHT_STRTAB []
+ ╙ 0x000000fc
+ ┎ 0x00000100 ST (3)
+ ┖ 0x000001bf
diff --git a/tests/testdata/orig/tiny.strtable.golden b/tests/testdata/orig/tiny.strtable.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/tiny.strtable.golden
@@ -0,0 +1,3 @@
+<>
+<.shstrtab>
+<.text>
diff --git a/tests/testdata/orig/vdso.elf.golden b/tests/testdata/orig/vdso.elf.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/vdso.elf.golden
@@ -0,0 +1,271 @@
+segment {
+    Type:       PT_LOAD
+    Flags:      [PF_X,PF_R]
+    VirtAddr:   0x0000000000000000
+    PhysAddr:   0x0000000000000000
+    AddMemSize: 0x0000000000000000
+    Align:      0x0000000000001000
+    Data:       
+        header {
+            Class:      ELFCLASS64
+            Data:       ELFDATA2LSB
+            OSABI:      ELFOSABI_SYSV
+            ABIVersion: 0
+            Type:       ET_DYN
+            Machine:    EM_X86_64
+            Entry:      0x0000000000000970
+            Flags:      0x00000000
+        }
+        segment table
+        section 1 ".hash" {
+            Type:      SHT_HASH
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000120
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000004
+            Info:      0x00000000
+            Link:      0x00000003
+            Data:      03 00 00 00 0a 00 00 00 04 00 00 00 03 00 00 00 # ................
+                       06 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 # ................
+                       ...
+                       05 00 00 00 00 00 00 00 02 00 00 00 08 00 00 00 # ................
+                       total: 60
+        }
+        section 2 ".gnu.hash" {
+            Type:      SHT_EXT 1879048182
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000160
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000003
+            Data:      03 00 00 00 01 00 00 00 01 00 00 00 06 00 00 00 # ................
+                       81 34 30 01 46 65 00 81 01 00 00 00 05 00 00 00 # .40.Fe..........
+                       ...
+                       19 a3 43 6e 8a 2a c6 26 26 b0 62 65 6d 58 87 ff # ..Cn.*.&&.bemX..
+                       total: 72
+        }
+        symbol table section 3 ".dynsym" {
+            Type:      SHT_DYNSYM
+            Flags:     [SHF_ALLOC]
+            Addr:      0x00000000000001a8
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000018
+            Info:      0x00000001
+            Link:      0x00000004
+            Data:      
+                symbol "" {
+                    Bind:  STB_Local
+                    Type:  STT_NoType
+                    ShNdx: SHN_Undef
+                    Value: 0x0000000000000000
+                    Size:  0x0000000000000000
+                }
+                symbol "clock_gettime" {
+                    Bind:  STB_Weak
+                    Type:  STT_Func
+                    ShNdx: SHN_EXT 12
+                    Value: 0x0000000000000a30
+                    Size:  0x0000000000000305
+                }
+                ...
+                symbol "getcpu" {
+                    Bind:  STB_Weak
+                    Type:  STT_Func
+                    ShNdx: SHN_EXT 12
+                    Value: 0x0000000000000f30
+                    Size:  0x000000000000002a
+                }
+                total: 10
+        }
+        section 4 ".dynstr" {
+            Type:      SHT_STRTAB
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000298
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      00 5f 5f 76 64 73 6f 5f 63 6c 6f 63 6b 5f 67 65 # .__vdso_clock_ge
+                       74 74 69 6d 65 00 5f 5f 76 64 73 6f 5f 67 65 74 # ttime.__vdso_get
+                       ...
+                       2e 73 6f 2e 31 00 4c 49 4e 55 58 5f 32 2e 36 00 # .so.1.LINUX_2.6.
+                       total: 94
+        }
+        section 5 ".gnu.version" {
+            Type:      SHT_EXT 1879048191
+            Flags:     [SHF_ALLOC]
+            Addr:      0x00000000000002f6
+            AddrAlign: 0x0000000000000002
+            EntSize:   0x0000000000000002
+            Info:      0x00000000
+            Link:      0x00000003
+            Data:      00 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 # ................
+                       02 00 02 00                                     # ....
+        }
+        section 6 ".gnu.version_d" {
+            Type:      SHT_EXT 1879048189
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000310
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+            Info:      0x00000002
+            Link:      0x00000004
+            Data:      01 00 01 00 01 00 01 00 a1 bf ee 0d 14 00 00 00 # ................
+                       1c 00 00 00 44 00 00 00 00 00 00 00 01 00 00 00 # ....D...........
+                       ...
+                       14 00 00 00 00 00 00 00 54 00 00 00 00 00 00 00 # ........T.......
+                       total: 56
+        }
+        segment {
+            Type:       PT_DYNAMIC
+            Flags:      [PF_R]
+            VirtAddr:   0x0000000000000348
+            PhysAddr:   0x0000000000000348
+            AddMemSize: 0x0000000000000000
+            Align:      0x0000000000000008
+            Data:       
+                section 7 ".dynamic" {
+                    Type:      SHT_DYNAMIC
+                    Flags:     [SHF_WRITE,SHF_ALLOC]
+                    Addr:      0x0000000000000348
+                    AddrAlign: 0x0000000000000008
+                    EntSize:   0x0000000000000010
+                    Info:      0x00000000
+                    Link:      0x00000004
+                    Data:      0e 00 00 00 00 00 00 00 44 00 00 00 00 00 00 00 # ........D.......
+                               10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                               ...
+                               00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                               total: 288
+                }
+        }
+        section 8 ".rodata" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_WRITE,SHF_ALLOC]
+            Addr:      0x0000000000000468
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                       ...
+                       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # ................
+                       total: 832
+        }
+        segment {
+            Type:       PT_NOTE
+            Flags:      [PF_R]
+            VirtAddr:   0x00000000000007a8
+            PhysAddr:   0x00000000000007a8
+            AddMemSize: 0x0000000000000000
+            Align:      0x0000000000000004
+            Data:       
+                section 9 ".note" {
+                    Type:      SHT_NOTE
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x00000000000007a8
+                    AddrAlign: 0x0000000000000004
+                    EntSize:   0x0000000000000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      06 00 00 00 04 00 00 00 00 00 00 00 4c 69 6e 75 # ............Linu
+                               78 00 00 00 12 0f 04 00 04 00 00 00 14 00 00 00 # x...............
+                               ...
+                               22 98 2b 1f 74 78 1a 66 3b 95 c6 9b e4 82 95 89 # ".+.tx.f;.......
+                               total: 60
+                }
+        }
+        segment {
+            Type:       PT_EXT 1685382480
+            Flags:      [PF_R]
+            VirtAddr:   0x00000000000007e4
+            PhysAddr:   0x00000000000007e4
+            AddMemSize: 0x0000000000000000
+            Align:      0x0000000000000004
+            Data:       
+                section 10 ".eh_frame_hdr" {
+                    Type:      SHT_PROGBITS
+                    Flags:     [SHF_ALLOC]
+                    Addr:      0x00000000000007e4
+                    AddrAlign: 0x0000000000000004
+                    EntSize:   0x0000000000000000
+                    Info:      0x00000000
+                    Link:      0x00000000
+                    Data:      01 1b 03 3b 38 00 00 00 06 00 00 00 8c 01 00 00 # ...;8...........
+                               54 00 00 00 bc 01 00 00 7c 00 00 00 4c 02 00 00 # T.......|...L...
+                               ...
+                               2c 07 00 00 44 01 00 00 4c 07 00 00 64 01 00 00 # ,...D...L...d...
+                               total: 60
+                }
+        }
+        section 11 ".eh_frame" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000820
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01 # .........zR..x..
+                       1b 0c 07 08 90 01 00 00 24 00 00 00 1c 00 00 00 # ........$.......
+                       ...
+                       00 41 0e 10 86 02 48 0d 06 60 c6 0c 07 08 00 00 # .A....H..`......
+                       total: 328
+        }
+        section 12 ".text" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x0000000000000970
+            AddrAlign: 0x0000000000000010
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      55 48 89 e5 0f ae e8 0f 31 48 c1 e2 20 48 09 d0 # UH......1H.. H..
+                       48 8b 15 01 c7 ff ff 48 39 c2 77 02 5d c3 48 89 # H......H9.w.].H.
+                       ...
+                       89 17 48 85 f6 74 05 c1 e8 0c 89 06 31 c0 5d c3 # ..H..t......1.].
+                       total: 1514
+        }
+        section 13 ".altinstructions" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC]
+            Addr:      0x0000000000000f5a
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      1a fa ff ff 8b 00 00 00 71 00 03 03 03 0d fa ff # ........q.......
+                       ff 81 00 00 00 72 00 03 03 03 48 fa ff ff 77 00 # .....r....H...w.
+                       ...
+                       03 03 03 5d ff ff ff 27 00 00 00 16 02 04 04 01 # ...]...'........
+                       total: 143
+        }
+        section 14 ".altinstr_replacement" {
+            Type:      SHT_PROGBITS
+            Flags:     [SHF_ALLOC,SHF_EXECINSTR]
+            Addr:      0x0000000000000fe9
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+            Info:      0x00000000
+            Link:      0x00000000
+            Data:      0f ae f0 0f ae e8 0f ae f0 0f ae e8 0f ae f0 0f # ................
+                       ae e8 0f ae f0 0f ae e8 0f ae f0 0f ae e8 f3 0f # ................
+                       c7 f8                                           # ..
+        }
+}
+section 15 ".comment" {
+    Type:      SHT_PROGBITS
+    Flags:     [SHF_EXT 16,SHF_EXT 32]
+    Addr:      0x0000000000000000
+    AddrAlign: 0x0000000000000001
+    EntSize:   0x0000000000000001
+    Info:      0x00000000
+    Link:      0x00000000
+    Data:      47 43 43 3a 20 28 55 62 75 6e 74 75 20 37 2e 33 # GCC: (Ubuntu 7.3
+               2e 30 2d 31 36 75 62 75 6e 74 75 33 29 20 37 2e # .0-16ubuntu3) 7.
+               33 2e 30 00                                     # 3.0.
+}
+string table section 16 ".shstrtab"
+section table
diff --git a/tests/testdata/orig/vdso.elf_header.golden b/tests/testdata/orig/vdso.elf_header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/vdso.elf_header.golden
@@ -0,0 +1,15 @@
+Class:      ELFCLASS64
+Data:       ELFDATA2LSB
+OSABI:      ELFOSABI_SYSV
+ABIVersion: 0
+Type:       ET_DYN
+Machine:    EM_X86_64
+Entry:      0x0000000000000970
+PhOff:      0x0000000000000040
+ShOff:      0x00000000000010d8
+Flags:      0x00000000
+PhEntSize:  0x0038
+PhNum:      4
+ShEntSize:  0x0040
+ShNum:      17
+ShStrNdx:   SHN_EXT 16
diff --git a/tests/testdata/orig/vdso.header.golden b/tests/testdata/orig/vdso.header.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/vdso.header.golden
@@ -0,0 +1,238 @@
+Header:   Class:      ELFCLASS64
+          Data:       ELFDATA2LSB
+          OSABI:      ELFOSABI_SYSV
+          ABIVersion: 0
+          Type:       ET_DYN
+          Machine:    EM_X86_64
+          Entry:      0x0000000000000970
+          PhOff:      0x0000000000000040
+          ShOff:      0x00000000000010d8
+          Flags:      0x00000000
+          PhEntSize:  0x0038
+          PhNum:      4
+          ShEntSize:  0x0040
+          ShNum:      17
+          ShStrNdx:   SHN_EXT 16
+Sections: - N:         0
+            Name:      0
+            Type:      SHT_NULL
+            Flags:     0x0000000000000000
+            Addr:      0x0000000000000000
+            Offset:    0x0000000000000000
+            Size:      0x0000000000000000
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000000
+            EntSize:   0x0000000000000000
+          - N:         1
+            Name:      15
+            Type:      SHT_HASH
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000120
+            Offset:    0x0000000000000120
+            Size:      0x000000000000003c
+            Link:      3
+            Info:      0
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000004
+          - N:         2
+            Name:      11
+            Type:      SHT_EXT 1879048182
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000160
+            Offset:    0x0000000000000160
+            Size:      0x0000000000000048
+            Link:      3
+            Info:      0
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+          - N:         3
+            Name:      21
+            Type:      SHT_DYNSYM
+            Flags:     0x0000000000000002
+            Addr:      0x00000000000001a8
+            Offset:    0x00000000000001a8
+            Size:      0x00000000000000f0
+            Link:      4
+            Info:      1
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000018
+          - N:         4
+            Name:      29
+            Type:      SHT_STRTAB
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000298
+            Offset:    0x0000000000000298
+            Size:      0x000000000000005e
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+          - N:         5
+            Name:      37
+            Type:      SHT_EXT 1879048191
+            Flags:     0x0000000000000002
+            Addr:      0x00000000000002f6
+            Offset:    0x00000000000002f6
+            Size:      0x0000000000000014
+            Link:      3
+            Info:      0
+            AddrAlign: 0x0000000000000002
+            EntSize:   0x0000000000000002
+          - N:         6
+            Name:      50
+            Type:      SHT_EXT 1879048189
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000310
+            Offset:    0x0000000000000310
+            Size:      0x0000000000000038
+            Link:      4
+            Info:      2
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+          - N:         7
+            Name:      65
+            Type:      SHT_DYNAMIC
+            Flags:     0x0000000000000003
+            Addr:      0x0000000000000348
+            Offset:    0x0000000000000348
+            Size:      0x0000000000000120
+            Link:      4
+            Info:      0
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000010
+          - N:         8
+            Name:      74
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000003
+            Addr:      0x0000000000000468
+            Offset:    0x0000000000000468
+            Size:      0x0000000000000340
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+          - N:         9
+            Name:      82
+            Type:      SHT_NOTE
+            Flags:     0x0000000000000002
+            Addr:      0x00000000000007a8
+            Offset:    0x00000000000007a8
+            Size:      0x000000000000003c
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000004
+            EntSize:   0x0000000000000000
+          - N:         10
+            Name:      88
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000002
+            Addr:      0x00000000000007e4
+            Offset:    0x00000000000007e4
+            Size:      0x000000000000003c
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000004
+            EntSize:   0x0000000000000000
+          - N:         11
+            Name:      102
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000820
+            Offset:    0x0000000000000820
+            Size:      0x0000000000000148
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000008
+            EntSize:   0x0000000000000000
+          - N:         12
+            Name:      112
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000006
+            Addr:      0x0000000000000970
+            Offset:    0x0000000000000970
+            Size:      0x00000000000005ea
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000010
+            EntSize:   0x0000000000000000
+          - N:         13
+            Name:      118
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000002
+            Addr:      0x0000000000000f5a
+            Offset:    0x0000000000000f5a
+            Size:      0x000000000000008f
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+          - N:         14
+            Name:      135
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000006
+            Addr:      0x0000000000000fe9
+            Offset:    0x0000000000000fe9
+            Size:      0x0000000000000022
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+          - N:         15
+            Name:      157
+            Type:      SHT_PROGBITS
+            Flags:     0x0000000000000030
+            Addr:      0x0000000000000000
+            Offset:    0x000000000000100b
+            Size:      0x0000000000000024
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000001
+          - N:         16
+            Name:      1
+            Type:      SHT_STRTAB
+            Flags:     0x0000000000000000
+            Addr:      0x0000000000000000
+            Offset:    0x000000000000102f
+            Size:      0x00000000000000a6
+            Link:      0
+            Info:      0
+            AddrAlign: 0x0000000000000001
+            EntSize:   0x0000000000000000
+Segments: - N:        0
+            Type:     PT_LOAD
+            Flags:    [PF_X,PF_R]
+            Offset:   0x0000000000000000
+            VirtAddr: 0x0000000000000000
+            PhysAddr: 0x0000000000000000
+            FileSize: 0x000000000000100b
+            MemSize:  0x000000000000100b
+            Align:    0x0000000000001000
+          - N:        1
+            Type:     PT_DYNAMIC
+            Flags:    [PF_R]
+            Offset:   0x0000000000000348
+            VirtAddr: 0x0000000000000348
+            PhysAddr: 0x0000000000000348
+            FileSize: 0x0000000000000120
+            MemSize:  0x0000000000000120
+            Align:    0x0000000000000008
+          - N:        2
+            Type:     PT_NOTE
+            Flags:    [PF_R]
+            Offset:   0x00000000000007a8
+            VirtAddr: 0x00000000000007a8
+            PhysAddr: 0x00000000000007a8
+            FileSize: 0x000000000000003c
+            MemSize:  0x000000000000003c
+            Align:    0x0000000000000004
+          - N:        3
+            Type:     PT_EXT 1685382480
+            Flags:    [PF_R]
+            Offset:   0x00000000000007e4
+            VirtAddr: 0x00000000000007e4
+            PhysAddr: 0x00000000000007e4
+            FileSize: 0x000000000000003c
+            MemSize:  0x000000000000003c
+            Align:    0x0000000000000004
diff --git a/tests/testdata/orig/vdso.layout.golden b/tests/testdata/orig/vdso.layout.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/vdso.layout.golden
@@ -0,0 +1,46 @@
+┌── 0x00000000 P PT_LOAD [PF_X,PF_R]
+│ ┎ 0x00000000 H
+│ ┖ 0x0000003f
+│ ┎ 0x00000040 PT (4)
+│ ┖ 0x0000011f
+│ ╓ 0x00000120 S1 ".hash" SHT_HASH [SHF_ALLOC]
+│ ╙ 0x0000015b
+│ ╓ 0x00000160 S2 ".gnu.hash" SHT_EXT 1879048182 [SHF_ALLOC]
+│ ╙ 0x000001a7
+│ ╓ 0x000001a8 S3 ".dynsym" SHT_DYNSYM [SHF_ALLOC]
+│ ╙ 0x00000297
+│ ╓ 0x00000298 S4 ".dynstr" SHT_STRTAB [SHF_ALLOC]
+│ ╙ 0x000002f5
+│ ╓ 0x000002f6 S5 ".gnu.version" SHT_EXT 1879048191 [SHF_ALLOC]
+│ ╙ 0x00000309
+│ ╓ 0x00000310 S6 ".gnu.version_d" SHT_EXT 1879048189 [SHF_ALLOC]
+│ ╙ 0x00000347
+│┌─ 0x00000348 P PT_DYNAMIC [PF_R]
+││╓ 0x00000348 S7 ".dynamic" SHT_DYNAMIC [SHF_WRITE,SHF_ALLOC]
+││╙ 0x00000467
+│└─ 0x00000467
+│ ╓ 0x00000468 S8 ".rodata" SHT_PROGBITS [SHF_WRITE,SHF_ALLOC]
+│ ╙ 0x000007a7
+│┌─ 0x000007a8 P PT_NOTE [PF_R]
+││╓ 0x000007a8 S9 ".note" SHT_NOTE [SHF_ALLOC]
+││╙ 0x000007e3
+│└─ 0x000007e3
+│┌─ 0x000007e4 P PT_EXT 1685382480 [PF_R]
+││╓ 0x000007e4 S10 ".eh_frame_hdr" SHT_PROGBITS [SHF_ALLOC]
+││╙ 0x0000081f
+│└─ 0x0000081f
+│ ╓ 0x00000820 S11 ".eh_frame" SHT_PROGBITS [SHF_ALLOC]
+│ ╙ 0x00000967
+│ ╓ 0x00000970 S12 ".text" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+│ ╙ 0x00000f59
+│ ╓ 0x00000f5a S13 ".altinstructions" SHT_PROGBITS [SHF_ALLOC]
+│ ╙ 0x00000fe8
+│ ╓ 0x00000fe9 S14 ".altinstr_replacement" SHT_PROGBITS [SHF_ALLOC,SHF_EXECINSTR]
+│ ╙ 0x0000100a
+└── 0x0000100a
+  ╓ 0x0000100b S15 ".comment" SHT_PROGBITS [SHF_EXT 16,SHF_EXT 32]
+  ╙ 0x0000102e
+  ╓ 0x0000102f S16 ".shstrtab" SHT_STRTAB []
+  ╙ 0x000010d4
+  ┎ 0x000010d8 ST (17)
+  ┖ 0x00001517
diff --git a/tests/testdata/orig/vdso.strtable.golden b/tests/testdata/orig/vdso.strtable.golden
new file mode 100644
--- /dev/null
+++ b/tests/testdata/orig/vdso.strtable.golden
@@ -0,0 +1,16 @@
+<>
+<.altinstr_replacement>
+<.altinstructions>
+<.comment>
+<.dynamic>
+<.dynstr>
+<.dynsym>
+<.eh_frame>
+<.eh_frame_hdr>
+<.gnu.hash>
+<.gnu.version>
+<.gnu.version_d>
+<.note>
+<.rodata>
+<.shstrtab>
+<.text>
