Skip to content

Commit

Permalink
Merge pull request #41 from GaloisInc/T35
Browse files Browse the repository at this point in the history
Add PPC{32,64} relocation types
  • Loading branch information
RyanGlScott authored Nov 14, 2023
2 parents 3ba7d71 + 5531161 commit fa665fa
Show file tree
Hide file tree
Showing 10 changed files with 1,028 additions and 2 deletions.
4 changes: 3 additions & 1 deletion elf-edit.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -72,4 +74,4 @@ test-suite test-elf
tasty,
tasty-hunit >= 0.10,
tasty-quickcheck,
vector
vector
6 changes: 6 additions & 0 deletions src/Data/ElfEdit/Prim.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
279 changes: 279 additions & 0 deletions src/Data/ElfEdit/Relocations/PPC32.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
{-
Copyright : (c) Galois, Inc 2023
Maintainer : Ryan Scott <rscott@galois.com>
PPC32 relocation types. The list of relocation types is taken from Section 4-14
(Relocation) of <http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf>.
-}
{-# 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
Loading

0 comments on commit fa665fa

Please sign in to comment.