mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-4239 Transitioned to new AbstractElfRelocationHandler implementation which uses ElfRelocationType enums specific to each handler.
This commit is contained in:
@@ -22,7 +22,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
|
||||
import ghidra.app.util.bin.format.elf.relocation.PowerPC64_ElfRelocationConstants;
|
||||
import ghidra.app.util.bin.format.elf.relocation.PowerPC64_ElfRelocationType;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
@@ -155,7 +155,7 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
// paint TOC_BASE value as r2 across executable blocks since r2
|
||||
// is needed to resolve call stubs
|
||||
Symbol tocSymbol = SymbolUtilities.getLabelOrFunctionSymbol(elfLoadHelper.getProgram(),
|
||||
TOC_BASE, err -> elfLoadHelper.getLog().error("PowerPC64_ELF", err));
|
||||
TOC_BASE, err -> elfLoadHelper.getLog().appendMsg("PowerPC64_ELF", err));
|
||||
if (tocSymbol != null) {
|
||||
paintTocAsR2value(tocSymbol.getAddress().getOffset(), elfLoadHelper, monitor);
|
||||
}
|
||||
@@ -180,8 +180,9 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
return;
|
||||
}
|
||||
|
||||
int relEntrySize = (dynamicTable.getDynamicValue(
|
||||
ElfDynamicType.DT_PLTREL) == ElfDynamicType.DT_RELA.value) ? 24 : 16;
|
||||
int relEntrySize = (dynamicTable
|
||||
.getDynamicValue(ElfDynamicType.DT_PLTREL) == ElfDynamicType.DT_RELA.value) ? 24
|
||||
: 16;
|
||||
|
||||
long pltEntryCount =
|
||||
dynamicTable.getDynamicValue(ElfDynamicType.DT_PLTRELSZ) / relEntrySize;
|
||||
@@ -392,8 +393,8 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
if (function == null) {
|
||||
// Check for potential pointer table (unsure a non-function would be referenced by OPD section)
|
||||
List<Relocation> relocations = program.getRelocationTable().getRelocations(refAddr);
|
||||
if (!relocations.isEmpty() &&
|
||||
relocations.get(0).getType() == PowerPC64_ElfRelocationConstants.R_PPC64_RELATIVE) {
|
||||
if (!relocations.isEmpty() && relocations.get(0)
|
||||
.getType() == PowerPC64_ElfRelocationType.R_PPC64_RELATIVE.typeId) {
|
||||
return program.getSymbolTable().getPrimarySymbol(refAddr);
|
||||
}
|
||||
|
||||
@@ -455,7 +456,7 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
// ensure that r12 context has been set on global entry function
|
||||
Symbol entrySymbol = SymbolUtilities.getLabelOrFunctionSymbol(
|
||||
elfLoadHelper.getProgram(), ElfLoader.ELF_ENTRY_FUNCTION_NAME,
|
||||
err -> elfLoadHelper.getLog().error("PowerPC64_ELF", err));
|
||||
err -> elfLoadHelper.getLog().appendMsg("PowerPC64_ELF", err));
|
||||
if (entrySymbol != null && entrySymbol.getSymbolType() == SymbolType.FUNCTION) {
|
||||
setPPC64v2GlobalFunctionR12Context(program, entrySymbol.getAddress());
|
||||
}
|
||||
@@ -508,8 +509,9 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
||||
// TODO: global function should be a thunk to the local function - need analyzer to do this
|
||||
String cmt = "local function entry for global function " + name + " at {@address " +
|
||||
address + "}";
|
||||
elfLoadHelper.getProgram().getListing().setComment(localFunctionAddr,
|
||||
CodeUnit.PRE_COMMENT, cmt);
|
||||
elfLoadHelper.getProgram()
|
||||
.getListing()
|
||||
.setComment(localFunctionAddr, CodeUnit.PRE_COMMENT, cmt);
|
||||
}
|
||||
catch (Exception e) {
|
||||
elfLoadHelper.log("Failed to generate local function symbol " + localName + " at " +
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/* ###
|
||||
* 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 PowerPC64_ElfRelocationConstants {
|
||||
|
||||
public static final int R_PPC64_NONE = 0;
|
||||
public static final int R_PPC64_ADDR32 = 1; // word32* S + A
|
||||
public static final int R_PPC64_ADDR24 = 2; // low24* (S + A) >> 2
|
||||
public static final int R_PPC64_ADDR16 = 3; // half16* S + A
|
||||
public static final int R_PPC64_ADDR16_LO = 4; // half16 #lo(S + A)
|
||||
public static final int R_PPC64_ADDR16_HI = 5; // half16 #hi(S + A)
|
||||
public static final int R_PPC64_ADDR16_HA = 6; // half16 #ha(S + A)
|
||||
public static final int R_PPC64_ADDR14 = 7; // low14* (S + A) >> 2
|
||||
public static final int R_PPC64_ADDR14_BRTAKEN = 8; // low14* (S + A) >> 2
|
||||
public static final int R_PPC64_ADDR14_BRNTAKEN = 9; // low14* (S + A) >> 2
|
||||
public static final int R_PPC64_REL24 = 10; // low24* (S + A - P) >> 2
|
||||
public static final int R_PPC64_REL14 = 11; // low14* (S + A - P) >> 2
|
||||
public static final int R_PPC64_REL14_BRTAKEN = 12; // low14* (S + A - P) >> 2
|
||||
public static final int R_PPC64_REL14_BRNTAKEN = 13; // low14* (S + A - P) >> 2
|
||||
public static final int R_PPC64_GOT16 = 14; // half16* G
|
||||
public static final int R_PPC64_GOT16_LO = 15; // half16 #lo(G)
|
||||
public static final int R_PPC64_GOT16_HI = 16; // half16 #hi(G)
|
||||
public static final int R_PPC64_GOT16_HA = 17; // half16 #ha(G)
|
||||
public static final int R_PPC64_COPY = 19;
|
||||
public static final int R_PPC64_GLOB_DAT = 20; // doubleword64 S + A
|
||||
public static final int R_PPC64_JMP_SLOT = 21; // none see below
|
||||
public static final int R_PPC64_RELATIVE = 22; // doubleword64 B + A
|
||||
public static final int R_PPC64_UADDR32 = 24; // word32* S + A
|
||||
public static final int R_PPC64_UADDR16 = 25; // half16* S + A
|
||||
public static final int R_PPC64_REL32 = 26; // word32* S + A - P
|
||||
public static final int R_PPC64_PLT32 = 27; // word32* L
|
||||
public static final int R_PPC64_PLTREL32 = 28; // word32* L - P
|
||||
public static final int R_PPC64_PLT16_LO = 29; // half16 #lo(L)
|
||||
public static final int R_PPC64_PLT16_HI = 30; // half16 #hi(L)
|
||||
public static final int R_PPC64_PLT16_HA = 31; // half16 #ha(L)
|
||||
public static final int R_PPC64_SECTOFF = 33; // half16* R + A
|
||||
public static final int R_PPC64_SECTOFF_LO = 34; // half16 #lo(R + A)
|
||||
public static final int R_PPC64_SECTOFF_HI = 35; // half16 #hi(R + A)
|
||||
public static final int R_PPC64_SECTOFF_HA = 36; // half16 #ha(R + A)
|
||||
public static final int R_PPC64_ADDR30 = 37; // word30 (S + A - P) >> 2
|
||||
public static final int R_PPC64_ADDR64 = 38; // doubleword64 S + A
|
||||
public static final int R_PPC64_ADDR16_HIGHER = 39; // half16 #higher(S + A)
|
||||
public static final int R_PPC64_ADDR16_HIGHERA = 40; // half16 #highera(S + A)
|
||||
public static final int R_PPC64_ADDR16_HIGHEST = 41; // half16 #highest(S + A)
|
||||
public static final int R_PPC64_ADDR16_HIGHESTA = 42; // half16 #highesta(S + A)
|
||||
public static final int R_PPC64_UADDR64 = 43; // doubleword64 S + A
|
||||
public static final int R_PPC64_REL64 = 44; // doubleword64 S + A - P
|
||||
public static final int R_PPC64_PLT64 = 45; // doubleword64 L
|
||||
public static final int R_PPC64_PLTREL64 = 46; // doubleword64 L - P
|
||||
public static final int R_PPC64_TOC16 = 47; // half16* S + A - .TOC.
|
||||
public static final int R_PPC64_TOC16_LO = 48; // half16 #lo(S + A - .TOC.)
|
||||
public static final int R_PPC64_TOC16_HI = 49; // half16 #hi(S + A - .TOC.)
|
||||
public static final int R_PPC64_TOC16_HA = 50; // half16 #ha(S + A - .TOC.)
|
||||
public static final int R_PPC64_TOC = 51; // doubleword64 .TOC.
|
||||
public static final int R_PPC64_PLTGOT16 = 52; // half16* M
|
||||
public static final int R_PPC64_PLTGOT16_LO = 53; // half16 #lo(M)
|
||||
public static final int R_PPC64_PLTGOT16_HI = 54; // half16 #hi(M)
|
||||
public static final int R_PPC64_PLTGOT16_HA = 55; // half16 #ha(M)
|
||||
public static final int R_PPC64_ADDR16_DS = 56; // half16ds* (S + A) >> 2
|
||||
public static final int R_PPC64_ADDR16_LO_DS = 57; // half16ds #lo(S + A) >> 2
|
||||
public static final int R_PPC64_GOT16_DS = 58; // half16ds* G >> 2
|
||||
public static final int R_PPC64_GOT16_LO_DS = 59; // half16ds #lo(G) >> 2
|
||||
public static final int R_PPC64_PLT16_LO_DS = 60; // half16ds #lo(L) >> 2
|
||||
public static final int R_PPC64_SECTOFF_DS = 61; // half16ds* (R + A) >> 2
|
||||
public static final int R_PPC64_SECTOFF_LO_DS = 62; // half16ds #lo(R + A) >> 2
|
||||
public static final int R_PPC64_TOC16_DS = 63; // half16ds* (S + A - .TOC.) >> 2
|
||||
public static final int R_PPC64_TOC16_LO_DS = 64; // half16ds #lo(S + A - .TOC.) >> 2
|
||||
public static final int R_PPC64_PLTGOT16_DS = 65; // half16ds* M >> 2
|
||||
public static final int R_PPC64_PLTGOT16_LO_DS = 66; // half16ds #lo(M) >> 2
|
||||
public static final int R_PPC64_TLS = 67;
|
||||
public static final int R_PPC64_DTPMOD64 = 68; // doubleword64 @dtpmod
|
||||
public static final int R_PPC64_TPREL16 = 69; // half16* @tprel
|
||||
public static final int R_PPC64_TPREL16_LO = 60; // half16 #lo(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HI = 71; // half16 #hi(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HA = 72; // half16 #ha(@tprel)
|
||||
public static final int R_PPC64_TPREL64 = 73; // doubleword64 @tprel
|
||||
public static final int R_PPC64_DTPREL16 = 74; // half16* @dtprel
|
||||
public static final int R_PPC64_DTPREL16_LO = 75; // half16 #lo(@dtprel)
|
||||
public static final int R_PPC64_DTPREL16_HI = 76; // half16 #hi(@dtprel)
|
||||
public static final int R_PPC64_DTPREL16_HA = 77; // half16 #ha(@dtprel)
|
||||
public static final int R_PPC64_DTPREL64 = 78; // doubleword64 @dtprel
|
||||
public static final int R_PPC64_GOT_TLSGD16 = 79; // half16* @got@tlsgd
|
||||
public static final int R_PPC64_GOT_TLSGD16_LO = 80; // half16 #lo(@got@tlsgd)
|
||||
public static final int R_PPC64_GOT_TLSGD16_HI = 81; // half16 #hi(@got@tlsgd)
|
||||
public static final int R_PPC64_GOT_TLSGD16_HA = 82; // half16 #ha(@got@tlsgd)
|
||||
public static final int R_PPC64_GOT_TLSLD16 = 83; // half16* @got@tlsld
|
||||
public static final int R_PPC64_GOT_TLSLD16_LO = 84; // half16 #lo(@got@tlsld)
|
||||
public static final int R_PPC64_GOT_TLSLD16_HI = 85; // half16 #hi(@got@tlsld)
|
||||
public static final int R_PPC64_GOT_TLSLD16_HA = 86; // half16 #ha(@got@tlsld)
|
||||
public static final int R_PPC64_GOT_TPREL16_DS = 87; // half16ds* @got@tprel
|
||||
public static final int R_PPC64_GOT_TPREL16_LO_DS = 88; // half16ds #lo(@got@tprel)
|
||||
public static final int R_PPC64_GOT_TPREL16_HI = 89; // half16 #hi(@got@tprel)
|
||||
public static final int R_PPC64_GOT_TPREL16_HA = 90; // half16 #ha(@got@tprel)
|
||||
public static final int R_PPC64_GOT_DTPREL16_DS = 91; // half16ds* @got@dtprel
|
||||
public static final int R_PPC64_GOT_DTPREL16_LO_DS = 92;// half16ds #lo(@got@dtprel)
|
||||
public static final int R_PPC64_GOT_DTPREL16_HI = 93; // half16 #hi(@got@dtprel)
|
||||
public static final int R_PPC64_GOT_DTPREL16_HA = 94; // half16 #ha(@got@dtprel)
|
||||
public static final int R_PPC64_TPREL16_DS = 95; // half16ds* @tprel
|
||||
public static final int R_PPC64_TPREL16_LO_DS = 96; // half16ds #lo(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HIGHER = 97; // half16 #higher(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HIGHERA = 98; // half16 #highera(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HIGHEST = 99; // half16 #highest(@tprel)
|
||||
public static final int R_PPC64_TPREL16_HIGHESTA = 100; // half16 #highesta(@tprel)
|
||||
public static final int R_PPC64_DTPREL16_DS = 101; // half16ds* @dtprel
|
||||
public static final int R_PPC64_DTPREL16_LO_DS = 102; // half16ds #lo(@dtprel)
|
||||
public static final int R_PPC64_DTPREL16_HIGHER = 103; // half16 #higher(@dtprel)
|
||||
public static final int R_PPC64_DTPREL16_HIGHERA = 104; // half16 #highera(@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_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;
|
||||
public static final int PPC64_LOW24 = 0x03FFFFFC;
|
||||
public static final int PPC64_LOW14 = 0x0020FFFC;
|
||||
public static final int PPC64_HALF16 = 0xFFFF;
|
||||
|
||||
private PowerPC64_ElfRelocationConstants() {
|
||||
// no construct
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.extend.PowerPC64_ElfExtension;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.reloc.Relocation.Status;
|
||||
@@ -27,9 +26,23 @@ import ghidra.program.model.reloc.RelocationResult;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
|
||||
public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
public class PowerPC64_ElfRelocationHandler
|
||||
extends AbstractElfRelocationHandler<PowerPC64_ElfRelocationType, ElfRelocationContext<?>> {
|
||||
|
||||
// Masks for manipulating Power PC relocation targets
|
||||
private static final int PPC64_WORD32 = 0xFFFFFFFF;
|
||||
private static final int PPC64_WORD30 = 0xFFFFFFFC;
|
||||
private static final int PPC64_LOW24 = 0x03FFFFFC;
|
||||
private static final int PPC64_LOW14 = 0x0020FFFC;
|
||||
private static final int PPC64_HALF16 = 0xFFFF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PowerPC64_ElfRelocationHandler() {
|
||||
super(PowerPC64_ElfRelocationType.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(ElfHeader elf) {
|
||||
@@ -37,42 +50,19 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
|
||||
ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
||||
ElfHeader elf = elfRelocationContext.getElfHeader();
|
||||
if (elf.e_machine() != ElfConstants.EM_PPC64 || !elf.is64Bit()) {
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
|
||||
ElfRelocation relocation, PowerPC64_ElfRelocationType type, Address relocationAddress,
|
||||
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
|
||||
throws MemoryAccessException {
|
||||
|
||||
Program program = elfRelocationContext.getProgram();
|
||||
Memory memory = program.getMemory();
|
||||
|
||||
int type = relocation.getType();
|
||||
if (type == PowerPC64_ElfRelocationConstants.R_PPC64_NONE) {
|
||||
return RelocationResult.SKIPPED;
|
||||
}
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
||||
Language language = elfRelocationContext.getProgram().getLanguage();
|
||||
if (!"PowerPC".equals(language.getProcessor().toString()) ||
|
||||
language.getLanguageDescription().getSize() != 64) {
|
||||
markAsError(program, relocationAddress, Long.toString(type), null,
|
||||
"Unsupported language for 64-bit PowerPC relocation",
|
||||
elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
|
||||
long addend = relocation.getAddend();
|
||||
|
||||
long offset = relocationAddress.getOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
|
||||
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
|
||||
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
int oldValue = memory.getInt(relocationAddress);
|
||||
int newValue = 0;
|
||||
int byteLength = 4; // most relocations affect 4-bytes (change if different)
|
||||
@@ -89,17 +79,17 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
// Obtain TOC base used by certain relocations
|
||||
long toc = 0;
|
||||
switch (type) {
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_LO:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_HI:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_HA:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_LO_DS:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC:
|
||||
case R_PPC64_TOC16_LO:
|
||||
case R_PPC64_TOC16_HI:
|
||||
case R_PPC64_TOC16_HA:
|
||||
case R_PPC64_TOC16_LO_DS:
|
||||
case R_PPC64_TOC:
|
||||
|
||||
MessageLog log = elfRelocationContext.getLog();
|
||||
Symbol tocBaseSym = SymbolUtilities.getLabelOrFunctionSymbol(program,
|
||||
PowerPC64_ElfExtension.TOC_BASE, err -> log.appendMsg(err));
|
||||
if (tocBaseSym == null) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
|
||||
"TOC_BASE unknown", log);
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
@@ -109,101 +99,98 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_COPY:
|
||||
markAsWarning(program, relocationAddress, "R_PPC64_COPY", symbolName,
|
||||
symbolIndex, "Runtime copy not supported", elfRelocationContext.getLog());
|
||||
case R_PPC64_COPY:
|
||||
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
|
||||
"Runtime copy not supported", elfRelocationContext.getLog());
|
||||
return RelocationResult.UNSUPPORTED;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR32:
|
||||
case R_PPC64_ADDR32:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR24:
|
||||
case R_PPC64_ADDR24:
|
||||
newValue = (int) ((symbolValue + addend) >> 2);
|
||||
newValue =
|
||||
(oldValue & ~PowerPC64_ElfRelocationConstants.PPC64_LOW24) | (newValue << 2);
|
||||
newValue = (oldValue & ~PPC64_LOW24) | (newValue << 2);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR16:
|
||||
case R_PPC64_ADDR16:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR16_LO:
|
||||
case R_PPC64_ADDR16_LO:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_LO:
|
||||
case R_PPC64_TOC16_LO:
|
||||
newValue = (int) (symbolValue + addend - toc);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_LO_DS:
|
||||
case R_PPC64_TOC16_LO_DS:
|
||||
newValue = (int) ((symbolValue + addend - toc) >> 2);
|
||||
newValue = ((oldValue >>> 16) & 0x3) | (newValue << 2);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR16_HI:
|
||||
case R_PPC64_ADDR16_HI:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
newValue = ((newValue >> 16) & 0xFFFF);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_HI:
|
||||
case R_PPC64_TOC16_HI:
|
||||
newValue = (int) (symbolValue + addend - toc);
|
||||
newValue = ((newValue >> 16) & 0xFFFF);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR16_HA:
|
||||
case R_PPC64_ADDR16_HA:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
newValue = ((newValue >> 16) + (((newValue & 0x8000) != 0) ? 1 : 0));
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC16_HA:
|
||||
case R_PPC64_TOC16_HA:
|
||||
newValue = (int) (symbolValue + addend - toc);
|
||||
newValue = ((newValue >> 16) + (((newValue & 0x8000) != 0) ? 1 : 0));
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR14:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR14_BRTAKEN:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR14_BRNTAKEN:
|
||||
case R_PPC64_ADDR14:
|
||||
case R_PPC64_ADDR14_BRTAKEN:
|
||||
case R_PPC64_ADDR14_BRNTAKEN:
|
||||
newValue = (int) ((symbolValue + addend) >> 2);
|
||||
newValue = (oldValue & ~PowerPC64_ElfRelocationConstants.PPC64_LOW14) |
|
||||
((newValue << 2) & PowerPC64_ElfRelocationConstants.PPC64_LOW24);
|
||||
newValue = (oldValue & ~PPC64_LOW14) | ((newValue << 2) & PPC64_LOW24);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_REL24:
|
||||
case R_PPC64_REL24:
|
||||
|
||||
// attempt to handle Object module case where referenced symbol resides within .opd
|
||||
symbolValue = fixupOPDSymbolValue(elfRelocationContext, sym);
|
||||
|
||||
newValue = (int) ((symbolValue + addend - offset) >> 2);
|
||||
newValue = ((newValue << 2) & PowerPC64_ElfRelocationConstants.PPC64_LOW24);
|
||||
newValue = (oldValue & ~PowerPC64_ElfRelocationConstants.PPC64_LOW24) | newValue;
|
||||
newValue = ((newValue << 2) & PPC64_LOW24);
|
||||
newValue = (oldValue & ~PPC64_LOW24) | newValue;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_RELATIVE:
|
||||
case R_PPC64_RELATIVE:
|
||||
long value64 = elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||
memory.setLong(relocationAddress, value64);
|
||||
byteLength = 8;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_REL32:
|
||||
case R_PPC64_REL32:
|
||||
newValue = (int) (symbolValue + addend - offset);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_REL14:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_REL14_BRTAKEN:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_REL14_BRNTAKEN:
|
||||
case R_PPC64_REL14:
|
||||
case R_PPC64_REL14_BRTAKEN:
|
||||
case R_PPC64_REL14_BRNTAKEN:
|
||||
newValue = (int) (symbolValue + addend - offset) >> 2;
|
||||
newValue = (oldValue & ~PowerPC64_ElfRelocationConstants.PPC64_LOW14) |
|
||||
((newValue << 2) & PowerPC64_ElfRelocationConstants.PPC64_LOW14);
|
||||
newValue = (oldValue & ~PPC64_LOW14) | ((newValue << 2) & PPC64_LOW14);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_JMP_SLOT:
|
||||
case R_PPC64_JMP_SLOT:
|
||||
// TODO: do we need option to allow function descriptor
|
||||
// use - or not? The EF_PPC64_ABI in e_flags is not reliable.
|
||||
Address functionDescriptorAddr = relocationAddress.getNewAddress(symbolValue);
|
||||
@@ -226,28 +213,28 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
byteLength = bytes.length;
|
||||
}
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR32:
|
||||
case R_PPC64_UADDR32:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR16:
|
||||
case R_PPC64_UADDR16:
|
||||
newValue = (int) (symbolValue + addend);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR64:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR64:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_GLOB_DAT:
|
||||
case R_PPC64_UADDR64:
|
||||
case R_PPC64_ADDR64:
|
||||
case R_PPC64_GLOB_DAT:
|
||||
value64 = symbolValue + addend;
|
||||
memory.setLong(relocationAddress, value64);
|
||||
byteLength = 8;
|
||||
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
|
||||
warnExternalOffsetRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||
warnExternalOffsetRelocation(program, relocationAddress, symbolAddr, symbolName,
|
||||
addend, elfRelocationContext.getLog());
|
||||
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||
}
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC:
|
||||
case R_PPC64_TOC:
|
||||
memory.setLong(relocationAddress, toc);
|
||||
byteLength = 8;
|
||||
break;
|
||||
@@ -266,12 +253,12 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
* applied to call stubs. It is also important that relocations have already
|
||||
* been applied to the .opd section since we will be using its data for
|
||||
* locating the real function.
|
||||
* @param elfRelocationContext
|
||||
* @param sym
|
||||
* @param elfRelocationContext ELF relocation context
|
||||
* @param sym ELF relocation symbol
|
||||
* @return symbol value
|
||||
* @throws MemoryAccessException
|
||||
* @throws MemoryAccessException if memory access error occurs
|
||||
*/
|
||||
private long fixupOPDSymbolValue(ElfRelocationContext elfRelocationContext, ElfSymbol sym)
|
||||
private long fixupOPDSymbolValue(ElfRelocationContext<?> elfRelocationContext, ElfSymbol sym)
|
||||
throws MemoryAccessException {
|
||||
Address addr = elfRelocationContext.getSymbolAddress(sym);
|
||||
if (addr == null) {
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/* ###
|
||||
* 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 enum PowerPC64_ElfRelocationType implements ElfRelocationType {
|
||||
|
||||
R_PPC64_NONE(0),
|
||||
R_PPC64_ADDR32(1), // word32* S + A
|
||||
R_PPC64_ADDR24(2), // low24* (S + A) >> 2
|
||||
R_PPC64_ADDR16(3), // half16* S + A
|
||||
R_PPC64_ADDR16_LO(4), // half16 #lo(S + A)
|
||||
R_PPC64_ADDR16_HI(5), // half16 #hi(S + A)
|
||||
R_PPC64_ADDR16_HA(6), // half16 #ha(S + A)
|
||||
R_PPC64_ADDR14(7), // low14* (S + A) >> 2
|
||||
R_PPC64_ADDR14_BRTAKEN(8), // low14* (S + A) >> 2
|
||||
R_PPC64_ADDR14_BRNTAKEN(9), // low14* (S + A) >> 2
|
||||
R_PPC64_REL24(10), // low24* (S + A - P) >> 2
|
||||
R_PPC64_REL14(11), // low14* (S + A - P) >> 2
|
||||
R_PPC64_REL14_BRTAKEN(12), // low14* (S + A - P) >> 2
|
||||
R_PPC64_REL14_BRNTAKEN(13), // low14* (S + A - P) >> 2
|
||||
R_PPC64_GOT16(14), // half16* G
|
||||
R_PPC64_GOT16_LO(15), // half16 #lo(G)
|
||||
R_PPC64_GOT16_HI(16), // half16 #hi(G)
|
||||
R_PPC64_GOT16_HA(17), // half16 #ha(G)
|
||||
R_PPC64_COPY(19),
|
||||
R_PPC64_GLOB_DAT(20), // doubleword64 S + A
|
||||
R_PPC64_JMP_SLOT(21), // none see below
|
||||
R_PPC64_RELATIVE(22), // doubleword64 B + A
|
||||
R_PPC64_UADDR32(24), // word32* S + A
|
||||
R_PPC64_UADDR16(25), // half16* S + A
|
||||
R_PPC64_REL32(26), // word32* S + A - P
|
||||
R_PPC64_PLT32(27), // word32* L
|
||||
R_PPC64_PLTREL32(28), // word32* L - P
|
||||
R_PPC64_PLT16_LO(29), // half16 #lo(L)
|
||||
R_PPC64_PLT16_HI(30), // half16 #hi(L)
|
||||
R_PPC64_PLT16_HA(31), // half16 #ha(L)
|
||||
R_PPC64_SECTOFF(33), // half16* R + A
|
||||
R_PPC64_SECTOFF_LO(34), // half16 #lo(R + A)
|
||||
R_PPC64_SECTOFF_HI(35), // half16 #hi(R + A)
|
||||
R_PPC64_SECTOFF_HA(36), // half16 #ha(R + A)
|
||||
R_PPC64_ADDR30(37), // word30 (S + A - P) >> 2
|
||||
R_PPC64_ADDR64(38), // doubleword64 S + A
|
||||
R_PPC64_ADDR16_HIGHER(39), // half16 #higher(S + A)
|
||||
R_PPC64_ADDR16_HIGHERA(40), // half16 #highera(S + A)
|
||||
R_PPC64_ADDR16_HIGHEST(41), // half16 #highest(S + A)
|
||||
R_PPC64_ADDR16_HIGHESTA(42), // half16 #highesta(S + A)
|
||||
R_PPC64_UADDR64(43), // doubleword64 S + A
|
||||
R_PPC64_REL64(44), // doubleword64 S + A - P
|
||||
R_PPC64_PLT64(45), // doubleword64 L
|
||||
R_PPC64_PLTREL64(46), // doubleword64 L - P
|
||||
R_PPC64_TOC16(47), // half16* S + A - .TOC.
|
||||
R_PPC64_TOC16_LO(48), // half16 #lo(S + A - .TOC.)
|
||||
R_PPC64_TOC16_HI(49), // half16 #hi(S + A - .TOC.)
|
||||
R_PPC64_TOC16_HA(50), // half16 #ha(S + A - .TOC.)
|
||||
R_PPC64_TOC(51), // doubleword64 .TOC.
|
||||
R_PPC64_PLTGOT16(52), // half16* M
|
||||
R_PPC64_PLTGOT16_LO(53), // half16 #lo(M)
|
||||
R_PPC64_PLTGOT16_HI(54), // half16 #hi(M)
|
||||
R_PPC64_PLTGOT16_HA(55), // half16 #ha(M)
|
||||
R_PPC64_ADDR16_DS(56), // half16ds* (S + A) >> 2
|
||||
R_PPC64_ADDR16_LO_DS(57), // half16ds #lo(S + A) >> 2
|
||||
R_PPC64_GOT16_DS(58), // half16ds* G >> 2
|
||||
R_PPC64_GOT16_LO_DS(59), // half16ds #lo(G) >> 2
|
||||
R_PPC64_PLT16_LO_DS(60), // half16ds #lo(L) >> 2
|
||||
R_PPC64_SECTOFF_DS(61), // half16ds* (R + A) >> 2
|
||||
R_PPC64_SECTOFF_LO_DS(62), // half16ds #lo(R + A) >> 2
|
||||
R_PPC64_TOC16_DS(63), // half16ds* (S + A - .TOC.) >> 2
|
||||
R_PPC64_TOC16_LO_DS(64), // half16ds #lo(S + A - .TOC.) >> 2
|
||||
R_PPC64_PLTGOT16_DS(65), // half16ds* M >> 2
|
||||
R_PPC64_PLTGOT16_LO_DS(66), // half16ds #lo(M) >> 2
|
||||
R_PPC64_TLS(67),
|
||||
R_PPC64_DTPMOD64(68), // doubleword64 @dtpmod
|
||||
R_PPC64_TPREL16(69), // half16* @tprel
|
||||
R_PPC64_TPREL16_LO(60), // half16 #lo(@tprel)
|
||||
R_PPC64_TPREL16_HI(71), // half16 #hi(@tprel)
|
||||
R_PPC64_TPREL16_HA(72), // half16 #ha(@tprel)
|
||||
R_PPC64_TPREL64(73), // doubleword64 @tprel
|
||||
R_PPC64_DTPREL16(74), // half16* @dtprel
|
||||
R_PPC64_DTPREL16_LO(75), // half16 #lo(@dtprel)
|
||||
R_PPC64_DTPREL16_HI(76), // half16 #hi(@dtprel)
|
||||
R_PPC64_DTPREL16_HA(77), // half16 #ha(@dtprel)
|
||||
R_PPC64_DTPREL64(78), // doubleword64 @dtprel
|
||||
R_PPC64_GOT_TLSGD16(79), // half16* @got@tlsgd
|
||||
R_PPC64_GOT_TLSGD16_LO(80), // half16 #lo(@got@tlsgd)
|
||||
R_PPC64_GOT_TLSGD16_HI(81), // half16 #hi(@got@tlsgd)
|
||||
R_PPC64_GOT_TLSGD16_HA(82), // half16 #ha(@got@tlsgd)
|
||||
R_PPC64_GOT_TLSLD16(83), // half16* @got@tlsld
|
||||
R_PPC64_GOT_TLSLD16_LO(84), // half16 #lo(@got@tlsld)
|
||||
R_PPC64_GOT_TLSLD16_HI(85), // half16 #hi(@got@tlsld)
|
||||
R_PPC64_GOT_TLSLD16_HA(86), // half16 #ha(@got@tlsld)
|
||||
R_PPC64_GOT_TPREL16_DS(87), // half16ds* @got@tprel
|
||||
R_PPC64_GOT_TPREL16_LO_DS(88), // half16ds #lo(@got@tprel)
|
||||
R_PPC64_GOT_TPREL16_HI(89), // half16 #hi(@got@tprel)
|
||||
R_PPC64_GOT_TPREL16_HA(90), // half16 #ha(@got@tprel)
|
||||
R_PPC64_GOT_DTPREL16_DS(91), // half16ds* @got@dtprel
|
||||
R_PPC64_GOT_DTPREL16_LO_DS(92),// half16ds #lo(@got@dtprel)
|
||||
R_PPC64_GOT_DTPREL16_HI(93), // half16 #hi(@got@dtprel)
|
||||
R_PPC64_GOT_DTPREL16_HA(94), // half16 #ha(@got@dtprel)
|
||||
R_PPC64_TPREL16_DS(95), // half16ds* @tprel
|
||||
R_PPC64_TPREL16_LO_DS(96), // half16ds #lo(@tprel)
|
||||
R_PPC64_TPREL16_HIGHER(97), // half16 #higher(@tprel)
|
||||
R_PPC64_TPREL16_HIGHERA(98), // half16 #highera(@tprel)
|
||||
R_PPC64_TPREL16_HIGHEST(99), // half16 #highest(@tprel)
|
||||
R_PPC64_TPREL16_HIGHESTA(100), // half16 #highesta(@tprel)
|
||||
R_PPC64_DTPREL16_DS(101), // half16ds* @dtprel
|
||||
R_PPC64_DTPREL16_LO_DS(102), // half16ds #lo(@dtprel)
|
||||
R_PPC64_DTPREL16_HIGHER(103), // half16 #higher(@dtprel)
|
||||
R_PPC64_DTPREL16_HIGHERA(104), // half16 #highera(@dtprel)
|
||||
R_PPC64_DTPREL16_HIGHEST(105), // half16 #highest(@dtprel)
|
||||
R_PPC64_DTPREL16_HIGHESTA(106), // half16 #highesta(@dtprel)
|
||||
|
||||
R_PPC64_PLTSEQ_NOTOC(121),
|
||||
R_PPC64_PLTCALL_NOTOC(122),
|
||||
R_PPC64_PCREL_OPT(123),
|
||||
|
||||
R_PPC64_D34(128),
|
||||
R_PPC64_D34_LO(129),
|
||||
R_PPC64_D34_HI30(130),
|
||||
R_PPC64_D34_HA30(131),
|
||||
R_PPC64_PCREL34(132),
|
||||
R_PPC64_GOT_PCREL34(133),
|
||||
R_PPC64_PLT_PCREL34(134),
|
||||
R_PPC64_PLT_PCREL34_NOTOC(135),
|
||||
R_PPC64_ADDR16_HIGHER34(136),
|
||||
R_PPC64_ADDR16_HIGHERA34(137),
|
||||
R_PPC64_ADDR16_HIGHEST34(138),
|
||||
R_PPC64_ADDR16_HIGHESTA34(139),
|
||||
R_PPC64_REL16_HIGHER34(140),
|
||||
R_PPC64_REL16_HIGHERA34(141),
|
||||
R_PPC64_REL16_HIGHEST34(142),
|
||||
R_PPC64_REL16_HIGHESTA34(143),
|
||||
R_PPC64_D28(144),
|
||||
R_PPC64_PCREL28(145),
|
||||
R_PPC64_TPREL34(146),
|
||||
R_PPC64_DTPREL34(147),
|
||||
R_PPC64_GOT_TLSGD_PCREL34(148),
|
||||
R_PPC64_GOT_TLSLD_PCREL34(149),
|
||||
R_PPC64_GOT_TPREL_PCREL34(150),
|
||||
R_PPC64_GOT_DTPREL_PCREL34(151),
|
||||
|
||||
R_PPC64_REL16_HIGH(240),
|
||||
R_PPC64_REL16_HIGHA(241),
|
||||
R_PPC64_REL16_HIGHER(242),
|
||||
R_PPC64_REL16_HIGHERA(243),
|
||||
R_PPC64_REL16_HIGHEST(244),
|
||||
R_PPC64_REL16_HIGHESTA(245),
|
||||
|
||||
R_PPC64_JMP_IREL(247);
|
||||
|
||||
public final int typeId;
|
||||
|
||||
private PowerPC64_ElfRelocationType(int typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int typeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/* ###
|
||||
* 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 PowerPC_ElfRelocationConstants {
|
||||
|
||||
public static final int R_PPC_NONE = 0;
|
||||
public static final int R_PPC_ADDR32 = 1; // word32 S + A
|
||||
public static final int R_PPC_ADDR24 = 2; // low24 (S + A) >> 2
|
||||
public static final int R_PPC_ADDR16 = 3; // half16 S + A
|
||||
public static final int R_PPC_ADDR16_LO = 4; // half16 #lo(S + A)
|
||||
public static final int R_PPC_ADDR16_HI = 5; // half16 #hi(S + A)
|
||||
public static final int R_PPC_ADDR16_HA = 6; // half16 #ha(S + A)
|
||||
public static final int R_PPC_ADDR14 = 7; // low14 (S + A) >> 2
|
||||
public static final int R_PPC_ADDR14_BRTAKEN = 8; // low14 (S + A) >> 2
|
||||
public static final int R_PPC_ADDR14_BRNTAKEN = 9; // low14 (S + A) >> 2
|
||||
public static final int R_PPC_REL24 = 10; // low24 (S + A - P) >> 2
|
||||
public static final int R_PPC_REL14 = 11; // low14 (S + A - P) >> 2
|
||||
public static final int R_PPC_REL14_BRTAKEN = 12; // low14 (S + A - P) >>
|
||||
// 2
|
||||
public static final int R_PPC_REL14_BRNTAKEN = 13; // low14 (S + A - P) >>
|
||||
// 2
|
||||
public static final int R_PPC_GOT16 = 14; // half16 G + A
|
||||
public static final int R_PPC_GOT16_LO = 15; // half16 #lo(G + A)
|
||||
public static final int R_PPC_GOT16_HI = 16; // half16 #hi(G + A)
|
||||
public static final int R_PPC_GOT16_HA = 17; // half16 #ha(G + A)
|
||||
public static final int R_PPC_PLTREL24 = 18; // low24 (L + A + P) >> 2
|
||||
public static final int R_PPC_COPY = 19; // none none
|
||||
public static final int R_PPC_GLOB_DAT = 20; // word32 S + A
|
||||
public static final int R_PPC_JMP_SLOT = 21; // Old ABI: word32 S + A, New ABI: generate branch instruction
|
||||
public static final int R_PPC_RELATIVE = 22; // word32 S + A
|
||||
public static final int R_PPC_LOCAL24PC = 23; // none
|
||||
public static final int R_PPC_UADDR32 = 24; // low24
|
||||
public static final int R_PPC_UADDR16 = 25; // half16 S + A
|
||||
public static final int R_PPC_REL32 = 26; // word32 S + A - P
|
||||
public static final int R_PPC_PLT32 = 27; // word32 L + A
|
||||
public static final int R_PPC_PLTREL32 = 28; // word32 L + A - P
|
||||
public static final int R_PPC_PLT16_LO = 29; // half16 #lo(L + A)
|
||||
public static final int R_PPC_PLT16_HI = 30; // half16 #hi(L + A)
|
||||
public static final int R_PPC_PLT16_HA = 31; // half16 #ha(L + A)
|
||||
public static final int R_PPC_SDAREL16 = 32; // half16 S + A - _SDA_BASE_
|
||||
public static final int R_PPC_SECTOFF = 33; // half16 R + A
|
||||
public static final int R_PPC_SECTOFF_LO = 34; // half16 #lo(R + A)
|
||||
public static final int R_PPC_SECTOFF_HI = 35; // half16 #hi(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_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;
|
||||
public static final int PPC_LOW24 = 0x03FFFFFC;
|
||||
public static final int PPC_LOW14 = 0x0020FFFC;
|
||||
public static final int PPC_HALF16 = 0xFFFF;
|
||||
|
||||
private PowerPC_ElfRelocationConstants() {
|
||||
// no construct
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* ###
|
||||
* 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 java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.ElfLoadHelper;
|
||||
import ghidra.app.util.bin.format.elf.ElfSymbol;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
public class PowerPC_ElfRelocationContext
|
||||
extends ElfRelocationContext<PowerPC_ElfRelocationHandler> {
|
||||
|
||||
private Integer sdaBase;
|
||||
private Integer sda2Base;
|
||||
|
||||
protected PowerPC_ElfRelocationContext(PowerPC_ElfRelocationHandler handler,
|
||||
ElfLoadHelper loadHelper, Map<ElfSymbol, Address> symbolMap) {
|
||||
super(handler, loadHelper, 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));
|
||||
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));
|
||||
return sda2Base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply register context to all memory blocks which satisfy blockPredicate check.
|
||||
* @param regName register name
|
||||
* @param value context value
|
||||
*/
|
||||
private void setRegisterContext(String regName, BigInteger value) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,26 +15,32 @@
|
||||
*/
|
||||
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.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.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.reloc.Relocation.Status;
|
||||
import ghidra.program.model.reloc.RelocationResult;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.*;
|
||||
|
||||
public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
public class PowerPC_ElfRelocationHandler extends
|
||||
AbstractElfRelocationHandler<PowerPC_ElfRelocationType, PowerPC_ElfRelocationContext> {
|
||||
|
||||
// Masks for manipulating Power PC relocation targets
|
||||
private static final int PPC_WORD32 = 0xFFFFFFFF;
|
||||
private static final int PPC_WORD30 = 0xFFFFFFFC;
|
||||
private static final int PPC_LOW24 = 0x03FFFFFC;
|
||||
private static final int PPC_LOW14 = 0x0020FFFC;
|
||||
private static final int PPC_HALF16 = 0xFFFF;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PowerPC_ElfRelocationHandler() {
|
||||
super(PowerPC_ElfRelocationType.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(ElfHeader elf) {
|
||||
@@ -48,43 +54,19 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
|
||||
ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
protected RelocationResult relocate(PowerPC_ElfRelocationContext elfRelocationContext,
|
||||
ElfRelocation relocation, PowerPC_ElfRelocationType type, Address relocationAddress,
|
||||
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
|
||||
throws MemoryAccessException {
|
||||
|
||||
PowerPC_ElfRelocationContext ppcRelocationContext =
|
||||
(PowerPC_ElfRelocationContext) elfRelocationContext;
|
||||
|
||||
ElfHeader elf = ppcRelocationContext.getElfHeader();
|
||||
if (elf.e_machine() != ElfConstants.EM_PPC || !elf.is32Bit()) {
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
|
||||
Program program = ppcRelocationContext.getProgram();
|
||||
Program program = elfRelocationContext.getProgram();
|
||||
Memory memory = program.getMemory();
|
||||
|
||||
int type = relocation.getType();
|
||||
if (type == PowerPC_ElfRelocationConstants.R_PPC_NONE) {
|
||||
return RelocationResult.SKIPPED;
|
||||
}
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
||||
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",
|
||||
ppcRelocationContext.getLog());
|
||||
// TODO: should we return failure status?
|
||||
}
|
||||
|
||||
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
|
||||
int addend = (int) relocation.getAddend();
|
||||
|
||||
int offset = (int) relocationAddress.getOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
|
||||
|
||||
// if (sym.isLocal() && sym.getSectionHeaderIndex() != ElfSectionHeaderConstants.SHN_UNDEF) {
|
||||
//
|
||||
// // see glibc - sysdeps/powerpc/powerpc32/dl-machine.h elf_machine_rela
|
||||
@@ -93,49 +75,44 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
//
|
||||
// // Relocation addend already includes original symbol value but needs to account
|
||||
// // for any image base adjustment
|
||||
// symbolValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
// symbolValue = elfRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
// }
|
||||
// else {
|
||||
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
|
||||
int symbolValue = (int) elfRelocationContext.getSymbolValue(sym);
|
||||
// }
|
||||
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
|
||||
|
||||
int offset = (int) relocationAddress.getOffset();
|
||||
int oldValue = memory.getInt(relocationAddress);
|
||||
int newValue = 0;
|
||||
|
||||
int byteLength = 4; // most relocations affect 4-bytes (change if different)
|
||||
|
||||
switch (type) {
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_COPY:
|
||||
markAsWarning(program, relocationAddress, "R_PPC_COPY", symbolName,
|
||||
symbolIndex, "Runtime copy not supported", elfRelocationContext.getLog());
|
||||
case R_PPC_COPY:
|
||||
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
|
||||
"Runtime copy not supported", elfRelocationContext.getLog());
|
||||
return RelocationResult.SKIPPED;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR32:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_UADDR32:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_GLOB_DAT:
|
||||
newValue = symbolValue + addend;
|
||||
case R_PPC_ADDR32:
|
||||
case R_PPC_UADDR32:
|
||||
case R_PPC_GLOB_DAT:
|
||||
newValue = (int) symbolValue + addend;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
|
||||
warnExternalOffsetRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||
warnExternalOffsetRelocation(program, relocationAddress, symbolAddr, symbolName,
|
||||
addend, elfRelocationContext.getLog());
|
||||
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||
}
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR24:
|
||||
newValue = (symbolValue + addend) >> 2;
|
||||
newValue = (oldValue & ~PowerPC_ElfRelocationConstants.PPC_LOW24) | (newValue << 2);
|
||||
case R_PPC_ADDR24:
|
||||
newValue = ((int) symbolValue + addend) >> 2;
|
||||
newValue = (oldValue & ~PPC_LOW24) | (newValue << 2);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR16:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_UADDR16:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR16_LO:
|
||||
newValue = symbolValue + addend;
|
||||
case R_PPC_ADDR16:
|
||||
case R_PPC_UADDR16:
|
||||
case R_PPC_ADDR16_LO:
|
||||
newValue = (int) symbolValue + addend;
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR16_HI:
|
||||
newValue = (symbolValue + addend) >> 16;
|
||||
case R_PPC_ADDR16_HI:
|
||||
newValue = ((int) symbolValue + addend) >> 16;
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
@@ -168,44 +145,43 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
|
||||
*/
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR16_HA:
|
||||
newValue = (symbolValue + addend + 0x8000) >> 16;
|
||||
case R_PPC_ADDR16_HA:
|
||||
newValue = ((int) symbolValue + addend + 0x8000) >> 16;
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
byteLength = 2;
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR14:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR14_BRTAKEN:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR14_BRNTAKEN:
|
||||
newValue = (symbolValue + addend) >> 2;
|
||||
newValue = (oldValue & ~PowerPC_ElfRelocationConstants.PPC_LOW14) |
|
||||
((newValue << 2) & PowerPC_ElfRelocationConstants.PPC_LOW24);
|
||||
case R_PPC_ADDR14:
|
||||
case R_PPC_ADDR14_BRTAKEN:
|
||||
case R_PPC_ADDR14_BRNTAKEN:
|
||||
newValue = ((int) symbolValue + addend) >> 2;
|
||||
newValue = (oldValue & ~PPC_LOW14) | ((newValue << 2) & PPC_LOW24);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL24:
|
||||
newValue = (symbolValue + addend - offset) >> 2;
|
||||
newValue = ((newValue << 2) & PowerPC_ElfRelocationConstants.PPC_LOW24);
|
||||
newValue = (oldValue & ~PowerPC_ElfRelocationConstants.PPC_LOW24) | newValue;
|
||||
case R_PPC_REL24:
|
||||
newValue = ((int) symbolValue + addend - offset) >> 2;
|
||||
newValue = ((newValue << 2) & PPC_LOW24);
|
||||
newValue = (oldValue & ~PPC_LOW24) | newValue;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_RELATIVE:
|
||||
newValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||
case R_PPC_RELATIVE:
|
||||
newValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL32:
|
||||
newValue = (symbolValue + addend - offset);
|
||||
case R_PPC_REL32:
|
||||
newValue = ((int) symbolValue + addend - offset);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL14:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL14_BRTAKEN:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_REL14_BRNTAKEN:
|
||||
newValue = (symbolValue + addend - offset) >> 2;
|
||||
newValue = (oldValue & ~PowerPC_ElfRelocationConstants.PPC_LOW14) |
|
||||
((newValue << 2) & PowerPC_ElfRelocationConstants.PPC_LOW14);
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
newValue = ((int) symbolValue + addend - offset) >> 2;
|
||||
newValue = (oldValue & ~PPC_LOW14) | ((newValue << 2) & PPC_LOW14);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_JMP_SLOT:
|
||||
int value = symbolValue + addend;
|
||||
ElfDynamicTable dynamicTable = elf.getDynamicTable();
|
||||
case R_PPC_JMP_SLOT:
|
||||
int value = (int) symbolValue + addend;
|
||||
ElfDynamicTable dynamicTable =
|
||||
elfRelocationContext.getElfHeader().getDynamicTable();
|
||||
if (dynamicTable != null &&
|
||||
dynamicTable.containsDynamicValue(PowerPC_ElfExtension.DT_PPC_GOT)) {
|
||||
// Old ABI - presence of dynamic entry DT_PPC_GOT used as indicator
|
||||
@@ -228,11 +204,11 @@ 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,
|
||||
ppcRelocationContext.getLog());
|
||||
elfRelocationContext.getLog());
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_EMB_SDA21:
|
||||
case 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.
|
||||
@@ -241,7 +217,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
oldValue = memory.getInt(relocationAddress);
|
||||
|
||||
Address symAddr = ppcRelocationContext.getSymbolAddress(sym);
|
||||
Address symAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
MemoryBlock block = memory.getBlock(symAddr);
|
||||
Integer sdaBase = null;
|
||||
Integer gprID = null;
|
||||
@@ -249,11 +225,11 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
if (block != null) {
|
||||
String blockName = block.getName();
|
||||
if (".sdata".equals(blockName) || ".sbss".equals(blockName)) {
|
||||
sdaBase = ppcRelocationContext.getSDABase();
|
||||
sdaBase = elfRelocationContext.getSDABase();
|
||||
gprID = 13;
|
||||
}
|
||||
else if (".sdata2".equals(blockName) || ".sbss2".equals(blockName)) {
|
||||
sdaBase = ppcRelocationContext.getSDA2Base();
|
||||
sdaBase = elfRelocationContext.getSDA2Base();
|
||||
gprID = 2;
|
||||
}
|
||||
else if (".PPC.EMB.sdata0".equals(blockName) ||
|
||||
@@ -262,19 +238,19 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
gprID = 0;
|
||||
}
|
||||
else if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(blockName)) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
|
||||
"Unsupported relocation for external symbol",
|
||||
ppcRelocationContext.getLog());
|
||||
elfRelocationContext.getLog());
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
}
|
||||
if (gprID == null || sdaBase == null) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"Failed to identfy appropriate data block", ppcRelocationContext.getLog());
|
||||
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
|
||||
"Failed to identfy appropriate data block", elfRelocationContext.getLog());
|
||||
return RelocationResult.FAILURE;
|
||||
}
|
||||
|
||||
newValue = (symbolValue - sdaBase + addend) & 0xffff;
|
||||
newValue = ((int) symbolValue - sdaBase + addend) & 0xffff;
|
||||
newValue |= gprID << 16;
|
||||
newValue |= oldValue & 0xffe00000;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
@@ -282,147 +258,10 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
default:
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
ppcRelocationContext.getLog());
|
||||
elfRelocationContext.getLog());
|
||||
return RelocationResult.UNSUPPORTED;
|
||||
}
|
||||
return new RelocationResult(Status.APPLIED, byteLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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, Map<ElfSymbol, Address> symbolMap) {
|
||||
super(handler, loadHelper, 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/* ###
|
||||
* 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 enum PowerPC_ElfRelocationType implements ElfRelocationType {
|
||||
|
||||
R_PPC_NONE(0),
|
||||
R_PPC_ADDR32(1), // word32 S + A
|
||||
R_PPC_ADDR24(2), // low24 (S + A) >> 2
|
||||
R_PPC_ADDR16(3), // half16 S + A
|
||||
R_PPC_ADDR16_LO(4), // half16 #lo(S + A)
|
||||
R_PPC_ADDR16_HI(5), // half16 #hi(S + A)
|
||||
R_PPC_ADDR16_HA(6), // half16 #ha(S + A)
|
||||
R_PPC_ADDR14(7), // low14 (S + A) >> 2
|
||||
R_PPC_ADDR14_BRTAKEN(8), // low14 (S + A) >> 2
|
||||
R_PPC_ADDR14_BRNTAKEN(9), // low14 (S + A) >> 2
|
||||
R_PPC_REL24(10), // low24 (S + A - P) >> 2
|
||||
R_PPC_REL14(11), // low14 (S + A - P) >> 2
|
||||
R_PPC_REL14_BRTAKEN(12), // low14 (S + A - P) >> 2
|
||||
R_PPC_REL14_BRNTAKEN(13), // low14 (S + A - P) >> 2
|
||||
R_PPC_GOT16(14), // half16 G + A
|
||||
R_PPC_GOT16_LO(15), // half16 #lo(G + A)
|
||||
R_PPC_GOT16_HI(16), // half16 #hi(G + A)
|
||||
R_PPC_GOT16_HA(17), // half16 #ha(G + A)
|
||||
R_PPC_PLTREL24(18), // low24 (L + A + P) >> 2
|
||||
R_PPC_COPY(19), // none none
|
||||
R_PPC_GLOB_DAT(20), // word32 S + A
|
||||
R_PPC_JMP_SLOT(21), // Old ABI: word32 S + A, New ABI: generate branch instruction
|
||||
R_PPC_RELATIVE(22), // word32 S + A
|
||||
R_PPC_LOCAL24PC(23), // none
|
||||
R_PPC_UADDR32(24), // low24
|
||||
R_PPC_UADDR16(25), // half16 S + A
|
||||
R_PPC_REL32(26), // word32 S + A - P
|
||||
R_PPC_PLT32(27), // word32 L + A
|
||||
R_PPC_PLTREL32(28), // word32 L + A - P
|
||||
R_PPC_PLT16_LO(29), // half16 #lo(L + A)
|
||||
R_PPC_PLT16_HI(30), // half16 #hi(L + A)
|
||||
R_PPC_PLT16_HA(31), // half16 #ha(L + A)
|
||||
R_PPC_SDAREL16(32), // half16 S + A - _SDA_BASE_
|
||||
R_PPC_SECTOFF(33), // half16 R + A
|
||||
R_PPC_SECTOFF_LO(34), // half16 #lo(R + A)
|
||||
R_PPC_SECTOFF_HI(35), // half16 #hi(R + A)
|
||||
R_PPC_SECTOFF_HA(36), // half16 #ha(R + A)
|
||||
R_PPC_ADDR30(37), // word30 (S + A - P) >> 2
|
||||
|
||||
R_POWERPC_TLS(67),
|
||||
R_POWERPC_DTPMOD(68),
|
||||
R_POWERPC_TPREL16(69),
|
||||
R_POWERPC_TPREL16_LO(70),
|
||||
R_POWERPC_TPREL16_HI(71),
|
||||
R_POWERPC_TPREL16_HA(72),
|
||||
R_POWERPC_TPREL(73),
|
||||
R_POWERPC_DTPREL16(74),
|
||||
R_POWERPC_DTPREL16_LO(75),
|
||||
R_POWERPC_DTPREL16_HI(76),
|
||||
R_POWERPC_DTPREL16_HA(77),
|
||||
R_POWERPC_DTPREL(78),
|
||||
R_POWERPC_GOT_TLSGD16(79),
|
||||
R_POWERPC_GOT_TLSGD16_LO(80),
|
||||
R_POWERPC_GOT_TLSGD16_HI(81),
|
||||
R_POWERPC_GOT_TLSGD16_HA(82),
|
||||
R_POWERPC_GOT_TLSLD16(83),
|
||||
R_POWERPC_GOT_TLSLD16_LO(84),
|
||||
R_POWERPC_GOT_TLSLD16_HI(85),
|
||||
R_POWERPC_GOT_TLSLD16_HA(86),
|
||||
R_POWERPC_GOT_TPREL16(87),
|
||||
R_POWERPC_GOT_TPREL16_LO(88),
|
||||
R_POWERPC_GOT_TPREL16_HI(89),
|
||||
R_POWERPC_GOT_TPREL16_HA(90),
|
||||
R_POWERPC_GOT_DTPREL16(91),
|
||||
R_POWERPC_GOT_DTPREL16_LO(92),
|
||||
R_POWERPC_GOT_DTPREL16_HI(93),
|
||||
R_POWERPC_GOT_DTPREL16_HA(94),
|
||||
R_PPC_TLSGD(95),
|
||||
R_PPC_TLSLD(96),
|
||||
|
||||
R_PPC_EMB_NADDR32(101), // uword32 (A - S)
|
||||
R_PPC_EMB_NADDR16(102), // uhalf16 (A - S)
|
||||
R_PPC_EMB_NADDR16_LO(103), // uhalf16 #lo(A - S)
|
||||
R_PPC_EMB_NADDR16_HI(104), // uhalf16 #hi(A - S)
|
||||
R_PPC_EMB_NADDR16_HA(105), // uhalf16 #ha(A - S)
|
||||
R_PPC_EMB_SDAI16(106), // uhalf16 T
|
||||
R_PPC_EMB_SDA2I16(107), // uhalf16 U
|
||||
R_PPC_EMB_SDA2REL(108), // uhalf16 S + A - _SDA2_BASE_
|
||||
R_PPC_EMB_SDA21(109), // ulow21
|
||||
R_PPC_EMB_MRKREF(110), // none
|
||||
R_PPC_EMB_RELSEC16(111), // uhalf16 V + A
|
||||
R_PPC_EMB_RELST_LO(112), // uhalf16 #lo(W + A)
|
||||
R_PPC_EMB_RELST_HI(113), // uhalf16 #hi(W + A)
|
||||
R_PPC_EMB_RELST_HA(114), // uhalf16 #ha(W + A)
|
||||
R_PPC_EMB_BIT_FLD(115), // uword32
|
||||
R_PPC_EMB_RELSDA(116), // uhalf16
|
||||
|
||||
R_POWERPC_PLTSEQ(119),
|
||||
R_POWERPC_PLTCALL(120),
|
||||
|
||||
R_PPC_VLE_REL8(216),
|
||||
R_PPC_VLE_REL15(217),
|
||||
R_PPC_VLE_REL24(218),
|
||||
R_PPC_VLE_LO16A(219),
|
||||
R_PPC_VLE_LO16D(220),
|
||||
R_PPC_VLE_HI16A(221),
|
||||
R_PPC_VLE_HI16D(222),
|
||||
R_PPC_VLE_HA16A(223),
|
||||
R_PPC_VLE_HA16D(224),
|
||||
R_PPC_VLE_SDA21(225),
|
||||
R_PPC_VLE_SDA21_LO(226),
|
||||
R_PPC_VLE_SDAREL_LO16A(227),
|
||||
R_PPC_VLE_SDAREL_LO16D(228),
|
||||
R_PPC_VLE_SDAREL_HI16A(229),
|
||||
R_PPC_VLE_SDAREL_HI16D(230),
|
||||
R_PPC_VLE_SDAREL_HA16A(231),
|
||||
R_PPC_VLE_SDAREL_HA16D(232),
|
||||
|
||||
R_POWERPC_REL16DX_HA(246),
|
||||
R_POWERPC_IRELATIVE(248),
|
||||
R_POWERPC_REL16(249),
|
||||
R_POWERPC_REL16_LO(250),
|
||||
R_POWERPC_REL16_HI(251),
|
||||
R_POWERPC_REL16_HA(252),
|
||||
R_POWERPC_GNU_VTINHERIT(253),
|
||||
R_POWERPC_GNU_VTENTRY(254),
|
||||
R_PPC_TOC16(255);
|
||||
|
||||
public final int typeId;
|
||||
|
||||
private PowerPC_ElfRelocationType(int typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int typeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user