-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
{- | ||
Copyright : (c) Galois, Inc 2024 | ||
Maintainer : Ryan Scott <rscott@galois.com> | ||
RISC-V relocation types. The list of relocation types is taken from Table 3 | ||
(Relocation types) of | ||
<https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/17038f12910bf6e0bc8bb12d3a2d09dce3f9152a/riscv-elf.adoc#relocations>. | ||
-} | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE PatternGuards #-} | ||
{-# LANGUAGE PatternSynonyms #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
{-# LANGUAGE StandaloneDeriving #-} | ||
{-# LANGUAGE TypeApplications #-} | ||
{-# LANGUAGE TypeFamilies #-} | ||
{-# LANGUAGE TypeOperators #-} | ||
{-# LANGUAGE UndecidableInstances #-} | ||
module Data.ElfEdit.Relocations.RISCV | ||
( RISCV_RelocationType(..) | ||
, pattern R_RISCV_NONE | ||
, pattern R_RISCV_32 | ||
, pattern R_RISCV_64 | ||
, pattern R_RISCV_RELATIVE | ||
, pattern R_RISCV_COPY | ||
, pattern R_RISCV_JUMP_SLOT | ||
-- TODO RGS: Fill in the rest | ||
, riscv_RelocationTypes | ||
) where | ||
|
||
import qualified Data.Map.Strict as Map | ||
import Data.Proxy (Proxy(..)) | ||
import Data.Type.Equality ((:~:)(..)) | ||
import GHC.TypeLits (KnownNat, natVal, sameNat) | ||
|
||
import Data.ElfEdit.Prim.Ehdr (ElfClass(..), ElfWidthConstraints, ElfWordType) | ||
import Data.ElfEdit.Relocations.Common | ||
import Data.ElfEdit.Utils (ppHex) | ||
|
||
------------------------------------------------------------------------ | ||
-- RISCV_RelocationType | ||
|
||
-- | Relocation types for RISC-V code. The @w@ type parameter represents the | ||
-- word size (@32@ for ILP32 and @64@ for LP64). | ||
newtype RISCV_RelocationType w = RISCV_RelocationType { fromRISCV_RelocationType :: ElfWordType w } | ||
deriving instance Eq (ElfWordType w) => Eq (RISCV_RelocationType w) | ||
deriving instance Ord (ElfWordType w) => Ord (RISCV_RelocationType w) | ||
|
||
-- These values are derived from Table 3 (Relocation types) of | ||
-- https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/17038f12910bf6e0bc8bb12d3a2d09dce3f9152a/riscv-elf.adoc#relocations. | ||
|
||
pattern R_RISCV_NONE :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_NONE = RISCV_RelocationType 0 | ||
|
||
pattern R_RISCV_32 :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_32 = RISCV_RelocationType 1 -- S + A | ||
|
||
pattern R_RISCV_64 :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_64 = RISCV_RelocationType 2 -- S + A | ||
|
||
pattern R_RISCV_RELATIVE :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_RELATIVE = RISCV_RelocationType 3 -- B + A | ||
|
||
pattern R_RISCV_COPY :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_COPY = RISCV_RelocationType 4 | ||
|
||
pattern R_RISCV_JUMP_SLOT :: (Eq (ElfWordType w), Num (ElfWordType w)) | ||
=> RISCV_RelocationType w | ||
pattern R_RISCV_JUMP_SLOT = RISCV_RelocationType 5 -- S | ||
|
||
-- TODO RGS: Fill in the rest | ||
|
||
riscvReloc :: RISCV_RelocationType w | ||
-> String | ||
-> Int | ||
-> (RISCV_RelocationType w, (String,Int)) | ||
riscvReloc tp nm c = (tp, (nm, c)) | ||
|
||
-- These values are derived from Table 5 (Variables used in relocation fields) of | ||
-- https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/17038f12910bf6e0bc8bb12d3a2d09dce3f9152a/riscv-elf.adoc#relocations. | ||
-- | ||
-- Note that the treatment of `TODO RGS` here is not correct. See | ||
-- https://github.com/GaloisInc/elf-edit/issues/39 for more information. | ||
|
||
none :: Int | ||
none = 0 | ||
|
||
word6 :: Int | ||
word6 = 6 | ||
Check failure on line 95 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
word8 :: Int | ||
word8 = 8 | ||
Check failure on line 98 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
word16 :: Int | ||
word16 = 16 | ||
Check failure on line 101 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
word32 :: Int | ||
word32 = 32 | ||
|
||
word64 :: Int | ||
word64 = 64 | ||
|
||
uleb :: Int | ||
uleb = error "TODO RGS" | ||
Check failure on line 110 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
bType :: Int | ||
bType = error "TODO RGS" | ||
Check failure on line 113 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
cbType :: Int | ||
cbType = error "TODO RGS" | ||
Check failure on line 116 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
ciType :: Int | ||
ciType = error "TODO RGS" | ||
Check failure on line 119 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
cjType :: Int | ||
cjType = error "TODO RGS" | ||
Check failure on line 122 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
iType :: Int | ||
iType = error "TODO RGS" | ||
Check failure on line 125 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
sType :: Int | ||
sType = error "TODO RGS" | ||
Check failure on line 128 in src/Data/ElfEdit/Relocations/RISCV.hs
|
||
|
||
uType :: Int | ||
uType = error "TODO RGS" | ||
|
||
jType :: Int | ||
jType = error "TODO RGS" | ||
|
||
uiType :: Int | ||
uiType = error "TODO RGS" | ||
|
||
-- This map is derived from Table 3 (Relocation types) of | ||
-- https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/17038f12910bf6e0bc8bb12d3a2d09dce3f9152a/riscv-elf.adoc#relocations. | ||
|
||
riscv_RelocationTypes :: | ||
forall w. | ||
(ElfWidthConstraints w, KnownNat w) => | ||
Map.Map (RISCV_RelocationType w) (String, Int) | ||
riscv_RelocationTypes = Map.fromList | ||
[ riscvReloc R_RISCV_NONE "R_RISCV_NONE" none | ||
, riscvReloc R_RISCV_32 "R_RISCV_32" word32 | ||
, riscvReloc R_RISCV_64 "R_RISCV_64" word64 | ||
, riscvReloc R_RISCV_RELATIVE "R_RISCV_RELATIVE" wordclass | ||
, riscvReloc R_RISCV_COPY "R_RISCV_COPY" none | ||
, riscvReloc R_RISCV_JUMP_SLOT "R_RISCV_JUMP_SLOT" wordclass | ||
-- TODO RGS: Fill in the rest | ||
] | ||
where | ||
wordclass :: Int | ||
wordclass = withRiscvWordSize (Proxy @w) word32 word64 | ||
|
||
instance (ElfWidthConstraints w, KnownNat w) => Show (RISCV_RelocationType w) where | ||
show i = | ||
case Map.lookup i riscv_RelocationTypes of | ||
Just (s,_) -> s | ||
Nothing -> ppHex (fromRISCV_RelocationType i) | ||
|
||
instance (ElfWidthConstraints w, KnownNat w) => IsRelocationType (RISCV_RelocationType w) where | ||
type RelocationWidth (RISCV_RelocationType w) = w | ||
|
||
relaWidth _ = withRiscvWordSize (Proxy @w) ELFCLASS32 ELFCLASS64 | ||
|
||
toRelocType = RISCV_RelocationType . fromIntegral | ||
|
||
isRelative R_RISCV_RELATIVE = True | ||
isRelative _ = False | ||
|
||
relocTargetBits tp = | ||
case Map.lookup tp riscv_RelocationTypes of | ||
Just (_,w) -> w | ||
Nothing -> fromInteger $ natVal $ Proxy @w | ||
|
||
-- We only support 32-bit and 64-bit RISC-V. This is a helper function for | ||
-- dispatching on the RISC-V word size, with each continuation having type-level | ||
-- evidence that the word size is equal to either 32 or 64. | ||
withRiscvWordSize :: KnownNat n => proxy n -> ((n ~ 32) => r) -> ((n ~ 64) => r) -> r | ||
withRiscvWordSize proxy k32 k64 | ||
| Just Refl <- sameNat proxy (Proxy @32) | ||
= k32 | ||
| Just Refl <- sameNat proxy (Proxy @64) | ||
= k64 | ||
| otherwise | ||
= error $ "Unsupported RISC-V word size: " ++ show (natVal proxy) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
int main(void) { | ||
return 0; | ||
} |