Merge remote-tracking branch

'origin/GP-3236_ghidra1_PeMingwRelocs--SQUASHED' (Closes #5155)
This commit is contained in:
Ryan Kurtz 2023-04-20 07:50:04 -04:00
commit 9dcc504965
7 changed files with 752 additions and 18 deletions

View file

@ -0,0 +1,705 @@
/* ###
* 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.plugin.core.analysis;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.cmd.label.DemanglerCmd;
import ghidra.app.services.*;
import ghidra.app.util.bin.format.elf.relocation.ElfRelocationHandler;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.*;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.reloc.RelocationTable;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class MingwRelocationAnalyzer extends AbstractAnalyzer {
private final static String NAME = "MinGW Relocations";
private final static String DESCRIPTION =
"Identify, markup and apply MinGW pseudo-relocations (must be done immediately after import).";
public MingwRelocationAnalyzer() {
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
// run right before any other analyzer and immediately after import
setPriority(AnalysisPriority.FORMAT_ANALYSIS.before().before().before().before().before());
setDefaultEnablement(true);
}
@Override
public boolean canAnalyze(Program program) {
if (!MinGWPseudoRelocationHandler.canHandle(program)) {
return false;
}
if (!program.hasExclusiveAccess()) {
// Exclusive access required since relocation table lacks merge support
Msg.warn(this,
NAME + " analysis requires exclusive access to " + program.getDomainFile());
return false;
}
return true;
}
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
if (MinGWPseudoRelocationHandler.isRelocTableWithinSet(program, set)) {
MinGWPseudoRelocationHandler handler = new MinGWPseudoRelocationHandler(program);
handler.processRelocations(log, monitor);
}
return true;
}
}
/**
* MinGW pseudo-relocation handler
*/
class MinGWPseudoRelocationHandler {
private static final String PSEUDO_RELOC_LIST_START_NAME = "__RUNTIME_PSEUDO_RELOC_LIST__";
private static final String PSEUDO_RELOC_LIST_END_NAME = "__RUNTIME_PSEUDO_RELOC_LIST_END__";
private static final int RP_VERSION_V1 = 0;
private static final int RP_VERSION_V2 = 1;
private static final int OLD_STYLE_ENTRY_SIZE = 8;
private static final int NEW_STYLE_ENTRY_HEADER_SIZE = 12;
private static final String RELOC_TABLE_HEADER_STRUCT_NAME = "pseudoRelocTableHeader";
private static final String V1_RELOC_ITEM_STRUCT_NAME = "pseudoRelocItemV1";
private static final String V2_RELOC_ITEM_STRUCT_NAME = "pseudoRelocItemV2";
private Program program;
private int pointerSize;
private DataType dwAddressDataType;
/**
* Determine if the specified Program contains MingGW pseud-relocations that can be processed.
* This does not check if they were previously processed.
* @param program program to be processed.
* @return true if Program contains MingGW pseud-relocations that can be processed.
*/
static boolean canHandle(Program program) {
return isSupportedProgram(program) &&
getLabel(program, PSEUDO_RELOC_LIST_START_NAME) != null &&
getLabel(program, PSEUDO_RELOC_LIST_END_NAME) != null;
}
/**
* Determine if the relocation table is contained within the specified address set.
* @param program program to be processed
* @param set address set
* @return true if table contained within set of addresses
*/
static boolean isRelocTableWithinSet(Program program, AddressSetView set) {
Symbol pdwTableBegin = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
PSEUDO_RELOC_LIST_START_NAME, m -> {
/* ignore */});
Symbol pdwTableEnd = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
PSEUDO_RELOC_LIST_END_NAME, m -> {
/* ignore */});
if (pdwTableBegin == null || pdwTableEnd == null) {
return false;
}
Address pdwTableBeginAddr = pdwTableBegin.getAddress();
Address pdwTableEndAddr = pdwTableEnd.getAddress();
if (pdwTableBeginAddr.getAddressSpace() != pdwTableEndAddr.getAddressSpace()) {
return false;
}
return set.contains(pdwTableBeginAddr, pdwTableEndAddr);
}
/**
* Construct MinGW pseudo-relocation handler for a Program.
* @param program program to be processed
*/
MinGWPseudoRelocationHandler(Program program) {
this.program = program;
}
private static boolean isSupportedProgram(Program program) {
return "x86".equals(program.getLanguage().getProcessor().toString()) &&
"windows".equals(program.getCompilerSpec().getCompilerSpecID().toString());
}
private static Symbol getLabel(Program program, String name) {
return SymbolUtilities.getExpectedLabelOrFunctionSymbol(program, name, m -> {
/* ignore */});
}
private Symbol createPrimaryLabel(Address address, String name) {
try {
SymbolTable symbolTable = program.getSymbolTable();
Symbol symbol = symbolTable.createLabel(address, name, null, SourceType.ANALYSIS);
if (!symbol.isPrimary()) {
symbol.setPrimary();
}
return symbol;
}
catch (InvalidInputException e) {
throw new AssertException("unexpected", e);
}
}
boolean processRelocations(MessageLog log, TaskMonitor monitor) throws CancelledException {
if (!isSupportedProgram(program)) {
return false;
}
pointerSize = program.getDefaultPointerSize();
dwAddressDataType = new IBO32DataType(program.getDataTypeManager());
Symbol pdwTableBegin = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
PSEUDO_RELOC_LIST_START_NAME, m -> {
/* ignore */});
Symbol pdwTableEnd = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
PSEUDO_RELOC_LIST_END_NAME, m -> {
/* ignore */});
if (pdwTableBegin == null || pdwTableEnd == null) {
return false;
}
Address pdwTableBeginAddr = pdwTableBegin.getAddress();
Address pdwTableEndAddr = pdwTableEnd.getAddress();
if (pdwTableBeginAddr.getAddressSpace() != pdwTableEndAddr.getAddressSpace()) {
return false;
}
long size = pdwTableEndAddr.subtract(pdwTableBeginAddr);
Memory memory = program.getMemory();
// First table entry is used to identify implementation version
int version;
try {
if (size >= OLD_STYLE_ENTRY_SIZE && memory.getLong(pdwTableBeginAddr) != 0) {
version = RP_VERSION_V1; // header not used
}
else if (size >= NEW_STYLE_ENTRY_HEADER_SIZE) {
applyPseudoRelocHeader(program, pdwTableBeginAddr, log);
version = memory.getInt(pdwTableBeginAddr.add(8)); // 3rd DWORD is version
// update table pointer to first item
pdwTableBeginAddr = pdwTableBeginAddr.add(NEW_STYLE_ENTRY_HEADER_SIZE);
size -= NEW_STYLE_ENTRY_HEADER_SIZE; // reduce size by header size
}
else {
log.appendMsg("Unsupported MinGW relocation table at " + pdwTableBeginAddr);
return false;
}
}
catch (MemoryAccessException | AddressOutOfBoundsException e) {
String msg = "MinGW relocation table processing failed at " + pdwTableBeginAddr;
log.appendMsg(msg);
Msg.error(this, msg, e);
return false;
}
boolean success;
switch (version) {
case RP_VERSION_V1:
success = relocateV1(pdwTableBeginAddr, (int) (size / OLD_STYLE_ENTRY_SIZE), log,
monitor);
break;
case RP_VERSION_V2:
success = relocateV2(pdwTableBeginAddr, (int) (size / NEW_STYLE_ENTRY_HEADER_SIZE),
log, monitor);
break;
default:
log.appendMsg("Unsupported MinGW relocation table (Version: " + version + ") at " +
pdwTableBeginAddr);
return false;
}
// Cleanup duplicate External Import symbols
ExternalManager extMgr = program.getExternalManager();
ReferenceManager refMgr = program.getReferenceManager();
SymbolTable symbolTable = program.getSymbolTable();
for (Symbol extSym : program.getSymbolTable().getExternalSymbols()) {
monitor.checkCancelled();
ExternalLocation extLoc = extMgr.getExternalLocation(extSym);
if (extLoc.getOriginalImportedName() != null) {
continue; // skip - already demangled
}
if (refMgr.hasReferencesTo(extSym.getAddress())) {
continue; // skip - reference exists
}
List<Symbol> globalSymbols = symbolTable.getGlobalSymbols(extSym.getName());
if (globalSymbols.size() != 1) {
continue;
}
Symbol s = globalSymbols.get(0);
if (memory.isExternalBlockAddress(s.getAddress())) {
extSym.delete();
}
}
return success;
}
/**
* Maps IAT addresses to EXTERNAL block allocation identified by {@link ExternalIATSymbol}
*/
private class ExternalIATSymbolMap extends HashMap<Address, ExternalIATSymbol> {
private Address nextExtAddr;
ExternalIATSymbolMap(Address extBlockStart) {
this.nextExtAddr = extBlockStart;
}
ExternalIATSymbol allocateIATEntry(Address iatEntryAddr, RelocationTable relocationTable)
throws MemoryAccessException, CodeUnitInsertionException {
/**
* symbolAddr (0x41a724) - corresponds to IAT location which refers to
* __imp__ZTIPi -> _ZTIPi
* following original IBO32 value points at IMAGE_IMPORT_BY_NAME:
* dword index (0x135c)
* ds name ("_ZTIPi")
* The above was used to formulate external location and reference
*
* targetAddr (0x410ea0) - location to be fixed-up (relocation applied)
* data at relocation target:
* -original bytes: address of IAT entry (i.e., symbolAddr) - may vary by bitLength!
* -post fixup: adjusted by offset from symbolAddr to real external
* symbol address (*symbolAddr - symbolAddr)
*/
ExternalIATSymbol existingEntry = get(iatEntryAddr);
if (existingEntry != null) {
return existingEntry;
}
Reference ref =
program.getReferenceManager().getPrimaryReferenceFrom(iatEntryAddr, 0);
if (!ref.isExternalReference()) {
return null;
}
Symbol extSym = program.getSymbolTable().getSymbol(ref);
if (extSym == null) {
return null;
}
ExternalLocation extLoc =
program.getExternalManager().getExternalLocation(extSym);
if (extLoc == null) {
return null;
}
// Update IAT value - reference to EXTERNAL block
Listing listing = program.getListing();
listing.clearCodeUnits(iatEntryAddr, iatEntryAddr, false);
Memory memory = program.getMemory();
if (pointerSize == 8) { // 64-bit
memory.setLong(iatEntryAddr, nextExtAddr.getOffset());
}
else { // 32-bit
memory.setInt(iatEntryAddr, (int) nextExtAddr.getOffset());
}
listing.createData(iatEntryAddr, PointerDataType.dataType);
relocationTable.add(iatEntryAddr, Status.APPLIED_OTHER, 0, null, pointerSize,
extSym.getName());
try {
if (extLoc.isFunction()) {
Function func = listing.createFunction(null, nextExtAddr,
new AddressSet(nextExtAddr, nextExtAddr), SourceType.DEFAULT);
func.setThunkedFunction(extLoc.getFunction());
}
else {
// TODO: Not sure how to preserve relationship to external symbol
// which refers to Library
listing.setComment(nextExtAddr, CodeUnit.PLATE_COMMENT,
"External Location: " + extSym.getName(true));
String name = extLoc.getOriginalImportedName();
boolean demangle = true;
if (name == null) {
name = extSym.getName();
demangle = false;
}
createPrimaryLabel(nextExtAddr, name);
if (demangle) {
DemanglerCmd cmd = new DemanglerCmd(nextExtAddr, name);
cmd.applyTo(program);
}
}
}
catch (Exception e) {
Msg.error(this, "Failed to create EXTERNAL block symbol at " + nextExtAddr);
}
ExternalIATSymbol extIATSym = new ExternalIATSymbol(nextExtAddr, extLoc);
put(iatEntryAddr, extIATSym);
nextExtAddr = nextExtAddr.add(pointerSize);
return extIATSym;
}
}
/**
* External Import Address Table (IAT) Symbol Record
*/
private static record ExternalIATSymbol(Address extAddr, ExternalLocation extLoc) {
// record only
}
private Address getDWAddress(MemBuffer buf) {
return (Address) dwAddressDataType.getValue(buf, dwAddressDataType.getDefaultSettings(),
-1);
}
private boolean relocateV2(Address pdwTableBeginAddr, int entryCount, MessageLog log,
TaskMonitor monitor) throws CancelledException {
Listing listing = program.getListing();
Data d = listing.getDefinedDataAt(pdwTableBeginAddr);
if (d != null && (d.isArray() || d.isStructure())) {
return false; // silent - appears to have been previously processed
}
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
Memory memory = program.getMemory();
DataTypeManager dtm = program.getDataTypeManager();
RelocationTable relocationTable = program.getRelocationTable();
// Determine number of unique IAT symbol locations referenced
Address addr = pdwTableBeginAddr;
MemoryBufferImpl buf = new MemoryBufferImpl(memory, addr);
HashSet<Address> uniqueIATAddressSet = new HashSet<>();
for (int i = 0; i < entryCount; i++) {
monitor.checkCancelled();
Address iatSymbolAddr = getDWAddress(buf);
if (iatSymbolAddr == null) {
log.appendMsg("Failed to read Mingw pseudo-relocation symbol RVA at: " + addr);
return false;
}
uniqueIATAddressSet.add(iatSymbolAddr);
addr = addr.add(NEW_STYLE_ENTRY_HEADER_SIZE);
buf.setPosition(addr);
}
// Allocate EXTERNAL block
int extBlockSize = uniqueIATAddressSet.size() * pointerSize;
Address extBlockStart;
try {
extBlockStart = allocateBlock(MemoryBlock.EXTERNAL_BLOCK_NAME, extBlockSize);
}
catch (Exception e) {
String msg = "Failed to allocate EXTERNAL block for MinGW relocation processing";
log.appendMsg(msg);
Msg.error(this, msg, e);
return false;
}
ExternalIATSymbolMap extIATSymbolMap = new ExternalIATSymbolMap(extBlockStart);
// relocation result counters
int applied = 0;
int failed = 0;
int unsupported = 0;
// Process relocations
addr = pdwTableBeginAddr; // 1st dword of item is symbol address
buf.setPosition(addr);
for (int i = 0; i < entryCount; i++) {
monitor.checkCancelled();
Address iatSymbolAddr = getDWAddress(buf);
addr = addr.add(4); // 2nd dword of item is target address
buf.setPosition(addr);
Address targetAddr = getDWAddress(buf);
if (targetAddr == null) {
log.appendMsg("Failed to read Mingw pseudo-relocation target RVA at: " + addr);
return false;
}
addr = addr.add(4); // 3rd dword of item is flags (treated as bit-length)
buf.setPosition(addr);
String symbolName = null;
RelocationResult result;
try {
// read item flags as bit-length
int bitLength = buf.getInt(0) & 0xff;
ExternalIATSymbol extSymbolEntry =
extIATSymbolMap.allocateIATEntry(iatSymbolAddr, relocationTable);
if (extSymbolEntry == null) {
throw new UnsupportedOperationException();
}
symbolName = extSymbolEntry.extLoc.getOriginalImportedName();
if (symbolName == null) {
symbolName = extSymbolEntry.extLoc.getSymbol().getName();
}
// compute relocation symbol offset value
long impValue = pointerSize == 8 ? memory.getLong(iatSymbolAddr)
: Integer.toUnsignedLong(memory.getInt(iatSymbolAddr));
Address pointerValue = space.getAddress(impValue);
long qwOffset = pointerValue.subtract(iatSymbolAddr);
long addend = 0;
result = new RelocationResult(Status.APPLIED_OTHER, bitLength / 8); // treat flags as bit length
switch (bitLength) {
case 8:
byte val8 = (byte) (memory.getByte(targetAddr) + qwOffset);
memory.setByte(targetAddr, val8);
++applied;
break;
case 16:
short val16 = (short) (memory.getShort(targetAddr) + qwOffset);
memory.setShort(targetAddr, val16);
++applied;
break;
case 32:
int val32 = memory.getInt(targetAddr);
if (pointerSize == 4) {
addend = (val32 - (int) iatSymbolAddr.getOffset());
}
val32 += qwOffset;
memory.setInt(targetAddr, val32);
++applied;
break;
case 64:
long val64 = memory.getLong(targetAddr);
if (pointerSize == 8) {
addend = val64 - iatSymbolAddr.getOffset();
}
val64 += qwOffset;
memory.setLong(targetAddr, val64);
++applied;
break;
default:
result = RelocationResult.UNSUPPORTED;
++unsupported;
}
if (addend != 0) {
ElfRelocationHandler.warnExternalOffsetRelocation(program,
targetAddr, pointerValue, symbolName, addend, null);
if (!memory.getBlock(targetAddr).isExecute()) {
// assume pointer if not in execute block
ElfRelocationHandler.applyComponentOffsetPointer(program,
targetAddr, addend);
}
}
}
catch (MemoryAccessException | UnsupportedOperationException
| CodeUnitInsertionException e) {
markAsError(targetAddr, symbolName, e.getMessage(), log);
result = RelocationResult.FAILURE;
++failed;
}
relocationTable.add(targetAddr, result.status(), 0, null, result.byteLength(),
symbolName);
addr = addr.add(4);
buf.setPosition(addr); // position on next element
}
if (failed != 0 || unsupported != 0) {
log.appendMsg("MinGW pseudo-relocations - applied:" + applied + " failed:" + failed +
" unsupported:" + unsupported);
}
Structure relocEntryStruct = new StructureDataType(V2_RELOC_ITEM_STRUCT_NAME, 0, dtm);
relocEntryStruct.setPackingEnabled(true);
relocEntryStruct.add(dwAddressDataType, "sym", null);
relocEntryStruct.add(DWordDataType.dataType, "target", null); // could be offcut
relocEntryStruct.add(DWordDataType.dataType, "flags", null);
Array a = new ArrayDataType(relocEntryStruct, entryCount, -1, dtm);
try {
DataUtilities.createData(program, pdwTableBeginAddr, a, -1, false,
ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
log.appendMsg(
"Failed to markup Mingw pseudo-relocation Table at: " + pdwTableBeginAddr);
}
return true;
}
private void applyPseudoRelocHeader(Program program, Address relocHeaderAddr, MessageLog log) {
Structure relocHeaderStruct =
new StructureDataType(RELOC_TABLE_HEADER_STRUCT_NAME, 0, program.getDataTypeManager());
relocHeaderStruct.setPackingEnabled(true);
relocHeaderStruct.add(DWordDataType.dataType, "zero1", null);
relocHeaderStruct.add(DWordDataType.dataType, "zero2", null);
relocHeaderStruct.add(DWordDataType.dataType, "version", null);
try {
DataUtilities.createData(program, relocHeaderAddr, relocHeaderStruct, -1,
false, ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
log.appendMsg(
"Failed to markup Mingw pseudo-relocation Table header at: " + relocHeaderAddr);
}
}
private void markAsError(Address relocationAddress, String symbolName, String msg,
MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? "<noname>" : symbolName;
log.appendMsg("MinGW Relocation Error: at " + relocationAddress + ", Symbol = " +
symbolName + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "MinGW Relocation",
"MinGW Relocation Error: Symbol = " + symbolName + ": " + msg);
}
private void markAsError(Address relocationAddress, String msg, MessageLog log) {
log.appendMsg("MinGW Relocation Error: at " + relocationAddress + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager();
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "MinGW Relocation",
"MinGW Relocation Error: " + msg);
}
private Address allocateBlock(String blockName, int extBlockSize) throws Exception {
Memory memory = program.getMemory();
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
long delta = 0x10000000;
Address startAddr = null;
for (long offset = delta; offset < 0x100000000L; offset += delta) {
Address addr = space.getAddress(offset);
AddressIterator addresses = memory.getAddresses(addr, true);
if (!addresses.hasNext()) {
startAddr = addr;
break;
}
Address nextAddr = addresses.next();
if (!nextAddr.getAddressSpace().equals(space) ||
nextAddr.subtract(addr) > extBlockSize) {
startAddr = addr;
break;
}
}
if (startAddr != null) {
memory.createUninitializedBlock(blockName, startAddr, extBlockSize, false);
return startAddr;
}
throw new MemoryAccessException("Failed to allocate block: " + blockName);
}
private boolean relocateV1(Address pdwTablePayloadAddr, int entryCount, MessageLog log,
TaskMonitor monitor) throws CancelledException {
Listing listing = program.getListing();
Data d = listing.getDefinedDataAt(pdwTablePayloadAddr);
if (d != null && (d.isArray() || d.isStructure())) {
return false; // silent - appears to have been previously processed
}
Memory memory = program.getMemory();
DataTypeManager dtm = program.getDataTypeManager();
RelocationTable relocationTable = program.getRelocationTable();
Address addr = pdwTablePayloadAddr;
DumbMemBufferImpl buf = new DumbMemBufferImpl(memory, pdwTablePayloadAddr);
RelocationResult appliedResult = new RelocationResult(Status.APPLIED_OTHER, 4);
// relocation result counters
int applied = 0;
int failed = 0;
for (int i = 0; i < entryCount; i++) {
monitor.checkCancelled();
RelocationResult result = appliedResult;
int dwOffset = 0;
try {
dwOffset = buf.getInt(0);
}
catch (MemoryAccessException e1) {
log.appendMsg("Failed to read Mingw pseudo-relocation offset at: " + addr);
return false;
}
addr = addr.add(4);
buf.setPosition(addr); // position on 2nd value
Address targetAddr = getDWAddress(buf);
if (targetAddr == null) {
log.appendMsg("Failed to read Mingw pseudo-relocation target RVA at: " + addr);
return false;
}
try {
int val32 = memory.getInt(targetAddr) + dwOffset;
memory.setInt(targetAddr, val32);
++applied;
}
catch (Exception e) {
markAsError(targetAddr, e.getMessage(), log);
result = RelocationResult.FAILURE;
++failed;
}
relocationTable.add(targetAddr, result.status(), 0, null, result.byteLength(), null);
addr = addr.add(4);
buf.setPosition(addr); // position on next element
}
if (failed != 0) {
log.appendMsg("MinGW pseudo-relocations - applied:" + applied + " failed:" + failed);
}
Structure s = new StructureDataType(V1_RELOC_ITEM_STRUCT_NAME, 0, dtm);
s.setPackingEnabled(true);
s.add(DWordDataType.dataType, "addend", null);
s.add(DWordDataType.dataType, "target", null); // may be offcut
Array a = new ArrayDataType(s, entryCount, -1, dtm);
try {
DataUtilities.createData(program, pdwTablePayloadAddr, a, -1, false,
ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
Msg.error(this,
"Failed to markup Mingw pseudo-relocation Table at: " + pdwTablePayloadAddr);
}
return true;
}
}

View file

@ -103,6 +103,7 @@ public class RelocationTablePlugin extends Plugin implements DomainObjectListene
@Override @Override
public void domainObjectChanged(DomainObjectChangedEvent ev) { public void domainObjectChanged(DomainObjectChangedEvent ev) {
if (ev.containsEvent(ChangeManager.DOCR_IMAGE_BASE_CHANGED) || if (ev.containsEvent(ChangeManager.DOCR_IMAGE_BASE_CHANGED) ||
ev.containsEvent(ChangeManager.DOCR_RELOCATION_ADDED) ||
ev.containsEvent(DomainObject.DO_OBJECT_RESTORED)) { ev.containsEvent(DomainObject.DO_OBJECT_RESTORED)) {
provider.setProgram(currentProgram); provider.setProgram(currentProgram);
} }

View file

@ -184,7 +184,7 @@ public class FlatProgramAPI {
* only necessary to analyze changes and not the entire program which can take much * only necessary to analyze changes and not the entire program which can take much
* longer and affect more of the program than is necessary. * longer and affect more of the program than is necessary.
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public void analyze(Program program) { public void analyze(Program program) {
analyzeAll(program); analyzeAll(program);
} }
@ -405,7 +405,7 @@ public class FlatProgramAPI {
* @deprecated use {@link #createLabel(Address, String, boolean)} instead. * @deprecated use {@link #createLabel(Address, String, boolean)} instead.
* Deprecated in Ghidra 7.4 * Deprecated in Ghidra 7.4
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final Symbol createSymbol(Address address, String name, boolean makePrimary) public final Symbol createSymbol(Address address, String name, boolean makePrimary)
throws Exception { throws Exception {
return createLabel(address, name, makePrimary); return createLabel(address, name, makePrimary);
@ -443,9 +443,8 @@ public class FlatProgramAPI {
*/ */
public final Symbol createLabel(Address address, String name, Namespace namespace, public final Symbol createLabel(Address address, String name, Namespace namespace,
boolean makePrimary, SourceType sourceType) throws Exception { boolean makePrimary, SourceType sourceType) throws Exception {
Symbol symbol;
SymbolTable symbolTable = currentProgram.getSymbolTable(); SymbolTable symbolTable = currentProgram.getSymbolTable();
symbol = symbolTable.createLabel(address, name, namespace, sourceType); Symbol symbol = symbolTable.createLabel(address, name, namespace, sourceType);
if (makePrimary && !symbol.isPrimary()) { if (makePrimary && !symbol.isPrimary()) {
SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(address, name, namespace); SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(address, name, namespace);
if (cmd.applyTo(currentProgram)) { if (cmd.applyTo(currentProgram)) {
@ -458,7 +457,7 @@ public class FlatProgramAPI {
/** /**
* @deprecated use {@link #createLabel(Address, String, boolean, SourceType)} instead. Deprecated in Ghidra 7.4 * @deprecated use {@link #createLabel(Address, String, boolean, SourceType)} instead. Deprecated in Ghidra 7.4
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final Symbol createSymbol(Address address, String name, boolean makePrimary, public final Symbol createSymbol(Address address, String name, boolean makePrimary,
boolean makeUnique, SourceType sourceType) throws Exception { boolean makeUnique, SourceType sourceType) throws Exception {
return createLabel(address, name, makePrimary, sourceType); return createLabel(address, name, makePrimary, sourceType);
@ -1129,7 +1128,7 @@ public class FlatProgramAPI {
* no longer have to be unique. Use {@link #getGlobalFunctions(String)} * no longer have to be unique. Use {@link #getGlobalFunctions(String)}
* Deprecated in Ghidra 7.4 * Deprecated in Ghidra 7.4
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final Function getFunction(String name) { public final Function getFunction(String name) {
List<Function> globalFunctions = currentProgram.getListing().getGlobalFunctions(name); List<Function> globalFunctions = currentProgram.getListing().getGlobalFunctions(name);
return globalFunctions.isEmpty() ? null : globalFunctions.get(0); return globalFunctions.isEmpty() ? null : globalFunctions.get(0);
@ -1383,7 +1382,7 @@ public class FlatProgramAPI {
* @deprecated Since the same label name can be at the same address if in a different namespace, * @deprecated Since the same label name can be at the same address if in a different namespace,
* this method is ambiguous. Use {@link #getSymbolAt(Address, String, Namespace)} instead. * this method is ambiguous. Use {@link #getSymbolAt(Address, String, Namespace)} instead.
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final Symbol getSymbolAt(Address address, String name) { public final Symbol getSymbolAt(Address address, String name) {
SymbolIterator symbols = currentProgram.getSymbolTable().getSymbolsAsIterator(address); SymbolIterator symbols = currentProgram.getSymbolTable().getSymbolsAsIterator(address);
for (Symbol symbol : symbols) { for (Symbol symbol : symbols) {
@ -1477,7 +1476,7 @@ public class FlatProgramAPI {
* @throws IllegalStateException if there is more than one symbol with that name. * @throws IllegalStateException if there is more than one symbol with that name.
* @deprecated use {@link #getSymbols(String, Namespace)} * @deprecated use {@link #getSymbols(String, Namespace)}
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final Symbol getSymbol(String name, Namespace namespace) { public final Symbol getSymbol(String name, Namespace namespace) {
List<Symbol> symbols = currentProgram.getSymbolTable().getSymbols(name, namespace); List<Symbol> symbols = currentProgram.getSymbolTable().getSymbols(name, namespace);
if (symbols.size() == 1) { if (symbols.size() == 1) {
@ -1583,7 +1582,7 @@ public class FlatProgramAPI {
* @deprecated This method is deprecated because it did not allow you to include the * @deprecated This method is deprecated because it did not allow you to include the
* largest possible address. Instead use the one that takes a start address and a length. * largest possible address. Instead use the one that takes a start address and a length.
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final ProgramFragment createFragment(String fragmentName, Address start, Address end) public final ProgramFragment createFragment(String fragmentName, Address start, Address end)
throws DuplicateNameException, NotFoundException { throws DuplicateNameException, NotFoundException {
ProgramModule module = currentProgram.getListing().getDefaultRootModule(); ProgramModule module = currentProgram.getListing().getDefaultRootModule();
@ -1617,7 +1616,7 @@ public class FlatProgramAPI {
* @deprecated This method is deprecated because it did not allow you to include the * @deprecated This method is deprecated because it did not allow you to include the
* largest possible address. Instead use the one that takes a start address and a length. * largest possible address. Instead use the one that takes a start address and a length.
*/ */
@Deprecated @Deprecated(since = "7.4", forRemoval = true)
public final ProgramFragment createFragment(ProgramModule module, String fragmentName, public final ProgramFragment createFragment(ProgramModule module, String fragmentName,
Address start, Address end) throws DuplicateNameException, NotFoundException { Address start, Address end) throws DuplicateNameException, NotFoundException {
ProgramFragment fragment = getFragment(module, fragmentName); ProgramFragment fragment = getFragment(module, fragmentName);

View file

@ -19,12 +19,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.app.util.demangler.DemangledAddressTable; import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.DemangledException;
import ghidra.app.util.demangler.DemangledFunction;
import ghidra.app.util.demangler.DemangledObject;
import ghidra.app.util.demangler.Demangler;
import ghidra.app.util.demangler.DemanglerOptions;
import ghidra.app.util.opinion.ElfLoader; import ghidra.app.util.opinion.ElfLoader;
import ghidra.app.util.opinion.MachoLoader; import ghidra.app.util.opinion.MachoLoader;
import ghidra.framework.Application; import ghidra.framework.Application;
@ -66,6 +61,7 @@ public class GnuDemangler implements Demangler {
if (!specId.toLowerCase().contains("windows")) { if (!specId.toLowerCase().contains("windows")) {
return true; return true;
} }
return false; return false;
} }

View file

@ -31,6 +31,7 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.reloc.Relocation; import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status; import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationTable; import ghidra.program.model.reloc.RelocationTable;
import ghidra.program.util.ChangeManager;
import ghidra.util.Lock; import ghidra.util.Lock;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
@ -147,9 +148,15 @@ public class RelocationManager implements RelocationTable, ManagerDB {
try { try {
byte flags = RelocationDBAdapter.getFlags(status, 0); byte flags = RelocationDBAdapter.getFlags(status, 0);
adapter.add(addr, flags, type, values, bytes, symbolName); adapter.add(addr, flags, type, values, bytes, symbolName);
return new Relocation(addr, status, type, values, Relocation reloc = new Relocation(addr, status, type, values,
getOriginalBytes(addr, status, bytes, 0), getOriginalBytes(addr, status, bytes, 0),
symbolName); symbolName);
// fire event
// TODO: full change support is missing
program.setChanged(ChangeManager.DOCR_RELOCATION_ADDED, null, reloc);
return reloc;
} }
catch (IOException e) { catch (IOException e) {
program.dbError(e); program.dbError(e);
@ -167,9 +174,15 @@ public class RelocationManager implements RelocationTable, ManagerDB {
try { try {
byte flags = RelocationDBAdapter.getFlags(status, byteLength); byte flags = RelocationDBAdapter.getFlags(status, byteLength);
adapter.add(addr, flags, type, values, null, symbolName); adapter.add(addr, flags, type, values, null, symbolName);
return new Relocation(addr, status, type, values, Relocation reloc = new Relocation(addr, status, type, values,
getOriginalBytes(addr, status, null, byteLength), getOriginalBytes(addr, status, null, byteLength),
symbolName); symbolName);
// fire event
// TODO: full change support is missing
program.setChanged(ChangeManager.DOCR_RELOCATION_ADDED, null, reloc);
return reloc;
} }
catch (IOException e) { catch (IOException e) {
program.dbError(e); program.dbError(e);

View file

@ -179,16 +179,25 @@ public abstract class AbstractPointerTypedefBuiltIn extends BuiltIn implements T
@Override @Override
public Class<?> getValueClass(Settings settings) { public Class<?> getValueClass(Settings settings) {
if (settings == null) {
settings = getDefaultSettings();
}
return modelTypedef.getValueClass(settings); return modelTypedef.getValueClass(settings);
} }
@Override @Override
public Object getValue(MemBuffer buf, Settings settings, int length) { public Object getValue(MemBuffer buf, Settings settings, int length) {
if (settings == null) {
settings = getDefaultSettings();
}
return modelTypedef.getValue(buf, settings, length); return modelTypedef.getValue(buf, settings, length);
} }
@Override @Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) { public String getRepresentation(MemBuffer buf, Settings settings, int length) {
if (settings == null) {
settings = getDefaultSettings();
}
return modelTypedef.getRepresentation(buf, settings, length); return modelTypedef.getRepresentation(buf, settings, length);
} }

View file

@ -724,6 +724,17 @@ public interface ChangeManager {
*/ */
public static final int DOCR_USER_DATA_CHANGED = 201; public static final int DOCR_USER_DATA_CHANGED = 201;
////////////////////////////////////////////////////////////////////////////
//
// RELOCATIONS
//
////////////////////////////////////////////////////////////////////////////
/**
* A relocation entry was added
*/
public static final int DOCR_RELOCATION_ADDED = 210;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
/** /**
* Mark the state of a Program as having changed and generate * Mark the state of a Program as having changed and generate