GP-1571 ELF: create fake relocation table entry for non-relocation memory modifications (needed for ELF export)

This commit is contained in:
ghidra1 2021-12-13 14:52:24 -05:00
parent b5927ce849
commit 9076b2429c
5 changed files with 66 additions and 17 deletions

View file

@ -378,9 +378,11 @@ public class ElfDefaultGotPltMarkup {
// TODO: record artificial relative relocation for reversion/export concerns
entry1Value += imageBaseAdj; // adjust first entry value
if (elf.is64Bit()) {
elfLoadHelper.addFakeRelocTableEntry(gotStart, 8);
memory.setLong(gotStart, entry1Value);
}
else {
elfLoadHelper.addFakeRelocTableEntry(gotStart, 4);
memory.setInt(gotStart, (int) entry1Value);
}
}

View file

@ -17,8 +17,7 @@ package ghidra.app.util.bin.format.elf;
import ghidra.app.util.bin.format.MemoryLoadable;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryAccessException;
@ -203,4 +202,18 @@ public interface ElfLoadHelper {
public long getOriginalValue(Address addr, boolean signExtend)
throws MemoryAccessException;
/**
* Add a fake relocation table entry if none previously existed for the specified address.
* This is intended to record original file bytes when forced modifications have been
* performed during the ELF import processing. A relocation type of 0 will be specified for
* fake entry.
* @param address relocation address
* @param length number of bytes affected
* @return true if recorded successfully, or false if conflict with existing relocation entry occurs
* @throws MemoryAccessException if unable to read bytes from memory
* @throws AddressOverflowException if range address wrap occurs
*/
public boolean addFakeRelocTableEntry(Address address, int length)
throws MemoryAccessException, AddressOverflowException;
}

View file

@ -846,6 +846,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
monitor.checkCanceled();
monitor.incrementProgress(1);
long type = reloc.getType();
if (type == 0) {
continue; // ignore relocation type 0 (i.e., ..._NONE)
}
int symbolIndex = reloc.getSymbolIndex();
String symbolName = null;
if (symbolIndex >= 0 && symbolIndex < symbols.length) {
@ -863,7 +868,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4];
long type = reloc.getType();
if (relrRelocationType != 0) {
type = relrRelocationType;
reloc.setType(relrRelocationType);
@ -929,6 +933,28 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
: dataConverter.getValue(bytes, len);
}
@Override
public boolean addFakeRelocTableEntry(Address address, int length)
throws MemoryAccessException, AddressOverflowException {
byte[] bytes = new byte[length];
Address maxAddr = address.addNoWrap(length - 1);
RelocationTable relocationTable = program.getRelocationTable();
Relocation relocation = relocationTable.getRelocation(address);
if (relocation != null) {
return false;
}
relocation = relocationTable.getRelocationAfter(address);
if (relocation != null && relocation.getAddress().compareTo(maxAddr) <= 0) {
return false;
}
int cnt = memory.getBytes(address, bytes);
if (cnt != length) {
throw new MemoryAccessException();
}
relocationTable.add(address, 0, new long[0], bytes, null);
return true;
}
/**
* Add reference to previously applied header structure (assumes markupElfHeader previously called)
* @param componentName

View file

@ -454,7 +454,7 @@ public class MIPS_ElfExtension extends ElfExtension {
setTableEntryIfZero(gotBaseAddress, gotIndex, symbolOffset, elfLoadHelper);
}
catch (MemoryAccessException e) {
catch (MemoryAccessException | AddressOverflowException e) {
Msg.error(this, "Failed to update .got table entry", e);
}
catch (NotFoundException e) {
@ -793,7 +793,7 @@ public class MIPS_ElfExtension extends ElfExtension {
catch (NotFoundException e) {
throw new AssertException("unexpected", e);
}
catch (MemoryAccessException e) {
catch (MemoryAccessException | AddressOverflowException e) {
elfLoadHelper.log("Failed to adjust GOT: " + e.getMessage());
}
}
@ -846,37 +846,42 @@ public class MIPS_ElfExtension extends ElfExtension {
catch (NotFoundException e) {
throw new AssertException("unexpected", e);
}
catch (MemoryAccessException e) {
catch (MemoryAccessException | AddressOverflowException e) {
elfLoadHelper.log("Failed to adjust MIPS GOT: " + e.getMessage());
}
}
private Address adjustTableEntryIfNonZero(Address tableBaseAddr, int entryIndex,
long adjustment, ElfLoadHelper elfLoadHelper) throws MemoryAccessException {
// TODO: record artificial relative relocation for reversion/export concerns
long adjustment, ElfLoadHelper elfLoadHelper)
throws MemoryAccessException, AddressOverflowException {
boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit();
Memory memory = elfLoadHelper.getProgram().getMemory();
Address tableEntryAddr;
if (is64Bit) {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
long offset = memory.getLong(tableEntryAddr);
if (offset != 0) {
memory.setLong(tableEntryAddr, offset + adjustment);
if (adjustment != 0) {
long offset = memory.getLong(tableEntryAddr);
if (offset != 0) {
elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 8);
memory.setLong(tableEntryAddr, offset + adjustment);
}
}
}
else {
tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
int offset = memory.getInt(tableEntryAddr);
if (offset != 0) {
memory.setInt(tableEntryAddr, (int) (offset + adjustment));
if (adjustment != 0) {
int offset = memory.getInt(tableEntryAddr);
if (offset != 0) {
elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 4);
memory.setInt(tableEntryAddr, (int) (offset + adjustment));
}
}
}
return tableEntryAddr;
}
private Address setTableEntryIfZero(Address tableBaseAddr, int entryIndex, long value,
ElfLoadHelper elfLoadHelper) throws MemoryAccessException {
// TODO: record artificial relative relocation for reversion/export concerns
ElfLoadHelper elfLoadHelper) throws MemoryAccessException, AddressOverflowException {
boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit();
Memory memory = elfLoadHelper.getProgram().getMemory();
Address tableEntryAddr;
@ -884,6 +889,7 @@ public class MIPS_ElfExtension extends ElfExtension {
tableEntryAddr = tableBaseAddr.add(entryIndex * 8);
long offset = memory.getLong(tableEntryAddr);
if (offset == 0) {
elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 8);
memory.setLong(tableEntryAddr, value);
}
}
@ -891,6 +897,7 @@ public class MIPS_ElfExtension extends ElfExtension {
tableEntryAddr = tableBaseAddr.add(entryIndex * 4);
int offset = memory.getInt(tableEntryAddr);
if (offset == 0) {
elfLoadHelper.addFakeRelocTableEntry(tableEntryAddr, 4);
memory.setInt(tableEntryAddr, (int) value);
}
}

View file

@ -113,9 +113,10 @@ public class PowerPC_ElfExtension extends ElfExtension {
// Update first got entry normally updated by link editor to refer to dynamic table
int dynamicOffset =
memory.getInt(gotAddr) + (int) elfLoadHelper.getImageBaseWordAdjustmentOffset();
elfLoadHelper.addFakeRelocTableEntry(gotAddr, 4);
memory.setInt(gotAddr, dynamicOffset);
}
catch (MemoryAccessException e) {
catch (MemoryAccessException | AddressOverflowException e) {
elfLoadHelper.log(e);
}
}