mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 05:33:02 +00:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
5555566e59
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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 “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
|
||||
|
|
72
build.gradle
72
build.gradle
|
@ -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 {
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue