GP-4239 Transitioned to new AbstractElfRelocationHandler implementation which uses ElfRelocationType enums specific to each handler.

This commit is contained in:
ghidra1
2024-02-12 10:52:25 -05:00
parent f01a7172c7
commit 3ead54f0ac
71 changed files with 4921 additions and 4934 deletions

View File

@@ -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 " +

View File

@@ -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
}
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}