Merge remote-tracking branch 'origin/patch'

This commit is contained in:
ghidra1 2019-12-18 11:02:47 -05:00
commit 8fbdec4eca
13 changed files with 174 additions and 91 deletions

View file

@ -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>

View file

@ -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.

View file

@ -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();

View file

@ -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;
}
/**

View file

@ -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);
}
}
/**

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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) {

View file

@ -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));
}

View file

@ -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

View file

@ -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();

View file

@ -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());