mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
8fbdec4eca
13 changed files with 174 additions and 91 deletions
|
@ -6,6 +6,38 @@
|
|||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
<H1 align="center">Ghidra 9.1.1 Change History (December 2019)</H1>
|
||||
<blockquote><p><u>Improvements</u></p>
|
||||
<ul>
|
||||
<li><I>Importer:MachO</I>. Improved import/load time of DYLD shared cache files. (GT-3261)</li>
|
||||
<li><I>Program API</I>. Cached the addresses that correspond to executable memory to improve analysis performance. (GT-3260)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<blockquote><p><u>Bugs</u></p>
|
||||
<ul>
|
||||
<li><I>Analysis</I>. Fixed a symbol name error that occurred in the Objective-C analyzer. (GT-3321, Issue #1200)</li>
|
||||
<li><I>Analysis</I>. Constant references are now computed correctly within functions in overlay spaces. (GT-3373)</li>
|
||||
<li><I>Build</I>. Corrected build of <B>DMG.jar</B> which was improperly built within Ghidra 9.1 release. (GT-3364)</li>
|
||||
<li><I>Decompiler</I>. Fixed bug causing <code>Pcode: XML comms: Badly formed address</code> errors when decompiling HCS12 <code>XGATE</code> code. (GT-3297)</li>
|
||||
<li><I>Decompiler</I>. Fixed <code>Array DataType must be Fixed length</code> exceptions related to function pointer data types. (GT-3309)</li>
|
||||
<li><I>Decompiler</I>. Fixed bug causing decompiler to drop statements, assigning string constants to global variables. (GT-3315)</li>
|
||||
<li><I>Decompiler</I>. Fixed issue with enum name strings causing <code>Low-level Error: XML error: syntax error</code> in the decompiler. (GT-3387, Issue #1329)</li>
|
||||
<li><I>GUI</I>. Fixed a potential ConcurrentModificationException in the interactive python interpreter. (GT-3280)</li>
|
||||
<li><I>Importer:PE</I>. Fixed an exception in the PeLoader that occurred when the size of the memory block for the headers is larger than the file size. (GT-3344, Issue #1266)</li>
|
||||
<li><I>Languages</I>. Corrected Sparc floating point instruction pcode implementation. (GT-3202)</li>
|
||||
<li><I>Languages</I>. Corrected the semantics of the PowerPC <code>e_cmpi</code> instruction. (GT-3228, Issue #1127)</li>
|
||||
<li><I>Languages</I>. Corrected bit generation for PowerPC instructions <code>se_bclri</code>, <code>se_bgeni</code>, <code>se_bseti</code>, and <code>se_btsti</code>. (GT-3232, Issue #967)</li>
|
||||
<li><I>Languages</I>. Corrected register definitions for x86 <code>RDRAND</code> instruction. (GT-3253, Issue #1169)</li>
|
||||
<li><I>Languages</I>. Corrected signed immediate calculation for some powerPC VLE offsets being incorrect. (GT-3254, Issue #1160)</li>
|
||||
<li><I>Languages</I>. Resolved issue with x86 escape opcodes preventing certain instruction patterns from decoding. (GT-3256)</li>
|
||||
<li><I>Languages</I>. Corrected bug in <code>XGATE</code> <code>LDH</code> instruction shifting out high bits. (GT-3268)</li>
|
||||
<li><I>Languages</I>. Corrected processing of <code>R_MIPS_REL32</code>, <code>R_X86_64_RELATIVE</code>, and <code>R_X86_64_RELATIVE64</code> ELF relocations affecting relocatable binaries which have non-zero section/segment load addresses. (GT-3349)</li>
|
||||
<li><I>Listing</I>. Fixed missing scroll bar in listing. (GT-3290)</li>
|
||||
<li><I>Listing</I>. Fixed issue that was causing a stack trace to be generated when contiguous addresses were cleared for a range greater than <code>Integer.MAX</code>. (GT-3357)</li>
|
||||
<li><I>Listing:References</I>. Corrected <B>Create Default Reference</B> action bug which did not handle composite/array data components properly. (GT-3371)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
|
||||
<H1 align="center">Ghidra 9.1 Change History (October 2019)</H1>
|
||||
<blockquote><p><u>New Features</u></p>
|
||||
<ul>
|
||||
|
@ -107,7 +139,7 @@
|
|||
<blockquote><p><u>Bugs</u></p>
|
||||
<ul>
|
||||
<li><I>Analysis</I>. Fixed an exception in the EmbeddedMediaAnalyzer that occurred when media was discovered at the very end of the address space. (GT-2890)</li>
|
||||
<li><I>Analysis</I>. Recognition and disassembly of the FMA, F16C, and several missing AVX instructions have been added to the base x86 processor specification. The pcode for these instructions is pseudo-op and not a full pcode implementation. (GT-3168)</li>
|
||||
<li><I>Analysis</I>. Recognition and disassembly of the <code>FMA</code>, <code>F16C</code>, and several missing <code>AVX</code> instructions have been added to the base x86 processor specification. The pcode for these instructions is pseudo-op and not a full pcode implementation. (GT-3168)</li>
|
||||
<li><I>Basic Infrastructure</I>. Updated the apache-commons-lang3 library to version 3.9 which supports Java 11. (GT-2879)</li>
|
||||
<li><I>Basic Infrastructure</I>. Prevented Ghidra from launching with 32-bit Java installations. (GT-3146, Issue #882)</li>
|
||||
<li><I>Data Types</I>. Corrected string data default label generation when defined within uninitialized memory, which will now render as <code>STRING_<I>address</I></code>. (GT-2715, Issue #272)</li>
|
||||
|
@ -204,7 +236,7 @@
|
|||
<li><I>Project Manager</I>. Fixed a path traversal vulnerability that could occur when restoring a malicious project archive. (GT-3001, Issue #789)</li>
|
||||
<li><I>Scripting</I>. <code>GhidraScript.askDomainFile()</code> now correctly throws a CancelledException when the cancel button is clicked. (GT-2841)</li>
|
||||
<li><I>Scripting</I>. Removed deprecated scripting methods older than 5 releases. (GT-2949)</li>
|
||||
<li><I>Security</I>. Removed use of insecure XMLEncoder/XMLDecoder from Ghidra code base. (GT-3198, Issue #1090)</li>
|
||||
<li><I>Security</I>. Removed use of nonsecure XMLEncoder/XMLDecoder from Ghidra code base. (GT-3198, Issue #1090)</li>
|
||||
<li><I>Sleigh</I>. Corrected Sleigh compiler bug which performed improper bounds checking for named register offset specification when space wordsize is not one (1). (GT-3034, Issue #831)</li>
|
||||
<li><I>Testing:CUnits</I>. Fixed error logging in pcodetest for reporting an error when running a compile command. (GT-3199, Issue #1089)</li>
|
||||
<li><I>Version Tracking</I>. Fixed NullPointerException in Version Tracking hashing algorithm. (GT-2976)</li>
|
||||
|
|
|
@ -45,6 +45,7 @@ public class CreateDataCmd implements Command {
|
|||
/**
|
||||
* Constructs a command for creating data at an address.
|
||||
* Simple pointer conversion will NOT be performed.
|
||||
* Existing Undefined data will always be cleared even when force is false.
|
||||
* @param addr the address at which to apply the datatype. Offcut data
|
||||
* address allowed, provided force==true.
|
||||
* @param force if true any existing conflicting data will be cleared
|
||||
|
@ -75,7 +76,8 @@ public class CreateDataCmd implements Command {
|
|||
/**
|
||||
* Constructs a command for creating data at an address.
|
||||
* Simple pointer conversion will NOT be performed and existing
|
||||
* data will not be cleared.
|
||||
* defined data will not be cleared, however existing Undefined data will
|
||||
* be cleared.
|
||||
* @param addr the address at which to apply the datatype.
|
||||
* @param dataType the datatype to be applied at the given address.
|
||||
*/
|
||||
|
@ -86,7 +88,7 @@ public class CreateDataCmd implements Command {
|
|||
/**
|
||||
* This is the same as {@link #CreateDataCmd(Address, DataType)} except that
|
||||
* it allows the caller to control whether or not pointer conversion should be handled.
|
||||
*
|
||||
* Existing Undefined data will always be cleared.
|
||||
* @param addr the address at which to apply the datatype.
|
||||
* @param dataType the datatype to be applied at the given address.
|
||||
* @param isCycle true indicates this is from a cycle group action.
|
||||
|
|
|
@ -51,7 +51,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
private List<Address> referringThunkAddresses = new ArrayList<>();
|
||||
private boolean checkForSideEffects = true;
|
||||
|
||||
private static final int MAX_NUMBER_OF_THUNKING_INSTRUCTIONS = 5;
|
||||
private static final int MAX_NUMBER_OF_THUNKING_INSTRUCTIONS = 8;
|
||||
|
||||
static String DEFAULT_FUNCTION_COMMENT = " THUNK-FUNCTION";
|
||||
|
||||
|
@ -269,10 +269,10 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
}
|
||||
referencedFunctionAddr = referencedSymbol.getAddress();
|
||||
}
|
||||
else if ((referencedFunctionAddr == null || referencedFunctionAddr == Address.NO_ADDRESS) && autoThunkOK) {
|
||||
else if ((referencedFunctionAddr == null || referencedFunctionAddr == Address.NO_ADDRESS) &&
|
||||
autoThunkOK) {
|
||||
// first try to get the address that is already there
|
||||
referencedFunctionAddr =
|
||||
getThunkedExternalFunctionAddress(program, entry);
|
||||
referencedFunctionAddr = getThunkedExternalFunctionAddress(program, entry);
|
||||
if (referencedFunctionAddr == null) {
|
||||
referencedFunctionAddr = getThunkedAddr(program, entry, checkForSideEffects);
|
||||
}
|
||||
|
@ -280,7 +280,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
if (referencedFunctionAddr == null || referencedFunctionAddr == Address.NO_ADDRESS) {
|
||||
try {
|
||||
if (resolveComputableFlow(program, entry, monitor)) {
|
||||
referencedFunctionAddr = getThunkedAddr(program, entry, checkForSideEffects);
|
||||
referencedFunctionAddr =
|
||||
getThunkedAddr(program, entry, checkForSideEffects);
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
|
@ -479,7 +480,6 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
return referencedFunction;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* if the code starting at entry is a thunk, return the thunked addess if known.
|
||||
*
|
||||
|
@ -500,7 +500,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
*
|
||||
* @return address that the thunk thunks,Address.NO_ADDRESS if thunk but unknown addr, null otherwise
|
||||
*/
|
||||
public static Address getThunkedAddr(Program program, Address entry, boolean checkForSideEffects) {
|
||||
public static Address getThunkedAddr(Program program, Address entry,
|
||||
boolean checkForSideEffects) {
|
||||
// General algorithm:
|
||||
//
|
||||
// get function, if has no other calls, and no other flow
|
||||
|
@ -566,8 +567,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
}
|
||||
|
||||
// record any used registers, checking for use of an unexpected unset register
|
||||
if (!addRegisterUsage(program, setAtStartRegisters, setRegisters, usedRegisters, pcodeOp,
|
||||
allow8bitNonUse)) {
|
||||
if (checkForSideEffects && !addRegisterUsage(program, setAtStartRegisters,
|
||||
setRegisters, usedRegisters, pcodeOp, allow8bitNonUse)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -586,8 +587,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
}
|
||||
|
||||
// reached a flow, end of the line, gotta see what we have
|
||||
return getFlowingAddrFromFinalState(program, instr, flowType,
|
||||
checkForSideEffects, setRegisters, usedRegisters);
|
||||
return getFlowingAddrFromFinalState(program, instr, flowType, checkForSideEffects,
|
||||
setRegisters, usedRegisters);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -664,8 +665,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
}
|
||||
|
||||
private static Address getFlowingAddrFromFinalState(Program program, Instruction instr,
|
||||
FlowType flowType, boolean checkForSideEffects,
|
||||
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters) {
|
||||
FlowType flowType, boolean checkForSideEffects, HashSet<Varnode> setRegisters,
|
||||
HashSet<Varnode> usedRegisters) {
|
||||
|
||||
// conditional jumps can't be thunks.
|
||||
// any other flow, not good
|
||||
|
@ -736,8 +737,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
|||
* false if input register found that was not initialized
|
||||
*/
|
||||
private static boolean addRegisterUsage(Program program, HashSet<Varnode> setAtStartRegisters,
|
||||
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters,
|
||||
PcodeOp pcode, boolean allow8bitNonUse) {
|
||||
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters, PcodeOp pcode,
|
||||
boolean allow8bitNonUse) {
|
||||
int opcode = pcode.getOpcode();
|
||||
Varnode output = pcode.getOutput();
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -21,7 +20,6 @@ import ghidra.program.model.listing.Function;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* Organizational class to record vital data used by a DwarfEHDecoder.
|
||||
|
@ -33,12 +31,10 @@ public class DwarfDecodeContext {
|
|||
private final MemoryBlock ehBlock;
|
||||
private final Address functionEntryPoint;
|
||||
|
||||
private final ProgramLocation loc;
|
||||
private Object decodedValue;
|
||||
private int encodedLength;
|
||||
private MemBuffer buffer;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Dwarf decode context.
|
||||
* @param program the program containing the encoded data
|
||||
|
@ -85,7 +81,8 @@ public class DwarfDecodeContext {
|
|||
* @param ehBlock the exception handling memory block
|
||||
* @param entryPoint the associated function's entry point
|
||||
*/
|
||||
public DwarfDecodeContext(Program program, Address readAddr, MemoryBlock ehBlock, Address entryPoint) {
|
||||
public DwarfDecodeContext(Program program, Address readAddr, MemoryBlock ehBlock,
|
||||
Address entryPoint) {
|
||||
|
||||
if (program == null) {
|
||||
throw new NullPointerException("DwarfDecodeContext requires a program");
|
||||
|
@ -99,7 +96,6 @@ public class DwarfDecodeContext {
|
|||
this.ehBlock = ehBlock;
|
||||
this.functionEntryPoint = entryPoint;
|
||||
|
||||
this.loc = new ProgramLocation(program, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,16 +120,6 @@ public class DwarfDecodeContext {
|
|||
this.addr = buffer.getAddress();
|
||||
this.ehBlock = ehBlock;
|
||||
this.functionEntryPoint = entryPoint;
|
||||
|
||||
this.loc = new ProgramLocation(program, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of the encoded data.
|
||||
* @return the program location
|
||||
*/
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -80,9 +81,14 @@ public abstract class GccAnalysisClass {
|
|||
* @param dt the type for the data
|
||||
*/
|
||||
protected static void createData(Program program, Address addr, DataType dt) {
|
||||
|
||||
CreateDataCmd dataCmd = new CreateDataCmd(addr, dt);
|
||||
dataCmd.applyTo(program);
|
||||
try {
|
||||
// try creating without clearing, the code units should be clear
|
||||
program.getListing().createData(addr, dt);
|
||||
}
|
||||
catch (CodeUnitInsertionException | DataTypeConflictException e) {
|
||||
CreateDataCmd dataCmd = new CreateDataCmd(addr, dt);
|
||||
dataCmd.applyTo(program);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -84,20 +83,26 @@ public class DebugFrameSection extends AbstractFrameSection {
|
|||
}
|
||||
|
||||
private List<RegionDescriptor> analyzeSection(MemoryBlock curMemBlock)
|
||||
throws MemoryAccessException, AddressOutOfBoundsException, ExceptionHandlerFrameException {
|
||||
|
||||
throws MemoryAccessException, AddressOutOfBoundsException,
|
||||
ExceptionHandlerFrameException {
|
||||
|
||||
monitor.setMessage("Analyzing " + curMemBlock.getName() + " section");
|
||||
monitor.setShowProgressValue(true);
|
||||
monitor.setIndeterminate(true);
|
||||
monitor.setIndeterminate(false);
|
||||
|
||||
ProgramLocation loc = new ProgramLocation(program, curMemBlock.getStart());
|
||||
Address curAddress = loc.getAddress();
|
||||
|
||||
List<RegionDescriptor> regions = new ArrayList<>();
|
||||
|
||||
if (curAddress != null) {
|
||||
monitor.setMaximum(curMemBlock.getEnd().subtract(curAddress));
|
||||
}
|
||||
|
||||
while (curAddress != null && curAddress.compareTo(curMemBlock.getEnd()) < 0) {
|
||||
if (monitor.isCancelled()) {
|
||||
return regions;
|
||||
}
|
||||
|
||||
/* Get the Common Information Entry */
|
||||
Cie cie = getCie(curAddress);
|
||||
|
@ -112,8 +117,12 @@ public class DebugFrameSection extends AbstractFrameSection {
|
|||
/*
|
||||
* Add each Frame Description Entry (FDE) for the current CIE.
|
||||
*/
|
||||
List<RegionDescriptor> newRegions = new ArrayList<>();
|
||||
|
||||
while (curAddress != null && (curAddress.compareTo(curMemBlock.getEnd()) < 0)) {
|
||||
|
||||
monitor.setProgress(curAddress.subtract(loc.getAddress()));
|
||||
|
||||
Address currFdeAddr = curAddress;
|
||||
|
||||
try {
|
||||
|
@ -126,23 +135,24 @@ public class DebugFrameSection extends AbstractFrameSection {
|
|||
}
|
||||
|
||||
if (region != null) {
|
||||
regions.add(region);
|
||||
newRegions.add(region);
|
||||
createFdeComment(curAddress);
|
||||
monitor.incrementProgress(1);
|
||||
}
|
||||
|
||||
curAddress = fde.getNextAddress(); // This can be null.
|
||||
|
||||
} catch (ExceptionHandlerFrameException efe) {
|
||||
}
|
||||
catch (ExceptionHandlerFrameException efe) {
|
||||
// May have run into another CIE.
|
||||
curAddress = currFdeAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
createAugmentationData(regions, cie);
|
||||
createAugmentationData(newRegions, cie);
|
||||
|
||||
regions.addAll(newRegions);
|
||||
}
|
||||
return regions;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,21 @@ package ghidra.app.plugin.exceptionhandlers.gcc.structures.ehFrame;
|
|||
|
||||
import ghidra.app.cmd.comments.SetCommentCmd;
|
||||
import ghidra.app.cmd.data.CreateArrayCmd;
|
||||
import ghidra.app.cmd.data.CreateDataCmd;
|
||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||
import ghidra.app.plugin.exceptionhandlers.gcc.*;
|
||||
import ghidra.app.plugin.exceptionhandlers.gcc.datatype.UnsignedLeb128DataType;
|
||||
import ghidra.app.plugin.exceptionhandlers.gcc.sections.CieSource;
|
||||
import ghidra.app.plugin.exceptionhandlers.gcc.sections.DebugFrameSection;
|
||||
import ghidra.app.plugin.exceptionhandlers.gcc.structures.gccexcepttable.LSDATable;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -265,8 +268,18 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
|||
DataType encodedDt = cie.getFDEDecoder().getDataType(program);
|
||||
|
||||
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
||||
program.getReferenceManager().addMemoryReference(addr, pcBeginAddr, RefType.DATA,
|
||||
SourceType.ANALYSIS, 0);
|
||||
if (pcBeginAddr.getOffset() != 0x0) {
|
||||
// if the program was moved from a preferred image base, need to adjust
|
||||
// the beginning of frame pointer
|
||||
Long oib = ElfLoader.getElfOriginalImageBase(program);
|
||||
if (oib != null) {
|
||||
long imageBaseOffset = program.getImageBase().getOffset() - oib;
|
||||
pcBeginAddr = pcBeginAddr.add(imageBaseOffset);
|
||||
}
|
||||
|
||||
program.getReferenceManager().addMemoryReference(addr, pcBeginAddr, RefType.DATA,
|
||||
SourceType.ANALYSIS, 0);
|
||||
}
|
||||
|
||||
curSize += encodedLen;
|
||||
return addr.add(encodedLen);
|
||||
|
@ -386,8 +399,14 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
|||
|
||||
// Create initial instructions array with remaining bytes.
|
||||
int instructionLength = intLength - curSize;
|
||||
arrayCmd = new CreateArrayCmd(addr, instructionLength, new ByteDataType(), BYTE_LEN);
|
||||
arrayCmd.applyTo(program);
|
||||
ArrayDataType adt = new ArrayDataType(ByteDataType.dataType, instructionLength, BYTE_LEN);
|
||||
try {
|
||||
program.getListing().createData(addr, adt, adt.getLength());
|
||||
}
|
||||
catch (CodeUnitInsertionException e) {
|
||||
CreateDataCmd dataCmd = new CreateDataCmd(addr, adt);
|
||||
dataCmd.applyTo(program);
|
||||
}
|
||||
|
||||
SetCommentCmd.createComment(program, addr, "(FDE) Call Frame Instructions",
|
||||
CodeUnit.EOL_COMMENT);
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.util.demangler;
|
|||
|
||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||
import ghidra.app.cmd.function.CreateThunkFunctionCmd;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.InstructionContext;
|
||||
import ghidra.program.model.listing.*;
|
||||
|
@ -110,8 +111,7 @@ public class DemangledThunk extends DemangledObject {
|
|||
function.setThunkedFunction(thunkedFunction);
|
||||
}
|
||||
|
||||
Symbol s =
|
||||
applyDemangledName(thunkAddress, function.isThunk(), false, program);
|
||||
Symbol s = applyDemangledName(thunkAddress, function.isThunk(), false, program);
|
||||
return s != null;
|
||||
}
|
||||
|
||||
|
@ -181,8 +181,15 @@ public class DemangledThunk extends DemangledObject {
|
|||
}
|
||||
|
||||
Symbol s = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
|
||||
thunkedFunctionObject.originalMangled, err -> Msg.error(this, err));
|
||||
thunkedFunctionObject.originalMangled, err -> Msg.warn(this, err));
|
||||
|
||||
if (s == null) {
|
||||
Address thunkedAddr =
|
||||
CreateThunkFunctionCmd.getThunkedAddr(program, thunkAddress, false);
|
||||
if (thunkedAddr != null) {
|
||||
s = program.getSymbolTable().getPrimarySymbol(thunkedAddr);
|
||||
}
|
||||
}
|
||||
if (s == null || !block.contains(s.getAddress())) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -502,6 +502,9 @@ public class GnuDemanglerParser implements DemanglerParser {
|
|||
if (pos == -1) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (str.endsWith(")")) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
DemangledObject dobj = parse(null, str.substring(0, pos));
|
||||
if (dobj == null) {
|
||||
|
|
|
@ -62,6 +62,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
"_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev");// virtual thunk
|
||||
demangle(process, parser, "_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE");// covariant return thunk
|
||||
|
||||
demangle(process, parser, "_ZNK2cc14ScrollSnapTypeneERKS0_");
|
||||
|
||||
List<String> list = loadTextResource(GnuDemanglerParserTest.class, "libMagick.symbols.txt");
|
||||
for (String mangled : list) {
|
||||
if (mangled == null) {
|
||||
|
@ -73,8 +75,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
System.out.println("Elapsed Time: " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
private void demangle(GnuDemanglerNativeProcess process, GnuDemanglerParser parser, String mangled)
|
||||
throws IOException {
|
||||
private void demangle(GnuDemanglerNativeProcess process, GnuDemanglerParser parser,
|
||||
String mangled) throws IOException {
|
||||
String demangled = process.demangle(mangled);
|
||||
assertNotNull(demangled);
|
||||
assertNotEquals(mangled, demangled);
|
||||
|
@ -165,6 +167,16 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
"covariant return thunk [nv:0] [nv:16] to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const");
|
||||
assertTrue(parse instanceof DemangledThunk);
|
||||
assertName(parse, "copy", "KHotKeys", "WindowTrigger");
|
||||
|
||||
try {
|
||||
parse = parser.parse(
|
||||
"_ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j",
|
||||
"GrGLFunction<unsigned char const* (unsigned int)>::GrGLFunction<skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0>(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)::{lambda(void const*, unsigned int)#1}::__invoke(void const*, unsigned int)");
|
||||
assertNull("Shouldn't have parsed", parser);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
// should get an exception
|
||||
}
|
||||
}
|
||||
|
||||
private void assertName(DemangledObject demangledObj, String name, String... namespaces) {
|
||||
|
@ -193,9 +205,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertTrue(object instanceof DemangledFunction);
|
||||
|
||||
assertEquals(
|
||||
"undefined glob_fn9(" +
|
||||
"char,int,long,long long,unsigned int,unsigned long,float,double,long double,bool,void *,void * *)",
|
||||
assertEquals("undefined glob_fn9(" +
|
||||
"char,int,long,long long,unsigned int,unsigned long,float,double,long double,bool,void *,void * *)",
|
||||
object.getSignature(false));
|
||||
}
|
||||
|
||||
|
|
|
@ -1358,7 +1358,8 @@ with : ARMcondCk=1 {
|
|||
|
||||
:hlt immed6 is TMode=1 & op6=0b1011101010 & immed6
|
||||
{
|
||||
software_hlt(immed6:4);
|
||||
pc = software_hlt(immed6:4);
|
||||
goto [pc];
|
||||
}
|
||||
|
||||
:bkpt immed8 is TMode=1 & ItCond & op8=0xbe & immed8
|
||||
|
@ -1384,14 +1385,16 @@ with : ARMcondCk=1 {
|
|||
:udf^ItCond "#"thc0007 is TMode=1 & ItCond & op8 = 0xde & thc0007
|
||||
{
|
||||
build ItCond;
|
||||
software_udf(thc0007:4);
|
||||
pc = software_udf(thc0007:4);
|
||||
goto [pc];
|
||||
}
|
||||
@endif
|
||||
|
||||
:udf^ItCond "#"tmp is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0xa & thc0011 [tmp = thc0003 << 12 | thc0011;]
|
||||
{
|
||||
build ItCond;
|
||||
software_udf(tmp:4);
|
||||
pc = software_udf(tmp:4);
|
||||
goto [pc];
|
||||
}
|
||||
|
||||
@endif # VERSION_5
|
||||
|
|
|
@ -193,11 +193,12 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
try {
|
||||
String symname = "_gp_" + index++;
|
||||
// check if it already exists
|
||||
Symbol existingSymbol = SymbolUtilities.getLabelOrFunctionSymbol(program, symname,
|
||||
err -> { /* ignore multiple symbols, if even one exists we need to skip if it has a different address */ } );
|
||||
Symbol existingSymbol =
|
||||
SymbolUtilities.getLabelOrFunctionSymbol(program, symname, err -> {
|
||||
/* ignore multiple symbols, if even one exists we need to skip if it has a different address */ });
|
||||
if (existingSymbol != null) {
|
||||
if (existingSymbol.getAddress().equals(toAddr)) {
|
||||
return existingSymbol;
|
||||
return existingSymbol;
|
||||
}
|
||||
continue; // can't use this one, look for the next free gp_<x> symbol
|
||||
}
|
||||
|
@ -223,14 +224,16 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
|
||||
final AddressSet coveredSet = new AddressSet();
|
||||
|
||||
Address currentGPAssumptionValue = gp_assumption_value;
|
||||
|
||||
if (func != null) {
|
||||
flowStart = func.getEntryPoint();
|
||||
if (gp_assumption_value != null) {
|
||||
if (currentGPAssumptionValue != null) {
|
||||
ProgramContext programContext = program.getProgramContext();
|
||||
RegisterValue gpVal = programContext.getRegisterValue(gp, flowStart);
|
||||
if (gpVal == null || !gpVal.hasValue()) {
|
||||
gpVal =
|
||||
new RegisterValue(gp, BigInteger.valueOf(gp_assumption_value.getOffset()));
|
||||
gpVal = new RegisterValue(gp,
|
||||
BigInteger.valueOf(currentGPAssumptionValue.getOffset()));
|
||||
try {
|
||||
program.getProgramContext().setRegisterValue(func.getEntryPoint(),
|
||||
func.getEntryPoint(), gpVal);
|
||||
|
@ -245,6 +248,7 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
// follow all flows building up context
|
||||
// use context to fill out addresses on certain instructions
|
||||
ContextEvaluator eval = new ConstantPropagationContextEvaluator(trustWriteMemOption) {
|
||||
private Address localGPAssumptionValue = currentGPAssumptionValue;
|
||||
|
||||
private boolean mustStopNow = false; // if something discovered in processing, mustStop flag
|
||||
|
||||
|
@ -297,8 +301,8 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
if (registerValue != null) {
|
||||
BigInteger value = registerValue.getUnsignedValue();
|
||||
long unsignedValue = value.longValue();
|
||||
if (gp_assumption_value == null ||
|
||||
!(unsignedValue == gp_assumption_value.getOffset())) {
|
||||
if (localGPAssumptionValue == null ||
|
||||
!(unsignedValue == localGPAssumptionValue.getOffset())) {
|
||||
synchronized (gp) {
|
||||
Address gpRefAddr =
|
||||
instr.getMinAddress().getNewAddress(unsignedValue);
|
||||
|
@ -317,18 +321,18 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
instr.getMinAddress().getAddressSpace().getBaseSpaceID(),
|
||||
unsignedValue, 1, RefType.DATA, PcodeOp.UNIMPLEMENTED, true,
|
||||
monitor);
|
||||
if (gp_assumption_value == null) {
|
||||
if (localGPAssumptionValue == null) {
|
||||
program.getBookmarkManager().setBookmark(
|
||||
lastSetInstr.getMinAddress(), BookmarkType.WARNING,
|
||||
"GP Global Register Set",
|
||||
"Global GP Register is set here.");
|
||||
}
|
||||
if (gp_assumption_value != null &&
|
||||
!gp_assumption_value.equals(gpRefAddr)) {
|
||||
gp_assumption_value = null;
|
||||
if (localGPAssumptionValue != null &&
|
||||
!localGPAssumptionValue.equals(gpRefAddr)) {
|
||||
localGPAssumptionValue = gp_assumption_value = null;
|
||||
}
|
||||
else {
|
||||
gp_assumption_value = gpRefAddr;
|
||||
localGPAssumptionValue = gp_assumption_value = gpRefAddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +406,8 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||
context.clearRegister(reg);
|
||||
|
||||
// need to add the reference here, register operand will no longer have a value
|
||||
instr.addOperandReference(0, addr, refType, SourceType.ANALYSIS);
|
||||
instr.addOperandReference(0, addr, refType,
|
||||
SourceType.ANALYSIS);
|
||||
|
||||
// set the register value on the target address
|
||||
ProgramContext progContext = program.getProgramContext();
|
||||
|
|
|
@ -213,18 +213,16 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
|||
waitForTasks();
|
||||
|
||||
// make some changes to check in
|
||||
Program program = (Program) ((DomainFileNode) node).getDomainFile()
|
||||
.getDomainObject(this,
|
||||
true, false, TaskMonitor.DUMMY);
|
||||
Program program = (Program) ((DomainFileNode) node).getDomainFile().getDomainObject(this,
|
||||
true, false, TaskMonitor.DUMMY);
|
||||
editProgram(program, (p) -> {
|
||||
SymbolTable symTable = p.getSymbolTable();
|
||||
symTable.createLabel(p.getMinAddress().getNewAddress(0x010001000), "fred",
|
||||
SourceType.USER_DEFINED);
|
||||
});
|
||||
|
||||
program = (Program) ((DomainFileNode) xnode).getDomainFile()
|
||||
.getDomainObject(this, true,
|
||||
false, TaskMonitor.DUMMY);
|
||||
program = (Program) ((DomainFileNode) xnode).getDomainFile().getDomainObject(this, true,
|
||||
false, TaskMonitor.DUMMY);
|
||||
editProgram(program, (p) -> {
|
||||
SymbolTable symTable = p.getSymbolTable();
|
||||
symTable.createLabel(p.getMinAddress(), "bob", SourceType.USER_DEFINED);
|
||||
|
@ -253,9 +251,8 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
|||
checkout(programNode);
|
||||
|
||||
Program program =
|
||||
(Program) ((DomainFileNode) programNode).getDomainFile()
|
||||
.getDomainObject(this, true,
|
||||
false, TaskMonitor.DUMMY);
|
||||
(Program) ((DomainFileNode) programNode).getDomainFile().getDomainObject(this, true,
|
||||
false, TaskMonitor.DUMMY);
|
||||
|
||||
createHistoryEntry(program, "Symbol1");
|
||||
frontEnd.checkIn(programNode, "This is checkin 1");
|
||||
|
@ -608,8 +605,9 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
|||
selectInTable(table, node);
|
||||
|
||||
DockingActionIf undoCheckoutAction = getAction("UndoCheckOut");
|
||||
assertTrue(undoCheckoutAction.isEnabledForContext(dialog.getActionContext(null)));
|
||||
performAction(undoCheckoutAction);
|
||||
ActionContext actionContext = dialog.getActionContext(null);
|
||||
assertTrue(undoCheckoutAction.isEnabledForContext(actionContext));
|
||||
performAction(undoCheckoutAction, actionContext, true);
|
||||
|
||||
waitForBusyTable(table);
|
||||
assertEquals(1, model.getRowCount());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue