{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
module Data.Macaw.Memory.ElfLoader.DynamicDependencies
( loadDynamicDependencies
, parseDynNeeded
, DynamicLoadingError(..)
) where
import qualified Control.Exception as X
import qualified Control.Monad.Catch as CMC
import qualified Data.ByteString as BS
import qualified Data.ByteString.UTF8 as UTF8
import qualified Data.ElfEdit as EE
import qualified Data.Set as Set
import qualified Data.Sequence as Seq
import qualified Data.Type.Equality as DTE
import qualified Prettyprinter as PP
import qualified System.Directory as SD
import qualified System.FilePath as SF
loadDynamicDependencies ::
forall w
. EE.ElfMachine
-> EE.ElfClass w
-> FilePath
-> EE.ElfHeaderInfo w
-> FilePath
-> IO [(EE.ElfHeaderInfo w, FilePath)]
loadDynamicDependencies :: forall (w :: Nat).
ElfMachine
-> ElfClass w
-> FilePath
-> ElfHeaderInfo w
-> FilePath
-> IO [(ElfHeaderInfo w, FilePath)]
loadDynamicDependencies ElfMachine
expectedHeaderMachine ElfClass w
expectedHeaderClass
FilePath
sharedObjectDir ElfHeaderInfo w
mainBinaryEHI FilePath
mainBinaryPath =
case ElfHeaderInfo w
-> FilePath -> Maybe (Either DynamicLoadingError [ByteString])
forall (w :: Nat).
ElfHeaderInfo w
-> FilePath -> Maybe (Either DynamicLoadingError [ByteString])
parseDynNeeded ElfHeaderInfo w
mainBinaryEHI FilePath
mainBinaryPath of
Maybe (Either DynamicLoadingError [ByteString])
Nothing -> [(ElfHeaderInfo w, FilePath)] -> IO [(ElfHeaderInfo w, FilePath)]
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure []
Just Either DynamicLoadingError [ByteString]
dynNeededs -> do
[ByteString]
dynNeededs' <- (DynamicLoadingError -> IO [ByteString])
-> ([ByteString] -> IO [ByteString])
-> Either DynamicLoadingError [ByteString]
-> IO [ByteString]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either DynamicLoadingError -> IO [ByteString]
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM [ByteString] -> IO [ByteString]
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Either DynamicLoadingError [ByteString]
dynNeededs
Set ByteString
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
go Set ByteString
forall a. Set a
Set.empty (Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)])
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
forall a b. (a -> b) -> a -> b
$ [ByteString] -> Seq ByteString
forall a. [a] -> Seq a
Seq.fromList [ByteString]
dynNeededs'
where
go ::
Set.Set BS.ByteString ->
Seq.Seq BS.ByteString ->
IO [(EE.ElfHeaderInfo w, FilePath)]
go :: Set ByteString
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
go Set ByteString
sosSeenSoFar Seq ByteString
dynQueue =
case Seq ByteString -> ViewL ByteString
forall a. Seq a -> ViewL a
Seq.viewl Seq ByteString
dynQueue of
ViewL ByteString
Seq.EmptyL -> [(ElfHeaderInfo w, FilePath)] -> IO [(ElfHeaderInfo w, FilePath)]
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure []
ByteString
dynNext Seq.:< Seq ByteString
dynRest
|
ByteString
dynNext ByteString -> Set ByteString -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set ByteString
sosSeenSoFar
-> Set ByteString
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
go Set ByteString
sosSeenSoFar Seq ByteString
dynRest
| Bool
otherwise
-> do let dynNextFP :: FilePath
dynNextFP = ByteString -> FilePath
UTF8.toString ByteString
dynNext
let fullPath :: FilePath
fullPath = FilePath
sharedObjectDir FilePath -> FilePath -> FilePath
SF.</> FilePath
dynNextFP
Bool
exists <- FilePath -> IO Bool
SD.doesFileExist FilePath
fullPath
if Bool
exists
then do
ByteString
soBytes <- FilePath -> IO ByteString
BS.readFile FilePath
fullPath
ElfHeaderInfo w
so <- FilePath -> ByteString -> IO (ElfHeaderInfo w)
loadSharedObject FilePath
dynNextFP ByteString
soBytes
case ElfHeaderInfo w
-> FilePath -> Maybe (Either DynamicLoadingError [ByteString])
forall (w :: Nat).
ElfHeaderInfo w
-> FilePath -> Maybe (Either DynamicLoadingError [ByteString])
parseDynNeeded ElfHeaderInfo w
so FilePath
dynNextFP of
Maybe (Either DynamicLoadingError [ByteString])
Nothing -> DynamicLoadingError -> IO [(ElfHeaderInfo w, FilePath)]
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM (DynamicLoadingError -> IO [(ElfHeaderInfo w, FilePath)])
-> DynamicLoadingError -> IO [(ElfHeaderInfo w, FilePath)]
forall a b. (a -> b) -> a -> b
$ FilePath -> DynamicLoadingError
ElfNonDynamicSharedLib FilePath
dynNextFP
Just Either DynamicLoadingError [ByteString]
dynNeededs -> do
[ByteString]
dynNeededs' <- (DynamicLoadingError -> IO [ByteString])
-> ([ByteString] -> IO [ByteString])
-> Either DynamicLoadingError [ByteString]
-> IO [ByteString]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either DynamicLoadingError -> IO [ByteString]
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM [ByteString] -> IO [ByteString]
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Either DynamicLoadingError [ByteString]
dynNeededs
[(ElfHeaderInfo w, FilePath)]
sos <- Set ByteString
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
go (ByteString -> Set ByteString -> Set ByteString
forall a. Ord a => a -> Set a -> Set a
Set.insert ByteString
dynNext Set ByteString
sosSeenSoFar)
(Seq ByteString
dynRest Seq ByteString -> Seq ByteString -> Seq ByteString
forall a. Semigroup a => a -> a -> a
<> [ByteString] -> Seq ByteString
forall a. [a] -> Seq a
Seq.fromList [ByteString]
dynNeededs')
[(ElfHeaderInfo w, FilePath)] -> IO [(ElfHeaderInfo w, FilePath)]
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ((ElfHeaderInfo w
so, FilePath
dynNextFP)(ElfHeaderInfo w, FilePath)
-> [(ElfHeaderInfo w, FilePath)] -> [(ElfHeaderInfo w, FilePath)]
forall a. a -> [a] -> [a]
:[(ElfHeaderInfo w, FilePath)]
sos)
else Set ByteString
-> Seq ByteString -> IO [(ElfHeaderInfo w, FilePath)]
go Set ByteString
sosSeenSoFar Seq ByteString
dynRest
loadSharedObject ::
FilePath ->
BS.ByteString ->
IO (EE.ElfHeaderInfo w)
loadSharedObject :: FilePath -> ByteString -> IO (ElfHeaderInfo w)
loadSharedObject FilePath
soName ByteString
soBytes =
case ByteString -> Either (ByteOffset, FilePath) (SomeElf ElfHeaderInfo)
EE.decodeElfHeaderInfo ByteString
soBytes of
Right (EE.SomeElf ElfHeaderInfo w
ehi) -> do
let hdr :: ElfHeader w
hdr = ElfHeaderInfo w -> ElfHeader w
forall (w :: Nat). ElfHeaderInfo w -> ElfHeader w
EE.header ElfHeaderInfo w
ehi
let actualHeaderClass :: ElfClass w
actualHeaderClass = ElfHeader w -> ElfClass w
forall (w :: Nat). ElfHeader w -> ElfClass w
EE.headerClass ElfHeader w
hdr
let actualHeaderMachine :: ElfMachine
actualHeaderMachine = ElfHeader w -> ElfMachine
forall (w :: Nat). ElfHeader w -> ElfMachine
EE.headerMachine ElfHeader w
hdr
if ElfMachine
actualHeaderMachine ElfMachine -> ElfMachine -> Bool
forall a. Eq a => a -> a -> Bool
== ElfMachine
expectedHeaderMachine
then
case ElfClass w -> ElfClass w -> Maybe (w :~: w)
forall (a :: Nat) (b :: Nat).
ElfClass a -> ElfClass b -> Maybe (a :~: b)
forall {k} (f :: k -> Type) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
DTE.testEquality ElfClass w
actualHeaderClass ElfClass w
expectedHeaderClass of
Just w :~: w
DTE.Refl -> ElfHeaderInfo w -> IO (ElfHeaderInfo w)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ElfHeaderInfo w
ElfHeaderInfo w
ehi
Maybe (w :~: w)
_ -> DynamicLoadingError -> IO (ElfHeaderInfo w)
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM (DynamicLoadingError -> IO (ElfHeaderInfo w))
-> DynamicLoadingError -> IO (ElfHeaderInfo w)
forall a b. (a -> b) -> a -> b
$ ElfClass w -> ElfClass w -> DynamicLoadingError
forall (w :: Nat) (w' :: Nat).
ElfClass w -> ElfClass w' -> DynamicLoadingError
SoMismatchedElfClass ElfClass w
actualHeaderClass
ElfClass w
expectedHeaderClass
else DynamicLoadingError -> IO (ElfHeaderInfo w)
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM (DynamicLoadingError -> IO (ElfHeaderInfo w))
-> DynamicLoadingError -> IO (ElfHeaderInfo w)
forall a b. (a -> b) -> a -> b
$ ElfMachine -> ElfMachine -> DynamicLoadingError
SoMismatchedElfMachine ElfMachine
actualHeaderMachine
ElfMachine
expectedHeaderMachine
Left (ByteOffset, FilePath)
_ -> DynamicLoadingError -> IO (ElfHeaderInfo w)
forall e a. (HasCallStack, Exception e) => e -> IO a
forall (m :: Type -> Type) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
CMC.throwM (DynamicLoadingError -> IO (ElfHeaderInfo w))
-> DynamicLoadingError -> IO (ElfHeaderInfo w)
forall a b. (a -> b) -> a -> b
$ FilePath -> DynamicLoadingError
NonElfBinaryFormat FilePath
soName
parseDynNeeded ::
EE.ElfHeaderInfo w ->
FilePath ->
Maybe (Either DynamicLoadingError [BS.ByteString])
parseDynNeeded :: forall (w :: Nat).
ElfHeaderInfo w
-> FilePath -> Maybe (Either DynamicLoadingError [ByteString])
parseDynNeeded ElfHeaderInfo w
elfHeaderInfo FilePath
elfFP = ElfClass w
-> (ElfWidthConstraints w =>
Maybe (Either DynamicLoadingError [ByteString]))
-> Maybe (Either DynamicLoadingError [ByteString])
forall (w :: Nat) a.
ElfClass w -> (ElfWidthConstraints w => a) -> a
EE.elfClassInstances ElfClass w
elfClass ((ElfWidthConstraints w =>
Maybe (Either DynamicLoadingError [ByteString]))
-> Maybe (Either DynamicLoadingError [ByteString]))
-> (ElfWidthConstraints w =>
Maybe (Either DynamicLoadingError [ByteString]))
-> Maybe (Either DynamicLoadingError [ByteString])
forall a b. (a -> b) -> a -> b
$
case (Phdr w -> Bool) -> [Phdr w] -> [Phdr w]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Phdr w
p -> Phdr w -> PhdrType
forall (w :: Nat). Phdr w -> PhdrType
EE.phdrSegmentType Phdr w
p PhdrType -> PhdrType -> Bool
forall a. Eq a => a -> a -> Bool
== PhdrType
EE.PT_DYNAMIC) [Phdr w]
elfPhdrs of
[Phdr w
dynPhdr] -> Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString])
forall a. a -> Maybe a
Just (Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString]))
-> Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString])
forall a b. (a -> b) -> a -> b
$
let dynContents :: ByteString
dynContents = FileRange (ElfWordType w) -> ByteString -> ByteString
forall w. Integral w => FileRange w -> ByteString -> ByteString
EE.slice (Phdr w -> FileRange (ElfWordType w)
forall (w :: Nat). Phdr w -> FileRange (ElfWordType w)
EE.phdrFileRange Phdr w
dynPhdr) ByteString
elfBytes
in case ElfData
-> ElfClass w
-> ByteString
-> Either DynamicError (DynamicSection w)
forall (w :: Nat).
ElfData
-> ElfClass w
-> ByteString
-> Either DynamicError (DynamicSection w)
EE.dynamicEntries (ElfHeader w -> ElfData
forall (w :: Nat). ElfHeader w -> ElfData
EE.headerData ElfHeader w
elfHeader) ElfClass w
elfClass ByteString
dynContents of
Left DynamicError
dynError ->
DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. a -> Either a b
Left (DynamicLoadingError -> Either DynamicLoadingError [ByteString])
-> DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. (a -> b) -> a -> b
$ FilePath -> DynamicError -> DynamicLoadingError
ElfDynamicParseError FilePath
elfFP DynamicError
dynError
Right DynamicSection w
dynSection -> do
case ByteString -> [Phdr w] -> Maybe (VirtAddrMap w)
forall (t :: Type -> Type) (w :: Nat).
(Foldable t, Integral (ElfWordType w)) =>
ByteString -> t (Phdr w) -> Maybe (VirtAddrMap w)
EE.virtAddrMap ByteString
elfBytes [Phdr w]
elfPhdrs of
Maybe (VirtAddrMap w)
Nothing -> do
DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. a -> Either a b
Left (DynamicLoadingError -> Either DynamicLoadingError [ByteString])
-> DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. (a -> b) -> a -> b
$ FilePath -> DynamicLoadingError
ElfVirtualAddressMapError FilePath
elfFP
Just VirtAddrMap w
phdrs ->
case DynamicSection w -> VirtAddrMap w -> Either FilePath [ByteString]
forall (w :: Nat).
DynamicSection w -> VirtAddrMap w -> Either FilePath [ByteString]
EE.dynNeeded DynamicSection w
dynSection VirtAddrMap w
phdrs of
Left FilePath
errMsg -> DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. a -> Either a b
Left (DynamicLoadingError -> Either DynamicLoadingError [ByteString])
-> DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> DynamicLoadingError
ElfDynamicNeededError FilePath
elfFP FilePath
errMsg
Right [ByteString]
deps -> [ByteString] -> Either DynamicLoadingError [ByteString]
forall a b. b -> Either a b
Right [ByteString]
deps
[] -> Maybe (Either DynamicLoadingError [ByteString])
forall a. Maybe a
Nothing
[Phdr w]
_ -> Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString])
forall a. a -> Maybe a
Just (Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString]))
-> Either DynamicLoadingError [ByteString]
-> Maybe (Either DynamicLoadingError [ByteString])
forall a b. (a -> b) -> a -> b
$ DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. a -> Either a b
Left (DynamicLoadingError -> Either DynamicLoadingError [ByteString])
-> DynamicLoadingError -> Either DynamicLoadingError [ByteString]
forall a b. (a -> b) -> a -> b
$ FilePath -> DynamicLoadingError
ElfMultipleDynamicHeaders FilePath
elfFP
where
elfHeader :: ElfHeader w
elfHeader = ElfHeaderInfo w -> ElfHeader w
forall (w :: Nat). ElfHeaderInfo w -> ElfHeader w
EE.header ElfHeaderInfo w
elfHeaderInfo
elfPhdrs :: [Phdr w]
elfPhdrs = ElfHeaderInfo w -> [Phdr w]
forall (w :: Nat). ElfHeaderInfo w -> [Phdr w]
EE.headerPhdrs ElfHeaderInfo w
elfHeaderInfo
elfBytes :: ByteString
elfBytes = ElfHeaderInfo w -> ByteString
forall (w :: Nat). ElfHeaderInfo w -> ByteString
EE.headerFileContents ElfHeaderInfo w
elfHeaderInfo
elfClass :: ElfClass w
elfClass = ElfHeader w -> ElfClass w
forall (w :: Nat). ElfHeader w -> ElfClass w
EE.headerClass ElfHeader w
elfHeader
data DynamicLoadingError where
NonElfBinaryFormat ::
FilePath
-> DynamicLoadingError
ElfDynamicParseError ::
FilePath
-> EE.DynamicError
-> DynamicLoadingError
ElfDynamicNeededError ::
FilePath
-> String
-> DynamicLoadingError
ElfVirtualAddressMapError ::
FilePath
-> DynamicLoadingError
::
FilePath
-> DynamicLoadingError
ElfNonDynamicSharedLib ::
FilePath
-> DynamicLoadingError
SoMismatchedElfMachine ::
EE.ElfMachine
-> EE.ElfMachine
-> DynamicLoadingError
SoMismatchedElfClass ::
EE.ElfClass w
-> EE.ElfClass w'
-> DynamicLoadingError
deriving instance Show DynamicLoadingError
instance X.Exception DynamicLoadingError where
displayException :: DynamicLoadingError -> FilePath
displayException = Doc Any -> FilePath
forall a. Show a => a -> FilePath
show (Doc Any -> FilePath)
-> (DynamicLoadingError -> Doc Any)
-> DynamicLoadingError
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynamicLoadingError -> Doc Any
forall a ann. Pretty a => a -> Doc ann
forall ann. DynamicLoadingError -> Doc ann
PP.pretty
instance PP.Pretty DynamicLoadingError where
pretty :: forall ann. DynamicLoadingError -> Doc ann
pretty DynamicLoadingError
e =
case DynamicLoadingError
e of
NonElfBinaryFormat FilePath
p ->
Doc ann
"Unsupported, non-ELF binary format for file" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+>
Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
PP.dquotes (FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
p)
ElfDynamicParseError FilePath
fp DynamicError
dynErr ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ DynamicError -> Doc ann
forall a ann. Show a => a -> Doc ann
PP.viaShow DynamicError
dynErr
, Doc ann
"In the file:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
fp
]
ElfVirtualAddressMapError FilePath
fp ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ Doc ann
"Could not construct virtual address map"
, Doc ann
"In the file:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
fp
]
ElfDynamicNeededError FilePath
fp FilePath
errMsg ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
errMsg
, Doc ann
"In the file:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
fp
]
ElfMultipleDynamicHeaders FilePath
fp ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ Doc ann
"Encountered multiple PT_DYNAMIC program headers"
, Doc ann
"In the file:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
fp
]
ElfNonDynamicSharedLib FilePath
fp ->
Doc ann
"The shared library" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> FilePath -> Doc ann
forall ann. FilePath -> Doc ann
forall a ann. Pretty a => a -> Doc ann
PP.pretty FilePath
fp Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+>
Doc ann
"is not dynamically linked"
SoMismatchedElfMachine ElfMachine
soMachine ElfMachine
mainMachine ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ Doc ann
"A shared object has a different ELF machine value than the main binary."
, Doc ann
"Shared object has machine " Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> ElfMachine -> Doc ann
forall a ann. Show a => a -> Doc ann
PP.viaShow ElfMachine
soMachine Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+>
Doc ann
"and main binary has machine " Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> ElfMachine -> Doc ann
forall a ann. Show a => a -> Doc ann
PP.viaShow ElfMachine
mainMachine
]
SoMismatchedElfClass ElfClass w
soClass ElfClass w'
mainClass ->
[Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
PP.vcat
[ Doc ann
"A shared object has a different ELF class value than the main binary."
, Doc ann
"Shared object has class " Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> ElfClass w -> Doc ann
forall a ann. Show a => a -> Doc ann
PP.viaShow ElfClass w
soClass Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+>
Doc ann
"and main binary has class " Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
PP.<+> ElfClass w' -> Doc ann
forall a ann. Show a => a -> Doc ann
PP.viaShow ElfClass w'
mainClass
]