mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 00:24:29 +08:00
Merge remote-tracking branch 'origin/GP-2081_ghidra1_TICoffRelocHandler_REBASED--SQUASHED'
This commit is contained in:
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.bin.format;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>RelocationException</code> thrown when a supported relocation encounters an
|
||||||
|
* unexpected error during processing.
|
||||||
|
*/
|
||||||
|
public class RelocationException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new exception with the specified detail message.
|
||||||
|
*
|
||||||
|
* @param message the detail message (required).
|
||||||
|
*/
|
||||||
|
public RelocationException(String message) {
|
||||||
|
super(message);
|
||||||
|
Objects.requireNonNull(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new exception with the specified detail message and
|
||||||
|
* cause. <p>Note that the detail message associated with
|
||||||
|
* {@code cause} is <i>not</i> automatically incorporated in
|
||||||
|
* this exception's detail message.
|
||||||
|
*
|
||||||
|
* @param message the detail message (required).
|
||||||
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
|
* unknown.)
|
||||||
|
*/
|
||||||
|
RelocationException(String message, Exception cause) {
|
||||||
|
super(message, cause);
|
||||||
|
Objects.requireNonNull(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.bin.format.coff.relocation;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.RelocationException;
|
||||||
|
import ghidra.app.util.bin.format.coff.*;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.symbol.Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>CoffRelocationContext</code> provide COFF relocation context data to be used by
|
||||||
|
* {@link CoffRelocationHandler} during processing of relocations.
|
||||||
|
*/
|
||||||
|
public class CoffRelocationContext {
|
||||||
|
|
||||||
|
private final Program program;
|
||||||
|
private final CoffFileHeader header;
|
||||||
|
private final Map<CoffSymbol, Symbol> symbolsMap;
|
||||||
|
|
||||||
|
private final Map<String, Object> contextMap = new HashMap<>();
|
||||||
|
private CoffSectionHeader section;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct COFF relocation context
|
||||||
|
* @param program program to which relocations are applied
|
||||||
|
* @param header COFF file header
|
||||||
|
* @param symbolsMap symbol lookup map
|
||||||
|
*/
|
||||||
|
public CoffRelocationContext(Program program, CoffFileHeader header,
|
||||||
|
Map<CoffSymbol, Symbol> symbolsMap) {
|
||||||
|
this.program = program;
|
||||||
|
this.header = header;
|
||||||
|
this.symbolsMap = symbolsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset context at start of COFF section relocation processing
|
||||||
|
* @param coffSection COFF section
|
||||||
|
*/
|
||||||
|
public void resetContext(CoffSectionHeader coffSection) {
|
||||||
|
this.section = coffSection;
|
||||||
|
contextMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get program to which relocations are being applied
|
||||||
|
* @return program
|
||||||
|
*/
|
||||||
|
public Program getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get COFF section to which relocations are being applied
|
||||||
|
* @return COFF section
|
||||||
|
*/
|
||||||
|
public CoffSectionHeader getSection() {
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get symbol required to process a relocation. Method should only be invoked
|
||||||
|
* when a symbol is required since some relocations may not require a symbol.
|
||||||
|
* @param relocation relocation whose related symbol should be returned
|
||||||
|
* @return relocation symbol
|
||||||
|
* @throws RelocationException if symbol not found
|
||||||
|
*/
|
||||||
|
public Symbol getSymbol(CoffRelocation relocation) throws RelocationException {
|
||||||
|
Symbol symbol =
|
||||||
|
symbolsMap.get(header.getSymbolAtIndex(relocation.getSymbolIndex()));
|
||||||
|
if (symbol == null) {
|
||||||
|
throw new RelocationException("missing required symbol");
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get address of symbol required to process a relocation. Method should only be invoked
|
||||||
|
* when a symbol is required since some relocations may not require a symbol.
|
||||||
|
* @param relocation relocation whose related symbol should be returned
|
||||||
|
* @return relocation symbol
|
||||||
|
* @throws RelocationException if symbol not found
|
||||||
|
*/
|
||||||
|
public Address getSymbolAddress(CoffRelocation relocation) throws RelocationException {
|
||||||
|
return getSymbol(relocation).getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and optionally compute context value for specified key
|
||||||
|
* @param key extension-specific context key
|
||||||
|
* @param mappingFunction function used to compute value if absent
|
||||||
|
* @return context value
|
||||||
|
*/
|
||||||
|
public Object computeContextValueIfAbsent(String key,
|
||||||
|
Function<String, Object> mappingFunction) {
|
||||||
|
return contextMap.computeIfAbsent(key, mappingFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store context value for specified key
|
||||||
|
* @param key extension-specific context key
|
||||||
|
* @param value context value
|
||||||
|
*/
|
||||||
|
public void putContextValue(String key, Object value) {
|
||||||
|
contextMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get context value for specified key
|
||||||
|
* @param key extension-specific key
|
||||||
|
* @return context value or null if absent
|
||||||
|
*/
|
||||||
|
public Object getContextValue(String key) {
|
||||||
|
return contextMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+10
-9
@@ -15,12 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.coff.relocation;
|
package ghidra.app.util.bin.format.coff.relocation;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.RelocationException;
|
||||||
import ghidra.app.util.bin.format.coff.CoffFileHeader;
|
import ghidra.app.util.bin.format.coff.CoffFileHeader;
|
||||||
import ghidra.app.util.bin.format.coff.CoffRelocation;
|
import ghidra.app.util.bin.format.coff.CoffRelocation;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ import ghidra.util.exception.NotFoundException;
|
|||||||
* An abstract class used to perform COFF relocations. Classes should extend this class to
|
* An abstract class used to perform COFF relocations. Classes should extend this class to
|
||||||
* provide relocations in a machine/processor specific way.
|
* provide relocations in a machine/processor specific way.
|
||||||
*/
|
*/
|
||||||
abstract public class CoffRelocationHandler implements ExtensionPoint {
|
public interface CoffRelocationHandler extends ExtensionPoint {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see whether or not an instance of this COFF relocation hander can handle
|
* Checks to see whether or not an instance of this COFF relocation hander can handle
|
||||||
@@ -37,18 +36,20 @@ abstract public class CoffRelocationHandler implements ExtensionPoint {
|
|||||||
* @param fileHeader The file header associated with the COFF to relocate.
|
* @param fileHeader The file header associated with the COFF to relocate.
|
||||||
* @return True if this relocation handler can do the relocation; otherwise, false.
|
* @return True if this relocation handler can do the relocation; otherwise, false.
|
||||||
*/
|
*/
|
||||||
abstract public boolean canRelocate(CoffFileHeader fileHeader);
|
public boolean canRelocate(CoffFileHeader fileHeader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a relocation.
|
* Performs a relocation at the specified address.
|
||||||
*
|
*
|
||||||
* @param program The program to relocate.
|
|
||||||
* @param address The address at which to perform the relocation.
|
* @param address The address at which to perform the relocation.
|
||||||
* @param symbol The symbol used during relocation.
|
|
||||||
* @param relocation The relocation information to use to perform the relocation.
|
* @param relocation The relocation information to use to perform the relocation.
|
||||||
|
* @param relocationContext relocation context data
|
||||||
* @throws MemoryAccessException If there is a problem accessing memory during the relocation.
|
* @throws MemoryAccessException If there is a problem accessing memory during the relocation.
|
||||||
* @throws NotFoundException If this handler didn't find a way to perform the relocation.
|
* @throws NotFoundException If this handler didn't find a way to perform the relocation.
|
||||||
|
* @throws RelocationException if supported relocation encountered an error during processing.
|
||||||
*/
|
*/
|
||||||
abstract public void relocate(Program program, Address address, Symbol symbol,
|
public void relocate(Address address, CoffRelocation relocation,
|
||||||
CoffRelocation relocation) throws MemoryAccessException, NotFoundException;
|
CoffRelocationContext relocationContext)
|
||||||
|
throws MemoryAccessException, NotFoundException, RelocationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import java.util.Map.Entry;
|
|||||||
import ghidra.app.util.MemoryBlockUtils;
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.Option;
|
import ghidra.app.util.Option;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
import ghidra.app.util.bin.format.RelocationException;
|
||||||
import ghidra.app.util.bin.format.coff.*;
|
import ghidra.app.util.bin.format.coff.*;
|
||||||
import ghidra.app.util.bin.format.coff.relocation.CoffRelocationHandler;
|
import ghidra.app.util.bin.format.coff.relocation.*;
|
||||||
import ghidra.app.util.bin.format.coff.relocation.CoffRelocationHandlerFactory;
|
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.program.database.mem.FileBytes;
|
import ghidra.program.database.mem.FileBytes;
|
||||||
@@ -128,7 +128,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||||||
// Only one of the CoffLoader/MSCoffLoader will survive this check
|
// Only one of the CoffLoader/MSCoffLoader will survive this check
|
||||||
return loadSpecs;
|
return loadSpecs;
|
||||||
}
|
}
|
||||||
String secondary = isCLI(header) ? "cli" : null;
|
String secondary = isCLI(header) ? "cli" : Integer.toString(header.getFlags() & 0xffff);
|
||||||
List<QueryResult> results =
|
List<QueryResult> results =
|
||||||
QueryOpinionService.query(getName(), header.getMachineName(), secondary);
|
QueryOpinionService.query(getName(), header.getMachineName(), secondary);
|
||||||
for (QueryResult result : results) {
|
for (QueryResult result : results) {
|
||||||
@@ -645,6 +645,16 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||||||
MessageLog log, TaskMonitor monitor) {
|
MessageLog log, TaskMonitor monitor) {
|
||||||
|
|
||||||
CoffRelocationHandler handler = CoffRelocationHandlerFactory.getHandler(header);
|
CoffRelocationHandler handler = CoffRelocationHandlerFactory.getHandler(header);
|
||||||
|
if (handler == null) {
|
||||||
|
String msg = String.format("No COFF relocation handler for machine type 0x%x",
|
||||||
|
(Short) header.getMachine());
|
||||||
|
log.appendMsg(msg);
|
||||||
|
Msg.error(this, program.getName() + ": " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoffRelocationContext relocationContext =
|
||||||
|
new CoffRelocationContext(program, header, symbolsMap);
|
||||||
|
int failureCount = 0;
|
||||||
|
|
||||||
for (CoffSectionHeader section : header.getSections()) {
|
for (CoffSectionHeader section : header.getSections()) {
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
@@ -653,69 +663,123 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||||||
|
|
||||||
Address sectionStartAddr = sectionsMap.get(section);
|
Address sectionStartAddr = sectionsMap.get(section);
|
||||||
if (sectionStartAddr == null) {
|
if (sectionStartAddr == null) {
|
||||||
if (section.getRelocationCount() > 0) {
|
int relocCount = section.getRelocationCount();
|
||||||
log.appendMsg("Unable to process relocations for " + section.getName() +
|
if (relocCount > 0) {
|
||||||
". No memory block was created.");
|
failureCount += relocCount;
|
||||||
|
String msg = "Unable to process " + relocCount + " relocations for section " +
|
||||||
|
section.getName() + ". No memory block was created.";
|
||||||
|
log.appendMsg(msg);
|
||||||
|
Msg.error(this, program.getName() + ": " + msg);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relocationContext.resetContext(section);
|
||||||
|
|
||||||
|
Address failedAddr = null;
|
||||||
for (CoffRelocation relocation : section.getRelocations()) {
|
for (CoffRelocation relocation : section.getRelocations()) {
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address address = sectionStartAddr.add(relocation.getAddress()); // assuming it's always a byte-offset
|
// Sections are defined with physical address while relocations use virtual address.
|
||||||
|
// Must adjust relocation address to physical.
|
||||||
|
// NOTE: Relocation address offset assumed to always be a byte-offset
|
||||||
|
Address address =
|
||||||
|
sectionStartAddr.add(relocation.getAddress() - section.getVirtualAddress());
|
||||||
|
short relocationType = relocation.getType();
|
||||||
|
|
||||||
byte[] origBytes = new byte[0];
|
byte[] origBytes = new byte[0];
|
||||||
|
|
||||||
Symbol symbol =
|
|
||||||
symbolsMap.get(header.getSymbolAtIndex(relocation.getSymbolIndex()));
|
|
||||||
|
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
handleRelocationError(program, log, address, String.format(
|
++failureCount;
|
||||||
"No relocation handler for machine type 0x%x to process relocation at %s with type 0x%x",
|
handleRelocationError(program, address, relocationType,
|
||||||
header.getMachine(), address, relocation.getType()));
|
"No COFF relocation handler", null);
|
||||||
}
|
|
||||||
else if (symbol == null) {
|
|
||||||
handleRelocationError(program, log, address,
|
|
||||||
String.format("No symbol to process relocation at %s with type 0x%x",
|
|
||||||
address, relocation.getType()));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
origBytes = new byte[4];
|
origBytes = new byte[4];
|
||||||
program.getMemory().getBytes(address, origBytes);
|
if (address.equals(failedAddr)) {
|
||||||
handler.relocate(program, address, symbol, relocation);
|
// skip relocation if previous failed relocation was at the same address
|
||||||
|
// since it is likely dependent on the previous failed relocation result
|
||||||
|
++failureCount;
|
||||||
|
|
||||||
|
String logMessage =
|
||||||
|
String.format("Skipped dependent COFF Relocation type 0x%x at %s",
|
||||||
|
relocationType, address.toString());
|
||||||
|
Msg.error(this, program.getName() + ": " + logMessage);
|
||||||
|
|
||||||
|
// TODO: once RelocationTable can retain all relocations at the same address
|
||||||
|
// this continue statement should be removed (see GP-2128)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//else {
|
||||||
|
program.getMemory().getBytes(address, origBytes);
|
||||||
|
handler.relocate(address, relocation, relocationContext);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
catch (MemoryAccessException e) {
|
catch (MemoryAccessException e) {
|
||||||
handleRelocationError(program, log, address, String.format(
|
++failureCount;
|
||||||
"Error accessing memory at address %s. Relocation failed.", address));
|
failedAddr = address;
|
||||||
|
handleRelocationError(program, address, relocationType,
|
||||||
|
"Error accessing memory", null);
|
||||||
}
|
}
|
||||||
catch (NotFoundException e) {
|
catch (NotFoundException e) {
|
||||||
handleRelocationError(program, log, address,
|
++failureCount;
|
||||||
String.format("Relocation type 0x%x at address %s is not supported.",
|
failedAddr = address;
|
||||||
relocation.getType(), address));
|
handleRelocationError(program, address, relocationType,
|
||||||
|
"Unsupported COFF relocation type", null);
|
||||||
}
|
}
|
||||||
catch (AddressOutOfBoundsException e) {
|
catch (RelocationException e) {
|
||||||
handleRelocationError(program, log, address,
|
++failureCount;
|
||||||
String.format("Error computing relocation at address %s.", address));
|
failedAddr = address;
|
||||||
|
handleRelocationError(program, address, relocationType, e.getMessage(),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
++failureCount;
|
||||||
|
failedAddr = address;
|
||||||
|
String msg = e.getMessage();
|
||||||
|
if (msg == null) {
|
||||||
|
msg = e.toString();
|
||||||
|
}
|
||||||
|
handleRelocationError(program, address, relocationType, msg, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The relocation symbol may be null when either not required by a relocation or
|
||||||
|
// not found with symbol index
|
||||||
|
Symbol symbol =
|
||||||
|
symbolsMap.get(header.getSymbolAtIndex(relocation.getSymbolIndex()));
|
||||||
|
|
||||||
|
// TODO: There may be multiple relocations at the same address.
|
||||||
|
// The RelocationTable for retaining relocations needs to be revised to handle
|
||||||
|
// this. At present only the last one will remain in the DB-backed address-based
|
||||||
|
// table. (see GP-2128)
|
||||||
program.getRelocationTable()
|
program.getRelocationTable()
|
||||||
.add(address, relocation.getType(),
|
.add(address, relocation.getType(),
|
||||||
new long[] { relocation.getSymbolIndex() }, origBytes,
|
new long[] { relocation.getSymbolIndex() }, origBytes,
|
||||||
symbol != null ? symbol.getName() : "<null>");
|
symbol != null ? symbol.getName() : "<null>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failureCount != 0) {
|
||||||
|
String msg = "Failed to process a total of " + failureCount +
|
||||||
|
" relocations. See log and error bookmarks for details.";
|
||||||
|
log.appendMsg(msg);
|
||||||
|
Msg.error(this, program.getName() + ": " + msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRelocationError(Program program, MessageLog log, Address address,
|
private void handleRelocationError(Program program, Address address,
|
||||||
String message) {
|
Short relocationType, String message, Exception causeToReport) {
|
||||||
|
String bookmarkMessage =
|
||||||
|
String.format("Failed to apply COFF Relocation type 0x%x: %s", relocationType, message);
|
||||||
program.getBookmarkManager()
|
program.getBookmarkManager()
|
||||||
.setBookmark(address, BookmarkType.ERROR, "Relocations", message);
|
.setBookmark(address, BookmarkType.ERROR, "Relocations", bookmarkMessage);
|
||||||
log.appendMsg(message);
|
String logMessage = String.format("Failed to apply COFF Relocation type 0x%x at %s: %s",
|
||||||
|
relocationType, address.toString(), message);
|
||||||
|
Msg.error(this, program.getName() + ": " + logMessage, causeToReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+23
-11
@@ -15,14 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.coff.relocation;
|
package ghidra.app.util.bin.format.coff.relocation;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.RelocationException;
|
||||||
import ghidra.app.util.bin.format.coff.*;
|
import ghidra.app.util.bin.format.coff.*;
|
||||||
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.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
|
|
||||||
public class X86_32_CoffRelocationHandler extends CoffRelocationHandler {
|
public class X86_32_CoffRelocationHandler implements CoffRelocationHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRelocate(CoffFileHeader fileHeader) {
|
public boolean canRelocate(CoffFileHeader fileHeader) {
|
||||||
@@ -30,27 +31,38 @@ public class X86_32_CoffRelocationHandler extends CoffRelocationHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relocate(Program program, Address address, Symbol symbol,
|
public void relocate(Address address, CoffRelocation relocation,
|
||||||
CoffRelocation relocation) throws MemoryAccessException, NotFoundException {
|
CoffRelocationContext relocationContext)
|
||||||
|
throws MemoryAccessException, NotFoundException, RelocationException {
|
||||||
|
|
||||||
int addend = program.getMemory().getInt(address);
|
Program program = relocationContext.getProgram();
|
||||||
|
Memory mem = program.getMemory();
|
||||||
|
|
||||||
|
int addend = mem.getInt(address);
|
||||||
|
|
||||||
switch (relocation.getType()) {
|
switch (relocation.getType()) {
|
||||||
|
|
||||||
// We are implementing these types:
|
// We are implementing these types:
|
||||||
case IMAGE_REL_I386_DIR32: {
|
case IMAGE_REL_I386_DIR32: {
|
||||||
program.getMemory().setInt(address,
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
(int) symbol.getAddress().add(addend).getOffset());
|
.add(addend)
|
||||||
|
.getOffset();
|
||||||
|
program.getMemory().setInt(address, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IMAGE_REL_I386_DIR32NB: {
|
case IMAGE_REL_I386_DIR32NB: {
|
||||||
program.getMemory().setInt(address,
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
(int) symbol.getAddress().add(addend).subtract(program.getImageBase()));
|
.add(addend)
|
||||||
|
.subtract(program.getImageBase());
|
||||||
|
mem.setInt(address, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IMAGE_REL_I386_REL32: {
|
case IMAGE_REL_I386_REL32: {
|
||||||
program.getMemory().setInt(address,
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
(int) symbol.getAddress().add(addend).subtract(address) - 4);
|
.add(addend)
|
||||||
|
.subtract(address);
|
||||||
|
value -= 4;
|
||||||
|
mem.setInt(address, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-16
@@ -15,41 +15,55 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.coff.relocation;
|
package ghidra.app.util.bin.format.coff.relocation;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.RelocationException;
|
||||||
import ghidra.app.util.bin.format.coff.*;
|
import ghidra.app.util.bin.format.coff.*;
|
||||||
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.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
|
|
||||||
public class X86_64_CoffRelocationHandler extends CoffRelocationHandler {
|
public class X86_64_CoffRelocationHandler implements CoffRelocationHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRelocate(CoffFileHeader fileHeader) {
|
public boolean canRelocate(CoffFileHeader fileHeader) {
|
||||||
return fileHeader.getMachine() == CoffMachineType.IMAGE_FILE_MACHINE_AMD64;
|
return fileHeader.getMachine() == CoffMachineType.IMAGE_FILE_MACHINE_AMD64;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relocate(Program program, Address address, Symbol symbol,
|
public void relocate(Address address, CoffRelocation relocation,
|
||||||
CoffRelocation relocation) throws MemoryAccessException, NotFoundException {
|
CoffRelocationContext relocationContext)
|
||||||
|
throws MemoryAccessException, NotFoundException, RelocationException {
|
||||||
|
|
||||||
|
Program program = relocationContext.getProgram();
|
||||||
|
Memory mem = program.getMemory();
|
||||||
|
|
||||||
int distance = 0;
|
int distance = 0;
|
||||||
long addend = program.getMemory().getInt(address);
|
long addend = mem.getInt(address);
|
||||||
|
|
||||||
switch (relocation.getType()) {
|
switch (relocation.getType()) {
|
||||||
|
|
||||||
// We are implementing these types:
|
// We are implementing these types:
|
||||||
case IMAGE_REL_AMD64_ADDR64:
|
case IMAGE_REL_AMD64_ADDR64: {
|
||||||
addend = program.getMemory().getLong(address); // overwrite default 4-byte addend
|
addend = mem.getLong(address); // overwrite default 4-byte addend
|
||||||
program.getMemory().setLong(address, symbol.getAddress().add(addend).getOffset());
|
long value = relocationContext.getSymbolAddress(relocation)
|
||||||
|
.add(addend)
|
||||||
|
.getOffset();
|
||||||
|
mem.setLong(address, value);
|
||||||
break;
|
break;
|
||||||
case IMAGE_REL_AMD64_ADDR32:
|
}
|
||||||
program.getMemory().setInt(address,
|
case IMAGE_REL_AMD64_ADDR32: {
|
||||||
(int) symbol.getAddress().add(addend).getOffset());
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
|
.add(addend)
|
||||||
|
.getOffset();
|
||||||
|
mem.setInt(address, value);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case IMAGE_REL_AMD64_ADDR32NB: {
|
case IMAGE_REL_AMD64_ADDR32NB: {
|
||||||
program.getMemory().setInt(address,
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
(int) symbol.getAddress().add(addend).subtract(program.getImageBase()));
|
.add(addend)
|
||||||
|
.subtract(program.getImageBase());
|
||||||
|
mem.setInt(address, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IMAGE_REL_AMD64_REL32_5: { // fallthrough to IMAGE_REL_AMD64_REL32 to get correct 'distance'
|
case IMAGE_REL_AMD64_REL32_5: { // fallthrough to IMAGE_REL_AMD64_REL32 to get correct 'distance'
|
||||||
@@ -68,8 +82,11 @@ public class X86_64_CoffRelocationHandler extends CoffRelocationHandler {
|
|||||||
distance++;
|
distance++;
|
||||||
}
|
}
|
||||||
case IMAGE_REL_AMD64_REL32: {
|
case IMAGE_REL_AMD64_REL32: {
|
||||||
program.getMemory().setInt(address,
|
int value = (int) relocationContext.getSymbolAddress(relocation)
|
||||||
(int) symbol.getAddress().add(addend).subtract(address) - 4 - distance);
|
.add(addend)
|
||||||
|
.subtract(address);
|
||||||
|
value -= (distance + 4);
|
||||||
|
mem.setInt(address, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user