mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch
'origin/GP-713_ghidra1_ELF_PowerPC_EMB_Relocation--SQUASHED' (Closes #890)
This commit is contained in:
@@ -87,6 +87,9 @@
|
|||||||
</pentry>
|
</pentry>
|
||||||
</output>
|
</output>
|
||||||
<unaffected>
|
<unaffected>
|
||||||
|
<register name="r1"/> <!-- stack pointer -->
|
||||||
|
<register name="r2"/> <!-- _SDA2_BASE_ -->
|
||||||
|
<register name="r13"/> <!-- _SDA_BASE_ -->
|
||||||
<register name="r14"/>
|
<register name="r14"/>
|
||||||
<register name="r15"/>
|
<register name="r15"/>
|
||||||
<register name="r16"/>
|
<register name="r16"/>
|
||||||
@@ -105,7 +108,8 @@
|
|||||||
<register name="r29"/>
|
<register name="r29"/>
|
||||||
<register name="r30"/>
|
<register name="r30"/>
|
||||||
<register name="r31"/>
|
<register name="r31"/>
|
||||||
<register name="r1"/>
|
<register name="cr2"/>
|
||||||
|
<register name="cr3"/>
|
||||||
<register name="cr4"/>
|
<register name="cr4"/>
|
||||||
</unaffected>
|
</unaffected>
|
||||||
</prototype>
|
</prototype>
|
||||||
|
|||||||
@@ -87,6 +87,9 @@
|
|||||||
</pentry>
|
</pentry>
|
||||||
</output>
|
</output>
|
||||||
<unaffected>
|
<unaffected>
|
||||||
|
<register name="r1"/> <!-- stack pointer -->
|
||||||
|
<register name="r2"/> <!-- _SDA2_BASE_ -->
|
||||||
|
<register name="r13"/> <!-- _SDA_BASE_ -->
|
||||||
<register name="r14"/>
|
<register name="r14"/>
|
||||||
<register name="r15"/>
|
<register name="r15"/>
|
||||||
<register name="r16"/>
|
<register name="r16"/>
|
||||||
@@ -105,7 +108,9 @@
|
|||||||
<register name="r29"/>
|
<register name="r29"/>
|
||||||
<register name="r30"/>
|
<register name="r30"/>
|
||||||
<register name="r31"/>
|
<register name="r31"/>
|
||||||
<register name="r1"/>
|
<register name="cr2"/>
|
||||||
|
<register name="cr3"/>
|
||||||
|
<register name="cr4"/>
|
||||||
</unaffected>
|
</unaffected>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|||||||
@@ -1733,12 +1733,20 @@ define pcodeop stdcixOp;
|
|||||||
}
|
}
|
||||||
|
|
||||||
# binutils-descr: "lq", OP(56), OP_MASK, POWER4, PPC476, {RTQ, DQ, RAQ}
|
# binutils-descr: "lq", OP(56), OP_MASK, POWER4, PPC476, {RTQ, DQ, RAQ}
|
||||||
define pcodeop lqOp;
|
|
||||||
# ISA-cmt: lq - Load Quadword
|
# ISA-cmt: lq - Load Quadword
|
||||||
# ISA-info: lq - Form "DQ" Page 751 Category "LSQ"
|
# ISA-info: lq - Form "DQ" Page 751 Category "LSQ"
|
||||||
# binutils: power4.d: +0: e0 83 00 00 lq r4,0\(r3\)
|
# binutils: power4.d: +0: e0 83 00 00 lq r4,0\(r3\)
|
||||||
# binutils: power4.d: +4: 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;
|
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); }
|
: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}
|
# binutils-descr: "stq", DSO(62,2), DS_MASK, POWER4, PPC476, {RSQ, DS, RA0}
|
||||||
define pcodeop stqOp;
|
|
||||||
# ISA-cmt: stq - Store Quadword
|
# ISA-cmt: stq - Store Quadword
|
||||||
# ISA-info: stq - Form "DS" Page 751 Category "LSQ"
|
# ISA-info: stq - Form "DS" Page 751 Category "LSQ"
|
||||||
# binutils: power4.d: +50: f8 c7 00 02 stq r6,0\(r7\)
|
# 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: +58: f8 c7 ff f2 stq r6,-16\(r7\)
|
||||||
# binutils: power4.d: +5c: f8 c7 80 02 stq r6,-32768\(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\)
|
# 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 {
|
: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);
|
ea:$(REGISTER_SIZE) = RA_OR_ZERO + sext(DS:2 << 2);
|
||||||
*:16 EA = stqOp(S,RA_OR_ZERO,DS: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;
|
define pcodeop stvepxOp;
|
||||||
|
|||||||
@@ -47,11 +47,22 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
|||||||
public static final ElfDynamicType DT_PPC64_OPDSZ = new ElfDynamicType(0x70000002,
|
public static final ElfDynamicType DT_PPC64_OPDSZ = new ElfDynamicType(0x70000002,
|
||||||
"DT_PPC64_OPDSZ", "Specify the size of the .opd section", ElfDynamicValueType.ADDRESS);
|
"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",
|
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
|
// PPC64 ABI Version Flag Bits contained within ElfHeader e_flags
|
||||||
private static final int EF_PPC64_ABI = 3;
|
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
|
public static final String TOC_BASE = "TOC_BASE"; // injected symbol to mark global TOC_BASE
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ public class PowerPC_ElfExtension extends ElfExtension {
|
|||||||
public static final ElfDynamicType DT_PPC_OPT = new ElfDynamicType(0x70000001, "DT_PPC_OPT",
|
public static final ElfDynamicType DT_PPC_OPT = new ElfDynamicType(0x70000001, "DT_PPC_OPT",
|
||||||
"Specify that tls descriptors should be optimized", ElfDynamicValueType.VALUE);
|
"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
|
// Program header (segment) flags
|
||||||
private static final int PF_PPC_VLE = 0x10000000;
|
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_HIGHEST = 105; // half16 #highest(@dtprel)
|
||||||
public static final int R_PPC64_DTPREL16_HIGHESTA = 106; // half16 #highesta(@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
|
// Masks for manipulating Power PC relocation targets
|
||||||
public static final int PPC64_WORD32 = 0xFFFFFFFF;
|
public static final int PPC64_WORD32 = 0xFFFFFFFF;
|
||||||
public static final int PPC64_WORD30 = 0xFFFFFFFC;
|
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_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_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
|
// Masks for manipulating Power PC relocation targets
|
||||||
public static final int PPC_WORD32 = 0xFFFFFFFF;
|
public static final int PPC_WORD32 = 0xFFFFFFFF;
|
||||||
public static final int PPC_WORD30 = 0xFFFFFFFC;
|
public static final int PPC_WORD30 = 0xFFFFFFFC;
|
||||||
|
|||||||
@@ -15,14 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.elf.relocation;
|
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.*;
|
||||||
import ghidra.app.util.bin.format.elf.extend.PowerPC_ElfExtension;
|
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.Language;
|
||||||
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.listing.ContextChangeException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.*;
|
||||||
|
|
||||||
public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
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();
|
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
|
@Override
|
||||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
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()) {
|
if (elf.e_machine() != ElfConstants.EM_PPC || !elf.is32Bit()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program program = elfRelocationContext.getProgram();
|
Program program = ppcRelocationContext.getProgram();
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
|
|
||||||
int type = relocation.getType();
|
int type = relocation.getType();
|
||||||
@@ -49,12 +66,12 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
|||||||
}
|
}
|
||||||
int symbolIndex = relocation.getSymbolIndex();
|
int symbolIndex = relocation.getSymbolIndex();
|
||||||
|
|
||||||
Language language = elfRelocationContext.getProgram().getLanguage();
|
Language language = ppcRelocationContext.getProgram().getLanguage();
|
||||||
if (!"PowerPC".equals(language.getProcessor().toString()) ||
|
if (!"PowerPC".equals(language.getProcessor().toString()) ||
|
||||||
language.getLanguageDescription().getSize() != 32) {
|
language.getLanguageDescription().getSize() != 32) {
|
||||||
markAsError(program, relocationAddress, Long.toString(type), null,
|
markAsError(program, relocationAddress, Long.toString(type), null,
|
||||||
"Unsupported language for 32-bit PowerPC relocation",
|
"Unsupported language for 32-bit PowerPC relocation",
|
||||||
elfRelocationContext.getLog());
|
ppcRelocationContext.getLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
|
// 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
|
// // Relocation addend already includes original symbol value but needs to account
|
||||||
// // for any image base adjustment
|
// // for any image base adjustment
|
||||||
// symbolValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
|
// symbolValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
|
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
|
||||||
@@ -162,7 +179,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
|||||||
memory.setInt(relocationAddress, newValue);
|
memory.setInt(relocationAddress, newValue);
|
||||||
break;
|
break;
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_RELATIVE:
|
case PowerPC_ElfRelocationConstants.R_PPC_RELATIVE:
|
||||||
newValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
newValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||||
memory.setInt(relocationAddress, newValue);
|
memory.setInt(relocationAddress, newValue);
|
||||||
break;
|
break;
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_REL32:
|
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
|
// 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.
|
// and we may only have room in the plt for two instructions.
|
||||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||||
elfRelocationContext.getLog());
|
ppcRelocationContext.getLog());
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||||
elfRelocationContext.getLog());
|
ppcRelocationContext.getLog());
|
||||||
break;
|
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