diff --git a/src/ArchC-Core/AcRelocation.class.st b/src/ArchC-Core/AcRelocation.class.st index b902b84..68f91fa 100644 --- a/src/ArchC-Core/AcRelocation.class.st +++ b/src/ArchC-Core/AcRelocation.class.st @@ -59,6 +59,11 @@ AcRelocation >> address: anIntegerOrNil [ address := anIntegerOrNil. ] +{ #category : #processing } +AcRelocation >> calculate: finalAddress [ + self subclassResponsibility +] + { #category : #'printing & storing' } AcRelocation >> disassembleOn: aStream [ aStream nextPutAll: self class name. @@ -72,6 +77,16 @@ AcRelocation >> disassembleOn: aStream [ ]. ] +{ #category : #processing } +AcRelocation >> fixupBinaryCode: memory finalAddress: finalAddress [ + self fixupBinaryCode: memory value: (self calculate: finalAddress). +] + +{ #category : #processing } +AcRelocation >> fixupBinaryCode: memory value: value [ + self subclassResponsibility +] + { #category : #processing } AcRelocation >> fixupCode: bytes address: finalAddress [ self subclassResponsibility diff --git a/src/ArchC-Core/ByteArray.extension.st b/src/ArchC-Core/ByteArray.extension.st index 385e14e..fae99dc 100644 --- a/src/ArchC-Core/ByteArray.extension.st +++ b/src/ArchC-Core/ByteArray.extension.st @@ -1,5 +1,35 @@ Extension { #name : #ByteArray } +{ #category : #'*ArchC-Core' } +ByteArray >> bitAnd: aByteArray [ + | answer | + + answer := self copy. + 1 to: (self size min: aByteArray size) do: [ :i | + answer at: i put: ((self at: i) bitAnd: (aByteArray at: i)) + ]. + ^ answer + + " + #[0 255 0 255] bitAnd: #[255 0 255 0] + " +] + +{ #category : #'*ArchC-Core' } +ByteArray >> bitOr: aByteArray [ + | answer | + + answer := self copy. + 1 to: (self size min: aByteArray size) do: [ :i | + answer at: i put: ((self at: i) bitOr: (aByteArray at: i)) + ]. + ^ answer + + " + #[0 255 0 255] bitOr: #[255 0 255 0] + " +] + { #category : #'*ArchC-Core' } ByteArray >> toBitVector: xlen endian: endian startingAt: startIndex [ self assert: (xlen \\ 8) == 0. diff --git a/src/ArchC-RISCV/R_RISCV_CALL_PLT.class.st b/src/ArchC-RISCV/R_RISCV_CALL_PLT.class.st new file mode 100644 index 0000000..6cdc245 --- /dev/null +++ b/src/ArchC-RISCV/R_RISCV_CALL_PLT.class.st @@ -0,0 +1,59 @@ +Class { + #name : #'R_RISCV_CALL_PLT', + #superclass : #AcRelocation, + #pools : [ + 'AcIntLimits', + 'AcRISCVISALimits' + ], + #category : #'ArchC-RISCV-Relocations' +} + +{ #category : #queries } +R_RISCV_CALL_PLT class >> isValidForInstruction: insn [ + ^ insn name = 'auipc' +] + +{ #category : #processing } +R_RISCV_CALL_PLT >> calculate: finalAddress [ + " + S + A - P + + S = finalAddress # Value of the symbol in the symbol table + A = addend # Addend field in the relocation entry associated with the symbol + P = address # Position of the relocation + + See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#relocations + " + + | value | + + value := finalAddress + addend - address. + (value between: INT32_MIN and: INT32_MAX) ifFalse:[ + "We better throw OverflowError but it does not exist in Pharo, sign" + self error: 'Relocated value overflow / underflow'. + ]. + ^ value +] + +{ #category : #processing } +R_RISCV_CALL_PLT >> fixupBinaryCode: memory value: value [ + | lo hi code imms | + + lo := value & (16rFFFFFFFF << RISCV_IMM_BITS) bitInvert32. + hi := value & (16rFFFFFFFF << RISCV_IMM_BITS). + + (lo & (1 << (RISCV_IMM_BITS - 1))) ~~ 0 ifTrue: [ + hi := hi + (1 << RISCV_IMM_BITS). + ]. + + imms := ByteArray new: 8. + imms unsignedLongAt: 1 put: hi bigEndian: false. + imms unsignedLongAt: 5 put: lo << RISCV_IMM_SHIFT bigEndian: false. + + code := memory copyFrom: address to: address + 4"auipc" + 4"jalr". + code := code bitOr: imms. + memory replaceFrom: address to: address + 4"auipc" + 4"jalr" - 1 with: code. + " + AcProcessorDescriptions riscv64 decode: code + " +]