mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-19 16:40:38 -09:00
GP-713 added support for ELF PowerPC R_PPC_EMB_SDA21 relocation. Also revised PowerPC cspecs in support of EABI.
This commit is contained in:
@@ -87,6 +87,9 @@
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="r1"/> <!-- stack pointer -->
|
||||
<register name="r2"/> <!-- _SDA2_BASE_ -->
|
||||
<register name="r13"/> <!-- _SDA_BASE_ -->
|
||||
<register name="r14"/>
|
||||
<register name="r15"/>
|
||||
<register name="r16"/>
|
||||
@@ -105,7 +108,8 @@
|
||||
<register name="r29"/>
|
||||
<register name="r30"/>
|
||||
<register name="r31"/>
|
||||
<register name="r1"/>
|
||||
<register name="cr2"/>
|
||||
<register name="cr3"/>
|
||||
<register name="cr4"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="r1"/> <!-- stack pointer -->
|
||||
<register name="r2"/> <!-- _SDA2_BASE_ -->
|
||||
<register name="r13"/> <!-- _SDA_BASE_ -->
|
||||
<register name="r14"/>
|
||||
<register name="r15"/>
|
||||
<register name="r16"/>
|
||||
@@ -105,7 +108,9 @@
|
||||
<register name="r29"/>
|
||||
<register name="r30"/>
|
||||
<register name="r31"/>
|
||||
<register name="r1"/>
|
||||
<register name="cr2"/>
|
||||
<register name="cr3"/>
|
||||
<register name="cr4"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
@@ -1733,12 +1733,20 @@ define pcodeop stdcixOp;
|
||||
}
|
||||
|
||||
# binutils-descr: "lq", OP(56), OP_MASK, POWER4, PPC476, {RTQ, DQ, RAQ}
|
||||
define pcodeop lqOp;
|
||||
# ISA-cmt: lq - Load Quadword
|
||||
# ISA-info: lq - Form "DQ" Page 751 Category "LSQ"
|
||||
# binutils: power4.d: +0: e0 83 00 00 lq r4,0\(r3\)
|
||||
# binutils: power4.d: +4: e0 83 00 00 lq r4,0\(r3\)
|
||||
:lq RT,A,DQ is $(NOTVLE) & OP=56 & RT & A & DQ & BITS_0_3=0 { RT = lqOp(RT,A); }
|
||||
:lq RT,A,DQ is $(NOTVLE) & OP=56 & RT & Dp & A & DQ & BITS_0_3=0 & regp [regpset = Dp+1;] {
|
||||
ea:$(REGISTER_SIZE) = A + sext(DQ:2 << 4);
|
||||
@if ENDIAN == "big"
|
||||
RT = *:$(REGISTER_SIZE) ea;
|
||||
regp = *:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE));
|
||||
@else
|
||||
RT = *:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE));
|
||||
regp = *:$(REGISTER_SIZE) ea;
|
||||
@endif
|
||||
}
|
||||
|
||||
define pcodeop lvepxOp;
|
||||
:lvepx RT,A,B is OP=31 & RT & A & B & XOP_1_10=295 & BIT_0=0 { RT = lvepxOp(RT,A,B); }
|
||||
@@ -2038,7 +2046,6 @@ define pcodeop stfdpOp;
|
||||
}
|
||||
|
||||
# binutils-descr: "stq", DSO(62,2), DS_MASK, POWER4, PPC476, {RSQ, DS, RA0}
|
||||
define pcodeop stqOp;
|
||||
# ISA-cmt: stq - Store Quadword
|
||||
# ISA-info: stq - Form "DS" Page 751 Category "LSQ"
|
||||
# binutils: power4.d: +50: f8 c7 00 02 stq r6,0\(r7\)
|
||||
@@ -2046,9 +2053,15 @@ define pcodeop stqOp;
|
||||
# binutils: power4.d: +58: f8 c7 ff f2 stq r6,-16\(r7\)
|
||||
# binutils: power4.d: +5c: f8 c7 80 02 stq r6,-32768\(r7\)
|
||||
# binutils: power4.d: +60: f8 c7 7f f2 stq r6,32752\(r7\)
|
||||
:stq S,RA_OR_ZERO,DS is $(NOTVLE) & OP=62 & S & RA_OR_ZERO & DS & BITS_0_1=2 {
|
||||
EA:$(REGISTER_SIZE) = RA_OR_ZERO + sext(DS:2 << 2);
|
||||
*:16 EA = stqOp(S,RA_OR_ZERO,DS:2);
|
||||
:stq RS,RA_OR_ZERO,DS is $(NOTVLE) & OP=62 & RS & Dp & RA_OR_ZERO & DS & BITS_0_1=2 & regp [regpset = Dp+1;] {
|
||||
ea:$(REGISTER_SIZE) = RA_OR_ZERO + sext(DS:2 << 2);
|
||||
@if ENDIAN == "big"
|
||||
*:$(REGISTER_SIZE) ea = RS;
|
||||
*:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE)) = regp;
|
||||
@else
|
||||
*:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE)) = RS;
|
||||
*:$(REGISTER_SIZE) ea = regp;
|
||||
@endif
|
||||
}
|
||||
|
||||
define pcodeop stvepxOp;
|
||||
|
||||
@@ -47,11 +47,22 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
public static final ElfDynamicType DT_PPC64_OPDSZ = new ElfDynamicType(0x70000002,
|
||||
"DT_PPC64_OPDSZ", "Specify the size of the .opd section", ElfDynamicValueType.ADDRESS);
|
||||
public static final ElfDynamicType DT_PPC64_OPT = new ElfDynamicType(0x70000003, "DT_PPC64_OPT",
|
||||
"Specify whether various optimisations are possible", ElfDynamicValueType.VALUE);
|
||||
"Specify whether various optimizations are possible", ElfDynamicValueType.VALUE);
|
||||
|
||||
// PPC64 ABI Version Flag Bits contained within ElfHeader e_flags
|
||||
private static final int EF_PPC64_ABI = 3;
|
||||
|
||||
// DT_PPC64_OPT bits
|
||||
private static final int PPC64_OPT_TLS = 1;
|
||||
private static final int PPC64_OPT_MULTI_TOC = 2;
|
||||
private static final int PPC64_OPT_LOCALENTRY = 4;
|
||||
|
||||
// ELFv2 ABI symbol st_other bits
|
||||
// STO_PPC64_LOCAL specifies the number of instructions between a
|
||||
// function's global entry point and local entry point
|
||||
private static final int STO_PPC64_LOCAL_BIT = 5;
|
||||
private static final int STO_PPC64_LOCAL_MASK = 0xE0;
|
||||
|
||||
public static final String TOC_BASE = "TOC_BASE"; // injected symbol to mark global TOC_BASE
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,6 +46,11 @@ public class PowerPC_ElfExtension extends ElfExtension {
|
||||
public static final ElfDynamicType DT_PPC_OPT = new ElfDynamicType(0x70000001, "DT_PPC_OPT",
|
||||
"Specify that tls descriptors should be optimized", ElfDynamicValueType.VALUE);
|
||||
|
||||
// ELF header flags
|
||||
private static final int EF_PPC_EMB = 0x80000000; // PowerPC embedded flag
|
||||
private static final int EF_PPC_RELOCATABLE = 0x00010000;
|
||||
private static final int EF_PPC_RELOCATABLE_LIB = 0x00008000;
|
||||
|
||||
// Program header (segment) flags
|
||||
private static final int PF_PPC_VLE = 0x10000000;
|
||||
|
||||
|
||||
@@ -122,6 +122,44 @@ public class PowerPC64_ElfRelocationConstants {
|
||||
public static final int R_PPC64_DTPREL16_HIGHEST = 105; // half16 #highest(@dtprel)
|
||||
public static final int R_PPC64_DTPREL16_HIGHESTA = 106; // half16 #highesta(@dtprel)
|
||||
|
||||
public static final int R_PPC64_PLTSEQ_NOTOC = 121;
|
||||
public static final int R_PPC64_PLTCALL_NOTOC = 122;
|
||||
public static final int R_PPC64_PCREL_OPT = 123;
|
||||
|
||||
public static final int R_PPC64_D34 = 128;
|
||||
public static final int R_PPC64_D34_LO = 129;
|
||||
public static final int R_PPC64_D34_HI30 = 130;
|
||||
public static final int R_PPC64_D34_HA30 = 131;
|
||||
public static final int R_PPC64_PCREL34 = 132;
|
||||
public static final int R_PPC64_GOT_PCREL34 = 133;
|
||||
public static final int R_PPC64_PLT_PCREL34 = 134;
|
||||
public static final int R_PPC64_PLT_PCREL34_NOTOC = 135;
|
||||
public static final int R_PPC64_ADDR16_HIGHER34 = 136;
|
||||
public static final int R_PPC64_ADDR16_HIGHERA34 = 137;
|
||||
public static final int R_PPC64_ADDR16_HIGHEST34 = 138;
|
||||
public static final int R_PPC64_ADDR16_HIGHESTA34 = 139;
|
||||
public static final int R_PPC64_REL16_HIGHER34 = 140;
|
||||
public static final int R_PPC64_REL16_HIGHERA34 = 141;
|
||||
public static final int R_PPC64_REL16_HIGHEST34 = 142;
|
||||
public static final int R_PPC64_REL16_HIGHESTA34 = 143;
|
||||
public static final int R_PPC64_D28 = 144;
|
||||
public static final int R_PPC64_PCREL28 = 145;
|
||||
public static final int R_PPC64_TPREL34 = 146;
|
||||
public static final int R_PPC64_DTPREL34 = 147;
|
||||
public static final int R_PPC64_GOT_TLSGD_PCREL34 = 148;
|
||||
public static final int R_PPC64_GOT_TLSLD_PCREL34 = 149;
|
||||
public static final int R_PPC64_GOT_TPREL_PCREL34 = 150;
|
||||
public static final int R_PPC64_GOT_DTPREL_PCREL34 = 151;
|
||||
|
||||
public static final int R_PPC64_REL16_HIGH = 240;
|
||||
public static final int R_PPC64_REL16_HIGHA = 241;
|
||||
public static final int R_PPC64_REL16_HIGHER = 242;
|
||||
public static final int R_PPC64_REL16_HIGHERA = 243;
|
||||
public static final int R_PPC64_REL16_HIGHEST = 244;
|
||||
public static final int R_PPC64_REL16_HIGHESTA = 245;
|
||||
|
||||
public static final int R_PPC64_JMP_IREL = 247;
|
||||
|
||||
// Masks for manipulating Power PC relocation targets
|
||||
public static final int PPC64_WORD32 = 0xFFFFFFFF;
|
||||
public static final int PPC64_WORD30 = 0xFFFFFFFC;
|
||||
|
||||
@@ -58,6 +58,85 @@ public class PowerPC_ElfRelocationConstants {
|
||||
public static final int R_PPC_SECTOFF_HA = 36; // half16 #ha(R + A)
|
||||
public static final int R_PPC_ADDR30 = 37; // word30 (S + A - P) >> 2
|
||||
|
||||
public static final int R_POWERPC_TLS = 67;
|
||||
public static final int R_POWERPC_DTPMOD = 68;
|
||||
public static final int R_POWERPC_TPREL16 = 69;
|
||||
public static final int R_POWERPC_TPREL16_LO = 70;
|
||||
public static final int R_POWERPC_TPREL16_HI = 71;
|
||||
public static final int R_POWERPC_TPREL16_HA = 72;
|
||||
public static final int R_POWERPC_TPREL = 73;
|
||||
public static final int R_POWERPC_DTPREL16 = 74;
|
||||
public static final int R_POWERPC_DTPREL16_LO = 75;
|
||||
public static final int R_POWERPC_DTPREL16_HI = 76;
|
||||
public static final int R_POWERPC_DTPREL16_HA = 77;
|
||||
public static final int R_POWERPC_DTPREL = 78;
|
||||
public static final int R_POWERPC_GOT_TLSGD16 = 79;
|
||||
public static final int R_POWERPC_GOT_TLSGD16_LO = 80;
|
||||
public static final int R_POWERPC_GOT_TLSGD16_HI = 81;
|
||||
public static final int R_POWERPC_GOT_TLSGD16_HA = 82;
|
||||
public static final int R_POWERPC_GOT_TLSLD16 = 83;
|
||||
public static final int R_POWERPC_GOT_TLSLD16_LO = 84;
|
||||
public static final int R_POWERPC_GOT_TLSLD16_HI = 85;
|
||||
public static final int R_POWERPC_GOT_TLSLD16_HA = 86;
|
||||
public static final int R_POWERPC_GOT_TPREL16 = 87;
|
||||
public static final int R_POWERPC_GOT_TPREL16_LO = 88;
|
||||
public static final int R_POWERPC_GOT_TPREL16_HI = 89;
|
||||
public static final int R_POWERPC_GOT_TPREL16_HA = 90;
|
||||
public static final int R_POWERPC_GOT_DTPREL16 = 91;
|
||||
public static final int R_POWERPC_GOT_DTPREL16_LO = 92;
|
||||
public static final int R_POWERPC_GOT_DTPREL16_HI = 93;
|
||||
public static final int R_POWERPC_GOT_DTPREL16_HA = 94;
|
||||
public static final int R_PPC_TLSGD = 95;
|
||||
public static final int R_PPC_TLSLD = 96;
|
||||
|
||||
public static final int R_PPC_EMB_NADDR32 = 101; // uword32 (A - S)
|
||||
public static final int R_PPC_EMB_NADDR16 = 102; // uhalf16 (A - S)
|
||||
public static final int R_PPC_EMB_NADDR16_LO = 103; // uhalf16 #lo(A - S)
|
||||
public static final int R_PPC_EMB_NADDR16_HI = 104; // uhalf16 #hi(A - S)
|
||||
public static final int R_PPC_EMB_NADDR16_HA = 105; // uhalf16 #ha(A - S)
|
||||
public static final int R_PPC_EMB_SDAI16 = 106; // uhalf16 T
|
||||
public static final int R_PPC_EMB_SDA2I16 = 107; // uhalf16 U
|
||||
public static final int R_PPC_EMB_SDA2REL = 108; // uhalf16 S + A - _SDA2_BASE_
|
||||
public static final int R_PPC_EMB_SDA21 = 109; // ulow21
|
||||
public static final int R_PPC_EMB_MRKREF = 110; // none
|
||||
public static final int R_PPC_EMB_RELSEC16 = 111; // uhalf16 V + A
|
||||
public static final int R_PPC_EMB_RELST_LO = 112; // uhalf16 #lo(W + A)
|
||||
public static final int R_PPC_EMB_RELST_HI = 113; // uhalf16 #hi(W + A)
|
||||
public static final int R_PPC_EMB_RELST_HA = 114; // uhalf16 #ha(W + A)
|
||||
public static final int R_PPC_EMB_BIT_FLD = 115; // uword32
|
||||
public static final int R_PPC_EMB_RELSDA = 116; // uhalf16
|
||||
|
||||
public static final int R_POWERPC_PLTSEQ = 119;
|
||||
public static final int R_POWERPC_PLTCALL = 120;
|
||||
|
||||
public static final int R_PPC_VLE_REL8 = 216;
|
||||
public static final int R_PPC_VLE_REL15 = 217;
|
||||
public static final int R_PPC_VLE_REL24 = 218;
|
||||
public static final int R_PPC_VLE_LO16A = 219;
|
||||
public static final int R_PPC_VLE_LO16D = 220;
|
||||
public static final int R_PPC_VLE_HI16A = 221;
|
||||
public static final int R_PPC_VLE_HI16D = 222;
|
||||
public static final int R_PPC_VLE_HA16A = 223;
|
||||
public static final int R_PPC_VLE_HA16D = 224;
|
||||
public static final int R_PPC_VLE_SDA21 = 225;
|
||||
public static final int R_PPC_VLE_SDA21_LO = 226;
|
||||
public static final int R_PPC_VLE_SDAREL_LO16A = 227;
|
||||
public static final int R_PPC_VLE_SDAREL_LO16D = 228;
|
||||
public static final int R_PPC_VLE_SDAREL_HI16A = 229;
|
||||
public static final int R_PPC_VLE_SDAREL_HI16D = 230;
|
||||
public static final int R_PPC_VLE_SDAREL_HA16A = 231;
|
||||
public static final int R_PPC_VLE_SDAREL_HA16D = 232;
|
||||
|
||||
public static final int R_POWERPC_REL16DX_HA = 246;
|
||||
public static final int R_POWERPC_IRELATIVE = 248;
|
||||
public static final int R_POWERPC_REL16 = 249;
|
||||
public static final int R_POWERPC_REL16_LO = 250;
|
||||
public static final int R_POWERPC_REL16_HI = 251;
|
||||
public static final int R_POWERPC_REL16_HA = 252;
|
||||
public static final int R_POWERPC_GNU_VTINHERIT = 253;
|
||||
public static final int R_POWERPC_GNU_VTENTRY = 254;
|
||||
public static final int R_PPC_TOC16 = 255;
|
||||
|
||||
// Masks for manipulating Power PC relocation targets
|
||||
public static final int PPC_WORD32 = 0xFFFFFFFF;
|
||||
public static final int PPC_WORD30 = 0xFFFFFFFC;
|
||||
|
||||
@@ -15,14 +15,22 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.elf.relocation;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.extend.PowerPC_ElfExtension;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.*;
|
||||
|
||||
public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
@@ -31,16 +39,25 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
return elf.e_machine() == ElfConstants.EM_PPC && elf.is32Bit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PowerPC_ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
|
||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||
return new PowerPC_ElfRelocationContext(this, loadHelper, relocationTable, symbolMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
||||
ElfHeader elf = elfRelocationContext.getElfHeader();
|
||||
PowerPC_ElfRelocationContext ppcRelocationContext =
|
||||
(PowerPC_ElfRelocationContext) elfRelocationContext;
|
||||
|
||||
ElfHeader elf = ppcRelocationContext.getElfHeader();
|
||||
if (elf.e_machine() != ElfConstants.EM_PPC || !elf.is32Bit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Program program = elfRelocationContext.getProgram();
|
||||
Program program = ppcRelocationContext.getProgram();
|
||||
Memory memory = program.getMemory();
|
||||
|
||||
int type = relocation.getType();
|
||||
@@ -49,12 +66,12 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
}
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
||||
Language language = elfRelocationContext.getProgram().getLanguage();
|
||||
Language language = ppcRelocationContext.getProgram().getLanguage();
|
||||
if (!"PowerPC".equals(language.getProcessor().toString()) ||
|
||||
language.getLanguageDescription().getSize() != 32) {
|
||||
markAsError(program, relocationAddress, Long.toString(type), null,
|
||||
"Unsupported language for 32-bit PowerPC relocation",
|
||||
elfRelocationContext.getLog());
|
||||
ppcRelocationContext.getLog());
|
||||
}
|
||||
|
||||
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
|
||||
@@ -72,7 +89,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
//
|
||||
// // Relocation addend already includes original symbol value but needs to account
|
||||
// // for any image base adjustment
|
||||
// symbolValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
// symbolValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
// }
|
||||
// else {
|
||||
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
|
||||
@@ -162,7 +179,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_RELATIVE:
|
||||
newValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||
newValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL32:
|
||||
@@ -202,15 +219,200 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
// not too far away since a fabricated GOT would be in the same block
|
||||
// and we may only have room in the plt for two instructions.
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
ppcRelocationContext.getLog());
|
||||
}
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_EMB_SDA21:
|
||||
// NOTE: PPC EABI V1.0 specifies this relocation on a 24-bit field address while
|
||||
// GNU assumes a 32-bit field address. We cope with this difference by
|
||||
// forcing a 32-bit alignment of the relocation address.
|
||||
long alignedRelocOffset = relocationAddress.getOffset() & ~3;
|
||||
relocationAddress = relocationAddress.getNewAddress(alignedRelocOffset);
|
||||
|
||||
oldValue = memory.getInt(relocationAddress);
|
||||
|
||||
Address symAddr = ppcRelocationContext.getSymbolAddress(sym);
|
||||
MemoryBlock block = memory.getBlock(symAddr);
|
||||
Integer sdaBase = null;
|
||||
Integer gprID = null;
|
||||
|
||||
if (block != null) {
|
||||
String blockName = block.getName();
|
||||
if (".sdata".equals(blockName) || ".sbss".equals(blockName)) {
|
||||
sdaBase = ppcRelocationContext.getSDABase();
|
||||
gprID = 13;
|
||||
}
|
||||
else if (".sdata2".equals(blockName) || ".sbss2".equals(blockName)) {
|
||||
sdaBase = ppcRelocationContext.getSDA2Base();
|
||||
gprID = 2;
|
||||
}
|
||||
else if (".PPC.EMB.sdata0".equals(blockName) ||
|
||||
".PPC.EMB.sbss0".equals(blockName)) {
|
||||
sdaBase = 0;
|
||||
gprID = 0;
|
||||
}
|
||||
else if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(blockName)) {
|
||||
markAsError(program, relocationAddress, type, sym.getNameAsString(),
|
||||
"Unsupported relocation for external symbol",
|
||||
ppcRelocationContext.getLog());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gprID == null || sdaBase == null) {
|
||||
markAsError(program, relocationAddress, type, sym.getNameAsString(),
|
||||
"Failed to identfy appropriate data block", ppcRelocationContext.getLog());
|
||||
break;
|
||||
}
|
||||
|
||||
newValue = (symbolValue - sdaBase + addend) & 0xffff;
|
||||
newValue |= gprID << 16;
|
||||
newValue |= oldValue & 0xffe00000;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
ppcRelocationContext.getLog());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>PowerPC_ElfRelocationContext</code> provides extended relocation context..
|
||||
*/
|
||||
private static class PowerPC_ElfRelocationContext extends ElfRelocationContext {
|
||||
|
||||
private Integer sdaBase;
|
||||
private Integer sda2Base;
|
||||
|
||||
protected PowerPC_ElfRelocationContext(ElfRelocationHandler handler,
|
||||
ElfLoadHelper loadHelper, ElfRelocationTable relocationTable,
|
||||
Map<ElfSymbol, Address> symbolMap) {
|
||||
super(handler, loadHelper, relocationTable, symbolMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or establish _SDA_BASE_ value and apply as r13 context value to all memory blocks
|
||||
* with execute permission.
|
||||
* @return _SDA_BASE_ offset or null if unable to determine or establish
|
||||
*/
|
||||
Integer getSDABase() {
|
||||
if (sdaBase != null) {
|
||||
if (sdaBase == -1) {
|
||||
return null;
|
||||
}
|
||||
return sdaBase;
|
||||
}
|
||||
sdaBase = getBaseOffset("_SDA_BASE_", ".sdata", ".sbss");
|
||||
if (sdaBase == -1) {
|
||||
getLog().appendMsg("ERROR: failed to establish _SDA_BASE_");
|
||||
return null;
|
||||
}
|
||||
setRegisterContext("r13", BigInteger.valueOf(sdaBase), b -> b.isExecute());
|
||||
return sdaBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or establish _SDA2_BASE_ value and apply as r2 context value to all memory blocks
|
||||
* with execute permission.
|
||||
* @return _SDA2_BASE_ offset or null if unable to determine or establish
|
||||
*/
|
||||
Integer getSDA2Base() {
|
||||
if (sda2Base != null) {
|
||||
if (sda2Base == -1) {
|
||||
return null;
|
||||
}
|
||||
return sda2Base;
|
||||
}
|
||||
sda2Base = getBaseOffset("_SDA2_BASE_", ".sdata2", ".sbss2");
|
||||
if (sda2Base == -1) {
|
||||
getLog().appendMsg("ERROR: failed to establish _SDA2_BASE_");
|
||||
return null;
|
||||
}
|
||||
setRegisterContext("r2", BigInteger.valueOf(sda2Base), b -> b.isExecute());
|
||||
return sda2Base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply register context to all memory blocks which satisfy blockPredicate check.
|
||||
* @param regName register name
|
||||
* @param value context value
|
||||
* @param blockPredicate determine which memory blocks get context applied
|
||||
*/
|
||||
private void setRegisterContext(String regName, BigInteger value,
|
||||
Predicate<MemoryBlock> blockPredicate) {
|
||||
Register reg = program.getRegister(regName);
|
||||
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
||||
if (block.isExecute()) {
|
||||
try {
|
||||
program.getProgramContext().setValue(reg, block.getStart(), block.getEnd(),
|
||||
value);
|
||||
}
|
||||
catch (ContextChangeException e) {
|
||||
throw new AssertException(e); // no instructions should exist yet
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish base offset from symbol or range of specified memory blocks.
|
||||
* @param symbolName base symbol name
|
||||
* @param blockNames block names which may be used to establish base range
|
||||
* @return base offset or -1 on failure
|
||||
*/
|
||||
private Integer getBaseOffset(String symbolName, String... blockNames) {
|
||||
|
||||
MessageLog log = getLog();
|
||||
|
||||
Symbol baseSymbol = SymbolUtilities.getLabelOrFunctionSymbol(program, symbolName,
|
||||
msg -> log.appendMsg(msg));
|
||||
if (baseSymbol != null) {
|
||||
int baseOffset = (int) baseSymbol.getAddress().getOffset();
|
||||
String absString = "";
|
||||
if (baseSymbol.isPinned()) {
|
||||
absString = "absolute ";
|
||||
}
|
||||
log.appendMsg(
|
||||
"Using " + absString + symbolName + " of 0x" + Integer.toHexString(baseOffset));
|
||||
return baseOffset;
|
||||
}
|
||||
|
||||
Memory mem = program.getMemory();
|
||||
AddressSpace defaultSpace = program.getAddressFactory().getDefaultAddressSpace();
|
||||
AddressSet blockSet = new AddressSet();
|
||||
for (String blockName : blockNames) {
|
||||
MemoryBlock block = mem.getBlock(blockName);
|
||||
if (block != null) {
|
||||
if (!block.getStart().getAddressSpace().equals(defaultSpace)) {
|
||||
log.appendMsg("ERROR: " + blockName + " not in default space");
|
||||
return -1;
|
||||
}
|
||||
blockSet.add(block.getStart(), block.getEnd());
|
||||
}
|
||||
}
|
||||
if (blockSet.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Address baseAddr = blockSet.getMinAddress();
|
||||
long range = blockSet.getMaxAddress().subtract(baseAddr) + 1;
|
||||
if (range > Short.MAX_VALUE) {
|
||||
// use aligned midpoint of range
|
||||
baseAddr = baseAddr.add((range / 2) & ~0x0f);
|
||||
}
|
||||
|
||||
try {
|
||||
program.getSymbolTable().createLabel(baseAddr, symbolName, SourceType.ANALYSIS);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
|
||||
int baseOffset = (int) baseAddr.getOffset();
|
||||
log.appendMsg("Defined " + symbolName + " of 0x" + Integer.toHexString(baseOffset));
|
||||
return baseOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user