Skip to content

Commit

Permalink
RISC-V: add R_RISCV_GOT_HI20 relocation
Browse files Browse the repository at this point in the history
This commit adds `R_RISCV_GOT_HI20` relocation class and fixes
`R_RISCV_PCREL_LO12_*` to also work with it. This allows consumers to
generate GOT access for external symbols.
  • Loading branch information
janvrany committed Nov 28, 2024
1 parent e958a0f commit cebbde2
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 6 deletions.
83 changes: 83 additions & 0 deletions src/ArchC-RISCV/R_RISCV_GOT_HI20.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
Class {
#name : #'R_RISCV_GOT_HI20',
#superclass : #AcRelocation,
#pools : [
'AcIntLimits',
'AcRISCVISALimits'
],
#category : #'ArchC-RISCV-Relocations'
}

{ #category : #queries }
R_RISCV_GOT_HI20 class >> isValidForInstruction: insn [
^ insn format name = 'Type_U'
]

{ #category : #'processing - simplified' }
R_RISCV_GOT_HI20 >> fixup: memory at: address with: value [
| code imms |

imms := ByteArray new: 4.
imms unsignedLongAt: 1 put: (value << RISCV_BIGIMM_SHIFT) & UINT32_MAX.

code := memory copyFrom: address to: address + 4"U-type" - 1.
code := code bitOr: imms.
memory replaceFrom: address to: address + 4"U-Type" - 1 with: code.
"
AcProcessorDescriptions riscv64 decode: code
"
]

{ #category : #processing }
R_RISCV_GOT_HI20 >> fixup: memory symbols: symbols relocations: relocations [
"
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#relocations
High 20 bits of 32-bit PC-relative GOT access, %got_pcrel_hi(symbol)
NOTE: when calculating value, we have to ask for GOT entry address,
hence we cannot use simplified processing and have to override
this method.
"

| g a p v hi20 lo12 |

(symbols includesKey: symbol) ifFalse: [
AcRelocationSymbolUnresolved new
relocation: self;
signal: 'Relocation symbol is unresolved (symbol address is not known)'.
^ self
].
(relocations includesKey: self) ifFalse: [
AcRelocationFailed new
relocation: self;
signal: 'Relocation position is not known!'. "This should not happen!"
^ self
].


g := (AcRelocationRequestGOTEntry query:self) value.
a := addend.
p := relocations at: self.

v := g + a - p.
(v between: INT32_MIN and: INT32_MAX) ifFalse: [
AcRelocationOverflow new
relocation: self;
signal: 'GOT entry out of range!'.
^ self
].


hi20 := v & (UINT32_MAX >> RISCV_IMM_BITS << RISCV_IMM_BITS).
lo12 := v & (UINT32_MAX << RISCV_IMM_BITS) bitInvert32.

(lo12 & (1 << (RISCV_IMM_BITS - 1))) ~~ 0 ifTrue: [
hi20 := hi20 + (1 << RISCV_IMM_BITS).
].
"This is PITA! Here we have to convert unsigned
hi and lo to signed values!"
hi20 := hi20 > INT32_MAX ifTrue: [ hi20 - (1 << 32) ] ifFalse: [ hi20 ].

self fixup: memory at: p with: (hi20 >> (32 - RISCV_BIGIMM_BITS) )
]
21 changes: 15 additions & 6 deletions src/ArchC-RISCV/R_RISCV_PCREL_LO12.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ R_RISCV_PCREL_LO12 >> fixup: memory symbols: symbols relocations: relocations [
position of corresponding R_RISCV_*_HI20 relocation, hence we cannot
use simplified processing and have to override this method.
"
| hi20reloc s a p v lo12 |
| hi20reloc s g a p v lo12 |

(symbols includesKey: symbol) ifFalse: [
"This is a failure because the real symbol is the one associated with
Expand All @@ -68,7 +68,7 @@ R_RISCV_PCREL_LO12 >> fixup: memory symbols: symbols relocations: relocations [
signal: 'Invalid ', self class name , ' relocation, no corresponding R_RISCV_*_HI20 Relocation!'. "This should not happen!"
^ self
].
hi20reloc class ~~ R_RISCV_PCREL_HI20 ifTrue: [
({ R_RISCV_PCREL_HI20 . R_RISCV_GOT_HI20 } includes: hi20reloc class) ifFalse: [
AcRelocationFailed new
relocation: self;
signal: 'Invalid ', self class name , ' relocation, must be paired with R_RISCV_*_HI20 Relocation!'. "This should not happen!"
Expand All @@ -81,11 +81,20 @@ R_RISCV_PCREL_LO12 >> fixup: memory symbols: symbols relocations: relocations [
^ self
].

s := symbols at: hi20reloc symbol. "Value of the symbol in the symbol table"
a := hi20reloc addend. "Addend field in the relocation entry associated with the symbol"
p := relocations at: hi20reloc. "Position of the relocation"
hi20reloc class == R_RISCV_GOT_HI20 ifTrue: [
g := (AcRelocationRequestGOTEntry query:hi20reloc) value. "Position of GOT entry (G + GOT in spec)"
a := hi20reloc addend. "Addend field in the relocation entry associated with the symbol"
p := relocations at: hi20reloc. "Position of the relocation"

v := g + a - p.
] ifFalse: [
s := symbols at: hi20reloc symbol. "Value of the symbol in the symbol table"
a := hi20reloc addend. "Addend field in the relocation entry associated with the symbol"
p := relocations at: hi20reloc. "Position of the relocation"

v := s + a - p.
].

v := s + a - p.

(v between: INT32_MIN and: INT32_MAX) ifFalse:[
AcRelocationOverflow new
Expand Down

0 comments on commit cebbde2

Please sign in to comment.