From 5531161f64f92e13ae04cfe0de0042754ae050cd Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Wed, 1 Nov 2023 20:19:34 -0400 Subject: [PATCH] Add PPC{32,64} relocation types Fixes #35. --- elf-edit.cabal | 4 +- src/Data/ElfEdit/Prim.hs | 6 + src/Data/ElfEdit/Relocations/PPC32.hs | 279 ++++++++++++ src/Data/ElfEdit/Relocations/PPC64.hs | 615 ++++++++++++++++++++++++++ tests/Makefile | 8 +- tests/Test.hs | 112 +++++ tests/ppc32-relocs.c | 3 + tests/ppc32-relocs.elf | Bin 0 -> 68020 bytes tests/ppc64-relocs.c | 3 + tests/ppc64-relocs.elf | Bin 0 -> 68848 bytes 10 files changed, 1028 insertions(+), 2 deletions(-) create mode 100644 src/Data/ElfEdit/Relocations/PPC32.hs create mode 100644 src/Data/ElfEdit/Relocations/PPC64.hs create mode 100644 tests/ppc32-relocs.c create mode 100755 tests/ppc32-relocs.elf create mode 100644 tests/ppc64-relocs.c create mode 100755 tests/ppc64-relocs.elf diff --git a/elf-edit.cabal b/elf-edit.cabal index 9ad2f2a..dd24976 100644 --- a/elf-edit.cabal +++ b/elf-edit.cabal @@ -49,6 +49,8 @@ library Data.ElfEdit.Relocations.ARM32 Data.ElfEdit.Relocations.AArch64 Data.ElfEdit.Relocations.I386 + Data.ElfEdit.Relocations.PPC32 + Data.ElfEdit.Relocations.PPC64 Data.ElfEdit.Relocations.X86_64 Data.ElfEdit.Prim.Ehdr Data.ElfEdit.Prim.File @@ -72,4 +74,4 @@ test-suite test-elf tasty, tasty-hunit >= 0.10, tasty-quickcheck, - vector \ No newline at end of file + vector diff --git a/src/Data/ElfEdit/Prim.hs b/src/Data/ElfEdit/Prim.hs index 4d5ea5b..485581d 100644 --- a/src/Data/ElfEdit/Prim.hs +++ b/src/Data/ElfEdit/Prim.hs @@ -24,6 +24,10 @@ module Data.ElfEdit.Prim , module Data.ElfEdit.Relocations.ARM32 -- ** ARM64 relocations , module Data.ElfEdit.Relocations.AArch64 + -- ** PPC32 relocations + , module Data.ElfEdit.Relocations.PPC32 + -- ** PPC64 relocations + , module Data.ElfEdit.Relocations.PPC64 -- ** Android-specific , module Data.ElfEdit.Relocations.Android ) where @@ -41,4 +45,6 @@ import Data.ElfEdit.Relocations.ARM32 import Data.ElfEdit.Relocations.Android import Data.ElfEdit.Relocations.Common import Data.ElfEdit.Relocations.I386 +import Data.ElfEdit.Relocations.PPC32 +import Data.ElfEdit.Relocations.PPC64 import Data.ElfEdit.Relocations.X86_64 diff --git a/src/Data/ElfEdit/Relocations/PPC32.hs b/src/Data/ElfEdit/Relocations/PPC32.hs new file mode 100644 index 0000000..762c7e9 --- /dev/null +++ b/src/Data/ElfEdit/Relocations/PPC32.hs @@ -0,0 +1,279 @@ +{- +Copyright : (c) Galois, Inc 2023 +Maintainer : Ryan Scott + +PPC32 relocation types. The list of relocation types is taken from Section 4-14 +(Relocation) of . +-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE TypeFamilies #-} +module Data.ElfEdit.Relocations.PPC32 + ( PPC32_RelocationType(..) + , pattern R_PPC_NONE + , pattern R_PPC_ADDR32 + , pattern R_PPC_ADDR24 + , pattern R_PPC_ADDR16 + , pattern R_PPC_ADDR16_LO + , pattern R_PPC_ADDR16_HI + , pattern R_PPC_ADDR16_HA + , pattern R_PPC_ADDR14 + , pattern R_PPC_ADDR14_BRTAKEN + , pattern R_PPC_ADDR14_BRNTAKEN + , pattern R_PPC_REL24 + , pattern R_PPC_REL14 + , pattern R_PPC_REL14_BRTAKEN + , pattern R_PPC_REL14_BRNTAKEN + , pattern R_PPC_GOT16 + , pattern R_PPC_GOT16_LO + , pattern R_PPC_GOT16_HI + , pattern R_PPC_GOT16_HA + , pattern R_PPC_PLTREL24 + , pattern R_PPC_COPY + , pattern R_PPC_GLOB_DAT + , pattern R_PPC_JMP_SLOT + , pattern R_PPC_RELATIVE + , pattern R_PPC_LOCAL24PC + , pattern R_PPC_UADDR32 + , pattern R_PPC_UADDR16 + , pattern R_PPC_REL32 + , pattern R_PPC_PLT32 + , pattern R_PPC_PLTREL32 + , pattern R_PPC_PLT16_LO + , pattern R_PPL_PLT16_HI + , pattern R_PPC_PLT16_HA + , pattern R_PPC_SDAREL16 + , pattern R_PPC_SECTOFF + , pattern R_PPC_SECTOFF_LO + , pattern R_PPC_SECTOFF_HI + , pattern R_PPC_SECTOFF_HA + , pattern R_PPC_ADDR30 + , ppc32_RelocationTypes + ) where + +import qualified Data.Map.Strict as Map +import Data.Word + +import Data.ElfEdit.Prim.Ehdr (ElfClass(..)) +import Data.ElfEdit.Relocations.Common +import Data.ElfEdit.Utils (ppHex) + +------------------------------------------------------------------------ +-- PPC32_RelocationType + +-- | Relocation types for 32-bit PPC code. +newtype PPC32_RelocationType = PPC32_RelocationType { fromPPC32_RelocationType :: Word32 } + deriving (Eq,Ord) + +-- These values are derived from Table 4-8 (Relocation Types) of +-- http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf. + +pattern R_PPC_NONE :: PPC32_RelocationType +pattern R_PPC_NONE = PPC32_RelocationType 0 -- none + +pattern R_PPC_ADDR32 :: PPC32_RelocationType +pattern R_PPC_ADDR32 = PPC32_RelocationType 1 -- S + A + +pattern R_PPC_ADDR24 :: PPC32_RelocationType +pattern R_PPC_ADDR24 = PPC32_RelocationType 2 -- (S + A) >> 2 + +pattern R_PPC_ADDR16 :: PPC32_RelocationType +pattern R_PPC_ADDR16 = PPC32_RelocationType 3 -- S + A + +pattern R_PPC_ADDR16_LO :: PPC32_RelocationType +pattern R_PPC_ADDR16_LO = PPC32_RelocationType 4 -- #lo(S + A) + +pattern R_PPC_ADDR16_HI :: PPC32_RelocationType +pattern R_PPC_ADDR16_HI = PPC32_RelocationType 5 -- #hi(S + A) + +pattern R_PPC_ADDR16_HA :: PPC32_RelocationType +pattern R_PPC_ADDR16_HA = PPC32_RelocationType 6 -- #ha(S + A) + +pattern R_PPC_ADDR14 :: PPC32_RelocationType +pattern R_PPC_ADDR14 = PPC32_RelocationType 7 -- (S + A) >> 2 + +pattern R_PPC_ADDR14_BRTAKEN :: PPC32_RelocationType +pattern R_PPC_ADDR14_BRTAKEN = PPC32_RelocationType 8 -- (S + A) >> 2 + +pattern R_PPC_ADDR14_BRNTAKEN :: PPC32_RelocationType +pattern R_PPC_ADDR14_BRNTAKEN = PPC32_RelocationType 9 -- (S + A) >> 2 + +pattern R_PPC_REL24 :: PPC32_RelocationType +pattern R_PPC_REL24 = PPC32_RelocationType 10 -- (S + A - P) >> 2 + +pattern R_PPC_REL14 :: PPC32_RelocationType +pattern R_PPC_REL14 = PPC32_RelocationType 11 -- (S + A - P) >> 2 + +pattern R_PPC_REL14_BRTAKEN :: PPC32_RelocationType +pattern R_PPC_REL14_BRTAKEN = PPC32_RelocationType 12 -- (S + A - P) >> 2 + +pattern R_PPC_REL14_BRNTAKEN :: PPC32_RelocationType +pattern R_PPC_REL14_BRNTAKEN = PPC32_RelocationType 13 -- (S + A - P) >> 2 + +pattern R_PPC_GOT16 :: PPC32_RelocationType +pattern R_PPC_GOT16 = PPC32_RelocationType 14 -- G + A + +pattern R_PPC_GOT16_LO :: PPC32_RelocationType +pattern R_PPC_GOT16_LO = PPC32_RelocationType 15 -- #lo(G + A) + +pattern R_PPC_GOT16_HI :: PPC32_RelocationType +pattern R_PPC_GOT16_HI = PPC32_RelocationType 16 -- #hi(G + A) + +pattern R_PPC_GOT16_HA :: PPC32_RelocationType +pattern R_PPC_GOT16_HA = PPC32_RelocationType 17 -- #ha(G + A) + +pattern R_PPC_PLTREL24 :: PPC32_RelocationType +pattern R_PPC_PLTREL24 = PPC32_RelocationType 18 -- (L + A - P) >> 2 + +pattern R_PPC_COPY :: PPC32_RelocationType +pattern R_PPC_COPY = PPC32_RelocationType 19 -- none + +pattern R_PPC_GLOB_DAT :: PPC32_RelocationType +pattern R_PPC_GLOB_DAT = PPC32_RelocationType 20 -- S + A + +pattern R_PPC_JMP_SLOT :: PPC32_RelocationType +pattern R_PPC_JMP_SLOT = PPC32_RelocationType 21 + +pattern R_PPC_RELATIVE :: PPC32_RelocationType +pattern R_PPC_RELATIVE = PPC32_RelocationType 22 -- B + A + +pattern R_PPC_LOCAL24PC :: PPC32_RelocationType +pattern R_PPC_LOCAL24PC = PPC32_RelocationType 23 + +pattern R_PPC_UADDR32 :: PPC32_RelocationType +pattern R_PPC_UADDR32 = PPC32_RelocationType 24 -- S + A + +pattern R_PPC_UADDR16 :: PPC32_RelocationType +pattern R_PPC_UADDR16 = PPC32_RelocationType 25 -- S + A + +pattern R_PPC_REL32 :: PPC32_RelocationType +pattern R_PPC_REL32 = PPC32_RelocationType 26 -- S + A - P + +pattern R_PPC_PLT32 :: PPC32_RelocationType +pattern R_PPC_PLT32 = PPC32_RelocationType 27 -- L + A + +pattern R_PPC_PLTREL32 :: PPC32_RelocationType +pattern R_PPC_PLTREL32 = PPC32_RelocationType 28 -- L + A - P + +pattern R_PPC_PLT16_LO :: PPC32_RelocationType +pattern R_PPC_PLT16_LO = PPC32_RelocationType 29 -- #lo(L + A) + +pattern R_PPL_PLT16_HI :: PPC32_RelocationType +pattern R_PPL_PLT16_HI = PPC32_RelocationType 30 -- #hi(L + A) + +pattern R_PPC_PLT16_HA :: PPC32_RelocationType +pattern R_PPC_PLT16_HA = PPC32_RelocationType 31 -- #ha(L + A) + +pattern R_PPC_SDAREL16 :: PPC32_RelocationType +pattern R_PPC_SDAREL16 = PPC32_RelocationType 32 -- S + A - _SDA_BASE_ + +pattern R_PPC_SECTOFF :: PPC32_RelocationType +pattern R_PPC_SECTOFF = PPC32_RelocationType 33 -- R + A + +pattern R_PPC_SECTOFF_LO :: PPC32_RelocationType +pattern R_PPC_SECTOFF_LO = PPC32_RelocationType 34 -- #lo(R + A) + +pattern R_PPC_SECTOFF_HI :: PPC32_RelocationType +pattern R_PPC_SECTOFF_HI = PPC32_RelocationType 35 -- #hi(R + A) + +pattern R_PPC_SECTOFF_HA :: PPC32_RelocationType +pattern R_PPC_SECTOFF_HA = PPC32_RelocationType 36 -- #ha(R + A) + +pattern R_PPC_ADDR30 :: PPC32_RelocationType +pattern R_PPC_ADDR30 = PPC32_RelocationType 37 -- (S + A - P) >> 2 + +ppc32Reloc :: PPC32_RelocationType + -> String + -> Int + -> (PPC32_RelocationType, (String,Int)) +ppc32Reloc tp nm c = (tp, (nm, c)) + +-- These values are derived from Figure 4-1 (Relocation Fields) of +-- http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf. +-- +-- Note that the treatment of `low24` and `low14` here is not correct. See +-- https://github.com/GaloisInc/elf-edit/issues/39 for more information. + +none :: Int +none = 0 + +word32 :: Int +word32 = 32 + +word30 :: Int +word30 = 30 + +low24 :: Int +low24 = 24 + +low14 :: Int +low14 = 14 + +half16 :: Int +half16 = 16 + +-- This map is derived from Table 4-8 (Relocation Types) of +-- http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf. + +ppc32_RelocationTypes :: Map.Map PPC32_RelocationType (String, Int) +ppc32_RelocationTypes = Map.fromList + [ ppc32Reloc R_PPC_NONE "R_PPC_NONE" none + , ppc32Reloc R_PPC_ADDR32 "R_PPC_ADDR32" word32 + , ppc32Reloc R_PPC_ADDR24 "R_PPC_ADDR24" low24 + , ppc32Reloc R_PPC_ADDR16 "R_PPC_ADDR16" half16 + , ppc32Reloc R_PPC_ADDR16_LO "R_PPC_ADDR16_LO" half16 + , ppc32Reloc R_PPC_ADDR16_HI "R_PPC_ADDR16_HI" half16 + , ppc32Reloc R_PPC_ADDR16_HA "R_PPC_ADDR16_HA" half16 + , ppc32Reloc R_PPC_ADDR14 "R_PPC_ADDR14" low14 + , ppc32Reloc R_PPC_ADDR14_BRTAKEN "R_PPC_ADDR14_BRTAKEN" low14 + , ppc32Reloc R_PPC_ADDR14_BRNTAKEN "R_PPC_ADDR14_BRNTAKEN" low14 + , ppc32Reloc R_PPC_REL24 "R_PPC_REL24" low24 + , ppc32Reloc R_PPC_REL14 "R_PPC_REL14" low14 + , ppc32Reloc R_PPC_REL14_BRTAKEN "R_PPC_REL14_BRTAKEN" low14 + , ppc32Reloc R_PPC_REL14_BRNTAKEN "R_PPC_REL14_BRNTAKEN" low14 + , ppc32Reloc R_PPC_GOT16 "R_PPC_GOT16" half16 + , ppc32Reloc R_PPC_GOT16_LO "R_PPC_GOT16_LO" half16 + , ppc32Reloc R_PPC_GOT16_HI "R_PPC_GOT16_HI" half16 + , ppc32Reloc R_PPC_GOT16_HA "R_PPC_GOT16_HA" half16 + , ppc32Reloc R_PPC_PLTREL24 "R_PPC_PLTREL24" low24 + , ppc32Reloc R_PPC_COPY "R_PPC_COPY" none + , ppc32Reloc R_PPC_GLOB_DAT "R_PPC_GLOB_DAT" word32 + , ppc32Reloc R_PPC_JMP_SLOT "R_PPC_JMP_SLOT" none + , ppc32Reloc R_PPC_RELATIVE "R_PPC_RELATIVE" word32 + , ppc32Reloc R_PPC_LOCAL24PC "R_PPC_LOCAL24PC" low24 + , ppc32Reloc R_PPC_UADDR32 "R_PPC_UADDR32" word32 + , ppc32Reloc R_PPC_UADDR16 "R_PPC_UADDR16" half16 + , ppc32Reloc R_PPC_REL32 "R_PPC_REL32" word32 + , ppc32Reloc R_PPC_PLT32 "R_PPC_PLT32" word32 + , ppc32Reloc R_PPC_PLTREL32 "R_PPC_PLTREL32" word32 + , ppc32Reloc R_PPC_PLT16_LO "R_PPC_PLT16_LO" half16 + , ppc32Reloc R_PPL_PLT16_HI "R_PPL_PLT16_HI" half16 + , ppc32Reloc R_PPC_PLT16_HA "R_PPC_PLT16_HA" half16 + , ppc32Reloc R_PPC_SDAREL16 "R_PPC_SDAREL16" half16 + , ppc32Reloc R_PPC_SECTOFF "R_PPC_SECTOFF" half16 + , ppc32Reloc R_PPC_SECTOFF_LO "R_PPC_SECTOFF_LO" half16 + , ppc32Reloc R_PPC_SECTOFF_HI "R_PPC_SECTOFF_HI" half16 + , ppc32Reloc R_PPC_SECTOFF_HA "R_PPC_SECTOFF_HA" half16 + , ppc32Reloc R_PPC_ADDR30 "R_PPC_ADDR30" word30 + ] + +instance Show PPC32_RelocationType where + show i = + case Map.lookup i ppc32_RelocationTypes of + Just (s,_) -> s + Nothing -> ppHex (fromPPC32_RelocationType i) + +instance IsRelocationType PPC32_RelocationType where + type RelocationWidth PPC32_RelocationType = 32 + + relaWidth _ = ELFCLASS32 + + toRelocType = PPC32_RelocationType . fromIntegral + + isRelative R_PPC_RELATIVE = True + isRelative _ = False + + relocTargetBits tp = + case Map.lookup tp ppc32_RelocationTypes of + Just (_,w) -> w + Nothing -> 32 diff --git a/src/Data/ElfEdit/Relocations/PPC64.hs b/src/Data/ElfEdit/Relocations/PPC64.hs new file mode 100644 index 0000000..ea78a8a --- /dev/null +++ b/src/Data/ElfEdit/Relocations/PPC64.hs @@ -0,0 +1,615 @@ +{- +Copyright : (c) Galois, Inc 2023 +Maintainer : Ryan Scott + +PPC64 relocation types. The list of relocation types is taken from Section 4.5 +(Relocation) of . +-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE TypeFamilies #-} +module Data.ElfEdit.Relocations.PPC64 + ( PPC64_RelocationType(..) + , pattern R_PPC64_NONE + , pattern R_PPC64_ADDR32 + , pattern R_PPC64_ADDR24 + , pattern R_PPC64_ADDR16 + , pattern R_PPC64_ADDR16_LO + , pattern R_PPC64_ADDR16_HI + , pattern R_PPC64_ADDR16_HA + , pattern R_PPC64_ADDR14 + , pattern R_PPC64_ADDR14_BRTAKEN + , pattern R_PPC64_ADDR14_BRNTAKEN + , pattern R_PPC64_REL24 + , pattern R_PPC64_REL14 + , pattern R_PPC64_REL14_BRTAKEN + , pattern R_PPC64_REL14_BRNTAKEN + , pattern R_PPC64_GOT16 + , pattern R_PPC64_GOT16_LO + , pattern R_PPC64_GOT16_HI + , pattern R_PPC64_GOT16_HA + , pattern R_PPC64_COPY + , pattern R_PPC64_GLOB_DAT + , pattern R_PPC64_JMP_SLOT + , pattern R_PPC64_RELATIVE + , pattern R_PPC64_UADDR32 + , pattern R_PPC64_UADDR16 + , pattern R_PPC64_REL32 + , pattern R_PPC64_PLT32 + , pattern R_PPC64_PLTREL32 + , pattern R_PPC64_PLT16_LO + , pattern R_PPC64_PLT16_HI + , pattern R_PPC64_PLT16_HA + , pattern R_PPC64_SECTOFF + , pattern R_PPC64_SECTOFF_LO + , pattern R_PPC64_SECTOFF_HI + , pattern R_PPC64_SECTOFF_HA + , pattern R_PPC64_ADDR30 + , pattern R_PPC64_ADDR64 + , pattern R_PPC64_ADDR16_HIGHER + , pattern R_PPC64_ADDR16_HIGHERA + , pattern R_PPC64_ADDR16_HIGHEST + , pattern R_PPC64_ADDR16_HIGHESTA + , pattern R_PPC64_UADDR64 + , pattern R_PPC64_REL64 + , pattern R_PPC64_PLT64 + , pattern R_PPC64_PLTREL64 + , pattern R_PPC64_TOC16 + , pattern R_PPC64_TOC16_LO + , pattern R_PPC64_TOC16_HI + , pattern R_PPC64_TOC16_HA + , pattern R_PPC64_TOC + , pattern R_PPC64_PLTGOT16 + , pattern R_PPC64_PLTGOT16_LO + , pattern R_PPC64_PLTGOT16_HI + , pattern R_PPC64_PLTGOT16_HA + , pattern R_PPC64_ADDR16_DS + , pattern R_PPC64_ADDR16_LO_DS + , pattern R_PPC64_GOT16_DS + , pattern R_PPC64_GOT16_LO_DS + , pattern R_PPC64_PLT16_LO_DS + , pattern R_PPC64_SECTOFF_DS + , pattern R_PPC64_SECTOFF_LO_DS + , pattern R_PPC64_TOC16_DS + , pattern R_PPC64_TOC16_LO_DS + , pattern R_PPC64_PLTGOT16_DS + , pattern R_PPC64_PLTGOT16_LO_DS + , pattern R_PPC64_TLS + , pattern R_PPC64_DTPMOD64 + , pattern R_PPC64_TPREL16 + , pattern R_PPC64_TPREL16_LO + , pattern R_PPC64_TPREL16_HI + , pattern R_PPC64_TPREL16_HA + , pattern R_PPC64_TPREL64 + , pattern R_PPC64_DTPREL16 + , pattern R_PPC64_DTPREL16_LO + , pattern R_PPC64_DTPREL16_HI + , pattern R_PPC64_DTPREL16_HA + , pattern R_PPC64_DTPREL64 + , pattern R_PPC64_GOT_TLSGD16 + , pattern R_PPC64_GOT_TLSGD16_LO + , pattern R_PPC64_GOT_TLSGD16_HI + , pattern R_PPC64_GOT_TLSGD16_HA + , pattern R_PPC64_GOT_TLSLD16 + , pattern R_PPC64_GOT_TLSLD16_LO + , pattern R_PPC64_GOT_TLSLD16_HI + , pattern R_PPC64_GOT_TLSLD16_HA + , pattern R_PPC64_GOT_TPREL16_DS + , pattern R_PPC64_GOT_TPREL16_LO_DS + , pattern R_PPC64_GOT_TPREL16_HI + , pattern R_PPC64_GOT_TPREL16_HA + , pattern R_PPC64_GOT_DTPREL16_DS + , pattern R_PPC64_GOT_DTPREL16_LO_DS + , pattern R_PPC64_GOT_DTPREL16_HI + , pattern R_PPC64_GOT_DTPREL16_HA + , pattern R_PPC64_TPREL16_DS + , pattern R_PPC64_TPREL16_LO_DS + , pattern R_PPC64_TPREL16_HIGHER + , pattern R_PPC64_TPREL16_HIGHERA + , pattern R_PPC64_TPREL16_HIGHEST + , pattern R_PPC64_TPREL16_HIGHESTA + , pattern R_PPC64_DTPREL16_DS + , pattern R_PPC64_DTPREL16_LO_DS + , pattern R_PPC64_DTPREL16_HIGHER + , pattern R_PPC64_DTPREL16_HIGHERA + , pattern R_PPC64_DTPREL16_HIGHEST + , pattern R_PPC64_DTPREL16_HIGHESTA + , ppc64_RelocationTypes + ) where + +import qualified Data.Map.Strict as Map +import Data.Word + +import Data.ElfEdit.Prim.Ehdr (ElfClass(..)) +import Data.ElfEdit.Relocations.Common +import Data.ElfEdit.Utils (ppHex) + +------------------------------------------------------------------------ +-- PPC64_RelocationType + +-- | Relocation types for 64-bit PPC code. +newtype PPC64_RelocationType = PPC64_RelocationType { fromPPC64_RelocationType :: Word32 } + deriving (Eq,Ord) + +-- These values are derived from Figure 4-1 (Relocation Types) of +-- https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf. + +pattern R_PPC64_NONE :: PPC64_RelocationType +pattern R_PPC64_NONE = PPC64_RelocationType 0 -- none + +pattern R_PPC64_ADDR32 :: PPC64_RelocationType +pattern R_PPC64_ADDR32 = PPC64_RelocationType 1 -- S + A + +pattern R_PPC64_ADDR24 :: PPC64_RelocationType +pattern R_PPC64_ADDR24 = PPC64_RelocationType 2 -- (S + A) >> 2 + +pattern R_PPC64_ADDR16 :: PPC64_RelocationType +pattern R_PPC64_ADDR16 = PPC64_RelocationType 3 -- S + A + +pattern R_PPC64_ADDR16_LO :: PPC64_RelocationType +pattern R_PPC64_ADDR16_LO = PPC64_RelocationType 4 -- #lo(S + A) + +pattern R_PPC64_ADDR16_HI :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HI = PPC64_RelocationType 5 -- #hi(S + A) + +pattern R_PPC64_ADDR16_HA :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HA = PPC64_RelocationType 6 -- #ha(S + A) + +pattern R_PPC64_ADDR14 :: PPC64_RelocationType +pattern R_PPC64_ADDR14 = PPC64_RelocationType 7 -- (S + A) >> 2 + +pattern R_PPC64_ADDR14_BRTAKEN :: PPC64_RelocationType +pattern R_PPC64_ADDR14_BRTAKEN = PPC64_RelocationType 8 -- (S + A) >> 2 + +pattern R_PPC64_ADDR14_BRNTAKEN :: PPC64_RelocationType +pattern R_PPC64_ADDR14_BRNTAKEN = PPC64_RelocationType 9 -- (S + A) >> 2 + +pattern R_PPC64_REL24 :: PPC64_RelocationType +pattern R_PPC64_REL24 = PPC64_RelocationType 10 -- (S + A - P) >> 2 + +pattern R_PPC64_REL14 :: PPC64_RelocationType +pattern R_PPC64_REL14 = PPC64_RelocationType 11 -- (S + A - P) >> 2 + +pattern R_PPC64_REL14_BRTAKEN :: PPC64_RelocationType +pattern R_PPC64_REL14_BRTAKEN = PPC64_RelocationType 12 -- (S + A - P) >> 2 + +pattern R_PPC64_REL14_BRNTAKEN :: PPC64_RelocationType +pattern R_PPC64_REL14_BRNTAKEN = PPC64_RelocationType 13 -- (S + A - P) >> 2 + +pattern R_PPC64_GOT16 :: PPC64_RelocationType +pattern R_PPC64_GOT16 = PPC64_RelocationType 14 -- G + +pattern R_PPC64_GOT16_LO :: PPC64_RelocationType +pattern R_PPC64_GOT16_LO = PPC64_RelocationType 15 -- #lo(G) + +pattern R_PPC64_GOT16_HI :: PPC64_RelocationType +pattern R_PPC64_GOT16_HI = PPC64_RelocationType 16 -- #hi(G) + +pattern R_PPC64_GOT16_HA :: PPC64_RelocationType +pattern R_PPC64_GOT16_HA = PPC64_RelocationType 17 -- #ha(G) + +pattern R_PPC64_COPY :: PPC64_RelocationType +pattern R_PPC64_COPY = PPC64_RelocationType 19 -- none + +pattern R_PPC64_GLOB_DAT :: PPC64_RelocationType +pattern R_PPC64_GLOB_DAT = PPC64_RelocationType 20 -- S + A + +pattern R_PPC64_JMP_SLOT :: PPC64_RelocationType +pattern R_PPC64_JMP_SLOT = PPC64_RelocationType 21 -- see below + +pattern R_PPC64_RELATIVE :: PPC64_RelocationType +pattern R_PPC64_RELATIVE = PPC64_RelocationType 22 -- B + A + +pattern R_PPC64_UADDR32 :: PPC64_RelocationType +pattern R_PPC64_UADDR32 = PPC64_RelocationType 24 -- S + A + +pattern R_PPC64_UADDR16 :: PPC64_RelocationType +pattern R_PPC64_UADDR16 = PPC64_RelocationType 25 -- S + A + +pattern R_PPC64_REL32 :: PPC64_RelocationType +pattern R_PPC64_REL32 = PPC64_RelocationType 26 -- S + A - P + +pattern R_PPC64_PLT32 :: PPC64_RelocationType +pattern R_PPC64_PLT32 = PPC64_RelocationType 27 -- L + +pattern R_PPC64_PLTREL32 :: PPC64_RelocationType +pattern R_PPC64_PLTREL32 = PPC64_RelocationType 28 -- L - P + +pattern R_PPC64_PLT16_LO :: PPC64_RelocationType +pattern R_PPC64_PLT16_LO = PPC64_RelocationType 29 -- #lo(L) + +pattern R_PPC64_PLT16_HI :: PPC64_RelocationType +pattern R_PPC64_PLT16_HI = PPC64_RelocationType 30 -- #hi(L) + +pattern R_PPC64_PLT16_HA :: PPC64_RelocationType +pattern R_PPC64_PLT16_HA = PPC64_RelocationType 31 -- #ha(L) + +pattern R_PPC64_SECTOFF :: PPC64_RelocationType +pattern R_PPC64_SECTOFF = PPC64_RelocationType 33 -- R + A + +pattern R_PPC64_SECTOFF_LO :: PPC64_RelocationType +pattern R_PPC64_SECTOFF_LO = PPC64_RelocationType 34 -- #lo(R + A) + +pattern R_PPC64_SECTOFF_HI :: PPC64_RelocationType +pattern R_PPC64_SECTOFF_HI = PPC64_RelocationType 35 -- #hi(R + A) + +pattern R_PPC64_SECTOFF_HA :: PPC64_RelocationType +pattern R_PPC64_SECTOFF_HA = PPC64_RelocationType 36 -- #ha(R + A) + +pattern R_PPC64_ADDR30 :: PPC64_RelocationType +pattern R_PPC64_ADDR30 = PPC64_RelocationType 37 -- (S + A - P) >> 2 + +pattern R_PPC64_ADDR64 :: PPC64_RelocationType +pattern R_PPC64_ADDR64 = PPC64_RelocationType 38 -- S + A + +pattern R_PPC64_ADDR16_HIGHER :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HIGHER = PPC64_RelocationType 39 -- #higher(S + A) + +pattern R_PPC64_ADDR16_HIGHERA :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HIGHERA = PPC64_RelocationType 40 -- #highera(S + A) + +pattern R_PPC64_ADDR16_HIGHEST :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HIGHEST = PPC64_RelocationType 41 -- #highest(S + A) + +pattern R_PPC64_ADDR16_HIGHESTA :: PPC64_RelocationType +pattern R_PPC64_ADDR16_HIGHESTA = PPC64_RelocationType 42 -- #highesta(S + A) + +pattern R_PPC64_UADDR64 :: PPC64_RelocationType +pattern R_PPC64_UADDR64 = PPC64_RelocationType 43 -- S + A + +pattern R_PPC64_REL64 :: PPC64_RelocationType +pattern R_PPC64_REL64 = PPC64_RelocationType 44 -- S + A - P + +pattern R_PPC64_PLT64 :: PPC64_RelocationType +pattern R_PPC64_PLT64 = PPC64_RelocationType 45 -- L + +pattern R_PPC64_PLTREL64 :: PPC64_RelocationType +pattern R_PPC64_PLTREL64 = PPC64_RelocationType 46 -- L - P + +pattern R_PPC64_TOC16 :: PPC64_RelocationType +pattern R_PPC64_TOC16 = PPC64_RelocationType 47 -- S + A - .TOC. + +pattern R_PPC64_TOC16_LO :: PPC64_RelocationType +pattern R_PPC64_TOC16_LO = PPC64_RelocationType 48 -- #lo(S + A - .TOC.) + +pattern R_PPC64_TOC16_HI :: PPC64_RelocationType +pattern R_PPC64_TOC16_HI = PPC64_RelocationType 49 -- #hi(S + A - .TOC.) + +pattern R_PPC64_TOC16_HA :: PPC64_RelocationType +pattern R_PPC64_TOC16_HA = PPC64_RelocationType 50 -- #ha(S + A - .TOC.) + +pattern R_PPC64_TOC :: PPC64_RelocationType +pattern R_PPC64_TOC = PPC64_RelocationType 51 -- .TOC. + +pattern R_PPC64_PLTGOT16 :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16 = PPC64_RelocationType 52 -- M + +pattern R_PPC64_PLTGOT16_LO :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16_LO = PPC64_RelocationType 53 -- #lo(M) + +pattern R_PPC64_PLTGOT16_HI :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16_HI = PPC64_RelocationType 54 -- #hi(M) + +pattern R_PPC64_PLTGOT16_HA :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16_HA = PPC64_RelocationType 55 -- #ha(M) + +pattern R_PPC64_ADDR16_DS :: PPC64_RelocationType +pattern R_PPC64_ADDR16_DS = PPC64_RelocationType 56 -- (S + A) >> 2 + +pattern R_PPC64_ADDR16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_ADDR16_LO_DS = PPC64_RelocationType 57 -- #lo(S + A) >> 2 + +pattern R_PPC64_GOT16_DS :: PPC64_RelocationType +pattern R_PPC64_GOT16_DS = PPC64_RelocationType 58 -- G >> 2 + +pattern R_PPC64_GOT16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_GOT16_LO_DS = PPC64_RelocationType 59 -- #lo(G) >> 2 + +pattern R_PPC64_PLT16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_PLT16_LO_DS = PPC64_RelocationType 60 -- #lo(L) >> 2 + +pattern R_PPC64_SECTOFF_DS :: PPC64_RelocationType +pattern R_PPC64_SECTOFF_DS = PPC64_RelocationType 61 -- (R + A) >> 2 + +pattern R_PPC64_SECTOFF_LO_DS :: PPC64_RelocationType +pattern R_PPC64_SECTOFF_LO_DS = PPC64_RelocationType 62 -- #lo(R + A) >> 2 + +pattern R_PPC64_TOC16_DS :: PPC64_RelocationType +pattern R_PPC64_TOC16_DS = PPC64_RelocationType 63 -- (S + A - .TOC.) >> 2 + +pattern R_PPC64_TOC16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_TOC16_LO_DS = PPC64_RelocationType 64 -- #lo(S + A - .TOC.) >> 2 + +pattern R_PPC64_PLTGOT16_DS :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16_DS = PPC64_RelocationType 65 -- M >> 2 + +pattern R_PPC64_PLTGOT16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_PLTGOT16_LO_DS = PPC64_RelocationType 66 -- #lo(M) >> 2 + +pattern R_PPC64_TLS :: PPC64_RelocationType +pattern R_PPC64_TLS = PPC64_RelocationType 67 -- none + +pattern R_PPC64_DTPMOD64 :: PPC64_RelocationType +pattern R_PPC64_DTPMOD64 = PPC64_RelocationType 68 -- @dtpmod + +pattern R_PPC64_TPREL16 :: PPC64_RelocationType +pattern R_PPC64_TPREL16 = PPC64_RelocationType 69 -- @tprel + +pattern R_PPC64_TPREL16_LO :: PPC64_RelocationType +pattern R_PPC64_TPREL16_LO = PPC64_RelocationType 60 -- #lo(@tprel) + +pattern R_PPC64_TPREL16_HI :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HI = PPC64_RelocationType 71 -- #hi(@tprel) + +pattern R_PPC64_TPREL16_HA :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HA = PPC64_RelocationType 72 -- #ha(@tprel) + +pattern R_PPC64_TPREL64 :: PPC64_RelocationType +pattern R_PPC64_TPREL64 = PPC64_RelocationType 73 -- @tprel + +pattern R_PPC64_DTPREL16 :: PPC64_RelocationType +pattern R_PPC64_DTPREL16 = PPC64_RelocationType 74 -- @dtprel + +pattern R_PPC64_DTPREL16_LO :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_LO = PPC64_RelocationType 75 -- #lo(@dtprel) + +pattern R_PPC64_DTPREL16_HI :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HI = PPC64_RelocationType 76 -- #hi(@dtprel) + +pattern R_PPC64_DTPREL16_HA :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HA = PPC64_RelocationType 77 -- #ha(@dtprel) + +pattern R_PPC64_DTPREL64 :: PPC64_RelocationType +pattern R_PPC64_DTPREL64 = PPC64_RelocationType 78 -- @dtprel + +pattern R_PPC64_GOT_TLSGD16 :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSGD16 = PPC64_RelocationType 79 -- @got@tlsgd + +pattern R_PPC64_GOT_TLSGD16_LO :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSGD16_LO = PPC64_RelocationType 80 -- #lo(@got@tlsgd) + +pattern R_PPC64_GOT_TLSGD16_HI :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSGD16_HI = PPC64_RelocationType 81 -- #hi(@got@tlsgd) + +pattern R_PPC64_GOT_TLSGD16_HA :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSGD16_HA = PPC64_RelocationType 82 -- #ha(@got@tlsgd) + +pattern R_PPC64_GOT_TLSLD16 :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSLD16 = PPC64_RelocationType 83 -- @got@tlsld + +pattern R_PPC64_GOT_TLSLD16_LO :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSLD16_LO = PPC64_RelocationType 84 -- #lo(@got@tlsld) + +pattern R_PPC64_GOT_TLSLD16_HI :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSLD16_HI = PPC64_RelocationType 85 -- #hi(@got@tlsld) + +pattern R_PPC64_GOT_TLSLD16_HA :: PPC64_RelocationType +pattern R_PPC64_GOT_TLSLD16_HA = PPC64_RelocationType 86 -- #ha(@got@tlsld) + +pattern R_PPC64_GOT_TPREL16_DS :: PPC64_RelocationType +pattern R_PPC64_GOT_TPREL16_DS = PPC64_RelocationType 87 -- @got@tprel + +pattern R_PPC64_GOT_TPREL16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_GOT_TPREL16_LO_DS = PPC64_RelocationType 88 -- #lo(@got@tprel) + +pattern R_PPC64_GOT_TPREL16_HI :: PPC64_RelocationType +pattern R_PPC64_GOT_TPREL16_HI = PPC64_RelocationType 89 -- #hi(@got@tprel) + +pattern R_PPC64_GOT_TPREL16_HA :: PPC64_RelocationType +pattern R_PPC64_GOT_TPREL16_HA = PPC64_RelocationType 90 -- #ha(@got@tprel) + +pattern R_PPC64_GOT_DTPREL16_DS :: PPC64_RelocationType +pattern R_PPC64_GOT_DTPREL16_DS = PPC64_RelocationType 91 -- @got@dtprel + +pattern R_PPC64_GOT_DTPREL16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_GOT_DTPREL16_LO_DS = PPC64_RelocationType 92 -- #lo(@got@dtprel) + +pattern R_PPC64_GOT_DTPREL16_HI :: PPC64_RelocationType +pattern R_PPC64_GOT_DTPREL16_HI = PPC64_RelocationType 93 -- #hi(@got@dtprel) + +pattern R_PPC64_GOT_DTPREL16_HA :: PPC64_RelocationType +pattern R_PPC64_GOT_DTPREL16_HA = PPC64_RelocationType 94 -- #ha(@got@dtprel) + +pattern R_PPC64_TPREL16_DS :: PPC64_RelocationType +pattern R_PPC64_TPREL16_DS = PPC64_RelocationType 95 -- @tprel + +pattern R_PPC64_TPREL16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_TPREL16_LO_DS = PPC64_RelocationType 96 -- #lo(@tprel) + +pattern R_PPC64_TPREL16_HIGHER :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HIGHER = PPC64_RelocationType 97 -- #higher(@tprel) + +pattern R_PPC64_TPREL16_HIGHERA :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HIGHERA = PPC64_RelocationType 98 -- #highera(@tprel) + +pattern R_PPC64_TPREL16_HIGHEST :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HIGHEST = PPC64_RelocationType 99 -- #highest(@tprel) + +pattern R_PPC64_TPREL16_HIGHESTA :: PPC64_RelocationType +pattern R_PPC64_TPREL16_HIGHESTA = PPC64_RelocationType 100 -- #highesta(@tprel) + +pattern R_PPC64_DTPREL16_DS :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_DS = PPC64_RelocationType 101 -- @dtprel + +pattern R_PPC64_DTPREL16_LO_DS :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_LO_DS = PPC64_RelocationType 102 -- #lo(@dtprel) + +pattern R_PPC64_DTPREL16_HIGHER :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HIGHER = PPC64_RelocationType 103 -- #higher(@dtprel) + +pattern R_PPC64_DTPREL16_HIGHERA :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HIGHERA = PPC64_RelocationType 104 -- #highera(@dtprel) + +pattern R_PPC64_DTPREL16_HIGHEST :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HIGHEST = PPC64_RelocationType 105 -- #highest(@dtprel) + +pattern R_PPC64_DTPREL16_HIGHESTA :: PPC64_RelocationType +pattern R_PPC64_DTPREL16_HIGHESTA = PPC64_RelocationType 106 -- #highesta(@dtprel) + +ppc64Reloc :: PPC64_RelocationType + -> String + -> Int + -> (PPC64_RelocationType, (String,Int)) +ppc64Reloc tp nm c = (tp, (nm, c)) + +-- These values are derived from Section 4.5.1 (Relocation Types) of +-- https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf. +-- +-- Note that the treatment of `low24` and `low14` here is not correct. See +-- https://github.com/GaloisInc/elf-edit/issues/39 for more information. + +none :: Int +none = 0 + +doubleword64 :: Int +doubleword64 = 64 + +word32 :: Int +word32 = 32 + +word30 :: Int +word30 = 30 + +low24 :: Int +low24 = 24 + +low14 :: Int +low14 = 14 + +half16 :: Int +half16 = 16 + +half16ds :: Int +half16ds = 14 + +-- This map is derived from Figure 4-1 (Relocation Types) of +-- https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf. + +ppc64_RelocationTypes :: Map.Map PPC64_RelocationType (String, Int) +ppc64_RelocationTypes = Map.fromList + [ ppc64Reloc R_PPC64_NONE "R_PPC64_NONE" none + , ppc64Reloc R_PPC64_ADDR32 "R_PPC64_ADDR32" word32 + , ppc64Reloc R_PPC64_ADDR24 "R_PPC64_ADDR24" low24 + , ppc64Reloc R_PPC64_ADDR16 "R_PPC64_ADDR16" half16 + , ppc64Reloc R_PPC64_ADDR16_LO "R_PPC64_ADDR16_LO" half16 + , ppc64Reloc R_PPC64_ADDR16_HI "R_PPC64_ADDR16_HI" half16 + , ppc64Reloc R_PPC64_ADDR16_HA "R_PPC64_ADDR16_HA" half16 + , ppc64Reloc R_PPC64_ADDR14 "R_PPC64_ADDR14" low14 + , ppc64Reloc R_PPC64_ADDR14_BRTAKEN "R_PPC64_ADDR14_BRTAKEN" low14 + , ppc64Reloc R_PPC64_ADDR14_BRNTAKEN "R_PPC64_ADDR14_BRNTAKEN" low14 + , ppc64Reloc R_PPC64_REL24 "R_PPC64_REL24" low24 + , ppc64Reloc R_PPC64_REL14 "R_PPC64_REL14" low14 + , ppc64Reloc R_PPC64_REL14_BRTAKEN "R_PPC64_REL14_BRTAKEN" low14 + , ppc64Reloc R_PPC64_REL14_BRNTAKEN "R_PPC64_REL14_BRNTAKEN" low14 + , ppc64Reloc R_PPC64_GOT16 "R_PPC64_GOT16" half16 + , ppc64Reloc R_PPC64_GOT16_LO "R_PPC64_GOT16_LO" half16 + , ppc64Reloc R_PPC64_GOT16_HI "R_PPC64_GOT16_HI" half16 + , ppc64Reloc R_PPC64_GOT16_HA "R_PPC64_GOT16_HA" half16 + , ppc64Reloc R_PPC64_COPY "R_PPC64_COPY" none + , ppc64Reloc R_PPC64_GLOB_DAT "R_PPC64_GLOB_DAT" doubleword64 + , ppc64Reloc R_PPC64_JMP_SLOT "R_PPC64_JMP_SLOT" none + , ppc64Reloc R_PPC64_RELATIVE "R_PPC64_RELATIVE" doubleword64 + , ppc64Reloc R_PPC64_UADDR32 "R_PPC64_UADDR32" word32 + , ppc64Reloc R_PPC64_UADDR16 "R_PPC64_UADDR16" half16 + , ppc64Reloc R_PPC64_REL32 "R_PPC64_REL32" word32 + , ppc64Reloc R_PPC64_PLT32 "R_PPC64_PLT32" word32 + , ppc64Reloc R_PPC64_PLTREL32 "R_PPC64_PLTREL32" word32 + , ppc64Reloc R_PPC64_PLT16_LO "R_PPC64_PLT16_LO" half16 + , ppc64Reloc R_PPC64_PLT16_HI "R_PPC64_PLT16_HI" half16 + , ppc64Reloc R_PPC64_PLT16_HA "R_PPC64_PLT16_HA" half16 + , ppc64Reloc R_PPC64_SECTOFF "R_PPC64_SECTOFF" half16 + , ppc64Reloc R_PPC64_SECTOFF_LO "R_PPC64_SECTOFF_LO" half16 + , ppc64Reloc R_PPC64_SECTOFF_HI "R_PPC64_SECTOFF_HI" half16 + , ppc64Reloc R_PPC64_SECTOFF_HA "R_PPC64_SECTOFF_HA" half16 + , ppc64Reloc R_PPC64_ADDR30 "R_PPC64_ADDR30" word30 + , ppc64Reloc R_PPC64_ADDR64 "R_PPC64_ADDR64" doubleword64 + , ppc64Reloc R_PPC64_ADDR16_HIGHER "R_PPC64_ADDR16_HIGHER" half16 + , ppc64Reloc R_PPC64_ADDR16_HIGHERA "R_PPC64_ADDR16_HIGHERA" half16 + , ppc64Reloc R_PPC64_ADDR16_HIGHEST "R_PPC64_ADDR16_HIGHEST" half16 + , ppc64Reloc R_PPC64_ADDR16_HIGHESTA "R_PPC64_ADDR16_HIGHESTA" half16 + , ppc64Reloc R_PPC64_UADDR64 "R_PPC64_UADDR64" doubleword64 + , ppc64Reloc R_PPC64_REL64 "R_PPC64_REL64" doubleword64 + , ppc64Reloc R_PPC64_PLT64 "R_PPC64_PLT64" doubleword64 + , ppc64Reloc R_PPC64_PLTREL64 "R_PPC64_PLTREL64" doubleword64 + , ppc64Reloc R_PPC64_TOC16 "R_PPC64_TOC16" half16 + , ppc64Reloc R_PPC64_TOC16_LO "R_PPC64_TOC16_LO" half16 + , ppc64Reloc R_PPC64_TOC16_HI "R_PPC64_TOC16_HI" half16 + , ppc64Reloc R_PPC64_TOC16_HA "R_PPC64_TOC16_HA" half16 + , ppc64Reloc R_PPC64_TOC "R_PPC64_TOC" doubleword64 + , ppc64Reloc R_PPC64_PLTGOT16 "R_PPC64_PLTGOT16" half16 + , ppc64Reloc R_PPC64_PLTGOT16_LO "R_PPC64_PLTGOT16_LO" half16 + , ppc64Reloc R_PPC64_PLTGOT16_HI "R_PPC64_PLTGOT16_HI" half16 + , ppc64Reloc R_PPC64_PLTGOT16_HA "R_PPC64_PLTGOT16_HA" half16 + , ppc64Reloc R_PPC64_ADDR16_DS "R_PPC64_ADDR16_DS" half16ds + , ppc64Reloc R_PPC64_ADDR16_LO_DS "R_PPC64_ADDR16_LO_DS" half16ds + , ppc64Reloc R_PPC64_GOT16_DS "R_PPC64_GOT16_DS" half16ds + , ppc64Reloc R_PPC64_GOT16_LO_DS "R_PPC64_GOT16_LO_DS" half16ds + , ppc64Reloc R_PPC64_PLT16_LO_DS "R_PPC64_PLT16_LO_DS" half16ds + , ppc64Reloc R_PPC64_SECTOFF_DS "R_PPC64_SECTOFF_DS" half16ds + , ppc64Reloc R_PPC64_SECTOFF_LO_DS "R_PPC64_SECTOFF_LO_DS" half16ds + , ppc64Reloc R_PPC64_TOC16_DS "R_PPC64_TOC16_DS" half16ds + , ppc64Reloc R_PPC64_TOC16_LO_DS "R_PPC64_TOC16_LO_DS" half16ds + , ppc64Reloc R_PPC64_PLTGOT16_DS "R_PPC64_PLTGOT16_DS" half16ds + , ppc64Reloc R_PPC64_PLTGOT16_LO_DS "R_PPC64_PLTGOT16_LO_DS" half16ds + , ppc64Reloc R_PPC64_TLS "R_PPC64_TLS" none + , ppc64Reloc R_PPC64_DTPMOD64 "R_PPC64_DTPMOD64" doubleword64 + , ppc64Reloc R_PPC64_TPREL16 "R_PPC64_TPREL16" half16 + , ppc64Reloc R_PPC64_TPREL16_LO "R_PPC64_TPREL16_LO" half16 + , ppc64Reloc R_PPC64_TPREL16_HI "R_PPC64_TPREL16_HI" half16 + , ppc64Reloc R_PPC64_TPREL16_HA "R_PPC64_TPREL16_HA" half16 + , ppc64Reloc R_PPC64_TPREL64 "R_PPC64_TPREL64" doubleword64 + , ppc64Reloc R_PPC64_DTPREL16 "R_PPC64_DTPREL16" half16 + , ppc64Reloc R_PPC64_DTPREL16_LO "R_PPC64_DTPREL16_LO" half16 + , ppc64Reloc R_PPC64_DTPREL16_HI "R_PPC64_DTPREL16_HI" half16 + , ppc64Reloc R_PPC64_DTPREL16_HA "R_PPC64_DTPREL16_HA" half16 + , ppc64Reloc R_PPC64_DTPREL64 "R_PPC64_DTPREL64" doubleword64 + , ppc64Reloc R_PPC64_GOT_TLSGD16 "R_PPC64_GOT_TLSGD16" half16 + , ppc64Reloc R_PPC64_GOT_TLSGD16_LO "R_PPC64_GOT_TLSGD16_LO" half16 + , ppc64Reloc R_PPC64_GOT_TLSGD16_HI "R_PPC64_GOT_TLSGD16_HI" half16 + , ppc64Reloc R_PPC64_GOT_TLSGD16_HA "R_PPC64_GOT_TLSGD16_HA" half16 + , ppc64Reloc R_PPC64_GOT_TLSLD16 "R_PPC64_GOT_TLSLD16" half16 + , ppc64Reloc R_PPC64_GOT_TLSLD16_LO "R_PPC64_GOT_TLSLD16_LO" half16 + , ppc64Reloc R_PPC64_GOT_TLSLD16_HI "R_PPC64_GOT_TLSLD16_HI" half16 + , ppc64Reloc R_PPC64_GOT_TLSLD16_HA "R_PPC64_GOT_TLSLD16_HA" half16 + , ppc64Reloc R_PPC64_GOT_TPREL16_DS "R_PPC64_GOT_TPREL16_DS" half16ds + , ppc64Reloc R_PPC64_GOT_TPREL16_LO_DS "R_PPC64_GOT_TPREL16_LO_DS" half16ds + , ppc64Reloc R_PPC64_GOT_TPREL16_HI "R_PPC64_GOT_TPREL16_HI" half16 + , ppc64Reloc R_PPC64_GOT_TPREL16_HA "R_PPC64_GOT_TPREL16_HA" half16 + , ppc64Reloc R_PPC64_GOT_DTPREL16_DS "R_PPC64_GOT_DTPREL16_DS" half16ds + , ppc64Reloc R_PPC64_GOT_DTPREL16_LO_DS "R_PPC64_GOT_DTPREL16_LO_DS" half16ds + , ppc64Reloc R_PPC64_GOT_DTPREL16_HI "R_PPC64_GOT_DTPREL16_HI" half16 + , ppc64Reloc R_PPC64_GOT_DTPREL16_HA "R_PPC64_GOT_DTPREL16_HA" half16 + , ppc64Reloc R_PPC64_TPREL16_DS "R_PPC64_TPREL16_DS" half16ds + , ppc64Reloc R_PPC64_TPREL16_LO_DS "R_PPC64_TPREL16_LO_DS" half16ds + , ppc64Reloc R_PPC64_TPREL16_HIGHER "R_PPC64_TPREL16_HIGHER" half16 + , ppc64Reloc R_PPC64_TPREL16_HIGHERA "R_PPC64_TPREL16_HIGHERA" half16 + , ppc64Reloc R_PPC64_TPREL16_HIGHEST "R_PPC64_TPREL16_HIGHEST" half16 + , ppc64Reloc R_PPC64_TPREL16_HIGHESTA "R_PPC64_TPREL16_HIGHESTA" half16 + , ppc64Reloc R_PPC64_DTPREL16_DS "R_PPC64_DTPREL16_DS" half16ds + , ppc64Reloc R_PPC64_DTPREL16_LO_DS "R_PPC64_DTPREL16_LO_DS" half16ds + , ppc64Reloc R_PPC64_DTPREL16_HIGHER "R_PPC64_DTPREL16_HIGHER" half16 + , ppc64Reloc R_PPC64_DTPREL16_HIGHERA "R_PPC64_DTPREL16_HIGHERA" half16 + , ppc64Reloc R_PPC64_DTPREL16_HIGHEST "R_PPC64_DTPREL16_HIGHEST" half16 + , ppc64Reloc R_PPC64_DTPREL16_HIGHESTA "R_PPC64_DTPREL16_HIGHESTA" half16 + ] + +instance Show PPC64_RelocationType where + show i = + case Map.lookup i ppc64_RelocationTypes of + Just (s,_) -> s + Nothing -> ppHex (fromPPC64_RelocationType i) + +instance IsRelocationType PPC64_RelocationType where + type RelocationWidth PPC64_RelocationType = 64 + + relaWidth _ = ELFCLASS64 + + toRelocType = PPC64_RelocationType . fromIntegral + + isRelative R_PPC64_RELATIVE = True + isRelative _ = False + + relocTargetBits tp = + case Map.lookup tp ppc64_RelocationTypes of + Just (_,w) -> w + Nothing -> 64 diff --git a/tests/Makefile b/tests/Makefile index 6612978..044b768 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,4 @@ -all: simple.elf simple.static.elf libsymbol_versions.2.so fmax.elf +all: simple.elf simple.static.elf libsymbol_versions.2.so fmax.elf ppc32-relocs.elf ppc64-relocs.elf simple.elf: Makefile simple.c gcc simple.c -o simple.elf @@ -11,3 +11,9 @@ libsymbol_versions.2.so: symbol_versions.c fmax.elf: fmax.c gcc $< -o $@ -lm + +ppc32-relocs.elf: ppc32-relocs.c + powerpc-linux-musl-gcc $< -o $@ + +ppc64-relocs.elf: ppc64-relocs.c + powerpc64-linux-musl-gcc $< -o $@ diff --git a/tests/Test.hs b/tests/Test.hs index a21bf99..d404b7f 100644 --- a/tests/Test.hs +++ b/tests/Test.hs @@ -1,7 +1,10 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} module Main ( main ) where @@ -10,8 +13,11 @@ import Control.Applicative import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C8 import qualified Data.ByteString.Lazy as L +import qualified Data.List as List import qualified Data.Map as Map import Data.Maybe +import Data.Ord ( comparing ) +import Data.Proxy import Data.String import qualified Data.Vector as V import Data.Word ( Word32 ) @@ -189,6 +195,61 @@ testDynNeeded fp expectedDtNeeded = do Right deps -> pure deps T.assertEqual "Testing DT_NEEDED entries" actualDtNeeded expectedDtNeeded +-- | Test that the list of RELA relocations in a dynamically linked ELF binary +-- match the expected results. +testRelocEntries :: + forall tp proxy + . (Eq tp, Ord (Elf.RelocationWord tp), Elf.IsRelocationType tp) + => proxy tp + -> FilePath + -- ^ The path of the ELF file to load. + -> [(Elf.RelocationWord tp, tp)] + -- ^ The address and type of each relocation entry that is expected to be in + -- the list of RELA relocations. + -> T.Assertion +testRelocEntries _ fp expectedEntries = do + bs <- B.readFile fp + withElfHeader bs $ \e -> do + let ph = Elf.headerPhdrs e + dynPhdr <- + case filter (\p -> Elf.phdrSegmentType p == Elf.PT_DYNAMIC) ph of + [r] -> pure r + _ -> T.assertFailure "Could not find DYNAMIC section" + let hdr = Elf.header e + let d = Elf.headerData hdr + let cl = Elf.headerClass hdr + Elf.elfClassInstances cl $ do + let contents = Elf.headerFileContents e + virtMap <- maybe (T.assertFailure "Overlapping loaded segments") pure $ + Elf.virtAddrMap contents ph + let dynContents = Elf.slice (Elf.phdrFileRange dynPhdr) contents + dynSection <- either (T.assertFailure . show) pure $ + Elf.dynamicEntries d cl dynContents + relaEntries <- + case Elf.dynRelaBuffer dynSection virtMap of + Left errMsg -> T.assertFailure $ show errMsg + Right Nothing -> pure [] + Right (Just relaBuffer) -> + case Elf.decodeRelaEntries @tp d relaBuffer of + Left errMsg -> T.assertFailure errMsg + Right relaEntries -> pure relaEntries + relEntries <- + case Elf.dynRelBuffer dynSection virtMap of + Left errMsg -> T.assertFailure $ show errMsg + Right Nothing -> pure [] + Right (Just relBuffer) -> + case Elf.decodeRelEntries @tp d relBuffer of + Left errMsg -> T.assertFailure errMsg + Right relEntries -> pure relEntries + let actualEntries = + List.sortBy (comparing fst) + $ map (\rela -> (Elf.relaAddr rela, Elf.relaType rela)) relaEntries + ++ map (\rel -> (Elf.relAddr rel, Elf.relType rel)) relEntries + T.assertEqual + "Testing relocation entries" + expectedEntries + actualEntries + tests :: T.TestTree tests = T.testGroup "ELF Tests" [ T.testCase "Empty ELF" testEmptyElf @@ -220,6 +281,57 @@ tests = T.testGroup "ELF Tests" , ("MYSTUFF_1.2", True) ] ] + + , T.testGroup "Relocation entries" + [ T.testCase "PPC32 relocations" $ + testRelocEntries + (Proxy @Elf.PPC32_RelocationType) + "./tests/ppc32-relocs.elf" + [ (0x0001fecc, Elf.R_PPC_RELATIVE) + , (0x0001fed0, Elf.R_PPC_RELATIVE) + , (0x0001fed4, Elf.R_PPC_RELATIVE) + , (0x0001fed8, Elf.R_PPC_RELATIVE) + , (0x0001fedc, Elf.R_PPC_RELATIVE) + , (0x0001fee0, Elf.R_PPC_RELATIVE) + , (0x0001fee4, Elf.R_PPC_ADDR32) + , (0x0001fee8, Elf.R_PPC_RELATIVE) + , (0x0001feec, Elf.R_PPC_ADDR32) + , (0x0001fef0, Elf.R_PPC_RELATIVE) + , (0x0001fef4, Elf.R_PPC_ADDR32) + , (0x0001fef8, Elf.R_PPC_RELATIVE) + , (0x0001fefc, Elf.R_PPC_ADDR32) + , (0x0001ff00, Elf.R_PPC_RELATIVE) + , (0x0001ff04, Elf.R_PPC_ADDR32) + , (0x0001ff08, Elf.R_PPC_RELATIVE) + , (0x00020000, Elf.R_PPC_JMP_SLOT) + , (0x00020004, Elf.R_PPC_JMP_SLOT) + , (0x00020008, Elf.R_PPC_JMP_SLOT) + , (0x0002000c, Elf.R_PPC_JMP_SLOT) + , (0x00020010, Elf.R_PPC_RELATIVE) + ] + , T.testCase "PPC64 relocations" $ + testRelocEntries + (Proxy @Elf.PPC64_RelocationType) + "./tests/ppc64-relocs.elf" + [ (0x000000000001fd10, Elf.R_PPC64_RELATIVE) + , (0x000000000001fd18, Elf.R_PPC64_RELATIVE) + , (0x000000000001ff08, Elf.R_PPC64_ADDR64) + , (0x000000000001ff10, Elf.R_PPC64_ADDR64) + , (0x000000000001ff18, Elf.R_PPC64_ADDR64) + , (0x000000000001ff20, Elf.R_PPC64_ADDR64) + , (0x000000000001ff28, Elf.R_PPC64_ADDR64) + {- + These relocations (which live in the binary's .rela.plt section) + are not discovered by elf-edit. See + https://github.com/GaloisInc/elf-edit/issues/40 for a diagnosis. + -} + -- , (0x0000000000020010, Elf.R_PPC64_JMP_SLOT) + -- , (0x0000000000020018, Elf.R_PPC64_JMP_SLOT) + -- , (0x0000000000020020, Elf.R_PPC64_JMP_SLOT) + -- , (0x0000000000020028, Elf.R_PPC64_JMP_SLOT) + , (0x0000000000020030, Elf.R_PPC64_RELATIVE) + ] + ] ] main :: IO () diff --git a/tests/ppc32-relocs.c b/tests/ppc32-relocs.c new file mode 100644 index 0000000..03b2213 --- /dev/null +++ b/tests/ppc32-relocs.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/tests/ppc32-relocs.elf b/tests/ppc32-relocs.elf new file mode 100755 index 0000000000000000000000000000000000000000..2b4d8d9340bce53f59d323f9927ebbb99136c6cf GIT binary patch literal 68020 zcmeH}U2Ggz701tv*J~$n!nSOK+eENQERl$2YnxCdBq3SHP8`*C-E@Ic3X}2f*j}<< z>`uTA>vmJ8B8Y$@1s>W5%7-xGp;EQ)KIFlI3h{u_B7sztNVHOc1|l#2b7#ih zd^Dos4gHUF=ALu!x%Zy?yLaZ!Gb3Y1E!&b+>5wFBRKyY}_lVVbS){2}O1fpI+%LVT zkDE5FHLCs17%>>C9q`c>sXTx>Rc%`hh8;@RQzEL;84RP(mCIsb_g^oswH9i~1mkmb_Q=6U}KHe${)k}t+3xTwvG40T2bDcv0G}t-DbZR+6kOZm^ywJ-l3Lq()eCzVl8In z&zN8LT64pBjYammI0}({1H41Kg)`F?*ydE(_nE%7o~4e+#$55p?m@hYPg-m1;h2FM_Mb_;ct!RMSdyp{^`DySkI$>w8lk@t?ZPc?&aP2&BriiUo;=qyE7cO z6pa_{1?FGYu{8I_p$&7GR~B|WGPmy;Ni1G%-B@tHIH&WSefn%_pjKW9u5Y3E#N@#XVmEuPKXvxP^^=Wt9ZQW3PbL>m zKAFUxo4IuyaHFr67SNIwy9>Uuj{E~Kl!JwMEk}WKtgZdaA$uKf6Y8Hsd@su0F#fxUUv7(k zA>2ES$9~E$wN2%H@_h~YKB4W1Z{xHY|9h}E^=MBZ>k8Tv zY6k7r)$nY`?ltGi0^dMVrm%Dmjik)e{uEYj`Xe6evynsWFq$SqU-!sJ$~^7)mA|~#QL@=@JOlgc&_FTq;rCz z?w_8XhUqvXqt4M2neh>4Xyn-O3CEGVSMz2Hb>FKwe#yxdD`l@Pxk{;8^n5R$9zdUb z#hEEqrre^F_bau!I>JR&(bauk6?6r84yuFXyNGWxD2;JSTs;RGLTM zHqSv9|E50GYVMPRyK7#tlB=7XgM>#WhLNr_{Dq0k`0*ps57`S%&s6-ubhYR^)dKpZ z9Va*EY9em2aK^h!Sg|mbbLzfZ^PQ4gDBmTr4N;JIp*&r|DrSm>@+oI>EL-#HmEza# zHrXoU+Xuiv_@Jz9%;@k5agL2WI+Pi69zA;W@sX^P%?yo=VC_zJ{D>2BaPswvGwYV~ zMNbSvagJxlooFIN>Q-jmDQypyiT&4*wdLF#Xo=Ke%sB+Bm~Je?o&>OE=h%FAJ$25MUm^jK&Q1^24CTl>R0 z{j5ZBkHOZl@eSAe-~0pUw<{8jQ~5kJjMHzUs{N`qgaY5lm+%bZ^qZ$@{uzSSU|zLz zP>sVn^jmMf_jj82t7~yx-MFWql7&VR<@XI#=-t>6+vMr+1mT&vc(6(KyvH zXb=Z7#xmCe>_DP_N$1Sh+LF9mJ06k_P9>n!(VAbC?@Vdnnw~? literal 0 HcmV?d00001 diff --git a/tests/ppc64-relocs.c b/tests/ppc64-relocs.c new file mode 100644 index 0000000..03b2213 --- /dev/null +++ b/tests/ppc64-relocs.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/tests/ppc64-relocs.elf b/tests/ppc64-relocs.elf new file mode 100755 index 0000000000000000000000000000000000000000..b1e7d35b34c2c334d23248413ec23bf194824804 GIT binary patch literal 68848 zcmeH~U2I%O701uL{#rL5IKgdQ5|vGYs3Rp?J1Wrz64jqgqQu4xMtrE{?)C0EUb@~j zyPL)iwraZp8VXWTL4pdY1*GtT5Dy>~@nWPr6p0r^#S1TqR3uw{ze9tavv`zA}51}I4}e)iCV ztcz1?&`)eLrA|6)#;lT~iCVbYIM;M@YEx9werr%E^OD+T?M+1Ir0KBItVW)8L0erx zzf&ivrPsu@q)dPCl*wpZ+}O9aOLA@o_E1tRQ~BEj+wA&c>!!b6-m|_|j(d`Q?RX~Y zzj$_W+y(Ztzc&?$t~IYV@pst2e*Rq?*1>jR#U*yb zNa`XlSIAY!n`S|tm!9{f>F0A-vaIrErM+^+FIBu*KUW~pd9S!9lPzU0=E{|9$(t_u zvsq3v&GxgCW1ewg zCQrRR&UQJ|^>)o4+E1P*H#xNMtHqdm{fg?`qa>=S$1qq29%-Q{9V)cFfNoXn!lo<_9J0t&zsnS8m|9x zuznu9*XBE^^9k~Oy3BWdM|E@Q#ni-7>dW29oz*ut zUL=~Q%~jdsjb|t(?+Bl#KXQG8>kY1JW>23D)}V8)KWomume25r@_xJ3YV|3WXITD_ zWgl1h9*}e80=3Q$I{S787lv*&^{`Kh

RR4$@HjAh+c%(#Q6lB57!M->c5xu8)tH zAhw}^00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*>m z&lBj_G)wGA*`+#GCam0PWZQ(*cNrPGVfBXs>1=gbeV>&vD?euYd#t{{uD{jjZd_!s zdiS=~Q$|voku5J-z1>Ln1*_j@UTaWmEA>zLlv9CnzHzW3+?r~{vpx5?=Rp;e{ zHK$0+`DMgkxZC3VZf{CICE@p)*XiWq>atBbzi(`J+juf|z4mh(#5sTE{Axd9Q$5A` z-)fRaAlIKa3ANMn=o#;c3xi{$-q7gjv*VsenQSS0F;}i+OI~HxOXrJ)Y?=Ks zMekz1IOXTPOr=;Vd;X<)N*8D6^4Ur@ljv{k;Z5fXInOVZ`~@#tsFW6Hy5!Ghz09TA z*##<2eKnh|B>FfuV)i(svMpwAE`9v5qor)Vm@Wr%HWMBlAK~ft1*P9l%;hUy+Rx_` zo|n%}rM+^+FIBu*KUW}ctf>NqBr9gGI{P0Cgh!+ z9P@Nm>?vC_=}$?&SuF3TxYS19?&M9C%f^#}jUg|a@hd)yLWU?&UYM=;Q!FbbBWJXg zEAVNUqr}C+rNoS1o}ol$p}_7&R!WrM&GE%(Tf7&P2&^}Z##6!{(e6j!y|c)f?JB)xY^j1=W1?NeNJZZ=-;g(_(+;=@h-eh1^9 zj`R&lC#T!oE-58Ou6vAqTl|x3)A`sBx&AJwq)*s56*^zh<#((;epxyg*>WJLWyHwv z84p`TPjkC2Ucc)q|Ks@SNWA5zzq2auIe*dlf9>9QzH$UbB~2JTd`9EH&Q^0T(sK~r zYr_9KdR{bv>LS0z)!aX7@%DZd-m}!dQT)qn)E{7T4#Rtl-e;Vf?4$3PCWmsK3acaMgqwZ~UEbT=lPy7yaj4 zwO`}Sz10ctuSVDCn!i|n!BxlKKF?ab{$JG$>Mv4ixMFn(q(fgcddnKi2e{gO4d*Mm l+?C9{xv{M{t=8Xtc$>X8Uop!&-6X#KxQ+Xbl`3@p^lt(L244UG literal 0 HcmV?d00001