GP-3260 Corrected MIPS relocation issues and a few related issues affecting listing markup

This commit is contained in:
ghidra1 2023-03-27 19:10:19 -04:00
parent acb07dd535
commit 836604e09d
12 changed files with 266 additions and 235 deletions

View File

@ -472,7 +472,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
/**
* Processes the GNU version section.
* @throws CancelledException
* @throws CancelledException if load task is cancelled
*/
private void processGNU(TaskMonitor monitor) throws CancelledException {
monitor.checkCanceled();
@ -594,24 +594,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
}
/**
* Transition load segment to read-only
* @param loadedSegment loaded segment
*/
private void setReadOnlyMemory(MemoryLoadable loadedSegment) {
if (loadedSegment == null) {
return;
}
List<AddressRange> resolvedLoadAddresses = getResolvedLoadAddresses(loadedSegment);
if (resolvedLoadAddresses == null) {
log("Set read-only failed for: " + loadedSegment + " (please report this issue)");
return;
}
for (AddressRange range : resolvedLoadAddresses) {
setReadOnlyMemory(range);
}
}
/**
* Transition memory range to read-only
* @param range constrained read-only region or null for entire load segment
@ -670,7 +652,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
long entry = elf.e_entry(); // already adjusted for pre-link
if (entry != 0) {
Address entryAddr =
createEntryFunction(ElfLoader.ELF_ENTRY_FUNCTION_NAME, entry, monitor);
createEntryFunction(ElfLoader.ELF_ENTRY_FUNCTION_NAME, entry);
if (entryAddr != null) {
addElfHeaderReferenceMarkup(elf.getEntryComponentOrdinal(), entryAddr);
}
@ -703,7 +685,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
elf.adjustAddressForPrelink(dynamicTable.getDynamicValue(dynamicEntryType));
if (entryArraySizeType == null) {
// single entry addr case
createEntryFunction("_" + dynamicEntryType.name, entryAddrOffset, monitor);
createEntryFunction("_" + dynamicEntryType.name, entryAddrOffset);
return;
}
@ -748,7 +730,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
funcAddr = getDefaultAddress(funcAddrOffset);
data.addOperandReference(0, funcAddr, RefType.DATA, SourceType.ANALYSIS);
}
createEntryFunction(baseName + i, funcAddr, monitor);
createEntryFunction(baseName + i, funcAddr);
}
}
catch (NotFoundException e) {
@ -763,13 +745,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* @param name function name
* @param entryAddr function address offset (must already be adjusted for pre-linking).
* Any required image-base adjustment will be applied before converting to an Address.
* @param monitor task monitor
* @return address which corresponds to entryAddr
*/
private Address createEntryFunction(String name, long entryAddr, TaskMonitor monitor) {
private Address createEntryFunction(String name, long entryAddr) {
entryAddr += getImageBaseWordAdjustmentOffset(); // word offset
Address entryAddress = getDefaultAddressSpace().getTruncatedAddress(entryAddr, true);
createEntryFunction(name, entryAddress, monitor);
createEntryFunction(name, entryAddress);
return entryAddress;
}
@ -778,9 +759,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* Note: entries in the dynamic table appear to have any pre-link adjustment already applied.
* @param name function name
* @param entryAddress function Address
* @param monitor task monitor
*/
private void createEntryFunction(String name, Address entryAddress, TaskMonitor monitor) {
private void createEntryFunction(String name, Address entryAddress) {
// TODO: Entry may refer to a pointer - make sure we have execute permission
@ -1112,14 +1092,21 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
Address maxAddr = address.addNoWrap(length - 1);
RelocationTable relocationTable = program.getRelocationTable();
List<Relocation> relocations = relocationTable.getRelocations(address);
if (!relocations.isEmpty()) {
Msg.warn(this, "Artificial relocation at " + address +
" conflicts with a previous relocation");
boolean hasConflict = false;
for (Relocation reloc : relocations) {
if (reloc.getStatus() != Status.APPLIED_OTHER || reloc.getLength() != length) {
hasConflict = true;
break;
}
}
Address nextRelocAddr = relocationTable.getRelocationAddressAfter(address);
if (nextRelocAddr != null && nextRelocAddr.compareTo(maxAddr) <= 0) {
if (!hasConflict) {
Address nextRelocAddr = relocationTable.getRelocationAddressAfter(address);
hasConflict = nextRelocAddr != null && nextRelocAddr.compareTo(maxAddr) <= 0;
}
if (hasConflict) {
Msg.warn(this,
"Artificial relocation at " + address + " overlaps a previous relocation");
"Artificial relocation for " + address +
" conflicts with a previous relocation");
}
relocationTable.add(address, Status.APPLIED_OTHER, 0, null, length, null);
return true;
@ -1132,8 +1119,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
/**
* Add reference to previously applied header structure (assumes markupElfHeader previously called)
* @param componentName
* @param refAddr
* @param componentOrdinal structure component ordinal
* @param refAddr reference to-address
*/
private void addElfHeaderReferenceMarkup(int componentOrdinal, Address refAddr) {
@ -1355,10 +1342,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
return program.getLanguage().getDefaultDataSpace();
}
private AddressSpace getConstantSpace() {
return program.getAddressFactory().getConstantSpace();
}
private void allocateUndefinedSymbolData(HashMap<Address, Integer> dataAllocationMap) {
for (Address addr : dataAllocationMap.keySet()) {
// Create undefined data for each data/object symbol
@ -2673,8 +2656,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (dynamicType != null) {
if (dynamicType.valueType == ElfDynamicValueType.ADDRESS) {
addDynamicMemoryReference(dynamics[i], valueData, false,
"_" + dynamicType.name);
addDynamicMemoryReference(valueData, false, "_" + dynamicType.name);
}
else if (dynamicType.valueType == ElfDynamicValueType.STRING) {
ElfStringTable dynamicStringTable = elf.getDynamicStringTable();
@ -2695,17 +2677,18 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
/**
* Add memory reference to dynamic table value and return the referenced address
* Add memory reference to dynamic table scalar value and return the referenced address
* specified by the value
* @param elfDynamic
* @param valueData
* @param definedMemoryOnly
* @param label
* @return referenced address specified by the value
* @throws InvalidInputException
* @param valueData defined {@link Data} within the dynamic table whose operand value should
* be treated as an address offset and to which a memory reference should be applied.
* @param definedMemoryOnly if true derived reference to-address must exist within a defined
* memory block.
* @param label optional label to be applied at reference to-address (may be null)
* @return referenced to-address specified by the value
* @throws InvalidInputException if an invalid label name is specified
*/
private Address addDynamicMemoryReference(ElfDynamic elfDynamic, Data valueData,
boolean definedMemoryOnly, String label) throws InvalidInputException {
private Address addDynamicMemoryReference(Data valueData, boolean definedMemoryOnly,
String label) throws InvalidInputException {
Scalar value = valueData.getScalar(0);
if (value == null || value.getUnsignedValue() == 0) {
return null;
@ -2836,7 +2819,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* While this method can produce the intended load address, there is no guarantee that
* the segment data did not get bumped into an overlay area due to a conflict with
* another segment or section.
* @param elfProgramHeader
* @param elfProgramHeader ELF program header
* @return segment load address
*/
private Address getSegmentLoadAddress(ElfProgramHeader elfProgramHeader) {
@ -2854,7 +2837,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* Determine preferred section load address address space prior to load.
* Non-allocated sections may return the OTHER space or an existing OTHER
* overlay established by a program header.
* @param elfSectionHeader
* @param elfSectionHeader ELF section header
* @return section load address space
*/
private AddressSpace getSectionAddressSpace(ElfSectionHeader elfSectionHeader) {
@ -2878,7 +2861,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
/**
* Determine section's load address.
* @param elfSectionHeader
* @param elfSectionHeader ELF section header
* @return section load address
*/
private Address getSectionLoadAddress(ElfSectionHeader elfSectionHeader) {
@ -3015,8 +2998,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* Expand/create PT_LOAD program header block regions which are zeroed
* - to the extent possible. This should only be done when section headers are
* not present.
* @param monitor
* @throws CancelledException
* @param monitor load task monitor
* @throws CancelledException if load task is cancelled
*/
private void expandProgramHeaderBlocks(TaskMonitor monitor) throws CancelledException {
@ -3583,7 +3566,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
* @param fileOffset byte provider offset
* @param dataLength the in-memory data length in bytes (actual bytes read from dataInput may be more)
* @return input stream for loading memory block
* @throws IOException
* @throws IOException if failed to obtain input stream
*/
private InputStream getInitializedBlockInputStream(MemoryLoadable loadable, Address start,
long fileOffset, long dataLength) throws IOException {

View File

@ -1202,10 +1202,9 @@ public class CodeUnitFormat {
long offset = offsetRef.getOffset();
String sign = "+";
if (offset < 0) {
offset = -offset;
sign = "-";
sign = ""; // sign provided by Scalar.toString()
}
Scalar offsetScalar = new Scalar(64, offsetRef.getOffset(), true);
Scalar offsetScalar = new Scalar(64, offset, true);
OperandRepresentationList list = new OperandRepresentationList();
list.add(baseRefObj);
list.add(sign);

View File

@ -2477,7 +2477,8 @@ public class SymbolicPropogator {
}
private int createData(Address address, int size) {
if (!program.getListing().isUndefined(address, address)) {
if (program.getMemory().isExternalBlockAddress(address) ||
!program.getListing().isUndefined(address, address)) {
return 0;
}

View File

@ -162,7 +162,9 @@ public abstract class DecompilerReference {
int n = parent.getLength();
if (offset >= 0 && offset < n) {
DataTypeComponent dtc = parent.getComponentContaining(field.getOffset());
fieldDt = dtc.getDataType();
if (dtc != null) {
return dtc.getDataType();
}
}
}
return fieldDt;

View File

@ -18,6 +18,7 @@ package ghidra.program.database.references;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
import ghidra.util.NumericUtilities;
class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
@ -58,7 +59,8 @@ class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
@Override
public String toString() {
return super.toString() + " Offset: 0x" + Long.toHexString(offsetOrShift);
String offsetStr = NumericUtilities.toSignedHexString(offsetOrShift);
return super.toString() + " Offset: " + offsetStr;
}
}

View File

@ -114,7 +114,12 @@ public class ComponentOffsetSettingsDefinition
public String getAttributeSpecification(Settings settings) {
if (hasValue(settings)) {
long offset = getValue(settings);
return "offset(0x" + Long.toHexString(offset) + ")";
String sign = "";
if (offset < 0) {
offset = -offset;
sign = "-";
}
return "offset(" + sign + "0x" + Long.toHexString(offset) + ")";
}
return null;
}

View File

@ -184,6 +184,16 @@ public class Relocation {
return bytes;
}
/**
* Returns the number of original instruction bytes affected by applied relocation.
*
* @return number of original instruction bytes affected by relocation if it was successfully applied
* (i.e., {@link Status#APPLIED}, {@link Status#APPLIED_OTHER}), otherwise null may be returned.
*/
public int getLength() {
return bytes != null ? bytes.length : 0;
}
/**
* The name of the symbol being relocated or <code>null</code> if there is no symbol name.
*

View File

@ -16,6 +16,7 @@
package ghidra.app.util.bin.format.elf.extend;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang3.StringUtils;
@ -460,7 +461,7 @@ public class MIPS_ElfExtension extends ElfExtension {
setTableEntryIfZero(gotBaseAddress, gotIndex, symbolOffset, elfLoadHelper);
}
catch (MemoryAccessException | AddressOverflowException e) {
catch (MemoryAccessException e) {
Msg.error(this, "Failed to update .got table entry", e);
}
catch (NotFoundException e) {
@ -682,6 +683,14 @@ public class MIPS_ElfExtension extends ElfExtension {
// NOTES: assumes only one gp0 value
AtomicBoolean multipleGp0 = new AtomicBoolean(false);
Symbol gp0Sym = SymbolUtilities.getLabelOrFunctionSymbol(elfLoadHelper.getProgram(),
MIPS_GP0_VALUE_SYMBOL, msg -> multipleGp0.set(true));
Long otherGp0Value = gp0Sym != null ? gp0Sym.getAddress().getOffset() : null;
AddressSpace defaultSpace =
elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace();
boolean is64bit = elfLoadHelper.getElfHeader().is64Bit();
Structure regInfoStruct = buildRegInfoStructure(is64bit);
@ -692,8 +701,15 @@ public class MIPS_ElfExtension extends ElfExtension {
// Create gp0 symbol in default space which represents a constant value (pinned)
Scalar gp0Value = gpValueComponent.getScalar(0);
long gp0 = gp0Value.getUnsignedValue();
AddressSpace defaultSpace =
elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace();
if (multipleGp0.get() || otherGp0Value != null) {
if (multipleGp0.get() || gp0 != otherGp0Value) {
elfLoadHelper.log(
"Multiple gp0 values defined (not supported): 0x" +
Long.toHexString(gp0));
}
return;
}
Address gpAddr = defaultSpace.getAddress(gp0);
elfLoadHelper.createSymbol(gpAddr, MIPS_GP0_VALUE_SYMBOL, false, false,
null).setPinned(true);
@ -870,9 +886,10 @@ public class MIPS_ElfExtension extends ElfExtension {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
if (adjustment != 0) {
long offset = memory.getLong(tableEntryAddr);
if (offset != 0) {
long newValue = offset + adjustment;
if (offset != 0 && offset != newValue) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 8);
memory.setLong(tableEntryAddr, offset + adjustment);
memory.setLong(tableEntryAddr, newValue);
}
}
}
@ -880,9 +897,10 @@ public class MIPS_ElfExtension extends ElfExtension {
tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
if (adjustment != 0) {
int offset = memory.getInt(tableEntryAddr);
if (offset != 0) {
int newValue = (int) (offset + adjustment);
if (offset != 0 && offset != newValue) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 4);
memory.setInt(tableEntryAddr, (int) (offset + adjustment));
memory.setInt(tableEntryAddr, newValue);
}
}
}
@ -890,14 +908,14 @@ public class MIPS_ElfExtension extends ElfExtension {
}
private Address setTableEntryIfZero(Address tableBaseAddr, int entryIndex, long value,
ElfLoadHelper elfLoadHelper) throws MemoryAccessException, AddressOverflowException {
ElfLoadHelper elfLoadHelper) throws MemoryAccessException {
boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit();
Memory memory = elfLoadHelper.getProgram().getMemory();
Address tableEntryAddr;
if (is64Bit) {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
long offset = memory.getLong(tableEntryAddr);
if (offset == 0) {
if (offset == 0 && value != 0) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 8);
memory.setLong(tableEntryAddr, value);
}
@ -905,7 +923,7 @@ public class MIPS_ElfExtension extends ElfExtension {
else {
tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
int offset = memory.getInt(tableEntryAddr);
if (offset == 0) {
if (offset == 0 && value != 0) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 4);
memory.setInt(tableEntryAddr, (int) value);
}

View File

@ -63,7 +63,8 @@ public class MIPS_Elf64Relocation extends ElfRelocation {
}
/**
* Return the special symbol index associated with this relocation
* Return the special symbol index associated with this relocation. This symbol
* may be used by the 2nd relocation of a compound relocations.
* @return special symbol index (r_ssym)
*/
public int getSpecialSymbolIndex() {

View File

@ -75,6 +75,14 @@ public class MIPS_ElfRelocationConstants {
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;
@ -144,6 +152,7 @@ public class MIPS_ElfRelocationConstants {
// 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

@ -51,6 +51,7 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
boolean savedAddendHasError = false;
long savedAddend;
ElfSymbol lastElfSymbol;
Address lastSymbolAddr;
MIPS_ElfRelocationContext(MIPS_ElfRelocationHandler handler, ElfLoadHelper loadHelper,
@ -82,6 +83,7 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext {
useSavedAddend = false;
savedAddendHasError = false;
lastSymbolAddr = null;
lastElfSymbol = null;
super.endRelocationTableProcessing();
}

View File

@ -15,19 +15,19 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import java.util.*;
import java.util.Iterator;
import java.util.Map;
import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.extend.MIPS_ElfExtension;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOutOfBoundsException;
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.*;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.NotFoundException;
public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
@ -47,8 +47,8 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfRelocation relocation, Address relocationAddress)
throws MemoryAccessException {
ElfHeader elf = elfRelocationContext.getElfHeader();
@ -59,6 +59,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
MIPS_ElfRelocationContext mipsRelocationContext =
(MIPS_ElfRelocationContext) elfRelocationContext;
mipsRelocationContext.lastSymbolAddr = null;
mipsRelocationContext.lastElfSymbol = null;
int type = relocation.getType();
int symbolIndex = relocation.getSymbolIndex();
@ -68,17 +69,30 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
RelocationResult lastResult = RelocationResult.FAILURE;
if (elf.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 == 0) {
symbolIndex = mips64Relocation.getSymbolIndex();
}
else if (n == 1) {
symbolIndex = mips64Relocation.getSpecialSymbolIndex();
}
else {
symbolIndex = 0;
}
int relocType = type & 0xff;
type >>= 8;
int nextRelocType =
(n < 2) ? (type & 0xff) : MIPS_ElfRelocationConstants.R_MIPS_NONE;
RelocationResult result = doRelocate(mipsRelocationContext, relocType, symbolIndex,
relocation,
relocationAddress, nextRelocType != MIPS_ElfRelocationConstants.R_MIPS_NONE ||
mips64Relocation, relocationAddress,
nextRelocType != MIPS_ElfRelocationConstants.R_MIPS_NONE ||
saveValueForNextReloc);
if (result.status() == Status.FAILURE || result.status() == Status.UNSUPPORTED) {
return result;
@ -102,19 +116,17 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
* Perform MIPS ELF relocation
* @param mipsRelocationContext MIPS ELF relocation context
* @param relocType relocation type (unpacked from relocation r_info)
* @param relocation
* @param relocation relocation record to be processed (may be compound for 64-bit)
* @param relocationAddress address at which relocation is applied (i.e., relocation offset)
* @param saveValue true if result value should be stored in mipsRelocationContext.savedAddend
* and mipsRelocationContext.useSavedAddend set true. If false, result value should be written
* to relocationAddress per relocation type.
* @return applied relocation result
* @throws MemoryAccessException
* @throws NotFoundException
* @throws MemoryAccessException memory access error occured
*/
private RelocationResult doRelocate(MIPS_ElfRelocationContext mipsRelocationContext,
int relocType,
int symbolIndex, ElfRelocation relocation, Address relocationAddress, boolean saveValue)
throws MemoryAccessException, NotFoundException, AddressOutOfBoundsException {
int relocType, int symbolIndex, ElfRelocation relocation, Address relocationAddress,
boolean saveValue) throws MemoryAccessException, AddressOutOfBoundsException {
if (relocType == MIPS_ElfRelocationConstants.R_MIPS_NONE) {
return RelocationResult.SKIPPED;
@ -137,6 +149,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (symbolIndex != 0) {
mipsRelocationContext.lastSymbolAddr = symbolAddr;
mipsRelocationContext.lastElfSymbol = elfSymbol;
}
long addend = 0;
@ -184,10 +197,14 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
int oldValue =
unshuffle(memory.getInt(relocationAddress), relocType, mipsRelocationContext);
int value = 0; // computed value which will be used as savedAddend if needed
int newValue = 0; // value blended with oldValue as appropriate for relocation
long oldValue = Integer.toUnsignedLong(
unshuffle(memory.getInt(relocationAddress), relocType, mipsRelocationContext));
// Intermediate results are retained as long values so they may be used with 64-bit
// compound relocation processing
long value = 0; // computed value which will be used as savedAddend if needed
long newValue = 0; // value blended with oldValue as appropriate for relocation
boolean writeNewValue = false;
Status status = Status.PARTIAL;
@ -202,7 +219,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
}
long pageOffset = (symbolValue + addend + 0x8000) & ~0xffff;
value = (int) (symbolValue + addend - pageOffset);
value = symbolValue + addend - pageOffset;
newValue = (oldValue & ~0xffff) | (value & 0xffff);
writeNewValue = true;
@ -229,7 +246,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
value = (int) getGpOffset(mipsRelocationContext, gotAddr.getOffset());
value = getGpOffset(mipsRelocationContext, gotAddr.getOffset());
if (value == -1) {
// Unhandled GOT/GP case
markAsError(mipsRelocationContext.getProgram(), relocationAddress,
@ -263,7 +280,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
}
// use address offset within section GOT as symbol value
value = (int) getGpOffset(mipsRelocationContext, gotAddr.getOffset());
value = getGpOffset(mipsRelocationContext, gotAddr.getOffset());
if (value == -1) {
// Unhandled GOT/GP case
markAsError(mipsRelocationContext.getProgram(), relocationAddress,
@ -275,7 +292,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
int appliedValue;
long appliedValue;
if (relocType == MIPS_ElfRelocationConstants.R_MIPS_GOT_DISP) {
appliedValue = value & 0xffff;
}
@ -294,7 +311,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (elfSymbol.isLocal()) {
// Defer processing of local GOT16 relocations until suitable LO16 relocation is processed
MIPS_DeferredRelocation got16reloc = new MIPS_DeferredRelocation(relocType,
elfSymbol, relocationAddress, oldValue, (int) addend, isGpDisp);
elfSymbol, relocationAddress, oldValue, addend, isGpDisp);
mipsRelocationContext.addGOT16Relocation(got16reloc);
break; // report as 4-byte applied even though it is deferred (could still fail)
}
@ -317,7 +334,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
value = (int) getGpOffset(mipsRelocationContext, gotAddr.getOffset());
value = getGpOffset(mipsRelocationContext, gotAddr.getOffset());
if (value == -1) {
// Unhandled GOT/GP case
markAsError(mipsRelocationContext.getProgram(), relocationAddress,
@ -348,7 +365,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
value = (int) getGpOffset(mipsRelocationContext, gotAddr.getOffset());
value = getGpOffset(mipsRelocationContext, gotAddr.getOffset());
if (value == -1) {
// Unhandled GOT/GP case
markAsError(mipsRelocationContext.getProgram(), relocationAddress,
@ -395,7 +412,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
processGOT16Relocations(mipsRelocationContext, relocType, elfSymbol, (int) addend);
if (isGpDisp) {
value = (int) mipsRelocationContext.getGPValue();
value = mipsRelocationContext.getGPValue();
if (value == -1) {
markAsError(program, relocationAddress, Integer.toString(relocType),
symbolName, "Failed to perform GP-based relocation",
@ -422,43 +439,48 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
break;
case MIPS_ElfRelocationConstants.R_MIPS_REL32:
// TODO: unsure if reloc valid for symbolIndex != 0
if (symbolIndex == 0) {
symbolValue = mipsRelocationContext.getImageBaseWordAdjustmentOffset();
}
case MIPS_ElfRelocationConstants.R_MIPS_32:
value = (int) symbolValue;
int intAddend;
value = symbolValue;
if (mipsRelocationContext.extractAddend()) {
intAddend = elf.is64Bit() ? (int) memory.getLong(relocationAddress)
// extract addend based upon pointer size
addend = elf.is64Bit() ? (int) memory.getLong(relocationAddress)
: memory.getInt(relocationAddress);
}
else {
intAddend = (int) addend;
}
newValue = value + intAddend;
long newValueBig = Integer.toUnsignedLong(newValue);
newValue = value + addend;
if (saveValue) {
mipsRelocationContext.savedAddend = newValueBig;
mipsRelocationContext.savedAddend = newValue;
}
else {
if (elf.is64Bit()) {
memory.setLong(relocationAddress, newValueBig);
byteLength = 8;
}
else {
memory.setInt(relocationAddress, newValue);
byteLength = 4;
}
if (symbolIndex != 0 && intAddend != 0 && !saveValue) {
// If not continuing with compound relocation (64-bit only)
// perform fixup so we can create offset-pointer now.
memory.setInt(relocationAddress, (int) newValue);
status = Status.APPLIED;
// Handle possible offset-pointer use
if (symbolIndex != 0 && addend != 0 && elfSymbol.isGlobal()) {
// create offset-pointer and resulting offset-reference
warnExternalOffsetRelocation(program, relocationAddress,
symbolAddr, symbolName, intAddend, mipsRelocationContext.getLog());
applyComponentOffsetPointer(program, relocationAddress, intAddend);
symbolAddr, symbolName, addend, mipsRelocationContext.getLog());
applyComponentOffsetPointer(program, relocationAddress, addend);
}
}
break;
case MIPS_ElfRelocationConstants.R_MIPS_32: /* In Elf 64: alias R_MIPS_ADD */
value = symbolValue;
if (mipsRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue = value + addend;
if (saveValue) {
mipsRelocationContext.savedAddend = newValue;
}
else {
memory.setInt(relocationAddress, (int) newValue);
status = Status.APPLIED;
}
break;
@ -474,20 +496,44 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
addend = signExtend((int) addend, 26 + shift);
}
// TODO: cross-mode jump detection/handling is unsupported
value = (int) (addend + symbolValue) >> shift;
value = (addend + symbolValue) >> shift;
newValue = (oldValue & ~MIPS_ElfRelocationConstants.MIPS_LOW26) |
(value & MIPS_ElfRelocationConstants.MIPS_LOW26);
writeNewValue = true;
break;
case MIPS_ElfRelocationConstants.R_MIPS_PC21_S2:
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & MIPS_ElfRelocationConstants.MIPS_LOW21) << 2;
}
if (!elfSymbol.isLocal() && !elfSymbol.isSection()) {
addend = signExtend((int) addend, 21 + 2);
}
value = (addend + symbolValue - offset) >> 2;
newValue = (oldValue & ~MIPS_ElfRelocationConstants.MIPS_LOW21) |
(value & MIPS_ElfRelocationConstants.MIPS_LOW21);
writeNewValue = true;
break;
case MIPS_ElfRelocationConstants.R_MIPS_PC26_S2:
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & MIPS_ElfRelocationConstants.MIPS_LOW26) << 2;
}
if (!elfSymbol.isLocal() && !elfSymbol.isSection()) {
addend = signExtend((int) addend, 26 + 2);
}
value = (addend + symbolValue - offset) >> 2;
newValue = (oldValue & ~MIPS_ElfRelocationConstants.MIPS_LOW26) |
(value & MIPS_ElfRelocationConstants.MIPS_LOW26);
writeNewValue = true;
break;
case MIPS_ElfRelocationConstants.R_MIPS_PC16:
newValue =
mipsRelocationContext.extractAddend() ? (oldValue & 0xffff) << 2 : (int) addend;
newValueBig = signExtend(newValue, 18);
newValueBig += symbolValue - offset;
value = (int) newValueBig;
newValue = (oldValue & ~0xffff) | ((int) (newValueBig >> 2) & 0xffff);
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & 0xffff) << 2;
}
value = symbolValue - offset + signExtend((int) addend, 18);
newValue = (oldValue & ~0xffff) | ((value >> 2) & 0xffff);
writeNewValue = true;
break;
@ -495,25 +541,31 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (mipsRelocationContext.extractAddend()) {
addend = memory.getLong(relocationAddress);
}
// NOTE: provisions may be needed for sign-extending a 32-bit value
newValueBig = symbolValue + addend;
newValue = symbolValue + addend;
if (saveValue) {
mipsRelocationContext.savedAddend = newValueBig;
mipsRelocationContext.savedAddend = newValue;
}
else {
memory.setLong(relocationAddress, newValueBig);
memory.setLong(relocationAddress, newValue);
byteLength = 8;
status = Status.APPLIED;
Address addr =
symbolIndex == 0 ? mipsRelocationContext.lastSymbolAddr : symbolAddr;
if (addr != null && addend != 0) {
// Handle possible offset-pointer use
boolean isGlobal = elfSymbol.isGlobal();
Address addr = symbolAddr;
if (symbolIndex == 0 && mipsRelocationContext.lastSymbolAddr != null) {
// handle compound mips64 relocation
addr = mipsRelocationContext.lastSymbolAddr;
symbolName = mipsRelocationContext.lastElfSymbol.getNameAsString();
isGlobal = mipsRelocationContext.lastElfSymbol.isGlobal();
}
if (addr != null && isGlobal) {
if (symbolIndex == 0) {
// compute addend used with compound relocation and lastSymbolAddr
addend -= addr.getOffset();
}
if (addend != 0) {
// If not continuing with compound relocation perform fixup so
// we can create offset-pointer now.
// NOTE: this may not handle all combound relocation cases
// create offset-pointer and resulting offset-reference
warnExternalOffsetRelocation(program, relocationAddress,
addr, symbolName, addend, mipsRelocationContext.getLog());
if (elf.is64Bit()) {
@ -526,83 +578,33 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
case MIPS_ElfRelocationConstants.R_MIPS_HIGHER:
case MIPS_ElfRelocationConstants.R_MICROMIPS_HIGHER:
newValueBig = (mipsRelocationContext.extractAddend() ? oldValue : addend) & 0xffff;
newValueBig += symbolValue + 0x080008000L;
value = (int) ((newValueBig >> 32) & 0xffff);
if (mipsRelocationContext.extractAddend()) {
addend = oldValue;
}
addend &= 0xffff;
value = symbolValue + 0x080008000L + addend;
value = (value >> 32) & 0xffff;
newValue = (oldValue & ~0xffff) | value;
writeNewValue = true;
break;
case MIPS_ElfRelocationConstants.R_MIPS_HIGHEST:
case MIPS_ElfRelocationConstants.R_MICROMIPS_HIGHEST:
newValueBig = (mipsRelocationContext.extractAddend() ? oldValue : addend) & 0xffff;
newValueBig += symbolValue + 0x0800080008000L;
value = (int) ((newValueBig >> 48) & 0xffff);
if (mipsRelocationContext.extractAddend()) {
addend = oldValue;
}
addend &= 0xffff;
value = symbolValue + 0x080008000L + addend;
value = (value >> 48) & 0xffff;
newValue = (oldValue & ~0xffff) | value;
writeNewValue = true;
break;
// case MIPS_ElfRelocationConstants.R_MIPS_TLS_TPREL32:
// if (mipsRelocationContext.extractAddend()) {
// addend = oldValue;
// }
// value = (int) ((symbolValue + addend) - TP_OFFSET);
//
// newValue = value;
// writeNewValue = true;
// break;
//
// case MIPS_ElfRelocationConstants.R_MIPS_TLS_TPREL64:
// if (mipsRelocationContext.extractAddend()) {
// addend = oldValue;
// }
// newValueBig = symbolValue + addend - TP_OFFSET;
//
// if (saveValue) {
// mipsRelocationContext.savedAddend = newValueBig;
// }
// else {
// memory.setLong(relocationAddress, newValueBig);
// byteLength = 8;
// status = Status.APPLIED;
// }
// break;
//
// case MIPS_ElfRelocationConstants.R_MIPS_TLS_DTPREL32:
// if (mipsRelocationContext.extractAddend()) {
// addend = oldValue;
// }
// value = (int) ((symbolValue + addend) - DTP_OFFSET);
//
// newValue = value;
// writeNewValue = true;
// break;
//
//
// case MIPS_ElfRelocationConstants.R_MIPS_TLS_DTPREL64:
// if (mipsRelocationContext.extractAddend()) {
// addend = oldValue;
// }
// newValueBig = symbolValue + addend - DTP_OFFSET;
//
// if (saveValue) {
// mipsRelocationContext.savedAddend = newValueBig;
// }
// else {
// memory.setLong(relocationAddress, newValueBig);
// byteLength = 8;
// status = Status.APPLIED;
// }
// break;
case MIPS_ElfRelocationConstants.R_MICROMIPS_PC7_S1:
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & 0x7f0000) >> 15;
}
value = (int) (((symbolValue + addend) - offset) >> 1) & 0x7f;
value = (((symbolValue + addend) - offset) >> 1) & 0x7f;
newValue = (oldValue & ~0x7f0000) | (value << 16);
writeNewValue = true;
break;
@ -611,8 +613,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & 0x3ff0000) >> 15;
}
value = (int) (((symbolValue + addend) - offset) >> 1) & 0x3ff;
value = (((symbolValue + addend) - offset) >> 1) & 0x3ff;
newValue = (oldValue & ~0x3ff0000) | (value << 16);
writeNewValue = true;
break;
@ -621,8 +622,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (mipsRelocationContext.extractAddend()) {
addend = (oldValue & 0xffff) << 1;
}
value = (int) (((symbolValue + addend) - offset) >> 1) & 0xffff;
value = (((symbolValue + addend) - offset) >> 1) & 0xffff;
newValue = (oldValue & ~0xffff) | value;
writeNewValue = true;
break;
@ -678,12 +678,11 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return RelocationResult.FAILURE;
}
value = (int) (symbolValue + addend - gp + gp0);
value = (symbolValue + addend - gp + gp0);
int mask =
relocType == MIPS_ElfRelocationConstants.R_MIPS_GPREL32 ? 0xffffffff : 0xffff;
long mask =
relocType == MIPS_ElfRelocationConstants.R_MIPS_GPREL32 ? 0xffffffffL : 0xffff;
newValue = (oldValue & ~mask) | (value & mask);
writeNewValue = true;
break;
@ -692,13 +691,13 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
if (mipsRelocationContext.extractAddend()) {
addend = oldValue;
}
newValueBig = symbolValue - addend;
newValue = symbolValue - addend;
if (saveValue) {
mipsRelocationContext.savedAddend = newValueBig;
mipsRelocationContext.savedAddend = newValue;
}
else {
memory.setLong(relocationAddress, newValueBig);
memory.setLong(relocationAddress, newValue);
byteLength = 8;
status = Status.APPLIED;
}
@ -796,7 +795,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
// Each relocation which sets writeNewValue must establish a 32-bit newValue
// to be written to relocationAddress.
memory.setInt(relocationAddress,
shuffle(newValue, relocType, mipsRelocationContext));
shuffle((int) newValue, relocType, mipsRelocationContext));
status = Status.APPLIED;
}
}
@ -937,9 +936,9 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
* @return true if successful or false if unsupported
*/
private void processHI16Relocation(MIPS_ElfRelocationContext mipsRelocationContext,
MIPS_DeferredRelocation hi16reloc, int lo16Addend) {
MIPS_DeferredRelocation hi16reloc, long lo16Addend) {
int newValue;
long newValue;
if (hi16reloc.isGpDisp) {
newValue = (int) mipsRelocationContext.getGPValue();
@ -960,20 +959,20 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
newValue = (int) mipsRelocationContext.getSymbolValue(hi16reloc.elfSymbol);
}
// FIXME: should always use hi16reloc.addend - figure out at time of deferral
int addend;
long addend;
if (mipsRelocationContext.extractAddend()) {
addend = ((hi16reloc.oldValue & 0xffff) << 16) + lo16Addend;
addend = ((hi16reloc.oldValueL & 0xffff) << 16) + lo16Addend;
}
else {
addend = hi16reloc.addend;
addend = hi16reloc.addendL;
}
newValue = (newValue + addend + 0x8000) >> 16;
newValue = (hi16reloc.oldValue & ~0xffff) | (newValue & 0xffff);
newValue = (hi16reloc.oldValueL & ~0xffff) | (newValue & 0xffff);
Memory memory = mipsRelocationContext.getProgram().getMemory();
try {
memory.setInt(hi16reloc.relocAddr,
shuffle(newValue, hi16reloc.relocType, mipsRelocationContext));
shuffle((int) newValue, hi16reloc.relocType, mipsRelocationContext));
}
catch (MemoryAccessException e) {
// Unexpected since we did a previous getInt without failure
@ -1011,14 +1010,14 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
* @return true if successful or false if unsupported
*/
private void processGOT16Relocation(MIPS_ElfRelocationContext mipsRelocationContext,
MIPS_DeferredRelocation got16reloc, int lo16Addend) {
MIPS_DeferredRelocation got16reloc, long lo16Addend) {
long addend;
if (mipsRelocationContext.extractAddend()) {
addend = ((got16reloc.oldValue & 0xffff) << 16) + lo16Addend;
addend = ((got16reloc.oldValueL & 0xffff) << 16) + lo16Addend;
}
else {
addend = got16reloc.addend;
addend = got16reloc.addendL;
}
long symbolValue = (int) mipsRelocationContext.getSymbolValue(got16reloc.elfSymbol);
@ -1047,12 +1046,12 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
return;
}
int newValue = (got16reloc.oldValue & ~0xffff) | ((int) value & 0xffff);
long newValue = (got16reloc.oldValueL & ~0xffff) | ((int) value & 0xffff);
Memory memory = mipsRelocationContext.getProgram().getMemory();
try {
memory.setInt(got16reloc.relocAddr,
shuffle(newValue, got16reloc.relocType, mipsRelocationContext));
shuffle((int) newValue, got16reloc.relocType, mipsRelocationContext));
}
catch (MemoryAccessException e) {
// Unexpected since we did a previous getInt without failure
@ -1079,17 +1078,17 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
final int relocType;
final ElfSymbol elfSymbol;
final Address relocAddr;
final int oldValue;
final int addend;
final long oldValueL;
final long addendL;
final boolean isGpDisp;
MIPS_DeferredRelocation(int relocType, ElfSymbol elfSymbol, Address relocAddr, int oldValue,
int addend, boolean isGpDisp) {
MIPS_DeferredRelocation(int relocType, ElfSymbol elfSymbol, Address relocAddr,
long oldValue, long addend, boolean isGpDisp) {
this.relocType = relocType;
this.elfSymbol = elfSymbol;
this.relocAddr = relocAddr;
this.oldValue = oldValue;
this.addend = addend;
this.oldValueL = oldValue;
this.addendL = addend;
this.isGpDisp = isGpDisp;
}