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

@ -0,0 +1,65 @@
/* ###
* 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.plugin.core.reloc;
import java.util.HashMap;
import java.util.Map;
import ghidra.app.util.bin.format.elf.relocation.ElfRelocationType;
public abstract class ElfRelocationFixupHandler extends RelocationFixupHandler {
private Map<Integer, ElfRelocationType> relocationTypesMap;
/**
* Abstract constructor for an {@link ElfRelocationFixupHandler}.
*
* @param relocationEnumClass specifies the {@link ElfRelocationType} enum which defines
* all supported relocation types for this relocation handler.
*/
protected ElfRelocationFixupHandler(Class<? extends ElfRelocationType> relocationEnumClass) {
initRelocationTypeMap(relocationEnumClass);
}
private void initRelocationTypeMap(Class<? extends ElfRelocationType> relocationEnumClass) {
if (!relocationEnumClass.isEnum() ||
!ElfRelocationType.class.isAssignableFrom(relocationEnumClass)) {
throw new IllegalArgumentException(
"Invalid class specified - expected enum which implements ElfRelocationType: " +
relocationEnumClass.getName());
}
relocationTypesMap = new HashMap<>();
for (ElfRelocationType t : relocationEnumClass.getEnumConstants()) {
relocationTypesMap.put(t.typeId(), t);
}
}
/**
* Get the relocation type enum value which corresponds to the specified type value.
*
* @param type relocation type value
* @return relocation type enum value or null if type not found or this handler was not
* constructed with a {@link ElfRelocationType} enum class. The returned value may be
* safely cast to the relocation enum class specified during handler construction.
*/
public ElfRelocationType getRelocationType(int type) {
if (relocationTypesMap == null) {
return null;
}
return relocationTypesMap.get(type);
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,15 +25,21 @@ import ghidra.util.classfinder.ExtensionPoint;
public abstract class RelocationFixupHandler implements ExtensionPoint {
/**
* Default abstract constructor for an {@link RelocationFixupHandler}.
*/
protected RelocationFixupHandler() {
}
public abstract boolean processRelocation(Program program, Relocation relocation,
Address oldImageBase, Address newImageBase) throws MemoryAccessException,
CodeUnitInsertionException;
Address oldImageBase, Address newImageBase)
throws MemoryAccessException, CodeUnitInsertionException;
public abstract boolean handlesProgram(Program program);
protected boolean process32BitRelocation(Program program, Relocation relocation,
Address oldImageBase, Address newImageBase) throws MemoryAccessException,
CodeUnitInsertionException {
Address oldImageBase, Address newImageBase)
throws MemoryAccessException, CodeUnitInsertionException {
long diff = newImageBase.subtract(oldImageBase);
Address address = relocation.getAddress();
@ -52,8 +57,8 @@ public abstract class RelocationFixupHandler implements ExtensionPoint {
}
public boolean process64BitRelocation(Program program, Relocation relocation,
Address oldImageBase, Address newImageBase) throws MemoryAccessException,
CodeUnitInsertionException {
Address oldImageBase, Address newImageBase)
throws MemoryAccessException, CodeUnitInsertionException {
long diff = newImageBase.subtract(oldImageBase);

View file

@ -22,7 +22,7 @@ import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter;
import ghidra.app.util.bin.format.elf.relocation.ElfRelocationContext;
import ghidra.app.util.bin.format.elf.relocation.ElfRelocationHandler;
import ghidra.app.util.bin.format.elf.relocation.AbstractElfRelocationHandler;
import ghidra.program.model.data.*;
/**
@ -62,7 +62,7 @@ import ghidra.program.model.data.*;
*
* RELR entry (see SHT_RELR, DT_RELR):
* NOTE: Relocation type is data <i>relative</i> and must be specified by appropriate relocation handler
* (see {@link ElfRelocationHandler#getRelrRelocationType()}) since it is not contained within the
* (see {@link AbstractElfRelocationHandler#getRelrRelocationType()}) since it is not contained within the
* relocation table which only specifies <i>r_offset</i> for each entry.
*
* </pre>
@ -272,27 +272,27 @@ public class ElfRelocation implements StructConverter {
}
/**
* The type of relocation to apply.
* NOTE 1: Relocation types are processor-specific (see {@link ElfRelocationHandler}).
* NOTE 2: A type of 0 is returned by default for RELR relocations and must be updated
* The type ID value for this relocation
* NOTE 1: Relocation types are processor-specific (see {@link AbstractElfRelocationHandler}).
* NOTE 2: A type ID of 0 is returned by default for RELR relocations and must be updated
* during relocation processing (see {@link #setType(long)}). The appropriate RELR
* relocation type can be obtained from the appropriate
* {@link ElfRelocationHandler#getRelrRelocationType()} or
* {@link AbstractElfRelocationHandler#getRelrRelocationType()} or
* {@link ElfRelocationContext#getRelrRelocationType()} if available.
* @return type of relocation to apply
* @return type ID for this relocation
*/
public int getType() {
return (int) (is32bit ? (r_info & BYTE_MASK) : (r_info & INT_MASK));
}
/**
* Set the relocation type associated with this relocation.
* Set the relocation type ID associated with this relocation.
* Updating the relocation type is required for RELR relocations.
* @param type relocation type to be applied
* @param typeId relocation type ID value for this relocation
*/
public void setType(long type) {
public void setType(long typeId) {
long mask = is32bit ? BYTE_MASK : INT_MASK;
r_info = (r_info & ~mask) + (type & mask);
r_info = (r_info & ~mask) + (typeId & mask);
}
/**

View file

@ -0,0 +1,237 @@
/* ###
* 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.util.HashMap;
import java.util.Map;
import ghidra.app.util.bin.format.elf.ElfRelocation;
import ghidra.app.util.bin.format.elf.ElfSymbol;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.BookmarkType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.classfinder.ClassSearcher;
/**
* <code>ElfRelocationHandler</code> provides the base class for processor specific
* ELF relocation handlers. Implementations may only specify a public default constructor
* as they will be identified and instatiated by the {@link ClassSearcher}. As such their
* name must end with "ElfRelocationHandler" (e.g., MyProc_ElfRelocationHandler).
*
* @param <T> ELF relocation type enum class
* @param <C> ELF relocation context class
*/
abstract public class AbstractElfRelocationHandler<T extends ElfRelocationType, C extends ElfRelocationContext<?>>
extends ElfRelocationHandler {
private Map<Integer, T> relocationTypesMap;
/**
* Abstract constructor for an {@link AbstractElfRelocationHandler}.
*
* @param relocationEnumClass specifies the {@link ElfRelocationType} enum which defines
* all supported relocation types for this relocation handler.
*/
protected AbstractElfRelocationHandler(Class<T> relocationEnumClass) {
super(); // must continue to use ElfRelocationHandler until eliminated
initRelocationTypeMap(relocationEnumClass);
}
private void initRelocationTypeMap(Class<T> relocationEnumClass) {
if (!relocationEnumClass.isEnum() ||
!ElfRelocationType.class.isAssignableFrom(relocationEnumClass)) {
throw new IllegalArgumentException(
"Invalid class specified - expected enum which implements ElfRelocationType: " +
relocationEnumClass.getName());
}
relocationTypesMap = new HashMap<>();
for (T t : relocationEnumClass.getEnumConstants()) {
relocationTypesMap.put(t.typeId(), t);
}
}
/**
* Get the relocation type enum object which corresponds to the specified type ID value.
*
* @param typeId relocation type ID value
* @return relocation type enum value or null if type not found or this handler was not
* constructed with a {@link ElfRelocationType} enum class. The returned value may be
* safely cast to the relocation enum class specified during handler construction.
*/
public T getRelocationType(int typeId) {
if (relocationTypesMap == null) {
return null;
}
return relocationTypesMap.get(typeId);
}
/**
* Perform relocation fixup.
*
* @param elfRelocationContext relocation context
* @param relocation ELF relocation
* @param relocationAddress relocation target address (fixup location)
* @return applied relocation result (conveys status and applied byte-length)
* @throws MemoryAccessException memory access failure
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected final RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress) throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
int typeId = relocation.getType();
if (typeId == 0) {
return RelocationResult.SKIPPED;
}
T type = getRelocationType(typeId);
if (type == null) {
markAsUndefined(program, relocationAddress, typeId, symbolName, symbolIndex,
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
return relocate((C) elfRelocationContext, relocation, type, relocationAddress, sym,
symbolAddr, symbolValue, symbolName);
}
/**
* Perform relocation fixup.
*
* @param elfRelocationContext relocation context
* @param relocation ELF relocation
* @param relocationType ELF relocation type enum value
* @param relocationAddress relocation target address (fixup location)
* @param elfSymbol relocation symbol (may be null)
* @param symbolAddr elfSymbol memory address (may be null)
* @param symbolValue unadjusted elfSymbol value (0 if no symbol)
* @param symbolName elfSymbol name (may be null)
* @return applied relocation result (conveys status and applied byte-length)
* @throws MemoryAccessException memory access failure
*/
protected abstract RelocationResult relocate(C elfRelocationContext, ElfRelocation relocation,
T relocationType, Address relocationAddress, ElfSymbol elfSymbol, Address symbolAddr,
long symbolValue, String symbolName) throws MemoryAccessException;
//
// Error and Warning markup methods
//
// private String getRelocationTypeDetail(int typeId) {
// T relocationType = relocationTypesMap.get(typeId);
// if (relocationType == null) {
// return getDefaultRelocationTypeDetail(typeId);
// }
// return getRelocationTypeDetail(relocationType);
// }
private String getRelocationTypeDetail(T relocationType) {
int typeId = relocationType.typeId();
return relocationType.name() + " (" + typeId + ", 0x" + Integer.toHexString(typeId) + ")";
}
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unhandled relocation.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value
* @param symbolIndex associated symbol index within symbol table
* @param symbolName associated symbol name
* @param log import log
*/
protected void markAsUndefined(Program program, Address relocationAddress, int typeId,
String symbolName, int symbolIndex, MessageLog log) {
markupErrorOrWarning(program, "Undefined ELF Relocation", null, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unhandled relocation.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param relocationType relocation type
* @param symbolIndex associated symbol index within symbol table
* @param symbolName associated symbol name
* @param log import log
*/
protected void markAsUnhandled(Program program, Address relocationAddress, T relocationType,
int symbolIndex, String symbolName, MessageLog log) {
markupErrorOrWarning(program, "Unhandled ELF Relocation", null, relocationAddress,
getRelocationTypeDetail(relocationType), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
/**
* Generate relocation warning log entry and bookmark at relocationAddress.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param relocationType relocation type
* @param symbolName symbol name
* @param symbolIndex symbol index (-1 to ignore)
* @param msg message associated with warning
* @param log import log
*/
protected void markAsWarning(Program program, Address relocationAddress, T relocationType,
String symbolName, int symbolIndex, String msg, MessageLog log) {
markupErrorOrWarning(program, "ELF Relocation Failure", msg, relocationAddress,
getRelocationTypeDetail(relocationType), symbolIndex, symbolName, BookmarkType.WARNING,
log);
}
/**
* Generate relocation error log entry and bookmark at relocationAddress.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param relocationType relocation type
* @param symbolName associated symbol name
* @param symbolIndex symbol index (-1 to ignore)
* @param msg additional error message
* @param log import log
*/
protected void markAsError(Program program, Address relocationAddress, T relocationType,
String symbolName, int symbolIndex, String msg, MessageLog log) {
markupErrorOrWarning(program, "Elf Relocation Failure", msg, relocationAddress,
getRelocationTypeDetail(relocationType), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
// @Override
// protected void markAsError(Program program, Address relocationAddress, int typeId,
// String symbolName, int symbolIndex, String msg, MessageLog log) {
// markupErrorOrWarning(program, "ELF Relocation Error", msg, relocationAddress,
// getRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR, log);
// }
}

View file

@ -17,8 +17,6 @@ package ghidra.app.util.bin.format.elf.relocation;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter;
import ghidra.app.util.importer.MessageLog;
@ -32,10 +30,12 @@ import ghidra.util.exception.*;
/**
* <code>ElfRelocationContext</code> provides a relocation handler context related
* to the processing of entries contained within a specific relocation table.
*
* @param <H> ELF relocation handler class
*/
public class ElfRelocationContext {
public class ElfRelocationContext<H extends ElfRelocationHandler> {
protected final ElfRelocationHandler handler;
protected final H handler;
protected final ElfLoadHelper loadHelper;
protected final Map<ElfSymbol, Address> symbolMap;
protected final Program program;
@ -51,12 +51,16 @@ public class ElfRelocationContext {
* @param loadHelper the elf load helper
* @param symbolMap Elf symbol placement map
*/
protected ElfRelocationContext(ElfRelocationHandler handler, ElfLoadHelper loadHelper,
protected ElfRelocationContext(H handler, ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
this.handler = handler;
this.loadHelper = loadHelper;
this.symbolMap = symbolMap;
this.program = loadHelper.getProgram();
if (handler == null) {
loadHelper.log("Unable to process ELF relocations: relocation handler not found");
}
}
/**
@ -83,7 +87,7 @@ public class ElfRelocationContext {
/**
* Process a relocation from the relocation table which corresponds to this context.
* All relocation entries must be processed in the order they appear within the table.
* All relocation entries will be processed in the order they appear within the table.
* @param relocation relocation to be processed
* @param relocationAddress relocation address where it should be applied
* @return applied relocation result
@ -91,81 +95,104 @@ public class ElfRelocationContext {
public final RelocationResult processRelocation(ElfRelocation relocation,
Address relocationAddress) {
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = getSymbol(symbolIndex);
if (handler == null) {
handleNoHandlerError(relocation, relocationAddress);
String symbolName = sym != null ? sym.getNameAsString() : null;
ElfRelocationHandler.bookmarkNoHandlerError(program, relocationAddress,
relocation.getType(), symbolIndex, symbolName);
return RelocationResult.FAILURE;
}
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = getSymbol(symbolIndex);
if (sym == null) {
ElfRelocationHandler.markAsError(program, relocationAddress, relocation.getType(), null,
"invalid symbol index (" + symbolIndex + ")", getLog());
handler.markAsError(program, relocationAddress, relocation.getType(), null, -1,
"Invalid symbol index (" + symbolIndex + ")", getLog());
return RelocationResult.FAILURE;
}
if (sym.isTLS()) {
handleUnsupportedTLSRelocation(relocation, relocationAddress, sym);
return RelocationResult.FAILURE;
handler.markAsWarning(program, relocationAddress, relocation.getType(),
sym.getNameAsString(), symbolIndex, "Relocation for TLS Symbol not supported",
getLog());
return RelocationResult.UNSUPPORTED;
}
try {
return handler.relocate(this, relocation, relocationAddress);
return processRelocation(relocation, sym, relocationAddress);
}
catch (MemoryAccessException | NotFoundException e) {
loadHelper.log(e);
ElfRelocationHandler.markAsUnhandled(program, relocationAddress, relocation.getType(),
symbolIndex, sym.getNameAsString(), getLog());
handler.markAsError(program, relocationAddress, relocation.getType(),
sym.getNameAsString(), symbolIndex, "Processing Failure - " + e.getMessage(),
getLog());
}
return RelocationResult.FAILURE;
}
/**
* Process a relocation from the relocation table which corresponds to this context
* after preliminary checks have been performed and ELF symbol resolved.
* All relocation entries will be processed in the order they appear within the table.
*
* @param relocation relocation to be processed
* @param elfSymbol resolved ELF symbol (not null)
* @param relocationAddress relocation address where it should be applied
* @return applied relocation result
* @throws MemoryAccessException if a memory access error occurs
* @throws NotFoundException NOTE: use of this exception is deprecated and should not be thrown
*/
protected RelocationResult processRelocation(ElfRelocation relocation, ElfSymbol elfSymbol,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
return handler.relocate(this, relocation, relocationAddress);
}
/**
* Generate relocation error log entry and bookmark.
*
* @param relocationAddress relocation address
* @param typeId relocation type ID value (will get mapped to {@link ElfRelocationType#name()}
* if possible).
* @param symbolIndex associated symbol index within symbol table (-1 to ignore)
* @param symbolName relocation symbol name or null if unknown
* @param msg error message
*/
public final void markRelocationError(Address relocationAddress, int typeId, int symbolIndex,
String symbolName, String msg) {
if (handler != null) {
handler.markAsError(program, relocationAddress, typeId, symbolName, -1, msg, getLog());
}
else {
// must use static method without relocation type resolution
ElfRelocationHandler.markAsError(program, relocationAddress, typeId, symbolIndex,
symbolName, msg, getLog());
}
}
/**
* Get the RELR relocation type associated with the underlying
* relocation handler.
* @return RELR relocation type or 0 if not supported
*/
public long getRelrRelocationType() {
public int getRelrRelocationType() {
return handler != null ? handler.getRelrRelocationType() : 0;
}
private void handleUnsupportedTLSRelocation(ElfRelocation relocation, Address relocationAddress,
ElfSymbol sym) {
ElfRelocationHandler.markAsError(program, relocationAddress, relocation.getType(),
sym.getNameAsString(), "TLS symbol relocation not yet supported", getLog());
}
private void handleNoHandlerError(ElfRelocation relocation, Address relocationAddress) {
String symName = getSymbolName(relocation.getSymbolIndex());
String nameMsg = "";
if (!StringUtils.isBlank(symName)) {
nameMsg = " to: " + symName;
}
program.getBookmarkManager()
.setBookmark(relocationAddress, BookmarkType.ERROR, "Relocation",
"No handler to process ELF Relocation" + nameMsg);
loadHelper.log(
"WARNING: At " + relocationAddress + " no handler to process ELF Relocation" + nameMsg);
}
/**
* Get a relocation context for a specfic Elf image and relocation table
* @param loadHelper Elf load helper
* @param symbolMap Elf symbol placement map
* @return relocation context or null
* @return relocation context object
*/
public static ElfRelocationContext getRelocationContext(ElfLoadHelper loadHelper,
public static ElfRelocationContext<?> getRelocationContext(ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
ElfHeader elf = loadHelper.getElfHeader();
ElfRelocationContext context = null;
ElfRelocationContext<?> context = null;
ElfRelocationHandler handler = ElfRelocationHandlerFactory.getHandler(elf);
if (handler != null) {
context = handler.createRelocationContext(loadHelper, symbolMap);
}
if (context == null) {
context = new ElfRelocationContext(handler, loadHelper, symbolMap);
context = new ElfRelocationContext<>(handler, loadHelper, symbolMap);
}
return context;
}

View file

@ -31,12 +31,20 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.classfinder.ExtensionPoint;
import ghidra.util.exception.NotFoundException;
/**
* NOTE: ELF relocation handler implementations should extend {@link AbstractElfRelocationHandler}
* which now uses {@link ElfRelocationType} enum values instead of simple constants. This class may
* transition to an interface in the future. This abstract class remains exposed for backward
* compatibility with older implementations.
* <br>
* <code>ElfRelocationHandler</code> provides the base class for processor specific
* ELF relocation handlers.
* ELF relocation handlers. Implementations may only specify a public default constructor
* as they will be identified and instatiated by the {@link ClassSearcher}. As such their
* name must end with "ElfRelocationHandler" (e.g., MyProc_ElfRelocationHandler).
*/
abstract public class ElfRelocationHandler implements ExtensionPoint {
@ -46,14 +54,24 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
*/
public static final String GOT_BLOCK_NAME = "%got";
/**
* Default abstract constructor for an {@link ElfRelocationHandler}.
*
* @deprecated extending {@link AbstractElfRelocationHandler} in conjunction with the use of
* a processor-specific {@link ElfRelocationType} enum is now preferred.
*/
@Deprecated(since = "11.1", forRemoval = true)
protected ElfRelocationHandler() {
// enumTypesMap use is not supported
}
abstract public boolean canRelocate(ElfHeader elf);
/**
* Get the architecture-specific relative relocation type
* which should be applied to RELR relocations. The
* default implementation returns 0 which indicates
* RELR is unsupported.
* @return RELR relocation type
* Get the architecture-specific relative relocation type which should be applied to
* RELR relocations. The default implementation returns 0 which indicates RELR is unsupported.
*
* @return RELR relocation type ID value
*/
public int getRelrRelocationType() {
return 0;
@ -62,31 +80,103 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
/**
* Relocation context for a specific Elf image and relocation table. The relocation context
* is used to process relocations and manage any data required to process relocations.
*
* @param loadHelper Elf load helper
* @param symbolMap Elf symbol placement map
* @return relocation context or null if unsupported
*/
public ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
@SuppressWarnings("rawtypes")
protected ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
return null;
}
/**
* Perform relocation fixup
* Perform relocation fixup.
* <br>
* IMPORTANT: this class must be overriden if this implementation does not specify an
* {@link ElfRelocationType} enum class (see {@link #ElfRelocationHandler()}).
*
* @param elfRelocationContext relocation context
* @param relocation ELF relocation
* @param relocationAddress relocation target address (fixup location)
* @return applied relocation result (conveys status and applied byte-length)
* @throws MemoryAccessException memory access failure
* @throws NotFoundException required relocation data not found
* @throws NotFoundException NOTE: use of this exception is deprecated and should not be thrown
*/
abstract public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
@SuppressWarnings("rawtypes")
protected abstract RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException;
//
// Error and Warning markup methods
//
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unhandled relocation.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value
* @param symbolName associated symbol name
* @param symbolIndex symbol index within symbol table (-1 to ignore)
* @param log import log
*/
protected void markAsUnhandled(Program program, Address relocationAddress, int typeId,
String symbolName, int symbolIndex, MessageLog log) {
markupErrorOrWarning(program, "Unhandled ELF Relocation", null, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
/**
* Generate error log entry and bookmark at relocationAddress where relocation failed to
* be applied.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value
* @param symbolName associated symbol name
* @param symbolIndex symbol index within symbol table (-1 to ignore)
* @param msg error message
* @param log import log
*/
protected void markAsError(Program program, Address relocationAddress, int typeId,
String symbolName, int symbolIndex, String msg, MessageLog log) {
markupErrorOrWarning(program, "ELF Relocation Error", msg, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
/**
* Generate warning log entry and bookmark at relocationAddress where relocation failed to
* be applied.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value
* @param symbolName associated symbol name
* @param symbolIndex symbol index within symbol table (-1 to ignore)
* @param msg error message
* @param log import log
*/
protected void markAsWarning(Program program, Address relocationAddress, int typeId,
String symbolName, int symbolIndex, String msg, MessageLog log) {
markupErrorOrWarning(program, "ELF Relocation Warning", msg, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.WARNING,
log);
}
//
// Static methods
//
/**
* Apply a pointer-typedef with a specified component-offset if specified address
* is not contained within an execute block.
*
* @param program program
* @param addr address where data should be applied
* @param componentOffset component offset
@ -116,8 +206,10 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
* If so, relocationAddress will be marked with a <code>EXTERNAL Data Elf Relocation with pointer-offset</code>
* warning or error bookmark. Bookmark and logged message will be conveyed as an error if
* relocationAddress resides within an executable memory block.
* <br>
* NOTE: This method should only be invoked when the symbol offset will be adjusted with a non-zero
* value (i.e., addend).
*
* @param program program
* @param relocationAddress relocation address to be bookmarked if EXTERNAL block relocation
* @param symbolAddr symbol address correspondng to relocation (may be null)
@ -125,9 +217,8 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
* @param adjustment relocation symbol offset adjustment/addend
* @param log import log
*/
public static void warnExternalOffsetRelocation(Program program,
Address relocationAddress, Address symbolAddr, String symbolName, long adjustment,
MessageLog log) {
public static void warnExternalOffsetRelocation(Program program, Address relocationAddress,
Address symbolAddr, String symbolName, long adjustment, MessageLog log) {
if (symbolAddr == null || adjustment == 0 ||
!program.getMemory().isExternalBlockAddress(symbolAddr)) {
@ -146,7 +237,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
String adjStr = sign + "0x" + Long.toHexString(adjustment);
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
String msg1 = "EXTERNAL Data Elf Relocation with offset: at " + relocationAddress +
String msg1 = "EXTERNAL Data ELF Relocation with offset: at " + relocationAddress +
" (External Location = " + symbolName + adjStr + ")";
if (showAsError) {
Msg.error(ElfRelocationHandler.class, msg1);
@ -158,146 +249,195 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.WARNING,
"EXTERNAL Relocation",
"EXTERNAL Data Elf Relocation with offset: External Location = " + symbolName +
"EXTERNAL Data ELF Relocation with offset: External Location = " + symbolName +
adjStr);
}
}
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unhandled relocation.
* Get default relocation type details. This will not provide the name of the relocation
* type and must be used for static method invocations or a specific relocation enum type
* is not found.
*
* @param typeId relocation type ID value
* @return formatted relocation type detail for logging
*/
static String getDefaultRelocationTypeDetail(int typeId) {
return "Type = " + Integer.toUnsignedLong(typeId) + " (0x" + Integer.toHexString(typeId) +
")";
}
/**
* Generate error bookmark at relocationAddress indicating a missing relocation handler.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param symbolIndex associated symbol index within symbol table
* @param typeId relocation type ID value
* @param symbolIndex associated symbol index within symbol table (-1 to ignore)
* @param symbolName associated symbol name
* @param log import log
*/
public static void markAsUnhandled(Program program, Address relocationAddress, long type,
long symbolIndex, String symbolName, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Unhandled Elf Relocation: Type = " + type + " (0x" + Long.toHexString(type) +
") at " + relocationAddress + " (Symbol = " + symbolName + ")");
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR,
"Relocation Type " + type,
"Unhandled Elf Relocation: Type = " + type + " (0x" + Long.toHexString(type) +
") Symbol = " + symbolName + " (0x" + Long.toHexString(symbolIndex) + ").");
public static void bookmarkNoHandlerError(Program program, Address relocationAddress,
int typeId, int symbolIndex, String symbolName) {
markupErrorOrWarning(program, "No relocation handler", null, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR,
null); // null log to prevent logging
}
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unsupported RELR relocation.
* Generate error bookmark at relocationAddress indicating an unsupported RELR relocation.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
*/
public static void markAsUnsupportedRelr(Program program, Address relocationAddress) {
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR,
"Unsupported RELR Relocation", "ELF Extension does not specify type");
}
/**
* Generate error log entry and bookmark at relocationAddress where
* import failed to transition block to initialized while processing relocation.
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param symbolIndex associated symbol index within symbol table
* @param symbolIndex associated symbol index within symbol table (-1 to ignore)
* @param symbolName associated symbol name
* @param log import log
*/
public static void markAsUninitializedMemory(Program program, Address relocationAddress,
long type, long symbolIndex, String symbolName, MessageLog log) {
public static void bookmarkUnsupportedRelr(Program program, Address relocationAddress,
int symbolIndex, String symbolName) {
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Unable to perform relocation: Type = " + type + " (0x" +
Long.toHexString(type) + ") at " + relocationAddress + " (Symbol = " + symbolName +
") - uninitialized memory");
String symbolIndexStr =
symbolIndex < 0 ? "" : (" (0x" + Integer.toHexString(symbolIndex) + ")");
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR,
"Relocation_Type_" + type,
"Unable to perform relocation: Type = " + type + " (0x" + Long.toHexString(type) +
") Symbol = " + symbolName + " (0x" + Long.toHexString(symbolIndex) +
") - uninitialized memory.");
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "Relocation",
"Unsupported RELR Relocation: Symbol = " + symbolName + symbolIndexStr +
" - ELF Extension does not specify type");
}
/**
* Generate error log entry and bookmark at relocationAddress where
* import failed to be applied.
* Generate error log entry and bookmark at relocationAddress
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param typeId relocation type
* @param symbolIndex associated symbol index within symbol table (-1 to ignore)
* @param symbolName associated symbol name
* @param msg error messge
* @param log import log
*/
public static void markAsError(Program program, Address relocationAddress, long type,
public static void markAsError(Program program, Address relocationAddress, int typeId,
int symbolIndex, String symbolName, String msg, MessageLog log) {
markupErrorOrWarning(program, "Elf Relocation Error", msg, relocationAddress,
getDefaultRelocationTypeDetail(typeId), symbolIndex, symbolName, BookmarkType.ERROR,
log);
}
/**
* Generate error or warning log entry and bookmark at relocationAddress indicating a
* relocation failure.
*
* @param program program
* @param mainMsg relocation error message (required)
* @param tailMsg relocation error cause (optional, may be null)
* @param relocationAddress relocation address to be bookmarked
* @param relocTypeDetail relocation type detail
* @param symbolIndex associated symbol index within symbol table (-1 to ignore)
* @param symbolName associated symbol name
* @param bookmarkType bookmark type: ({@link BookmarkType#ERROR} or ({@link BookmarkType#WARNING}
* @param log import log or null if no logging required
*/
static void markupErrorOrWarning(Program program, String mainMsg, String tailMsg,
Address relocationAddress, String relocTypeDetail, int symbolIndex, String symbolName,
String bookmarkType, MessageLog log) {
tailMsg = StringUtils.isEmpty(tailMsg) ? "" : (" - " + tailMsg);
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
String symbolIndexStr =
symbolIndex < 0 ? "" : (" (0x" + Integer.toHexString(symbolIndex) + ")");
if (log != null) {
log.appendMsg(mainMsg + ": " + relocTypeDetail + " at " + relocationAddress +
" (Symbol = " + symbolName + ")" + tailMsg);
}
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, bookmarkType, "Relocation", mainMsg + ": " +
relocTypeDetail + " Symbol = " + symbolName + symbolIndexStr + tailMsg);
}
//
// Deprecated methods
//
/**
* Generate error log entry and bookmark at relocationAddress indicating
* an unhandled relocation.
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value (limited to int value).
* @param symbolIndex associated symbol index within symbol table (limited to int value).
* @param symbolName associated symbol name
* @param log import log
*/
@Deprecated
public static void markAsUnhandled(Program program, Address relocationAddress, long typeId,
long symbolIndex, String symbolName, MessageLog log) {
markupErrorOrWarning(program, "Unhandled ELF Relocation", null, relocationAddress,
getDefaultRelocationTypeDetail((int) typeId), (int) symbolIndex, symbolName,
BookmarkType.ERROR, log);
}
/**
* Generate warning log entry and bookmark at relocationAddress
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type ID name
* @param msg message associated with warning
* @param log import log
*/
@Deprecated
public static void markAsWarning(Program program, Address relocationAddress, String type,
String msg, MessageLog log) {
markAsWarning(program, relocationAddress, type, null, -1, msg, log);
}
/**
* Generate warning log entry and bookmark at relocationAddress
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type ID name
* @param symbolName symbol name
* @param symbolIndex symbol index (-1 to ignore)
* @param msg message associated with warning
* @param log import log
*/
@Deprecated
public static void markAsWarning(Program program, Address relocationAddress, String type,
String symbolName, int symbolIndex, String msg, MessageLog log) {
markupErrorOrWarning(program, "Elf Relocation Warning", msg, relocationAddress,
"Type = " + type, symbolIndex, symbolName, BookmarkType.WARNING, log);
}
/**
* Generate error log entry and bookmark at relocationAddress
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param typeId relocation type ID value
* @param symbolName associated symbol name
* @param msg error messge
* @param log import log
*/
@Deprecated
public static void markAsError(Program program, Address relocationAddress, long typeId,
String symbolName, String msg, MessageLog log) {
markAsError(program, relocationAddress, type + " (0x" + Long.toHexString(type) + ")",
markAsError(program, relocationAddress, typeId + " (0x" + Long.toHexString(typeId) + ")",
symbolName, msg, log);
}
/**
* Generate error log entry and bookmark at relocationAddress where
* import failed to be applied.
* Generate error log entry and bookmark at relocationAddress
*
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param type relocation type ID name
* @param symbolName associated symbol name
* @param msg additional error message
* @param log import log
*/
@Deprecated
public static void markAsError(Program program, Address relocationAddress, String type,
String symbolName, String msg, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Elf Relocation Error: Type = " + type + " at " + relocationAddress +
", Symbol = " + symbolName + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "Relocation_" + type,
"Elf Relocation Error: Symbol = " + symbolName + ": " + msg);
}
/**
* Generate warning log entry and bookmark at relocationAddress where
* import issue occurred.
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param msg message associated with warning
* @param log import log
*/
public static void markAsWarning(Program program, Address relocationAddress, String type,
String msg, MessageLog log) {
markAsWarning(program, relocationAddress, type, null, 0, msg, log);
}
/**
* Generate warning log entry and bookmark at relocationAddress where
* import issue occurred.
* @param program program
* @param relocationAddress relocation address to be bookmarked
* @param type relocation type
* @param symbolName symbol name
* @param symbolIndex symbol index
* @param msg message associated with warning
* @param log import log
*/
public static void markAsWarning(Program program, Address relocationAddress, String type,
String symbolName, long symbolIndex, String msg, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Elf Relocation Warning: Type = " + type + " at " + relocationAddress +
", Symbol = " + symbolName + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.WARNING,
"Relocation_Type_" + type,
"Unhandled Elf relocation ("+type+") at address: " + relocationAddress +
". Symbol = " + symbolName + " (" + Long.toHexString(symbolIndex) + ")" +
". " + msg);
markupErrorOrWarning(program, "Elf Relocation Error", msg, relocationAddress,
"Type = " + type, -1, symbolName, BookmarkType.ERROR, log);
}
}

View file

@ -15,12 +15,12 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.util.bin.format.elf.ElfHeader;
import ghidra.util.classfinder.ClassSearcher;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.format.elf.ElfHeader;
import ghidra.util.classfinder.ClassSearcher;
public final class ElfRelocationHandlerFactory {
public final static List<ElfRelocationHandler> getHandlers() {

View file

@ -15,22 +15,18 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
public class eBPF_ElfRelocationConstants {
public interface ElfRelocationType {
/** No operation needed */
public static final int R_BPF_NONE = 0;
/** S + A */
public static final int R_BPF_64_64 = 1;
/** S + A */
public static final int R_BPF_64_ABS64 = 2;
/** S + A */
public static final int R_BPF_64_ABS32 = 3;
/** S + A */
public static final int R_BPF_64_NODYLD32 = 4;
/** (S + A) / 8 - 1 */
public static final int R_BPF_64_32 = 10;
/**
* Get the name of this relocation type (i.e., enum name)
* @return name of this relocation type
*/
public String name();
/**
* Get the value associated with this relocation type.
* @return relocation type value.
*/
public int typeId();
private eBPF_ElfRelocationConstants() {
// no construct
}
}

View file

@ -879,10 +879,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
monitor.initialize(totalCount);
ElfRelocationContext context = null;
if (processRelocations) {
context = ElfRelocationContext.getRelocationContext(this, symbolMap);
}
ElfRelocationContext context = ElfRelocationContext.getRelocationContext(this, symbolMap);
try {
for (ElfRelocationTable relocationTable : relocationTables) {
monitor.checkCancelled();
@ -979,7 +976,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
boolean relrTypeUnknown = false;
long relrRelocationType = 0;
int relrRelocationType = 0;
if (relocationTable.isRelrTable() && context != null) {
relrRelocationType = context.getRelrRelocationType();
if (relrRelocationType == 0) {
@ -993,7 +990,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
monitor.checkCancelled();
monitor.incrementProgress(1);
long type = reloc.getType();
int type = reloc.getType();
if (type == 0) {
continue; // ignore relocation type 0 (i.e., ..._NONE)
}
@ -1023,8 +1020,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
try {
if (unableToApplyRelocs) {
status = Status.FAILURE;
ElfRelocationHandler.markAsError(program, relocAddr, type, symbolName,
"missing symbol table", log);
context.markRelocationError(relocAddr, type, symbolIndex, symbolName,
"Missing symbol table");
continue;
}
@ -1039,9 +1036,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
catch (Exception e) {
status = Status.FAILURE;
Msg.error(this,
"Unexpected exception while converting block to initialized", e);
ElfRelocationHandler.markAsUninitializedMemory(program, relocAddr, type,
reloc.getSymbolIndex(), symbolName, log);
"Unexpected exception while converting block to initialized for relocations",
e);
context.markRelocationError(relocAddr, type, symbolIndex, symbolName,
"Uninitialized memory");
continue;
}
}
@ -1049,7 +1047,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (context != null) {
if (relrTypeUnknown) {
status = Status.UNSUPPORTED;
ElfRelocationHandler.markAsUnsupportedRelr(program, relocAddr);
ElfRelocationHandler.bookmarkUnsupportedRelr(program, relocAddr,
symbolIndex, symbolName);
}
else {
RelocationResult result = context.processRelocation(reloc, relocAddr);

View file

@ -1,349 +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 AARCH64_ElfRelocationConstants {
public static final int R_AARCH64_NONE = 0;
// .word: (S+A)
public static final int R_AARCH64_P32_ABS32 = 1;
// .half: (S+A)
public static final int R_AARCH64_P32_ABS16 = 2;
// .word: (S+A-P)
public static final int R_AARCH64_P32_PREL32 = 3;
// .half: (S+A-P)
public static final int R_AARCH64_P32_PREL16 = 4;
// MOV[ZK]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_P32_MOVW_UABS_G0 = 5;
// MOV[ZK]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_P32_MOVW_UABS_G0_NC = 6;
// MOV[ZK]: ((S+A) >> 16) & 0xffff
public static final int R_AARCH64_P32_MOVW_UABS_G1 = 7;
// MOV[ZN]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_P32_MOVW_SABS_G0 = 8;
// LD-lit: ((S+A-P) >> 2) & 0x7ffff
public static final int R_AARCH64_P32_LD_PREL_LO19 = 9;
// ADR: (S+A-P) & 0x1fffff
public static final int R_AARCH64_P32_ADR_PREL_LO21 = 10;
// ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
public static final int R_AARCH64_P32_ADR_PREL_PG_HI21 = 11;
// ADD: (S+A) & 0xfff
public static final int R_AARCH64_P32_ADD_ABS_LO12_NC = 12;
// LD/ST8: (S+A) & 0xfff
public static final int R_AARCH64_P32_LDST8_ABS_LO12_NC = 13;
// LD/ST16: (S+A) & 0xffe
public static final int R_AARCH64_P32_LDST16_ABS_LO12_NC = 14;
// LD/ST32: (S+A) & 0xffc
public static final int R_AARCH64_P32_LDST32_ABS_LO12_NC = 15;
// LD/ST64: (S+A) & 0xff8
public static final int R_AARCH64_P32_LDST64_ABS_LO12_NC = 16;
// LD/ST128: (S+A) & 0xff0
public static final int R_AARCH64_P32_LDST128_ABS_LO12_NC = 17;
// TBZ/NZ: ((S+A-P) >> 2) & 0x3fff.
public static final int R_AARCH64_P32_TSTBR14 = 18;
// B.cond: ((S+A-P) >> 2) & 0x7ffff.
public static final int R_AARCH64_P32_CONDBR19 = 19;
// B: ((S+A-P) >> 2) & 0x3ffffff.
public static final int R_AARCH64_P32_JUMP26 = 20;
// BL: ((S+A-P) >> 2) & 0x3ffffff.
public static final int R_AARCH64_P32_CALL26 = 21;
public static final int R_AARCH64_P32_GOT_LD_PREL19 = 25;
public static final int R_AARCH64_P32_ADR_GOT_PAGE = 26;
public static final int R_AARCH64_P32_LD32_GOT_LO12_NC = 27;
public static final int R_AARCH64_P32_LD32_GOTPAGE_LO14 = 28;
public static final int R_AARCH64_P32_TLSGD_ADR_PREL21 = 80;
public static final int R_AARCH64_P32_TLSGD_ADR_PAGE21 = 81;
public static final int R_AARCH64_P32_TLSGD_ADD_LO12_NC = 82;
public static final int R_AARCH64_P32_TLSLD_ADR_PREL21 = 83;
public static final int R_AARCH64_P32_TLSLD_ADR_PAGE21 = 84;
public static final int R_AARCH64_P32_TLSLD_ADD_LO12_NC = 85;
public static final int R_AARCH64_P32_TLSLD_MOVW_DTPREL_G1 = 87;
public static final int R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0 = 88;
public static final int R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0_NC = 89;
public static final int R_AARCH64_P32_TLSLD_ADD_DTPREL_HI12 = 90;
public static final int R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12 = 91;
public static final int R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12_NC = 92;
public static final int R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 = 103;
public static final int R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC = 104;
public static final int R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 = 105;
public static final int R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 = 106;
public static final int R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 = 107;
public static final int R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC = 108;
public static final int R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 = 109;
public static final int R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 = 110;
public static final int R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC = 111;
public static final int R_AARCH64_P32_TLSDESC_LD_PREL19 = 122;
public static final int R_AARCH64_P32_TLSDESC_ADR_PREL21 = 123;
public static final int R_AARCH64_P32_TLSDESC_ADR_PAGE21 = 124;
public static final int R_AARCH64_P32_TLSDESC_LD32_LO12_NC = 125;
public static final int R_AARCH64_P32_TLSDESC_ADD_LO12_NC = 126;
public static final int R_AARCH64_P32_TLSDESC_CALL = 127;
// Copy symbol at runtime.
public static final int R_AARCH64_P32_COPY = 180;
// Create GOT entry.
public static final int R_AARCH64_P32_GLOB_DAT = 181;
// Create PLT entry.
public static final int R_AARCH64_P32_JUMP_SLOT = 182;
// Adjust by program base.
public static final int R_AARCH64_P32_RELATIVE = 183;
public static final int R_AARCH64_P32_TLS_DTPMOD = 184;
public static final int R_AARCH64_P32_TLS_DTPREL = 185;
public static final int R_AARCH64_P32_TLS_TPREL = 186;
public static final int R_AARCH64_P32_TLSDESC = 187;
public static final int R_AARCH64_P32_IRELATIVE = 188;
public static final int R_AARCH64_NULL = 256; // No reloc
// Basic data relocations.
// .xword: (S+A)
public static final int R_AARCH64_ABS64 = 257;
// .word: (S+A)
public static final int R_AARCH64_ABS32 = 258;
// .half: (S+A)
public static final int R_AARCH64_ABS16 = 259;
// .xword: (S+A-P)
public static final int R_AARCH64_PREL64 = 260;
// .word: (S+A-P)
public static final int R_AARCH64_PREL32 = 261;
// .half: (S+A-P)
public static final int R_AARCH64_PREL16 = 262;
// MOV[ZK]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G0 = 263;
// MOV[ZK]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G0_NC = 264;
// MOV[ZK]: ((S+A) >> 16) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G1 = 265;
// MOV[ZK]: ((S+A) >> 16) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G1_NC = 266;
// MOV[ZK]: ((S+A) >> 32) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G2 = 267;
// MOV[ZK]: ((S+A) >> 32) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G2_NC = 268;
// MOV[ZK]: ((S+A) >> 48) & 0xffff
public static final int R_AARCH64_MOVW_UABS_G3 = 269;
// MOV[ZN]: ((S+A) >> 0) & 0xffff
public static final int R_AARCH64_MOVW_SABS_G0 = 270;
// MOV[ZN]: ((S+A) >> 16) & 0xffff
public static final int R_AARCH64_MOVW_SABS_G1 = 271;
// MOV[ZN]: ((S+A) >> 32) & 0xffff
public static final int R_AARCH64_MOVW_SABS_G2 = 272;
// LD-lit: ((S+A-P) >> 2) & 0x7ffff
public static final int R_AARCH64_LD_PREL_LO19 = 273;
// ADR: (S+A-P) & 0x1fffff
public static final int R_AARCH64_ADR_PREL_LO21 = 274;
// ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
public static final int R_AARCH64_ADR_PREL_PG_HI21 = 275;
// ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
public static final int R_AARCH64_ADR_PREL_PG_HI21_NC = 276;
// ADD: (S+A) & 0xfff
public static final int R_AARCH64_ADD_ABS_LO12_NC = 277;
// LD/ST8: (S+A) & 0xfff
public static final int R_AARCH64_LDST8_ABS_LO12_NC = 278;
// TBZ/NZ: ((S+A-P) >> 2) & 0x3fff.
public static final int R_AARCH64_TSTBR14 = 279;
// B.cond: ((S+A-P) >> 2) & 0x7ffff.
public static final int R_AARCH64_CONDBR19 = 280;
// B: ((S+A-P) >> 2) & 0x3ffffff.
public static final int R_AARCH64_JUMP26 = 282;
// BL: ((S+A-P) >> 2) & 0x3ffffff.
public static final int R_AARCH64_CALL26 = 283;
// LD/ST16: (S+A) & 0xffe
public static final int R_AARCH64_LDST16_ABS_LO12_NC = 284;
// LD/ST32: (S+A) & 0xffc
public static final int R_AARCH64_LDST32_ABS_LO12_NC = 285;
// LD/ST64: (S+A) & 0xff8
public static final int R_AARCH64_LDST64_ABS_LO12_NC = 286;
public static final int R_AARCH64_MOVW_PREL_G0 = 287;
public static final int R_AARCH64_MOVW_PREL_G0_NC = 288;
public static final int R_AARCH64_MOVW_PREL_G1 = 289;
public static final int R_AARCH64_MOVW_PREL_G1_NC = 290;
public static final int R_AARCH64_MOVW_PREL_G2 = 291;
public static final int R_AARCH64_MOVW_PREL_G2_NC = 292;
public static final int R_AARCH64_MOVW_PREL_G3 = 293;
// LD/ST128: (S+A) & 0xff0
public static final int R_AARCH64_LDST128_ABS_LO12_NC = 299;
public static final int R_AARCH64_MOVW_GOTOFF_G0 = 300;
public static final int R_AARCH64_MOVW_GOTOFF_G0_NC = 301;
public static final int R_AARCH64_MOVW_GOTOFF_G1 = 302;
public static final int R_AARCH64_MOVW_GOTOFF_G1_NC = 303;
public static final int R_AARCH64_MOVW_GOTOFF_G2 = 304;
public static final int R_AARCH64_MOVW_GOTOFF_G2_NC = 305;
public static final int R_AARCH64_MOVW_GOTOFF_G3 = 306;
public static final int R_AARCH64_GOTREL64 = 307;
public static final int R_AARCH64_GOTREL32 = 308;
public static final int R_AARCH64_GOT_LD_PREL19 = 309;
public static final int R_AARCH64_LD64_GOTOFF_LO15 = 310;
public static final int R_AARCH64_ADR_GOT_PAGE = 311;
public static final int R_AARCH64_LD64_GOT_LO12_NC = 312;
public static final int R_AARCH64_LD64_GOTPAGE_LO15 = 313;
public static final int R_AARCH64_TLSGD_ADR_PREL21 = 512;
public static final int R_AARCH64_TLSGD_ADR_PAGE21 = 513;
public static final int R_AARCH64_TLSGD_ADD_LO12_NC = 514;
public static final int R_AARCH64_TLSGD_MOVW_G1 = 515;
public static final int R_AARCH64_TLSGD_MOVW_G0_NC = 516;
public static final int R_AARCH64_TLSLD_ADR_PREL21 = 517;
public static final int R_AARCH64_TLSLD_ADR_PAGE21 = 518;
public static final int R_AARCH64_TLSLD_ADD_LO12_NC = 519;
public static final int R_AARCH64_TLSLD_MOVW_G1 = 520;
public static final int R_AARCH64_TLSLD_MOVW_G0_NC = 521;
public static final int R_AARCH64_TLSLD_LD_PREL19 = 522;
public static final int R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523;
public static final int R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524;
public static final int R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525;
public static final int R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526;
public static final int R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527;
public static final int R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528;
public static final int R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529;
public static final int R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530;
public static final int R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531;
public static final int R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532;
public static final int R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533;
public static final int R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534;
public static final int R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535;
public static final int R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536;
public static final int R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537;
public static final int R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538;
public static final int R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539;
public static final int R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540;
public static final int R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541;
public static final int R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542;
public static final int R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543;
public static final int R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544;
public static final int R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545;
public static final int R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546;
public static final int R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547;
public static final int R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548;
public static final int R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549;
public static final int R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550;
public static final int R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551;
public static final int R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552;
public static final int R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553;
public static final int R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554;
public static final int R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 555;
public static final int R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556;
public static final int R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557;
public static final int R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558;
public static final int R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559;
public static final int R_AARCH64_TLSDESC_LD_PREL19 = 560;
public static final int R_AARCH64_TLSDESC_ADR_PREL21 = 561;
public static final int R_AARCH64_TLSDESC_ADR_PAGE21 = 562;
public static final int R_AARCH64_TLSDESC_LD64_LO12_NC = 563;
public static final int R_AARCH64_TLSDESC_ADD_LO12_NC = 564;
public static final int R_AARCH64_TLSDESC_OFF_G1 = 565;
public static final int R_AARCH64_TLSDESC_OFF_G0_NC = 566;
public static final int R_AARCH64_TLSDESC_LDR = 567;
public static final int R_AARCH64_TLSDESC_ADD = 568;
public static final int R_AARCH64_TLSDESC_CALL = 569;
public static final int R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570;
public static final int R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571;
public static final int R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572;
public static final int R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573;
// Copy symbol at runtime.
public static final int R_AARCH64_COPY = 1024;
// Create GOT entry.
public static final int R_AARCH64_GLOB_DAT = 1025;
// Create PLT entry.
public static final int R_AARCH64_JUMP_SLOT = 1026;
// Adjust by program base.
public static final int R_AARCH64_RELATIVE = 1027;
public static final int R_AARCH64_TLS_DTPMOD64 = 1028;
public static final int R_AARCH64_TLS_DTPREL64 = 1029;
public static final int R_AARCH64_TLS_TPREL64 = 1030;
public static final int R_AARCH64_TLS_DTPMOD = 1028;
public static final int R_AARCH64_TLS_DTPREL = 1029;
public static final int R_AARCH64_TLS_TPREL = 1030;
public static final int R_AARCH64_TLSDESC = 1031;
public static final int R_AARCH64_IRELATIVE = 1032;
private AARCH64_ElfRelocationConstants() {
// no construct
}
}

View file

@ -24,9 +24,16 @@ 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.util.exception.NotFoundException;
public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
public class AARCH64_ElfRelocationHandler
extends AbstractElfRelocationHandler<AARCH64_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public AARCH64_ElfRelocationHandler() {
super(AARCH64_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -35,58 +42,37 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public int getRelrRelocationType() {
return AARCH64_ElfRelocationConstants.R_AARCH64_RELATIVE;
return AARCH64_ElfRelocationType.R_AARCH64_RELATIVE.typeId;
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (elf.e_machine() != ElfConstants.EM_AARCH64) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, AARCH64_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 == AARCH64_ElfRelocationConstants.R_AARCH64_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
String symbolName = sym.getNameAsString();
//boolean isThumb = isThumb(sym);
long offset = (int) relocationAddress.getOffset();
boolean isBigEndianInstructions =
program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
boolean is64bit = true;
boolean overflowCheck = true; // *_NC type relocations specify "no overflow check"
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
long newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
// .xword: (S+A)
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS64: {
case R_AARCH64_ABS64: {
newValue = (symbolValue + addend);
memory.setLong(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);
}
byteLength = 8;
@ -94,17 +80,17 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// .word: (S+A)
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS32:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_ABS32:{
case R_AARCH64_ABS32:
case R_AARCH64_P32_ABS32: {
newValue = (symbolValue + addend);
memory.setInt(relocationAddress, (int) (newValue & 0xffffffff));
break;
}
// .half: (S+A)
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS16:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_ABS16: {
case R_AARCH64_ABS16:
case R_AARCH64_P32_ABS16: {
newValue = (symbolValue + addend);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
byteLength = 2;
@ -112,7 +98,7 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// .xword: (S+A-P)
case AARCH64_ElfRelocationConstants.R_AARCH64_PREL64: {
case R_AARCH64_PREL64: {
newValue = (symbolValue + addend);
newValue -= (offset); // PC relative
memory.setLong(relocationAddress, newValue);
@ -121,8 +107,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// .word: (S+A-P)
case AARCH64_ElfRelocationConstants.R_AARCH64_PREL32:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_PREL32: {
case R_AARCH64_PREL32:
case R_AARCH64_P32_PREL32: {
newValue = (symbolValue + addend);
newValue -= (offset); // PC relative
memory.setInt(relocationAddress, (int) (newValue & 0xffffffff));
@ -130,8 +116,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// .half: (S+A-P)
case AARCH64_ElfRelocationConstants.R_AARCH64_PREL16:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_PREL16: {
case R_AARCH64_PREL16:
case R_AARCH64_P32_PREL16: {
newValue = (symbolValue + addend);
newValue -= (offset); // PC relative
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
@ -140,11 +126,11 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// MOV[ZK]: ((S+A) >> 0) & 0xffff
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G0_NC: {
case R_AARCH64_MOVW_UABS_G0_NC: {
overflowCheck = false;
// fall-through
}
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G0: {
case R_AARCH64_MOVW_UABS_G0: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
long imm = (symbolValue + addend) >> 0;
@ -155,19 +141,18 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
if (overflowCheck && imm > 0xffffL) {
// relocation already applied; report overflow condition
markAsError(program, relocationAddress, "R_AARCH64_MOVW_UABS_G0", symbolName,
"Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed overflow check for immediate value", elfRelocationContext.getLog());
}
break;
}
// MOV[ZK]: ((S+A) >> 16) & 0xffff
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G1_NC: {
case R_AARCH64_MOVW_UABS_G1_NC: {
overflowCheck = false;
// fall-through
}
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G1: {
case R_AARCH64_MOVW_UABS_G1: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
long imm = (symbolValue + addend) >> 16;
@ -178,19 +163,18 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
if (overflowCheck && imm > 0xffffL) {
// relocation already applied; report overflow condition
markAsError(program, relocationAddress, "R_AARCH64_MOVW_UABS_G0", symbolName,
"Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed overflow check for immediate value", elfRelocationContext.getLog());
}
break;
}
// MOV[ZK]: ((S+A) >> 32) & 0xffff
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G2_NC: {
case R_AARCH64_MOVW_UABS_G2_NC: {
overflowCheck = false;
// fall-through
}
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G2: {
case R_AARCH64_MOVW_UABS_G2: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
long imm = (symbolValue + addend) >> 32;
@ -201,15 +185,14 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
if (overflowCheck && imm > 0xffffL) {
// relocation already applied; report overflow condition
markAsError(program, relocationAddress, "R_AARCH64_MOVW_UABS_G0", symbolName,
"Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed overflow check for immediate value", elfRelocationContext.getLog());
}
break;
}
// MOV[ZK]: ((S+A) >> 48) & 0xffff
case AARCH64_ElfRelocationConstants.R_AARCH64_MOVW_UABS_G3: {
case R_AARCH64_MOVW_UABS_G3: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
long imm = (symbolValue + addend) >> 48;
@ -221,8 +204,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
case AARCH64_ElfRelocationConstants.R_AARCH64_ADR_PREL_PG_HI21:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_ADR_PREL_PG_HI21: {
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_P32_ADR_PREL_PG_HI21: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = ((PG(symbolValue + addend) - PG(offset)) >> 12) & 0x1fffff;
@ -234,8 +217,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// ADD: (S+A) & 0xfff
case AARCH64_ElfRelocationConstants.R_AARCH64_ADD_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_ADD_ABS_LO12_NC: {
case R_AARCH64_ADD_ABS_LO12_NC:
case R_AARCH64_P32_ADD_ABS_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) (symbolValue + addend) & 0xfff;
@ -246,8 +229,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// LD/ST8: (S+A) & 0xfff
case AARCH64_ElfRelocationConstants.R_AARCH64_LDST8_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_LDST8_ABS_LO12_NC: {
case R_AARCH64_LDST8_ABS_LO12_NC:
case R_AARCH64_P32_LDST8_ABS_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) (symbolValue + addend) & 0xfff;
@ -259,10 +242,10 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
// B: ((S+A-P) >> 2) & 0x3ffffff.
// BL: ((S+A-P) >> 2) & 0x3ffffff
case AARCH64_ElfRelocationConstants.R_AARCH64_JUMP26:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_JUMP26:
case AARCH64_ElfRelocationConstants.R_AARCH64_CALL26:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_CALL26: {
case R_AARCH64_JUMP26:
case R_AARCH64_P32_JUMP26:
case R_AARCH64_CALL26:
case R_AARCH64_P32_CALL26: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (symbolValue + addend);
@ -275,8 +258,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// LD/ST16: (S+A) & 0xffe
case AARCH64_ElfRelocationConstants.R_AARCH64_LDST16_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_LDST16_ABS_LO12_NC: {
case R_AARCH64_LDST16_ABS_LO12_NC:
case R_AARCH64_P32_LDST16_ABS_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) ((symbolValue + addend) & 0xffe) >> 1;
@ -287,8 +270,8 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// LD/ST32: (S+A) & 0xffc
case AARCH64_ElfRelocationConstants.R_AARCH64_LDST32_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_LDST32_ABS_LO12_NC: {
case R_AARCH64_LDST32_ABS_LO12_NC:
case R_AARCH64_P32_LDST32_ABS_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) ((symbolValue + addend) & 0xffc) >> 2;
@ -299,9 +282,9 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// LD/ST64: (S+A) & 0xff8
case AARCH64_ElfRelocationConstants.R_AARCH64_LDST64_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_LDST64_ABS_LO12_NC:
case AARCH64_ElfRelocationConstants.R_AARCH64_LD64_GOT_LO12_NC: {
case R_AARCH64_LDST64_ABS_LO12_NC:
case R_AARCH64_P32_LDST64_ABS_LO12_NC:
case R_AARCH64_LD64_GOT_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) ((symbolValue + addend) & 0xff8) >> 3;
@ -312,7 +295,7 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
}
// LD/ST128: (S+A) & 0xff0
case AARCH64_ElfRelocationConstants.R_AARCH64_LDST128_ABS_LO12_NC: {
case R_AARCH64_LDST128_ABS_LO12_NC: {
int oldValue = memory.getInt(relocationAddress, isBigEndianInstructions);
newValue = (int) ((symbolValue + addend) & 0xff0) >> 4;
@ -322,9 +305,9 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_GLOB_DAT:
case R_AARCH64_P32_GLOB_DAT:
is64bit = false;
case AARCH64_ElfRelocationConstants.R_AARCH64_GLOB_DAT: {
case R_AARCH64_GLOB_DAT: {
// Corresponds to resolved local/EXTERNAL symbols within GOT
if (elfRelocationContext.extractAddend()) {
addend = getValue(memory, relocationAddress, is64bit);
@ -334,9 +317,9 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_JUMP_SLOT:
case R_AARCH64_P32_JUMP_SLOT:
is64bit = false;
case AARCH64_ElfRelocationConstants.R_AARCH64_JUMP_SLOT: {
case R_AARCH64_JUMP_SLOT: {
// Corresponds to lazy dynamically linked external symbols within
// GOT/PLT symbolValue corresponds to PLT entry for which we need to
// create and external function location. Don't bother changing
@ -352,22 +335,20 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
setValue(memory, relocationAddress, symAddress.getOffset(), is64bit);
}
if ((isPltSym || isExternalSym) && !StringUtils.isBlank(symbolName)) {
Function extFunction =
elfRelocationContext.getLoadHelper().createExternalFunctionLinkage(
symbolName, symAddress, null);
Function extFunction = elfRelocationContext.getLoadHelper()
.createExternalFunctionLinkage(symbolName, symAddress, null);
if (extFunction == null) {
markAsError(program, relocationAddress, "R_AARCH64_JUMP_SLOT", symbolName,
"Failed to create R_AARCH64_JUMP_SLOT external function",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to create external function", elfRelocationContext.getLog());
// relocation already applied above
}
}
break;
}
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_RELATIVE:
case R_AARCH64_P32_RELATIVE:
is64bit = false;
case AARCH64_ElfRelocationConstants.R_AARCH64_RELATIVE: {
case R_AARCH64_RELATIVE: {
if (elfRelocationContext.extractAddend()) {
addend = getValue(memory, relocationAddress, is64bit);
}
@ -376,9 +357,9 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case AARCH64_ElfRelocationConstants.R_AARCH64_P32_COPY:
case AARCH64_ElfRelocationConstants.R_AARCH64_COPY: {
markAsWarning(program, relocationAddress, "R_AARCH64_COPY", symbolName, symbolIndex,
case R_AARCH64_P32_COPY:
case R_AARCH64_COPY: {
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
@ -418,7 +399,7 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
* @param addr address in memory
* @param is64bit true if 64 bit value, false if 32 bit value
* @return value from memory as a long
* @throws MemoryAccessException
* @throws MemoryAccessException if memory access failed
*/
private long getValue(Memory memory, Address addr, boolean is64bit)
throws MemoryAccessException {

View file

@ -0,0 +1,237 @@
/* ###
* 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 AARCH64_ElfRelocationType implements ElfRelocationType {
R_AARCH64_NONE(0),
R_AARCH64_P32_ABS32(1), // .word: (S+A)
R_AARCH64_P32_ABS16(2), // .half: (S+A)
R_AARCH64_P32_PREL32(3), // .word: (S+A-P)
R_AARCH64_P32_PREL16(4), // .half: (S+A-P)
R_AARCH64_P32_MOVW_UABS_G0(5), // MOV[ZK]: ((S+A) >> 0) & 0xffff
R_AARCH64_P32_MOVW_UABS_G0_NC(6), // MOV[ZK]: ((S+A) >> 0) & 0xffff
R_AARCH64_P32_MOVW_UABS_G1(7), // MOV[ZK]: ((S+A) >> 16) & 0xffff
R_AARCH64_P32_MOVW_SABS_G0(8), // MOV[ZN]: ((S+A) >> 0) & 0xffff
R_AARCH64_P32_LD_PREL_LO19(9), // LD-lit: ((S+A-P) >> 2) & 0x7ffff
R_AARCH64_P32_ADR_PREL_LO21(10), // ADR: (S+A-P) & 0x1fffff
R_AARCH64_P32_ADR_PREL_PG_HI21(11), // ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
R_AARCH64_P32_ADD_ABS_LO12_NC(12), // ADD: (S+A) & 0xfff
R_AARCH64_P32_LDST8_ABS_LO12_NC(13), // LD/ST8: (S+A) & 0xfff
R_AARCH64_P32_LDST16_ABS_LO12_NC(14), // LD/ST16: (S+A) & 0xffe
R_AARCH64_P32_LDST32_ABS_LO12_NC(15), // LD/ST32: (S+A) & 0xffc
R_AARCH64_P32_LDST64_ABS_LO12_NC(16), // LD/ST64: (S+A) & 0xff8
R_AARCH64_P32_LDST128_ABS_LO12_NC(17), // LD/ST128: (S+A) & 0xff0
R_AARCH64_P32_TSTBR14(18), // TBZ/NZ: ((S+A-P) >> 2) & 0x3fff.
R_AARCH64_P32_CONDBR19(19), // B.cond: ((S+A-P) >> 2) & 0x7ffff.
R_AARCH64_P32_JUMP26(20), // B: ((S+A-P) >> 2) & 0x3ffffff.
R_AARCH64_P32_CALL26(21), // BL: ((S+A-P) >> 2) & 0x3ffffff.
R_AARCH64_P32_GOT_LD_PREL19(25),
R_AARCH64_P32_ADR_GOT_PAGE(26),
R_AARCH64_P32_LD32_GOT_LO12_NC(27),
R_AARCH64_P32_LD32_GOTPAGE_LO14(28),
R_AARCH64_P32_TLSGD_ADR_PREL21(80),
R_AARCH64_P32_TLSGD_ADR_PAGE21(81),
R_AARCH64_P32_TLSGD_ADD_LO12_NC(82),
R_AARCH64_P32_TLSLD_ADR_PREL21(83),
R_AARCH64_P32_TLSLD_ADR_PAGE21(84),
R_AARCH64_P32_TLSLD_ADD_LO12_NC(85),
R_AARCH64_P32_TLSLD_MOVW_DTPREL_G1(87),
R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0(88),
R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0_NC(89),
R_AARCH64_P32_TLSLD_ADD_DTPREL_HI12(90),
R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12(91),
R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12_NC(92),
R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21(103),
R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC(104),
R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19(105),
R_AARCH64_P32_TLSLE_MOVW_TPREL_G1(106),
R_AARCH64_P32_TLSLE_MOVW_TPREL_G0(107),
R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC(108),
R_AARCH64_P32_TLSLE_ADD_TPREL_HI12(109),
R_AARCH64_P32_TLSLE_ADD_TPREL_LO12(110),
R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC(111),
R_AARCH64_P32_TLSDESC_LD_PREL19(122),
R_AARCH64_P32_TLSDESC_ADR_PREL21(123),
R_AARCH64_P32_TLSDESC_ADR_PAGE21(124),
R_AARCH64_P32_TLSDESC_LD32_LO12_NC(125),
R_AARCH64_P32_TLSDESC_ADD_LO12_NC(126),
R_AARCH64_P32_TLSDESC_CALL(127),
R_AARCH64_P32_COPY(180), // Copy symbol at runtime.
R_AARCH64_P32_GLOB_DAT(181), // Create GOT entry.
R_AARCH64_P32_JUMP_SLOT(182), // Create PLT entry.
// Adjust by program base.
R_AARCH64_P32_RELATIVE(183),
R_AARCH64_P32_TLS_DTPMOD(184),
R_AARCH64_P32_TLS_DTPREL(185),
R_AARCH64_P32_TLS_TPREL(186),
R_AARCH64_P32_TLSDESC(187),
R_AARCH64_P32_IRELATIVE(188),
R_AARCH64_NULL(256), // No reloc
// Basic data relocations.
R_AARCH64_ABS64(257), // .xword: (S+A)
R_AARCH64_ABS32(258), // .word: (S+A)
R_AARCH64_ABS16(259), // .half: (S+A)
R_AARCH64_PREL64(260), // .xword: (S+A-P)
R_AARCH64_PREL32(261), // .word: (S+A-P)
R_AARCH64_PREL16(262), // .half: (S+A-P)
R_AARCH64_MOVW_UABS_G0(263), // MOV[ZK]: ((S+A) >> 0) & 0xffff
R_AARCH64_MOVW_UABS_G0_NC(264), // MOV[ZK]: ((S+A) >> 0) & 0xffff
R_AARCH64_MOVW_UABS_G1(265), // MOV[ZK]: ((S+A) >> 16) & 0xffff
R_AARCH64_MOVW_UABS_G1_NC(266), // MOV[ZK]: ((S+A) >> 16) & 0xffff
R_AARCH64_MOVW_UABS_G2(267), // MOV[ZK]: ((S+A) >> 32) & 0xffff
R_AARCH64_MOVW_UABS_G2_NC(268), // MOV[ZK]: ((S+A) >> 32) & 0xffff
R_AARCH64_MOVW_UABS_G3(269), // MOV[ZK]: ((S+A) >> 48) & 0xffff
R_AARCH64_MOVW_SABS_G0(270), // MOV[ZN]: ((S+A) >> 0) & 0xffff
R_AARCH64_MOVW_SABS_G1(271), // MOV[ZN]: ((S+A) >> 16) & 0xffff
R_AARCH64_MOVW_SABS_G2(272), // MOV[ZN]: ((S+A) >> 32) & 0xffff
R_AARCH64_LD_PREL_LO19(273), // LD-lit: ((S+A-P) >> 2) & 0x7ffff
R_AARCH64_ADR_PREL_LO21(274), // ADR: (S+A-P) & 0x1fffff
R_AARCH64_ADR_PREL_PG_HI21(275), // ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
R_AARCH64_ADR_PREL_PG_HI21_NC(276), // ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
R_AARCH64_ADD_ABS_LO12_NC(277), // ADD: (S+A) & 0xfff
R_AARCH64_LDST8_ABS_LO12_NC(278), // LD/ST8: (S+A) & 0xfff
R_AARCH64_TSTBR14(279), // TBZ/NZ: ((S+A-P) >> 2) & 0x3fff.
R_AARCH64_CONDBR19(280), // B.cond: ((S+A-P) >> 2) & 0x7ffff.
R_AARCH64_JUMP26(282), // B: ((S+A-P) >> 2) & 0x3ffffff.
R_AARCH64_CALL26(283), // BL: ((S+A-P) >> 2) & 0x3ffffff.
R_AARCH64_LDST16_ABS_LO12_NC(284), // LD/ST16: (S+A) & 0xffe
R_AARCH64_LDST32_ABS_LO12_NC(285), // LD/ST32: (S+A) & 0xffc
R_AARCH64_LDST64_ABS_LO12_NC(286), // LD/ST64: (S+A) & 0xff8
R_AARCH64_MOVW_PREL_G0(287),
R_AARCH64_MOVW_PREL_G0_NC(288),
R_AARCH64_MOVW_PREL_G1(289),
R_AARCH64_MOVW_PREL_G1_NC(290),
R_AARCH64_MOVW_PREL_G2(291),
R_AARCH64_MOVW_PREL_G2_NC(292),
R_AARCH64_MOVW_PREL_G3(293),
R_AARCH64_LDST128_ABS_LO12_NC(299), // LD/ST128: (S+A) & 0xff0
R_AARCH64_MOVW_GOTOFF_G0(300),
R_AARCH64_MOVW_GOTOFF_G0_NC(301),
R_AARCH64_MOVW_GOTOFF_G1(302),
R_AARCH64_MOVW_GOTOFF_G1_NC(303),
R_AARCH64_MOVW_GOTOFF_G2(304),
R_AARCH64_MOVW_GOTOFF_G2_NC(305),
R_AARCH64_MOVW_GOTOFF_G3(306),
R_AARCH64_GOTREL64(307),
R_AARCH64_GOTREL32(308),
R_AARCH64_GOT_LD_PREL19(309),
R_AARCH64_LD64_GOTOFF_LO15(310),
R_AARCH64_ADR_GOT_PAGE(311),
R_AARCH64_LD64_GOT_LO12_NC(312),
R_AARCH64_LD64_GOTPAGE_LO15(313),
R_AARCH64_TLSGD_ADR_PREL21(512),
R_AARCH64_TLSGD_ADR_PAGE21(513),
R_AARCH64_TLSGD_ADD_LO12_NC(514),
R_AARCH64_TLSGD_MOVW_G1(515),
R_AARCH64_TLSGD_MOVW_G0_NC(516),
R_AARCH64_TLSLD_ADR_PREL21(517),
R_AARCH64_TLSLD_ADR_PAGE21(518),
R_AARCH64_TLSLD_ADD_LO12_NC(519),
R_AARCH64_TLSLD_MOVW_G1(520),
R_AARCH64_TLSLD_MOVW_G0_NC(521),
R_AARCH64_TLSLD_LD_PREL19(522),
R_AARCH64_TLSLD_MOVW_DTPREL_G2(523),
R_AARCH64_TLSLD_MOVW_DTPREL_G1(524),
R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC(525),
R_AARCH64_TLSLD_MOVW_DTPREL_G0(526),
R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC(527),
R_AARCH64_TLSLD_ADD_DTPREL_HI12(528),
R_AARCH64_TLSLD_ADD_DTPREL_LO12(529),
R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC(530),
R_AARCH64_TLSLD_LDST8_DTPREL_LO12(531),
R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC(532),
R_AARCH64_TLSLD_LDST16_DTPREL_LO12(533),
R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC(534),
R_AARCH64_TLSLD_LDST32_DTPREL_LO12(535),
R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC(536),
R_AARCH64_TLSLD_LDST64_DTPREL_LO12(537),
R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC(538),
R_AARCH64_TLSIE_MOVW_GOTTPREL_G1(539),
R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC(540),
R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(541),
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(542),
R_AARCH64_TLSIE_LD_GOTTPREL_PREL19(543),
R_AARCH64_TLSLE_MOVW_TPREL_G2(544),
R_AARCH64_TLSLE_MOVW_TPREL_G1(545),
R_AARCH64_TLSLE_MOVW_TPREL_G1_NC(546),
R_AARCH64_TLSLE_MOVW_TPREL_G0(547),
R_AARCH64_TLSLE_MOVW_TPREL_G0_NC(548),
R_AARCH64_TLSLE_ADD_TPREL_HI12(549),
R_AARCH64_TLSLE_ADD_TPREL_LO12(550),
R_AARCH64_TLSLE_ADD_TPREL_LO12_NC(551),
R_AARCH64_TLSLE_LDST8_TPREL_LO12(552),
R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC(553),
R_AARCH64_TLSLE_LDST16_TPREL_LO12(554),
R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC(555),
R_AARCH64_TLSLE_LDST32_TPREL_LO12(556),
R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC(557),
R_AARCH64_TLSLE_LDST64_TPREL_LO12(558),
R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC(559),
R_AARCH64_TLSDESC_LD_PREL19(560),
R_AARCH64_TLSDESC_ADR_PREL21(561),
R_AARCH64_TLSDESC_ADR_PAGE21(562),
R_AARCH64_TLSDESC_LD64_LO12_NC(563),
R_AARCH64_TLSDESC_ADD_LO12_NC(564),
R_AARCH64_TLSDESC_OFF_G1(565),
R_AARCH64_TLSDESC_OFF_G0_NC(566),
R_AARCH64_TLSDESC_LDR(567),
R_AARCH64_TLSDESC_ADD(568),
R_AARCH64_TLSDESC_CALL(569),
R_AARCH64_TLSLE_LDST128_TPREL_LO12(570),
R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC(571),
R_AARCH64_TLSLD_LDST128_DTPREL_LO12(572),
R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC(573),
R_AARCH64_COPY(1024), // Copy symbol at runtime.
R_AARCH64_GLOB_DAT(1025), // Create GOT entry.
R_AARCH64_JUMP_SLOT(1026), // Create PLT entry.
R_AARCH64_RELATIVE(1027), // Adjust by program base.
R_AARCH64_TLS_DTPMOD64(1028),
R_AARCH64_TLS_DTPREL64(1029),
R_AARCH64_TLS_TPREL64(1030),
R_AARCH64_TLS_DTPMOD(1028),
R_AARCH64_TLS_DTPREL(1029),
R_AARCH64_TLS_TPREL(1030),
R_AARCH64_TLSDESC(1031),
R_AARCH64_IRELATIVE(1032);
public final int typeId;
private AARCH64_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,285 +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 ARM_ElfRelocationConstants {
/** No operation needed */
public static final int R_ARM_NONE = 0;
/** ((S + A) | T) - P [DEPRECATED] */
public static final int R_ARM_PC24 = 1;
/** (S + A) | T */
public static final int R_ARM_ABS32 = 2;
/** ((S + A) | T) - P */
public static final int R_ARM_REL32 = 3;
/** S + A - P */
public static final int R_ARM_LDR_PC_G0 = 4;
/** S + A */
public static final int R_ARM_ABS16 = 5;
/** S + A */
public static final int R_ARM_ABS12 = 6;
/** S + A */
public static final int R_ARM_THM_ABS5 = 7;
/** S + A */
public static final int R_ARM_ABS_8 = 8;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_SBREL32 = 9;
/** ((S + A) | T) - P */
public static final int R_ARM_THM_CALL = 10;
/** S + A - Pa */
public static final int R_ARM_THM_PC8 = 11;
/** DELTA(B(S)) + A */
public static final int R_ARM_BREL_ADJ = 12;
public static final int R_ARM_TLS_DESC = 13;
/** [OBSOLETE] */
public static final int R_ARM_THM_SWI8 = 14;
/** [OBSOLETE] */
public static final int R_ARM_XPC25 = 15;
/** [OBSOLETE] */
public static final int R_ARM_THM_XPC22 = 16;
/** Module[S] */
public static final int R_ARM_TLS_DTPMOD32 = 17;
/** S + A - TLS */
public static final int R_ARM_TLS_DTPOFF32 = 18;
/** S + A - TLS */
public static final int R_ARM_TLS_TPOFF32 = 19;
/** Miscellaneous */
public static final int R_ARM_COPY = 20;
/** (S + A) | T */
public static final int R_ARM_GLOB_DAT = 21;
/** (S + A) | T */
public static final int R_ARM_JUMP_SLOT = 22;
/** B(S) + A [Note: see Table 4-16] */
public static final int R_ARM_RELATIVE = 23;
/** ((S + A) | T) - GOT_ORG */
public static final int R_ARM_GOTOFF32 = 24;
/** B(S) + A - P */
public static final int R_ARM_BASE_PREL = 25;
/** GOT(S) + A - GOT_ORG */
public static final int R_ARM_GOT_BREL = 26;
/** ((S + A) | T) - P */
public static final int R_ARM_PLT32 = 27;
/** ((S + A) | T) - P */
public static final int R_ARM_CALL = 28;
/** ((S + A) | T) - P */
public static final int R_ARM_JUMP24 = 29;
/** ((S + A) | T) - P */
public static final int R_ARM_THM_JUMP24 = 30;
/** B(S) + A */
public static final int R_ARM_BASE_ABS = 31;
/** Obsolete */
public static final int R_ARM_ALU_PCREL_7_0 = 32;
/** Obsolete */
public static final int R_ARM_ALU_PCREL_15_8 = 33;
/** Obsolete */
public static final int R_ARM_ALU_PCREL_23_15 = 34;
/** S + A - B(S) */
public static final int R_ARM_LDR_SBREL_11_0_NC = 35;
/** S + A - B(S) */
public static final int R_ARM_ALU_SBREL_19_12_NC = 36;
/** S + A - B(S) */
public static final int R_ARM_ALU_SBREL_27_20_CK = 37;
/** (S + A) | T or ((S + A) | T) - P */
public static final int R_ARM_TARGET1 = 38;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_SBREL31 = 39;
/** Miscellaneous */
public static final int R_ARM_V4BX = 40;
/** Miscellaneous */
public static final int R_ARM_TARGET2 = 41;
/** ((S + A) | T) - P */
public static final int R_ARM_PREL31 = 42;
/** (S + A) | T */
public static final int R_ARM_MOVW_ABS_NC = 43;
/** S + A */
public static final int R_ARM_MOVT_ABS = 44;
/** ((S + A) | T) - P */
public static final int R_ARM_MOVW_PREL_NC = 45;
/** S + A - P */
public static final int R_ARM_MOVT_PREL = 46;
/** (S + A) | T */
public static final int R_ARM_THM_MOVW_ABS_NC = 47;
/** S + A */
public static final int R_ARM_THM_MOVT_ABS = 48;
/** ((S + A) | T) - P */
public static final int R_ARM_THM_MOVW_PREL_NC = 49;
/** S + A - P */
public static final int R_ARM_THM_MOVT_PREL = 50;
/** ((S + A) | T) - P */
public static final int R_ARM_THM_JUMP19 = 51;
/** S + A - P */
public static final int R_ARM_THM_JUMP6 = 52;
/** ((S + A) | T) - Pa */
public static final int R_ARM_THM_ALU_PREL_11_0 = 53;
/** S + A - Pa */
public static final int R_ARM_THM_PC12 = 54;
/** S + A */
public static final int R_ARM_ABS32_NOI = 55;
/** S + A - P */
public static final int R_ARM_REL32_NOI = 56;
/** ((S + A) | T) - P */
public static final int R_ARM_ALU_PC_G0_NC = 57;
/** ((S + A) | T) - P */
public static final int R_ARM_ALU_PC_G0 = 58;
/** ((S + A) | T) - P */
public static final int R_ARM_ALU_PC_G1_NC = 59;
/** ((S + A) | T) - P */
public static final int R_ARM_ALU_PC_G1 = 60;
/** ((S + A) | T) - P */
public static final int R_ARM_ALU_PC_G2 = 61;
/** S + A - P */
public static final int R_ARM_LDR_PC_G1 = 62;
/** S + A - P */
public static final int R_ARM_LDR_PC_G2 = 63;
/** S + A - P */
public static final int R_ARM_LDRS_PC_G0 = 64;
/** S + A - P */
public static final int R_ARM_LDRS_PC_G1 = 65;
/** S + A - P */
public static final int R_ARM_LDRS_PC_G2 = 66;
/** S + A - P */
public static final int R_ARM_LDC_PC_G0 = 67;
/** S + A - P */
public static final int R_ARM_LDC_PC_G1 = 68;
/** S + A - P */
public static final int R_ARM_LDC_PC_G2 = 69;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_ALU_SB_G0_NC = 70;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_ALU_SB_G0 = 71;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_ALU_SB_G1_NC = 72;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_ALU_SB_G1 = 73;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_ALU_SB_G2 = 74;
/** S + A - B(S) */
public static final int R_ARM_LDR_SB_G0 = 75;
/** S + A - B(S) */
public static final int R_ARM_LDR_SB_G1 = 76;
/** S + A - B(S) */
public static final int R_ARM_LDR_SB_G2 = 77;
/** S + A - B(S) */
public static final int R_ARM_LDRS_SB_G0 = 78;
/** S + A - B(S) */
public static final int R_ARM_LDRS_SB_G1 = 79;
/** S + A - B(S) */
public static final int R_ARM_LDRS_SB_G2 = 80;
/** S + A - B(S) */
public static final int R_ARM_LDC_SB_G0 = 81;
/** S + A - B(S) */
public static final int R_ARM_LDC_SB_G1 = 82;
/** S + A - B(S) */
public static final int R_ARM_LDC_SB_G2 = 83;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_MOVW_BREL_NC = 84;
/** S + A - B(S) */
public static final int R_ARM_MOVT_BREL = 85;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_MOVW_BREL = 86;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_THM_MOVW_BREL_NC = 87;
/** S + A - B(S) */
public static final int R_ARM_THM_MOVT_BREL = 88;
/** ((S + A) | T) - B(S) */
public static final int R_ARM_THM_MOVW_BREL = 89;
/** ? */
public static final int R_ARM_TLS_GOTDESC = 90;
/** ? */
public static final int R_ARM_TLS_CALL = 91;
/** TLS relaxation */
public static final int R_ARM_TLS_DESCSEQ = 92;
/** ? */
public static final int R_ARM_THM_TLS_CALL = 93;
/** PLT(S) + A */
public static final int R_ARM_PLT32_ABS = 94;
/** GOT(S) + A */
public static final int R_ARM_GOT_ABS = 95;
/** GOT(S) + A - P */
public static final int R_ARM_GOT_PREL = 96;
/** GOT(S) + A - GOT_ORG */
public static final int R_ARM_GOT_BREL12 = 97;
/** S + A - GOT_ORG */
public static final int R_ARM_GOTOFF12 = 98;
/** ? */
public static final int R_ARM_GOTRELAX = 99;
/** ? */
public static final int R_ARM_GNU_VTENTRY = 100;
/** ? */
public static final int R_ARM_GNU_VTINHERIT = 101;
/** S + A - P */
public static final int R_ARM_THM_JUMP11 = 102;
/** S + A - P */
public static final int R_ARM_THM_JUMP8 = 103;
/** GOT(S) + A - P */
public static final int R_ARM_TLS_GD32 = 104;
/** GOT(S) + A - P */
public static final int R_ARM_TLS_LDM32 = 105;
/** S + A - TLS */
public static final int R_ARM_TLS_LDO32 = 106;
/** GOT(S) + A - P */
public static final int R_ARM_TLS_IE32 = 107;
/** S + A - tp */
public static final int R_ARM_TLS_LE32 = 108;
/** S + A - TLS */
public static final int R_ARM_TLS_LDO12 = 109;
/** S + A - tp */
public static final int R_ARM_TLS_LE12 = 110;
/** GOT(S) + A - GOT_ORG */
public static final int R_ARM_TLS_IE12GP = 111;
/** ? */
public static final int R_ARM_PRIVATE_0 = 112;
/** ? */
public static final int R_ARM_PRIVATE_1 = 113;
/** ? */
public static final int R_ARM_PRIVATE_2 = 114;
/** ? */
public static final int R_ARM_PRIVATE_3 = 115;
/** ? */
public static final int R_ARM_PRIVATE_4 = 116;
/** ? */
public static final int R_ARM_PRIVATE_5 = 117;
/** ? */
public static final int R_ARM_PRIVATE_6 = 118;
/** ? */
public static final int R_ARM_PRIVATE_7 = 119;
/** ? */
public static final int R_ARM_PRIVATE_8 = 120;
/** ? */
public static final int R_ARM_PRIVATE_9 = 121;
/** ? */
public static final int R_ARM_PRIVATE_10 = 122;
/** ? */
public static final int R_ARM_PRIVATE_11 = 123;
/** ? */
public static final int R_ARM_PRIVATE_12 = 124;
/** ? */
public static final int R_ARM_PRIVATE_13 = 125;
/** ? */
public static final int R_ARM_PRIVATE_14 = 126;
/** ? */
public static final int R_ARM_PRIVATE_15 = 127;
/** ? */
public static final int R_ARM_ME_TOO = 128;
/** ? */
public static final int R_ARM_THM_TLS_DESCSEQ16 = 129;
/** ? */
public static final int R_ARM_THM_TLS_DESCSEQ32 = 130;
private ARM_ElfRelocationConstants() {
// no construct
}
}

View file

@ -22,11 +22,11 @@ import ghidra.app.util.bin.format.elf.ElfSymbol;
import ghidra.app.util.bin.format.elf.extend.ARM_ElfExtension;
import ghidra.program.model.address.Address;
class ARM_ElfRelocationContext extends ElfRelocationContext {
class ARM_ElfRelocationContext extends ElfRelocationContext<ARM_ElfRelocationHandler> {
private final boolean applyPcBiasToRelativeRelocations;
protected ARM_ElfRelocationContext(ElfRelocationHandler handler, ElfLoadHelper loadHelper,
protected ARM_ElfRelocationContext(ARM_ElfRelocationHandler handler, ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
super(handler, loadHelper, symbolMap);

View file

@ -24,9 +24,16 @@ 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.util.exception.NotFoundException;
public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
public class ARM_ElfRelocationHandler
extends AbstractElfRelocationHandler<ARM_ElfRelocationType, ARM_ElfRelocationContext> {
/**
* Constructor
*/
public ARM_ElfRelocationHandler() {
super(ARM_ElfRelocationType.class);
}
@Override
public ARM_ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
@ -41,51 +48,31 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public int getRelrRelocationType() {
return ARM_ElfRelocationConstants.R_ARM_RELATIVE;
return ARM_ElfRelocationType.R_ARM_RELATIVE.typeId;
}
@Override
public RelocationResult relocate(ElfRelocationContext context, ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = context.getElfHeader();
if (elf.e_machine() != ElfConstants.EM_ARM ||
!(context instanceof ARM_ElfRelocationContext)) {
return RelocationResult.FAILURE;
}
ARM_ElfRelocationContext elfRelocationContext = (ARM_ElfRelocationContext) context;
protected RelocationResult relocate(ARM_ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, ARM_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
boolean instructionBigEndian = program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
int type = relocation.getType();
if (type == ARM_ElfRelocationConstants.R_ARM_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
boolean instructionBigEndian =
program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
boolean isThumb = isThumb(sym);
long addend = relocation.getAddend(); // will be 0 for REL case
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
boolean isThumb = isThumb(sym);
long offset = (int) relocationAddress.getOffset();
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
long offset = Integer.toUnsignedLong((int) relocationAddress.getOffset());
int symbolIndex = relocation.getSymbolIndex();
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case ARM_ElfRelocationConstants.R_ARM_PC24: { // Target class: ARM Instruction
case R_ARM_PC24: { // Target class: ARM Instruction
int oldValue = memory.getInt(relocationAddress, instructionBigEndian);
if (elfRelocationContext.extractAddend()) {
addend = (oldValue << 8) >> 6; // extract addend and sign-extend with *4 factor
@ -104,7 +91,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, newValue, instructionBigEndian);
break;
}
case ARM_ElfRelocationConstants.R_ARM_ABS32: { // Target class: Data
case R_ARM_ABS32: { // Target class: Data
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
@ -114,13 +101,13 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
}
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 ARM_ElfRelocationConstants.R_ARM_REL32: { // Target class: Data
case R_ARM_REL32: { // Target class: Data
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
@ -132,7 +119,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, newValue);
break;
}
case ARM_ElfRelocationConstants.R_ARM_PREL31: { // Target class: Data
case R_ARM_PREL31: { // Target class: Data
int oldValue = memory.getInt(relocationAddress);
if (elfRelocationContext.extractAddend()) {
addend = (oldValue << 1) >> 1;
@ -146,7 +133,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, newValue);
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G0: { // Target class: ARM Instruction
case R_ARM_LDR_PC_G0: { // Target class: ARM Instruction
int oldValue = memory.getInt(relocationAddress, instructionBigEndian);
newValue = (int) (symbolValue + addend);
newValue -= (offset + elfRelocationContext.getPcBias(false));
@ -155,13 +142,13 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, newValue, instructionBigEndian);
break;
}
case ARM_ElfRelocationConstants.R_ARM_ABS16: { // Target class: Data
case R_ARM_ABS16: { // Target class: Data
short sValue = (short) (symbolValue + addend);
memory.setShort(relocationAddress, sValue);
byteLength = 2;
break;
}
case ARM_ElfRelocationConstants.R_ARM_ABS12: { // Target class: ARM Instruction
case R_ARM_ABS12: { // Target class: ARM Instruction
int oldValue = memory.getInt(relocationAddress, instructionBigEndian);
newValue = (int) (symbolValue + addend);
newValue = (oldValue & 0xfffff000) | (newValue & 0x00000fff);
@ -169,23 +156,23 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_THM_ABS5: {
case R_ARM_THM_ABS5: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_ABS_8: { // Target class: Data
case R_ARM_ABS_8: { // Target class: Data
byte bValue = (byte) (symbolValue + addend);
memory.setByte(relocationAddress, bValue);
byteLength = 1;
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_SBREL32: {
case R_ARM_SBREL32: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP24: // // Target class: Thumb32 Instruction
case ARM_ElfRelocationConstants.R_ARM_THM_CALL: {
case R_ARM_THM_JUMP24: // // Target class: Thumb32 Instruction
case R_ARM_THM_CALL: {
newValue = (int) (symbolValue + addend);
// since it is adding in the oldvalue below, don't need to add in 4 for pc offset
@ -220,7 +207,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress.add(2), newValueL, instructionBigEndian);
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_PC8: { // Target class: Thumb16 Instruction
case R_ARM_THM_PC8: { // Target class: Thumb16 Instruction
short oldValue = memory.getShort(relocationAddress, instructionBigEndian);
newValue = (int) (symbolValue + addend);
newValue -= (offset + elfRelocationContext.getPcBias(true));
@ -231,33 +218,33 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_BREL_ADJ: {
case R_ARM_BREL_ADJ: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_DESC: {
case R_ARM_TLS_DESC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_SWI8: {
case R_ARM_THM_SWI8: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_XPC25: {
case R_ARM_XPC25: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_XPC22: {
case R_ARM_THM_XPC22: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_DTPMOD32: {
case R_ARM_TLS_DTPMOD32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_DTPOFF32: {
case R_ARM_TLS_DTPOFF32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_TPOFF32: {
case R_ARM_TLS_TPOFF32: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_GLOB_DAT: {
case R_ARM_GLOB_DAT: {
// Corresponds to resolved local/EXTERNAL symbols within GOT
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
@ -270,7 +257,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case ARM_ElfRelocationConstants.R_ARM_JUMP_SLOT: { // Target class: Data
case R_ARM_JUMP_SLOT: { // Target class: Data
// Corresponds to lazy dynamically linked external symbols within
// GOT/PLT symbolValue corresponds to PLT entry for which we need to
// create and external function location. Don't bother changing
@ -285,20 +272,18 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, (int) symAddress.getOffset());
}
if (isPltSym || isExternalSym) {
Function extFunction =
elfRelocationContext.getLoadHelper().createExternalFunctionLinkage(
symbolName, symAddress, null);
Function extFunction = elfRelocationContext.getLoadHelper()
.createExternalFunctionLinkage(symbolName, symAddress, null);
if (extFunction == null) {
markAsError(program, relocationAddress, "R_ARM_JUMP_SLOT", symbolName,
"Failed to create R_ARM_JUMP_SLOT external function",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to create external function", elfRelocationContext.getLog());
// relocation already applied above
}
}
break;
}
case ARM_ElfRelocationConstants.R_ARM_RELATIVE: { // Target class: Data
case R_ARM_RELATIVE: { // Target class: Data
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
@ -308,20 +293,20 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_GOTOFF32: {
case R_ARM_GOTOFF32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_BASE_PREL: {
case R_ARM_BASE_PREL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOT_BREL: {
case R_ARM_GOT_BREL: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_JUMP24: // Target class: ARM Instruction
case ARM_ElfRelocationConstants.R_ARM_CALL:
case ARM_ElfRelocationConstants.R_ARM_PLT32:
case R_ARM_JUMP24: // Target class: ARM Instruction
case R_ARM_CALL:
case R_ARM_PLT32:
int oldValue = memory.getInt(relocationAddress, instructionBigEndian);
if (elfRelocationContext.extractAddend()) {
addend = (oldValue << 8) >> 6; // extract addend and sign-extend with *4 factor
@ -342,96 +327,95 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
/*
case ARM_ElfRelocationConstants.R_ARM_BASE_ABS: {
case R_ARM_BASE_ABS: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_7_0: {
case R_ARM_ALU_PCREL_7_0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_15_8: {
case R_ARM_ALU_PCREL_15_8: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_23_15: {
case R_ARM_ALU_PCREL_23_15: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_SBREL_11_0_NC: {
case R_ARM_LDR_SBREL_11_0_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SBREL_19_12_NC: {
case R_ARM_ALU_SBREL_19_12_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SBREL_27_20_CK: {
case R_ARM_ALU_SBREL_27_20_CK: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TARGET1: {
case R_ARM_TARGET1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_SBREL31: {
case R_ARM_SBREL31: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_V4BX: {
case R_ARM_V4BX: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TARGET2: {
case R_ARM_TARGET2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PREL31: {
case R_ARM_PREL31: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_MOVW_ABS_NC:
case ARM_ElfRelocationConstants.R_ARM_MOVT_ABS: { // Target Class: ARM Instruction
*/
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS: { // Target Class: ARM Instruction
oldValue = memory.getInt(relocationAddress, instructionBigEndian);
newValue = oldValue;
oldValue = ((oldValue & 0xf0000) >> 4) | (oldValue & 0xfff);
oldValue = (oldValue ^ 0x8000) - 0x8000;
oldValue += symbolValue;
if (type == ARM_ElfRelocationConstants.R_ARM_MOVT_ABS) {
if (type == ARM_ElfRelocationType.R_ARM_MOVT_ABS) {
oldValue >>= 16;
}
newValue &= 0xfff0f000;
newValue |= ((oldValue & 0xf000) << 4) |
(oldValue & 0x0fff);
newValue |= ((oldValue & 0xf000) << 4) | (oldValue & 0x0fff);
memory.setInt(relocationAddress, newValue, instructionBigEndian);
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_MOVW_PREL_NC: {
case R_ARM_MOVW_PREL_NC: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_ABS_NC:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_ABS:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_PREL_NC:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_PREL:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_BREL_NC:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_BREL:
case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_BREL: {
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
case R_ARM_THM_MOVW_PREL_NC:
case R_ARM_THM_MOVT_PREL:
case R_ARM_THM_MOVW_BREL_NC:
case R_ARM_THM_MOVW_BREL:
case R_ARM_THM_MOVT_BREL: {
oldValue = memory.getShort(relocationAddress, instructionBigEndian) << 16;
oldValue |= memory.getShort(relocationAddress.add(2), instructionBigEndian);
if (elfRelocationContext.extractAddend()) {
addend = ((oldValue >> 4) & 0xf000);
addend = ((oldValue >> 4) & 0xf000);
addend |= ((oldValue >> 15) & 0x0800);
addend |= ((oldValue >> 4) & 0x0700);
addend |= (oldValue & 0x00ff);
addend = (addend ^ 0x8000) - 0x8000;
}
int value = (int) (symbolValue + addend);
if (type == ARM_ElfRelocationConstants.R_ARM_THM_MOVW_PREL_NC ||
type == ARM_ElfRelocationConstants.R_ARM_THM_MOVT_PREL) {
if (type == ARM_ElfRelocationType.R_ARM_THM_MOVW_PREL_NC ||
type == ARM_ElfRelocationType.R_ARM_THM_MOVT_PREL) {
value -= (offset + elfRelocationContext.getPcBias(true));
}
if (type == ARM_ElfRelocationConstants.R_ARM_THM_MOVT_ABS ||
type == ARM_ElfRelocationConstants.R_ARM_THM_MOVT_PREL ||
type == ARM_ElfRelocationConstants.R_ARM_THM_MOVT_BREL) {
if (type == ARM_ElfRelocationType.R_ARM_THM_MOVT_ABS ||
type == ARM_ElfRelocationType.R_ARM_THM_MOVT_PREL ||
type == ARM_ElfRelocationType.R_ARM_THM_MOVT_BREL) {
value >>= 16;
}
@ -440,158 +424,158 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
newValue |= (value & 0x0800) << 15;
newValue |= (value & 0x0700) << 4;
newValue |= (value & 0x00ff);
memory.setShort(relocationAddress, (short)(newValue >> 16), instructionBigEndian);
memory.setShort(relocationAddress.add(2), (short)newValue, instructionBigEndian);
memory.setShort(relocationAddress, (short) (newValue >> 16), instructionBigEndian);
memory.setShort(relocationAddress.add(2), (short) newValue, instructionBigEndian);
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP19: {
case R_ARM_THM_JUMP19: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP6: {
case R_ARM_THM_JUMP6: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_ALU_PREL_11_0: {
case R_ARM_THM_ALU_PREL_11_0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_PC12: {
case R_ARM_THM_PC12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ABS32_NOI: {
case R_ARM_ABS32_NOI: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_REL32_NOI: {
case R_ARM_REL32_NOI: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G0_NC: {
case R_ARM_ALU_PC_G0_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G0: {
case R_ARM_ALU_PC_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G1_NC: {
case R_ARM_ALU_PC_G1_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G1: {
case R_ARM_ALU_PC_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G2: {
case R_ARM_ALU_PC_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G1: {
case R_ARM_LDR_PC_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G2: {
case R_ARM_LDR_PC_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G0: {
case R_ARM_LDRS_PC_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G1: {
case R_ARM_LDRS_PC_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G2: {
case R_ARM_LDRS_PC_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G0: {
case R_ARM_LDC_PC_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G1: {
case R_ARM_LDC_PC_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G2: {
case R_ARM_LDC_PC_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G0_NC: {
case R_ARM_ALU_SB_G0_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G0: {
case R_ARM_ALU_SB_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G1_NC: {
case R_ARM_ALU_SB_G1_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G1: {
case R_ARM_ALU_SB_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G2: {
case R_ARM_ALU_SB_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G0: {
case R_ARM_LDR_SB_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G1: {
case R_ARM_LDR_SB_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G2: {
case R_ARM_LDR_SB_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G0: {
case R_ARM_LDRS_SB_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G1: {
case R_ARM_LDRS_SB_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G2: {
case R_ARM_LDRS_SB_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G0: {
case R_ARM_LDC_SB_G0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G1: {
case R_ARM_LDC_SB_G1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G2: {
case R_ARM_LDC_SB_G2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_MOVW_BREL_NC: {
case R_ARM_MOVW_BREL_NC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_MOVT_BREL: {
case R_ARM_MOVT_BREL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_MOVW_BREL: {
case R_ARM_MOVW_BREL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_GOTDESC: {
case R_ARM_TLS_GOTDESC: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_CALL: {
case R_ARM_TLS_CALL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_DESCSEQ: {
case R_ARM_TLS_DESCSEQ: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_TLS_CALL: {
case R_ARM_THM_TLS_CALL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PLT32_ABS: {
case R_ARM_PLT32_ABS: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOT_ABS: {
case R_ARM_GOT_ABS: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOT_PREL: {
case R_ARM_GOT_PREL: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOT_BREL12: {
case R_ARM_GOT_BREL12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOTOFF12: {
case R_ARM_GOTOFF12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GOTRELAX: {
case R_ARM_GOTRELAX: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GNU_VTENTRY: {
case R_ARM_GNU_VTENTRY: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_GNU_VTINHERIT: {
case R_ARM_GNU_VTINHERIT: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP11: {
case R_ARM_THM_JUMP11: {
oldValue = memory.getShort(relocationAddress, instructionBigEndian);
if (elfRelocationContext.extractAddend()) {
addend = (oldValue << 21 >> 20); // extract addend and sign-extend with *2 factor
@ -603,7 +587,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 2;
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP8: {
case R_ARM_THM_JUMP8: {
oldValue = memory.getShort(relocationAddress, instructionBigEndian);
if (elfRelocationContext.extractAddend()) {
addend = (oldValue << 24 >> 23); // extract addend and sign-extend with *2 factor
@ -616,88 +600,88 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
/*
case ARM_ElfRelocationConstants.R_ARM_TLS_GD32: {
case R_ARM_TLS_GD32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_LDM32: {
case R_ARM_TLS_LDM32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_LDO32: {
case R_ARM_TLS_LDO32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_IE32: {
case R_ARM_TLS_IE32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_LE32: {
case R_ARM_TLS_LE32: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_LDO12: {
case R_ARM_TLS_LDO12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_LE12: {
case R_ARM_TLS_LE12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_TLS_IE12GP: {
case R_ARM_TLS_IE12GP: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_0: {
case R_ARM_PRIVATE_0: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_1: {
case R_ARM_PRIVATE_1: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_2: {
case R_ARM_PRIVATE_2: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_3: {
case R_ARM_PRIVATE_3: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_4: {
case R_ARM_PRIVATE_4: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_5: {
case R_ARM_PRIVATE_5: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_6: {
case R_ARM_PRIVATE_6: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_7: {
case R_ARM_PRIVATE_7: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_8: {
case R_ARM_PRIVATE_8: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_9: {
case R_ARM_PRIVATE_9: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_10: {
case R_ARM_PRIVATE_10: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_11: {
case R_ARM_PRIVATE_11: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_12: {
case R_ARM_PRIVATE_12: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_13: {
case R_ARM_PRIVATE_13: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_14: {
case R_ARM_PRIVATE_14: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_PRIVATE_15: {
case R_ARM_PRIVATE_15: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_TLS_DESCSEQ16: {
case R_ARM_THM_TLS_DESCSEQ16: {
break;
}
case ARM_ElfRelocationConstants.R_ARM_THM_TLS_DESCSEQ32: {
case R_ARM_THM_TLS_DESCSEQ32: {
break;
}
*/
case ARM_ElfRelocationConstants.R_ARM_COPY: {
markAsWarning(program, relocationAddress, "R_ARM_COPY", symbolName, symbolIndex,
case R_ARM_COPY: {
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}

View file

@ -0,0 +1,162 @@
/* ###
* 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 ARM_ElfRelocationType implements ElfRelocationType {
R_ARM_NONE(0), // No operation needed
R_ARM_PC24(1), // ((S + A) | T) - P [DEPRECATED]
R_ARM_ABS32(2), // (S + A) | T
R_ARM_REL32(3), // ((S + A) | T) - P
R_ARM_LDR_PC_G0(4), // S + A - P
R_ARM_ABS16(5), // S + A
R_ARM_ABS12(6), // S + A
R_ARM_THM_ABS5(7), // S + A
R_ARM_ABS_8(8), // S + A
R_ARM_SBREL32(9), // ((S + A) | T) - B(S)
R_ARM_THM_CALL(10), // ((S + A) | T) - P
R_ARM_THM_PC8(11), // S + A - Pa
R_ARM_BREL_ADJ(12), // DELTA(B(S)) + A
R_ARM_TLS_DESC(13),
R_ARM_THM_SWI8(14), // [OBSOLETE]
R_ARM_XPC25(15), // [OBSOLETE]
R_ARM_THM_XPC22(16), // [OBSOLETE]
R_ARM_TLS_DTPMOD32(17), // Module[S]
R_ARM_TLS_DTPOFF32(18), // S + A - TLS
R_ARM_TLS_TPOFF32(19), // S + A - TLS
R_ARM_COPY(20), // Miscellaneous
R_ARM_GLOB_DAT(21), // (S + A) | T
R_ARM_JUMP_SLOT(22), // (S + A) | T
R_ARM_RELATIVE(23), // B(S) + A [Note: see Table 4-16]
R_ARM_GOTOFF32(24), // ((S + A) | T) - GOT_ORG
R_ARM_BASE_PREL(25), // B(S) + A - P
R_ARM_GOT_BREL(26), // GOT(S) + A - GOT_ORG
R_ARM_PLT32(27), // ((S + A) | T) - P
R_ARM_CALL(28), // ((S + A) | T) - P
R_ARM_JUMP24(29), // ((S + A) | T) - P
R_ARM_THM_JUMP24(30), // ((S + A) | T) - P
R_ARM_BASE_ABS(31), // B(S) + A
R_ARM_ALU_PCREL_7_0(32), // Obsolete
R_ARM_ALU_PCREL_15_8(33), // Obsolete
R_ARM_ALU_PCREL_23_15(34), // Obsolete
R_ARM_LDR_SBREL_11_0_NC(35), // S + A - B(S)
R_ARM_ALU_SBREL_19_12_NC(36), // S + A - B(S)
R_ARM_ALU_SBREL_27_20_CK(37), // S + A - B(S)
R_ARM_TARGET1(38), // (S + A) | T or ((S + A) | T) - P
R_ARM_SBREL31(39), // ((S + A) | T) - B(S)
R_ARM_V4BX(40), // Miscellaneous
R_ARM_TARGET2(41), // Miscellaneous
R_ARM_PREL31(42), // ((S + A) | T) - P
R_ARM_MOVW_ABS_NC(43), // (S + A) | T
R_ARM_MOVT_ABS(44), // S + A
R_ARM_MOVW_PREL_NC(45), // ((S + A) | T) - P
R_ARM_MOVT_PREL(46), // S + A - P
R_ARM_THM_MOVW_ABS_NC(47), // (S + A) | T
R_ARM_THM_MOVT_ABS(48), // S + A
R_ARM_THM_MOVW_PREL_NC(49), // ((S + A) | T) - P
R_ARM_THM_MOVT_PREL(50), // S + A - P
R_ARM_THM_JUMP19(51), // ((S + A) | T) - P
R_ARM_THM_JUMP6(52), // S + A - P
R_ARM_THM_ALU_PREL_11_0(53),// ((S + A) | T) - Pa
R_ARM_THM_PC12(54), // S + A - Pa
R_ARM_ABS32_NOI(55), // S + A
R_ARM_REL32_NOI(56), // S + A - P
R_ARM_ALU_PC_G0_NC(57), // ((S + A) | T) - P
R_ARM_ALU_PC_G0(58), // ((S + A) | T) - P
R_ARM_ALU_PC_G1_NC(59), // ((S + A) | T) - P
R_ARM_ALU_PC_G1(60), // ((S + A) | T) - P
R_ARM_ALU_PC_G2(61), // ((S + A) | T) - P
R_ARM_LDR_PC_G1(62), // S + A - P
R_ARM_LDR_PC_G2(63), // S + A - P
R_ARM_LDRS_PC_G0(64), // S + A - P
R_ARM_LDRS_PC_G1(65), // S + A - P
R_ARM_LDRS_PC_G2(66), // S + A - P
R_ARM_LDC_PC_G0(67), // S + A - P
R_ARM_LDC_PC_G1(68), // S + A - P
R_ARM_LDC_PC_G2(69), // S + A - P
R_ARM_ALU_SB_G0_NC(70), // ((S + A) | T) - B(S)
R_ARM_ALU_SB_G0(71), // ((S + A) | T) - B(S)
R_ARM_ALU_SB_G1_NC(72), // ((S + A) | T) - B(S)
R_ARM_ALU_SB_G1(73), // ((S + A) | T) - B(S)
R_ARM_ALU_SB_G2(74), // ((S + A) | T) - B(S)
R_ARM_LDR_SB_G0(75), // S + A - B(S)
R_ARM_LDR_SB_G1(76), // S + A - B(S)
R_ARM_LDR_SB_G2(77), // S + A - B(S)
R_ARM_LDRS_SB_G0(78), // S + A - B(S)
R_ARM_LDRS_SB_G1(79), // S + A - B(S)
R_ARM_LDRS_SB_G2(80), // S + A - B(S)
R_ARM_LDC_SB_G0(81), // S + A - B(S)
R_ARM_LDC_SB_G1(82), // S + A - B(S)
R_ARM_LDC_SB_G2(83), // S + A - B(S)
R_ARM_MOVW_BREL_NC(84), // ((S + A) | T) - B(S)
R_ARM_MOVT_BREL(85), // S + A - B(S)
R_ARM_MOVW_BREL(86), // ((S + A) | T) - B(S)
R_ARM_THM_MOVW_BREL_NC(87), // ((S + A) | T) - B(S)
R_ARM_THM_MOVT_BREL(88), // S + A - B(S)
R_ARM_THM_MOVW_BREL(89), // ((S + A) | T) - B(S)
R_ARM_TLS_GOTDESC(90),
R_ARM_TLS_CALL(91),
R_ARM_TLS_DESCSEQ(92), // TLS relaxation
R_ARM_THM_TLS_CALL(93),
R_ARM_PLT32_ABS(94), // PLT(S) + A
R_ARM_GOT_ABS(95), // GOT(S) + A
R_ARM_GOT_PREL(96), // GOT(S) + A - P
R_ARM_GOT_BREL12(97), // GOT(S) + A - GOT_ORG
R_ARM_GOTOFF12(98), // S + A - GOT_ORG
R_ARM_GOTRELAX(99),
R_ARM_GNU_VTENTRY(100),
R_ARM_GNU_VTINHERIT(101),
R_ARM_THM_JUMP11(102), // S + A - P
R_ARM_THM_JUMP8(103), // S + A - P
R_ARM_TLS_GD32(104), // GOT(S) + A - P
R_ARM_TLS_LDM32(105), // GOT(S) + A - P
R_ARM_TLS_LDO32(106), // S + A - TLS
R_ARM_TLS_IE32(107), // GOT(S) + A - P
R_ARM_TLS_LE32(108), // S + A - tp
R_ARM_TLS_LDO12(109), // S + A - TLS
R_ARM_TLS_LE12(110), // S + A - tp
R_ARM_TLS_IE12GP(111), // GOT(S) + A - GOT_ORG
R_ARM_PRIVATE_0(112),
R_ARM_PRIVATE_1(113),
R_ARM_PRIVATE_2(114),
R_ARM_PRIVATE_3(115),
R_ARM_PRIVATE_4(116),
R_ARM_PRIVATE_5(117),
R_ARM_PRIVATE_6(118),
R_ARM_PRIVATE_7(119),
R_ARM_PRIVATE_8(120),
R_ARM_PRIVATE_9(121),
R_ARM_PRIVATE_10(122),
R_ARM_PRIVATE_11(123),
R_ARM_PRIVATE_12(124),
R_ARM_PRIVATE_13(125),
R_ARM_PRIVATE_14(126),
R_ARM_PRIVATE_15(127),
R_ARM_ME_TOO(128),
R_ARM_THM_TLS_DESCSEQ16(129),
R_ARM_THM_TLS_DESCSEQ32(130);
public final int typeId;
private ARM_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.plugin.core.reloc.RelocationFixupHandler;
import ghidra.app.plugin.core.reloc.ElfRelocationFixupHandler;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
@ -23,152 +23,167 @@ import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.util.CodeUnitInsertionException;
public class ElfArmRelocationFixupHandler extends RelocationFixupHandler {
public class ElfArmRelocationFixupHandler extends ElfRelocationFixupHandler {
public ElfArmRelocationFixupHandler() {
super(ARM_ElfRelocationType.class);
}
@Override
public boolean processRelocation(Program program, Relocation relocation, Address oldImageBase,
Address newImageBase) throws MemoryAccessException, CodeUnitInsertionException {
switch (relocation.getType()) {
if (relocation.getStatus() != Status.APPLIED) {
return false;
}
ARM_ElfRelocationType type =
(ARM_ElfRelocationType) getRelocationType(relocation.getType());
if (type == null) {
return false;
}
switch (type) {
// TODO: This over simplified relocation fixup is flawed and does not properly
// handle post-import image base change for supported relocations
case ARM_ElfRelocationConstants.R_ARM_NONE:
case ARM_ElfRelocationConstants.R_ARM_ABS32:
case ARM_ElfRelocationConstants.R_ARM_REL32:
case ARM_ElfRelocationConstants.R_ARM_GLOB_DAT:
// case ARM_ElfRelocationConstants.R_ARM_JUMP_SLOT:
case ARM_ElfRelocationConstants.R_ARM_RELATIVE:
case ARM_ElfRelocationConstants.R_ARM_PLT32:
case ARM_ElfRelocationConstants.R_ARM_CALL:
case ARM_ElfRelocationConstants.R_ARM_JUMP24:
case ARM_ElfRelocationConstants.R_ARM_THM_JUMP24:
case R_ARM_NONE:
case R_ARM_ABS32:
case R_ARM_REL32:
case R_ARM_GLOB_DAT:
// case R_ARM_JUMP_SLOT:
case R_ARM_RELATIVE:
case R_ARM_PLT32:
case R_ARM_CALL:
case R_ARM_JUMP24:
case R_ARM_THM_JUMP24:
return process32BitRelocation(program, relocation, oldImageBase, newImageBase);
// case ARM_ElfRelocationConstants.R_ARM_PC24:
// case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G0:
// case ARM_ElfRelocationConstants.R_ARM_ABS16:
// case ARM_ElfRelocationConstants.R_ARM_ABS12:
// case ARM_ElfRelocationConstants.R_ARM_THM_ABS5:
// case ARM_ElfRelocationConstants.R_ARM_ABS_8:
// case ARM_ElfRelocationConstants.R_ARM_SBREL32:
// case ARM_ElfRelocationConstants.R_ARM_THM_CALL:
// case ARM_ElfRelocationConstants.R_ARM_THM_PC8:
// case ARM_ElfRelocationConstants.R_ARM_BREL_ADJ:
// case ARM_ElfRelocationConstants.R_ARM_TLS_DESC:
// case ARM_ElfRelocationConstants.R_ARM_THM_SWI8:
// case ARM_ElfRelocationConstants.R_ARM_XPC25:
// case ARM_ElfRelocationConstants.R_ARM_THM_XPC22:
// case ARM_ElfRelocationConstants.R_ARM_TLS_DTPMOD32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_DTPOFF32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_TPOFF32:
// case ARM_ElfRelocationConstants.R_ARM_COPY:
// case ARM_ElfRelocationConstants.R_ARM_GOTOFF32:
// case ARM_ElfRelocationConstants.R_ARM_BASE_PREL:
// case ARM_ElfRelocationConstants.R_ARM_GOT_BREL:
// case ARM_ElfRelocationConstants.R_ARM_BASE_ABS:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_7_0:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_15_8:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PCREL_23_15:
// case ARM_ElfRelocationConstants.R_ARM_LDR_SBREL_11_0_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SBREL_19_12_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SBREL_27_20_CK:
// case ARM_ElfRelocationConstants.R_ARM_TARGET1:
// case ARM_ElfRelocationConstants.R_ARM_SBREL31:
// case ARM_ElfRelocationConstants.R_ARM_V4BX:
// case ARM_ElfRelocationConstants.R_ARM_TARGET2:
// case ARM_ElfRelocationConstants.R_ARM_PREL31:
// case ARM_ElfRelocationConstants.R_ARM_MOVW_ABS_NC:
// case ARM_ElfRelocationConstants.R_ARM_MOVT_ABS:
// case ARM_ElfRelocationConstants.R_ARM_MOVW_PREL_NC:
// case ARM_ElfRelocationConstants.R_ARM_MOVT_PREL:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_ABS_NC:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_ABS:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_PREL_NC:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_PREL:
// case ARM_ElfRelocationConstants.R_ARM_THM_JUMP19:
// case ARM_ElfRelocationConstants.R_ARM_THM_JUMP6:
// case ARM_ElfRelocationConstants.R_ARM_THM_ALU_PREL_11_0:
// case ARM_ElfRelocationConstants.R_ARM_THM_PC12:
// case ARM_ElfRelocationConstants.R_ARM_ABS32_NOI:
// case ARM_ElfRelocationConstants.R_ARM_REL32_NOI:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G0_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G0:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G1_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G1:
// case ARM_ElfRelocationConstants.R_ARM_ALU_PC_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G0:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_PC_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G0:
// case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDC_PC_G2:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G0_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G0:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G1_NC:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G1:
// case ARM_ElfRelocationConstants.R_ARM_ALU_SB_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G0:
// case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDR_SB_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G0:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDRS_SB_G2:
// case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G0:
// case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G1:
// case ARM_ElfRelocationConstants.R_ARM_LDC_SB_G2:
// case ARM_ElfRelocationConstants.R_ARM_MOVW_BREL_NC:
// case ARM_ElfRelocationConstants.R_ARM_MOVT_BREL:
// case ARM_ElfRelocationConstants.R_ARM_MOVW_BREL:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_BREL_NC:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVT_BREL:
// case ARM_ElfRelocationConstants.R_ARM_THM_MOVW_BREL:
// case ARM_ElfRelocationConstants.R_ARM_TLS_GOTDESC:
// case ARM_ElfRelocationConstants.R_ARM_TLS_CALL:
// case ARM_ElfRelocationConstants.R_ARM_TLS_DESCSEQ:
// case ARM_ElfRelocationConstants.R_ARM_THM_TLS_CALL:
// case ARM_ElfRelocationConstants.R_ARM_PLT32_ABS:
// case ARM_ElfRelocationConstants.R_ARM_GOT_ABS:
// case ARM_ElfRelocationConstants.R_ARM_GOT_PREL:
// case ARM_ElfRelocationConstants.R_ARM_GOT_BREL12:
// case ARM_ElfRelocationConstants.R_ARM_GOTOFF12:
// case ARM_ElfRelocationConstants.R_ARM_GOTRELAX:
// case ARM_ElfRelocationConstants.R_ARM_GNU_VTENTRY:
// case ARM_ElfRelocationConstants.R_ARM_GNU_VTINHERIT:
// case ARM_ElfRelocationConstants.R_ARM_THM_JUMP11:
// case ARM_ElfRelocationConstants.R_ARM_THM_JUMP8:
// case ARM_ElfRelocationConstants.R_ARM_TLS_GD32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_LDM32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_LDO32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_IE32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_LE32:
// case ARM_ElfRelocationConstants.R_ARM_TLS_LDO12:
// case ARM_ElfRelocationConstants.R_ARM_TLS_LE12:
// case ARM_ElfRelocationConstants.R_ARM_TLS_IE12GP:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_0:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_1:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_2:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_3:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_4:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_5:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_6:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_7:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_8:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_9:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_10:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_11:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_12:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_13:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_14:
// case ARM_ElfRelocationConstants.R_ARM_PRIVATE_15:
// case ARM_ElfRelocationConstants.R_ARM_THM_TLS_DESCSEQ16:
// case ARM_ElfRelocationConstants.R_ARM_THM_TLS_DESCSEQ32:
// return false;
// case R_ARM_PC24:
// case R_ARM_LDR_PC_G0:
// case R_ARM_ABS16:
// case R_ARM_ABS12:
// case R_ARM_THM_ABS5:
// case R_ARM_ABS_8:
// case R_ARM_SBREL32:
// case R_ARM_THM_CALL:
// case R_ARM_THM_PC8:
// case R_ARM_BREL_ADJ:
// case R_ARM_TLS_DESC:
// case R_ARM_THM_SWI8:
// case R_ARM_XPC25:
// case R_ARM_THM_XPC22:
// case R_ARM_TLS_DTPMOD32:
// case R_ARM_TLS_DTPOFF32:
// case R_ARM_TLS_TPOFF32:
// case R_ARM_COPY:
// case R_ARM_GOTOFF32:
// case R_ARM_BASE_PREL:
// case R_ARM_GOT_BREL:
// case R_ARM_BASE_ABS:
// case R_ARM_ALU_PCREL_7_0:
// case R_ARM_ALU_PCREL_15_8:
// case R_ARM_ALU_PCREL_23_15:
// case R_ARM_LDR_SBREL_11_0_NC:
// case R_ARM_ALU_SBREL_19_12_NC:
// case R_ARM_ALU_SBREL_27_20_CK:
// case R_ARM_TARGET1:
// case R_ARM_SBREL31:
// case R_ARM_V4BX:
// case R_ARM_TARGET2:
// case R_ARM_PREL31:
// case R_ARM_MOVW_ABS_NC:
// case R_ARM_MOVT_ABS:
// case R_ARM_MOVW_PREL_NC:
// case R_ARM_MOVT_PREL:
// case R_ARM_THM_MOVW_ABS_NC:
// case R_ARM_THM_MOVT_ABS:
// case R_ARM_THM_MOVW_PREL_NC:
// case R_ARM_THM_MOVT_PREL:
// case R_ARM_THM_JUMP19:
// case R_ARM_THM_JUMP6:
// case R_ARM_THM_ALU_PREL_11_0:
// case R_ARM_THM_PC12:
// case R_ARM_ABS32_NOI:
// case R_ARM_REL32_NOI:
// case R_ARM_ALU_PC_G0_NC:
// case R_ARM_ALU_PC_G0:
// case R_ARM_ALU_PC_G1_NC:
// case R_ARM_ALU_PC_G1:
// case R_ARM_ALU_PC_G2:
// case R_ARM_LDR_PC_G1:
// case R_ARM_LDR_PC_G2:
// case R_ARM_LDRS_PC_G0:
// case R_ARM_LDRS_PC_G1:
// case R_ARM_LDRS_PC_G2:
// case R_ARM_LDC_PC_G0:
// case R_ARM_LDC_PC_G1:
// case R_ARM_LDC_PC_G2:
// case R_ARM_ALU_SB_G0_NC:
// case R_ARM_ALU_SB_G0:
// case R_ARM_ALU_SB_G1_NC:
// case R_ARM_ALU_SB_G1:
// case R_ARM_ALU_SB_G2:
// case R_ARM_LDR_SB_G0:
// case R_ARM_LDR_SB_G1:
// case R_ARM_LDR_SB_G2:
// case R_ARM_LDRS_SB_G0:
// case R_ARM_LDRS_SB_G1:
// case R_ARM_LDRS_SB_G2:
// case R_ARM_LDC_SB_G0:
// case R_ARM_LDC_SB_G1:
// case R_ARM_LDC_SB_G2:
// case R_ARM_MOVW_BREL_NC:
// case R_ARM_MOVT_BREL:
// case R_ARM_MOVW_BREL:
// case R_ARM_THM_MOVW_BREL_NC:
// case R_ARM_THM_MOVT_BREL:
// case R_ARM_THM_MOVW_BREL:
// case R_ARM_TLS_GOTDESC:
// case R_ARM_TLS_CALL:
// case R_ARM_TLS_DESCSEQ:
// case R_ARM_THM_TLS_CALL:
// case R_ARM_PLT32_ABS:
// case R_ARM_GOT_ABS:
// case R_ARM_GOT_PREL:
// case R_ARM_GOT_BREL12:
// case R_ARM_GOTOFF12:
// case R_ARM_GOTRELAX:
// case R_ARM_GNU_VTENTRY:
// case R_ARM_GNU_VTINHERIT:
// case R_ARM_THM_JUMP11:
// case R_ARM_THM_JUMP8:
// case R_ARM_TLS_GD32:
// case R_ARM_TLS_LDM32:
// case R_ARM_TLS_LDO32:
// case R_ARM_TLS_IE32:
// case R_ARM_TLS_LE32:
// case R_ARM_TLS_LDO12:
// case R_ARM_TLS_LE12:
// case R_ARM_TLS_IE12GP:
// case R_ARM_PRIVATE_0:
// case R_ARM_PRIVATE_1:
// case R_ARM_PRIVATE_2:
// case R_ARM_PRIVATE_3:
// case R_ARM_PRIVATE_4:
// case R_ARM_PRIVATE_5:
// case R_ARM_PRIVATE_6:
// case R_ARM_PRIVATE_7:
// case R_ARM_PRIVATE_8:
// case R_ARM_PRIVATE_9:
// case R_ARM_PRIVATE_10:
// case R_ARM_PRIVATE_11:
// case R_ARM_PRIVATE_12:
// case R_ARM_PRIVATE_13:
// case R_ARM_PRIVATE_14:
// case R_ARM_PRIVATE_15:
// case R_ARM_THM_TLS_DESCSEQ16:
// case R_ARM_THM_TLS_DESCSEQ32:
default:
return false;
}
return false;
}
@Override

View file

@ -1,57 +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;
public class AVR8_ElfRelocationConstants {
public static final int R_AVR_NONE = 0;
public static final int R_AVR_32 = 1;
public static final int R_AVR_7_PCREL = 2;
public static final int R_AVR_13_PCREL = 3;
public static final int R_AVR_16 = 4;
public static final int R_AVR_16_PM = 5;
public static final int R_AVR_LO8_LDI = 6;
public static final int R_AVR_HI8_LDI = 7;
public static final int R_AVR_HH8_LDI = 8;
public static final int R_AVR_LO8_LDI_NEG = 9;
public static final int R_AVR_HI8_LDI_NEG = 10;
public static final int R_AVR_HH8_LDI_NEG = 11;
public static final int R_AVR_LO8_LDI_PM = 12;
public static final int R_AVR_HI8_LDI_PM = 13;
public static final int R_AVR_HH8_LDI_PM = 14;
public static final int R_AVR_LO8_LDI_PM_NEG = 15;
public static final int R_AVR_HI8_LDI_PM_NEG = 16;
public static final int R_AVR_HH8_LDI_PM_NEG = 17;
public static final int R_AVR_CALL = 18;
public static final int R_AVR_LDI = 19;
public static final int R_AVR_6 = 20;
public static final int R_AVR_6_ADIW = 21;
public static final int R_AVR_MS8_LDI = 22;
public static final int R_AVR_MS8_LDI_NEG = 23;
public static final int R_AVR_LO8_LDI_GS = 24;
public static final int R_AVR_HI8_LDI_GS = 25;
public static final int R_AVR_8 = 26;
public static final int R_AVR_8_LO8 = 27;
public static final int R_AVR_8_HI8 = 28;
public static final int R_AVR_8_HLO8 = 29;
public static final int R_AVR_DIFF8 = 30;
public static final int R_AVR_DIFF16 = 31;
public static final int R_AVR_DIFF32 = 32;
public static final int R_AVR_LDS_STS_16 = 33;
public static final int R_AVR_PORT6 = 34;
public static final int R_AVR_PORT5 = 35;
}

View file

@ -24,12 +24,19 @@ import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.NotFoundException;
public class AVR32_ElfRelocationHandler extends ElfRelocationHandler {
public class AVR32_ElfRelocationHandler
extends AbstractElfRelocationHandler<AVR32_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public AVR32_ElfRelocationHandler() {
super(AVR32_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -37,292 +44,278 @@ public class AVR32_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, AVR32_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
int type = relocation.getType();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
ElfHeader elf = elfRelocationContext.getElfHeader();
long offset = (int) relocationAddress.getOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
long symbolValue = elfRelocationContext.getSymbolValue(sym);
int symbolIndex = relocation.getSymbolIndex();
int oldValue = memory.getInt(relocationAddress);
int byteLength = 4; // most relocations affect 4-bytes (change if different)
int newValueShiftToAligntoUpper = 0;
if (elf.e_machine() == ElfConstants.EM_AVR32) {
int newValueShiftToAligntoUpper = 0;
switch (type) {
case AVR32_ElfRelocationConstants.R_AVR32_NONE:
return RelocationResult.SKIPPED;
case AVR32_ElfRelocationConstants.R_AVR32_32:
int newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
switch (type) {
case R_AVR32_NONE:
return RelocationResult.SKIPPED;
case R_AVR32_32:
int newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_DIFF32:
newValue = (((int) symbolValue + (int) addend + oldValue) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_22H_PCREL://(BR{cond4})
newValue = (int) ((symbolValue + (int) addend - offset) >> 1);
int nVpart1 = (newValue & 0x0000ffff);
int nVpart2 = (newValue & 0x00010000);
int nVpart3 = (newValue & 0x001e0000);
int newValueParts =
(((nVpart3 << 8) | (nVpart2 << 4) | (nVpart1)) & 0x1e10ffff);
int newValueSet = (oldValue | newValueParts);
memory.setInt(relocationAddress, newValueSet);
break;
case AVR32_ElfRelocationConstants.R_AVR32_11H_PCREL: //WORKING! (RJMP)
newValue = (int) (((symbolValue + (int) addend - offset) >> 1) << 4);
int tempNewValHold = (newValue & 0x00000ff3);
int tempDispHold = ((newValue & 0x00003000) >> 12);
newValueShiftToAligntoUpper = ((tempNewValHold << 16) | (tempDispHold << 16));
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_9H_PCREL://WORKING! (BR{cond3})
newValue =
(int) ((((symbolValue + (int) addend - offset) >> 1) << 4) & 0x00000ff0);
newValueShiftToAligntoUpper = (newValue << 16);
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_32_CPENT: //WORKING! (POINTER_SYMBOL_PLACEMENT)
newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
case R_AVR32_DIFF32:
newValue = (((int) symbolValue + (int) addend + oldValue) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case R_AVR32_22H_PCREL://(BR{cond4})
newValue = (int) ((symbolValue + (int) addend - offset) >> 1);
int nVpart1 = (newValue & 0x0000ffff);
int nVpart2 = (newValue & 0x00010000);
int nVpart3 = (newValue & 0x001e0000);
int newValueParts = (((nVpart3 << 8) | (nVpart2 << 4) | (nVpart1)) & 0x1e10ffff);
int newValueSet = (oldValue | newValueParts);
memory.setInt(relocationAddress, newValueSet);
break;
case R_AVR32_11H_PCREL: //WORKING! (RJMP)
newValue = (int) (((symbolValue + (int) addend - offset) >> 1) << 4);
int tempNewValHold = (newValue & 0x00000ff3);
int tempDispHold = ((newValue & 0x00003000) >> 12);
newValueShiftToAligntoUpper = ((tempNewValHold << 16) | (tempDispHold << 16));
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case R_AVR32_9H_PCREL://WORKING! (BR{cond3})
newValue = (int) ((((symbolValue + (int) addend - offset) >> 1) << 4) & 0x00000ff0);
newValueShiftToAligntoUpper = (newValue << 16);
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case R_AVR32_32_CPENT: //WORKING! (POINTER_SYMBOL_PLACEMENT)
newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
Address currNewAddress = space.getAddress(newValue);
Address currNewAddress = space.getAddress(newValue);
if (!memory.contains(currNewAddress) && sym != null) {
int currElfSymbolInfoBind = sym.getBind();
int currElfSymbolInfoType = sym.getType();
if (!memory.contains(currNewAddress) && sym != null) {
int currElfSymbolInfoBind = sym.getBind();
int currElfSymbolInfoType = sym.getType();
if ((currElfSymbolInfoBind == ElfSymbol.STB_GLOBAL) &&
((currElfSymbolInfoType == ElfSymbol.STT_OBJECT) ||
(currElfSymbolInfoType == ElfSymbol.STT_NOTYPE))) {
String currElfSymbolName = sym.getNameAsString();
if ((currElfSymbolInfoBind == ElfSymbol.STB_GLOBAL) &&
((currElfSymbolInfoType == ElfSymbol.STT_OBJECT) ||
(currElfSymbolInfoType == ElfSymbol.STT_NOTYPE))) {
String currElfSymbolName = sym.getNameAsString();
long currElfSymbolSize = sym.getSize();
if (currElfSymbolSize == 0) {
currElfSymbolSize = 2;
}
StringBuffer newSectionNameBuff = new StringBuffer();
newSectionNameBuff.append("cpool.");
newSectionNameBuff.append(currElfSymbolName);
StringBuffer newSectionTypeBuff = new StringBuffer();
newSectionTypeBuff.append("Constant Pool ");
boolean isReadable = true;
boolean isWritable = true;
boolean isExecutable = true;
if (currElfSymbolInfoType == ElfSymbol.STT_OBJECT) {
isReadable = true;
isWritable = true;
isExecutable = false;
newSectionTypeBuff.append("Global Variable Object");
}
else {
isReadable = true;
isWritable = false;
isExecutable = true;
newSectionTypeBuff.append("Global External Function");
}
ElfLoadHelper loadHelper = elfRelocationContext.getLoadHelper();
MemoryBlockUtils.createInitializedBlock(program, false,
newSectionNameBuff.toString(), currNewAddress, currElfSymbolSize,
newSectionTypeBuff.toString(), "AVR32-ELF Loader", isReadable,
isWritable, isExecutable, loadHelper.getLog());
long currElfSymbolSize = sym.getSize();
if (currElfSymbolSize == 0) {
currElfSymbolSize = 2;
}
}
try {
Listing listing = program.getListing();
listing.createData(relocationAddress, StructConverter.POINTER,
relocationAddress.getPointerSize());
}
catch (CodeUnitInsertionException cuie) {
System.out.println("Attempting to create Pointer Data: " + cuie);
}
break;
case AVR32_ElfRelocationConstants.R_AVR32_CPCALL: //WORKING! (MCALL)
int checkForPC = (oldValue & 0x000f0000);
if (checkForPC == 0xf0000) {
newValue =
(int) (((symbolValue + (int) addend - (offset & 0xfffffffc)) >> 2) &
0x0000ffff);
}
else {
newValue =
(int) (((symbolValue + (int) addend - offset) >> 2) & 0x0000ffff);
}
int newValueSet_CPCALL = ((oldValue | newValue) & 0xffffffff);
memory.setInt(relocationAddress, newValueSet_CPCALL);
break;
case AVR32_ElfRelocationConstants.R_AVR32_9W_CP: //WORKING! (LDDPC)
newValue =
(int) ((((symbolValue + (int) addend - (offset & 0xfffffffc)) >>> 2) << 4) &
0x000007f0);
newValueShiftToAligntoUpper = (newValue << 16);
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_ALIGN:
//System.out.print("-> type = " + type + ", symbolValue = " + symbolValue + ", addend = " + addend + ", offset = " + offset + " - ");
/*if((addend == 2) && (oldValueLong == 0)){
try{
Listing listing = prog.getListing();
listing.createData(relocationAddress, StructConverter.WORD, (int)addend);
}catch(CodeUnitInsertionException cuie){
System.out.println("Attempting to create Pointer Data: " + cuie);
}
System.out.println(" HANDLED AVR relocation: R_AVR32_ALIGN at "+relocationAddress + ", New = " + newValue);
}*/
//System.out.println(" HANDLED AVR relocation: R_AVR32_ALIGN at "+relocationAddress + ", OldValue = " + Integer.toHexString(oldValue));
return RelocationResult.SKIPPED;
//TODO: THE FOLLOWING:
/*case AVR32_ElfRelocationConstants.R_AVR32_16_CP:
//System.out.print("-> type = " + type + ", symbolValue = " + symbolValue + ", addend = " + addend + ", offset = " + offset + " - ");
//newValue = (int)((symbolValue + (int)addend - offset)) & 0x0000ffff;
//memory.setInt(relocationAddress, newValue);
//System.out.println("? HANDLED AVR relocation: R_AVR32_16_CP at "+relocationAddress + ", New = " + Integer.toHexString(newValue));
break;*/
/*case AVR32_ElfRelocationConstants.R_AVR32_RELATIVE:
newValue = (((int)elf.getImageBase() + (int)addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_RELATIVE at "+relocationAddress + ", New = " + newValue);
break;
*/
/*case AVR32_ElfRelocationConstants.R_AVR32_16:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_8:
newValue = ((symbolValue + (int)addend) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_32_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_32_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_16_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_8_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case AVR32_ElfRelocationConstants.R_AVR32_DIFF16:
newValue = ((symbolValue) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_DIFF8 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_DIFF8:
newValue = ((symbolValue) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_DIFF8 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_21S:
newValue = ((symbolValue + (int)addend) & 0x1e10ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_21S at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_16U: //Use long to accommodate the Unsignedness...
long newValueLong = ((symbolValue + addend) & 0x0000ffff);
memory.setLong(relocationAddress, newValueLong);
System.out.println(" HANDLED AVR relocation: R_AVR32_16U at "+relocationAddress + ", NewLong = " + newValueLong);
break;
case AVR32_ElfRelocationConstants.R_AVR32_16S:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16S at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_8S:
newValue = (((symbolValue + (int)addend) << 4) & 0x00000ff0);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8S at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_8S_EXT:
newValue = ((symbolValue + (int)addend) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8S_EXT at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_18W_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >> 2) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_18W_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_16B_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16B_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_16N_PCREL:
newValue = (int)((offset - symbolValue - (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16N_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_14UW_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >>> 2) & 0x0000f0ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_14UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case AVR32_ElfRelocationConstants.R_AVR32_10UW_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >>> 2) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_10UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case AVR32_ElfRelocationConstants.R_AVR32_9UW_PCREL:
newValue = (int)((((symbolValue + (int)addend - offset) >>> 2) << 4) & 0x000007f0);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_9UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_HI16:
newValue = (((symbolValue + (int)addend) >> 16) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_HI16 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_LO16:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_LO16 at "+relocationAddress + ", New = " + newValue);
break;
case AVR32_ElfRelocationConstants.R_AVR32_GOTPC:
ElfSectionHeader dotgot = elf.getGOT();
MemoryBlock got = memory.getBlock(dotgot.getNameAsString());
newValue = ((symbolValue + (int)addend - (int)got.getStart().getOffset()) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_GOTPC at "+relocationAddress + ", New = " + newValue);
break;*/
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex,
elfRelocationContext.getSymbolName(symbolIndex),
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
StringBuffer newSectionNameBuff = new StringBuffer();
newSectionNameBuff.append("cpool.");
newSectionNameBuff.append(currElfSymbolName);
StringBuffer newSectionTypeBuff = new StringBuffer();
newSectionTypeBuff.append("Constant Pool ");
boolean isReadable = true;
boolean isWritable = true;
boolean isExecutable = true;
if (currElfSymbolInfoType == ElfSymbol.STT_OBJECT) {
isReadable = true;
isWritable = true;
isExecutable = false;
newSectionTypeBuff.append("Global Variable Object");
}
else {
isReadable = true;
isWritable = false;
isExecutable = true;
newSectionTypeBuff.append("Global External Function");
}
ElfLoadHelper loadHelper = elfRelocationContext.getLoadHelper();
MemoryBlockUtils.createInitializedBlock(program, false,
newSectionNameBuff.toString(), currNewAddress, currElfSymbolSize,
newSectionTypeBuff.toString(), "AVR32-ELF Loader", isReadable,
isWritable, isExecutable, loadHelper.getLog());
}
}
try {
Listing listing = program.getListing();
listing.createData(relocationAddress, StructConverter.POINTER,
relocationAddress.getPointerSize());
}
catch (CodeUnitInsertionException cuie) {
System.out.println("Attempting to create Pointer Data: " + cuie);
}
break;
case R_AVR32_CPCALL: //WORKING! (MCALL)
int checkForPC = (oldValue & 0x000f0000);
if (checkForPC == 0xf0000) {
newValue = (int) (((symbolValue + (int) addend - (offset & 0xfffffffc)) >> 2) &
0x0000ffff);
}
else {
newValue = (int) (((symbolValue + (int) addend - offset) >> 2) & 0x0000ffff);
}
int newValueSet_CPCALL = ((oldValue | newValue) & 0xffffffff);
memory.setInt(relocationAddress, newValueSet_CPCALL);
break;
case R_AVR32_9W_CP: //WORKING! (LDDPC)
newValue =
(int) ((((symbolValue + (int) addend - (offset & 0xfffffffc)) >>> 2) << 4) &
0x000007f0);
newValueShiftToAligntoUpper = (newValue << 16);
newValue = ((oldValue | newValueShiftToAligntoUpper) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case R_AVR32_ALIGN:
//System.out.print("-> type = " + type + ", symbolValue = " + symbolValue + ", addend = " + addend + ", offset = " + offset + " - ");
/*if((addend == 2) && (oldValueLong == 0)){
try{
Listing listing = prog.getListing();
listing.createData(relocationAddress, StructConverter.WORD, (int)addend);
}catch(CodeUnitInsertionException cuie){
System.out.println("Attempting to create Pointer Data: " + cuie);
}
System.out.println(" HANDLED AVR relocation: R_AVR32_ALIGN at "+relocationAddress + ", New = " + newValue);
}*/
//System.out.println(" HANDLED AVR relocation: R_AVR32_ALIGN at "+relocationAddress + ", OldValue = " + Integer.toHexString(oldValue));
return RelocationResult.SKIPPED;
//TODO: THE FOLLOWING:
/*case R_AVR32_16_CP:
//System.out.print("-> type = " + type + ", symbolValue = " + symbolValue + ", addend = " + addend + ", offset = " + offset + " - ");
//newValue = (int)((symbolValue + (int)addend - offset)) & 0x0000ffff;
//memory.setInt(relocationAddress, newValue);
//System.out.println("? HANDLED AVR relocation: R_AVR32_16_CP at "+relocationAddress + ", New = " + Integer.toHexString(newValue));
break;*/
/*case R_AVR32_RELATIVE:
newValue = (((int)elf.getImageBase() + (int)addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_RELATIVE at "+relocationAddress + ", New = " + newValue);
break;
*/
/*case R_AVR32_16:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_8:
newValue = ((symbolValue + (int)addend) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_32_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_32_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_16_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_8_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case R_AVR32_DIFF16:
newValue = ((symbolValue) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_DIFF8 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_DIFF8:
newValue = ((symbolValue) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_DIFF8 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_21S:
newValue = ((symbolValue + (int)addend) & 0x1e10ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_21S at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_16U: //Use long to accommodate the Unsignedness...
long newValueLong = ((symbolValue + addend) & 0x0000ffff);
memory.setLong(relocationAddress, newValueLong);
System.out.println(" HANDLED AVR relocation: R_AVR32_16U at "+relocationAddress + ", NewLong = " + newValueLong);
break;
case R_AVR32_16S:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16S at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_8S:
newValue = (((symbolValue + (int)addend) << 4) & 0x00000ff0);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8S at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_8S_EXT:
newValue = ((symbolValue + (int)addend) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_8S_EXT at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_18W_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >> 2) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_18W_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_16B_PCREL:
newValue = (int)((symbolValue + (int)addend - offset) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16B_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_16N_PCREL:
newValue = (int)((offset - symbolValue - (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_16N_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_14UW_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >>> 2) & 0x0000f0ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_14UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case R_AVR32_10UW_PCREL:
newValue = (int)(((symbolValue + (int)addend - offset) >>> 2) & 0x000000ff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_10UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;*/
/*case R_AVR32_9UW_PCREL:
newValue = (int)((((symbolValue + (int)addend - offset) >>> 2) << 4) & 0x000007f0);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_9UW_PCREL at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_HI16:
newValue = (((symbolValue + (int)addend) >> 16) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_HI16 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_LO16:
newValue = ((symbolValue + (int)addend) & 0x0000ffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_LO16 at "+relocationAddress + ", New = " + newValue);
break;
case R_AVR32_GOTPC:
ElfSectionHeader dotgot = elf.getGOT();
MemoryBlock got = memory.getBlock(dotgot.getNameAsString());
newValue = ((symbolValue + (int)addend - (int)got.getStart().getOffset()) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
System.out.println(" HANDLED AVR relocation: R_AVR32_GOTPC at "+relocationAddress + ", New = " + newValue);
break;*/
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
return new RelocationResult(Status.APPLIED, byteLength);
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,58 +13,58 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.elf;
package ghidra.app.util.bin.format.elf.relocation;
public class AVR32_ElfRelocationConstants {
public enum AVR32_ElfRelocationType implements ElfRelocationType {
/* Atmel AVR32 relocations. */
// NONE (possibly a placeholder for relocations that are moved)
// <align:0 bitpos:0 bitsize:0 complain:dont>
public static final int R_AVR32_NONE = 0;
R_AVR32_NONE(0),
/* Data Relocations */
// DATA: ((S + A) & 0xffffffff) (Normal Data)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_32 = 1;
R_AVR32_32(1),
// DATA: ((S + A) & 0x0000ffff) (Normal Data)
// <align:0 bitpos:0 bitsize:16 complain:bitfield>
public static final int R_AVR32_16 = 2;
R_AVR32_16(2),
// DATA: ((S + A) & 0x000000ff)(Normal Data)
// <align:0 bitpos:0 bitsize:8 complain:bitfield>
public static final int R_AVR32_8 = 3;
R_AVR32_8(3),
// DATA: ((S + A - P) & 0xffffffff) (PC-relative)
// <align:0 bitpos:0 bitsize:32 complain:signed>
public static final int R_AVR32_32_PCREL = 4;
R_AVR32_32_PCREL(4),
// DATA: ((S + A - P) & 0x0000ffff) (PC-relative)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_16_PCREL = 5;
R_AVR32_16_PCREL(5),
// DATA: ((S + A - P) & 0x000000ff) (PC-relative)
// <align:0 bitpos:0 bitsize:8 complain:signed>
public static final int R_AVR32_8_PCREL = 6;
R_AVR32_8_PCREL(6),
// Difference between two labels: L2 - L1. The value of L1 is encoded as S +
// A,
// while the initial difference after assembly is
// inserted into the object file by the assembler.
// DATA: (S & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_DIFF32 = 7;
R_AVR32_DIFF32(7),
// DATA: (S & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_DIFF16 = 8;
R_AVR32_DIFF16(8),
// DATA: (S & 0x000000ff)
// <align:0 bitpos:0 bitsize:8 complain:signed>
public static final int R_AVR32_DIFF8 = 9;
R_AVR32_DIFF8(9),
// Reference to a symbol through the Global Offset Table (GOT). The linker
// will allocate an entry for symbol in the GOT and insert the offset
// of this entry as the relocation value. A = 0
// of this entry as the relocation value. A(0
// DATA: (G & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:signed>
public static final int R_AVR32_GOT32 = 10;
R_AVR32_GOT32(10),
// DATA: (G & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_GOT16 = 11;
R_AVR32_GOT16(11),
// DATA: (G & 0x000000ff)
// <align:0 bitpos:0 bitsize:8 complain:signed>
public static final int R_AVR32_GOT8 = 12;
R_AVR32_GOT8(12),
/* Normal Code Relocations */
// Normal (non-pc-relative) code relocations. Alignment and signedness
// is indicated by the suffixes. S means signed, U means unsigned.
@ -73,19 +72,19 @@ public class AVR32_ElfRelocationConstants {
// byte-aligned (no alignment.)
// NORMAL CODE: ((S + A) & 0x1e10ffff)
// <align:0 bitpos:0 bitsize:21 complain:signed>
public static final int R_AVR32_21S = 13;
R_AVR32_21S(13),
// NORMAL CODE: ((S + A) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:unsigned>
public static final int R_AVR32_16U = 14;
R_AVR32_16U(14),
// NORMAL CODE: ((S + A) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_16S = 15;
R_AVR32_16S(15),
// NORMAL CODE: (((S + A)) << 4) & 0x00000ff0)
// <align:0 bitpos:4 bitsize:8 complain:signed>
public static final int R_AVR32_8S = 16;
R_AVR32_8S(16),
// NORMAL CODE: ((S + A) & 0x000000ff)
// <align:0 bitpos:0 bitsize:8 complain:signed>
public static final int R_AVR32_8S_EXT = 17;
R_AVR32_8S_EXT(17),
/* PC-Relative Code Relocations */
// PC-relative relocations are signed if neither 'U' nor 'S' is
// specified. However, we explicitly tack on a 'B' to indicate no
@ -94,49 +93,49 @@ public class AVR32_ElfRelocationConstants {
// This particular one resolves to P - S - A.
// PC-REL CODE: (((S + A - P) >> 1) & 0x1e10ffff)
// <align:1 bitpos:0 bitsize:21 complain:signed>
public static final int R_AVR32_22H_PCREL = 18;
R_AVR32_22H_PCREL(18),
// PC-REL CODE: (((S + A - P) >> 2) & 0x0000ffff)
// <align:2 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_18W_PCREL = 19;
R_AVR32_18W_PCREL(19),
// PC-REL CODE: ((S + A - P) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_16B_PCREL = 20;
R_AVR32_16B_PCREL(20),
// PC-REL CODE: ((P - S - A) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_16N_PCREL = 21;
R_AVR32_16N_PCREL(21),
// PC-REL CODE: (((S + A - P) >>> 2) & 0x0000f0ff)
// <align:2 bitpos:0 bitsize:12 complain:unsigned>
public static final int R_AVR32_14UW_PCREL = 22;
R_AVR32_14UW_PCREL(22),
// PC-REL CODE: (((S + A - P) >> 1) << 4)
// Must then: tmp1 = (newValue & 0x00000ff3);
// Must then: tmp2 = ((newValue & 0x00003000) >> 12); (to match opcode disp)
// Must then: tmp3 = ((tmp1 << 16) | (tmp2 << 16))
// Must then: tmp1((newValue & 0x00000ff3)),
// Must then: tmp2(((newValue & 0x00003000) >> 12)), (to match opcode disp)
// Must then: tmp3(((tmp1 << 16) | (tmp2 << 16))
// Must then: (oldValue | tmp3) & 0xffffffff)
// <align:1 bitpos:4 bitsize:10 complain:signed>
public static final int R_AVR32_11H_PCREL = 23;
R_AVR32_11H_PCREL(23),
// PC-REL CODE: (((S + A - P) >>> 2) & 0x000000ff)
// <align:2 bitpos:0 bitsize:8 complain:unsigned>
public static final int R_AVR32_10UW_PCREL = 24;
R_AVR32_10UW_PCREL(24),
// PC-REL CODE: ((((S + A - P) >> 1) << 4) & 0x00000ff0)
// Must then: (oldValue | newValue << 16) & 0xffffffff)
// <align:1 bitpos:4 bitsize:8 complain:signed>
public static final int R_AVR32_9H_PCREL = 25;
R_AVR32_9H_PCREL(25),
// PC-REL CODE: ((((S + A) << 4) - P) >>> 2) & 0x000007f0)
// <align:2 bitpos:4 bitsize:7 complain:unsigned>
public static final int R_AVR32_9UW_PCREL = 26;
R_AVR32_9UW_PCREL(26),
/* Special Code Relocations */
// Special CODE: (((S + A) >> 16) & 0x0000ffff)
// <align:16 bitpos:0 bitsize:16 complain:dont>
public static final int R_AVR32_HI16 = 27;
R_AVR32_HI16(27),
// Special CODE: ((S + A) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:dont>
public static final int R_AVR32_LO16 = 28;
R_AVR32_LO16(28),
/* PIC Relocations */
// Subtract the link-time address of the GOT from (S + A) and
// insert the result.
// PIC: (((S + A) - GOT) & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_GOTPC = 29;
R_AVR32_GOTPC(29),
// Reference to a symbol through the GOT. The linker will
// allocate an entry for symbol in the GOT and insert
// the offset of this entry as the relocation value.
@ -144,51 +143,51 @@ public class AVR32_ElfRelocationConstants {
// word-aligned, etc.
// PIC: ((G >> 2) & 0x1e10ffff)
// <align:2 bitpos:0 bitsize:21 complain:signed> (Call instructions)
public static final int R_AVR32_GOTCALL = 30;
R_AVR32_GOTCALL(30),
// PIC: ((G >> 2) & 0x1e10ffff)
// <align:2 bitpos:0 bitsize:21 complain:signed> (lda.w instructions)
public static final int R_AVR32_LDA_GOT = 31;
R_AVR32_LDA_GOT(31),
// PIC: (G & 0x1e10ffff)
// <align:0 bitpos:0 bitsize:21 complain:signed>
public static final int R_AVR32_GOT21S = 32;
R_AVR32_GOT21S(32),
// PIC: ((G >> 2) & 0x0000ffff)
// <align:2 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_GOT18SW = 33;
R_AVR32_GOT18SW(33),
// PIC: (G & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_GOT16S = 34;
R_AVR32_GOT16S(34),
// PIC: (((G) << 4) >> 2) & 0x000001f0)
// <align:2 bitpos:4 bitsize:5 complain:unsigned>
public static final int R_AVR32_GOT7UW = 35;
R_AVR32_GOT7UW(35),
/* Constant Pool Relocations */
// 32-bit constant pool entry.
// CONST POOL: ((S + A) & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_32_CPENT = 36;
R_AVR32_32_CPENT(36),
// Constant pool references. Some of these relocations are signed,
// others are unsigned. Constant pool always comes after
// the code that references it.
// CONST POOL: (((S + A - P) >> 2) & 0x0000ffff)
// Must then: ((oldValue | newValue) & 0xffffffff)
// <align:2 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_CPCALL = 37;
R_AVR32_CPCALL(37),
// CONST POOL: ((S + A - P) & 0x0000ffff)
// <align:0 bitpos:0 bitsize:16 complain:signed>
public static final int R_AVR32_16_CP = 38;
R_AVR32_16_CP(38),
// CONST POOL: ((((S + A - P) >>> 2) << 4) & 0x000007f0)
// Must then: ((oldValue | newValue << 16) & 0xffffffff)
// <align:2 bitpos:4 bitsize:7 complain:unsigned>
public static final int R_AVR32_9W_CP = 39;
R_AVR32_9W_CP(39),
/* Dynamic Relocations */
// Dynamic: ((B + A) & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:signed>
public static final int R_AVR32_RELATIVE = 40;
R_AVR32_RELATIVE(40),
// Dynamic: ((S + A) & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_GLOB_DAT = 41;
R_AVR32_GLOB_DAT(41),
// Dynamic: ((S + A) & 0xffffffff)
// <align:0 bitpos:0 bitsize:32 complain:dont>
public static final int R_AVR32_JMP_SLOT = 42;
R_AVR32_JMP_SLOT(42),
/* Linkrelax Information */
// Symbol(S) must be the absolute symbol. The Addend(A) specifies
// the alignment order, e.g. if A is 2, the linker must add
@ -196,11 +195,22 @@ public class AVR32_ElfRelocationConstants {
// boundary.
// Linkrelax: (P << A)
// <align:0 bitpos:0 bitsize:0 complain:unsigned>
public static final int R_AVR32_ALIGN = 43;
public static final int R_AVR32_NUM = 44;
R_AVR32_ALIGN(43),
R_AVR32_NUM(44),
/* Total Size in Bytes of the Global Offset Table */
public static final int DT_AVR32_GOTSZ = 0x70000001;
DT_AVR32_GOTSZ(0x70000001),
/* CPU-Specific flags for the ELF header e_flags field */
public static final int EF_AVR32_LINKRELAX = 0x01;
public static final int EF_AVR32_PIC = 0x02;
EF_AVR32_LINKRELAX(0x01),
EF_AVR32_PIC(0x02);
public final int typeId;
private AVR32_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -20,11 +20,18 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.util.exception.NotFoundException;
import ghidra.program.model.reloc.RelocationResult;
public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
public class AVR8_ElfRelocationHandler
extends AbstractElfRelocationHandler<AVR8_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public AVR8_ElfRelocationHandler() {
super(AVR8_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -32,126 +39,114 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, AVR8_ElfRelocationType type, Address relocationAddress,
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
// WARNING: symbolValue is not in bytes.
// It is an addressable word offset within the symbols address space
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int type = relocation.getType();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
ElfHeader elf = elfRelocationContext.getElfHeader();
// WARNING: offset is in bytes
// be careful, word address potentially with byte indexes
// WARNING: offset is in bytes be careful, word address potentially with byte indexes
long offset = relocationAddress.getOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
// WARNING: symbolValue here is not in bytes.
// it is an addressable word offset for the symbols address space
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
int symbolIndex = relocation.getSymbolIndex();
int oldValue = memory.getShort(relocationAddress);
if (elf.e_machine() != ElfConstants.EM_AVR) {
return RelocationResult.FAILURE;
}
int newValue = 0;
int byteLength = 2; // most relocations affect 2-bytes (change if different)
switch (type) {
case AVR8_ElfRelocationConstants.R_AVR_NONE:
case R_AVR_NONE:
return RelocationResult.SKIPPED;
case AVR8_ElfRelocationConstants.R_AVR_32:
case R_AVR_32:
newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);
break;
case AVR8_ElfRelocationConstants.R_AVR_7_PCREL:
case R_AVR_7_PCREL:
newValue = (int) ((symbolValue * 2 + (int) addend - offset));
newValue -= 2; // branch PC is offset+2
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
if (newValue > ((1 << 7) - 1) || (newValue < -(1 << 7))) {
markAsError(program, relocationAddress, type, symbolName, "relocation overflow",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation overflow", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue = (oldValue & 0xfc07) | (((newValue >> 1) << 3) & 0x3f8);
memory.setShort(relocationAddress, (short) newValue);
break;
case AVR8_ElfRelocationConstants.R_AVR_13_PCREL:
case R_AVR_13_PCREL:
newValue = (int) ((symbolValue * 2 + (int) addend - offset));
newValue -= 2; // branch PC is offset+2
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
if (newValue < -2048 || newValue > 2047) {
markAsWarning(program, relocationAddress, symbolName, symbolName, symbolIndex,
"possible relocation error", elfRelocationContext.getLog());
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Possible relocation error", elfRelocationContext.getLog());
}
newValue = (oldValue & 0xf000) | (newValue & 0xfff);
memory.setShort(relocationAddress, (short) newValue);
break;
case AVR8_ElfRelocationConstants.R_AVR_16:
case R_AVR_16:
newValue = ((int) symbolValue + (int) addend);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_16_PM:
case R_AVR_16_PM:
newValue = (((int) symbolValue * 2 + (int) addend));
newValue >>= 1;
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI:
case R_AVR_LO8_LDI:
newValue = (((int) symbolValue + (int) addend));
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI:
case R_AVR_HI8_LDI:
newValue = (((int) symbolValue + (int) addend));
newValue = (newValue >> 8) & 0xff;
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI:
case R_AVR_HH8_LDI:
newValue = (((int) symbolValue + (int) addend));
newValue = (newValue >> 16) & 0xff;
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_NEG:
case R_AVR_LO8_LDI_NEG:
newValue = (((int) symbolValue + (int) addend));
newValue = -newValue;
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_NEG:
case R_AVR_HI8_LDI_NEG:
newValue = (((int) symbolValue + (int) addend));
newValue = -newValue;
newValue = (newValue >> 8) & 0xff;
@ -159,7 +154,7 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_NEG:
case R_AVR_HH8_LDI_NEG:
newValue = (((int) symbolValue + (int) addend));
newValue = -newValue;
newValue = (newValue >> 16) & 0xff;
@ -167,11 +162,11 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_PM:
case R_AVR_LO8_LDI_PM:
newValue = (((int) symbolValue * 2 + (int) addend));
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -179,11 +174,11 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_PM:
case R_AVR_HI8_LDI_PM:
newValue = (((int) symbolValue * 2 + (int) addend));
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -192,11 +187,11 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_PM:
case R_AVR_HH8_LDI_PM:
newValue = (((int) symbolValue * 2 + (int) addend));
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -205,12 +200,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_PM_NEG:
case R_AVR_LO8_LDI_PM_NEG:
newValue = (((int) symbolValue * 2 + (int) addend));
newValue = -newValue;
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -218,12 +213,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_PM_NEG:
case R_AVR_HI8_LDI_PM_NEG:
newValue = (((int) symbolValue * 2 + (int) addend));
newValue = -newValue;
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -232,12 +227,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_PM_NEG:
case R_AVR_HH8_LDI_PM_NEG:
newValue = (((int) symbolValue * 2 + (int) addend));
newValue = -newValue;
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -246,12 +241,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_CALL:
case R_AVR_CALL:
newValue = (int) symbolValue * 2 + (int) addend;
if ((newValue & 1) == 1) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
newValue >>= 1;
@ -263,12 +258,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 4;
break;
case AVR8_ElfRelocationConstants.R_AVR_LDI: /* data/eeprom */
case R_AVR_LDI: /* data/eeprom */
newValue = (((int) symbolValue + (int) addend));
if ((newValue & 0xffff) > 255) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -277,12 +272,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_6: /* data/eeprom **/
case R_AVR_6: /* data/eeprom **/
newValue = (((int) symbolValue + (int) addend));
if (((newValue & 0xffff) > 63) || (newValue < 0)) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -291,12 +286,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_6_ADIW:
case R_AVR_6_ADIW:
newValue = (((int) symbolValue + (int) addend));
if (((newValue & 0xffff) > 63) || (newValue < 0)) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -305,18 +300,18 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_DIFF8:
case AVR8_ElfRelocationConstants.R_AVR_DIFF16:
case AVR8_ElfRelocationConstants.R_AVR_DIFF32:
case R_AVR_DIFF8:
case R_AVR_DIFF16:
case R_AVR_DIFF32:
// nothing to do
break;
case AVR8_ElfRelocationConstants.R_AVR_LDS_STS_16:
case R_AVR_LDS_STS_16:
newValue = (((int) symbolValue + (int) addend));
if (((newValue & 0xffff) < 0x40) || (newValue & 0xFFFF) > 0xbf) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -325,12 +320,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_PORT6:
case R_AVR_PORT6:
newValue = (((int) symbolValue + (int) addend));
if ((newValue & 0xffff) > 0x3f) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -338,12 +333,12 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_PORT5:
case R_AVR_PORT5:
newValue = (((int) symbolValue + (int) addend));
if ((newValue & 0xffff) > 0x1f) {
markAsError(program, relocationAddress, type, symbolName,
"relocation out of range", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Relocation out of range", elfRelocationContext.getLog());
// continue to apply
}
@ -351,14 +346,14 @@ public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case AVR8_ElfRelocationConstants.R_AVR_MS8_LDI:
case AVR8_ElfRelocationConstants.R_AVR_MS8_LDI_NEG:
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_GS:
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_GS:
case AVR8_ElfRelocationConstants.R_AVR_8:
case AVR8_ElfRelocationConstants.R_AVR_8_LO8:
case AVR8_ElfRelocationConstants.R_AVR_8_HI8:
case AVR8_ElfRelocationConstants.R_AVR_8_HLO8:
case R_AVR_MS8_LDI:
case R_AVR_MS8_LDI_NEG:
case R_AVR_LO8_LDI_GS:
case R_AVR_HI8_LDI_GS:
case R_AVR_8:
case R_AVR_8_LO8:
case R_AVR_8_HI8:
case R_AVR_8_HLO8:
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View file

@ -0,0 +1,68 @@
/* ###
* 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 AVR8_ElfRelocationType implements ElfRelocationType {
R_AVR_NONE(0),
R_AVR_32(1),
R_AVR_7_PCREL(2),
R_AVR_13_PCREL(3),
R_AVR_16(4),
R_AVR_16_PM(5),
R_AVR_LO8_LDI(6),
R_AVR_HI8_LDI(7),
R_AVR_HH8_LDI(8),
R_AVR_LO8_LDI_NEG(9),
R_AVR_HI8_LDI_NEG(10),
R_AVR_HH8_LDI_NEG(11),
R_AVR_LO8_LDI_PM(12),
R_AVR_HI8_LDI_PM(13),
R_AVR_HH8_LDI_PM(14),
R_AVR_LO8_LDI_PM_NEG(15),
R_AVR_HI8_LDI_PM_NEG(16),
R_AVR_HH8_LDI_PM_NEG(17),
R_AVR_CALL(18),
R_AVR_LDI(19),
R_AVR_6(20),
R_AVR_6_ADIW(21),
R_AVR_MS8_LDI(22),
R_AVR_MS8_LDI_NEG(23),
R_AVR_LO8_LDI_GS(24),
R_AVR_HI8_LDI_GS(25),
R_AVR_8(26),
R_AVR_8_LO8(27),
R_AVR_8_HI8(28),
R_AVR_8_HLO8(29),
R_AVR_DIFF8(30),
R_AVR_DIFF16(31),
R_AVR_DIFF32(32),
R_AVR_LDS_STS_16(33),
R_AVR_PORT6(34),
R_AVR_PORT5(35);
public final int typeId;
private AVR8_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

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

View file

@ -22,10 +22,16 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class Loongarch_ElfRelocationHandler
extends AbstractElfRelocationHandler<Loongarch_ElfRelocationType, ElfRelocationContext<?>> {
public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
/**
* Constructor
*/
public Loongarch_ElfRelocationHandler() {
super(Loongarch_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -33,72 +39,61 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (!canRelocate(elf)) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, Loongarch_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
boolean is32 = elf.is32Bit();
int type = relocation.getType();
if (Loongarch_ElfRelocationConstants.R_LARCH_NONE == type) {
return RelocationResult.SKIPPED;
}
ElfHeader elf = elfRelocationContext.getElfHeader();
long addend = relocation.hasAddend() ? relocation.getAddend()
: elf.is32Bit() ? memory.getInt(relocationAddress)
: memory.getLong(relocationAddress);
long addend = relocation.hasAddend() ? relocation.getAddend() : is32 ? memory.getInt(relocationAddress) : memory.getLong(relocationAddress);
long offset = relocationAddress.getOffset();
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long value64 = 0;
int value32 = 0;
short value16 = 0;
byte value8 = 0;
byte[] bytes24 = new byte[3];
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case Loongarch_ElfRelocationConstants.R_LARCH_32:
case R_LARCH_32:
// Runtime address resolving *(int32_t *) PC = RtAddr + A
value32 = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value32);
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
warnExternalOffsetRelocation(program, relocationAddress,
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
warnExternalOffsetRelocation(program, relocationAddress, symbolAddr, symbolName,
addend, elfRelocationContext.getLog());
if (elf.is32Bit()) {
applyComponentOffsetPointer(program, relocationAddress, addend);
}
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_64:
case R_LARCH_64:
// Runtime address resolving *(int64_t *) PC = RtAddr + A
value64 = symbolValue + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
warnExternalOffsetRelocation(program, relocationAddress,
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
warnExternalOffsetRelocation(program, relocationAddress, symbolAddr, symbolName,
addend, elfRelocationContext.getLog());
if (elf.is64Bit()) {
applyComponentOffsetPointer(program, relocationAddress, addend);
}
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_RELATIVE:
case R_LARCH_RELATIVE:
// Runtime fixup for load-address *(void **) PC = B + A
if (is32) {
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
@ -109,15 +104,15 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_COPY:
case R_LARCH_COPY:
// Runtime memory copy in executable memcpy (PC, RtAddr, sizeof (sym))
markAsWarning(program, relocationAddress, "R_LARCH_COPY", symbolName, symbolIndex,
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_JUMP_SLOT:
case R_LARCH_JUMP_SLOT:
// Runtime PLT supporting (implementation-defined)
if (is32) {
if (elf.is32Bit()) {
value32 = (int) (symbolValue);
memory.setInt(relocationAddress, value32);
}
@ -128,47 +123,20 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPMOD32:
// TLS relocation word32 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPMOD32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
case R_LARCH_TLS_DTPMOD32: // TLS relocation word32 = S->TLSINDEX
case R_LARCH_TLS_DTPMOD64: // TLS relocation word64 = S->TLSINDEX
case R_LARCH_TLS_DTPREL32:
case R_LARCH_TLS_DTPREL64:
case R_LARCH_TLS_TPREL32:
case R_LARCH_TLS_TPREL64:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPMOD64:
// TLS relocation word64 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPMOD64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPREL32:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPREL32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_DTPREL64:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTPREL64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_TPREL32:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_DTREL32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_TLS_TPREL64:
markAsWarning(program, relocationAddress, "R_LARCH_TLS_TPREL64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case Loongarch_ElfRelocationConstants.R_LARCH_IRELATIVE:
if (is32) {
value32 = (int) ( addend + elfRelocationContext.getImageBaseWordAdjustmentOffset());
case R_LARCH_IRELATIVE:
if (elf.is32Bit()) {
value32 =
(int) (addend + elfRelocationContext.getImageBaseWordAdjustmentOffset());
memory.setInt(relocationAddress, value32);
}
else {
@ -178,75 +146,66 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
// case Loongarch_ElfRelocationConstants.R_LARCH_MARK_LA:
// case R_LARCH_MARK_LA:
// case R_LARCH_MARK_PCREL:
// case R_LARCH_SOP_PUSH_PCREL:
// case Loongarch_ElfRelocationConstants.R_LARCH_MARK_PCREL:
// case R_LARCH_SOP_PUSH_ABSOLUTE:
// PC-relative GOT reference MACRO la
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_PCREL:
// case R_LARCH_SOP_PUSH_DUP:
// PC-relative TLS IE GOT offset MACRO la.tls.ie
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_ABSOLUTE:
// PC-relative GOT reference MACRO la
// case R_LARCH_SOP_PUSH_GPREL:
// PC-relative TLS GD reference MACRO la.tls.gd
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_DUP:
// PC-relative TLS IE GOT offset MACRO la.tls.ie
// case R_LARCH_SOP_PUSH_TLS_TPREL:
// case R_LARCH_SOP_PUSH_TLS_GOT:
// case R_LARCH_SOP_PUSH_TLS_GD:
// case R_LARCH_SOP_PUSH_PLT_PCREL:
// case R_LARCH_SOP_ASSERT:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_GPREL:
// PC-relative TLS GD reference MACRO la.tls.gd
// case R_LARCH_SOP_NOT:
// Absolute address %lo(symbol) (S-Type)
// case R_LARCH_SOP_SUB:
// case R_LARCH_SOP_SL:
// case R_LARCH_SOP_SR:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_TPREL:
// case R_LARCH_SOP_ADD:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_GOT:
// case R_LARCH_SOP_AND:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_TLS_GD:
// case R_LARCH_SOP_IF_ELSE:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_PUSH_PLT_PCREL:
// case R_LARCH_SOP_POP_32_S_10_5:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_ASSERT:
// case R_LARCH_SOP_POP_32_U_10_12:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_NOT:
// Absolute address %lo(symbol) (S-Type)
// case R_LARCH_SOP_POP_32_S_10_12:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SUB:
// case R_LARCH_SOP_POP_32_S_10_16:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SL:
// case R_LARCH_SOP_POP_32_S_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_SR:
// case R_LARCH_SOP_POP_32_S_5_20:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_ADD:
// TLS LE thread usage %tprel_add(symbol)
// case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_AND:
// TLS LE thread usage %tprel_add(symbol)
// case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_IF_ELSE:
// TLS LE thread usage %tprel_add(symbol)
// case R_LARCH_SOP_POP_32_U:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_5:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_U_10_12:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_12:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_16:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_5_20:
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
// TLS LE thread usage %tprel_add(symbol)
// case Loongarch_ElfRelocationConstants.R_LARCH_SOP_POP_32_U:
// TLS LE thread usage %tprel_add(symbol)
case Loongarch_ElfRelocationConstants.R_LARCH_ADD8:
case R_LARCH_ADD8:
// 8-bit in-place addition *(int8_t *) PC += S + A
value8 = memory.getByte(relocationAddress);
value8 += (byte) symbolValue;
@ -255,7 +214,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD16:
case R_LARCH_ADD16:
// 16-bit in-place addition *(int16_t *) PC += S + A
value16 = memory.getShort(relocationAddress);
value16 += (short) symbolValue;
@ -264,10 +223,10 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 2;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD24:
case R_LARCH_ADD24:
// 24-bit in-place addition (int24_t *) PC += S + A
memory.getBytes(relocationAddress, bytes24);
value32 = ((bytes24[2] << 8) + bytes24[1] ) << 8 + bytes24[0];
value32 = ((bytes24[2] << 8) + bytes24[1]) << 8 + bytes24[0];
value32 += (int) symbolValue;
value32 += (int) addend;
bytes24[0] = (byte) value32;
@ -276,8 +235,8 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
memory.setBytes(relocationAddress, bytes24);
byteLength = 3;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD32:
case R_LARCH_ADD32:
// 32-bit in-place addition *(int32_t *) PC += S + A
value32 = memory.getInt(relocationAddress);
@ -286,7 +245,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case Loongarch_ElfRelocationConstants.R_LARCH_ADD64:
case R_LARCH_ADD64:
// 64-bit in-place addition *(int64_t *) PC += S + A
value64 = memory.getLong(relocationAddress);
@ -296,7 +255,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 8;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB8:
case R_LARCH_SUB8:
// 8-bit in-place subtraction *(int8_t *) PC -= S + A
value8 = memory.getByte(relocationAddress);
value8 -= (byte) symbolValue;
@ -305,7 +264,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB16:
case R_LARCH_SUB16:
// 16-bit in-place subtraction *(int16_t *) PC -= S + A
value16 = memory.getShort(relocationAddress);
value16 -= (short) symbolValue;
@ -314,10 +273,10 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 2;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB24:
case R_LARCH_SUB24:
// 24-bit in-place subtraction *(int324_t *) PC -= S + A
memory.getBytes(relocationAddress, bytes24);
value32 = ((bytes24[2] << 8) + bytes24[1] ) << 8 + bytes24[0];
value32 = ((bytes24[2] << 8) + bytes24[1]) << 8 + bytes24[0];
value32 -= (int) symbolValue;
value32 -= (int) addend;
bytes24[0] = (byte) value32;
@ -327,7 +286,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 3;
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB32:
case R_LARCH_SUB32:
// 32-bit in-place subtraction *(int32_t *) PC -= S + A
value32 = memory.getInt(relocationAddress);
value32 -= (int) symbolValue;
@ -335,7 +294,7 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case Loongarch_ElfRelocationConstants.R_LARCH_SUB64:
case R_LARCH_SUB64:
// 64-bit in-place subtraction *(int64_t *) PC -= S + A
value64 = memory.getLong(relocationAddress);
value64 -= symbolValue;
@ -344,113 +303,87 @@ public class Loongarch_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 8;
break;
// case Loongarch_ElfRelocationConstants.R_LARCH_GNU_VTINHERIT:
// GNU C++ vtable hierarchy
// case R_LARCH_GNU_VTINHERIT:
// GNU C++ vtable hierarchy
// case Loongarch_ElfRelocationConstants.R_LARCH_GNU_VTENTRY:
// GNU C++ vtable member usage
// case R_LARCH_GNU_VTENTRY:
// GNU C++ vtable member usage
// case Loongarch_ElfRelocationConstants.R_LARCH_B16:
// case R_LARCH_B16:
// case R_LARCH_B21:
// case R_LARCH_B26:
// case R_LARCH_ABS_HI20:
// case R_LARCH_ABS_LO12:
// case R_LARCH_ABS64_LO20:
// case R_LARCH_ABS64_HI12:
// case R_LARCH_PCALA_HI20:
// case R_LARCH_PCALA_LO12:
// case R_LARCH_PCALA64_LO20:
// case R_LARCH_PCALA64_HI12:
// case R_LARCH_GOT_PC_HI20:
// case R_LARCH_GOT_PC_LO12:
// case R_LARCH_GOT64_PC_LO20:
// case R_LARCH_GOT64_HI12:
// case R_LARCH_TLS_LE_HI20:
// case R_LARCH_TLS_LE_LO12:
// case R_LARCH_TLS_LE64_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_B21:
// case R_LARCH_TLS_LE64_HI12:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_B26:
// case R_LARCH_TLS_IE_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS_HI20:
// case R_LARCH_TLS_IE_PC_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS_LO12:
// case R_LARCH_TLS_IE64_PC_LO20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS64_LO20:
// case R_LARCH_TLS_IE64_PC_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_ABS64_HI12:
// case R_LARCH_TLS_IE_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA_HI20:
// case R_LARCH_TLS_IE_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA_LO12:
// case R_LARCH_TLS_IE64_LO20:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA64_LO20:
// case R_LARCH_TLS_IE64_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_PCALA64_HI12:
// case R_LARCH_TLS_LD_PC_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT_PC_HI20:
// case R_LARCH_TLS_LD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT_PC_LO12:
// case R_LARCH_TLS_GD_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT64_PC_LO20:
// case R_LARCH_TLS_GD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_GOT64_HI12:
// case R_LARCH_32_PCREL:
// 32-bit PC relative
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE64_LO20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LE64_HI12:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_PC_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_PC_LO20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_PC_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE_LO12:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_LO20:
// Instruction pair can be relaxed
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_IE64_HI12:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LD_PC_HI20:
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_LD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_GD_PC_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_TLS_GD_HI20:
// Local label subtraction
// case Loongarch_ElfRelocationConstants.R_LARCH_32_PCREL:
// 32-bit PC relative
// case Loongarch_ElfRelocationConstants.R_LARCH_RELAX:
// case Loongarch_ElfRelocationConstants.R_LARCH_DELETE:
// case Loongarch_ElfRelocationConstants.R_LARCH_ALIGN:
// case Loongarch_ElfRelocationConstants.R_LARCH_PCREL20_S2:
// case Loongarch_ElfRelocationConstants.R_LARCH_CFA:
// case Loongarch_ElfRelocationConstants.R_LARCH_ADD6:
// case Loongarch_ElfRelocationConstants.R_LARCH_SUB6:
// case Loongarch_ElfRelocationConstants.R_LARCH_ADD_ULEB128:
// case Loongarch_ElfRelocationConstants.R_LARCH_SUB_ULEB128:
// case Loongarch_ElfRelocationConstants.R_LARCH_64_PCREL:
// case R_LARCH_RELAX:
// case R_LARCH_DELETE:
// case R_LARCH_ALIGN:
// case R_LARCH_PCREL20_S2:
// case R_LARCH_CFA:
// case R_LARCH_ADD6:
// case R_LARCH_SUB6:
// case R_LARCH_ADD_ULEB128:
// case R_LARCH_SUB_ULEB128:
// case R_LARCH_64_PCREL:
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
return new RelocationResult(Status.APPLIED, byteLength);
}
}

View file

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

View file

@ -1,160 +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 MIPS_ElfRelocationConstants {
public static final int R_MIPS_NONE = 0;
public static final int R_MIPS_16 = 1;
public static final int R_MIPS_32 = 2; /* In Elf 64: alias R_MIPS_ADD */
public static final int R_MIPS_REL32 = 3; /* In Elf 64: alias R_MIPS_REL */
public static final int R_MIPS_26 = 4;
public static final int R_MIPS_HI16 = 5;
public static final int R_MIPS_LO16 = 6;
public static final int R_MIPS_GPREL16 = 7; /* In Elf 64: alias R_MIPS_GPREL */
public static final int R_MIPS_LITERAL = 8;
public static final int R_MIPS_GOT16 = 9; /* In Elf 64: alias R_MIPS_GOT */
public static final int R_MIPS_PC16 = 10;
public static final int R_MIPS_CALL16 = 11; /* In Elf 64: alias R_MIPS_CALL */
public static final int R_MIPS_GPREL32 = 12;
/* The remaining relocs are defined on Irix = although they are not
in the MIPS ELF ABI. */
public static final int R_MIPS_UNUSED1 = 13;
public static final int R_MIPS_UNUSED2 = 14;
public static final int R_MIPS_UNUSED3 = 15;
public static final int R_MIPS_SHIFT5 = 16;
public static final int R_MIPS_SHIFT6 = 17;
public static final int R_MIPS_64 = 18;
public static final int R_MIPS_GOT_DISP = 19;
public static final int R_MIPS_GOT_PAGE = 20;
public static final int R_MIPS_GOT_OFST = 21;
public static final int R_MIPS_GOT_HI16 = 22;
public static final int R_MIPS_GOT_LO16 = 23;
public static final int R_MIPS_SUB = 24;
public static final int R_MIPS_INSERT_A = 25;
public static final int R_MIPS_INSERT_B = 26;
public static final int R_MIPS_DELETE = 27;
public static final int R_MIPS_HIGHER = 28;
public static final int R_MIPS_HIGHEST = 29;
public static final int R_MIPS_CALL_HI16 = 30;
public static final int R_MIPS_CALL_LO16 = 31;
public static final int R_MIPS_SCN_DISP = 32;
public static final int R_MIPS_REL16 = 33;
public static final int R_MIPS_ADD_IMMEDIATE = 34;
public static final int R_MIPS_PJUMP = 35;
public static final int R_MIPS_RELGOT = 36;
public static final int R_MIPS_JALR = 37;
/* TLS relocations. */
public static final int R_MIPS_TLS_DTPMOD32 = 38;
public static final int R_MIPS_TLS_DTPREL32 = 39;
public static final int R_MIPS_TLS_DTPMOD64 = 40;
public static final int R_MIPS_TLS_DTPREL64 = 41;
public static final int R_MIPS_TLS_GD = 42;
public static final int R_MIPS_TLS_LDM = 43;
public static final int R_MIPS_TLS_DTPREL_HI16 = 44;
public static final int R_MIPS_TLS_DTPREL_LO16 = 45;
public static final int R_MIPS_TLS_GOTTPREL = 46;
public static final int R_MIPS_TLS_TPREL32 = 47;
public static final int R_MIPS_TLS_TPREL64 = 48;
public static final int R_MIPS_TLS_TPREL_HI16 = 49;
public static final int R_MIPS_TLS_TPREL_LO16 = 50;
public static final int R_MIPS_GLOB_DAT = 51;
/* MIPSr6 relocations */
public static final int R_MIPS_PC21_S2 = 60;
public static final int R_MIPS_PC26_S2 = 61;
public static final int R_MIPS_PC18_S3 = 62;
public static final int R_MIPS_PC19_S2 = 63;
public static final int R_MIPS_PCHI16 = 64;
public static final int R_MIPS_PCLO16 = 65;
/* These relocs are used for the mips16. */
public static final int R_MIPS16_26 = 100;
public static final int R_MIPS16_GPREL = 101;
public static final int R_MIPS16_GOT16 = 102;
public static final int R_MIPS16_CALL16 = 103;
public static final int R_MIPS16_HI16 = 104;
public static final int R_MIPS16_LO16 = 105;
public static final int R_MIPS16_TLS_GD = 106;
public static final int R_MIPS16_TLS_LDM = 107;
public static final int R_MIPS16_TLS_DTPREL_HI16 = 108;
public static final int R_MIPS16_TLS_DTPREL_LO16 = 109;
public static final int R_MIPS16_TLS_GOTTPREL = 110;
public static final int R_MIPS16_TLS_TPREL_HI16 = 111;
public static final int R_MIPS16_TLS_TPREL_LO16 = 112;
public static final int R_MIPS16_LO = 100; // First MIPS16 reloc type
public static final int R_MIPS16_HI = 112; // Last MIPS16 reloc type
/* These relocations are specific to VxWorks. */
public static final int R_MIPS_COPY = 126;
public static final int R_MIPS_JUMP_SLOT = 127;
/* These relocations are specific to the MicroMIPS */
public static final int R_MICROMIPS_26_S1 = 133;
public static final int R_MICROMIPS_HI16 = 134;
public static final int R_MICROMIPS_LO16 = 135;
public static final int R_MICROMIPS_GPREL16 = 136;
public static final int R_MICROMIPS_LITERAL = 137;
public static final int R_MICROMIPS_GOT16 = 138;
public static final int R_MICROMIPS_PC7_S1 = 139; // no shuffle required
public static final int R_MICROMIPS_PC10_S1 = 140; // no shuffle required
public static final int R_MICROMIPS_PC16_S1 = 141;
public static final int R_MICROMIPS_CALL16 = 142;
public static final int R_MICROMIPS_GOT_DISP = 145;
public static final int R_MICROMIPS_GOT_PAGE = 146;
public static final int R_MICROMIPS_GOT_OFST = 147;
public static final int R_MICROMIPS_GOT_HI16 = 148;
public static final int R_MICROMIPS_GOT_LO16 = 149;
public static final int R_MICROMIPS_SUB = 150;
public static final int R_MICROMIPS_HIGHER = 151;
public static final int R_MICROMIPS_HIGHEST = 152;
public static final int R_MICROMIPS_CALL_HI16 = 153;
public static final int R_MICROMIPS_CALL_LO16 = 154;
public static final int R_MICROMIPS_SCN_DISP = 155;
public static final int R_MICROMIPS_JALR = 156;
public static final int R_MICROMIPS_HI0_LO16 = 157;
/* TLS MicroMIPS related relocations */
public static final int R_MICROMIPS_TLS_GD = 162;
public static final int R_MICROMIPS_TLS_LDM = 163;
public static final int R_MICROMIPS_TLS_DTPREL_HI16 = 164;
public static final int R_MICROMIPS_TLS_DTPREL_LO16 = 165;
public static final int R_MICROMIPS_TLS_GOTTPREL = 166;
public static final int R_MICROMIPS_TLS_TPREL_HI16 = 169;
public static final int R_MICROMIPS_TLS_TPREL_LO16 = 170;
public static final int R_MICROMIPS_GPREL7_S2 = 172;
public static final int R_MICROMIPS_PC23_S2 = 173;
public static final int R_MICROMIPS_LO = 133; // First MicroMIPS reloc type
public static final int R_MICROMIPS_HI = 173; // Last MicroMIPS reloc type
public static final int R_MIPS_PC32 = 248;
// Masks for manipulating MIPS relocation targets
public static final int MIPS_LOW26 = 0x03FFFFFF;
public static final int MIPS_LOW21 = 0x001FFFFF;
private MIPS_ElfRelocationConstants() {
// no construct
}
}

View file

@ -23,19 +23,23 @@ import ghidra.app.util.bin.format.elf.extend.MIPS_ElfExtension;
import ghidra.app.util.bin.format.elf.relocation.MIPS_ElfRelocationHandler.MIPS_DeferredRelocation;
import ghidra.program.model.address.*;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.listing.BookmarkType;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.NotFoundException;
/**
* {@link MIPS_ElfRelocationContext} provides extended relocation context with the ability
* to retain deferred relocation lists. In addition, the ability to generate a section GOT
* table is provided to facilitate relocations encountered within object modules.
*/
class MIPS_ElfRelocationContext extends ElfRelocationContext {
class MIPS_ElfRelocationContext extends ElfRelocationContext<MIPS_ElfRelocationHandler> {
private LinkedList<MIPS_DeferredRelocation> hi16list = new LinkedList<>();
private LinkedList<MIPS_DeferredRelocation> got16list = new LinkedList<>();
@ -47,6 +51,7 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
private Map<Long, Address> gotMap;
boolean saveValueForNextReloc;
boolean useSavedAddend = false;
boolean savedAddendHasError = false;
long savedAddend;
@ -59,6 +64,81 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
super(handler, loadHelper, symbolMap);
}
@Override
protected RelocationResult processRelocation(ElfRelocation relocation, ElfSymbol elfSymbol,
Address relocationAddress) throws MemoryAccessException {
lastSymbolAddr = null;
lastElfSymbol = null;
int typeId = relocation.getType();
int symbolIndex = relocation.getSymbolIndex();
saveValueForNextReloc = nextRelocationHasSameOffset(relocation);
RelocationResult lastResult = RelocationResult.FAILURE;
if (getElfHeader().is64Bit()) {
MIPS_Elf64Relocation mips64Relocation = (MIPS_Elf64Relocation) relocation;
// Each relocation can pack upto 3 relocations for 64-bit
for (int n = 0; n < 3; n++) {
if (n == 1) {
symbolIndex = mips64Relocation.getSpecialSymbolIndex();
}
else {
symbolIndex = 0;
}
int relocType = typeId & 0xff;
typeId >>= 8;
int nextRelocType = (n < 2) ? (typeId & 0xff) : 0;
if (nextRelocType == MIPS_ElfRelocationType.R_MIPS_NONE.typeId) {
saveValueForNextReloc = false;
}
RelocationResult result =
doRelocate(mips64Relocation, relocationAddress, relocType, symbolIndex);
if (result.status() == Status.FAILURE || result.status() == Status.UNSUPPORTED) {
return result;
}
lastResult = result;
if (nextRelocType == MIPS_ElfRelocationType.R_MIPS_NONE.typeId) {
break;
}
}
return lastResult;
}
return doRelocate(relocation, relocationAddress, typeId, symbolIndex);
}
private RelocationResult doRelocate(ElfRelocation relocation, Address relocationAddress,
int relocType, int symbolIndex) throws MemoryAccessException {
if (relocType == 0) {
return RelocationResult.SKIPPED;
}
ElfSymbol elfSymbol = getSymbol(symbolIndex);
Address symbolAddr = getSymbolAddress(elfSymbol);
long symbolValue = getSymbolValue(elfSymbol);
String symbolName = elfSymbol != null ? elfSymbol.getNameAsString() : null;
MIPS_ElfRelocationType relocationType = handler.getRelocationType(relocType);
if (relocationType == null) {
handler.markAsUndefined(program, relocationAddress, relocType, symbolName, symbolIndex,
getLog());
return RelocationResult.UNSUPPORTED;
}
return handler.relocate(this, relocation, relocationType, relocationAddress,
getSymbol(symbolIndex), symbolAddr, symbolValue, symbolName);
}
@Override
public void endRelocationTableProcessing() {
@ -185,7 +265,7 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
return false;
}
return relocations[relocIndex].getOffset() == relocations[relocIndex + 1].getOffset() &&
relocations[relocIndex + 1].getType() != MIPS_ElfRelocationConstants.R_MIPS_NONE;
relocations[relocIndex + 1].getType() != MIPS_ElfRelocationType.R_MIPS_NONE.typeId;
}
/**
@ -226,8 +306,8 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
int size = (int) lastSectionGotEntryAddress.subtract(sectionGotAddress) + 1;
String blockName = getSectionGotName();
try {
MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false,
blockName, sectionGotAddress, size,
MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false, blockName,
sectionGotAddress, size,
"NOTE: This block is artificial and allows ELF Relocations to work correctly",
"Elf Loader", true, false, false, loadHelper.getLog());
DataConverter converter =
@ -260,7 +340,7 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
// TODO: this is a simplified use of GP and could be incorrect when multiple GPs exist
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program,
MIPS_ElfExtension.MIPS_GP_VALUE_SYMBOL, err -> getLog().error("MIPS_ELF", err));
MIPS_ElfExtension.MIPS_GP_VALUE_SYMBOL, err -> getLog().appendMsg("MIPS_ELF", err));
if (symbol == null) {
return -1;
}
@ -269,12 +349,11 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
/**
* Get the GP0 value (from .reginfo and generated symbol)
* @param mipsRelocationContext
* @return adjusted GP0 value or -1 if _mips_gp0_value symbol not defined.
*/
long getGP0Value() {
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program,
MIPS_ElfExtension.MIPS_GP0_VALUE_SYMBOL, err -> getLog().error("MIPS_ELF", err));
MIPS_ElfExtension.MIPS_GP0_VALUE_SYMBOL, err -> getLog().appendMsg("MIPS_ELF", err));
if (symbol == null) {
return -1;
}
@ -316,8 +395,8 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
}
/**
* Add HI16 relocation for deferred processing
* @param hi16reloc HI16 relocation
* Add GOT16 relocation for deferred processing
* @param got16reloc GOT16 relocation
*/
void addGOT16Relocation(MIPS_DeferredRelocation got16reloc) {
got16list.add(got16reloc);

View file

@ -0,0 +1,162 @@
/* ###
* 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 MIPS_ElfRelocationType implements ElfRelocationType {
R_MIPS_NONE(0),
R_MIPS_16(1),
R_MIPS_32(2), // In Elf 64: alias R_MIPS_ADD
R_MIPS_REL32(3), // In Elf 64: alias R_MIPS_REL
R_MIPS_26(4),
R_MIPS_HI16(5),
R_MIPS_LO16(6),
R_MIPS_GPREL16(7), // In Elf 64: alias R_MIPS_GPREL
R_MIPS_LITERAL(8),
R_MIPS_GOT16(9), // In Elf 64: alias R_MIPS_GOT
R_MIPS_PC16(10),
R_MIPS_CALL16(11), // In Elf 64: alias R_MIPS_CALL
R_MIPS_GPREL32(12),
/* The remaining relocs are defined on Irix(although they are not in the MIPS ELF ABI. */
R_MIPS_UNUSED1(13),
R_MIPS_UNUSED2(14),
R_MIPS_UNUSED3(15),
R_MIPS_SHIFT5(16),
R_MIPS_SHIFT6(17),
R_MIPS_64(18),
R_MIPS_GOT_DISP(19),
R_MIPS_GOT_PAGE(20),
R_MIPS_GOT_OFST(21),
R_MIPS_GOT_HI16(22),
R_MIPS_GOT_LO16(23),
R_MIPS_SUB(24),
R_MIPS_INSERT_A(25),
R_MIPS_INSERT_B(26),
R_MIPS_DELETE(27),
R_MIPS_HIGHER(28),
R_MIPS_HIGHEST(29),
R_MIPS_CALL_HI16(30),
R_MIPS_CALL_LO16(31),
R_MIPS_SCN_DISP(32),
R_MIPS_REL16(33),
R_MIPS_ADD_IMMEDIATE(34),
R_MIPS_PJUMP(35),
R_MIPS_RELGOT(36),
R_MIPS_JALR(37),
/* TLS relocations. */
R_MIPS_TLS_DTPMOD32(38),
R_MIPS_TLS_DTPREL32(39),
R_MIPS_TLS_DTPMOD64(40),
R_MIPS_TLS_DTPREL64(41),
R_MIPS_TLS_GD(42),
R_MIPS_TLS_LDM(43),
R_MIPS_TLS_DTPREL_HI16(44),
R_MIPS_TLS_DTPREL_LO16(45),
R_MIPS_TLS_GOTTPREL(46),
R_MIPS_TLS_TPREL32(47),
R_MIPS_TLS_TPREL64(48),
R_MIPS_TLS_TPREL_HI16(49),
R_MIPS_TLS_TPREL_LO16(50),
R_MIPS_GLOB_DAT(51),
/* MIPSr6 relocations */
R_MIPS_PC21_S2(60),
R_MIPS_PC26_S2(61),
R_MIPS_PC18_S3(62),
R_MIPS_PC19_S2(63),
R_MIPS_PCHI16(64),
R_MIPS_PCLO16(65),
/* These relocs are used for the mips16. */
R_MIPS16_26(100),
R_MIPS16_GPREL(101),
R_MIPS16_GOT16(102),
R_MIPS16_CALL16(103),
R_MIPS16_HI16(104),
R_MIPS16_LO16(105),
R_MIPS16_TLS_GD(106),
R_MIPS16_TLS_LDM(107),
R_MIPS16_TLS_DTPREL_HI16(108),
R_MIPS16_TLS_DTPREL_LO16(109),
R_MIPS16_TLS_GOTTPREL(110),
R_MIPS16_TLS_TPREL_HI16(111),
R_MIPS16_TLS_TPREL_LO16(112),
R_MIPS16_LO(100), // First MIPS16 reloc type
R_MIPS16_HI(112), // Last MIPS16 reloc type
/* These relocations are specific to VxWorks. */
R_MIPS_COPY(126),
R_MIPS_JUMP_SLOT(127),
/* These relocations are specific to the MicroMIPS */
R_MICROMIPS_26_S1(133),
R_MICROMIPS_HI16(134),
R_MICROMIPS_LO16(135),
R_MICROMIPS_GPREL16(136),
R_MICROMIPS_LITERAL(137),
R_MICROMIPS_GOT16(138),
R_MICROMIPS_PC7_S1(139), // no shuffle required
R_MICROMIPS_PC10_S1(140), // no shuffle required
R_MICROMIPS_PC16_S1(141),
R_MICROMIPS_CALL16(142),
R_MICROMIPS_GOT_DISP(145),
R_MICROMIPS_GOT_PAGE(146),
R_MICROMIPS_GOT_OFST(147),
R_MICROMIPS_GOT_HI16(148),
R_MICROMIPS_GOT_LO16(149),
R_MICROMIPS_SUB(150),
R_MICROMIPS_HIGHER(151),
R_MICROMIPS_HIGHEST(152),
R_MICROMIPS_CALL_HI16(153),
R_MICROMIPS_CALL_LO16(154),
R_MICROMIPS_SCN_DISP(155),
R_MICROMIPS_JALR(156),
R_MICROMIPS_HI0_LO16(157),
/* TLS MicroMIPS related relocations */
R_MICROMIPS_TLS_GD(162),
R_MICROMIPS_TLS_LDM(163),
R_MICROMIPS_TLS_DTPREL_HI16(164),
R_MICROMIPS_TLS_DTPREL_LO16(165),
R_MICROMIPS_TLS_GOTTPREL(166),
R_MICROMIPS_TLS_TPREL_HI16(169),
R_MICROMIPS_TLS_TPREL_LO16(170),
R_MICROMIPS_GPREL7_S2(172),
R_MICROMIPS_PC23_S2(173),
R_MICROMIPS_LO(133), // First MicroMIPS reloc type
R_MICROMIPS_HI(173), // Last MicroMIPS reloc type
R_MIPS_PC32(248);
public final int typeId;
private MIPS_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -22,13 +22,13 @@ import ghidra.app.util.bin.format.elf.ElfSymbol;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
class PIC30_ElfRelocationContext extends ElfRelocationContext {
protected PIC30_ElfRelocationContext(ElfRelocationHandler handler, ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
class PIC30_ElfRelocationContext extends ElfRelocationContext<PIC30_ElfRelocationHandler> {
protected PIC30_ElfRelocationContext(PIC30_ElfRelocationHandler handler,
ElfLoadHelper loadHelper, Map<ElfSymbol, Address> symbolMap) {
super(handler, loadHelper, symbolMap);
}
private boolean isDebugSection(AddressSpace overlaySpace) {
String name = overlaySpace.getName();
return name.startsWith(".debug_") || ".comment".equals(name);

View file

@ -23,81 +23,18 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.util.exception.NotFoundException;
import ghidra.program.model.reloc.RelocationResult;
public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
public class PIC30_ElfRelocationHandler
extends AbstractElfRelocationHandler<PIC30_ElfRelocationType, PIC30_ElfRelocationContext> {
/* PIC30 Relocation Types */
// Numbers found in ./include/elf/pic30.h:
public static final int R_PIC30_NONE = 0;
public static final int R_PIC30_8 = 1;
public static final int R_PIC30_16 = 2;
public static final int R_PIC30_32 = 3;
public static final int R_PIC30_FILE_REG_BYTE = 4;
public static final int R_PIC30_FILE_REG = 5;
public static final int R_PIC30_FILE_REG_WORD = 6;
public static final int R_PIC30_FILE_REG_WORD_WITH_DST = 7;
public static final int R_PIC30_WORD = 8;
public static final int R_PIC30_PBYTE = 9;
public static final int R_PIC30_PWORD = 10;
public static final int R_PIC30_HANDLE = 11;
public static final int R_PIC30_PADDR = 12;
public static final int R_PIC30_P_PADDR = 13;
public static final int R_PIC30_PSVOFFSET = 14;
public static final int R_PIC30_TBLOFFSET = 15;
public static final int R_PIC30_WORD_HANDLE = 16;
public static final int R_PIC30_WORD_PSVOFFSET = 17;
public static final int R_PIC30_PSVPAGE = 18;
public static final int R_PIC30_P_PSVPAGE = 19;
public static final int R_PIC30_WORD_PSVPAGE = 20;
public static final int R_PIC30_WORD_TBLOFFSET = 21;
public static final int R_PIC30_TBLPAGE = 22;
public static final int R_PIC30_P_TBLPAGE = 23;
public static final int R_PIC30_WORD_TBLPAGE = 24;
public static final int R_PIC30_P_HANDLE = 25;
public static final int R_PIC30_P_PSVOFFSET = 26;
public static final int R_PIC30_P_TBLOFFSET = 27;
public static final int R_PIC30_PCREL_BRANCH = 28;
public static final int R_PIC30_BRANCH_ABSOLUTE = 29;
public static final int R_PIC30_PCREL_DO = 30;
public static final int R_PIC30_DO_ABSOLUTE = 31;
public static final int R_PIC30_PGM_ADDR_LSB = 32;
public static final int R_PIC30_PGM_ADDR_MSB = 33;
public static final int R_PIC30_UNSIGNED_4 = 34;
public static final int R_PIC30_UNSIGNED_5 = 35;
public static final int R_PIC30_BIT_SELECT_3 = 36;
public static final int R_PIC30_BIT_SELECT_4_BYTE = 37;
public static final int R_PIC30_BIT_SELECT_4 = 38;
public static final int R_PIC30_DSP_6 = 39;
public static final int R_PIC30_DSP_PRESHIFT = 40;
public static final int R_PIC30_SIGNED_10_BYTE = 41;
public static final int R_PIC30_UNSIGNED_10 = 42;
public static final int R_PIC30_UNSIGNED_14 = 43;
public static final int R_PIC30_FRAME_SIZE = 44;
public static final int R_PIC30_PWRSAV_MODE = 45;
public static final int R_PIC30_DMAOFFSET = 46;
public static final int R_PIC30_P_DMAOFFSET = 47;
public static final int R_PIC30_WORD_DMAOFFSET = 48;
public static final int R_PIC30_PSVPTR = 49;
public static final int R_PIC30_P_PSVPTR = 50;
public static final int R_PIC30_L_PSVPTR = 51;
public static final int R_PIC30_WORD_PSVPTR = 52;
public static final int R_PIC30_CALL_ACCESS = 53;
public static final int R_PIC30_PCREL_ACCESS = 54;
public static final int R_PIC30_ACCESS = 55;
public static final int R_PIC30_P_ACCESS = 56;
public static final int R_PIC30_L_ACCESS = 57;
public static final int R_PIC30_WORD_ACCESS = 58;
public static final int R_PIC30_EDSPAGE = 59;
public static final int R_PIC30_P_EDSPAGE = 60;
public static final int R_PIC30_WORD_EDSPAGE = 61;
public static final int R_PIC30_EDSOFFSET = 62;
public static final int R_PIC30_P_EDSOFFSET = 63;
public static final int R_PIC30_WORD_EDSOFFSET = 64;
public static final int R_PIC30_UNSIGNED_8 = 65;
/**
* Constructor
*/
public PIC30_ElfRelocationHandler() {
super(PIC30_ElfRelocationType.class);
}
// cached state assumes new instance created for each import use
private Boolean isEDSVariant = null;
@ -112,8 +49,8 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
Map<ElfSymbol, Address> symbolMap) {
return new PIC30_ElfRelocationContext(this, loadHelper, symbolMap);
}
private boolean isEDSVariant(ElfRelocationContext elfRelocationContext) {
private boolean isEDSVariant(PIC30_ElfRelocationContext elfRelocationContext) {
if (isEDSVariant == null) {
// NOTE: non-EDS variants may improperly define DSRPAG
// in register space which should be corrected
@ -124,50 +61,37 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException {
int type = relocation.getType();
if (type == R_PIC30_NONE) {
return RelocationResult.SKIPPED;
}
protected RelocationResult relocate(PIC30_ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, PIC30_ElfRelocationType type, Address relocationAddress,
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int symbolIndex = relocation.getSymbolIndex();
int addend = (int) relocation.getAddend();
long relocWordOffset = (int) relocationAddress.getAddressableWordOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
int symbolValue = (int) elfRelocationContext.getSymbolValue(sym); // word offset
int oldValue = memory.getInt(relocationAddress);
short oldShortValue = memory.getShort(relocationAddress);
int newValue;
int byteLength = 2; // most relocations affect 2-bytes (change if different)
ElfHeader elf = elfRelocationContext.getElfHeader();
if (elf.e_machine() == ElfConstants.EM_DSPIC30F) {
switch (type) {
switch (type) {
case R_PIC30_16: // 2
case R_PIC30_FILE_REG_WORD: // 6
newValue = (symbolValue + addend + oldShortValue);
newValue = ((int) symbolValue + addend + oldShortValue);
memory.setShort(relocationAddress, (short) newValue);
break;
case R_PIC30_32: // 3
newValue = symbolValue + addend + oldValue;
newValue = (int) symbolValue + addend + oldValue;
memory.setInt(relocationAddress, newValue);
byteLength = 4;
break;
case R_PIC30_FILE_REG_BYTE: // 4 short
case R_PIC30_FILE_REG: // 5 short
int reloc = symbolValue;
int reloc = (int) symbolValue;
reloc += addend;
reloc += oldShortValue;
reloc &= 0x1fff;
@ -175,7 +99,7 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) newValue);
break;
case R_PIC30_FILE_REG_WORD_WITH_DST: // 7
reloc = symbolValue >> 1;
reloc = (int) symbolValue >> 1;
reloc += addend;
reloc += oldValue >> 4;
reloc &= 0x7fff;
@ -185,7 +109,7 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
break;
case R_PIC30_WORD: // 8
case R_PIC30_WORD_TBLOFFSET: // 0x15
reloc = symbolValue;
reloc = (int) symbolValue;
reloc += addend;
reloc += oldValue >> 4;
reloc &= 0xffff;
@ -194,7 +118,7 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 4;
break;
case R_PIC30_WORD_TBLPAGE: // 0x18
reloc = symbolValue >> 16;
reloc = (int) symbolValue >> 16;
reloc += addend;
reloc += oldValue >> 4;
reloc &= 0xffff;
@ -211,11 +135,9 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
default:
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
markAsUnhandled(program, relocationAddress, type, relocation.getSymbolIndex(),
symbolName, elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
}
return new RelocationResult(Status.APPLIED, byteLength);
}

View file

@ -0,0 +1,97 @@
/* ###
* 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 PIC30_ElfRelocationType implements ElfRelocationType {
R_PIC30_NONE(0),
R_PIC30_8(1),
R_PIC30_16(2),
R_PIC30_32(3),
R_PIC30_FILE_REG_BYTE(4),
R_PIC30_FILE_REG(5),
R_PIC30_FILE_REG_WORD(6),
R_PIC30_FILE_REG_WORD_WITH_DST(7),
R_PIC30_WORD(8),
R_PIC30_PBYTE(9),
R_PIC30_PWORD(10),
R_PIC30_HANDLE(11),
R_PIC30_PADDR(12),
R_PIC30_P_PADDR(13),
R_PIC30_PSVOFFSET(14),
R_PIC30_TBLOFFSET(15),
R_PIC30_WORD_HANDLE(16),
R_PIC30_WORD_PSVOFFSET(17),
R_PIC30_PSVPAGE(18),
R_PIC30_P_PSVPAGE(19),
R_PIC30_WORD_PSVPAGE(20),
R_PIC30_WORD_TBLOFFSET(21),
R_PIC30_TBLPAGE(22),
R_PIC30_P_TBLPAGE(23),
R_PIC30_WORD_TBLPAGE(24),
R_PIC30_P_HANDLE(25),
R_PIC30_P_PSVOFFSET(26),
R_PIC30_P_TBLOFFSET(27),
R_PIC30_PCREL_BRANCH(28),
R_PIC30_BRANCH_ABSOLUTE(29),
R_PIC30_PCREL_DO(30),
R_PIC30_DO_ABSOLUTE(31),
R_PIC30_PGM_ADDR_LSB(32),
R_PIC30_PGM_ADDR_MSB(33),
R_PIC30_UNSIGNED_4(34),
R_PIC30_UNSIGNED_5(35),
R_PIC30_BIT_SELECT_3(36),
R_PIC30_BIT_SELECT_4_BYTE(37),
R_PIC30_BIT_SELECT_4(38),
R_PIC30_DSP_6(39),
R_PIC30_DSP_PRESHIFT(40),
R_PIC30_SIGNED_10_BYTE(41),
R_PIC30_UNSIGNED_10(42),
R_PIC30_UNSIGNED_14(43),
R_PIC30_FRAME_SIZE(44),
R_PIC30_PWRSAV_MODE(45),
R_PIC30_DMAOFFSET(46),
R_PIC30_P_DMAOFFSET(47),
R_PIC30_WORD_DMAOFFSET(48),
R_PIC30_PSVPTR(49),
R_PIC30_P_PSVPTR(50),
R_PIC30_L_PSVPTR(51),
R_PIC30_WORD_PSVPTR(52),
R_PIC30_CALL_ACCESS(53),
R_PIC30_PCREL_ACCESS(54),
R_PIC30_ACCESS(55),
R_PIC30_P_ACCESS(56),
R_PIC30_L_ACCESS(57),
R_PIC30_WORD_ACCESS(58),
R_PIC30_EDSPAGE(59),
R_PIC30_P_EDSPAGE(60),
R_PIC30_WORD_EDSPAGE(61),
R_PIC30_EDSOFFSET(62),
R_PIC30_P_EDSOFFSET(63),
R_PIC30_WORD_EDSOFFSET(64),
R_PIC30_UNSIGNED_8(65);
public final int typeId;
private PIC30_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

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

View file

@ -1,84 +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 RISCV_ElfRelocationConstants {
/*
* A Addend field in the relocation entry associated with the symbol
* B Base address of a shared object loaded into memory
* G Offset of the symbol into the GOT (Global Offset Table)
* S Value of the symbol in the symbol table
* GP Global Pointer register (x3)
*/
public static final int R_RISCV_NONE = 0; // None
public static final int R_RISCV_32 = 1; // Runtime relocation word32 = S + A
public static final int R_RISCV_64 = 2; // Runtime relocation word64 = S + A
public static final int R_RISCV_RELATIVE = 3; // Runtime relocation word32,64 = B + A
public static final int R_RISCV_COPY = 4; // Runtime relocation must be in executable. not allowed in shared library
public static final int R_RISCV_JUMP_SLOT = 5; // Runtime relocation word32,64 = S ;handled by PLT unless LD_BIND_NOW
public static final int R_RISCV_TLS_DTPMOD32 = 6; // TLS relocation word32 = S->TLSINDEX
public static final int R_RISCV_TLS_DTPMOD64 = 7; // TLS relocation word64 = S->TLSINDEX
public static final int R_RISCV_TLS_DTPREL32 = 8; // TLS relocation word32 = TLS + S + A - TLS_TP_OFFSET
public static final int R_RISCV_TLS_DTPREL64 = 9; // TLS relocation word64 = TLS + S + A - TLS_TP_OFFSET
public static final int R_RISCV_TLS_TPREL32 = 10; // TLS relocation word32 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
public static final int R_RISCV_TLS_TPREL64 = 11; // TLS relocation word64 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
public static final int R_RISCV_BRANCH = 16; // PC-relative branch (SB-Type)
public static final int R_RISCV_JAL = 17; // PC-relative jump (UJ-Type)
public static final int R_RISCV_CALL = 18; // PC-relative call MACRO call,tail (auipc+jalr pair)
public static final int R_RISCV_CALL_PLT = 19; // PC-relative call (PLT) MACRO call,tail (auipc+jalr pair) PIC
public static final int R_RISCV_GOT_HI20 = 20; // PC-relative GOT reference MACRO la
public static final int R_RISCV_TLS_GOT_HI20 = 21; // PC-relative TLS IE GOT offset MACRO la.tls.ie
public static final int R_RISCV_TLS_GD_HI20 = 22; // PC-relative TLS GD reference MACRO la.tls.gd
public static final int R_RISCV_PCREL_HI20 = 23; // PC-relative reference %pcrel_hi(symbol) (U-Type)
public static final int R_RISCV_PCREL_LO12_I = 24; // PC-relative reference %pcrel_lo(symbol) (I-Type)
public static final int R_RISCV_PCREL_LO12_S = 25; // PC-relative reference %pcrel_lo(symbol) (S-Type)
public static final int R_RISCV_HI20 = 26; // Absolute address %hi(symbol) (U-Type)
public static final int R_RISCV_LO12_I = 27; // Absolute address %lo(symbol) (I-Type)
public static final int R_RISCV_LO12_S = 28; // Absolute address %lo(symbol) (S-Type)
public static final int R_RISCV_TPREL_HI20 = 29; // TLS LE thread offset %tprel_hi(symbol) (U-Type)
public static final int R_RISCV_TPREL_LO12_I = 30; // TLS LE thread offset %tprel_lo(symbol) (I-Type)
public static final int R_RISCV_TPREL_LO12_S = 31; // TLS LE thread offset %tprel_lo(symbol) (S-Type)
public static final int R_RISCV_TPREL_ADD = 32; // TLS LE thread usage %tprel_add(symbol)
public static final int R_RISCV_ADD8 = 33; // 8-bit label addition word8 = old + S + A
public static final int R_RISCV_ADD16 = 34; // 16-bit label addition word16 = old + S + A
public static final int R_RISCV_ADD32 = 35; // 32-bit label addition word32 = old + S + A
public static final int R_RISCV_ADD64 = 36; // 64-bit label addition word64 = old + S + A
public static final int R_RISCV_SUB8 = 37; // 8-bit label subtraction word8 = old - S - A
public static final int R_RISCV_SUB16 = 38; // 16-bit label subtraction word16 = old - S - A
public static final int R_RISCV_SUB32 = 39; // 32-bit label subtraction word32 = old - S - A
public static final int R_RISCV_SUB64 = 40; // 64-bit label subtraction word64 = old - S - A
public static final int R_RISCV_GNU_VTINHERIT = 41; // GNU C++ vtable hierarchy
public static final int R_RISCV_GNU_VTENTRY = 42; // GNU C++ vtable member usage
public static final int R_RISCV_ALIGN = 43; // Alignment statement
public static final int R_RISCV_RVC_BRANCH = 44; // PC-relative branch offset (CB-Type)
public static final int R_RISCV_RVC_JUMP = 45; // PC-relative jump offset (CJ-Type)
public static final int R_RISCV_RVC_LUI = 46; // Absolute address (CI-Type)
public static final int R_RISCV_GPREL_I = 47; // GP-relative reference (I-Type)
public static final int R_RISCV_GPREL_S = 48; // GP-relative reference (S-Type)
public static final int R_RISCV_TPREL_I = 49; // TP-relative TLS LE load (I-Type)
public static final int R_RISCV_TPREL_S = 50; // TP-relative TLS LE store (S-Type)
public static final int R_RISCV_RELAX = 51; // Instruction pair can be relaxed
public static final int R_RISCV_SUB6 = 52; // Local label subtraction
public static final int R_RISCV_SET6 = 53; // Local label subtraction
public static final int R_RISCV_SET8 = 54; // Local label subtraction
public static final int R_RISCV_SET16 = 55; // Local label subtraction
public static final int R_RISCV_SET32 = 56; // Local label subtraction
public static final int R_RISCV_32_PCREL = 57; // 32-bit PC relative
// 58-191 Reserved Reserved for future standard use
// 192-255 Reserved Reserved for nonstandard ABI extensions
}

View file

@ -20,10 +20,10 @@ import java.util.*;
import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address;
class RISCV_ElfRelocationContext extends ElfRelocationContext {
class RISCV_ElfRelocationContext extends ElfRelocationContext<RISCV_ElfRelocationHandler> {
protected RISCV_ElfRelocationContext(ElfRelocationHandler handler, ElfLoadHelper loadHelper,
Map<ElfSymbol, Address> symbolMap) {
protected RISCV_ElfRelocationContext(RISCV_ElfRelocationHandler handler,
ElfLoadHelper loadHelper, Map<ElfSymbol, Address> symbolMap) {
super(handler, loadHelper, symbolMap);
}
@ -72,9 +72,9 @@ class RISCV_ElfRelocationContext extends ElfRelocationContext {
}
// look for hi20 relocation
while (relIndex < relocations.length && relocations[relIndex].getOffset() == symValue) {
int type = relocations[relIndex].getType();
if ((type == RISCV_ElfRelocationConstants.R_RISCV_PCREL_HI20) ||
(type == RISCV_ElfRelocationConstants.R_RISCV_GOT_HI20)) {
int typeId = relocations[relIndex].getType();
if ((typeId == RISCV_ElfRelocationType.R_RISCV_PCREL_HI20.typeId) ||
(typeId == RISCV_ElfRelocationType.R_RISCV_GOT_HI20.typeId)) {
return relocations[relIndex];
}
++relIndex;

View file

@ -24,14 +24,16 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
/**
* See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc for information on the different riscv elf
* relocation types. Different relocation types are found in different contexts - not all of which are currently handled here.
* See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc for
* information on the different RISCV ELF relocation types. Different relocation types are found
* in different contexts - not all of which are currently handled here.
*
* The contexts we *attempt* to handle include:
*
* 1. fully linked Elf executables like the Linux `cp` utility which rely on dynamic linking to libraries like libc.so.6
* 1. fully linked Elf executables like the Linux `cp` utility which rely on dynamic linking to
* libraries like libc.so.6
* 2. object files compiled with or without Position Independent code (`-fpic`) support
* 3. Sharable object libraries like `libc.so.6`
* 3. kernel load modules compiled with position independent code (`-fpic`) support
@ -39,13 +41,24 @@ import ghidra.util.exception.NotFoundException;
* Keep in mind:
*
* 1. You may find multiple relocations at any single address.
* 2. Many relocations and relocation variants are there to support linker/loader optimizations unneeded by Ghidra.
* 3. Some relocations can only name their target indirectly. R_RISCV_PCREL_LO12_I references a R_RISCV_PCREL_HI20 relocation,
* but needs the symbol referenced by that R_RISCV_PCREL_HI20 in order to compute a PC relative offset.
* 4. Many discrete symbols can share the same symbol name, e.g. `.L0`. These symbol names can include non-printing characters like `".L0^B2"`
* 2. Many relocations and relocation variants are there to support linker/loader optimizations
* unneeded by Ghidra.
* 3. Some relocations can only name their target indirectly. R_RISCV_PCREL_LO12_I references
* a R_RISCV_PCREL_HI20 relocation, but needs the symbol referenced by that R_RISCV_PCREL_HI20
* in order to compute a PC relative offset.
* 4. Many discrete symbols can share the same symbol name, e.g. `.L0`. These symbol names can
* include non-printing characters like `".L0^B2"`
*
*/
public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
public class RISCV_ElfRelocationHandler
extends AbstractElfRelocationHandler<RISCV_ElfRelocationType, RISCV_ElfRelocationContext> {
/**
* Constructor
*/
public RISCV_ElfRelocationHandler() {
super(RISCV_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -94,11 +107,10 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
* actual address offet within the target program.
* @return the 32-bit HI20 relative offset value or 0 if HI20 relocation not found
*/
private static int getSymbolValueIndirect(ElfRelocationContext elfRelocationContext,
private static int getSymbolValueIndirect(RISCV_ElfRelocationContext elfRelocationContext,
ElfSymbol hi20Symbol, long relocAddrOffsetAdj) {
RISCV_ElfRelocationContext relocContext = (RISCV_ElfRelocationContext) elfRelocationContext;
ElfRelocation hi20Reloc = relocContext.getHi20Relocation(hi20Symbol);
ElfRelocation hi20Reloc = elfRelocationContext.getHi20Relocation(hi20Symbol);
if (hi20Reloc == null) {
return 0;
}
@ -118,36 +130,25 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (!canRelocate(elf)) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(RISCV_ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, RISCV_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
if (!relocation.hasAddend()) {
// Implementation only supports Elf_Rela relocations for RISCV
return RelocationResult.UNSUPPORTED;
}
ElfHeader elf = elfRelocationContext.getElfHeader();
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
boolean is32 = elf.is32Bit();
int type = relocation.getType();
if (RISCV_ElfRelocationConstants.R_RISCV_NONE == type) {
return RelocationResult.SKIPPED;
}
long addend = relocation.getAddend();
long offset = relocationAddress.getOffset();
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long value64 = 0;
int value32 = 0;
@ -158,7 +159,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case RISCV_ElfRelocationConstants.R_RISCV_32:
case R_RISCV_32:
// Runtime relocation word32 = S + A
value32 = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value32);
@ -171,7 +172,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case RISCV_ElfRelocationConstants.R_RISCV_64:
case R_RISCV_64:
// Runtime relocation word64 = S + A
value64 = symbolValue + addend;
memory.setLong(relocationAddress, value64);
@ -185,9 +186,9 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case RISCV_ElfRelocationConstants.R_RISCV_RELATIVE:
case R_RISCV_RELATIVE:
// Runtime relocation word32,64 = B + A
if (is32) {
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
@ -198,15 +199,15 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case RISCV_ElfRelocationConstants.R_RISCV_COPY:
case R_RISCV_COPY:
// Runtime relocation must be in executable. not allowed in shared library
markAsWarning(program, relocationAddress, "R_RISCV_COPY", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_JUMP_SLOT:
case R_RISCV_JUMP_SLOT:
// Runtime relocation word32,64 = S ;handled by PLT unless LD_BIND_NOW
if (is32) {
if (elf.is32Bit()) {
value32 = (int) (symbolValue);
memory.setInt(relocationAddress, value32);
}
@ -217,43 +218,19 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
}
break;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_DTPMOD32:
// TLS relocation word32 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_RISCV_TLS_DTPMOD32", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// case R_RISCV_TLS_DTPMOD32: // TLS relocation word32 = S->TLSINDEX
//
// case R_RISCV_TLS_DTPMOD64: // TLS relocation word64 = S->TLSINDEX
//
// case R_RISCV_TLS_DTPREL32: // TLS relocation word32 = TLS + S + A - TLS_TP_OFFSET
//
// case R_RISCV_TLS_DTPREL64: // TLS relocation word64 = TLS + S + A - TLS_TP_OFFSET
//
// case R_RISCV_TLS_TPREL32: // TLS relocation word32 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
//
// case R_RISCV_TLS_TPREL64: // TLS relocation word64 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
case RISCV_ElfRelocationConstants.R_RISCV_TLS_DTPMOD64:
// TLS relocation word64 = S->TLSINDEX
markAsWarning(program, relocationAddress, "R_RISCV_TLS_DTPMOD64", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_DTPREL32:
// TLS relocation word32 = TLS + S + A - TLS_TP_OFFSET
markAsWarning(program, relocationAddress, "R_RISCV_TLS_DTPREL32", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_DTPREL64:
// TLS relocation word64 = TLS + S + A - TLS_TP_OFFSET
markAsWarning(program, relocationAddress, "R_RISCV_TLS_DTPREL64", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_TPREL32:
// TLS relocation word32 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
markAsWarning(program, relocationAddress, "R_RISCV_TLS_TPREL32", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_TPREL64:
// TLS relocation word64 = TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
markAsWarning(program, relocationAddress, "R_RISCV_TLS_TPREL64", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_BRANCH:
case R_RISCV_BRANCH:
// PC-relative branch (SB-Type)
target = (int) (addend + symbolValue - offset);
value32 = encodeSBTypeImm(target) |
@ -261,7 +238,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_JAL:
case R_RISCV_JAL:
// PC-relative jump (UJ-Type)
target = (int) (addend + symbolValue - offset);
value32 = encodeUJTypeImm(target) |
@ -269,11 +246,11 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_CALL:
case R_RISCV_CALL:
// PC-relative call (PLT) MACRO call,tail (auipc+jalr pair) PIC
// Identical processing in Ghidra as the following
case RISCV_ElfRelocationConstants.R_RISCV_CALL_PLT:
case R_RISCV_CALL_PLT:
// PC-relative call MACRO call,tail (auipc+jalr pair)
target = (int) (addend + symbolValue - offset);
memory.setInt(relocationAddress,
@ -283,35 +260,26 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 8;
break;
case RISCV_ElfRelocationConstants.R_RISCV_TLS_GOT_HI20:
// PC-relative TLS IE GOT offset MACRO la.tls.ie
markAsWarning(program, relocationAddress, "R_RISCV_TLS_GOT_HI20", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// case R_RISCV_TLS_GOT_HI20: // PC-relative TLS IE GOT offset MACRO la.tls.ie
//
// case R_RISCV_TLS_GD_HI20: // PC-relative TLS GD reference MACRO la.tls.gd
case RISCV_ElfRelocationConstants.R_RISCV_TLS_GD_HI20:
// PC-relative TLS GD reference MACRO la.tls.gd
markAsWarning(program, relocationAddress, "R_RISCV_TLS_GD_HI20", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_GOT_HI20:
case R_RISCV_GOT_HI20:
// PC-relative GOT reference MACRO la
case RISCV_ElfRelocationConstants.R_RISCV_PCREL_HI20:
case R_RISCV_PCREL_HI20:
// PC-relative, not tested on 32 bit objects
target = (int) (addend + symbolValue - offset);
memory.setInt(relocationAddress,
getHi20(target) | (memory.getInt(relocationAddress) & 0xfff));
break;
case RISCV_ElfRelocationConstants.R_RISCV_PCREL_LO12_I:
case R_RISCV_PCREL_LO12_I:
// PC-relative reference %pcrel_lo(symbol) (I-Type), relative to the cited pc_rel_hi20
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName,
"Failed to locate HI20 relocation for R_RISCV_PCREL_LO12_I",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 =
@ -319,16 +287,15 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_PCREL_LO12_S:
case R_RISCV_PCREL_LO12_S:
// PC-relative reference %pcrel_lo(symbol) (S-Type)
// S-type immediates split the 12 bit value into separate 7 bit and 5 bit fields.
// Warning: untested!
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName,
"Failed to locate HI20 relocation for R_RISCV_PCREL_LO12_S",
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 = ((target & 0x000007f) << 25) | (target & 0x00000f80) |
@ -336,21 +303,21 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_HI20:
case R_RISCV_HI20:
// Absolute address %hi(symbol) (U-Type)
value32 = (int) ((symbolValue + 0x800) & 0xfffff000) |
(memory.getInt(relocationAddress) & 0xfff);
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_LO12_I:
case R_RISCV_LO12_I:
// Absolute address %lo(symbol) (I-Type)
value32 = ((int) (symbolValue & 0x00000fff) << 20) |
(memory.getInt(relocationAddress) & 0xfffff);
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_LO12_S:
case R_RISCV_LO12_S:
// Absolute address %lo(symbol) (S-Type)
value32 = (int) (symbolValue & 0x00000fff);
value32 = ((value32 & 0x1f) << 7) | ((value32 & 0xfe0) << 20) |
@ -358,31 +325,15 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_HI20:
// TLS LE thread offset %tprel_hi(symbol) (U-Type)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_HI20", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// case R_RISCV_TPREL_HI20: // TLS LE thread offset %tprel_hi(symbol) (U-Type)
//
// case R_RISCV_TPREL_LO12_I: // TLS LE thread offset %tprel_lo(symbol) (I-Type)
//
// case R_RISCV_TPREL_LO12_S: // TLS LE thread offset %tprel_lo(symbol) (S-Type)
//
// case R_RISCV_TPREL_ADD: // TLS LE thread usage %tprel_add(symbol)
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_LO12_I:
// TLS LE thread offset %tprel_lo(symbol) (I-Type)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_LO12_I", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_LO12_S:
// TLS LE thread offset %tprel_lo(symbol) (S-Type)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_LO12_S", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_ADD:
// TLS LE thread usage %tprel_add(symbol)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_ADD", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_ADD8:
case R_RISCV_ADD8:
// 8-bit label addition word8 = old + S + A
value8 = memory.getByte(relocationAddress);
value8 += (byte) (symbolValue + addend);
@ -390,7 +341,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case RISCV_ElfRelocationConstants.R_RISCV_ADD16:
case R_RISCV_ADD16:
// 16-bit label addition word16 = old + S + A
value16 = memory.getShort(relocationAddress);
value16 += (short) (symbolValue + addend);
@ -398,14 +349,14 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 2;
break;
case RISCV_ElfRelocationConstants.R_RISCV_ADD32:
case R_RISCV_ADD32:
// 32-bit label addition word32 = old + S + A
value32 = memory.getInt(relocationAddress);
value32 += (int) (symbolValue + addend);
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_ADD64:
case R_RISCV_ADD64:
// 64-bit label addition word64 = old + S + A
value64 = memory.getLong(relocationAddress);
value64 += (symbolValue + addend);
@ -413,7 +364,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 8;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SUB8:
case R_RISCV_SUB8:
// 8-bit label subtraction word8 = old - S - A
value8 = memory.getByte(relocationAddress);
value8 -= (byte) (symbolValue + addend);
@ -421,7 +372,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SUB16:
case R_RISCV_SUB16:
// 16-bit label subtraction word16 = old - S - A
value16 = memory.getShort(relocationAddress);
value16 -= (short) (symbolValue + addend);
@ -429,14 +380,14 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 2;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SUB32:
case R_RISCV_SUB32:
// 32-bit label subtraction word32 = old - S - A
value32 = memory.getInt(relocationAddress);
value32 -= (int) (symbolValue + addend);
memory.setInt(relocationAddress, value32);
break;
case RISCV_ElfRelocationConstants.R_RISCV_SUB64:
case R_RISCV_SUB64:
// 64-bit label subtraction word64 = old - S - A
value64 = memory.getLong(relocationAddress);
value64 -= (symbolValue + addend);
@ -444,25 +395,13 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 8;
break;
case RISCV_ElfRelocationConstants.R_RISCV_GNU_VTINHERIT:
// GNU C++ vtable hierarchy
markAsWarning(program, relocationAddress, "R_RISCV_GNU_VTINHERIT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// case R_RISCV_GNU_VTINHERIT: // GNU C++ vtable hierarchy
//
// case R_RISCV_GNU_VTENTRY: // GNU C++ vtable member usage
//
// case R_RISCV_ALIGN: // Alignment statement
case RISCV_ElfRelocationConstants.R_RISCV_GNU_VTENTRY:
// GNU C++ vtable member usage
markAsWarning(program, relocationAddress, "R_RISCV_GNU_VTENTRY", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_ALIGN:
// Alignment statement
markAsWarning(program, relocationAddress, "R_RISCV_ALIGN", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_RVC_BRANCH: {
case R_RISCV_RVC_BRANCH: {
// PC-relative branch offset (CB-Type)
short target_s = (short) (addend + symbolValue - offset);
value16 = (short) (encodeCBTypeImm(target_s) |
@ -472,7 +411,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case RISCV_ElfRelocationConstants.R_RISCV_RVC_JUMP: {
case R_RISCV_RVC_JUMP: {
// PC-relative jump offset (CJ-Type)
short target_s = (short) (addend + symbolValue - offset);
value16 = (short) (encodeCJTypeImm(target_s) |
@ -482,41 +421,21 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
break;
}
case RISCV_ElfRelocationConstants.R_RISCV_RVC_LUI:
// Absolute address (CI-Type)
markAsWarning(program, relocationAddress, "R_RISCV_RVC_LUI", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// case R_RISCV_RVC_LUI: // Absolute address (CI-Type)
//
// case R_RISCV_GPREL_I: // GP-relative reference (I-Type)
//
// case R_RISCV_GPREL_S: // GP-relative reference (S-Type)
//
// case R_RISCV_TPREL_I: // TP-relative TLS LE load (I-Type)
//
// case R_RISCV_TPREL_S: // TP-relative TLS LE store (S-Type)
case RISCV_ElfRelocationConstants.R_RISCV_GPREL_I:
// GP-relative reference (I-Type)
markAsWarning(program, relocationAddress, "R_RISCV_GPREL_I", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_GPREL_S:
// GP-relative reference (S-Type)
markAsWarning(program, relocationAddress, "R_RISCV_GPREL_S", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_I:
// TP-relative TLS LE load (I-Type)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_I", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_S:
// TP-relative TLS LE store (S-Type)
markAsWarning(program, relocationAddress, "R_RISCV_TPREL_S", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case RISCV_ElfRelocationConstants.R_RISCV_RELAX:
case R_RISCV_RELAX:
// Instruction pair can be relaxed by the linker/loader- ignore
return RelocationResult.SKIPPED;
case RISCV_ElfRelocationConstants.R_RISCV_SUB6:
case R_RISCV_SUB6:
int loc8 = memory.getByte(relocationAddress);
value8 = (byte) (symbolValue + addend);
value8 = (byte) ((loc8 & 0xc0) | (((loc8 & 0x3f) - value8) & 0x3f));
@ -524,7 +443,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SET6:
case R_RISCV_SET6:
loc8 = memory.getByte(relocationAddress);
value8 = (byte) (symbolValue + addend);
value8 = (byte) ((loc8 & 0xc0) | (value8 & 0x3f));
@ -532,20 +451,20 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 1;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SET8:
case R_RISCV_SET8:
value8 = (byte) (symbolValue + addend);
memory.setByte(relocationAddress, value8);
byteLength = 1;
break;
case RISCV_ElfRelocationConstants.R_RISCV_SET16:
case R_RISCV_SET16:
value16 = (short) (symbolValue + addend);
memory.setShort(relocationAddress, value8);
byteLength = 2;
break;
case RISCV_ElfRelocationConstants.R_RISCV_32_PCREL:
case RISCV_ElfRelocationConstants.R_RISCV_SET32:
case R_RISCV_32_PCREL:
case R_RISCV_SET32:
value32 = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value8);
break;

View file

@ -0,0 +1,94 @@
/* ###
* 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 RISCV_ElfRelocationType implements ElfRelocationType {
/*
* A Addend field in the relocation entry associated with the symbol
* B Base address of a shared object loaded into memory
* G Offset of the symbol into the GOT (Global Offset Table)
* S Value of the symbol in the symbol table
* GP Global Pointer register (x3)
*/
R_RISCV_NONE(0), // None
R_RISCV_32(1), // Runtime relocation word32(S + A
R_RISCV_64(2), // Runtime relocation word64(S + A
R_RISCV_RELATIVE(3), // Runtime relocation word32,64(B + A
R_RISCV_COPY(4), // Runtime relocation must be in executable. not allowed in shared library
R_RISCV_JUMP_SLOT(5), // Runtime relocation word32,64(S ),handled by PLT unless LD_BIND_NOW
R_RISCV_TLS_DTPMOD32(6), // TLS relocation word32(S->TLSINDEX
R_RISCV_TLS_DTPMOD64(7), // TLS relocation word64(S->TLSINDEX
R_RISCV_TLS_DTPREL32(8), // TLS relocation word32(TLS + S + A - TLS_TP_OFFSET
R_RISCV_TLS_DTPREL64(9), // TLS relocation word64(TLS + S + A - TLS_TP_OFFSET
R_RISCV_TLS_TPREL32(10), // TLS relocation word32(TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
R_RISCV_TLS_TPREL64(11), // TLS relocation word64(TLS + S + A + S_TLS_OFFSET - TLS_DTV_OFFSET
R_RISCV_BRANCH(16), // PC-relative branch (SB-Type)
R_RISCV_JAL(17), // PC-relative jump (UJ-Type)
R_RISCV_CALL(18), // PC-relative call MACRO call,tail (auipc+jalr pair)
R_RISCV_CALL_PLT(19), // PC-relative call (PLT) MACRO call,tail (auipc+jalr pair) PIC
R_RISCV_GOT_HI20(20), // PC-relative GOT reference MACRO la
R_RISCV_TLS_GOT_HI20(21), // PC-relative TLS IE GOT offset MACRO la.tls.ie
R_RISCV_TLS_GD_HI20(22), // PC-relative TLS GD reference MACRO la.tls.gd
R_RISCV_PCREL_HI20(23), // PC-relative reference %pcrel_hi(symbol) (U-Type)
R_RISCV_PCREL_LO12_I(24), // PC-relative reference %pcrel_lo(symbol) (I-Type)
R_RISCV_PCREL_LO12_S(25), // PC-relative reference %pcrel_lo(symbol) (S-Type)
R_RISCV_HI20(26), // Absolute address %hi(symbol) (U-Type)
R_RISCV_LO12_I(27), // Absolute address %lo(symbol) (I-Type)
R_RISCV_LO12_S(28), // Absolute address %lo(symbol) (S-Type)
R_RISCV_TPREL_HI20(29), // TLS LE thread offset %tprel_hi(symbol) (U-Type)
R_RISCV_TPREL_LO12_I(30), // TLS LE thread offset %tprel_lo(symbol) (I-Type)
R_RISCV_TPREL_LO12_S(31), // TLS LE thread offset %tprel_lo(symbol) (S-Type)
R_RISCV_TPREL_ADD(32), // TLS LE thread usage %tprel_add(symbol)
R_RISCV_ADD8(33), // 8-bit label addition word8(old + S + A
R_RISCV_ADD16(34), // 16-bit label addition word16(old + S + A
R_RISCV_ADD32(35), // 32-bit label addition word32(old + S + A
R_RISCV_ADD64(36), // 64-bit label addition word64(old + S + A
R_RISCV_SUB8(37), // 8-bit label subtraction word8(old - S - A
R_RISCV_SUB16(38), // 16-bit label subtraction word16(old - S - A
R_RISCV_SUB32(39), // 32-bit label subtraction word32(old - S - A
R_RISCV_SUB64(40), // 64-bit label subtraction word64(old - S - A
R_RISCV_GNU_VTINHERIT(41), // GNU C++ vtable hierarchy
R_RISCV_GNU_VTENTRY(42), // GNU C++ vtable member usage
R_RISCV_ALIGN(43), // Alignment statement
R_RISCV_RVC_BRANCH(44), // PC-relative branch offset (CB-Type)
R_RISCV_RVC_JUMP(45), // PC-relative jump offset (CJ-Type)
R_RISCV_RVC_LUI(46), // Absolute address (CI-Type)
R_RISCV_GPREL_I(47), // GP-relative reference (I-Type)
R_RISCV_GPREL_S(48), // GP-relative reference (S-Type)
R_RISCV_TPREL_I(49), // TP-relative TLS LE load (I-Type)
R_RISCV_TPREL_S(50), // TP-relative TLS LE store (S-Type)
R_RISCV_RELAX(51), // Instruction pair can be relaxed
R_RISCV_SUB6(52), // Local label subtraction
R_RISCV_SET6(53), // Local label subtraction
R_RISCV_SET8(54), // Local label subtraction
R_RISCV_SET16(55), // Local label subtraction
R_RISCV_SET32(56), // Local label subtraction
R_RISCV_32_PCREL(57); // 32-bit PC relative
// 58-191 Reserved Reserved for future standard use
// 192-255 Reserved Reserved for nonstandard ABI extensions
public final int typeId;
private RISCV_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,62 +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 SPARC_ElfRelocationConstants {
public static final int R_SPARC_NONE = 0; // No calculation
public static final int R_SPARC_5 = 44; // S + A
public static final int R_SPARC_6 = 45; // S + A
public static final int R_SPARC_7 = 43; // S + A
public static final int R_SPARC_8 = 1; // S + A
public static final int R_SPARC_10 = 30; // S + A
public static final int R_SPARC_11 = 31; // S + A
public static final int R_SPARC_13 = 11; // S + A
public static final int R_SPARC_16 = 2; // S + A
public static final int R_SPARC_22 = 10; // S + A
public static final int R_SPARC_32 = 3; // S + A
public static final int R_SPARC_LO10 = 12; // (S + A) & 0x3FF
public static final int R_SPARC_HI22 = 9; // (S + A) >> 10
public static final int R_SPARC_DISP8 = 4; // S + A - P
public static final int R_SPARC_DISP16 = 5; // S + A - P
public static final int R_SPARC_DISP32 = 6; // S + A - P
public static final int R_SPARC_WDISP16 = 40; // (S + A - P) >> 2
public static final int R_SPARC_WDISP19 = 41; // (S + A - P) >> 2
public static final int R_SPARC_WDISP22 = 8; // (S + A - P) >> 2
public static final int R_SPARC_WDISP30 = 7; // (S + A - P) >> 2
public static final int R_SPARC_PC10 = 16; // (S + A - P) & 0x3FF
public static final int R_SPARC_PC22 = 17; // (S + A - P) >> 10
public static final int R_SPARC_PLT32 = 24; // L + A
public static final int R_SPARC_PCPLT10 = 29; // (L + A - P) & 0x3FF
public static final int R_SPARC_PCPLT22 = 28; // (L + A - P) >> 10
public static final int R_SPARC_PCPLT32 = 27; // L + A - P
public static final int R_SPARC_GOT10 = 13; // G & 0x3FF
public static final int R_SPARC_GOT13 = 14; // G
public static final int R_SPARC_GOT22 = 15; // G >> 10
public static final int R_SPARC_WPLT30 = 18; // (L + A - P) >> 2
public static final int R_SPARC_LOPLT10 = 26; // (L + A) & 0x3FF
public static final int R_SPARC_HIPLT22 = 25; // (L + A) >> 10
public static final int R_SPARC_JMP_SLOT = 21;
public static final int R_SPARC_UA32 = 23; // S + A
public static final int R_SPARC_GLOB_DAT = 20; // S + A
public static final int R_SPARC_RELATIVE = 22; // B + A
public static final int R_SPARC_COPY = 19; // No calculation
private SPARC_ElfRelocationConstants() {
// no construct
}
}

View file

@ -20,11 +20,18 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.util.exception.NotFoundException;
import ghidra.program.model.reloc.RelocationResult;
public class SPARC_ElfRelocationHandler extends ElfRelocationHandler {
public class SPARC_ElfRelocationHandler
extends AbstractElfRelocationHandler<SPARC_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public SPARC_ElfRelocationHandler() {
super(SPARC_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -34,78 +41,62 @@ public class SPARC_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_SPARC &&
elf.e_machine() != ElfConstants.EM_SPARC32PLUS) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, SPARC_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 == SPARC_ElfRelocationConstants.R_SPARC_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
// TODO: possible sign-extension seems wrong; there are both 32-bit and 64-bit variants
long offset = (int) relocationAddress.getOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
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)
switch (type) {
case SPARC_ElfRelocationConstants.R_SPARC_DISP32:
case R_SPARC_DISP32:
newValue = (int) (symbolValue + addend - offset);
memory.setInt(relocationAddress, oldValue | newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_WDISP30:
case R_SPARC_WDISP30:
newValue = (int) (symbolValue + addend - offset) >>> 2;
memory.setInt(relocationAddress, oldValue | newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_HI22:
case R_SPARC_HI22:
newValue = ((int) symbolValue + (int) addend) >>> 10;
memory.setInt(relocationAddress, oldValue | newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_LO10:
case R_SPARC_LO10:
newValue = ((int) symbolValue + (int) addend) & 0x3FF;
memory.setInt(relocationAddress, oldValue | newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_JMP_SLOT:
case R_SPARC_JMP_SLOT:
// should copy address of symbol in EXTERNAL block
case SPARC_ElfRelocationConstants.R_SPARC_32:
case R_SPARC_32:
newValue = (int) symbolValue + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
// we punt on this because it's not linked yet!
case SPARC_ElfRelocationConstants.R_SPARC_GLOB_DAT:
case R_SPARC_GLOB_DAT:
newValue = (int) symbolValue;
memory.setInt(relocationAddress, newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_RELATIVE:
newValue = (int) elf.getImageBase() + (int) addend;
case R_SPARC_RELATIVE:
newValue = (int) elfRelocationContext.getElfHeader().getImageBase() + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_UA32:
case R_SPARC_UA32:
newValue = (int) symbolValue + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
case SPARC_ElfRelocationConstants.R_SPARC_COPY:
markAsWarning(program, relocationAddress, "R_SPARC_COPY", symbolName, symbolIndex,
case R_SPARC_COPY:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:

View file

@ -0,0 +1,70 @@
/* ###
* 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 SPARC_ElfRelocationType implements ElfRelocationType {
R_SPARC_NONE(0), // No calculation
R_SPARC_5(44), // S + A
R_SPARC_6(45), // S + A
R_SPARC_7(43), // S + A
R_SPARC_8(1), // S + A
R_SPARC_10(30), // S + A
R_SPARC_11(31), // S + A
R_SPARC_13(11), // S + A
R_SPARC_16(2), // S + A
R_SPARC_22(10), // S + A
R_SPARC_32(3), // S + A
R_SPARC_LO10(12), // (S + A) & 0x3FF
R_SPARC_HI22(9), // (S + A) >> 10
R_SPARC_DISP8(4), // S + A - P
R_SPARC_DISP16(5), // S + A - P
R_SPARC_DISP32(6), // S + A - P
R_SPARC_WDISP16(40), // (S + A - P) >> 2
R_SPARC_WDISP19(41), // (S + A - P) >> 2
R_SPARC_WDISP22(8), // (S + A - P) >> 2
R_SPARC_WDISP30(7), // (S + A - P) >> 2
R_SPARC_PC10(16), // (S + A - P) & 0x3FF
R_SPARC_PC22(17), // (S + A - P) >> 10
R_SPARC_PLT32(24), // L + A
R_SPARC_PCPLT10(29), // (L + A - P) & 0x3FF
R_SPARC_PCPLT22(28), // (L + A - P) >> 10
R_SPARC_PCPLT32(27), // L + A - P
R_SPARC_GOT10(13), // G & 0x3FF
R_SPARC_GOT13(14), // G
R_SPARC_GOT22(15), // G >> 10
R_SPARC_WPLT30(18), // (L + A - P) >> 2
R_SPARC_LOPLT10(26), // (L + A) & 0x3FF
R_SPARC_HIPLT22(25), // (L + A) >> 10
R_SPARC_JMP_SLOT(21),
R_SPARC_UA32(23), // S + A
R_SPARC_GLOB_DAT(20), // S + A
R_SPARC_RELATIVE(22), // B + A
R_SPARC_COPY(19); // No calculation
public final int typeId;
private SPARC_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.plugin.core.reloc.RelocationFixupHandler;
import ghidra.app.plugin.core.reloc.ElfRelocationFixupHandler;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
@ -23,29 +23,44 @@ import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.util.CodeUnitInsertionException;
public class ElfSH4RelocationFixupHandler extends RelocationFixupHandler {
public class ElfSH4RelocationFixupHandler extends ElfRelocationFixupHandler {
public ElfSH4RelocationFixupHandler() {
super(SH_ElfRelocationType.class);
}
@Override
public boolean processRelocation(Program program, Relocation relocation, Address oldImageBase,
Address newImageBase) throws MemoryAccessException, CodeUnitInsertionException {
switch (relocation.getType()) {
case SH_ElfRelocationConstants.R_SH_DIR32:
case SH_ElfRelocationConstants.R_SH_REL32:
case SH_ElfRelocationConstants.R_SH_GLOB_DAT:
case SH_ElfRelocationConstants.R_SH_JMP_SLOT:
case SH_ElfRelocationConstants.R_SH_RELATIVE:
if (relocation.getStatus() != Status.APPLIED) {
return false;
}
SH_ElfRelocationType type = (SH_ElfRelocationType) getRelocationType(relocation.getType());
if (type == null) {
return false;
}
switch (type) {
case R_SH_DIR32:
case R_SH_REL32:
case R_SH_GLOB_DAT:
case R_SH_JMP_SLOT:
case R_SH_RELATIVE:
return process32BitRelocation(program, relocation, oldImageBase, newImageBase);
// case SH_ElfRelocationConstants.R_SH_DIR8WPN:
// case SH_ElfRelocationConstants.R_SH_DIR8WPZ:
// case SH_ElfRelocationConstants.R_SH_IND12W:
// case SH_ElfRelocationConstants.R_SH_DIR8WPL:
// case R_SH_DIR8WPN:
// case R_SH_DIR8WPZ:
// case R_SH_IND12W:
// case R_SH_DIR8WPL:
default:
return false;
}
return false;
}
@Override
@ -58,7 +73,7 @@ public class ElfSH4RelocationFixupHandler extends RelocationFixupHandler {
return false;
}
Processor processor = language.getProcessor();
return ("SuperH4".equals(processor.toString()) || "SuperH".equals(processor.toString()));
return "SuperH4".equals(processor.toString());
}
}

View file

@ -1,134 +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 SH_ElfRelocationConstants {
public static final int R_SH_NONE = 0; // No operation needed
public static final int R_SH_DIR32 = 1; // (S + A) */
public static final int R_SH_REL32 = 2; // (S + A) - P
public static final int R_SH_DIR8WPN = 3; // 8-bit PC relative branch divided by 2 : (((S + A) - P) >> 1) & 0xff
public static final int R_SH_IND12W = 4; // 12-bit PC relative branch divided by 2 : (((S + A) - P) >> 1) & 0xfff
public static final int R_SH_DIR8WPL = 5; // 8-bit PC unsigned-relative branch divided by 4 : (((S + A) - P) >> 2) & 0xff
public static final int R_SH_DIR8WPZ = 6; // 8-bit PC unsigned-relative branch divided by 2 : (((S + A) - P) >> 1) & 0xff
public static final int R_SH_DIR8BP = 7;
public static final int R_SH_DIR8W = 8;
public static final int R_SH_DIR8L = 9;
// Relocation numbering in this file corresponds to GNU binutils and
// values below this point may differ significantly from those specified
// for other uses (e.g., see https://android.googlesource.com/platform/external/elfutils/+/android-4.1.2_r1/libelf/elf.h )
public static final int R_SH_LOOP_START = 10;
public static final int R_SH_LOOP_END = 11;
public static final int R_SH_GNU_VTINHERIT = 22;
public static final int R_SH_GNU_VTENTRY = 23;
public static final int R_SH_SWITCH8 = 24;
public static final int R_SH_SWITCH16 = 25;
public static final int R_SH_SWITCH32 = 26;
public static final int R_SH_USES = 27;
public static final int R_SH_COUNT = 28;
public static final int R_SH_ALIGN = 29;
public static final int R_SH_CODE = 30;
public static final int R_SH_DATA = 31;
public static final int R_SH_LABEL = 32;
public static final int R_SH_DIR16 = 33;
public static final int R_SH_DIR8 = 34;
public static final int R_SH_DIR8UL = 35;
public static final int R_SH_DIR8UW = 36;
public static final int R_SH_DIR8U = 37;
public static final int R_SH_DIR8SW = 38;
public static final int R_SH_DIR8S = 39;
public static final int R_SH_DIR4UL = 40;
public static final int R_SH_DIR4UW = 41;
public static final int R_SH_DIR4U = 42;
public static final int R_SH_PSHA = 43;
public static final int R_SH_PSHL = 44;
public static final int R_SH_DIR5U = 45;
public static final int R_SH_DIR6U = 46;
public static final int R_SH_DIR6S = 47;
public static final int R_SH_DIR10S = 48;
public static final int R_SH_DIR10SW = 49;
public static final int R_SH_DIR10SL = 50;
public static final int R_SH_DIR10SQ = 51;
public static final int R_SH_DIR16S = 53;
public static final int R_SH_TLS_GD_32 = 144;
public static final int R_SH_TLS_LD_32 = 145;
public static final int R_SH_TLS_LDO_32 = 146;
public static final int R_SH_TLS_IE_32 = 147;
public static final int R_SH_TLS_LE_32 = 148;
public static final int R_SH_TLS_DTPMOD32 = 149;
public static final int R_SH_TLS_DTPOFF32 = 150;
public static final int R_SH_TLS_TPOFF32 = 151;
public static final int R_SH_GOT32 = 160;
public static final int R_SH_PLT32 = 161;
public static final int R_SH_COPY = 162;
public static final int R_SH_GLOB_DAT = 163;
public static final int R_SH_JMP_SLOT = 164;
public static final int R_SH_RELATIVE = 165;
public static final int R_SH_GOTOFF = 166;
public static final int R_SH_GOTPC = 167;
public static final int R_SH_GOTPLT32 = 168;
public static final int R_SH_GOT_LOW16 = 169;
public static final int R_SH_GOT_MEDLOW16 = 170;
public static final int R_SH_GOT_MEDHI16 = 171;
public static final int R_SH_GOT_HI16 = 172;
public static final int R_SH_GOTPLT_LOW16 = 173;
public static final int R_SH_GOTPLT_MEDLOW16 = 174;
public static final int R_SH_GOTPLT_MEDHI16 = 175;
public static final int R_SH_GOTPLT_HI16 = 176;
public static final int R_SH_PLT_LOW16 = 177;
public static final int R_SH_PLT_MEDLOW16 = 178;
public static final int R_SH_PLT_MEDHI16 = 179;
public static final int R_SH_PLT_HI16 = 180;
public static final int R_SH_GOTOFF_LOW16 = 181;
public static final int R_SH_GOTOFF_MEDLOW16 = 182;
public static final int R_SH_GOTOFF_MEDHI16 = 183;
public static final int R_SH_GOTOFF_HI16 = 184;
public static final int R_SH_GOTPC_LOW16 = 185;
public static final int R_SH_GOTPC_MEDLOW16 = 186;
public static final int R_SH_GOTPC_MEDHI16 = 187;
public static final int R_SH_GOTPC_HI16 = 188;
public static final int R_SH_GOT10BY4 = 189;
public static final int R_SH_GOTPLT10BY4 = 190;
public static final int R_SH_GOT10BY8 = 191;
public static final int R_SH_GOTPLT10BY8 = 192;
public static final int R_SH_COPY64 = 193;
public static final int R_SH_GLOB_DAT64 = 194;
public static final int R_SH_JMP_SLOT64 = 195;
public static final int R_SH_RELATIVE64 = 196;
public static final int R_SH_SHMEDIA_CODE = 242;
public static final int R_SH_PT_16 = 243;
public static final int R_SH_IMMS16 = 244;
public static final int R_SH_IMMU16 = 245;
public static final int R_SH_IMM_LOW16 = 246;
public static final int R_SH_IMM_LOW16_PCREL = 247;
public static final int R_SH_IMM_MEDLOW16 = 248;
public static final int R_SH_IMM_MEDLOW16_PCREL = 249;
public static final int R_SH_IMM_MEDHI16 = 250;
public static final int R_SH_IMM_MEDHI16_PCREL = 251;
public static final int R_SH_IMM_HI16 = 252;
public static final int R_SH_IMM_HI16_PCREL = 253;
public static final int R_SH_64 = 254;
public static final int R_SH_64_PCREL = 255;
}

View file

@ -22,9 +22,16 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class SH_ElfRelocationHandler extends ElfRelocationHandler {
public class SH_ElfRelocationHandler
extends AbstractElfRelocationHandler<SH_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public SH_ElfRelocationHandler() {
super(SH_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -32,84 +39,66 @@ public class SH_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_SH || !elf.is32Bit()) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, SH_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 == SH_ElfRelocationConstants.R_SH_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
int addend = (int) relocation.getAddend();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
int offset = (int) relocationAddress.getOffset();
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
int symbolValue = (int) elfRelocationContext.getSymbolValue(sym);
int symbolIndex = relocation.getSymbolIndex();
int newValue = 0;
int oldValue;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case SH_ElfRelocationConstants.R_SH_DIR32:
case R_SH_DIR32:
// 32-bit absolute relocation w/ addend
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue = symbolValue + addend;
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 SH_ElfRelocationConstants.R_SH_GLOB_DAT:
case SH_ElfRelocationConstants.R_SH_JMP_SLOT:
case R_SH_GLOB_DAT:
case R_SH_JMP_SLOT:
// 32-bit absolute relocations, no addend
memory.setInt(relocationAddress, symbolValue);
memory.setInt(relocationAddress, (int) symbolValue);
break;
case SH_ElfRelocationConstants.R_SH_REL32: // 32-bit PC relative relocation
case R_SH_REL32: // 32-bit PC relative relocation
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue = (symbolValue + addend) - offset;
newValue = ((int) symbolValue + addend) - offset;
memory.setInt(relocationAddress, newValue);
break;
case SH_ElfRelocationConstants.R_SH_DIR8WPN: // 8-bit PC relative branch divided by 2
case SH_ElfRelocationConstants.R_SH_DIR8WPZ: // 8-bit PC unsigned-relative branch divided by 2
case R_SH_DIR8WPN: // 8-bit PC relative branch divided by 2
case R_SH_DIR8WPZ: // 8-bit PC unsigned-relative branch divided by 2
oldValue = memory.getShort(relocationAddress);
if (elfRelocationContext.extractAddend()) {
addend = oldValue & 0xff;
if (type == SH_ElfRelocationConstants.R_SH_DIR8WPN && (addend & 0x80) != 0) {
if (type == SH_ElfRelocationType.R_SH_DIR8WPN && (addend & 0x80) != 0) {
addend -= 0x100; // sign-extend addend for R_SH_DIR8WPN
}
}
newValue = ((symbolValue + addend) - offset) >> 1;
newValue = (((int) symbolValue + addend) - offset) >> 1;
newValue = (oldValue & 0xff00) | (newValue & 0xff);
memory.setShort(relocationAddress, (short) newValue);
byteLength = 2;
break;
case SH_ElfRelocationConstants.R_SH_IND12W: // 12-bit PC relative branch divided by 2
case R_SH_IND12W: // 12-bit PC relative branch divided by 2
oldValue = memory.getShort(relocationAddress);
if (elfRelocationContext.extractAddend()) {
addend = oldValue & 0xfff;
@ -117,29 +106,29 @@ public class SH_ElfRelocationHandler extends ElfRelocationHandler {
addend -= 0x1000; // sign-extend addend
}
}
newValue = ((symbolValue + addend) - offset) >> 1;
newValue = (((int) symbolValue + addend) - offset) >> 1;
newValue = (oldValue & 0xf000) | (newValue & 0xfff);
memory.setShort(relocationAddress, (short) newValue);
byteLength = 2;
break;
case SH_ElfRelocationConstants.R_SH_DIR8WPL: // 8-bit PC unsigned-relative branch divided by 4
case R_SH_DIR8WPL: // 8-bit PC unsigned-relative branch divided by 4
oldValue = memory.getShort(relocationAddress);
if (elfRelocationContext.extractAddend()) {
addend = oldValue & 0xff;
}
newValue = ((symbolValue + addend) - offset) >> 2;
newValue = (((int) symbolValue + addend) - offset) >> 2;
newValue = (oldValue & 0xff00) | (newValue & 0xff);
memory.setShort(relocationAddress, (short) newValue);
byteLength = 2;
break;
case SH_ElfRelocationConstants.R_SH_COPY:
markAsWarning(program, relocationAddress, "R_SH_COPY", symbolName, symbolIndex,
case R_SH_COPY:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case SH_ElfRelocationConstants.R_SH_RELATIVE:
case R_SH_RELATIVE:
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}

View file

@ -0,0 +1,145 @@
/* ###
* 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 SH_ElfRelocationType implements ElfRelocationType {
R_SH_NONE(0), // No operation needed
R_SH_DIR32(1), // (S + A) */
R_SH_REL32(2), // (S + A) - P
R_SH_DIR8WPN(3), // 8-bit PC relative branch divided by 2 : (((S + A) - P) >> 1) & 0xff
R_SH_IND12W(4), // 12-bit PC relative branch divided by 2 : (((S + A) - P) >> 1) & 0xfff
R_SH_DIR8WPL(5), // 8-bit PC unsigned-relative branch divided by 4 : (((S + A) - P) >> 2) & 0xff
R_SH_DIR8WPZ(6), // 8-bit PC unsigned-relative branch divided by 2 : (((S + A) - P) >> 1) & 0xff
R_SH_DIR8BP(7),
R_SH_DIR8W(8),
R_SH_DIR8L(9),
// Relocation numbering in this file corresponds to GNU binutils and
// values below this point may differ significantly from those specified
// for other uses (e.g., see https://android.googlesource.com/platform/external/elfutils/+/android-4.1.2_r1/libelf/elf.h )
R_SH_LOOP_START(10),
R_SH_LOOP_END(11),
R_SH_GNU_VTINHERIT(22),
R_SH_GNU_VTENTRY(23),
R_SH_SWITCH8(24),
R_SH_SWITCH16(25),
R_SH_SWITCH32(26),
R_SH_USES(27),
R_SH_COUNT(28),
R_SH_ALIGN(29),
R_SH_CODE(30),
R_SH_DATA(31),
R_SH_LABEL(32),
R_SH_DIR16(33),
R_SH_DIR8(34),
R_SH_DIR8UL(35),
R_SH_DIR8UW(36),
R_SH_DIR8U(37),
R_SH_DIR8SW(38),
R_SH_DIR8S(39),
R_SH_DIR4UL(40),
R_SH_DIR4UW(41),
R_SH_DIR4U(42),
R_SH_PSHA(43),
R_SH_PSHL(44),
R_SH_DIR5U(45),
R_SH_DIR6U(46),
R_SH_DIR6S(47),
R_SH_DIR10S(48),
R_SH_DIR10SW(49),
R_SH_DIR10SL(50),
R_SH_DIR10SQ(51),
R_SH_DIR16S(53),
R_SH_TLS_GD_32(144),
R_SH_TLS_LD_32(145),
R_SH_TLS_LDO_32(146),
R_SH_TLS_IE_32(147),
R_SH_TLS_LE_32(148),
R_SH_TLS_DTPMOD32(149),
R_SH_TLS_DTPOFF32(150),
R_SH_TLS_TPOFF32(151),
R_SH_GOT32(160),
R_SH_PLT32(161),
R_SH_COPY(162),
R_SH_GLOB_DAT(163),
R_SH_JMP_SLOT(164),
R_SH_RELATIVE(165),
R_SH_GOTOFF(166),
R_SH_GOTPC(167),
R_SH_GOTPLT32(168),
R_SH_GOT_LOW16(169),
R_SH_GOT_MEDLOW16(170),
R_SH_GOT_MEDHI16(171),
R_SH_GOT_HI16(172),
R_SH_GOTPLT_LOW16(173),
R_SH_GOTPLT_MEDLOW16(174),
R_SH_GOTPLT_MEDHI16(175),
R_SH_GOTPLT_HI16(176),
R_SH_PLT_LOW16(177),
R_SH_PLT_MEDLOW16(178),
R_SH_PLT_MEDHI16(179),
R_SH_PLT_HI16(180),
R_SH_GOTOFF_LOW16(181),
R_SH_GOTOFF_MEDLOW16(182),
R_SH_GOTOFF_MEDHI16(183),
R_SH_GOTOFF_HI16(184),
R_SH_GOTPC_LOW16(185),
R_SH_GOTPC_MEDLOW16(186),
R_SH_GOTPC_MEDHI16(187),
R_SH_GOTPC_HI16(188),
R_SH_GOT10BY4(189),
R_SH_GOTPLT10BY4(190),
R_SH_GOT10BY8(191),
R_SH_GOTPLT10BY8(192),
R_SH_COPY64(193),
R_SH_GLOB_DAT64(194),
R_SH_JMP_SLOT64(195),
R_SH_RELATIVE64(196),
R_SH_SHMEDIA_CODE(242),
R_SH_PT_16(243),
R_SH_IMMS16(244),
R_SH_IMMU16(245),
R_SH_IMM_LOW16(246),
R_SH_IMM_LOW16_PCREL(247),
R_SH_IMM_MEDLOW16(248),
R_SH_IMM_MEDLOW16_PCREL(249),
R_SH_IMM_MEDHI16(250),
R_SH_IMM_MEDHI16_PCREL(251),
R_SH_IMM_HI16(252),
R_SH_IMM_HI16_PCREL(253),
R_SH_64(254),
R_SH_64_PCREL(255);
public final int typeId;
private SH_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,53 +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;
/**
* class for elf_msp430x_reloc_type (from binutils source)
*/
public class MSP430X_ElfRelocationConstants {
// Note: some of the msp430x relocation types have "msp430" (without the x)
// in their names
public static final int R_MSP430_NONE = 0; // No calculation
public static final int R_MSP430_ABS32 = 1;// S + A
public static final int R_MSP430_ABS16 = 2; // S + A
public static final int R_MSP430_ABS8 = 3; // S + A
public static final int R_MSP430_PCR16 = 4; // S + A - PC
public static final int R_MSP430X_PCR20_EXT_SRC = 5; // S + A - PC
public static final int R_MSP430X_PCR20_EXT_DST = 6; // S + A - PC
public static final int R_MSP430X_PCR20_EXT_ODST = 7; // S + A - PC
public static final int R_MSP430X_ABS20_EXT_SRC = 8; // S + A
public static final int R_MSP430X_ABS20_EXT_DST = 9; // S + A
public static final int R_MSP430X_ABS20_EXT_ODST = 10; // S + A
public static final int R_MSP430X_ABS20_ADR_SRC = 11; // S + A
public static final int R_MSP430X_ABS20_ADR_DST = 12; // S + A
public static final int R_MSP430X_PCR16 = 13; // S + A - PC
public static final int R_MSP430X_PCR20_CALL = 14; // S + A - PC
public static final int R_MSP430X_ABS16 = 15; // S + A
public static final int R_MSP430_ABS_HI16 = 16; // S + A (Rela only)
public static final int R_MSP430_PREL31 = 17; // S + A - PC
public static final int R_MSP430_EHTYPE = 18; // encodes typeinfo addresses in exception tables
public static final int R_MSP430X_10_PCREL = 19; // Red Hat invention.
public static final int R_MSP430X_2X_PCREL = 20; // Red Hat invention
public static final int R_MSP430X_SYM_DIFF = 21; // Red Hat invention*/
public static final int R_MSP430X_SET_ULEB128 = 22; // GNU only
public static final int R_MSP430X_SUB_ULEB128 = 23; // GNU only
private MSP430X_ElfRelocationConstants() {
//class not for instantiation
}
}

View file

@ -23,9 +23,16 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
public class MSP430X_ElfRelocationHandler
extends AbstractElfRelocationHandler<MSP430X_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public MSP430X_ElfRelocationHandler() {
super(MSP430X_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -34,48 +41,42 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException {
int type = relocation.getType();
if (type == MSP430X_ElfRelocationConstants.R_MSP430_NONE) {
return RelocationResult.SKIPPED;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, MSP430X_ElfRelocationType type, Address relocationAddress,
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
int byteLength = 0;
int byteLength;
switch (type) {
case MSP430X_ElfRelocationConstants.R_MSP430_ABS32:
case R_MSP430_ABS32:
int newIntValue = (int) (symbolValue + addend);
memory.setInt(relocationAddress, newIntValue);
byteLength = 4;
break;
case MSP430X_ElfRelocationConstants.R_MSP430_ABS16:
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS16:
case R_MSP430_ABS16:
case R_MSP430X_ABS16:
short newShortValue = (short) (symbolValue + addend);
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
case MSP430X_ElfRelocationConstants.R_MSP430_ABS8:
case R_MSP430_ABS8:
byte newByteValue = (byte) (symbolValue + addend);
memory.setByte(relocationAddress, newByteValue);
byteLength = 1;
break;
case MSP430X_ElfRelocationConstants.R_MSP430_PCR16:
case MSP430X_ElfRelocationConstants.R_MSP430X_PCR16:
case R_MSP430_PCR16:
case R_MSP430X_PCR16:
newShortValue = (short) (symbolValue + addend - offset);
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_SRC:
case R_MSP430X_PCR20_EXT_SRC:
newIntValue = (int) (symbolValue + addend - offset - 4);
memory.setShort(relocationAddress.add(4), (short) (newIntValue));
newIntValue >>= 16;
@ -86,7 +87,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 6;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_DST:
case R_MSP430X_PCR20_EXT_DST:
newIntValue = (int) (symbolValue + addend - offset - 4);
memory.setShort(relocationAddress.add(4), (short) (newIntValue));
newIntValue >>= 16;
@ -97,7 +98,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 6;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_ODST:
case R_MSP430X_PCR20_EXT_ODST:
newIntValue = (int) (symbolValue + addend - offset - 4);
memory.setShort(relocationAddress.add(6), (short) (newIntValue));
newIntValue >>= 16;
@ -108,7 +109,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 8;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_SRC:
case R_MSP430X_ABS20_EXT_SRC:
newIntValue = (int) (symbolValue + addend);
memory.setShort(relocationAddress.add(4), (short) (newIntValue));
newIntValue >>= 16;
@ -119,7 +120,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 6;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_DST:
case R_MSP430X_ABS20_EXT_DST:
newIntValue = (int) (symbolValue + addend);
memory.setShort(relocationAddress.add(4), (short) (newIntValue));
newIntValue >>= 16;
@ -130,7 +131,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 6;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_ODST:
case R_MSP430X_ABS20_EXT_ODST:
newIntValue = (int) (symbolValue + addend);
memory.setShort(relocationAddress.add(6), (short) (newIntValue));
newIntValue >>= 16;
@ -141,7 +142,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 8;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_ADR_SRC:
case R_MSP430X_ABS20_ADR_SRC:
newIntValue = (int) (symbolValue + addend);
memory.setShort(relocationAddress.add(2), (short) (newIntValue & 0xffff));
newIntValue >>= 16;
@ -152,7 +153,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 4;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_ADR_DST:
case R_MSP430X_ABS20_ADR_DST:
newIntValue = (int) (symbolValue + addend);
memory.setShort(relocationAddress.add(2), (short) (newIntValue & 0xffff));
newIntValue >>= 16;
@ -163,7 +164,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 4;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_CALL:
case R_MSP430X_PCR20_CALL:
newIntValue = (int) (symbolValue + addend - offset);
memory.setShort(relocationAddress.add(2), (short) newIntValue);
newIntValue >>= 16;
@ -174,7 +175,7 @@ public class MSP430X_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, highWord);
byteLength = 4;
break;
case MSP430X_ElfRelocationConstants.R_MSP430X_10_PCREL:
case R_MSP430X_10_PCREL:
short oldShortValue = memory.getShort(relocationAddress);
oldShortValue &= 0xfc00;
newShortValue = (short) (symbolValue + addend - offset - 2);

View file

@ -0,0 +1,61 @@
/* ###
* 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;
/**
* class for elf_msp430x_reloc_type (from binutils source)
*/
public enum MSP430X_ElfRelocationType implements ElfRelocationType {
// Note: some of the msp430x relocation types have "msp430" (without the x)
// in their names
R_MSP430_NONE(0), // No calculation
R_MSP430_ABS32(1),// S + A
R_MSP430_ABS16(2), // S + A
R_MSP430_ABS8(3), // S + A
R_MSP430_PCR16(4), // S + A - PC
R_MSP430X_PCR20_EXT_SRC(5), // S + A - PC
R_MSP430X_PCR20_EXT_DST(6), // S + A - PC
R_MSP430X_PCR20_EXT_ODST(7), // S + A - PC
R_MSP430X_ABS20_EXT_SRC(8), // S + A
R_MSP430X_ABS20_EXT_DST(9), // S + A
R_MSP430X_ABS20_EXT_ODST(10), // S + A
R_MSP430X_ABS20_ADR_SRC(11), // S + A
R_MSP430X_ABS20_ADR_DST(12), // S + A
R_MSP430X_PCR16(13), // S + A - PC
R_MSP430X_PCR20_CALL(14), // S + A - PC
R_MSP430X_ABS16(15), // S + A
R_MSP430_ABS_HI16(16), // S + A (Rela only)
R_MSP430_PREL31(17), // S + A - PC
R_MSP430_EHTYPE(18), // encodes typeinfo addresses in exception tables
R_MSP430X_10_PCREL(19), // Red Hat invention.
R_MSP430X_2X_PCREL(20), // Red Hat invention
R_MSP430X_SYM_DIFF(21), // Red Hat invention*/
R_MSP430X_SET_ULEB128(22), // GNU only
R_MSP430X_SUB_ULEB128(23); // GNU only
public final int typeId;
private MSP430X_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -23,9 +23,16 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class MSP430_ElfRelocationHandler extends ElfRelocationHandler {
public class MSP430_ElfRelocationHandler
extends AbstractElfRelocationHandler<MSP430_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public MSP430_ElfRelocationHandler() {
super(MSP430_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -34,32 +41,25 @@ public class MSP430_ElfRelocationHandler extends ElfRelocationHandler {
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException {
int type = relocation.getType();
if (type == MSP430_ElfRelocationConstants.R_MSP430_NONE) {
return RelocationResult.SKIPPED;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, MSP430_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
int byteLength = 0;
int byteLength;
switch (type) {
case MSP430_ElfRelocationConstants.R_MSP430_32:
case R_MSP430_32:
int newIntValue = (int) (symbolValue + addend);
memory.setInt(relocationAddress, newIntValue);
byteLength = 4;
break;
case MSP430_ElfRelocationConstants.R_MSP430_10_PCREL:
case R_MSP430_10_PCREL:
short oldShortValue = memory.getShort(relocationAddress);
oldShortValue &= 0xfc00;
short newShortValue = (short) (symbolValue + addend - offset - 2);
@ -69,32 +69,32 @@ public class MSP430_ElfRelocationHandler extends ElfRelocationHandler {
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
case MSP430_ElfRelocationConstants.R_MSP430_16:
case R_MSP430_16:
newShortValue = (short) (symbolValue + addend);
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
//case TI_MSP430_ElfRelocationConstants.R_MSP430_16_PCREL:
case MSP430_ElfRelocationConstants.R_MSP430_16_BYTE:
//case TI_R_MSP430_16_PCREL:
case R_MSP430_16_BYTE:
newShortValue = (short) (symbolValue + addend);
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
case MSP430_ElfRelocationConstants.R_MSP430_16_PCREL_BYTE:
case R_MSP430_16_PCREL_BYTE:
newShortValue = (short) (symbolValue + addend - offset);
memory.setShort(relocationAddress, newShortValue);
byteLength = 2;
break;
//case TI_MSP430_ElfRelocationConstants.R_MSP430_2X_PCREL:
//case TI_MSP430_ElfRelocationConstants.R_MSP430_RL_PCREL:
case MSP430_ElfRelocationConstants.R_MSP430_8:
//case TI_R_MSP430_2X_PCREL:
//case TI_R_MSP430_RL_PCREL:
case R_MSP430_8:
byte newByteValue = (byte) (symbolValue + addend);
memory.setByte(relocationAddress, newByteValue);
byteLength = 1;
break;
//case TI_MSP430_ElfRelocationConstants.R_MSP430_SYM_DIFF:
//case TI_MSP430_ElfRelocationConstants.R_MSP430_SET_ULEB128:
//case TI_MSP430_ElfRelocationConstants.R_MSP430_SUB_ULEB128:
//case TI_R_MSP430_SYM_DIFF:
//case TI_R_MSP430_SET_ULEB128:
//case TI_R_MSP430_SUB_ULEB128:
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View file

@ -18,18 +18,30 @@ package ghidra.app.util.bin.format.elf.relocation;
/**
* class for elf_msp430_reloc_type (from binutils source)
*/
public class MSP430_ElfRelocationConstants {
public static final int R_MSP430_NONE = 0;
public static final int R_MSP430_32 = 1;
public static final int R_MSP430_10_PCREL = 2;
public static final int R_MSP430_16 = 3;
public static final int R_MSP430_16_PCREL = 4;
public static final int R_MSP430_16_BYTE = 5;
public static final int R_MSP430_16_PCREL_BYTE = 6;
public static final int R_MSP430_2X_PCREL = 7;
public static final int R_MSP430_RL_PCREL = 8;
public static final int R_MSP430_8 = 9;
public static final int R_MSP430_SYM_DIFF = 10;
public static final int R_MSP430_SET_ULEB128 = 11; // GNU only.
public static final int R_MSP430_SUB_ULEB128 = 12; // GNU only
public enum MSP430_ElfRelocationType implements ElfRelocationType {
R_MSP430_NONE(0),
R_MSP430_32(1),
R_MSP430_10_PCREL(2),
R_MSP430_16(3),
R_MSP430_16_PCREL(4),
R_MSP430_16_BYTE(5),
R_MSP430_16_PCREL_BYTE(6),
R_MSP430_2X_PCREL(7),
R_MSP430_RL_PCREL(8),
R_MSP430_8(9),
R_MSP430_SYM_DIFF(10),
R_MSP430_SET_ULEB128(11), // GNU only.
R_MSP430_SUB_ULEB128(12); // GNU only
public final int typeId;
private MSP430_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,73 +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 Xtensa_ElfRelocationConstants {
/* Xtensa processor ELF architecture-magic number */
// EM_XTENSA is already definded
public static final int EM_XTENSA_OLD = 0xABC7;
/* Xtensa relocations defined by the ABIs */
public static final int R_XTENSA_NONE = 0;
public static final int R_XTENSA_32 = 1;
public static final int R_XTENSA_RTLD = 2;
public static final int R_XTENSA_GLOB_DAT = 3;
public static final int R_XTENSA_JMP_SLOT = 4;
public static final int R_XTENSA_RELATIVE = 5;
public static final int R_XTENSA_PLT = 6;
public static final int R_XTENSA_OP0 = 8;
public static final int R_XTENSA_OP1 = 9;
public static final int R_XTENSA_OP2 = 10;
public static final int R_XTENSA_ASM_EXPAND = 11;
public static final int R_XTENSA_ASM_SIMPLIFY = 12;
public static final int R_XTENSA_GNU_VTINHERIT = 15;
public static final int R_XTENSA_GNU_VTENTRY = 16;
public static final int R_XTENSA_DIFF8 = 17;
public static final int R_XTENSA_DIFF16 = 18;
public static final int R_XTENSA_DIFF32 = 19;
public static final int R_XTENSA_SLOT0_OP = 20;
public static final int R_XTENSA_SLOT1_OP = 21;
public static final int R_XTENSA_SLOT2_OP = 22;
public static final int R_XTENSA_SLOT3_OP = 23;
public static final int R_XTENSA_SLOT4_OP = 24;
public static final int R_XTENSA_SLOT5_OP = 25;
public static final int R_XTENSA_SLOT6_OP = 26;
public static final int R_XTENSA_SLOT7_OP = 27;
public static final int R_XTENSA_SLOT8_OP = 28;
public static final int R_XTENSA_SLOT9_OP = 29;
public static final int R_XTENSA_SLOT10_OP = 30;
public static final int R_XTENSA_SLOT11_OP = 31;
public static final int R_XTENSA_SLOT12_OP = 32;
public static final int R_XTENSA_SLOT13_OP = 33;
public static final int R_XTENSA_SLOT14_OP = 34;
public static final int R_XTENSA_SLOT0_ALT = 35;
public static final int R_XTENSA_SLOT1_ALT = 36;
public static final int R_XTENSA_SLOT2_ALT = 37;
public static final int R_XTENSA_SLOT3_ALT = 38;
public static final int R_XTENSA_SLOT4_ALT = 39;
public static final int R_XTENSA_SLOT5_ALT = 40;
public static final int R_XTENSA_SLOT6_ALT = 41;
public static final int R_XTENSA_SLOT7_ALT = 42;
public static final int R_XTENSA_SLOT8_ALT = 43;
public static final int R_XTENSA_SLOT9_ALT = 44;
public static final int R_XTENSA_SLOT10_ALT = 45;
public static final int R_XTENSA_SLOT11_ALT = 46;
public static final int R_XTENSA_SLOT12_ALT = 47;
public static final int R_XTENSA_SLOT13_ALT = 48;
public static final int R_XTENSA_SLOT14_ALT = 49;
}

View file

@ -18,238 +18,175 @@ package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class Xtensa_ElfRelocationHandler extends ElfRelocationHandler {
public class Xtensa_ElfRelocationHandler
extends AbstractElfRelocationHandler<Xtensa_ElfRelocationType, ElfRelocationContext<?>> {
/* Xtensa processor ELF architecture-magic number */
// EM_XTENSA is already definded
public static final int EM_XTENSA_OLD = 0xABC7;
/**
* Constructor
*/
public Xtensa_ElfRelocationHandler() {
super(Xtensa_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
return elf.e_machine() == ElfConstants.EM_XTENSA ||
elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD;
return elf.e_machine() == ElfConstants.EM_XTENSA || elf.e_machine() == EM_XTENSA_OLD;
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (!canRelocate(elf)) {
return RelocationResult.FAILURE;
}
int type = relocation.getType();
if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) {
return RelocationResult.SKIPPED;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, Xtensa_ElfRelocationType type, Address relocationAddress,
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
ElfSymbol sym = null;
String symbolName = null;
int addend = (int) relocation.getAddend();
int symbolIndex = relocation.getSymbolIndex();
if (symbolIndex != 0) {
sym = elfRelocationContext.getSymbol(symbolIndex);
}
//int offset = (int) relocationAddress.getOffset();
if (null != sym) {
symbolName = sym.getNameAsString();
}
int byteLength = -1;
int newValue;
//int byteLength = 4; // most relocations affect 4-bytes (change if different)
int diff_mask = 0;
boolean neg = false;
switch (type) {
case Xtensa_ElfRelocationConstants.R_XTENSA_32:
markAsWarning(program, relocationAddress, "R_XTENSA_32", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_32:
newValue = memory.getInt(relocationAddress);
newValue += (symbolValue + addend);
memory.setInt(relocationAddress, newValue);
byteLength = 4;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD:
markAsWarning(program, relocationAddress, "R_XTENSA_RTLD", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
// case R_XTENSA_RTLD:
case R_XTENSA_RELATIVE:
newValue = ((int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend);
memory.setInt(relocationAddress, newValue);
byteLength = 4;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT:
markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_GLOB_DAT:
case R_XTENSA_JMP_SLOT:
case R_XTENSA_PLT:
newValue = ((int) symbolValue + addend);
memory.setInt(relocationAddress, newValue);
byteLength = 4;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT:
markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
// case R_XTENSA_OP0:
// case R_XTENSA_OP1:
// case R_XTENSA_OP2:
// case R_XTENSA_ASM_EXPAND:
// case R_XTENSA_ASM_SIMPLIFY:
// case R_XTENSA_GNU_VTINHERIT:
// case R_XTENSA_GNU_VTENTRY:
case R_XTENSA_DIFF8:
diff_mask = 0x7f;
byteLength = 1;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE:
markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_DIFF16:
diff_mask = 0x7fff;
byteLength = 2;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_PLT:
markAsWarning(program, relocationAddress, "R_XTENSA_PLT", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_DIFF32:
diff_mask = 0x7fffffff;
byteLength = 4;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_OP0:
markAsWarning(program, relocationAddress, "R_XTENSA_OP0", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
// case R_XTENSA_SLOT0_OP:
// case R_XTENSA_SLOT1_OP:
// case R_XTENSA_SLOT2_OP:
// case R_XTENSA_SLOT3_OP:
// case R_XTENSA_SLOT4_OP:
// case R_XTENSA_SLOT5_OP:
// case R_XTENSA_SLOT6_OP:
// case R_XTENSA_SLOT7_OP:
// case R_XTENSA_SLOT8_OP:
// case R_XTENSA_SLOT9_OP:
// case R_XTENSA_SLOT10_OP:
// case R_XTENSA_SLOT11_OP:
// case R_XTENSA_SLOT12_OP:
// case R_XTENSA_SLOT13_OP:
// case R_XTENSA_SLOT14_OP:
// case R_XTENSA_SLOT0_ALT:
// case R_XTENSA_SLOT1_ALT:
// case R_XTENSA_SLOT2_ALT:
// case R_XTENSA_SLOT3_ALT:
// case R_XTENSA_SLOT4_ALT:
// case R_XTENSA_SLOT5_ALT:
// case R_XTENSA_SLOT6_ALT:
// case R_XTENSA_SLOT7_ALT:
// case R_XTENSA_SLOT8_ALT:
// case R_XTENSA_SLOT9_ALT:
// case R_XTENSA_SLOT10_ALT:
// case R_XTENSA_SLOT11_ALT:
// case R_XTENSA_SLOT12_ALT:
// case R_XTENSA_SLOT13_ALT:
// case R_XTENSA_SLOT14_ALT:
case R_XTENSA_TLSDESC_FN:
case R_XTENSA_TLSDESC_ARG:
case R_XTENSA_TLS_DTPOFF:
case R_XTENSA_TLS_TPOFF:
case R_XTENSA_TLS_FUNC:
case R_XTENSA_TLS_ARG:
case R_XTENSA_TLS_CALL:
markAsWarning(program, relocationAddress, type, symbolName,
relocation.getSymbolIndex(), "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_OP1:
markAsWarning(program, relocationAddress, "R_XTENSA_OP1", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_NDIFF8:
neg = true;
// fall-through
case R_XTENSA_PDIFF8:
diff_mask = 0xff;
byteLength = 1;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_OP2:
markAsWarning(program, relocationAddress, "R_XTENSA_OP2", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_NDIFF16:
neg = true;
// fall-through
case R_XTENSA_PDIFF16:
diff_mask = 0xffff;
byteLength = 2;
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND:
markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY:
markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT:
markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY:
markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8:
markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8", symbolName, symbolIndex,
"TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16:
markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32:
markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
break;
case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT:
markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT", symbolName,
symbolIndex, "TODO, needs support ", elfRelocationContext.getLog());
case R_XTENSA_NDIFF32:
neg = true;
// fall-through
case R_XTENSA_PDIFF32:
diff_mask = 0xffffffff;
byteLength = 4;
break;
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
markAsUnhandled(program, relocationAddress, type, relocation.getSymbolIndex(),
symbolName, elfRelocationContext.getLog());
}
return RelocationResult.UNSUPPORTED;
if (diff_mask != 0) {
//TODO: Not sure if they can all be done here, handle DIFF relocations
//See values: diff_mask, neg, and byteLength
markAsUnhandled(program, relocationAddress, type, relocation.getSymbolIndex(),
symbolName, elfRelocationContext.getLog());
byteLength = -1; // not yet implemented
}
if (byteLength < 0) {
return RelocationResult.UNSUPPORTED;
}
return new RelocationResult(Status.APPLIED, byteLength);
}
}

View file

@ -0,0 +1,94 @@
/* ###
* 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 Xtensa_ElfRelocationType implements ElfRelocationType {
/* Xtensa relocations defined by the ABIs */
R_XTENSA_NONE(0),
R_XTENSA_32(1),
R_XTENSA_RTLD(2),
R_XTENSA_GLOB_DAT(3),
R_XTENSA_JMP_SLOT(4),
R_XTENSA_RELATIVE(5),
R_XTENSA_PLT(6),
R_XTENSA_OP0(8),
R_XTENSA_OP1(9),
R_XTENSA_OP2(10),
R_XTENSA_ASM_EXPAND(11),
R_XTENSA_ASM_SIMPLIFY(12),
R_XTENSA_32_PCREL(14),
R_XTENSA_GNU_VTINHERIT(15),
R_XTENSA_GNU_VTENTRY(16),
R_XTENSA_DIFF8(17),
R_XTENSA_DIFF16(18),
R_XTENSA_DIFF32(19),
R_XTENSA_SLOT0_OP(20),
R_XTENSA_SLOT1_OP(21),
R_XTENSA_SLOT2_OP(22),
R_XTENSA_SLOT3_OP(23),
R_XTENSA_SLOT4_OP(24),
R_XTENSA_SLOT5_OP(25),
R_XTENSA_SLOT6_OP(26),
R_XTENSA_SLOT7_OP(27),
R_XTENSA_SLOT8_OP(28),
R_XTENSA_SLOT9_OP(29),
R_XTENSA_SLOT10_OP(30),
R_XTENSA_SLOT11_OP(31),
R_XTENSA_SLOT12_OP(32),
R_XTENSA_SLOT13_OP(33),
R_XTENSA_SLOT14_OP(34),
R_XTENSA_SLOT0_ALT(35),
R_XTENSA_SLOT1_ALT(36),
R_XTENSA_SLOT2_ALT(37),
R_XTENSA_SLOT3_ALT(38),
R_XTENSA_SLOT4_ALT(39),
R_XTENSA_SLOT5_ALT(40),
R_XTENSA_SLOT6_ALT(41),
R_XTENSA_SLOT7_ALT(42),
R_XTENSA_SLOT8_ALT(43),
R_XTENSA_SLOT9_ALT(44),
R_XTENSA_SLOT10_ALT(45),
R_XTENSA_SLOT11_ALT(46),
R_XTENSA_SLOT12_ALT(47),
R_XTENSA_SLOT13_ALT(48),
R_XTENSA_SLOT14_ALT(49),
R_XTENSA_TLSDESC_FN(50),
R_XTENSA_TLSDESC_ARG(51),
R_XTENSA_TLS_DTPOFF(52),
R_XTENSA_TLS_TPOFF(53),
R_XTENSA_TLS_FUNC(54),
R_XTENSA_TLS_ARG(55),
R_XTENSA_TLS_CALL(56),
R_XTENSA_PDIFF8(57),
R_XTENSA_PDIFF16(58),
R_XTENSA_PDIFF32(59),
R_XTENSA_NDIFF8(60),
R_XTENSA_NDIFF16(61),
R_XTENSA_NDIFF32(62);
public final int typeId;
private Xtensa_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,47 +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;
import ghidra.app.plugin.core.reloc.RelocationFixupHandler;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.util.CodeUnitInsertionException;
public class ElfeBPFRelocationFixupHandler extends RelocationFixupHandler {
@Override
public boolean processRelocation(Program program, Relocation relocation, Address oldImageBase,
Address newImageBase) throws MemoryAccessException, CodeUnitInsertionException {
return process64BitRelocation(program, relocation, oldImageBase, newImageBase);
}
@Override
public boolean handlesProgram(Program program) {
if (!ElfLoader.ELF_NAME.equals(program.getExecutableFormat())) {
return false;
}
Language language = program.getLanguage();
if (language.getLanguageDescription().getSize() != 64) {
return false;
}
Processor processor = language.getProcessor();
return (processor.equals(Processor.findOrPossiblyCreateProcessor("eBPF")));
}
}

View file

@ -18,94 +18,91 @@ package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.util.exception.NotFoundException;
import ghidra.program.model.reloc.RelocationResult;
public class eBPF_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public boolean canRelocate(ElfHeader elf) {
return elf.e_machine() == ElfConstants.EM_BPF;
}
public class eBPF_ElfRelocationHandler
extends AbstractElfRelocationHandler<eBPF_ElfRelocationType, ElfRelocationContext<?>> {
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
/**
* Constructor
*/
public eBPF_ElfRelocationHandler() {
super(eBPF_ElfRelocationType.class);
}
ElfHeader elf = elfRelocationContext.getElfHeader();
if (elf.e_machine() != ElfConstants.EM_BPF) {
return RelocationResult.FAILURE;
}
@Override
public boolean canRelocate(ElfHeader elf) {
return elf.e_machine() == ElfConstants.EM_BPF;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
@Override
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, eBPF_ElfRelocationType type, Address relocationAddress,
ElfSymbol symbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
int type = relocation.getType();
if (type == eBPF_ElfRelocationConstants.R_BPF_NONE) {
return RelocationResult.SKIPPED;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
String section_name = elfRelocationContext.relocationTable.getSectionToBeRelocated().getNameAsString();
if (section_name.toString().contains("debug")) {
return RelocationResult.SKIPPED;
}
String section_name =
elfRelocationContext.relocationTable.getSectionToBeRelocated().getNameAsString();
if (section_name.toString().contains("debug")) {
return RelocationResult.SKIPPED;
}
SymbolTable table = program.getSymbolTable();
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol symbol = elfRelocationContext.getSymbol(symbolIndex);
String symbolName = symbol.getNameAsString();
Address symbolAddr = table.getSymbols(symbolName).next().getAddress();
int symbolIndex = relocation.getSymbolIndex();
long new_value = 0;
int byteLength = 8;
long new_value = 0;
int byteLength = 4; // most relocations affect 4-bytes
try {
switch (type){
case eBPF_ElfRelocationConstants.R_BPF_64_64: {
new_value = symbolAddr.getAddressableWordOffset();
Byte dst = memory.getByte(relocationAddress.add(0x1));
memory.setLong(relocationAddress.add(0x4), new_value);
memory.setByte(relocationAddress.add(0x1), (byte)(dst + 0x10));
break;
}
case eBPF_ElfRelocationConstants.R_BPF_64_32: {
// if we have, e.g, non-static function, it will be marked in the relocation table
// and indexed in the symbol table and it's easy to calculate the pc-relative offset
long instr_next = relocationAddress.add(0x8).getAddressableWordOffset();
if (symbol.isFunction()) {
new_value = symbolAddr.getAddressableWordOffset();
int offset = (int)(new_value - instr_next);
memory.setInt(relocationAddress.add(0x4), offset);
} else if (symbol.isSection()) {
if (memory.getInt(relocationAddress) == 0x1085) {
ElfSectionHeader sectionHeader = elfRelocationContext.getElfHeader().getSection(symbolName);
long section_start = program.getImageBase().getOffset() + sectionHeader.getAddress();
switch (type) {
case R_BPF_64_64: {
new_value = symbolAddr.getAddressableWordOffset();
Byte dst = memory.getByte(relocationAddress.add(0x1));
memory.setLong(relocationAddress.add(0x4), new_value);
memory.setByte(relocationAddress.add(0x1), (byte) (dst + 0x10));
break;
}
case R_BPF_64_32: {
// getting call instruction offset (current imm)
int current_imm = memory.getInt(relocationAddress.add(0x4));
// if we have, e.g, non-static function, it will be marked in the relocation table
// and indexed in the symbol table and it's easy to calculate the pc-relative offset
long instr_next = relocationAddress.add(0x8).getAddressableWordOffset();
if (symbol.isFunction()) {
new_value = symbolAddr.getAddressableWordOffset();
int offset = (int) (new_value - instr_next);
memory.setInt(relocationAddress.add(0x4), offset);
}
else if (symbol.isSection()) {
if (memory.getInt(relocationAddress) == 0x1085) {
ElfSectionHeader sectionHeader =
elfRelocationContext.getElfHeader().getSection(symbolName);
long section_start =
program.getImageBase().getOffset() + sectionHeader.getAddress();
// calculate the call target section offset
// according to formula in "kernel.org" docs: https://www.kernel.org/doc/html/latest/bpf/llvm_reloc.html
int func_sec_offset = (current_imm + 1) * 8;
long func_addr = section_start + func_sec_offset;
int offset = (int)(func_addr - instr_next);
memory.setInt(relocationAddress.add(0x4), offset);
}
}
break;
}
default: {
if (symbolIndex == 0) {
markAsWarning(program, relocationAddress,
Long.toString(type), "applied relocation with symbol-index of 0", elfRelocationContext.getLog());
}
return RelocationResult.UNSUPPORTED;
}
}
} catch (NullPointerException e) { }
return new RelocationResult(Status.APPLIED, byteLength);
}
// getting call instruction offset (current imm)
int current_imm = memory.getInt(relocationAddress.add(0x4));
// calculate the call target section offset
// according to formula in "kernel.org" docs: https://www.kernel.org/doc/html/latest/bpf/llvm_reloc.html
int func_sec_offset = (current_imm + 1) * 8;
long func_addr = section_start + func_sec_offset;
int offset = (int) (func_addr - instr_next);
memory.setInt(relocationAddress.add(0x4), offset);
}
}
break;
}
default: {
if (symbolIndex == 0) {
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"applied relocation with symbol-index of 0", elfRelocationContext.getLog());
}
return RelocationResult.UNSUPPORTED;
}
}
return new RelocationResult(Status.APPLIED, byteLength);
}
}

View file

@ -0,0 +1,37 @@
/* ###
* 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 eBPF_ElfRelocationType implements ElfRelocationType {
R_BPF_NONE(0), // No operation needed
R_BPF_64_64(1), // S + A
R_BPF_64_ABS64(2), // S + A
R_BPF_64_ABS32(3), // S + A
R_BPF_64_NODYLD32(4), // S + A
R_BPF_64_32(10); // (S + A) / 8 - 1
public final int typeId;
private eBPF_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.plugin.core.reloc.RelocationFixupHandler;
import ghidra.app.plugin.core.reloc.ElfRelocationFixupHandler;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
@ -23,51 +23,45 @@ import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.util.CodeUnitInsertionException;
public class Elfx86_32bitRelocationFixupHandler extends RelocationFixupHandler {
public class Elfx86_32bitRelocationFixupHandler extends ElfRelocationFixupHandler {
public Elfx86_32bitRelocationFixupHandler() {
super(X86_32_ElfRelocationType.class);
}
@Override
public boolean processRelocation(Program program, Relocation relocation, Address oldImageBase,
Address newImageBase) throws MemoryAccessException, CodeUnitInsertionException {
switch (relocation.getType()) {
case X86_32_ElfRelocationConstants.R_386_NONE:
case X86_32_ElfRelocationConstants.R_386_32:
case X86_32_ElfRelocationConstants.R_386_PC32:
case X86_32_ElfRelocationConstants.R_386_GOT32:
case X86_32_ElfRelocationConstants.R_386_PLT32:
case X86_32_ElfRelocationConstants.R_386_COPY:
case X86_32_ElfRelocationConstants.R_386_GLOB_DAT:
case X86_32_ElfRelocationConstants.R_386_JMP_SLOT:
case X86_32_ElfRelocationConstants.R_386_RELATIVE:
case X86_32_ElfRelocationConstants.R_386_GOTOFF:
case X86_32_ElfRelocationConstants.R_386_GOTPC:
case X86_32_ElfRelocationConstants.R_386_TLS_TPOFF:
case X86_32_ElfRelocationConstants.R_386_TLS_IE:
case X86_32_ElfRelocationConstants.R_386_TLS_GOTIE:
case X86_32_ElfRelocationConstants.R_386_TLS_LE:
case X86_32_ElfRelocationConstants.R_386_TLS_GD:
case X86_32_ElfRelocationConstants.R_386_TLS_LDM:
case X86_32_ElfRelocationConstants.R_386_TLS_GD_32:
case X86_32_ElfRelocationConstants.R_386_TLS_GD_PUSH:
case X86_32_ElfRelocationConstants.R_386_TLS_GD_CALL:
case X86_32_ElfRelocationConstants.R_386_TLS_GD_POP:
case X86_32_ElfRelocationConstants.R_386_TLS_LDM_32:
case X86_32_ElfRelocationConstants.R_386_TLS_LDM_PUSH:
case X86_32_ElfRelocationConstants.R_386_TLS_LDM_CALL:
case X86_32_ElfRelocationConstants.R_386_TLS_LDM_POP:
case X86_32_ElfRelocationConstants.R_386_TLS_LDO_32:
case X86_32_ElfRelocationConstants.R_386_TLS_IE_32:
case X86_32_ElfRelocationConstants.R_386_TLS_LE_32:
case X86_32_ElfRelocationConstants.R_386_TLS_DTPMOD32:
case X86_32_ElfRelocationConstants.R_386_TLS_DTPOFF32:
case X86_32_ElfRelocationConstants.R_386_TLS_TPOFF32:
return process32BitRelocation(program, relocation, oldImageBase, newImageBase);
if (relocation.getStatus() != Status.APPLIED) {
return false;
}
return false;
X86_32_ElfRelocationType type =
(X86_32_ElfRelocationType) getRelocationType(relocation.getType());
if (type == null) {
return false;
}
switch (type) {
case R_386_32:
case R_386_PC32:
case R_386_GOT32:
case R_386_PLT32:
case R_386_COPY:
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
case R_386_RELATIVE:
case R_386_GOTOFF:
case R_386_GOTPC:
return process32BitRelocation(program, relocation, oldImageBase, newImageBase);
default:
return false;
}
}
@Override

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import ghidra.app.plugin.core.reloc.RelocationFixupHandler;
import ghidra.app.plugin.core.reloc.ElfRelocationFixupHandler;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
@ -23,60 +23,43 @@ import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.util.CodeUnitInsertionException;
public class Elfx86_64bitRelocationFixupHandler extends RelocationFixupHandler {
public class Elfx86_64bitRelocationFixupHandler extends ElfRelocationFixupHandler {
public Elfx86_64bitRelocationFixupHandler() {
super(X86_64_ElfRelocationType.class);
}
@Override
public boolean processRelocation(Program program, Relocation relocation, Address oldImageBase,
Address newImageBase) throws MemoryAccessException, CodeUnitInsertionException {
switch (relocation.getType()) {
case X86_64_ElfRelocationConstants.R_X86_64_NONE:
case X86_64_ElfRelocationConstants.R_X86_64_64:
case X86_64_ElfRelocationConstants.R_X86_64_PC32:
case X86_64_ElfRelocationConstants.R_X86_64_GOT32:
case X86_64_ElfRelocationConstants.R_X86_64_PLT32:
case X86_64_ElfRelocationConstants.R_X86_64_COPY:
case X86_64_ElfRelocationConstants.R_X86_64_GLOB_DAT:
case X86_64_ElfRelocationConstants.R_X86_64_JUMP_SLOT:
case X86_64_ElfRelocationConstants.R_X86_64_RELATIVE:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL:
case X86_64_ElfRelocationConstants.R_X86_64_32:
case X86_64_ElfRelocationConstants.R_X86_64_32S:
case X86_64_ElfRelocationConstants.R_X86_64_16:
case X86_64_ElfRelocationConstants.R_X86_64_PC16:
case X86_64_ElfRelocationConstants.R_X86_64_8:
case X86_64_ElfRelocationConstants.R_X86_64_PC8:
case X86_64_ElfRelocationConstants.R_X86_64_DTPMOD64:
case X86_64_ElfRelocationConstants.R_X86_64_DTPOFF64:
case X86_64_ElfRelocationConstants.R_X86_64_TPOFF64:
case X86_64_ElfRelocationConstants.R_X86_64_TLSGD:
case X86_64_ElfRelocationConstants.R_X86_64_TLSLD:
case X86_64_ElfRelocationConstants.R_X86_64_DTPOFF32:
case X86_64_ElfRelocationConstants.R_X86_64_GOTTPOFF:
case X86_64_ElfRelocationConstants.R_X86_64_TPOFF32:
case X86_64_ElfRelocationConstants.R_X86_64_PC64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTOFF64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPC32:
case X86_64_ElfRelocationConstants.R_X86_64_GOT64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPC64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPLT64:
case X86_64_ElfRelocationConstants.R_X86_64_PLTOFF64:
case X86_64_ElfRelocationConstants.R_X86_64_SIZE32:
case X86_64_ElfRelocationConstants.R_X86_64_SIZE64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPC32_TLSDESC:
case X86_64_ElfRelocationConstants.R_X86_64_TLSDESC_CALL:
case X86_64_ElfRelocationConstants.R_X86_64_TLSDESC:
case X86_64_ElfRelocationConstants.R_X86_64_IRELATIVE:
case X86_64_ElfRelocationConstants.R_X86_64_RELATIVE64:
case X86_64_ElfRelocationConstants.R_X86_64_NUM:
case X86_64_ElfRelocationConstants.R_X86_64_GNU_VTINHERIT:
case X86_64_ElfRelocationConstants.R_X86_64_GNU_VTENTRY:
return process64BitRelocation(program, relocation, oldImageBase, newImageBase);
if (relocation.getStatus() != Status.APPLIED) {
return false;
}
X86_64_ElfRelocationType type =
(X86_64_ElfRelocationType) getRelocationType(relocation.getType());
if (type == null) {
return false;
}
switch (type) {
case R_X86_64_COPY:
case R_X86_64_64:
case R_X86_64_RELATIVE:
case R_X86_64_RELATIVE64:
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
case R_X86_64_GOTPCREL64:
case R_X86_64_IRELATIVE:
return process64BitRelocation(program, relocation, oldImageBase, newImageBase);
default:
// TODO: Apply bookmark where relocation fixup failed to be processed
return false;
}
return false;
}
@Override

View file

@ -1,61 +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 X86_32_ElfRelocationConstants {
public static final int R_386_NONE = 0; // No calculation
public static final int R_386_32 = 1; // S + A
public static final int R_386_PC32 = 2; // S + A - P
public static final int R_386_GOT32 = 3; // G + A - P
public static final int R_386_PLT32 = 4; // L + A - P
public static final int R_386_COPY = 5; // No calculation
public static final int R_386_GLOB_DAT = 6; // S
public static final int R_386_JMP_SLOT = 7; // S
public static final int R_386_RELATIVE = 8; // B + A
public static final int R_386_GOTOFF = 9; // S + A - GOT
public static final int R_386_GOTPC = 10; // GOT + A - P
public static final int R_386_32PLT = 11;
public static final int R_386_TLS_TPOFF = 14; // negative offset in static TLS block
public static final int R_386_TLS_IE = 15; // absolute address of GOT entry for negative static TLS block offset
public static final int R_386_TLS_GOTIE = 16; // GOT entry for negative static TLS block offset
public static final int R_386_TLS_LE = 17; // negative offset relative to static TLS
public static final int R_386_TLS_GD = 18; // direct 32 bit for GNU version of GD TLS
public static final int R_386_TLS_LDM = 19; // direct 32 bit for GNU version of LD TLS in LE code
public static final int R_386_TLS_GD_32 = 24; // direct 32 bit for GD TLS
public static final int R_386_TLS_GD_PUSH = 25; // tag for pushl in GD TLS code
public static final int R_386_TLS_GD_CALL = 26; // relocation for call
public static final int R_386_TLS_GD_POP = 27; // tag for popl in GD TLS code
public static final int R_386_TLS_LDM_32 = 28; // direct 32 bit for local dynamic code
public static final int R_386_TLS_LDM_PUSH = 29; // tag for pushl in LDM TLS code
public static final int R_386_TLS_LDM_CALL = 30; // relocation for call
public static final int R_386_TLS_LDM_POP = 31; // tag for popl in LDM TLS code
public static final int R_386_TLS_LDO_32 = 32; // offset relative to TLS block
public static final int R_386_TLS_IE_32 = 33; // got entry for static TLS block
public static final int R_386_TLS_LE_32 = 34; // offset relative to static TLS block
public static final int R_386_TLS_DTPMOD32 = 35; // ID of module containing symbol
public static final int R_386_TLS_DTPOFF32 = 36; // offset in TLS block
public static final int R_386_TLS_TPOFF32 = 37; // offset in static TLS block
public static final int R_386_TLS_GOTDESC = 39; // GOT offset for TLS descriptor. */
public static final int R_386_TLS_DESC_CALL = 40; // Marker of call through TLS descriptor for relaxation. */
public static final int R_386_TLS_DESC = 41; // TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol. */
public static final int R_386_IRELATIVE = 42; // Adjust indirectly by program base */
private X86_32_ElfRelocationConstants() {
// no construct
}
}

View file

@ -24,7 +24,15 @@ import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
public class X86_32_ElfRelocationHandler
extends AbstractElfRelocationHandler<X86_32_ElfRelocationType, ElfRelocationContext<?>> {
/**
* Constructor
*/
public X86_32_ElfRelocationHandler() {
super(X86_32_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -33,113 +41,84 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public int getRelrRelocationType() {
return X86_32_ElfRelocationConstants.R_386_RELATIVE;
return X86_32_ElfRelocationType.R_386_RELATIVE.typeId;
}
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
if (elf.e_machine() != ElfConstants.EM_386) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(ElfRelocationContext<?> elfRelocationContext,
ElfRelocation relocation, X86_32_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 == X86_32_ElfRelocationConstants.R_386_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
// addend is either pulled from the relocation or the bytes in memory
long addend =
relocation.hasAddend() ? relocation.getAddend() : memory.getInt(relocationAddress);
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long offset = (int) relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
int byteLength = 4; // most relocations affect 4-bytes (change if different)
int value;
switch (type) {
case X86_32_ElfRelocationConstants.R_386_32:
case R_386_32:
value = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value);
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 X86_32_ElfRelocationConstants.R_386_PC32:
case R_386_PC32:
value = (int) (symbolValue + addend - offset);
memory.setInt(relocationAddress, value);
break;
// we punt on these because they're not linked yet!
case X86_32_ElfRelocationConstants.R_386_GOT32:
case R_386_GOT32:
value = (int) (symbolValue + addend);
memory.setInt(relocationAddress, value);
break;
case X86_32_ElfRelocationConstants.R_386_PLT32:
case R_386_PLT32:
value = (int) (symbolValue + addend - offset);
memory.setInt(relocationAddress, value);
break;
case X86_32_ElfRelocationConstants.R_386_GLOB_DAT:
case X86_32_ElfRelocationConstants.R_386_JMP_SLOT:
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
value = (int) symbolValue;
memory.setInt(relocationAddress, value);
break;
case X86_32_ElfRelocationConstants.R_386_GOTOFF:
case R_386_GOTOFF:
try {
long dotgot = elfRelocationContext.getGOTValue();
value = (int) symbolValue + (int) addend - (int) dotgot;
memory.setInt(relocationAddress, value);
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, "R_386_GOTOFF", symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
}
break;
case X86_32_ElfRelocationConstants.R_386_COPY:
markAsWarning(program, relocationAddress, "R_386_COPY", symbolName, symbolIndex,
case R_386_COPY:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
break;
// Thread Local Symbol relocations (unimplemented concept)
case X86_32_ElfRelocationConstants.R_386_TLS_DTPMOD32:
markAsWarning(program, relocationAddress, "R_386_TLS_DTPMOD32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_32_ElfRelocationConstants.R_386_TLS_DTPOFF32:
markAsWarning(program, relocationAddress, "R_386_TLS_DTPOFF32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_32_ElfRelocationConstants.R_386_TLS_TPOFF32:
markAsWarning(program, relocationAddress, "R_386_TLS_TPOFF32", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_32_ElfRelocationConstants.R_386_TLS_TPOFF:
markAsWarning(program, relocationAddress, "R_386_TLS_TPOFF", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
case R_386_TLS_DTPMOD32:
case R_386_TLS_DTPOFF32:
case R_386_TLS_TPOFF32:
case R_386_TLS_TPOFF:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// cases which do not use symbol value
case X86_32_ElfRelocationConstants.R_386_RELATIVE:
case R_386_RELATIVE:
long base = program.getImageBase().getOffset();
if (elf.isPreLinked()) {
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getInt(relocationAddress) +
(int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
@ -150,14 +129,14 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value);
break;
case X86_32_ElfRelocationConstants.R_386_IRELATIVE:
case R_386_IRELATIVE:
// NOTE: We don't support this since the code actually uses a function to
// compute the relocation value (i.e., indirect)
markAsError(program, relocationAddress, "R_386_IRELATIVE", symbolName,
"indirect computed relocation not supported", elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Indirect computed relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_32_ElfRelocationConstants.R_386_GOTPC:
case R_386_GOTPC:
// similar to R_386_PC32 but uses .got address instead of symbol address
try {
long dotgot = elfRelocationContext.getGOTValue();
@ -165,31 +144,31 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, value);
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, "R_386_GOTPC", symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
}
break;
// TODO: Cases not yet examined
// case ElfRelocationConstants.R_386_32PLT
// case ElfRelocationConstants.R_386_TLS_IE:
// case ElfRelocationConstants.R_386_TLS_GOTIE:
// case ElfRelocationConstants.R_386_TLS_LE:
// case ElfRelocationConstants.R_386_TLS_GD:
// case ElfRelocationConstants.R_386_TLS_LDM:
// case ElfRelocationConstants.R_386_TLS_GD_32:
// case ElfRelocationConstants.R_386_TLS_GD_PUSH:
// case ElfRelocationConstants.R_386_TLS_GD_CALL:
// case ElfRelocationConstants.R_386_TLS_GD_POP:
// case ElfRelocationConstants.R_386_TLS_LDM_32:
// case ElfRelocationConstants.R_386_TLS_LDM_PUSH:
// case ElfRelocationConstants.R_386_TLS_LDO_32:
// case ElfRelocationConstants.R_386_TLS_IE_32:
// case ElfRelocationConstants.R_386_TLS_LE_32:
// case ElfRelocationConstants.R_386_TLS_GOTDESC:
// case ElfRelocationConstants.R_386_TLS_GOTDESC:
// case ElfRelocationConstants.R_386_TLS_DESC_CALL:
// case ElfRelocationConstants.R_386_TLS_DESC:
// case R_386_32PLT
// case R_386_TLS_IE:
// case R_386_TLS_GOTIE:
// case R_386_TLS_LE:
// case R_386_TLS_GD:
// case R_386_TLS_LDM:
// case R_386_TLS_GD_32:
// case R_386_TLS_GD_PUSH:
// case R_386_TLS_GD_CALL:
// case R_386_TLS_GD_POP:
// case R_386_TLS_LDM_32:
// case R_386_TLS_LDM_PUSH:
// case R_386_TLS_LDO_32:
// case R_386_TLS_IE_32:
// case R_386_TLS_LE_32:
// case R_386_TLS_GOTDESC:
// case R_386_TLS_GOTDESC:
// case R_386_TLS_DESC_CALL:
// case R_386_TLS_DESC:
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
@ -198,4 +177,5 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
}
return new RelocationResult(Status.APPLIED, byteLength);
}
}

View file

@ -0,0 +1,69 @@
/* ###
* 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 X86_32_ElfRelocationType implements ElfRelocationType {
R_386_NONE(0), // No calculation
R_386_32(1), // S + A
R_386_PC32(2), // S + A - P
R_386_GOT32(3), // G + A - P
R_386_PLT32(4), // L + A - P
R_386_COPY(5), // No calculation
R_386_GLOB_DAT(6), // S
R_386_JMP_SLOT(7), // S
R_386_RELATIVE(8), // B + A
R_386_GOTOFF(9), // S + A - GOT
R_386_GOTPC(10), // GOT + A - P
R_386_32PLT(11),
R_386_TLS_TPOFF(14), // negative offset in static TLS block
R_386_TLS_IE(15), // absolute address of GOT entry for negative static TLS block offset
R_386_TLS_GOTIE(16), // GOT entry for negative static TLS block offset
R_386_TLS_LE(17), // negative offset relative to static TLS
R_386_TLS_GD(18), // direct 32 bit for GNU version of GD TLS
R_386_TLS_LDM(19), // direct 32 bit for GNU version of LD TLS in LE code
R_386_TLS_GD_32(24), // direct 32 bit for GD TLS
R_386_TLS_GD_PUSH(25), // tag for pushl in GD TLS code
R_386_TLS_GD_CALL(26), // relocation for call
R_386_TLS_GD_POP(27), // tag for popl in GD TLS code
R_386_TLS_LDM_32(28), // direct 32 bit for local dynamic code
R_386_TLS_LDM_PUSH(29), // tag for pushl in LDM TLS code
R_386_TLS_LDM_CALL(30), // relocation for call
R_386_TLS_LDM_POP(31), // tag for popl in LDM TLS code
R_386_TLS_LDO_32(32), // offset relative to TLS block
R_386_TLS_IE_32(33), // got entry for static TLS block
R_386_TLS_LE_32(34), // offset relative to static TLS block
R_386_TLS_DTPMOD32(35), // ID of module containing symbol
R_386_TLS_DTPOFF32(36), // offset in TLS block
R_386_TLS_TPOFF32(37), // offset in static TLS block
R_386_TLS_GOTDESC(39), // GOT offset for TLS descriptor. */
R_386_TLS_DESC_CALL(40), // Marker of call through TLS descriptor for relaxation. */
R_386_TLS_DESC(41), // TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol. */
R_386_IRELATIVE(42); // Adjust indirectly by program base */
public final int typeId;
private X86_32_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}

View file

@ -1,119 +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 X86_64_ElfRelocationConstants {
public static final int R_X86_64_NONE = 0; /* No reloc */
/** S + A */
public static final int R_X86_64_64 = 1; /* Direct 64 bit */
/** S + A - P */
public static final int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */
/** G + P */
public static final int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */
/** L + A - P */
public static final int R_X86_64_PLT32 = 4; /* 32 bit PLT address */
/** ? */
public static final int R_X86_64_COPY = 5; /* Copy symbol at runtime */
/** S */
public static final int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */
/** S */
public static final int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */
/** B + A */
public static final int R_X86_64_RELATIVE = 8; /* Adjust by program base */
/** G + GOT + A - P */
public static final int R_X86_64_GOTPCREL = 9; /*
* 32 bit signed pc relative
* offset to GOT
*/
/** S + A */
public static final int R_X86_64_32 = 10; /* Direct 32 bit zero extended */
/** S + A */
public static final int R_X86_64_32S = 11; /* Direct 32 bit sign extended */
/** S + A */
public static final int R_X86_64_16 = 12; /* Direct 16 bit zero extended */
/** S + A - P */
public static final int R_X86_64_PC16 = 13; /*
* 16 bit sign extended pc
* relative
*/
/** S + A */
public static final int R_X86_64_8 = 14; /* Direct 8 bit sign extended */
/** S + A - P */
public static final int R_X86_64_PC8 = 15; /*
* 8 bit sign extended pc
* relative
*/
/**
* Calculates the object identifier of the
* object containing the TLS symbol.
*/
public static final int R_X86_64_DTPMOD64 = 16; // ID of module containing symbol
/**
* Calculates the offset of the variable relative
* to the start of the TLS block that contains the
* variable. The computed value is used as an
* immediate value of an addend and is not associated
* with a specific register.
*
*/
public static final int R_X86_64_DTPOFF64 = 17; // Offset in module's TLS block
public static final int R_X86_64_TPOFF64 = 18; // offset in the initial TLS block
public static final int R_X86_64_TLSGD = 19; // 32 bit signed PC relative offset to
// two GOT entries for GD symbol
public static final int R_X86_64_TLSLD = 20; // 32 bit signed PC relative offset to
// two GOT entries for LD symbol
public static final int R_X86_64_DTPOFF32 = 21; // offset in TLS block
public static final int R_X86_64_GOTTPOFF = 22; // 32 bit signed pc relative offst to
// GOT entry for IE symbol
public static final int R_X86_64_TPOFF32 = 23; // offset in initial TLS block
/** S + A - P */
public static final int R_X86_64_PC64 = 24; // PC relative 64 bit
/** S + A - GOT */
public static final int R_X86_64_GOTOFF64 = 25; // 64 bit offset to GOT
/** GOT + A + P */
public static final int R_X86_64_GOTPC32 = 26; // 32 bit signed pc relative offset to GOT
public static final int R_X86_64_GOT64 = 27; // 64 bit GOT entry offset
public static final int R_X86_64_GOTPCREL64 = 28; // 64 bit pc relative offset to GOT entry
public static final int R_X86_64_GOTPC64 = 29; // 64 bit pc relative offset to GOT
public static final int R_X86_64_GOTPLT64 = 30; //
public static final int R_X86_64_PLTOFF64 = 31; // 64 bit GOT relative offset to PLT entry
/** Z + A */
public static final int R_X86_64_SIZE32 = 32; // Size of symbol plus 32 bit addend
/** Z + A */
public static final int R_X86_64_SIZE64 = 33; // Size of symbol plus 64 bit addend
public static final int R_X86_64_GOTPC32_TLSDESC = 34; // GOT offset for TLS descriptor
public static final int R_X86_64_TLSDESC_CALL = 35; // Marker for call through TLS descriptor
public static final int R_X86_64_TLSDESC = 36; // TLS descriptor; word64 * 2
public static final int R_X86_64_IRELATIVE = 37; // Adjust indirectly by program base
public static final int R_X86_64_RELATIVE64 = 38; // 64-bit adjust by program base
public static final int R_X86_64_PC32_BND = 39; // deprecated
public static final int R_X86_64_PLT32_BND = 40; // deprecated
public static final int R_X86_64_GOTPCRELX = 41; // G + GOT + A - P
public static final int R_X86_64_REX_GOTPCRELX = 42; //G + GOT + A - P
public static final int R_X86_64_NUM = 43;
public static final int R_X86_64_GNU_VTINHERIT = 250;
public static final int R_X86_64_GNU_VTENTRY = 251;
private X86_64_ElfRelocationConstants() {
// no construct
}
}

View file

@ -31,7 +31,7 @@ import ghidra.util.exception.*;
* Global Offset Table (GOT) to facilitate GOT related relocations encountered within
* object modules.
*/
class X86_64_ElfRelocationContext extends ElfRelocationContext {
class X86_64_ElfRelocationContext extends ElfRelocationContext<X86_64_ElfRelocationHandler> {
private AddressRange allocatedGotLimits;
private Address allocatedGotAddress;
@ -116,16 +116,21 @@ class X86_64_ElfRelocationContext extends ElfRelocationContext {
private boolean requiresGotEntry(ElfRelocation r) {
switch (r.getType()) {
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL:
// case X86_64_ElfRelocationConstants.R_X86_64_GOTOFF64:
// case X86_64_ElfRelocationConstants.R_X86_64_GOTPC32:
// case X86_64_ElfRelocationConstants.R_X86_64_GOT64:
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL64:
// case X86_64_ElfRelocationConstants.R_X86_64_GOTPC64:
X86_64_ElfRelocationType type = handler.getRelocationType(r.getType());
if (type == null) {
return false;
}
switch (type) {
case R_X86_64_GOTPCREL:
// case R_X86_64_GOTOFF64:
// case R_X86_64_GOTPC32:
// case R_X86_64_GOT64:
case R_X86_64_GOTPCREL64:
// case R_X86_64_GOTPC64:
return true;
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCRELX:
case X86_64_ElfRelocationConstants.R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
// NOTE: Relocation may not actually require GOT entry in which case %got
// may be over-allocated, but is required in some cases.
return true;

View file

@ -26,7 +26,12 @@ import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
public class X86_64_ElfRelocationHandler extends
AbstractElfRelocationHandler<X86_64_ElfRelocationType, X86_64_ElfRelocationContext> {
public X86_64_ElfRelocationHandler() {
super(X86_64_ElfRelocationType.class);
}
@Override
public boolean canRelocate(ElfHeader elf) {
@ -35,7 +40,7 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public int getRelrRelocationType() {
return X86_64_ElfRelocationConstants.R_X86_64_RELATIVE;
return X86_64_ElfRelocationType.R_X86_64_RELATIVE.typeId;
}
@Override
@ -45,49 +50,29 @@ public class X86_64_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_X86_64) {
return RelocationResult.FAILURE;
}
protected RelocationResult relocate(X86_64_ElfRelocationContext elfRelocationContext,
ElfRelocation relocation, X86_64_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
X86_64_ElfRelocationContext x86RelocationContext =
(X86_64_ElfRelocationContext) elfRelocationContext;
int type = relocation.getType();
if (type == X86_64_ElfRelocationConstants.R_X86_64_NONE) {
return RelocationResult.SKIPPED;
}
int symbolIndex = relocation.getSymbolIndex();
// addend is either pulled from the relocation or the bytes in memory
long addend =
relocation.hasAddend() ? relocation.getAddend() : memory.getLong(relocationAddress);
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
long symbolSize = sym.getSize();
long offset = relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
int byteLength = 8; // most relocations affect 8-bytes (change if different)
long value;
switch (type) {
case X86_64_ElfRelocationConstants.R_X86_64_COPY:
markAsWarning(program, relocationAddress, "R_X86_64_COPY", symbolName, symbolIndex,
case R_X86_64_COPY:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Runtime copy not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_64_ElfRelocationConstants.R_X86_64_64:
case R_X86_64_64:
value = symbolValue + addend;
memory.setLong(relocationAddress, value);
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
@ -96,105 +81,92 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
applyComponentOffsetPointer(program, relocationAddress, addend);
}
break;
case X86_64_ElfRelocationConstants.R_X86_64_16:
case R_X86_64_16:
value = symbolValue + addend;
value = value & 0xffff;
memory.setShort(relocationAddress, (short) value);
byteLength = 2;
break;
case X86_64_ElfRelocationConstants.R_X86_64_8:
case R_X86_64_8:
value = symbolValue + addend;
value = value & 0xff;
memory.setByte(relocationAddress, (byte) value);
byteLength = 1;
break;
case X86_64_ElfRelocationConstants.R_X86_64_PC32:
case R_X86_64_PC32:
value = symbolValue + addend - offset;
value = value & 0xffffffff;
memory.setInt(relocationAddress, (int) value);
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_PC16:
case R_X86_64_PC16:
value = symbolValue + addend - offset;
value = value & 0xffff;
memory.setShort(relocationAddress, (short) value);
byteLength = 2;
break;
case X86_64_ElfRelocationConstants.R_X86_64_PC8:
case R_X86_64_PC8:
value = symbolValue + addend - offset;
value = value & 0xff;
memory.setByte(relocationAddress, (byte) value);
byteLength = 1;
break;
case X86_64_ElfRelocationConstants.R_X86_64_GOT32:
case R_X86_64_GOT32:
value = symbolValue + addend;
memory.setInt(relocationAddress, (int) value);
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_PLT32:
case R_X86_64_PLT32:
value = symbolValue + addend - offset;
memory.setInt(relocationAddress, (int) value);
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_GLOB_DAT:
case X86_64_ElfRelocationConstants.R_X86_64_JUMP_SLOT:
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
value = symbolValue + addend;
memory.setLong(relocationAddress, value);
break;
case X86_64_ElfRelocationConstants.R_X86_64_GOTOFF64:
case R_X86_64_GOTOFF64:
try {
long dotgot = elfRelocationContext.getGOTValue();
value = symbolValue + addend - dotgot;
memory.setLong(relocationAddress, value);
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, "R_X86_64_GOTOFF64", symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
}
break;
case X86_64_ElfRelocationConstants.R_X86_64_32: // this one complains for unsigned overflow
case X86_64_ElfRelocationConstants.R_X86_64_32S: // this one complains for signed overflow
case R_X86_64_32: // this one complains for unsigned overflow
case R_X86_64_32S: // this one complains for signed overflow
symbolValue += addend;
value = (symbolValue & 0xffffffff);
memory.setInt(relocationAddress, (int) value);
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_SIZE32:
value = symbolSize + addend;
case R_X86_64_SIZE32:
value = sym.getSize() + addend;
value = (value & 0xffffffff);
memory.setInt(relocationAddress, (int) value);
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_SIZE64:
value = symbolSize + addend;
case R_X86_64_SIZE64:
value = sym.getSize() + addend;
memory.setLong(relocationAddress, value);
break;
// Thread Local Symbol relocations (unimplemented concept)
case X86_64_ElfRelocationConstants.R_X86_64_DTPMOD64:
markAsWarning(program, relocationAddress, "R_X86_64_DTPMOD64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_64_ElfRelocationConstants.R_X86_64_DTPOFF64:
markAsWarning(program, relocationAddress, "R_X86_64_DTPOFF64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_64_ElfRelocationConstants.R_X86_64_TPOFF64:
markAsWarning(program, relocationAddress, "R_X86_64_TPOFF64", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case X86_64_ElfRelocationConstants.R_X86_64_TLSDESC:
markAsWarning(program, relocationAddress, "R_X86_64_TLSDESC", symbolName,
symbolIndex, "Thread Local Symbol relocation not supported",
elfRelocationContext.getLog());
case R_X86_64_DTPMOD64:
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
case R_X86_64_TLSDESC:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// cases which do not use symbol value
case X86_64_ElfRelocationConstants.R_X86_64_GOTPC32:
case R_X86_64_GOTPC32:
try {
long dotgot = elfRelocationContext.getGOTValue();
value = dotgot + addend - offset;
@ -202,13 +174,13 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 4;
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, "R_X86_64_GOTPC32", symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
}
break;
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCRELX:
case X86_64_ElfRelocationConstants.R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
// Check for supported Relax cases (assumes non-PIC)
// Assumes non-PIC treatment is OK and attempts
@ -262,10 +234,10 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
// If instruction not handled as relaxed instruction
// Let R_X86_64_GOTPCREL case handle as simple GOTPCREL relocation.
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL:
Address symbolGotAddress = x86RelocationContext.getGotEntryAddress(sym);
case R_X86_64_GOTPCREL:
Address symbolGotAddress = elfRelocationContext.getGotEntryAddress(sym);
if (symbolGotAddress == null) {
markAsError(program, relocationAddress, type, symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"GOT allocation failure", elfRelocationContext.getLog());
break;
}
@ -274,25 +246,25 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
byteLength = 4;
break;
case X86_64_ElfRelocationConstants.R_X86_64_GOTPCREL64:
symbolGotAddress = x86RelocationContext.getGotEntryAddress(sym);
case R_X86_64_GOTPCREL64:
symbolGotAddress = elfRelocationContext.getGotEntryAddress(sym);
if (symbolGotAddress == null) {
markAsError(program, relocationAddress, "R_X86_64_GOTPCREL64", symbolName,
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"GOT allocation failure", elfRelocationContext.getLog());
break;
}
value = symbolGotAddress.getOffset() + addend - offset;
memory.setLong(relocationAddress, value);
case X86_64_ElfRelocationConstants.R_X86_64_RELATIVE:
case R_X86_64_RELATIVE:
// word64 for LP64 and specifies word32 for ILP32,
// we assume LP64 only. We probably need a hybrid
// variant to handle the ILP32 case.
case X86_64_ElfRelocationConstants.R_X86_64_RELATIVE64:
case R_X86_64_RELATIVE64:
// dl_machine.h
// value = (Elf64_64Addr) map->l_addr + reloc->r_addend
long imageBaseAdjustment = elfRelocationContext.getImageBaseWordAdjustmentOffset();
if (elf.isPreLinked()) {
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getLong(relocationAddress) + imageBaseAdjustment;
}
@ -301,7 +273,7 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
}
memory.setLong(relocationAddress, value);
break;
case X86_64_ElfRelocationConstants.R_X86_64_IRELATIVE:
case R_X86_64_IRELATIVE:
value = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value);
break;

View file

@ -0,0 +1,91 @@
/* ###
* 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 X86_64_ElfRelocationType implements ElfRelocationType {
R_X86_64_NONE(0), // No reloc
R_X86_64_64(1), // Direct 64 bit (S + A)
R_X86_64_PC32(2), // PC relative 32 bit signed (S + A - P)
R_X86_64_GOT32(3), // 32 bit GOT entry (G + P)
R_X86_64_PLT32(4), // 32 bit PLT address (L + A - P)
R_X86_64_COPY(5), // Copy symbol at runtime
R_X86_64_GLOB_DAT(6), // Create GOT entry (S)
R_X86_64_JUMP_SLOT(7), // Create PLT entry (S)
R_X86_64_RELATIVE(8), // Adjust by program base (B + A)
R_X86_64_GOTPCREL(9), // 32 bit signed pc relative offset to GOT (G + GOT + A - P)
R_X86_64_32(10), // Direct 32 bit zero extended (S + A)
R_X86_64_32S(11), // Direct 32 bit sign extended (S + A)
R_X86_64_16(12), // Direct 16 bit zero extended (S + A)
R_X86_64_PC16(13), // 16 bit sign extended pc relative (S + A - P)
R_X86_64_8(14), // Direct 8 bit sign extended (S + A)
R_X86_64_PC8(15), // 8 bit sign extended pc relative (S + A - P)
/**
* Calculates the object identifier of the
* object containing the TLS symbol.
*/
R_X86_64_DTPMOD64(16), // ID of module containing symbol
/**
* Calculates the offset of the variable relative
* to the start of the TLS block that contains the
* variable. The computed value is used as an
* immediate value of an addend and is not associated
* with a specific register.
*/
R_X86_64_DTPOFF64(17), // Offset in module's TLS block
R_X86_64_TPOFF64(18), // offset in the initial TLS block
R_X86_64_TLSGD(19), // 32 bit signed PC relative offset to two GOT entries for GD symbol
R_X86_64_TLSLD(20), // 32 bit signed PC relative offset to two GOT entries for LD symbol
R_X86_64_DTPOFF32(21), // offset in TLS block
R_X86_64_GOTTPOFF(22), // 32 bit signed pc relative offst to GOT entry for IE symbol
R_X86_64_TPOFF32(23), // offset in initial TLS block
R_X86_64_PC64(24), // PC relative 64 bit (S + A - P)
R_X86_64_GOTOFF64(25), // 64 bit offset to GOT (S + A - GOT)
R_X86_64_GOTPC32(26), // 32 bit signed pc relative offset to GOT (GOT + A + P)
R_X86_64_GOT64(27), // 64 bit GOT entry offset
R_X86_64_GOTPCREL64(28), // 64 bit pc relative offset to GOT entry
R_X86_64_GOTPC64(29), // 64 bit pc relative offset to GOT
R_X86_64_GOTPLT64(30),
R_X86_64_PLTOFF64(31), // 64 bit GOT relative offset to PLT entry
R_X86_64_SIZE32(32), // Size of symbol plus 32 bit addend (Z + A)
R_X86_64_SIZE64(33), // Size of symbol plus 64 bit addend (Z + A)
R_X86_64_GOTPC32_TLSDESC(34), // GOT offset for TLS descriptor
R_X86_64_TLSDESC_CALL(35), // Marker for call through TLS descriptor
R_X86_64_TLSDESC(36), // TLS descriptor), word64 * 2
R_X86_64_IRELATIVE(37), // Adjust indirectly by program base
R_X86_64_RELATIVE64(38), // 64-bit adjust by program base
R_X86_64_PC32_BND(39), // deprecated
R_X86_64_PLT32_BND(40), // deprecated
R_X86_64_GOTPCRELX(41), // G + GOT + A - P
R_X86_64_REX_GOTPCRELX(42), //G + GOT + A - P
R_X86_64_NUM(43),
R_X86_64_GNU_VTINHERIT(250),
R_X86_64_GNU_VTENTRY(251);
public final int typeId;
private X86_64_ElfRelocationType(int typeId) {
this.typeId = typeId;
}
@Override
public int typeId() {
return typeId;
}
}