Merge remote-tracking branch 'origin/GP-3804_loongarch_relocations--SQUASHED' into Ghidra_11.0

This commit is contained in:
ghidra1 2023-12-18 12:59:18 -05:00
commit d156a09c29
2 changed files with 612 additions and 0 deletions

View File

@ -0,0 +1,156 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.elf.relocation;
public class Loongarch_ElfRelocationConstants {
public static final int R_LARCH_NONE = 0;
/* Runtime address resolving */
public static final int R_LARCH_32 = 1; // *(int32_t *) PC = RtAddr + A
public static final int R_LARCH_64 = 2; // *(int64_t *) PC = RtAddr + A
public static final int R_LARCH_RELATIVE = 3; // Runtime fixup for load-address *(void **) PC = B + A
public static final int R_LARCH_COPY = 4; // Runtime memory copy in executable memcpy (PC, RtAddr, sizeof (sym))
public static final int R_LARCH_JUMP_SLOT = 5; // Runtime PLT supporting (implementation defined)
/* Runtime relocations for TLS-GD */
public static final int R_LARCH_TLS_DTPMOD32 = 6; // *(int32_t *) PC = ID of module defining sym
public static final int R_LARCH_TLS_DTPMOD64 = 7; // *(int64_t *) PC = ID of module defining sym
public static final int R_LARCH_TLS_DTPREL32 = 8; // *(int32_t *) PC = DTV-relative offset for sym
public static final int R_LARCH_TLS_DTPREL64 = 9; // *(int64_t *) PC = DTV-relative offset for sym
/* Runtime relocations for TLE-IE */
public static final int R_LARCH_TLS_TPREL32 = 10; // *(int32_t *) PC = T
public static final int R_LARCH_TLS_TPREL64 = 11; // *(int64_t *) PC = T
public static final int R_LARCH_IRELATIVE = 12; /* Runtime local indirect function resolving
*(void **) PC = (((void *)(*)()) (B + A)) () */
/* Relocations 13..19 reserved for dynamic linker */
public static final int R_LARCH_MARK_LA = 20; // Mark la.abs Load absolute address for static link.
public static final int R_LARCH_MARK_PCREL = 21; // Mark external label branch Access PC relative address for static link.
public static final int R_LARCH_SOP_PUSH_PCREL = 22; // Push PC-relative offset push (S - PC + A)
public static final int R_LARCH_SOP_PUSH_ABSOLUTE = 23; // Push constant or absolute address push (S + A)
public static final int R_LARCH_SOP_PUSH_DUP = 24; // Duplicate stack top opr1 = pop (), push (opr1), push (opr1)
public static final int R_LARCH_SOP_PUSH_GPREL = 25; // Push for access GOT entry push (G)
public static final int R_LARCH_SOP_PUSH_TLS_TPREL = 26; // Push for TLS-LE push (T)
public static final int R_LARCH_SOP_PUSH_TLS_GOT = 27; // Push for TLS-IE push (IE)
public static final int R_LARCH_SOP_PUSH_TLS_GD = 28; // Push for TLS-GD push (GD)
public static final int R_LARCH_SOP_PUSH_PLT_PCREL = 29; // Push for external function calling push (PLT - PC)
public static final int R_LARCH_SOP_ASSERT = 30; // Assert stack top assert (pop ())
/* Stack top operations */
public static final int R_LARCH_SOP_NOT = 31;
public static final int R_LARCH_SOP_SUB = 32;
public static final int R_LARCH_SOP_SL = 33;
public static final int R_LARCH_SOP_SR = 34;
public static final int R_LARCH_SOP_ADD = 35;
public static final int R_LARCH_SOP_AND = 36;
public static final int R_LARCH_SOP_IF_ELSE = 37;
/* Instruction imm-field relocation */
public static final int R_LARCH_SOP_POP_32_S_10_5 = 38;
public static final int R_LARCH_SOP_POP_32_U_10_12 = 39;
public static final int R_LARCH_SOP_POP_32_S_10_12 = 40;
public static final int R_LARCH_SOP_POP_32_S_10_16 = 41;
public static final int R_LARCH_SOP_POP_32_S_10_16_S2 = 42;
public static final int R_LARCH_SOP_POP_32_S_5_20 = 43;
public static final int R_LARCH_SOP_POP_32_S_0_5_10_16_S2 = 44;
public static final int R_LARCH_SOP_POP_32_S_0_10_10_16_S2 = 45;
/* Instruction fixup */
public static final int R_LARCH_SOP_POP_32_U = 46;
/* n-bit in-place additions */
public static final int R_LARCH_ADD8 = 47;
public static final int R_LARCH_ADD16 = 48;
public static final int R_LARCH_ADD24 = 49;
public static final int R_LARCH_ADD32 = 50;
public static final int R_LARCH_ADD64 = 51;
/* n-bit in-place subtractions */
public static final int R_LARCH_SUB8 = 52;
public static final int R_LARCH_SUB16 = 53;
public static final int R_LARCH_SUB24 = 54;
public static final int R_LARCH_SUB32 = 55;
public static final int R_LARCH_SUB64 = 56;
public static final int R_LARCH_GNU_VTINHERIT = 57; // GNU C++ vtable hierarchy
public static final int R_LARCH_GNU_VTENTRY = 58; // GNU C++ vtable member usage
/* 59..63 reserved */
/* n-bit relative jumps */
public static final int R_LARCH_B16 = 64;
public static final int R_LARCH_B21 = 65;
public static final int R_LARCH_B26 = 66;
public static final int R_LARCH_ABS_HI20 = 67; // [31 12] bits of 32/64-bit absolute address
public static final int R_LARCH_ABS_LO12 = 68; // [11 0] bits of 32/64-bit absolute address
public static final int R_LARCH_ABS64_LO20 = 69; // [51 32] bits of 64-bit absolute address
public static final int R_LARCH_ABS64_HI12 = 70; // [63 52] bits of 64-bit absolute address
public static final int R_LARCH_PCALA_HI20 = 71; // [31 12] bits of 32/64-bit PC-relative offset
public static final int R_LARCH_PCALA_LO12 = 72; // [11 0] bits of 32/64-bit address
public static final int R_LARCH_PCALA64_LO20 = 73; // [51 32] bits of 64-bit PC-relative offset
public static final int R_LARCH_PCALA64_HI12 = 74; // [63 52] bits of 64-bit PC-relative offset
public static final int R_LARCH_GOT_PC_HI20 = 75; // [31 12] bits of 32/64-bit PC-relative offset to GOT entry
public static final int R_LARCH_GOT_PC_LO12 = 76; // [11 0] bits of 32/64-bit GOT entry address
public static final int R_LARCH_GOT64_PC_LO20 = 77; // [51 32] bits of 64-bit PC-relative offset to GOT entry
public static final int R_LARCH_GOT64_PC_HI12 = 78; // [63 52] bits of 64-bit PC-relative offset to GOT entry
public static final int R_LARCH_GOT_HI20 = 79; // [31 12] bits of 32/64-bit GOT entry absolute address
public static final int R_LARCH_GOT_LO12 = 80; // [11 0] bits of 32/64-bit GOT entry absolute address
public static final int R_LARCH_GOT64_LO20 = 81; // [51 32] bits of 64-bit GOT entry absolute address
public static final int R_LARCH_GOT64_HI12 = 82; // [63 52] bits of 64-bit GOT entry absolute address
public static final int R_LARCH_TLS_LE_HI20 = 83; // [31 12] bits of TLS LE 32/64-bit offset from TP register
public static final int R_LARCH_TLS_LE_LO12 = 84; // [11 0] bits of TLS LE 32/64-bit offset from TP register
public static final int R_LARCH_TLS_LE64_LO20 = 85; // [51 32] bits of TLS LE 64-bit offset from TP register
public static final int R_LARCH_TLS_LE64_HI12 = 86; // [63 52] bits of TLS LE 64-bit offset from TP register
public static final int R_LARCH_TLS_IE_PC_HI20 = 87; // [31 12] bits of 32/64-bit PC-relative offset to TLS IE GOT entry
public static final int R_LARCH_TLS_IE_PC_LO12 = 88; // [11 0] bits of 32/64-bit TLS IE GOT entry address
public static final int R_LARCH_TLS_IE64_PC_LO20 = 89; // [51 32] bits of 64-bit PC-relative offset to TLS IE GOT entry
public static final int R_LARCH_TLS_IE64_PC_HI12 = 90; // [63 52] bits of 64-bit PC-relative offset to TLS IE GOT entry
public static final int R_LARCH_TLS_IE_HI20 = 91; // [31 12] bits of 32/64-bit TLS IE GOT entry absolute address
public static final int R_LARCH_TLS_IE_LO12 = 92; // [11 0] bits of 32/64-bit TLS IE GOT entry absolute address
public static final int R_LARCH_TLS_IE64_LO20 = 93; // [51 32] bits of 64-bit TLS IE GOT entry absolute address
public static final int R_LARCH_TLS_IE64_HI12 = 94; // [63 52] bits of 64-bit TLS IE GOT entry absolute address
public static final int R_LARCH_TLS_LD_PC_HI20 = 95; // [31 12] bits of 32/64-bit PC-relative offset to TLS LD GOT entry
public static final int R_LARCH_TLS_LD_HI20 = 96; // [31 12] bits of 32/64-bit TLS LD GOT entry absolute address
public static final int R_LARCH_TLS_GD_PC_HI20 = 97; // [31 12] bits of 32/64-bit PC-relative offset to TLS GD GOT entry
public static final int R_LARCH_TLS_GD_HI20 = 98; // [31 12] bits of 32/64-bit TLS GD GOT entry absolute address
public static final int R_LARCH_32_PCREL = 99; // 32-bit PC relative
public static final int R_LARCH_RELAX = 100; // Instruction can be relaxed, paired with a normal relocation at the same address
// The following are from binutils and not found in the official Loongarch documentation
public static final int R_LARCH_DELETE = 101; // relax delete
public static final int R_LARCH_ALIGN = 102; // relax delete
public static final int R_LARCH_PCREL20_S2 = 103; // pcaddi
public static final int R_LARCH_CFA = 104; // relax delete
public static final int R_LARCH_ADD6 = 105; // relax delete
public static final int R_LARCH_SUB6 = 106; // pcaddi
public static final int R_LARCH_ADD_ULEB128 = 107; // relax delete
public static final int R_LARCH_SUB_ULEB128 = 108; // relax delete
public static final int R_LARCH_64_PCREL = 109; // pcaddi
private Loongarch_ElfRelocationConstants() {
// no construct
}
}

View File

@ -0,0 +1,456 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public boolean canRelocate(ElfHeader elf) {
return elf.e_machine() == ElfConstants.EM_LOONGARCH;
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (!canRelocate(elf)) {
return RelocationResult.FAILURE;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
boolean is32 = elf.is32Bit();
int type = relocation.getType();
if (Loongarch_ElfRelocationConstants.R_LARCH_NONE == type) {
return RelocationResult.SKIPPED;
}
long addend = relocation.hasAddend() ? relocation.getAddend() : is32 ? memory.getInt(relocationAddress) : memory.getLong(relocationAddress);
long offset = relocationAddress.getOffset();
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long value64 = 0;
int value32 = 0;
short value16 = 0;
byte value8 = 0;
byte[] bytes24 = new byte[3];
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case Loongarch_ElfRelocationConstants.R_LARCH_32:
// Runtime address resolving *(int32_t *) PC = RtAddr + A
value32 = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value32);
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
warnExternalOffsetRelocation(program, relocationAddress,
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
if (elf.is32Bit()) {
applyComponentOffsetPointer(program, relocationAddress, addend);
}
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_64:
// Runtime address resolving *(int64_t *) PC = RtAddr + A
value64 = symbolValue + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
warnExternalOffsetRelocation(program, relocationAddress,
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
if (elf.is64Bit()) {
applyComponentOffsetPointer(program, relocationAddress, addend);
}
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_RELATIVE:
// Runtime fixup for load-address *(void **) PC = B + A
if (is32) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
else {
value64 = base + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_COPY:
// Runtime memory copy in executable memcpy (PC, RtAddr, sizeof (sym))
markAsWarning(program, relocationAddress, "R_LARCH_COPY", symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_JUMP_SLOT:
// Runtime PLT supporting (implementation-defined)
if (is32) {
value32 = (int) (symbolValue);
memory.setInt(relocationAddress, value32);
}
else {
value64 = symbolValue;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPMOD32:
// TLS relocation word32 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPMOD32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPMOD64:
// TLS relocation word64 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPMOD64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPREL32:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPREL32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPREL64:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPREL64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_TPREL32:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTREL32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_TPREL64:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_TPREL64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_IRELATIVE:
if (is32) {
value32 = (int) ( addend + elfRelocationContext.getImageBaseWordAdjustmentOffset());
memory.setInt(relocationAddress, value32);
}
else {
byteLength = 8;
value64 = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value64);
}
break;
// case Loongarch_ElfRelocationConstants.R_LARCH_MARK_LA:
// case Loongarch_ElfRelocationConstants.R_LARCH_MARK_PCREL:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_PCREL:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_ABSOLUTE:
// PC-relative GOT reference MACRO la
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_DUP:
// PC-relative TLS IE GOT offset MACRO la.tls.ie
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_GPREL:
// PC-relative TLS GD reference MACRO la.tls.gd
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_TPREL:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_GOT:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_GD:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_PLT_PCREL:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_ASSERT:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_NOT:
// Absolute address %lo(symbol) (S-Type)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SUB:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SL:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SR:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_ADD:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_AND:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_IF_ELSE:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_5:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_U_10_12:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_12:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_16:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_5_20:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_U:
// TLS LE thread usage %tprel_add(symbol)
case Loongarch_ElfRelocationConstants.R_LARCH_ADD8:
// 8-bit in-place addition *(int8_t *) PC += S + A
value8 = memory.getByte(relocationAddress);
value8 += (byte) symbolValue;
value8 += (byte) addend;
memory.setByte(relocationAddress, value8);
byteLength = 1;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD16:
// 16-bit in-place addition *(int16_t *) PC += S + A
value16 = memory.getShort(relocationAddress);
value16 += (short) symbolValue;
value16 += (short) addend;
memory.setShort(relocationAddress, value16);
byteLength = 2;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD24:
// 24-bit in-place addition (int24_t *) PC += S + A
memory.getBytes(relocationAddress, bytes24);
value32 = ((bytes24[2] << 8) + bytes24[1] ) << 8 + bytes24[0];
value32 += (int) symbolValue;
value32 += (int) addend;
bytes24[0] = (byte) value32;
bytes24[1] = (byte) (value32 >> 8);
bytes24[2] = (byte) (value32 >> 16);
memory.setBytes(relocationAddress, bytes24);
byteLength = 3;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD32:
// 32-bit in-place addition *(int32_t *) PC += S + A
value32 = memory.getInt(relocationAddress);
value32 += (int) symbolValue;
value32 += (int) addend;
memory.setInt(relocationAddress, value32);
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD64:
// 64-bit in-place addition *(int64_t *) PC += S + A
value64 = memory.getLong(relocationAddress);
value64 += symbolValue;
value64 += addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB8:
// 8-bit in-place subtraction *(int8_t *) PC -= S + A
value8 = memory.getByte(relocationAddress);
value8 -= (byte) symbolValue;
value8 -= (byte) addend;
memory.setByte(relocationAddress, value8);
byteLength = 1;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB16:
// 16-bit in-place subtraction *(int16_t *) PC -= S + A
value16 = memory.getShort(relocationAddress);
value16 -= (short) symbolValue;
value16 -= (short) addend;
memory.setShort(relocationAddress, value16);
byteLength = 2;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB24:
// 24-bit in-place subtraction *(int324_t *) PC -= S + A
memory.getBytes(relocationAddress, bytes24);
value32 = ((bytes24[2] << 8) + bytes24[1] ) << 8 + bytes24[0];
value32 -= (int) symbolValue;
value32 -= (int) addend;
bytes24[0] = (byte) value32;
bytes24[1] = (byte) (value32 >> 8);
bytes24[2] = (byte) (value32 >> 16);
memory.setBytes(relocationAddress, bytes24);
byteLength = 3;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB32:
// 32-bit in-place subtraction *(int32_t *) PC -= S + A
value32 = memory.getInt(relocationAddress);
value32 -= (int) symbolValue;
value32 -= (int) addend;
memory.setInt(relocationAddress, value32);
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB64:
// 64-bit in-place subtraction *(int64_t *) PC -= S + A
value64 = memory.getLong(relocationAddress);
value64 -= symbolValue;
value64 -= addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
break;
// case Loongarch_ElfRelocationConstants.R_LARCH_GNU_VTINHERIT:
// GNU C++ vtable hierarchy
// case Loongarch_ElfRelocationConstants.R_LARCH_GNU_VTENTRY:
// GNU C++ vtable member usage
// case Loongarch_ElfRelocationConstants.R_LARCH_B16:
// case Loongarch_ElfRelocationConstants.R_LARCH_B21:
// case Loongarch_ElfRelocationConstants.R_LARCH_B26:
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS64_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS64_HI12:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA64_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA64_HI12:
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT_PC_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT_PC_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT64_PC_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT64_HI12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE64_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE64_HI12:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_PC_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_PC_LO20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_PC_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_LO20:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LD_PC_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_GD_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_GD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_32_PCREL:
// 32-bit PC relative
// case Loongarch_ElfRelocationConstants.R_LARCH_RELAX:
// case Loongarch_ElfRelocationConstants.R_LARCH_DELETE:
// case Loongarch_ElfRelocationConstants.R_LARCH_ALIGN:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCREL20_S2:
// case Loongarch_ElfRelocationConstants.R_LARCH_CFA:
// case Loongarch_ElfRelocationConstants.R_LARCH_ADD6:
// case Loongarch_ElfRelocationConstants.R_LARCH_SUB6:
// case Loongarch_ElfRelocationConstants.R_LARCH_ADD_ULEB128:
// case Loongarch_ElfRelocationConstants.R_LARCH_SUB_ULEB128:
// case Loongarch_ElfRelocationConstants.R_LARCH_64_PCREL:
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
return new RelocationResult(Status.APPLIED, byteLength);
}
}