packages feed

melf 1.0.2 → 1.1.0

raw patch · 9 files changed

+142/−105 lines, 9 filesdep +singletons-basedep +singletons-thdep ~basedep ~binarydep ~bytestring

Dependencies added: singletons-base, singletons-th

Dependency ranges changed: base, binary, bytestring, singletons, template-haskell

Files

ChangeLog.md view
@@ -1,3 +1,11 @@+1.1.0+=====++- Compile with GHC 8.8, 9.0, 9.2.+- Set up Github CI to build that.+- Fix bug that did not allow to specify length of `NOBITS` sections.+- Misc minor fixes+ 1.0.2 ===== 
README.md view
@@ -255,7 +255,7 @@  To create machine code that is used in the examples a pair of modules were created. The module-[`AsmAArch64`](https://github.com/aleksey-makarov/melf/blob/v1.0.2/examples/AsmAarch64.hs)+[`AsmAArch64`](https://github.com/aleksey-makarov/melf/blob/v1.0.2/examples/AsmAArch64.hs) provides a DSL embedded in Haskell. This DSL is a kind of assembler language for the AArch64 platform. It exports some primitives to generate machine instructions and organize machine code.@@ -267,7 +267,8 @@ ```  The idea was inspired by the article-([Stephen Diehl "Monads to Machine Code"](https://www.stephendiehl.com/posts/monads_machine_code.html)).+["Monads to Machine Code"](https://www.stephendiehl.com/posts/monads_machine_code.html)+by Stephen Diehl. Detailed description of this module is available in russian: [README_ru.md](https://github.com/aleksey-makarov/melf/blob/v1.0.2/examples/README_ru.md). 
examples/AsmAArch64.hs view
@@ -5,11 +5,18 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE CPP #-}++#if defined(MIN_VERSION_GLASGOW_HASKELL)+#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0)+{-# LANGUAGE StandaloneKindSignatures #-}+#endif+#endif+ {-# OPTIONS_GHC -Wno-unused-top-binds #-}  module AsmAArch64@@ -39,7 +46,6 @@ 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@@ -50,8 +56,7 @@  $(singletons [d| data RegisterWidth = X | W |]) -type Register :: RegisterWidth -> Type-newtype Register c = R Word32+newtype Register (c :: RegisterWidth) = 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)@@ -120,7 +125,7 @@ builderRepeatZero n = mconcat $ P.replicate n (word8 0)  b64 :: forall w . SingI w => Register w -> Word32-b64 _ = case sing @ w of+b64 _ = case sing @w of     SX -> 1     SW -> 0 
examples/README_ru.md view
@@ -175,8 +175,8 @@ на основании этой информации создаётся список элементов типа [`ElfXX`](https://hackage.haskell.org/package/melf-1.0.1/docs/Data-Elf.html#t:ElfXX), отображающий рекурсивную-структуру файла ELF.  Кроме восстановления структуры в процессе разбора, по номерам-секций восстанавливаются их имена.  В результате получается объект типа+структуру файла ELF.  Кроме восстановления структуры, в процессе разбора по индексам таблицы+строк восстанавливаются имена секций.  В результате получается объект типа [`Elf`](https://hackage.haskell.org/package/melf-1.0.1/docs/Data-Elf.html#t:Elf):  ``` Haskell@@ -392,7 +392,7 @@ -- | C6.2.10 ADR adr :: MonadState CodeState m =>                   Register 'X ->-                  Label -> m ()+                        Label -> m () ```  Для добавления данных в массив литералов используется функция `emitPool`:
melf.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           melf-version:        1.0.2+version:        1.1.0 synopsis:       An Elf parser description:    Parser for ELF object format category:       Data@@ -18,7 +18,7 @@ license-file:   LICENSE build-type:     Simple tested-with:-    GHC == 8.10.7+    GHC == 8.8.4, GHC == 8.10.7, GHC == 9.0.1, GHC == 9.2.1 extra-doc-files:     ChangeLog.md     README.md@@ -71,14 +71,18 @@       src   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints   build-depends:-      base >=4.6 && <5.0-    , binary >=0.8.8 && <0.9-    , bytestring >=0.10.12 && <0.11+      base >=4.13 && <5.0+    , binary >=0.8.7 && <0.9+    , bytestring >=0.10.10 && <0.12     , exceptions >=0.10.4 && <0.11     , mtl >=2.2.2 && <2.3     , prettyprinter >=1.7.0 && <1.8-    , singletons >=2.7 && <3-    , template-haskell ==2.16.*+    , singletons >=2.6 && <3.2+    , template-haskell >=2.15 && <2.19+  if impl(ghc >= 9.0)+    build-depends:+        singletons-base >=3.0 && <3.2+      , singletons-th >=3.0 && <3.2   default-language: Haskell2010  executable hobjdump@@ -89,7 +93,7 @@       app   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints -fno-warn-unused-do-bind -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base >=4.6 && <5.0+      base >=4.13 && <5.0     , binary     , bytestring     , melf@@ -105,7 +109,7 @@       app   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints -fno-warn-unused-do-bind -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base >=4.6 && <5.0+      base >=4.13 && <5.0     , binary     , bytestring     , exceptions@@ -126,7 +130,7 @@       examples   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints   build-depends:-      base >=4.6 && <5.0+      base >=4.13 && <5.0     , bytestring     , containers >=0.6.2.1 && <0.7     , exceptions@@ -138,6 +142,9 @@     , tasty-golden     , tasty-hunit     , unix >=2.7.2.2 && <2.8+  if impl(ghc >= 9.0)+    build-depends:+        singletons-th   default-language: Haskell2010  test-suite exceptions@@ -149,7 +156,7 @@       tests/exceptions   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints   build-depends:-      base >=4.6 && <5.0+      base >=4.13 && <5.0     , exceptions     , melf     , tasty@@ -165,7 +172,7 @@       tests   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-redundant-constraints   build-depends:-      base >=4.6 && <5.0+      base >=4.13 && <5.0     , binary     , bytestring     , directory >=1.3.6 && <1.4
src/Data/Elf/Headers.hs view
@@ -22,13 +22,20 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE CPP #-}++#if defined(MIN_VERSION_GLASGOW_HASKELL)+#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0)+{-# LANGUAGE StandaloneKindSignatures #-}+#endif+#endif+ {-# OPTIONS_GHC -Wno-unused-top-binds #-}  module Data.Elf.Headers (@@ -83,29 +90,28 @@      ) where --- import Control.Lens hiding (at)--- import Control.Arrow import Control.Monad import Control.Monad.Catch--- import Control.Monad.State hiding (get, put)--- import qualified Control.Monad.State as S import Data.Binary import Data.Binary.Get import Data.Binary.Put import Data.Bits import Data.ByteString       as BS import Data.ByteString.Lazy  as BSL--- import Data.ByteString.Char8 as BSC import Data.Data (Data)-import Data.Kind--- import Data.Kind import qualified Data.List as L import Data.Singletons.Sigma import Data.Singletons.TH import Data.Typeable (Typeable)--- import Numeric.Interval as I--- import Numeric.Interval.NonEmpty as INE +#if defined(MIN_VERSION_GLASGOW_HASKELL)+#if MIN_VERSION_GLASGOW_HASKELL(9,0,0,0)+import Data.Eq.Singletons+import Text.Show.Singletons+import Data.Bool.Singletons+#endif+#endif+ import Control.Exception.ChainedException import Data.BList import Data.Endian@@ -203,7 +209,6 @@  -- | @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)@@ -221,7 +226,7 @@       , FiniteBits (WordXX c)       , Binary (Be (WordXX c))       , Binary (Le (WordXX c))-      ) => IsElfClass c where+      ) => IsElfClass (c :: ElfClass) where     type WordXX c = r | r -> c  instance IsElfClass 'ELFCLASS32 where@@ -235,7 +240,6 @@ --------------------------------------------------------------------------  -- | Parsed ELF header-type HeaderXX :: ElfClass -> Type data HeaderXX c =     HeaderXX         { hData       :: ElfData    -- ^ Data encoding (big- or little-endian)@@ -370,7 +374,7 @@ --------------------------------------------------------------------------  -- | Parsed ELF section table entry-data SectionXX (c :: ElfClass) =+data SectionXX c =     SectionXX         { sName      :: Word32         -- ^ Section name         , sType      :: ElfSectionType -- ^ Section type@@ -418,19 +422,19 @@     putE sEntSize  instance forall (a :: ElfClass) . SingI a => Binary (Be (SectionXX a)) where-    put = withElfClass (sing @ a) (putSection putBe) . fromBe-    get = Be <$> withElfClass (sing @ a) (getSection getBe)+    put = withElfClass (sing @a) (putSection putBe) . fromBe+    get = Be <$> withElfClass (sing @a) (getSection getBe)  instance forall (a :: ElfClass) . SingI a => Binary (Le (SectionXX a)) where-    put = withElfClass (sing @ a) (putSection putLe) . fromLe-    get = Le <$> withElfClass (sing @ a) (getSection getLe)+    put = withElfClass (sing @a) (putSection putLe) . fromLe+    get = Le <$> withElfClass (sing @a) (getSection getLe)  -------------------------------------------------------------------------- -- Segment --------------------------------------------------------------------------  -- | Parsed ELF segment table entry-data SegmentXX (c :: ElfClass) =+data SegmentXX c =     SegmentXX         { pType     :: ElfSegmentType -- ^ Type of segment         , pFlags    :: ElfSegmentFlag -- ^ Segment attributes@@ -514,7 +518,7 @@ sectionIsSymbolTable sType  = sType `L.elem` [SHT_SYMTAB, SHT_DYNSYM]  -- | Parsed ELF symbol table entry-data SymbolXX (c :: ElfClass) =+data SymbolXX c =     SymbolXX         { stName  :: Word32          -- ^ Symbol name         , stInfo  :: Word8           -- ^ Type and Binding attributes@@ -582,7 +586,7 @@ --------------------------------------------------------------------------  -- | Parsed relocation table entry (@ElfXX_Rela@)-data RelaXX (c :: ElfClass) =+data RelaXX c =     RelaXX         { relaOffset :: WordXX c -- ^ Address of reference         , relaSym    :: Word32   -- ^ Symbol table index@@ -612,7 +616,7 @@     (forall b . (Binary (Le b), Binary (Be b)) => Get b) -> Get (RelaXX c) getRelocationTableAEntry getE = do     relaOffset <- getE-    (relaSym, relaType) <- case sing @ c of+    (relaSym, relaType) <- case sing @c of         SELFCLASS64 -> (\x -> (relaSym64 x, relaType64 x)) <$> getE         SELFCLASS32 -> (\x -> (relaSym32 x, relaType32 x)) <$> getE     relaAddend <- getE@@ -623,22 +627,22 @@                                   RelaXX c -> Put putRelocationTableAEntry putE (RelaXX{..}) = do     putE relaOffset-    (case sing @ c of+    (case sing @c of         SELFCLASS64 -> putE $ relaInfo64 relaSym relaType         SELFCLASS32 -> putE $ relaInfo32 relaSym relaType) :: Put     putE relaAddend  instance forall (a :: ElfClass) . SingI a => Binary (Be (RelaXX a)) where-    put = withElfClass (sing @ a) (putRelocationTableAEntry putBe) . fromBe-    get = Be <$> withElfClass (sing @ a) (getRelocationTableAEntry getBe)+    put = withElfClass (sing @a) (putRelocationTableAEntry putBe) . fromBe+    get = Be <$> withElfClass (sing @a) (getRelocationTableAEntry getBe)  instance forall (a :: ElfClass) . SingI a => Binary (Le (RelaXX a)) where-    put = withElfClass (sing @ a) (putRelocationTableAEntry putLe) . fromLe-    get = Le <$> withElfClass (sing @ a) (getRelocationTableAEntry getLe)+    put = withElfClass (sing @a) (putRelocationTableAEntry putLe) . fromLe+    get = Le <$> withElfClass (sing @a) (getRelocationTableAEntry getLe)  -- | Size of @RelaXX a@ in bytes. relocationTableAEntrySize :: forall a . IsElfClass a => WordXX a-relocationTableAEntrySize = fromIntegral $ BSL.length $ encode $ Le $ RelaXX @ a 0 0 0 0+relocationTableAEntrySize = fromIntegral $ BSL.length $ encode $ Le $ RelaXX @a 0 0 0 0  -------------------------------------------------------------------------- -- parseHeaders
src/Data/Elf/PrettyPrint.hs view
@@ -365,6 +365,7 @@             return $  printWord64 relaOffset                   <+> printWord64 relaAddend                   <+> viaShow (ElfRelocationType_AARCH64 relaType)+                  <+> viaShow relaSym                   <+> printElfSymbolTableEntryLine symbolTableEntry          split xs = if full then xs else@@ -405,32 +406,38 @@                 , ("Entry",      printWordXX ehEntry  ) -- WordXX c                 , ("Flags",      printWord32 ehFlags  ) -- Word32                 ]-        printElf'' s@ElfSection{ esData = (ElfSectionData bs), ..} = do-            (sectionName, dataDoc) <- if sectionIsSymbolTable esType-                then do-                    stes <- parseSymbolTable hData s elfs-                    return ("symbol table section", if null stes then "" else line <> indent 4 (printElfSymbolTable full stes))-                else if hMachine == EM_AARCH64-                        && hData == ELFDATA2LSB-                       && esType == SHT_RELA-                    && esEntSize == withElfClass classS relocationTableAEntrySize then-                        case classS of-                            SELFCLASS64 -> ("section", ) <$> printRelocationTableA_AARCH64 full esLink elfs bs-                            SELFCLASS32 -> $chainedError "invalid ELF: EM_AARCH64 and ELFCLASS32"-                else-                    return ("section", printData full bs)-            return $ formatPairsBlock (sectionName <+> viaShow (fromIntegral esN :: Word) <+> dquotes (pretty esName))-                [ ("Type",       viaShow esType          )-                , ("Flags",      viaShow $ splitBits esFlags )-                , ("Addr",       printWordXX esAddr      )-                , ("AddrAlign",  printWordXX esAddrAlign )-                , ("EntSize",    printWordXX esEntSize   )-                , ("Info",       printWord32 esInfo      )-                , ("Link",       printWord32 esLink      )-                , ("Data",       dataDoc )-                ]-        printElf'' ElfSection{ esData = ElfSectionDataStringTable, ..} =-            return $ "string table section" <+> viaShow (fromIntegral esN :: Word) <+> dquotes (pretty esName)+        printElf'' s@ElfSection{ ..} =+            let+                printSection' sectionTitle dataDoc = formatPairsBlock (sectionTitle <+> viaShow (fromIntegral esN :: Word) <+> dquotes (pretty esName))+                    [ ("Type",       viaShow esType          )+                    , ("Flags",      viaShow $ splitBits esFlags )+                    , ("Addr",       printWordXX esAddr      )+                    , ("AddrAlign",  printWordXX esAddrAlign )+                    , ("EntSize",    printWordXX esEntSize   )+                    , ("Info",       printWord32 esInfo      )+                    , ("Link",       printWord32 esLink      )+                    , ("Data",       dataDoc )+                    ]+            in+                case esData of+                    ElfSectionDataNoBits { .. } ->+                        return $ printSection' "section" ("NoBits:" <+> viaShow esdSize)+                    ElfSectionDataStringTable ->+                        return $ "string table section" <+> viaShow (fromIntegral esN :: Word) <+> dquotes (pretty esName)+                    ElfSectionData bs ->+                        if sectionIsSymbolTable esType+                            then do+                                stes <- parseSymbolTable hData s elfs+                                return $ printSection' "symbol table section" $ if null stes then "" else line <> indent 4 (printElfSymbolTable full stes)+                            else if hMachine == EM_AARCH64+                                    && hData == ELFDATA2LSB+                                && esType == SHT_RELA+                                && esEntSize == withElfClass classS relocationTableAEntrySize then+                                    case classS of+                                        SELFCLASS64 -> printSection' "section" <$> printRelocationTableA_AARCH64 full esLink elfs bs+                                        SELFCLASS32 -> $chainedError "invalid ELF: EM_AARCH64 and ELFCLASS32"+                            else+                                return $ printSection' "section" $ printData full bs         printElf'' ElfSegment{..} = do             dataDoc <- if null epData                 then return ""
src/Data/Internal/Elf.hs view
@@ -11,7 +11,6 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilyDependencies #-}@@ -29,21 +28,17 @@ import Control.Monad import Control.Monad.Catch import Control.Monad.State as MS--- import Data.Bifunctor import Data.Binary import Data.Bits as Bin import Data.ByteString.Lazy.Char8 as BSL8 import Data.ByteString.Lazy as BSL--- import Data.Either import Data.Foldable import Data.Int--- import Data.Kind import qualified Data.List as L import Data.Maybe import Data.Monoid import Data.Singletons import Data.Singletons.Sigma--- import Data.Word  -- import System.IO.Unsafe @@ -65,7 +60,7 @@ -- | @RBuilder@ is an intermediate internal data type that is used by parser. -- It contains information about layout of the ELF file that can be used -- by `Data.Elf.PrettyPrint.printLayout`-data RBuilder (c :: ElfClass)+data RBuilder c     = RBuilderHeader         { rbhHeader :: HeaderXX c         }@@ -289,6 +284,8 @@     in         addRBuilders' addRBuilderNonEmpty nonEmptyRBs [] >>= addRBuilders' addRBuilderEmpty emptyRBs +-- FIXME: Use validity (https://hackage.haskell.org/package/validity) for constraints on the Elf type (???)+ -- | `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]@@ -299,12 +296,17 @@ -- | 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+data ElfSectionData c+    = ElfSectionData                -- ^ Regular section data+        { esdData :: BSL.ByteString -- ^ The content of the section+        }     | ElfSectionDataStringTable     -- ^ Section data will be generated from section names+    | ElfSectionDataNoBits          -- ^ SHT_NOBITS uninitialized section data: section has size but no content+        { esdSize :: WordXX c       -- ^ Size of the section+        }  -- | The type of node that defines Elf structure.-data ElfXX (c :: ElfClass)+data ElfXX c     = ElfHeader         { ehData       :: ElfData    -- ^ Data encoding (big- or little-endian)         , ehOSABI      :: ElfOSABI   -- ^ OS/ABI identification@@ -326,7 +328,7 @@         , esN         :: ElfSectionIndex -- ^ Section number         , esInfo      :: Word32         -- ^ Miscellaneous information         , esLink      :: Word32         -- ^ Link to other section-        , esData      :: ElfSectionData -- ^ The content of the section+        , esData      :: ElfSectionData c -- ^ The content of the section         }     | ElfSegment         { epType       :: ElfSegmentType -- ^ Type of segment@@ -576,13 +578,12 @@                 , esN         = rbsN                 , esInfo      = sInfo                 , esLink      = sLink-                , esData      = if rbsN == hShStrNdx-                    then-                        ElfSectionDataStringTable-                    else-                        ElfSectionData if I.empty $ sectionInterval s-                            then BSL.empty-                            else getSectionData bs s+                , esData      =+                    if rbsN == hShStrNdx+                        then ElfSectionDataStringTable+                        else if sType == SHT_NOBITS+                            then ElfSectionDataNoBits sSize+                            else ElfSectionData $ getSectionData bs s                 }         rBuilderToElf RBuilderSegment{ rbpHeader = SegmentXX{..}, ..} = do             d <- mapM rBuilderToElf rbpData@@ -622,7 +623,7 @@     | WBuilderDataSectionTable     | WBuilderDataSegmentTable -data WBuilderState (a :: ElfClass) =+data WBuilderState a =     WBuilderState         { wbsSections         :: [(ElfSectionIndex, SectionXX a)]         , wbsSegmentsReversed :: [SegmentXX a]@@ -758,14 +759,15 @@         alignWord :: MonadThrow n => WBuilderState a -> n (WBuilderState a)         alignWord = align 0 $ wordSize $ fromSing $ sing @a -        dataIsEmpty :: ElfSectionData -> Bool+        dataIsEmpty :: ElfSectionData c -> Bool         dataIsEmpty (ElfSectionData bs)       = BSL.null bs         dataIsEmpty ElfSectionDataStringTable = BSL.null stringTable+        dataIsEmpty (ElfSectionDataNoBits _)  = True          lastSectionIsEmpty :: [ElfXX a] -> Bool         lastSectionIsEmpty [] = False         lastSectionIsEmpty l = case L.last l of-            ElfSection{..} -> esType == SHT_NOBITS || dataIsEmpty esData+            ElfSection{..} -> dataIsEmpty esData             _ -> False          elf2WBuilder' :: MonadThrow n => ElfXX a -> WBuilderState a -> n (WBuilderState a)@@ -792,15 +794,18 @@                 , ..                 }         elf2WBuilder' ElfSection{esFlags = ElfSectionFlag f, ..} s = do-            when (f .&. fromIntegral (complement (maxBound @ (WordXX a))) /= 0)+            when (f .&. fromIntegral (complement (maxBound @(WordXX a))) /= 0)                 ($chainedError $ "section flags at section " ++ show esN ++ "don't fit")-            WBuilderState{..} <- if esType == SHT_NOBITS+            -- I don't see any sense in aligning NOBITS sections+            -- still gcc does it for .o files+            WBuilderState{..} <- if esType == SHT_NOBITS && (ehType header') /= ET_REL                 then return s                 else align 0 esAddrAlign s             let-                (d, shStrNdx) = case esData of-                    ElfSectionData bs -> (bs, wbsShStrNdx)-                    ElfSectionDataStringTable -> (stringTable, esN)+                (d, shStrNdx, sz) = case esData of+                    ElfSectionData { .. } -> (esdData, wbsShStrNdx, fromIntegral $ BSL.length esdData)+                    ElfSectionDataStringTable -> (stringTable, esN, fromIntegral $ BSL.length stringTable)+                    ElfSectionDataNoBits { .. } -> (BSL.empty, wbsShStrNdx, esdSize)                 (n, ns) = case wbsNameIndexes of                     n' : ns' -> (n', ns')                     _ -> error "internal error: different number of sections in two iterations"@@ -809,7 +814,7 @@                 sFlags = fromIntegral f                 sAddr = esAddr                         -- WXX c                 sOffset = wbsOffset                    -- WXX c-                sSize = fromIntegral $ BSL.length d    -- WXX c+                sSize = sz                             -- WXX c                 sLink = esLink                         -- Word32                 sInfo = esInfo                         -- Word32                 sAddrAlign = esAddrAlign               -- WXX c@@ -898,7 +903,7 @@                                 hShStrNdx   = wbsShStrNdx                                  h :: Header-                                h = sing @ a :&: HeaderXX{..}+                                h = sing @a :&: HeaderXX{..}                             in                                 encode h                         _ -> error "this should be ElfHeader" -- FIXME@@ -923,7 +928,7 @@ -- FIXME: move this to a separate file  -- | Parsed ELF symbol table entry. NB: This is work in progress-data ElfSymbolXX (c :: ElfClass) =+data ElfSymbolXX c =     ElfSymbolXX         { steName  :: String           -- ^ Symbol name (NB: String, not string index)         , steBind  :: ElfSymbolBinding -- ^ Symbol binding attributes
tests/testdata/orig/bloated.elf.golden view
@@ -416,7 +416,7 @@     EntSize:   0x00000000     Info:      0x00000000     Link:      0x00000000-    Data:      +    Data:      NoBits: 144 } section 27 ".comment" {     Type:      SHT_PROGBITS