mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 15:40:14 +00:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
5b9dfc92dd
@ -637,7 +637,7 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
|||||||
FlowType[] dontFollow = { RefType.COMPUTED_CALL, RefType.CONDITIONAL_CALL,
|
FlowType[] dontFollow = { RefType.COMPUTED_CALL, RefType.CONDITIONAL_CALL,
|
||||||
RefType.UNCONDITIONAL_CALL, RefType.INDIRECTION };
|
RefType.UNCONDITIONAL_CALL, RefType.INDIRECTION };
|
||||||
AddressSet start = new AddressSet(entry, entry);
|
AddressSet start = new AddressSet(entry, entry);
|
||||||
FollowFlow flow = new FollowFlow(program, start, dontFollow, includeOtherFunctions);
|
FollowFlow flow = new FollowFlow(program, start, dontFollow, includeOtherFunctions, false);
|
||||||
return flow.getFlowAddressSet(monitor);
|
return flow.getFlowAddressSet(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1383,14 +1383,8 @@ public class VarnodeContext implements ProcessorContext {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is bad since registers could have multiple associated spaces
|
// flag running out of address spaces, so error only printed once
|
||||||
// private int getSymbolSpaceID(Varnode val) {
|
private boolean hitMaxAddressSpaces = false;
|
||||||
// Register reg = trans.getRegister(val);
|
|
||||||
// if (reg == null) {
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
// return getAddressSpace(reg.getName());
|
|
||||||
// }
|
|
||||||
|
|
||||||
public int getAddressSpace(String name) {
|
public int getAddressSpace(String name) {
|
||||||
int spaceID;
|
int spaceID;
|
||||||
@ -1399,7 +1393,10 @@ public class VarnodeContext implements ProcessorContext {
|
|||||||
regSpace = ((OffsetAddressFactory) addrFactory).createNewOffsetSpace(name);
|
regSpace = ((OffsetAddressFactory) addrFactory).createNewOffsetSpace(name);
|
||||||
}
|
}
|
||||||
if (regSpace == null) {
|
if (regSpace == null) {
|
||||||
Msg.error(this, "VarnodeContext: out of address spaces for: " + name);
|
if (!hitMaxAddressSpaces) {
|
||||||
|
Msg.error(this, "VarnodeContext: out of address spaces at @" + currentAddress +" for: " + name);
|
||||||
|
hitMaxAddressSpaces = true;
|
||||||
|
}
|
||||||
return BAD_SPACE_ID_VALUE;
|
return BAD_SPACE_ID_VALUE;
|
||||||
}
|
}
|
||||||
spaceID = regSpace.getSpaceID();
|
spaceID = regSpace.getSpaceID();
|
||||||
@ -1762,13 +1759,18 @@ class OffsetAddressFactory extends DefaultAddressFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maximum space ID used to create spaces
|
||||||
|
private int curMaxID = 0;
|
||||||
|
|
||||||
private int getNextUniqueID() {
|
private int getNextUniqueID() {
|
||||||
int maxID = 0;
|
if (curMaxID == 0) {
|
||||||
AddressSpace[] spaces = getAllAddressSpaces();
|
AddressSpace[] spaces = getAllAddressSpaces();
|
||||||
for (AddressSpace space : spaces) {
|
for (AddressSpace space : spaces) {
|
||||||
maxID = Math.max(maxID, space.getUnique());
|
curMaxID = Math.max(curMaxID, space.getUnique());
|
||||||
}
|
}
|
||||||
return maxID + 1;
|
}
|
||||||
|
curMaxID += 1;
|
||||||
|
return curMaxID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,6 +74,19 @@ public abstract class AbstractFollowFlowTest extends AbstractGhidraHeadedIntegra
|
|||||||
return followFlow.getFlowAddressSet(TaskMonitor.DUMMY);
|
return followFlow.getFlowAddressSet(TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddressSetView getFlowsFrom(int startAddressOffset, FlowType[] excludedFlows, boolean includeFunctions, boolean includeData) {
|
||||||
|
return getFlowsFrom(addr(startAddressOffset), excludedFlows, includeFunctions, includeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressSetView getFlowsFrom(Address startAddress, FlowType[] excludedFlows, boolean includeFunctions, boolean includeData) {
|
||||||
|
return getFlowsFrom(new AddressSet(startAddress), excludedFlows, includeFunctions, includeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressSetView getFlowsFrom(AddressSet startSet, FlowType[] excludedFlows, boolean includeFunctions, boolean includeData) {
|
||||||
|
FollowFlow followFlow = new FollowFlow(program, startSet, excludedFlows, includeFunctions, includeData);
|
||||||
|
return followFlow.getFlowAddressSet(TaskMonitor.DUMMY);
|
||||||
|
}
|
||||||
|
|
||||||
AddressSetView getFlowsTo(int startAddressOffset, FlowType[] excludedFlows) {
|
AddressSetView getFlowsTo(int startAddressOffset, FlowType[] excludedFlows) {
|
||||||
return getFlowsTo(addr(startAddressOffset), excludedFlows);
|
return getFlowsTo(addr(startAddressOffset), excludedFlows);
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,33 @@ public class FollowFlowForwardTest extends AbstractFollowFlowTest {
|
|||||||
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFollowAllFlowsFromNoData0x10() {
|
||||||
|
|
||||||
|
AddressSetView flowAddresses = getFlowsFrom(0x10, followAllFlows(), true, false);
|
||||||
|
|
||||||
|
AddressSet expectedAddresses = new AddressSet();
|
||||||
|
expectedAddresses.add(addr(0x0), addr(0x24));
|
||||||
|
expectedAddresses.add(addr(0x26), addr(0x2f));
|
||||||
|
expectedAddresses.add(addr(0x30), addr(0x52));
|
||||||
|
expectedAddresses.add(addr(0x54), addr(0x5f));
|
||||||
|
expectedAddresses.add(addr(0x60), addr(0x84));
|
||||||
|
expectedAddresses.add(addr(0x86), addr(0x8f));
|
||||||
|
expectedAddresses.add(addr(0x90), addr(0xb4));
|
||||||
|
expectedAddresses.add(addr(0xb6), addr(0xbf));
|
||||||
|
expectedAddresses.add(addr(0x130), addr(0x131));
|
||||||
|
expectedAddresses.add(addr(0x160), addr(0x161));
|
||||||
|
expectedAddresses.add(addr(0x190), addr(0x191));
|
||||||
|
expectedAddresses.add(addr(0x230), addr(0x231));
|
||||||
|
expectedAddresses.add(addr(0x260), addr(0x261));
|
||||||
|
expectedAddresses.add(addr(0x290), addr(0x291));
|
||||||
|
expectedAddresses.add(addr(0x330), addr(0x331));
|
||||||
|
expectedAddresses.add(addr(0x360), addr(0x361));
|
||||||
|
expectedAddresses.add(addr(0x390), addr(0x391));
|
||||||
|
|
||||||
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFollowAllFlowsFrom0x17() {
|
public void testFollowAllFlowsFrom0x17() {
|
||||||
|
|
||||||
@ -104,6 +131,27 @@ public class FollowFlowForwardTest extends AbstractFollowFlowTest {
|
|||||||
|
|
||||||
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void testFollowAllFlowsFromNoData0x17() {
|
||||||
|
|
||||||
|
AddressSetView flowAddresses = getFlowsFrom(0x17, followAllFlows(), true, false);
|
||||||
|
|
||||||
|
AddressSet expectedAddresses = new AddressSet();
|
||||||
|
expectedAddresses.add(addr(0x17), addr(0x24));
|
||||||
|
expectedAddresses.add(addr(0x26), addr(0x2f));
|
||||||
|
expectedAddresses.add(addr(0x60), addr(0x84));
|
||||||
|
expectedAddresses.add(addr(0x86), addr(0x8f));
|
||||||
|
expectedAddresses.add(addr(0x90), addr(0xb4));
|
||||||
|
expectedAddresses.add(addr(0xb6), addr(0xbf));
|
||||||
|
expectedAddresses.add(addr(0x230), addr(0x231));
|
||||||
|
expectedAddresses.add(addr(0x260), addr(0x261));
|
||||||
|
expectedAddresses.add(addr(0x290), addr(0x291));
|
||||||
|
expectedAddresses.add(addr(0x330), addr(0x331));
|
||||||
|
expectedAddresses.add(addr(0x360), addr(0x361));
|
||||||
|
expectedAddresses.add(addr(0x390), addr(0x391));
|
||||||
|
|
||||||
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFollowAllFlowsFrom0x2f() {
|
public void testFollowAllFlowsFrom0x2f() {
|
||||||
@ -160,6 +208,20 @@ public class FollowFlowForwardTest extends AbstractFollowFlowTest {
|
|||||||
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFollowAllFlowsFromNoData0x77() {
|
||||||
|
|
||||||
|
AddressSetView flowAddresses = getFlowsFrom(0x77, followAllFlows(), true, false);
|
||||||
|
|
||||||
|
AddressSet expectedAddresses = new AddressSet();
|
||||||
|
expectedAddresses.add(addr(0x77), addr(0x84));
|
||||||
|
expectedAddresses.add(addr(0x86), addr(0x8f));
|
||||||
|
expectedAddresses.add(addr(0x260), addr(0x261));
|
||||||
|
expectedAddresses.add(addr(0x290), addr(0x291));
|
||||||
|
|
||||||
|
assertEquals(new MySelection(expectedAddresses), new MySelection(flowAddresses));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFollowAllFlowsFrom0x5000() {
|
public void testFollowAllFlowsFrom0x5000() {
|
||||||
|
|
||||||
|
@ -0,0 +1,197 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand;
|
||||||
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
|
import ghidra.framework.cmd.Command;
|
||||||
|
import ghidra.framework.options.Options;
|
||||||
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.database.ProgramBuilder;
|
||||||
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
|
import ghidra.test.TestEnv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the {@link CreateFunctionCmdWithFlowTest}.
|
||||||
|
*/
|
||||||
|
public class CreateFunctionCmdWithFlowTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
|
private TestEnv env;
|
||||||
|
private PluginTool tool;
|
||||||
|
|
||||||
|
private Program program;
|
||||||
|
private ProgramBuilder builder;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
env = new TestEnv();
|
||||||
|
tool = env.getTool();
|
||||||
|
|
||||||
|
builder = new ProgramBuilder("notepad.exe", ProgramBuilder._PPC_32);
|
||||||
|
builder.createMemory("test", "0x07000000", 1024);
|
||||||
|
|
||||||
|
program = builder.getProgram();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create some functions (byte patterns, not Ghidra objects) with varying separation
|
||||||
|
//
|
||||||
|
// single function
|
||||||
|
builder.setBytes("0x07000008", "3d 60 07 00 61 6b 00 20 7d 69 03 a6 4e 80 04 20");
|
||||||
|
builder.disassemble("0x07000008", 16);
|
||||||
|
builder.createMemoryJumpReference("0x070000014", "0x07000020");
|
||||||
|
|
||||||
|
// Thunk to above single function
|
||||||
|
builder.setBytes("0x07000020", "7c 69 1b 78 88 04 00 00 38 84 00 01 7c 00 07 74 2f 80 00 00 98 09 00 00 39 29 00 01 40 9e ff e8 4e 80 00 20");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyze() {
|
||||||
|
// turn off some analyzers
|
||||||
|
setAnalysisOptions("Stack");
|
||||||
|
setAnalysisOptions("Embedded Media");
|
||||||
|
setAnalysisOptions("DWARF");
|
||||||
|
setAnalysisOptions("Create Address Tables");
|
||||||
|
setAnalysisOptions("MIPS Constant Reference Analyzer");
|
||||||
|
|
||||||
|
AutoAnalysisManager analysisMgr = AutoAnalysisManager.getAnalysisManager(program);
|
||||||
|
analysisMgr.reAnalyzeAll(null);
|
||||||
|
|
||||||
|
Command cmd = new AnalysisBackgroundCommand(analysisMgr, false);
|
||||||
|
tool.execute(cmd, program);
|
||||||
|
waitForBusyTool(tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setAnalysisOptions(String optionName) {
|
||||||
|
int txId = program.startTransaction("Analyze");
|
||||||
|
Options analysisOptions = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
||||||
|
analysisOptions.setBoolean(optionName, false);
|
||||||
|
program.endTransaction(txId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateFunction() {
|
||||||
|
|
||||||
|
int transactionID = program.startTransaction("Perform the TEST");
|
||||||
|
|
||||||
|
CreateFunctionCmd createCmd = new CreateFunctionCmd(addr(0x07000008));
|
||||||
|
createCmd.applyTo(program);
|
||||||
|
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
|
||||||
|
Function func8 = func(addr(0x07000008));
|
||||||
|
assertNotNull("Created normal function", func8);
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 16, func8.getBody().getNumAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateFunctionOneByte() throws OverlappingFunctionException {
|
||||||
|
|
||||||
|
int transactionID = program.startTransaction("Perform the TEST");
|
||||||
|
|
||||||
|
CreateFunctionCmd createCmd = new CreateFunctionCmd(addr(0x07000008));
|
||||||
|
createCmd.applyTo(program);
|
||||||
|
|
||||||
|
// doctor body
|
||||||
|
AddressSet body = new AddressSet(addr(0x07000008),addr(0x07000017));
|
||||||
|
body.add(addr(0x07000020));
|
||||||
|
|
||||||
|
Function func8 = func(addr(0x07000008));
|
||||||
|
|
||||||
|
func8.setBody(body);
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 17, func8.getBody().getNumAddresses());
|
||||||
|
|
||||||
|
builder.disassemble("0x07000020", 36);
|
||||||
|
|
||||||
|
createCmd = new CreateFunctionCmd(addr(0x07000020));
|
||||||
|
createCmd.applyTo(program);
|
||||||
|
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
|
||||||
|
assertNotNull("Created normal function", func8);
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 16, func8.getBody().getNumAddresses());
|
||||||
|
|
||||||
|
Function func20 = func(addr(0x07000020));
|
||||||
|
|
||||||
|
assertNotNull("Created normal function", func20);
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 36, func20.getBody().getNumAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPPCDisassemblyRef() throws OverlappingFunctionException {
|
||||||
|
|
||||||
|
int transactionID = program.startTransaction("Perform the TEST");
|
||||||
|
|
||||||
|
CreateFunctionCmd createCmd = new CreateFunctionCmd(addr(0x07000008));
|
||||||
|
createCmd.applyTo(program);
|
||||||
|
|
||||||
|
Function func8 = func(addr(0x07000008));
|
||||||
|
|
||||||
|
program.getMemory().getBlock(addr(0x07000000)).setExecute(true);
|
||||||
|
|
||||||
|
assertFalse("is not Thunk yet", func8.isThunk());
|
||||||
|
|
||||||
|
Instruction instructionAt = program.getListing().getInstructionAt(addr(0x07000020));
|
||||||
|
|
||||||
|
assertNull("Not disassembled yet", instructionAt);
|
||||||
|
|
||||||
|
builder.analyze();
|
||||||
|
|
||||||
|
assertNotNull("Created normal function", func8);
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 16, func8.getBody().getNumAddresses());
|
||||||
|
|
||||||
|
instructionAt = program.getListing().getInstructionAt(addr(0x07000020));
|
||||||
|
|
||||||
|
assertNotNull("Disassembled from computed branch", instructionAt);
|
||||||
|
|
||||||
|
createCmd = new CreateFunctionCmd(addr(0x07000020));
|
||||||
|
createCmd.applyTo(program);
|
||||||
|
|
||||||
|
Function func20 = func(addr(0x07000020));
|
||||||
|
|
||||||
|
builder.analyze();
|
||||||
|
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
|
||||||
|
assertTrue("is Thunk ", func8.isThunk());
|
||||||
|
|
||||||
|
assertEquals("Normal function body size", 36, func20.getBody().getNumAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(long l) {
|
||||||
|
AddressSpace addressSpace = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
|
return addressSpace.getAddress(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Function func(Address a) {
|
||||||
|
FunctionManager fm = program.getFunctionManager();
|
||||||
|
return fm.getFunctionAt(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<opinions>
|
<opinions>
|
||||||
<constraint loader="Dump File Loader">
|
<constraint loader="Dump File Loader">
|
||||||
<constraint compilerSpecID="linux">
|
<constraint compilerSpecID="linux">
|
||||||
<constraint primary="amd64" processor="x86" endian="little" size="64" />
|
<constraint primary="amd64" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
</constraint>
|
</constraint>
|
||||||
</opinions>
|
</opinions>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<!-- constraint primary="6" processor="IA64" endian="little" size="32" -->
|
<!-- constraint primary="6" processor="IA64" endian="little" size="32" -->
|
||||||
<!-- constraint primary="7" processor="ALPHA64" endian="little" size="32" -->
|
<!-- constraint primary="7" processor="ALPHA64" endian="little" size="32" -->
|
||||||
<!-- constraint primary="8" processor="MSIL" endian="little" size="32" -->
|
<!-- constraint primary="8" processor="MSIL" endian="little" size="32" -->
|
||||||
<constraint primary="9" processor="x86" endian="little" size="64" />
|
<constraint primary="9" processor="x86" endian="little" size="64" variant="default" />
|
||||||
<!-- constraint primary="10" processor="IA32/64" endian="little" size="32" -->
|
<!-- constraint primary="10" processor="IA32/64" endian="little" size="32" -->
|
||||||
<!-- constraint primary="11" processor="NEUTRAL" endian="little" size="32" -->
|
<!-- constraint primary="11" processor="NEUTRAL" endian="little" size="32" -->
|
||||||
<constraint primary="12" processor="ARM" endian="little" size="64" />
|
<constraint primary="12" processor="ARM" endian="little" size="64" />
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<constraint primary="386" processor="x86" endian="little" size="32" />
|
<constraint primary="386" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="486" processor="x86" endian="little" size="32" />
|
<constraint primary="486" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="586" processor="x86" endian="little" size="32" />
|
<constraint primary="586" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="8664" processor="x86" endian="little" size="64" />
|
<constraint primary="8664" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint compilerSpecID="default">
|
<constraint compilerSpecID="default">
|
||||||
<constraint primary="601" processor="PowerPC" endian="little" size="32" />
|
<constraint primary="601" processor="PowerPC" endian="little" size="32" />
|
||||||
|
@ -46,11 +46,15 @@ public class FollowFlow {
|
|||||||
private boolean followPointers = true;
|
private boolean followPointers = true;
|
||||||
|
|
||||||
private boolean followIntoFunction = true;
|
private boolean followIntoFunction = true;
|
||||||
|
private boolean includeData = true;
|
||||||
private Address nextSymbolAddr;
|
private Address nextSymbolAddr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
* Note: flow into existing functions will be included
|
||||||
|
* Note: flow into un-disassembled locations will be included
|
||||||
|
*
|
||||||
* @param program the program whose flow we are following.
|
* @param program the program whose flow we are following.
|
||||||
* @param addressSet the initial addresses that should be flowed from or flowed to.
|
* @param addressSet the initial addresses that should be flowed from or flowed to.
|
||||||
* @param doNotFollow array of flow types that are not to be followed.
|
* @param doNotFollow array of flow types that are not to be followed.
|
||||||
@ -63,6 +67,7 @@ public class FollowFlow {
|
|||||||
* <BR>FlowType.CONDITIONAL_JUMP
|
* <BR>FlowType.CONDITIONAL_JUMP
|
||||||
* <BR>FlowType.UNCONDITIONAL_JUMP
|
* <BR>FlowType.UNCONDITIONAL_JUMP
|
||||||
* <BR>FlowType.INDIRECTION
|
* <BR>FlowType.INDIRECTION
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public FollowFlow(Program program, AddressSet addressSet, FlowType[] doNotFollow) {
|
public FollowFlow(Program program, AddressSet addressSet, FlowType[] doNotFollow) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
@ -73,6 +78,8 @@ public class FollowFlow {
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
* Note: flow into un-disassembled locations will be included
|
||||||
|
*
|
||||||
* @param program the program whose flow we are following.
|
* @param program the program whose flow we are following.
|
||||||
* @param addressSet the initial addresses that should be flowed from or flowed to.
|
* @param addressSet the initial addresses that should be flowed from or flowed to.
|
||||||
* @param doNotFollow array of flow types that are not to be followed.
|
* @param doNotFollow array of flow types that are not to be followed.
|
||||||
@ -94,6 +101,31 @@ public class FollowFlow {
|
|||||||
this.followIntoFunction = followIntoFunctions;
|
this.followIntoFunction = followIntoFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param program the program whose flow we are following.
|
||||||
|
* @param addressSet the initial addresses that should be flowed from or flowed to.
|
||||||
|
* @param doNotFollow array of flow types that are not to be followed.
|
||||||
|
* null or empty array indicates follow all flows. The following are valid
|
||||||
|
* flow types for the doNotFollow array:
|
||||||
|
* <BR>FlowType.COMPUTED_CALL
|
||||||
|
* <BR>FlowType.CONDITIONAL_CALL
|
||||||
|
* <BR>FlowType.UNCONDITIONAL_CALL
|
||||||
|
* <BR>FlowType.COMPUTED_JUMP
|
||||||
|
* <BR>FlowType.CONDITIONAL_JUMP
|
||||||
|
* <BR>FlowType.UNCONDITIONAL_JUMP
|
||||||
|
* <BR>FlowType.INDIRECTION
|
||||||
|
* @param followIntoFunctions true if flows into (or back from) defined functions
|
||||||
|
* should be followed.
|
||||||
|
* @param includeData true if instruction flows into un-disassembled data should be included
|
||||||
|
*/
|
||||||
|
public FollowFlow(Program program, AddressSet addressSet, FlowType[] doNotFollow,
|
||||||
|
boolean followIntoFunctions, boolean includeData) {
|
||||||
|
this(program, addressSet, doNotFollow, followIntoFunctions);
|
||||||
|
this.includeData = includeData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* updateFollowFlags
|
* updateFollowFlags
|
||||||
*
|
*
|
||||||
@ -289,7 +321,9 @@ public class FollowFlow {
|
|||||||
codeUnit = instructionStack.pop();
|
codeUnit = instructionStack.pop();
|
||||||
if (!(codeUnit instanceof Instruction)) {
|
if (!(codeUnit instanceof Instruction)) {
|
||||||
// Probably undefined data which should be disassembled
|
// Probably undefined data which should be disassembled
|
||||||
|
if (includeData) {
|
||||||
flowAddressSet.addRange(codeUnit.getMinAddress(), codeUnit.getMaxAddress());
|
flowAddressSet.addRange(codeUnit.getMinAddress(), codeUnit.getMaxAddress());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +509,7 @@ public class FollowFlow {
|
|||||||
if (nextAddress != null) {
|
if (nextAddress != null) {
|
||||||
CodeUnit nextCodeUnit = program.getListing().getCodeUnitContaining(nextAddress);
|
CodeUnit nextCodeUnit = program.getListing().getCodeUnitContaining(nextAddress);
|
||||||
if (nextCodeUnit != null) {
|
if (nextCodeUnit != null) {
|
||||||
if (nextCodeUnit instanceof Data) {
|
if (nextCodeUnit instanceof Data && includeData) {
|
||||||
followData(instructionStack, flowAddressSet, (Data) nextCodeUnit,
|
followData(instructionStack, flowAddressSet, (Data) nextCodeUnit,
|
||||||
nextAddress);
|
nextAddress);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ public class ArmAnalyzer extends ConstantPropagationAnalyzer {
|
|||||||
public AddressSet flowConstants(final Program program, Address flowStart,
|
public AddressSet flowConstants(final Program program, Address flowStart,
|
||||||
AddressSetView flowSet, final SymbolicPropogator symEval, final TaskMonitor monitor)
|
AddressSetView flowSet, final SymbolicPropogator symEval, final TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
// 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
|
||||||
ConstantPropagationContextEvaluator eval =
|
ConstantPropagationContextEvaluator eval =
|
||||||
@ -230,10 +231,15 @@ public class ArmAnalyzer extends ConstantPropagationAnalyzer {
|
|||||||
public boolean evaluateReturn(Varnode retVN, VarnodeContext context, Instruction instruction) {
|
public boolean evaluateReturn(Varnode retVN, VarnodeContext context, Instruction instruction) {
|
||||||
// check if a return is actually returning, or is branching with a constant PC
|
// check if a return is actually returning, or is branching with a constant PC
|
||||||
|
|
||||||
|
// if flow already overridden, don't override again
|
||||||
|
if (instruction.getFlowOverride() != FlowOverride.NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (retVN != null && context.isConstant(retVN)) {
|
if (retVN != null && context.isConstant(retVN)) {
|
||||||
long offset = retVN.getOffset();
|
long offset = retVN.getOffset();
|
||||||
if (offset > 3 && offset != -1) {
|
if (offset > 3 && offset != -1) {
|
||||||
// need to override the return to a branch
|
// need to override the return flow to a branch
|
||||||
instruction.setFlowOverride(FlowOverride.BRANCH);
|
instruction.setFlowOverride(FlowOverride.BRANCH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,9 @@ public class PowerPCAddressAnalyzer extends ConstantPropagationAnalyzer {
|
|||||||
public boolean evaluateReference(VarnodeContext context, Instruction instr,
|
public boolean evaluateReference(VarnodeContext context, Instruction instr,
|
||||||
int pcodeop, Address address, int size, DataType dataType, RefType refType) {
|
int pcodeop, Address address, int size, DataType dataType, RefType refType) {
|
||||||
|
|
||||||
if (instr.getFlowType().isJump()) {
|
if (refType.isJump() && refType.isComputed() &&
|
||||||
|
program.getMemory().contains(address) && address.getOffset() != 0) {
|
||||||
|
super.evaluateReference(context, instr, pcodeop, address, size, dataType, refType);
|
||||||
// for branching instructions, if we have a good target, mark it
|
// for branching instructions, if we have a good target, mark it
|
||||||
// if this isn't straight code (thunk computation), let someone else lay down the reference
|
// if this isn't straight code (thunk computation), let someone else lay down the reference
|
||||||
return !symEval.encounteredBranch();
|
return !symEval.encounteredBranch();
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
<external_name tool="DWARF.register.mapping.file" name="x86-64.dwarf"/>
|
<external_name tool="DWARF.register.mapping.file" name="x86-64.dwarf"/>
|
||||||
<external_name tool="Golang.register.info.file" name="x86-64-golang.register.info"/>
|
<external_name tool="Golang.register.info.file" name="x86-64-golang.register.info"/>
|
||||||
</language>
|
</language>
|
||||||
<language processor="x86-compat32"
|
<language processor="x86"
|
||||||
endian="little"
|
endian="little"
|
||||||
size="64"
|
size="64"
|
||||||
variant="compat32"
|
variant="compat32"
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
<opinions>
|
<opinions>
|
||||||
|
<!-- NOTE: variant="default" is specified for 64-bit to give preference to the default variant -->
|
||||||
<constraint loader="Portable Executable (PE)">
|
<constraint loader="Portable Executable (PE)">
|
||||||
<constraint compilerSpecID="windows">
|
<constraint compilerSpecID="windows">
|
||||||
<constraint primary="332" processor="x86" endian="little" size="32" />
|
<constraint primary="332" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="333" processor="x86" endian="little" size="32" />
|
<constraint primary="333" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="334" processor="x86" endian="little" size="32" />
|
<constraint primary="334" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="34404" processor="x86" endian="little" size="64" />
|
<constraint primary="34404" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint compilerSpecID="clangwindows">
|
<constraint compilerSpecID="clangwindows">
|
||||||
<constraint primary="332" secondary="clang" processor="x86" endian="little" size="32" />
|
<constraint primary="332" secondary="clang" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="333" secondary="clang" processor="x86" endian="little" size="32" />
|
<constraint primary="333" secondary="clang" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="334" secondary="clang" processor="x86" endian="little" size="32" />
|
<constraint primary="334" secondary="clang" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="34404" secondary="clang" processor="x86" endian="little" size="64" />
|
<constraint primary="34404" secondary="clang" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint compilerSpecID="borlandcpp">
|
<constraint compilerSpecID="borlandcpp">
|
||||||
<constraint primary="332" secondary="borlandcpp" processor="x86" endian="little" size="32" />
|
<constraint primary="332" secondary="borlandcpp" processor="x86" endian="little" size="32" />
|
||||||
@ -24,18 +25,18 @@
|
|||||||
</constraint>
|
</constraint>
|
||||||
<constraint compilerSpecID="golang">
|
<constraint compilerSpecID="golang">
|
||||||
<constraint primary="332" secondary="golang" processor="x86" endian="little" size="32" />
|
<constraint primary="332" secondary="golang" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="34404" secondary="golang" processor="x86" endian="little" size="64" />
|
<constraint primary="34404" secondary="golang" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Debug Symbols (DBG)" compilerSpecID="windows">
|
<constraint loader="Debug Symbols (DBG)" compilerSpecID="windows">
|
||||||
<constraint primary="332" processor="x86" endian="little" size="32" />
|
<constraint primary="332" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="333" processor="x86" endian="little" size="32" />
|
<constraint primary="333" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="334" processor="x86" endian="little" size="32" />
|
<constraint primary="334" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="34404" processor="x86" endian="little" size="64" />
|
<constraint primary="34404" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="gcc">
|
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="gcc">
|
||||||
<constraint primary="3" processor="x86" endian="little" size="32" />
|
<constraint primary="3" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="62" processor="x86" endian="little" size="64" />
|
<constraint primary="62" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Module Definition (DEF)" compilerSpecID="windows">
|
<constraint loader="Module Definition (DEF)" compilerSpecID="windows">
|
||||||
<constraint primary="0" processor="x86" endian="little" size="32" />
|
<constraint primary="0" processor="x86" endian="little" size="32" />
|
||||||
@ -51,18 +52,18 @@
|
|||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Mac OS X Mach-O" compilerSpecID="gcc">
|
<constraint loader="Mac OS X Mach-O" compilerSpecID="gcc">
|
||||||
<constraint primary="7" processor="x86" endian="little" size="32" />
|
<constraint primary="7" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="16777223" processor="x86" endian="little" size="64" />
|
<constraint primary="16777223" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="DYLD Cache" compilerSpecID="gcc">
|
<constraint loader="DYLD Cache" compilerSpecID="gcc">
|
||||||
<constraint primary="x86_64" processor="x86" endian="little" size="64" />
|
<constraint primary="x86_64" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Common Object File Format (COFF)" compilerSpecID="gcc">
|
<constraint loader="Common Object File Format (COFF)" compilerSpecID="gcc">
|
||||||
<constraint primary="332" processor="x86" endian="little" size="32" />
|
<constraint primary="332" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="-31132" processor="x86" endian="little" size="64" />
|
<constraint primary="-31132" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="MS Common Object File Format (COFF)" compilerSpecID="windows">
|
<constraint loader="MS Common Object File Format (COFF)" compilerSpecID="windows">
|
||||||
<constraint primary="332" processor="x86" endian="little" size="32" />
|
<constraint primary="332" processor="x86" endian="little" size="32" />
|
||||||
<constraint primary="-31132" processor="x86" endian="little" size="64" />
|
<constraint primary="-31132" processor="x86" endian="little" size="64" variant="default" />
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint loader="Assembler Output (AOUT)" compilerSpecID="gcc">
|
<constraint loader="Assembler Output (AOUT)" compilerSpecID="gcc">
|
||||||
<constraint primary="134" processor="x86" endian="little" size="32" />
|
<constraint primary="134" processor="x86" endian="little" size="32" />
|
||||||
|
Loading…
Reference in New Issue
Block a user