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>
|
</HEAD>
|
||||||
|
|
||||||
<BODY>
|
<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>
|
<H1 align="center">Ghidra 9.1 Change History (October 2019)</H1>
|
||||||
<blockquote><p><u>New Features</u></p>
|
<blockquote><p><u>New Features</u></p>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -107,7 +139,7 @@
|
||||||
<blockquote><p><u>Bugs</u></p>
|
<blockquote><p><u>Bugs</u></p>
|
||||||
<ul>
|
<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>. 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>. 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>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>
|
<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>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>. <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>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>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>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>
|
<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.
|
* Constructs a command for creating data at an address.
|
||||||
* Simple pointer conversion will NOT be performed.
|
* 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
|
* @param addr the address at which to apply the datatype. Offcut data
|
||||||
* address allowed, provided force==true.
|
* address allowed, provided force==true.
|
||||||
* @param force if true any existing conflicting data will be cleared
|
* @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.
|
* Constructs a command for creating data at an address.
|
||||||
* Simple pointer conversion will NOT be performed and existing
|
* 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 addr the address at which to apply the datatype.
|
||||||
* @param dataType the datatype to be applied at the given address.
|
* @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
|
* 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.
|
* 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 addr the address at which to apply the datatype.
|
||||||
* @param dataType the datatype to be applied at the given address.
|
* @param dataType the datatype to be applied at the given address.
|
||||||
* @param isCycle true indicates this is from a cycle group action.
|
* @param isCycle true indicates this is from a cycle group action.
|
||||||
|
|
|
@ -50,8 +50,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
private Function referencedFunction;
|
private Function referencedFunction;
|
||||||
private List<Address> referringThunkAddresses = new ArrayList<>();
|
private List<Address> referringThunkAddresses = new ArrayList<>();
|
||||||
private boolean checkForSideEffects = true;
|
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";
|
static String DEFAULT_FUNCTION_COMMENT = " THUNK-FUNCTION";
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
Program program = (Program) obj;
|
Program program = (Program) obj;
|
||||||
|
|
||||||
FunctionManager functionMgr = program.getFunctionManager();
|
FunctionManager functionMgr = program.getFunctionManager();
|
||||||
|
|
||||||
if (referencedFunctionAddr == Address.NO_ADDRESS) {
|
if (referencedFunctionAddr == Address.NO_ADDRESS) {
|
||||||
referencedFunctionAddr = null;
|
referencedFunctionAddr = null;
|
||||||
}
|
}
|
||||||
|
@ -269,10 +269,10 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
referencedFunctionAddr = referencedSymbol.getAddress();
|
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
|
// first try to get the address that is already there
|
||||||
referencedFunctionAddr =
|
referencedFunctionAddr = getThunkedExternalFunctionAddress(program, entry);
|
||||||
getThunkedExternalFunctionAddress(program, entry);
|
|
||||||
if (referencedFunctionAddr == null) {
|
if (referencedFunctionAddr == null) {
|
||||||
referencedFunctionAddr = getThunkedAddr(program, entry, checkForSideEffects);
|
referencedFunctionAddr = getThunkedAddr(program, entry, checkForSideEffects);
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
if (referencedFunctionAddr == null || referencedFunctionAddr == Address.NO_ADDRESS) {
|
if (referencedFunctionAddr == null || referencedFunctionAddr == Address.NO_ADDRESS) {
|
||||||
try {
|
try {
|
||||||
if (resolveComputableFlow(program, entry, monitor)) {
|
if (resolveComputableFlow(program, entry, monitor)) {
|
||||||
referencedFunctionAddr = getThunkedAddr(program, entry, checkForSideEffects);
|
referencedFunctionAddr =
|
||||||
|
getThunkedAddr(program, entry, checkForSideEffects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
|
@ -479,7 +480,6 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
return referencedFunction;
|
return referencedFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if the code starting at entry is a thunk, return the thunked addess if known.
|
* 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
|
* @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:
|
// General algorithm:
|
||||||
//
|
//
|
||||||
// get function, if has no other calls, and no other flow
|
// 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
|
// record any used registers, checking for use of an unexpected unset register
|
||||||
if (!addRegisterUsage(program, setAtStartRegisters, setRegisters, usedRegisters, pcodeOp,
|
if (checkForSideEffects && !addRegisterUsage(program, setAtStartRegisters,
|
||||||
allow8bitNonUse)) {
|
setRegisters, usedRegisters, pcodeOp, allow8bitNonUse)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,8 +587,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reached a flow, end of the line, gotta see what we have
|
// reached a flow, end of the line, gotta see what we have
|
||||||
return getFlowingAddrFromFinalState(program, instr, flowType,
|
return getFlowingAddrFromFinalState(program, instr, flowType, checkForSideEffects,
|
||||||
checkForSideEffects, setRegisters, usedRegisters);
|
setRegisters, usedRegisters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -664,8 +665,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Address getFlowingAddrFromFinalState(Program program, Instruction instr,
|
private static Address getFlowingAddrFromFinalState(Program program, Instruction instr,
|
||||||
FlowType flowType, boolean checkForSideEffects,
|
FlowType flowType, boolean checkForSideEffects, HashSet<Varnode> setRegisters,
|
||||||
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters) {
|
HashSet<Varnode> usedRegisters) {
|
||||||
|
|
||||||
// conditional jumps can't be thunks.
|
// conditional jumps can't be thunks.
|
||||||
// any other flow, not good
|
// any other flow, not good
|
||||||
|
@ -736,8 +737,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
* false if input register found that was not initialized
|
* false if input register found that was not initialized
|
||||||
*/
|
*/
|
||||||
private static boolean addRegisterUsage(Program program, HashSet<Varnode> setAtStartRegisters,
|
private static boolean addRegisterUsage(Program program, HashSet<Varnode> setAtStartRegisters,
|
||||||
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters,
|
HashSet<Varnode> setRegisters, HashSet<Varnode> usedRegisters, PcodeOp pcode,
|
||||||
PcodeOp pcode, boolean allow8bitNonUse) {
|
boolean allow8bitNonUse) {
|
||||||
int opcode = pcode.getOpcode();
|
int opcode = pcode.getOpcode();
|
||||||
Varnode output = pcode.getOutput();
|
Varnode output = pcode.getOutput();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.listing.Program;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.util.ProgramLocation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Organizational class to record vital data used by a DwarfEHDecoder.
|
* Organizational class to record vital data used by a DwarfEHDecoder.
|
||||||
|
@ -33,12 +31,10 @@ public class DwarfDecodeContext {
|
||||||
private final MemoryBlock ehBlock;
|
private final MemoryBlock ehBlock;
|
||||||
private final Address functionEntryPoint;
|
private final Address functionEntryPoint;
|
||||||
|
|
||||||
private final ProgramLocation loc;
|
|
||||||
private Object decodedValue;
|
private Object decodedValue;
|
||||||
private int encodedLength;
|
private int encodedLength;
|
||||||
private MemBuffer buffer;
|
private MemBuffer buffer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Dwarf decode context.
|
* Constructs a Dwarf decode context.
|
||||||
* @param program the program containing the encoded data
|
* @param program the program containing the encoded data
|
||||||
|
@ -85,7 +81,8 @@ public class DwarfDecodeContext {
|
||||||
* @param ehBlock the exception handling memory block
|
* @param ehBlock the exception handling memory block
|
||||||
* @param entryPoint the associated function's entry point
|
* @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) {
|
if (program == null) {
|
||||||
throw new NullPointerException("DwarfDecodeContext requires a program");
|
throw new NullPointerException("DwarfDecodeContext requires a program");
|
||||||
|
@ -99,7 +96,6 @@ public class DwarfDecodeContext {
|
||||||
this.ehBlock = ehBlock;
|
this.ehBlock = ehBlock;
|
||||||
this.functionEntryPoint = entryPoint;
|
this.functionEntryPoint = entryPoint;
|
||||||
|
|
||||||
this.loc = new ProgramLocation(program, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,16 +120,6 @@ public class DwarfDecodeContext {
|
||||||
this.addr = buffer.getAddress();
|
this.addr = buffer.getAddress();
|
||||||
this.ehBlock = ehBlock;
|
this.ehBlock = ehBlock;
|
||||||
this.functionEntryPoint = entryPoint;
|
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.data.*;
|
||||||
import ghidra.program.model.listing.CodeUnit;
|
import ghidra.program.model.listing.CodeUnit;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,9 +81,14 @@ public abstract class GccAnalysisClass {
|
||||||
* @param dt the type for the data
|
* @param dt the type for the data
|
||||||
*/
|
*/
|
||||||
protected static void createData(Program program, Address addr, DataType dt) {
|
protected static void createData(Program program, Address addr, DataType dt) {
|
||||||
|
try {
|
||||||
CreateDataCmd dataCmd = new CreateDataCmd(addr, dt);
|
// try creating without clearing, the code units should be clear
|
||||||
dataCmd.applyTo(program);
|
program.getListing().createData(addr, dt);
|
||||||
|
}
|
||||||
|
catch (CodeUnitInsertionException | DataTypeConflictException e) {
|
||||||
|
CreateDataCmd dataCmd = new CreateDataCmd(addr, dt);
|
||||||
|
dataCmd.applyTo(program);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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)
|
private List<RegionDescriptor> analyzeSection(MemoryBlock curMemBlock)
|
||||||
throws MemoryAccessException, AddressOutOfBoundsException, ExceptionHandlerFrameException {
|
throws MemoryAccessException, AddressOutOfBoundsException,
|
||||||
|
ExceptionHandlerFrameException {
|
||||||
|
|
||||||
monitor.setMessage("Analyzing " + curMemBlock.getName() + " section");
|
monitor.setMessage("Analyzing " + curMemBlock.getName() + " section");
|
||||||
monitor.setShowProgressValue(true);
|
monitor.setShowProgressValue(true);
|
||||||
monitor.setIndeterminate(true);
|
monitor.setIndeterminate(false);
|
||||||
|
|
||||||
ProgramLocation loc = new ProgramLocation(program, curMemBlock.getStart());
|
ProgramLocation loc = new ProgramLocation(program, curMemBlock.getStart());
|
||||||
Address curAddress = loc.getAddress();
|
Address curAddress = loc.getAddress();
|
||||||
|
|
||||||
List<RegionDescriptor> regions = new ArrayList<>();
|
List<RegionDescriptor> regions = new ArrayList<>();
|
||||||
|
|
||||||
|
if (curAddress != null) {
|
||||||
|
monitor.setMaximum(curMemBlock.getEnd().subtract(curAddress));
|
||||||
|
}
|
||||||
|
|
||||||
while (curAddress != null && curAddress.compareTo(curMemBlock.getEnd()) < 0) {
|
while (curAddress != null && curAddress.compareTo(curMemBlock.getEnd()) < 0) {
|
||||||
|
if (monitor.isCancelled()) {
|
||||||
|
return regions;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the Common Information Entry */
|
/* Get the Common Information Entry */
|
||||||
Cie cie = getCie(curAddress);
|
Cie cie = getCie(curAddress);
|
||||||
|
@ -112,8 +117,12 @@ public class DebugFrameSection extends AbstractFrameSection {
|
||||||
/*
|
/*
|
||||||
* Add each Frame Description Entry (FDE) for the current CIE.
|
* Add each Frame Description Entry (FDE) for the current CIE.
|
||||||
*/
|
*/
|
||||||
|
List<RegionDescriptor> newRegions = new ArrayList<>();
|
||||||
|
|
||||||
while (curAddress != null && (curAddress.compareTo(curMemBlock.getEnd()) < 0)) {
|
while (curAddress != null && (curAddress.compareTo(curMemBlock.getEnd()) < 0)) {
|
||||||
|
|
||||||
|
monitor.setProgress(curAddress.subtract(loc.getAddress()));
|
||||||
|
|
||||||
Address currFdeAddr = curAddress;
|
Address currFdeAddr = curAddress;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -126,23 +135,24 @@ public class DebugFrameSection extends AbstractFrameSection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
regions.add(region);
|
newRegions.add(region);
|
||||||
createFdeComment(curAddress);
|
createFdeComment(curAddress);
|
||||||
monitor.incrementProgress(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curAddress = fde.getNextAddress(); // This can be null.
|
curAddress = fde.getNextAddress(); // This can be null.
|
||||||
|
|
||||||
} catch (ExceptionHandlerFrameException efe) {
|
}
|
||||||
|
catch (ExceptionHandlerFrameException efe) {
|
||||||
// May have run into another CIE.
|
// May have run into another CIE.
|
||||||
curAddress = currFdeAddr;
|
curAddress = currFdeAddr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createAugmentationData(regions, cie);
|
createAugmentationData(newRegions, cie);
|
||||||
|
|
||||||
|
regions.addAll(newRegions);
|
||||||
}
|
}
|
||||||
return regions;
|
return regions;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,21 @@ package ghidra.app.plugin.exceptionhandlers.gcc.structures.ehFrame;
|
||||||
|
|
||||||
import ghidra.app.cmd.comments.SetCommentCmd;
|
import ghidra.app.cmd.comments.SetCommentCmd;
|
||||||
import ghidra.app.cmd.data.CreateArrayCmd;
|
import ghidra.app.cmd.data.CreateArrayCmd;
|
||||||
|
import ghidra.app.cmd.data.CreateDataCmd;
|
||||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.*;
|
import ghidra.app.plugin.exceptionhandlers.gcc.*;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.datatype.UnsignedLeb128DataType;
|
import ghidra.app.plugin.exceptionhandlers.gcc.datatype.UnsignedLeb128DataType;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.sections.CieSource;
|
import ghidra.app.plugin.exceptionhandlers.gcc.sections.CieSource;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.sections.DebugFrameSection;
|
import ghidra.app.plugin.exceptionhandlers.gcc.sections.DebugFrameSection;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.structures.gccexcepttable.LSDATable;
|
import ghidra.app.plugin.exceptionhandlers.gcc.structures.gccexcepttable.LSDATable;
|
||||||
|
import ghidra.app.util.opinion.ElfLoader;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -265,8 +268,18 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
||||||
DataType encodedDt = cie.getFDEDecoder().getDataType(program);
|
DataType encodedDt = cie.getFDEDecoder().getDataType(program);
|
||||||
|
|
||||||
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
||||||
program.getReferenceManager().addMemoryReference(addr, pcBeginAddr, RefType.DATA,
|
if (pcBeginAddr.getOffset() != 0x0) {
|
||||||
SourceType.ANALYSIS, 0);
|
// 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;
|
curSize += encodedLen;
|
||||||
return addr.add(encodedLen);
|
return addr.add(encodedLen);
|
||||||
|
@ -386,8 +399,14 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
||||||
|
|
||||||
// Create initial instructions array with remaining bytes.
|
// Create initial instructions array with remaining bytes.
|
||||||
int instructionLength = intLength - curSize;
|
int instructionLength = intLength - curSize;
|
||||||
arrayCmd = new CreateArrayCmd(addr, instructionLength, new ByteDataType(), BYTE_LEN);
|
ArrayDataType adt = new ArrayDataType(ByteDataType.dataType, instructionLength, BYTE_LEN);
|
||||||
arrayCmd.applyTo(program);
|
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",
|
SetCommentCmd.createComment(program, addr, "(FDE) Call Frame Instructions",
|
||||||
CodeUnit.EOL_COMMENT);
|
CodeUnit.EOL_COMMENT);
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.util.demangler;
|
||||||
|
|
||||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||||
|
import ghidra.app.cmd.function.CreateThunkFunctionCmd;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.InstructionContext;
|
import ghidra.program.model.lang.InstructionContext;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -110,8 +111,7 @@ public class DemangledThunk extends DemangledObject {
|
||||||
function.setThunkedFunction(thunkedFunction);
|
function.setThunkedFunction(thunkedFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol s =
|
Symbol s = applyDemangledName(thunkAddress, function.isThunk(), false, program);
|
||||||
applyDemangledName(thunkAddress, function.isThunk(), false, program);
|
|
||||||
return s != null;
|
return s != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +181,15 @@ public class DemangledThunk extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol s = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
|
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())) {
|
if (s == null || !block.contains(s.getAddress())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,6 +502,9 @@ public class GnuDemanglerParser implements DemanglerParser {
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
if (str.endsWith(")")) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
DemangledObject dobj = parse(null, str.substring(0, pos));
|
DemangledObject dobj = parse(null, str.substring(0, pos));
|
||||||
if (dobj == null) {
|
if (dobj == null) {
|
||||||
|
|
|
@ -62,6 +62,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
"_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev");// virtual thunk
|
"_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev");// virtual thunk
|
||||||
demangle(process, parser, "_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE");// covariant return thunk
|
demangle(process, parser, "_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE");// covariant return thunk
|
||||||
|
|
||||||
|
demangle(process, parser, "_ZNK2cc14ScrollSnapTypeneERKS0_");
|
||||||
|
|
||||||
List<String> list = loadTextResource(GnuDemanglerParserTest.class, "libMagick.symbols.txt");
|
List<String> list = loadTextResource(GnuDemanglerParserTest.class, "libMagick.symbols.txt");
|
||||||
for (String mangled : list) {
|
for (String mangled : list) {
|
||||||
if (mangled == null) {
|
if (mangled == null) {
|
||||||
|
@ -73,8 +75,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
System.out.println("Elapsed Time: " + (System.currentTimeMillis() - start));
|
System.out.println("Elapsed Time: " + (System.currentTimeMillis() - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void demangle(GnuDemanglerNativeProcess process, GnuDemanglerParser parser, String mangled)
|
private void demangle(GnuDemanglerNativeProcess process, GnuDemanglerParser parser,
|
||||||
throws IOException {
|
String mangled) throws IOException {
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
assertNotNull(demangled);
|
assertNotNull(demangled);
|
||||||
assertNotEquals(mangled, 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");
|
"covariant return thunk [nv:0] [nv:16] to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const");
|
||||||
assertTrue(parse instanceof DemangledThunk);
|
assertTrue(parse instanceof DemangledThunk);
|
||||||
assertName(parse, "copy", "KHotKeys", "WindowTrigger");
|
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) {
|
private void assertName(DemangledObject demangledObj, String name, String... namespaces) {
|
||||||
|
@ -193,9 +205,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
DemangledObject object = parser.parse(mangled, demangled);
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
assertTrue(object instanceof DemangledFunction);
|
assertTrue(object instanceof DemangledFunction);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals("undefined glob_fn9(" +
|
||||||
"undefined glob_fn9(" +
|
"char,int,long,long long,unsigned int,unsigned long,float,double,long double,bool,void *,void * *)",
|
||||||
"char,int,long,long long,unsigned int,unsigned long,float,double,long double,bool,void *,void * *)",
|
|
||||||
object.getSignature(false));
|
object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1358,7 +1358,8 @@ with : ARMcondCk=1 {
|
||||||
|
|
||||||
:hlt immed6 is TMode=1 & op6=0b1011101010 & immed6
|
: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
|
: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
|
:udf^ItCond "#"thc0007 is TMode=1 & ItCond & op8 = 0xde & thc0007
|
||||||
{
|
{
|
||||||
build ItCond;
|
build ItCond;
|
||||||
software_udf(thc0007:4);
|
pc = software_udf(thc0007:4);
|
||||||
|
goto [pc];
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
:udf^ItCond "#"tmp is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0xa & thc0011 [tmp = thc0003 << 12 | thc0011;]
|
:udf^ItCond "#"tmp is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0xa & thc0011 [tmp = thc0003 << 12 | thc0011;]
|
||||||
{
|
{
|
||||||
build ItCond;
|
build ItCond;
|
||||||
software_udf(tmp:4);
|
pc = software_udf(tmp:4);
|
||||||
|
goto [pc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@endif # VERSION_5
|
@endif # VERSION_5
|
||||||
|
|
|
@ -193,11 +193,12 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
||||||
try {
|
try {
|
||||||
String symname = "_gp_" + index++;
|
String symname = "_gp_" + index++;
|
||||||
// check if it already exists
|
// check if it already exists
|
||||||
Symbol existingSymbol = SymbolUtilities.getLabelOrFunctionSymbol(program, symname,
|
Symbol existingSymbol =
|
||||||
err -> { /* ignore multiple symbols, if even one exists we need to skip if it has a different address */ } );
|
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 != null) {
|
||||||
if (existingSymbol.getAddress().equals(toAddr)) {
|
if (existingSymbol.getAddress().equals(toAddr)) {
|
||||||
return existingSymbol;
|
return existingSymbol;
|
||||||
}
|
}
|
||||||
continue; // can't use this one, look for the next free gp_<x> symbol
|
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();
|
final AddressSet coveredSet = new AddressSet();
|
||||||
|
|
||||||
|
Address currentGPAssumptionValue = gp_assumption_value;
|
||||||
|
|
||||||
if (func != null) {
|
if (func != null) {
|
||||||
flowStart = func.getEntryPoint();
|
flowStart = func.getEntryPoint();
|
||||||
if (gp_assumption_value != null) {
|
if (currentGPAssumptionValue != null) {
|
||||||
ProgramContext programContext = program.getProgramContext();
|
ProgramContext programContext = program.getProgramContext();
|
||||||
RegisterValue gpVal = programContext.getRegisterValue(gp, flowStart);
|
RegisterValue gpVal = programContext.getRegisterValue(gp, flowStart);
|
||||||
if (gpVal == null || !gpVal.hasValue()) {
|
if (gpVal == null || !gpVal.hasValue()) {
|
||||||
gpVal =
|
gpVal = new RegisterValue(gp,
|
||||||
new RegisterValue(gp, BigInteger.valueOf(gp_assumption_value.getOffset()));
|
BigInteger.valueOf(currentGPAssumptionValue.getOffset()));
|
||||||
try {
|
try {
|
||||||
program.getProgramContext().setRegisterValue(func.getEntryPoint(),
|
program.getProgramContext().setRegisterValue(func.getEntryPoint(),
|
||||||
func.getEntryPoint(), gpVal);
|
func.getEntryPoint(), gpVal);
|
||||||
|
@ -245,6 +248,7 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
||||||
// follow all flows building up context
|
// follow all flows building up context
|
||||||
// use context to fill out addresses on certain instructions
|
// use context to fill out addresses on certain instructions
|
||||||
ContextEvaluator eval = new ConstantPropagationContextEvaluator(trustWriteMemOption) {
|
ContextEvaluator eval = new ConstantPropagationContextEvaluator(trustWriteMemOption) {
|
||||||
|
private Address localGPAssumptionValue = currentGPAssumptionValue;
|
||||||
|
|
||||||
private boolean mustStopNow = false; // if something discovered in processing, mustStop flag
|
private boolean mustStopNow = false; // if something discovered in processing, mustStop flag
|
||||||
|
|
||||||
|
@ -297,8 +301,8 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
||||||
if (registerValue != null) {
|
if (registerValue != null) {
|
||||||
BigInteger value = registerValue.getUnsignedValue();
|
BigInteger value = registerValue.getUnsignedValue();
|
||||||
long unsignedValue = value.longValue();
|
long unsignedValue = value.longValue();
|
||||||
if (gp_assumption_value == null ||
|
if (localGPAssumptionValue == null ||
|
||||||
!(unsignedValue == gp_assumption_value.getOffset())) {
|
!(unsignedValue == localGPAssumptionValue.getOffset())) {
|
||||||
synchronized (gp) {
|
synchronized (gp) {
|
||||||
Address gpRefAddr =
|
Address gpRefAddr =
|
||||||
instr.getMinAddress().getNewAddress(unsignedValue);
|
instr.getMinAddress().getNewAddress(unsignedValue);
|
||||||
|
@ -317,18 +321,18 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
||||||
instr.getMinAddress().getAddressSpace().getBaseSpaceID(),
|
instr.getMinAddress().getAddressSpace().getBaseSpaceID(),
|
||||||
unsignedValue, 1, RefType.DATA, PcodeOp.UNIMPLEMENTED, true,
|
unsignedValue, 1, RefType.DATA, PcodeOp.UNIMPLEMENTED, true,
|
||||||
monitor);
|
monitor);
|
||||||
if (gp_assumption_value == null) {
|
if (localGPAssumptionValue == null) {
|
||||||
program.getBookmarkManager().setBookmark(
|
program.getBookmarkManager().setBookmark(
|
||||||
lastSetInstr.getMinAddress(), BookmarkType.WARNING,
|
lastSetInstr.getMinAddress(), BookmarkType.WARNING,
|
||||||
"GP Global Register Set",
|
"GP Global Register Set",
|
||||||
"Global GP Register is set here.");
|
"Global GP Register is set here.");
|
||||||
}
|
}
|
||||||
if (gp_assumption_value != null &&
|
if (localGPAssumptionValue != null &&
|
||||||
!gp_assumption_value.equals(gpRefAddr)) {
|
!localGPAssumptionValue.equals(gpRefAddr)) {
|
||||||
gp_assumption_value = null;
|
localGPAssumptionValue = gp_assumption_value = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gp_assumption_value = gpRefAddr;
|
localGPAssumptionValue = gp_assumption_value = gpRefAddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,10 +404,11 @@ public class MipsAddressAnalyzer extends ConstantPropagationAnalyzer {
|
||||||
// if it is assumed to be set to the same value, it can lead
|
// if it is assumed to be set to the same value, it can lead
|
||||||
// to incorrect re-use of the value (non-returning functions)
|
// to incorrect re-use of the value (non-returning functions)
|
||||||
context.clearRegister(reg);
|
context.clearRegister(reg);
|
||||||
|
|
||||||
// need to add the reference here, register operand will no longer have a value
|
// 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
|
// set the register value on the target address
|
||||||
ProgramContext progContext = program.getProgramContext();
|
ProgramContext progContext = program.getProgramContext();
|
||||||
if (progContext.getValue(reg, addr, false) == null) {
|
if (progContext.getValue(reg, addr, false) == null) {
|
||||||
|
|
|
@ -213,18 +213,16 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
// make some changes to check in
|
// make some changes to check in
|
||||||
Program program = (Program) ((DomainFileNode) node).getDomainFile()
|
Program program = (Program) ((DomainFileNode) node).getDomainFile().getDomainObject(this,
|
||||||
.getDomainObject(this,
|
true, false, TaskMonitor.DUMMY);
|
||||||
true, false, TaskMonitor.DUMMY);
|
|
||||||
editProgram(program, (p) -> {
|
editProgram(program, (p) -> {
|
||||||
SymbolTable symTable = p.getSymbolTable();
|
SymbolTable symTable = p.getSymbolTable();
|
||||||
symTable.createLabel(p.getMinAddress().getNewAddress(0x010001000), "fred",
|
symTable.createLabel(p.getMinAddress().getNewAddress(0x010001000), "fred",
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
});
|
});
|
||||||
|
|
||||||
program = (Program) ((DomainFileNode) xnode).getDomainFile()
|
program = (Program) ((DomainFileNode) xnode).getDomainFile().getDomainObject(this, true,
|
||||||
.getDomainObject(this, true,
|
false, TaskMonitor.DUMMY);
|
||||||
false, TaskMonitor.DUMMY);
|
|
||||||
editProgram(program, (p) -> {
|
editProgram(program, (p) -> {
|
||||||
SymbolTable symTable = p.getSymbolTable();
|
SymbolTable symTable = p.getSymbolTable();
|
||||||
symTable.createLabel(p.getMinAddress(), "bob", SourceType.USER_DEFINED);
|
symTable.createLabel(p.getMinAddress(), "bob", SourceType.USER_DEFINED);
|
||||||
|
@ -253,9 +251,8 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
||||||
checkout(programNode);
|
checkout(programNode);
|
||||||
|
|
||||||
Program program =
|
Program program =
|
||||||
(Program) ((DomainFileNode) programNode).getDomainFile()
|
(Program) ((DomainFileNode) programNode).getDomainFile().getDomainObject(this, true,
|
||||||
.getDomainObject(this, true,
|
false, TaskMonitor.DUMMY);
|
||||||
false, TaskMonitor.DUMMY);
|
|
||||||
|
|
||||||
createHistoryEntry(program, "Symbol1");
|
createHistoryEntry(program, "Symbol1");
|
||||||
frontEnd.checkIn(programNode, "This is checkin 1");
|
frontEnd.checkIn(programNode, "This is checkin 1");
|
||||||
|
@ -608,8 +605,9 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
|
||||||
selectInTable(table, node);
|
selectInTable(table, node);
|
||||||
|
|
||||||
DockingActionIf undoCheckoutAction = getAction("UndoCheckOut");
|
DockingActionIf undoCheckoutAction = getAction("UndoCheckOut");
|
||||||
assertTrue(undoCheckoutAction.isEnabledForContext(dialog.getActionContext(null)));
|
ActionContext actionContext = dialog.getActionContext(null);
|
||||||
performAction(undoCheckoutAction);
|
assertTrue(undoCheckoutAction.isEnabledForContext(actionContext));
|
||||||
|
performAction(undoCheckoutAction, actionContext, true);
|
||||||
|
|
||||||
waitForBusyTable(table);
|
waitForBusyTable(table);
|
||||||
assertEquals(1, model.getRowCount());
|
assertEquals(1, model.getRowCount());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue