35 lines
1.2 KiB
Go
35 lines
1.2 KiB
Go
package arm64
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
|
|
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
|
)
|
|
|
|
// ResolveRelocations implements backend.Machine ResolveRelocations.
|
|
//
|
|
// TODO: unit test!
|
|
func (m *machine) ResolveRelocations(refToBinaryOffset map[ssa.FuncRef]int, binary []byte, relocations []backend.RelocationInfo) {
|
|
for _, r := range relocations {
|
|
instrOffset := r.Offset
|
|
calleeFnOffset := refToBinaryOffset[r.FuncRef]
|
|
brInstr := binary[instrOffset : instrOffset+4]
|
|
diff := int64(calleeFnOffset) - (instrOffset)
|
|
// Check if the diff is within the range of the branch instruction.
|
|
if diff < -(1<<25)*4 || diff > ((1<<25)-1)*4 {
|
|
panic(fmt.Sprintf("TODO: too large binary where branch target is out of the supported range +/-128MB: %#x", diff))
|
|
}
|
|
// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/BL--Branch-with-Link-
|
|
imm26 := diff / 4
|
|
brInstr[0] = byte(imm26)
|
|
brInstr[1] = byte(imm26 >> 8)
|
|
brInstr[2] = byte(imm26 >> 16)
|
|
if diff < 0 {
|
|
brInstr[3] = (byte(imm26 >> 24 & 0b000000_01)) | 0b100101_10 // Set sign bit.
|
|
} else {
|
|
brInstr[3] = (byte(imm26 >> 24 & 0b000000_01)) | 0b100101_00 // No sign bit.
|
|
}
|
|
}
|
|
}
|