mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-3260 Corrected MIPS relocation issues and a few related issues affecting listing markup
This commit is contained in:
parent
acb07dd535
commit
836604e09d
12 changed files with 266 additions and 235 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue