Merge remote-tracking branch 'origin/patch'

This commit is contained in:
ghidra1 2020-12-10 10:12:40 -05:00
commit 5555566e59
15 changed files with 140 additions and 85 deletions

View file

@ -1321,12 +1321,18 @@ void JumpBasic::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addr
if (loadpoints != (vector<LoadTable> *)0)
emul.setLoadCollect(true);
uintb mask = ~((uintb)0);
int4 bit = fd->getArch()->funcptr_align;
if (bit != 0) {
mask = (mask >> bit) << bit;
}
AddrSpace *spc = indop->getAddr().getSpace();
bool notdone = jrange->initializeForReading();
while(notdone) {
val = jrange->getValue();
addr = emul.emulatePath(val,pathMeld,jrange->getStartOp(),jrange->getStartVarnode());
addr = AddrSpace::addressToByte(addr,spc->getWordSize());
addr &= mask;
addresstable.push_back(Address(spc,addr));
notdone = jrange->next();
}
@ -2008,9 +2014,15 @@ void JumpAssisted::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &a
for(int4 i=0;i<numInputs;++i)
inputs.push_back(assistOp->getIn(i+1)->getOffset());
uintb mask = ~((uintb)0);
int4 bit = fd->getArch()->funcptr_align;
if (bit != 0) {
mask = (mask >> bit) << bit;
}
for(int4 index=0;index<sizeIndices;++index) {
inputs[0] = index;
uintb output = pcodeScript->evaluate(inputs);
output &= mask;
addresstable.push_back(Address(spc,output));
}
ExecutablePcode *defaultScript = (ExecutablePcode *)fd->getArch()->pcodeinjectlib->getPayload(userop->getDefaultAddr());

View file

@ -411,7 +411,7 @@ input0 and output must be the same.
This instruction loads data from a dynamic location into the output
variable by dereferencing a pointer. The “pointer” comes in two
pieces. One piece, input1, is a normal variable containing the offset
of the object being pointed at. The other piece, input1, is a constant
of the object being pointed at. The other piece, input0, is a constant
indicating the space into which the offset applies. The data in input1
is interpreted as an unsigned offset and should have the same size as
the space referred to by the ID, i.e. a 4-byte address space requires

View file

@ -67,7 +67,7 @@ public class FillOutStructureCmd extends BackgroundCommand {
private int maxCallDepth = 1;
private NoisyStructureBuilder componentMap = new NoisyStructureBuilder();
private HashMap<Address, Integer> addressToCallInputMap = new HashMap<>();
private HashMap<Address, Address> addressToCallInputMap = new HashMap<>();
private Program currentProgram;
private ProgramLocation currentLocation;
@ -147,12 +147,11 @@ public class FillOutStructureCmd extends BackgroundCommand {
}
fillOutStructureDef(var);
pushIntoCalls();
structDT = createStructure(structDT, var, rootFunction, isThisParam);
populateStructure(structDT);
pushIntoCalls(structDT);
DataType pointerDT = new PointerDataType(structDT);
// Delay adding to the manager until full structure is accumulated
@ -171,33 +170,6 @@ public class FillOutStructureCmd extends BackgroundCommand {
return true;
}
/**
* Method to create a structure data type for a variable in the given function.
* @param var a parameter, local variable, or global variable used in the given function
* @param function the function to process
* @return a filled-in structure or null if one could not be created
*/
public Structure processStructure(HighVariable var, Function function) {
if (var == null || var.getSymbol() == null || var.getOffset() >= 0) {
return null;
}
Structure structDT;
try {
fillOutStructureDef(var);
structDT = createStructure(null, var, function, false);
populateStructure(structDT);
pushIntoCalls(structDT);
}
catch (Exception e) {
return null;
}
return structDT;
}
/**
* Retrieve the component map that was generated when structure was created using decomiler info
* @return componentMap
@ -226,16 +198,24 @@ public class FillOutStructureCmd extends BackgroundCommand {
/**
* Retrieve the (likely) storage address for a function parameter given its index
* @param function is the function
* @param paramIndex is the index of the parameter
* @param pointerDt is the pointer to structure datatype
* @return the storage address or null
* Retrieve the (likely) storage address of a function parameter given
* the inputs to a CALL p-code op and particular Varnode slot within the inputs.
* We compute the address from the point of view of the called function (callee)
* which may be different from the point of view of the caller, which may be
* different from the address of the Varnode currently holding the parameter.
* @param inputs is the array of Varnode inputs to the CALL
* @param slot is the index of the Varnode holding the parameter we want.
* @return the starting address of the parameter or null if the address can't be identified
*/
private Address computeParamAddress(Function function, int paramIndex, DataType pointerDt) {
private Address computeParamAddress(Varnode[] inputs, int slot) {
Address funcAddr = inputs[0].getAddress();
Function function = currentProgram.getFunctionManager().getFunctionAt(funcAddr);
if (function == null) {
return null;
}
Parameter[] parameters = function.getParameters();
if (paramIndex < parameters.length) {
return parameters[paramIndex].getMinAddress();
if (slot - 1 < parameters.length) {
return parameters[slot - 1].getMinAddress();
}
PrototypeModel model = function.getCallingConvention();
if (model == null) {
@ -244,26 +224,29 @@ public class FillOutStructureCmd extends BackgroundCommand {
return null;
}
}
VariableStorage argLocation =
model.getArgLocation(paramIndex, null, pointerDt, currentProgram);
return argLocation.getMinAddress();
DataType typeList[] = new DataType[slot + 1];
typeList[0] = DataType.DEFAULT; // Default function return data-type
for (int i = 1; i < slot + 1; ++i) {
typeList[i] = inputs[i].getHigh().getDataType();
}
VariableStorage[] storageLocations =
model.getStorageLocations(currentProgram, typeList, false);
return storageLocations[slot].getMinAddress();
}
/**
* Recursively visit calls that take the structure pointer as a parameter.
* Add any new references to the offsetToDataTypeMap.
* @param structDT is the structure to populate
*/
private void pushIntoCalls(Structure structDT) {
private void pushIntoCalls() {
AddressSet doneSet = new AddressSet();
DataType pointerDT = new PointerDataType(structDT);
while (addressToCallInputMap.size() > 0) {
currentCallDepth += 1;
if (currentCallDepth > maxCallDepth) {
return;
}
HashMap<Address, Integer> savedList = addressToCallInputMap;
HashMap<Address, Address> savedList = addressToCallInputMap;
addressToCallInputMap = new HashMap<>();
Set<Address> keys = savedList.keySet();
Iterator<Address> keyIter = keys.iterator();
@ -275,12 +258,10 @@ public class FillOutStructureCmd extends BackgroundCommand {
}
doneSet.addRange(addr, addr);
Function func = currentProgram.getFunctionManager().getFunctionAt(addr);
int paramIndex = savedList.get(addr);
Address storageAddr = computeParamAddress(func, paramIndex, pointerDT);
Address storageAddr = savedList.get(addr);
HighVariable paramHighVar = computeHighVariable(storageAddr, func);
if (paramHighVar != null) {
fillOutStructureDef(paramHighVar);
populateStructure(structDT);
}
}
}
@ -621,7 +602,7 @@ public class FillOutStructureCmd extends BackgroundCommand {
for (Varnode vn : instances) {
doneList.add(vn); // Mark instances as done to avoid recursion issues
if (vn != startVN) {
todoList.add(new PointerRef(startVN, 0)); // Make sure all instances are on the todo list
todoList.add(new PointerRef(vn, 0)); // Make sure all instances are on the todo list
}
}
@ -724,7 +705,10 @@ public class FillOutStructureCmd extends BackgroundCommand {
// find it as an input
int slot = pcodeOp.getSlot(currentRef.varnode);
if (slot > 0 && slot < pcodeOp.getNumInputs()) {
putOnCallParamList(inputs[0].getAddress(), slot - 1);
Address storageAddr = computeParamAddress(inputs, slot);
if (storageAddr != null) {
addressToCallInputMap.put(inputs[0].getAddress(), storageAddr);
}
}
}
else {
@ -742,16 +726,6 @@ public class FillOutStructureCmd extends BackgroundCommand {
}
}
/**
* Note that flow has hit a CALL instruction at a particular input parameter so that
* pushIntoCalls() can recurse into the call.
* @param address is the destination of the CALL
* @param j is the parameter index where flow hit
*/
private void putOnCallParamList(Address address, int j) {
addressToCallInputMap.put(address, j);
}
private long getSigned(Varnode varnode) {
long mask = 0x80L << ((varnode.getSize() - 1) * 8);
long value = varnode.getOffset();

View file

@ -2,8 +2,6 @@ EXCLUDE FROM GHIDRA JAR: true
MODULE FILE LICENSE: lib/jungrapht-visualization-1.0.jar BSD
MODULE FILE LICENSE: lib/jungrapht-layout-1.0.jar BSD
MODULE FILE LICENSE: lib/jgrapht-core-1.5.0.jar LGPL 2.1
MODULE FILE LICENSE: lib/jgrapht-io-1.5.0.jar LGPL 2.1
MODULE FILE LICENSE: lib/jheaps-0.13.jar Apache License 2.0
MODULE FILE LICENSE: lib/log4j-slf4j-impl-2.12.1.jar Apache License 2.0
MODULE FILE LICENSE: lib/slf4j-api-1.7.25.jar MIT

View file

@ -13,10 +13,7 @@ dependencies {
compile "com.github.tomnelson:jungrapht-visualization:1.0"
compile "com.github.tomnelson:jungrapht-layout:1.0"
compile "org.jgrapht:jgrapht-core:1.5.0"
// not using jgrapht-io code that depends on antlr, so exclude antlr
compile ("org.jgrapht:jgrapht-io:1.5.0") { exclude group: "org.antlr", module: "antlr4-runtime" }
runtime "org.slf4j:slf4j-api:1.7.25"
// use this if you want no slf4j log messages
runtime "org.slf4j:slf4j-nop:1.7.25"

View file

@ -2,4 +2,5 @@ MODULE FILE LICENSE: lib/jung-visualization-2.1.1.jar BSD
MODULE FILE LICENSE: lib/jung-algorithms-2.1.1.jar BSD
MODULE FILE LICENSE: lib/jung-api-2.1.1.jar BSD
MODULE FILE LICENSE: lib/jung-graph-impl-2.1.1.jar BSD
MODULE FILE LICENSE: lib/jgrapht-core-1.4.0.jar LGPL 2.1
MODULE FILE LICENSE: lib/jgrapht-core-1.5.0.jar LGPL 2.1
MODULE FILE LICENSE: lib/jgrapht-io-1.5.0.jar LGPL 2.1

View file

@ -17,7 +17,10 @@ dependencies {
compile "net.sf.jung:jung-graph-impl:2.1.1"
compile "net.sf.jung:jung-visualization:2.1.1"
compile "org.jgrapht:jgrapht-core:1.4.0"
compile "org.jgrapht:jgrapht-core:1.5.0"
// not using jgrapht-io code that depends on antlr, so exclude antlr
compile ("org.jgrapht:jgrapht-io:1.5.0") { exclude group: "org.antlr", module: "antlr4-runtime" }
// These have abstract test classes and stubs needed by this module
testCompile project(path: ':Docking', configuration: 'testArtifacts')

View file

@ -1,8 +1,8 @@
##VERSION: 2.0
##MODULE IP: BSD
##MODULE IP: FAMFAMFAM Icons - CC 2.5
##MODULE IP: Oxygen Icons - LGPL 3.0
##MODULE IP: LGPL 2.1
##MODULE IP: Oxygen Icons - LGPL 3.0
Module.manifest||GHIDRA||||END|
build.gradle||GHIDRA||||END|
data/ExtensionPoint.manifest||GHIDRA||||END|

View file

@ -30,6 +30,9 @@ dependencies {
// Must specify the specific antlr implementation to use or it will default to trying to find
// version 2.7.7 (which we don't have)
antlr "org.antlr:antlr:3.5.2"
// need to add in the antlr dependencies for when we build from flat jar dirs
antlr "org.antlr:antlr-runtime:3.5.2"
antlr "org.antlr:ST4:4.0.8"
}
def genSrcDir = 'generated-src/antlr/main'

View file

@ -123,7 +123,7 @@ input0 and output must be the same.
This instruction loads data from a dynamic location into the output
variable by dereferencing a pointer. The &#8220;pointer&#8221; comes in two
pieces. One piece, input1, is a normal variable containing the offset
of the object being pointed at. The other piece, input1, is a constant
of the object being pointed at. The other piece, input0, is a constant
indicating the space into which the offset applies. The data in input1
is interpreted as an unsigned offset and should have the same size as
the space referred to by the ID, i.e. a 4-byte address space requires

View file

@ -292,28 +292,49 @@ String getCurrentPlatformName() {
* given project
*
*********************************************************************************/
List<String> getExternalDependencies(Project project) {
List<String> getExternalRuntimeDependencies(Project project) {
List<String> list = new ArrayList<String>()
// for each dependency in the compile configuration
Configuration runtimeConfig = project.configurations.runtime
runtimeConfig.allDependencies.each { dep ->
list.addAll(getExternalDependencies(project.configurations.compile));
list.addAll(getExternalDependencies(project.configurations.runtime));
return list
}
List<String> getExternalDependencies(Configuration configuration) {
List<String> list = new ArrayList<>();
configuration.dependencies.each { dep ->
// if the dependency is an external jar
if (dep.class.toString().contains("DefaultExternalModuleDependency")) {
if (dep instanceof ExternalDependency) {
// loop back through all the dependency files, looking for one that contains the dependency name.
String depPath = runtimeConfig.find {
String depPath = configuration.find {
it.name.contains(dep.name)
}
// if we found the path, then add it to the list
if (depPath && !depPath.contains("libsForBuild")) {
if (depPath) {
list.add(depPath)
}
}
}
return list
return list;
}
/*********************************************************************************
* Returns a list of all the external library paths declared as dependencies for the
* given project
*
*********************************************************************************/
Set<String> getAllExternalDependencies(Project project) {
Set<String> set = new HashSet<String>()
project.getConfigurations().each { config ->
set.addAll(getExternalDependencies(config))
}
return set
}
/******************************************************************************************
@ -334,7 +355,7 @@ String generateLibraryDependencyMapping() {
libsFile.withWriter { out ->
subprojects { p ->
p.plugins.withType(JavaPlugin) {
List<String> libs = getExternalDependencies(p);
List<String> libs = getExternalRuntimeDependencies(p);
if (libs != null) {
out.println "Module: $p.name"
libs.each { path ->
@ -346,6 +367,37 @@ String generateLibraryDependencyMapping() {
}
return libsFile.absolutePath
}
/******************************************************************************************
*
* Creates a file that lists all external jars used to build and run Ghidra
*
******************************************************************************************/
String generateAllExternalLibsFile() {
File libsFile = file("$buildDir/AllExternalLibs.txt")
// Check to make sure the build folder exists - if it doesn't, the 'libsFile.withWriter'
// call (below) will fail miserably.
def buildFolder = file ("$buildDir")
if (!buildFolder.exists()) {
buildFolder.mkdirs()
}
Set<String> allLibs = new HashSet<>();
subprojects { p ->
p.plugins.withType(JavaPlugin) {
Set<String> libs = getAllExternalDependencies(p);
if (libs != null) {
allLibs.addAll(libs);
}
}
}
libsFile.withWriter { out ->
allLibs.each { path ->
out.println "$path"
}
}
return libsFile.absolutePath
}
task allSleighCompile {
}

View file

@ -173,7 +173,7 @@ plugins.withType(JavaPlugin) {
// External Libraries
gradle.taskGraph.whenReady { taskGraph ->
List<String> externalPaths = getExternalDependencies(p)
List<String> externalPaths = getExternalRuntimeDependencies(p)
externalPaths.each { path ->
from (path) {
into {zipPath + "/lib" }

View file

@ -12,8 +12,22 @@ task prepDev {
// the GhidraLauncher depends on this file to build the classpath in dev mode
dependsOn { generateLibraryDependencyMapping }
// generate list of all library files used to build and run ghidra. (not strictly necessary here, but nice to have)
dependsOn { generateAllExternalLibsFile }
}
/******************************************************************************************
* TASK generateAllExternalLibsFile
*
* Summary: Creates a file that lists all libraries used to build and run Ghidra
******************************************************************************************/
task generateAllExternalLibsFile {
doFirst{
generateAllExternalLibsFile()
}
}
/******************************************************************************************
* TASK generateLibraryDependencyMapping
@ -24,4 +38,5 @@ task generateLibraryDependencyMapping {
doFirst{
generateLibraryDependencyMapping()
}
}
}

View file

@ -61,7 +61,7 @@ task zipExtensions (type: Zip) {
/////////////////
gradle.taskGraph.whenReady { taskGraph ->
if (project.plugins.withType(JavaPlugin)) {
List<String> externalPaths = getExternalDependencies(p)
List<String> externalPaths = getExternalRuntimeDependencies(p)
externalPaths.each { path ->
from (path) {
into { getBaseProjectName(p) + "/lib" }

View file

@ -82,7 +82,7 @@ def Map<String, String> getModuleManifestIp(Project project) {
*********************************************************************************/
def checkExternalLibsInMap(Map<String, String> map, Project project) {
if (project.plugins.withType(JavaPlugin)) {
List<String> libs = getExternalDependencies(project)
List<String> libs = getExternalRuntimeDependencies(project)
libs.each { lib ->
String libName = new File(lib).getName() // get just the filename without the path
String relativePath = "lib/"+libName;