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

View file

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

View file

@ -2477,7 +2477,8 @@ public class SymbolicPropogator {
} }
private int createData(Address address, int size) { 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; return 0;
} }

View file

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

View file

@ -18,6 +18,7 @@ package ghidra.program.database.references;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.NumericUtilities;
class OffsetReferenceDB extends MemReferenceDB implements OffsetReference { class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
@ -58,7 +59,8 @@ class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
@Override @Override
public String toString() { 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) { public String getAttributeSpecification(Settings settings) {
if (hasValue(settings)) { if (hasValue(settings)) {
long offset = getValue(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; return null;
} }

View file

@ -184,6 +184,16 @@ public class Relocation {
return bytes; 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. * 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; package ghidra.app.util.bin.format.elf.extend;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -460,7 +461,7 @@ public class MIPS_ElfExtension extends ElfExtension {
setTableEntryIfZero(gotBaseAddress, gotIndex, symbolOffset, elfLoadHelper); setTableEntryIfZero(gotBaseAddress, gotIndex, symbolOffset, elfLoadHelper);
} }
catch (MemoryAccessException | AddressOverflowException e) { catch (MemoryAccessException e) {
Msg.error(this, "Failed to update .got table entry", e); Msg.error(this, "Failed to update .got table entry", e);
} }
catch (NotFoundException e) { catch (NotFoundException e) {
@ -682,6 +683,14 @@ public class MIPS_ElfExtension extends ElfExtension {
// NOTES: assumes only one gp0 value // 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(); boolean is64bit = elfLoadHelper.getElfHeader().is64Bit();
Structure regInfoStruct = buildRegInfoStructure(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) // Create gp0 symbol in default space which represents a constant value (pinned)
Scalar gp0Value = gpValueComponent.getScalar(0); Scalar gp0Value = gpValueComponent.getScalar(0);
long gp0 = gp0Value.getUnsignedValue(); long gp0 = gp0Value.getUnsignedValue();
AddressSpace defaultSpace = if (multipleGp0.get() || otherGp0Value != null) {
elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace(); if (multipleGp0.get() || gp0 != otherGp0Value) {
elfLoadHelper.log(
"Multiple gp0 values defined (not supported): 0x" +
Long.toHexString(gp0));
}
return;
}
Address gpAddr = defaultSpace.getAddress(gp0); Address gpAddr = defaultSpace.getAddress(gp0);
elfLoadHelper.createSymbol(gpAddr, MIPS_GP0_VALUE_SYMBOL, false, false, elfLoadHelper.createSymbol(gpAddr, MIPS_GP0_VALUE_SYMBOL, false, false,
null).setPinned(true); null).setPinned(true);
@ -870,9 +886,10 @@ public class MIPS_ElfExtension extends ElfExtension {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8); tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
if (adjustment != 0) { if (adjustment != 0) {
long offset = memory.getLong(tableEntryAddr); long offset = memory.getLong(tableEntryAddr);
if (offset != 0) { long newValue = offset + adjustment;
if (offset != 0 && offset != newValue) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 8); 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); tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
if (adjustment != 0) { if (adjustment != 0) {
int offset = memory.getInt(tableEntryAddr); int offset = memory.getInt(tableEntryAddr);
if (offset != 0) { int newValue = (int) (offset + adjustment);
if (offset != 0 && offset != newValue) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 4); 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, private Address setTableEntryIfZero(Address tableBaseAddr, int entryIndex, long value,
ElfLoadHelper elfLoadHelper) throws MemoryAccessException, AddressOverflowException { ElfLoadHelper elfLoadHelper) throws MemoryAccessException {
boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit(); boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit();
Memory memory = elfLoadHelper.getProgram().getMemory(); Memory memory = elfLoadHelper.getProgram().getMemory();
Address tableEntryAddr; Address tableEntryAddr;
if (is64Bit) { if (is64Bit) {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8); tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
long offset = memory.getLong(tableEntryAddr); long offset = memory.getLong(tableEntryAddr);
if (offset == 0) { if (offset == 0 && value != 0) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 8); elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 8);
memory.setLong(tableEntryAddr, value); memory.setLong(tableEntryAddr, value);
} }
@ -905,7 +923,7 @@ public class MIPS_ElfExtension extends ElfExtension {
else { else {
tableEntryAddr = tableBaseAddr.add(entryIndex * 4); tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
int offset = memory.getInt(tableEntryAddr); int offset = memory.getInt(tableEntryAddr);
if (offset == 0) { if (offset == 0 && value != 0) {
elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 4); elfLoadHelper.addArtificialRelocTableEntry(tableEntryAddr, 4);
memory.setInt(tableEntryAddr, (int) value); 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) * @return special symbol index (r_ssym)
*/ */
public int getSpecialSymbolIndex() { 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_TLS_TPREL_LO16 = 50;
public static final int R_MIPS_GLOB_DAT = 51; 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. */ /* These relocs are used for the mips16. */
public static final int R_MIPS16_26 = 100; public static final int R_MIPS16_26 = 100;
public static final int R_MIPS16_GPREL = 101; public static final int R_MIPS16_GPREL = 101;
@ -144,6 +152,7 @@ public class MIPS_ElfRelocationConstants {
// Masks for manipulating MIPS relocation targets // Masks for manipulating MIPS relocation targets
public static final int MIPS_LOW26 = 0x03FFFFFF; public static final int MIPS_LOW26 = 0x03FFFFFF;
public static final int MIPS_LOW21 = 0x001FFFFF;
private MIPS_ElfRelocationConstants() { private MIPS_ElfRelocationConstants() {
// no construct // no construct

View file

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

View file

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