Merge remote-tracking branch 'origin/GP-1659_SwitchWithInject' into

patch
This commit is contained in:
ghidra1 2022-01-14 19:33:45 -05:00
commit e5080cd9b1
15 changed files with 778 additions and 7 deletions

View File

@ -34,7 +34,7 @@ You may not need all of these, depending on which portions you are building or d
- https://adoptium.net/releases.html?variant=openjdk11&jvmVariant=hotspot
- Amazon Corretto
- https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html
* Gradle 6.4+ or 7.x
* Gradle 6.8+ or 7.x
- https://gradle.org/releases/
* A C/C++ compiler - We use GCC on Linux, Xcode (Clang) on macOS, and Visual Studio (2017 or later) on Windows.
- https://gcc.gnu.org/

View File

@ -17,6 +17,7 @@ package agent.gdb.pty.ssh;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import javax.swing.JOptionPane;
@ -28,7 +29,8 @@ import com.jcraft.jsch.ConfigRepository.Config;
import agent.gdb.pty.PtyFactory;
import docking.DockingWindowManager;
import docking.widgets.PasswordDialog;
import ghidra.util.*;
import ghidra.util.Msg;
import ghidra.util.StringUtilities;
public class GhidraSshPtyFactory implements PtyFactory {
private static final String TITLE = "GDB via SSH";
@ -209,6 +211,10 @@ public class GhidraSshPtyFactory implements PtyFactory {
return session;
}
catch (JSchException e) {
if (e.getMessage().equals("Auth cancel")) {
Msg.error(this, "SSH connection canceled");
throw new CancellationException("SSH connection canceled");
}
Msg.error(this, "SSH connection error");
throw new IOException("SSH connection error", e);
}

View File

@ -755,6 +755,8 @@ void FlowInfo::generateOps(void)
addrlist.push_back(data.getAddress());
while(!addrlist.empty()) // Recovering as much as possible except jumptables
fallthru();
if (hasInject())
injectPcode();
do {
bool collapsed_jumptable = false;
while(!tablelist.empty()) { // For each jumptable found

View File

@ -0,0 +1,35 @@
/* ###
* 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.
*/
import org.osgi.framework.BundleContext;
import ghidra.app.plugin.core.osgi.GhidraBundleActivator;
import pdbquery.PdbFactory;
/**
* Activator class for the PdbQuery bundle of scripts. On "stop," calls method to close all PDBs.
*/
public class PdbQueryActivator extends GhidraBundleActivator {
@Override
protected void start(BundleContext bc, Object api) {
// purposefully empty
}
@Override
protected void stop(BundleContext bc, Object api) {
PdbFactory.closeAllPdbs(null);
}
}

View File

@ -0,0 +1,29 @@
/* ###
* 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.
*/
// Closes all PDBs opened in the PdbQuery package.
//
//@category PDB
import ghidra.app.script.GhidraScript;
import pdbquery.PdbFactory;
public class PdbQueryCloseAllScript extends GhidraScript {
@Override
protected void run() throws Exception {
PdbFactory.closeAllPdbs(this);
}
}

View File

@ -0,0 +1,43 @@
/* ###
* 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.
*/
// Closes a user-selected PDB that was opened in the PdbQuery package.
//
//@category PDB
import java.util.List;
import ghidra.app.script.GhidraScript;
import pdbquery.PdbFactory;
import pdbquery.PdbFactory.PdbInfo;
public class PdbQueryCloseScript extends GhidraScript {
@Override
protected void run() throws Exception {
List<PdbInfo> orderedPdbInfo = PdbFactory.getPdbInfo();
if (orderedPdbInfo.isEmpty()) {
println("There are no open PDBs. Run " + PdbQueryOpenScript.class.getSimpleName() +
" to open a PDB.");
return;
}
PdbInfo lastPdbInfo = PdbFactory.getLastPdbInfoByScriptClass(getClass());
PdbInfo choice = askChoice("Choose PDB to Close", "PDB Info", orderedPdbInfo, lastPdbInfo);
PdbFactory.closePdb(this, choice.getFilename());
}
}

View File

@ -0,0 +1,51 @@
/* ###
* 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.
*/
// Queries a PDB in PdbQuery package for data and item type records that contain the search string.
//
//@category PDB
import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
import pdbquery.PdbFactory;
import pdbquery.PdbFactory.PdbInfo;
import pdbquery.PdbQuery;
public class PdbQueryDatatypeScript extends GhidraScript {
@Override
protected void run() throws Exception {
List<PdbInfo> orderedPdbInfo = PdbFactory.getPdbInfo();
if (orderedPdbInfo.isEmpty()) {
println("There are no open PDBs. Run " + PdbQueryOpenScript.class.getSimpleName() +
" to open a PDB.");
return;
}
PdbInfo lastPdbInfo = PdbFactory.getLastPdbInfoByScriptClass(getClass());
PdbInfo choice = askChoice("Choose PDB to query", "PDB Info", orderedPdbInfo, lastPdbInfo);
AbstractPdb pdb = choice.getPdb();
String searchString = askString("Enter Search String", "String");
println("Searching " + choice.getFilename() + " for: " + searchString);
PdbQuery.searchDataTypes(this, pdb, searchString);
PdbQuery.searchItemTypes(this, pdb, searchString);
}
}

View File

@ -0,0 +1,62 @@
/* ###
* 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.
*/
// Opens a PDB for the PdbQuery package.
//
//@category PDB
import java.io.File;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbIdentifiers;
import pdb.PdbUtils;
import pdbquery.PdbFactory;
public class PdbQueryOpenScript extends GhidraScript {
@Override
protected void run() throws Exception {
File pdbFile = askFile("Choose a PDB file", "OK");
if (pdbFile == null) {
println("Aborting: no file chosen.");
return;
}
String pdbFilename = pdbFile.getAbsolutePath();
if (!pdbFile.exists()) {
println("Aborting: " + pdbFilename + " is not a valid file.");
return;
}
if (!StringUtils.endsWithIgnoreCase(pdbFilename, ".pdb")) {
println("Aborting: filename missing .pdb extension: " + pdbFilename);
return;
}
PdbIdentifiers identifiers = PdbUtils.getPdbIdentifiers(pdbFile, monitor);
String fileAndIdentifiers =
pdbFilename + ", " + identifiers + " (File, GUID/Signature, Age, Version, Processor)";
if (!askYesNo("Confirm Load", fileAndIdentifiers)) {
println("Aborting: " + pdbFilename + " not confirmed.");
return;
}
PdbFactory.openPdb(this, pdbFilename, monitor);
println("PDB Opened: " + fileAndIdentifiers);
}
}

View File

@ -0,0 +1,49 @@
/* ###
* 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.
*/
// Queries a PDB in PdbQuery package for Symbol records that contain the search string.
//
//@category PDB
import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
import pdbquery.PdbFactory;
import pdbquery.PdbFactory.PdbInfo;
import pdbquery.PdbQuery;
public class PdbQuerySymbolScript extends GhidraScript {
@Override
protected void run() throws Exception {
List<PdbInfo> orderedPdbInfo = PdbFactory.getPdbInfo();
if (orderedPdbInfo.isEmpty()) {
println("There are no open PDBs. Run " + PdbQueryOpenScript.class.getSimpleName() +
" to open a PDB.");
return;
}
PdbInfo lastPdbInfo = PdbFactory.getLastPdbInfoByScriptClass(getClass());
PdbInfo choice = askChoice("Choose PDB to query", "PDB Info", orderedPdbInfo, lastPdbInfo);
AbstractPdb pdb = choice.getPdb();
String searchString = askString("Enter Search String", "String");
println("Searching " + choice.getFilename() + " for: " + searchString);
PdbQuery.searchSymbols(this, pdb, searchString);
}
}

View File

@ -0,0 +1,242 @@
/* ###
* 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 pdbquery;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Helper class for the PdbQuery set of scripts that allows the PdbQuery scripts to manage the
* opening, holding open (caching), and closing of PDB files so that multiple user queries can
* be run against the PDBs. Without this notion, if a user wanted to query a PDB with multiple
* runs of a query scripts, each run would have to, once again, open and parse the PDB file
* that is desired, which could take minutes or longer.
*/
public class PdbFactory {
private static TreeMap<String, PdbInfo> pdbInfoByFile = new TreeMap<>();
private static Map<Class<? extends GhidraScript>, PdbInfo> pdbInfoByScriptClass =
new HashMap<>();
/**
* Opens and retains reference to the PDB file specified. Must call
* {@link #closePdb(GhidraScript, String)} to close the PDB and remove it from the map; can
* alternatively use {@link #closeAllPdbs(GhidraScript)} to close all PDBs in the map.
* @param script script for which we are working
* @param filename name of PDB file to open and load into map
* @param monitor task monitor
* @return PDB associated with the filename
* @throws CancelledException upon user cancellation
* @throws PdbException upon issues parsing the PDB
*/
public static PdbInfo openPdb(GhidraScript script, String filename, TaskMonitor monitor)
throws CancelledException, PdbException {
PdbInfo pdbInfo = pdbInfoByFile.get(filename);
if (pdbInfo != null) {
return pdbInfo;
}
println(script, "Opening PDB: " + filename);
try {
AbstractPdb pdb = PdbParser.parse(filename, new PdbReaderOptions(), monitor);
PdbIdentifiers identifiers = pdb.getIdentifiers();
pdb.deserialize(monitor);
PdbReaderMetrics metrics = pdb.getPdbReaderMetrics();
pdbInfo = new PdbInfo(filename, identifiers, pdb, metrics);
pdbInfoByFile.put(filename, pdbInfo);
println(script, "\n" + metrics.getPostProcessingReport());
return pdbInfo;
}
catch (IOException ioe) {
println(script, ioe.getMessage());
Msg.debug(null, ioe.getMessage());
}
return null;
}
/**
* Closes and unloads the PDB file from the map. Not removed from map if IOException.
* @param script script for which we are working
* @param filename filename of the PDB file
* @return true if successfully closed and removed from the map; false if not found in the map
* or if problem closing the PDB.
*/
public static boolean closePdb(GhidraScript script, String filename) {
boolean success = closePdbInternal(script, filename);
if (success) {
pdbInfoByFile.remove(filename);
}
return success;
}
/**
* Closes and unloads the PDB file from the map. Not removed from map if IOException.
* @param script script for which we are working
* @return true if all PDBs were successfully closed and unloaded from the map
*/
public static boolean closeAllPdbs(GhidraScript script) {
boolean allUnloaded = true;
Iterator<Entry<String, PdbInfo>> iterator = pdbInfoByFile.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, PdbInfo> entry = iterator.next();
String filename = entry.getKey();
boolean success = closePdbInternal(script, filename);
if (success) {
iterator.remove();
}
allUnloaded &= success;
}
return allUnloaded;
}
private static boolean closePdbInternal(GhidraScript script, String filename) {
PdbInfo pdbInfo = pdbInfoByFile.get(filename);
AbstractPdb pdb = pdbInfo.getPdb();
if (pdb != null) {
try {
pdb.close();
String message = "PDB Closed: " + filename;
println(script, message);
}
catch (IOException ioe) {
println(script, ioe.getMessage());
Msg.info(null, ioe.getMessage());
return false;
}
return true;
}
return false;
}
/**
* Returns list of PDB information in alphabetical order by filename.
* @return the list
*/
public static List<PdbInfo> getPdbInfo() {
List<PdbInfo> orderedPdbInfo = new ArrayList<>();
for (String name : pdbInfoByFile.navigableKeySet()) {
orderedPdbInfo.add(pdbInfoByFile.get(name));
}
return orderedPdbInfo;
}
/**
* Sets the cache PdbInfo value for the class argument
* @param clazz the class for which to cache the value
* @param pdbInfo the PdbInfo value to cache.
*/
public static void setLastPdbInfoByScriptClass(Class<? extends GhidraScript> clazz,
PdbInfo pdbInfo) {
pdbInfoByScriptClass.put(clazz, pdbInfo);
}
/**
* Returns the PdbInfo cached for the class argument.
* @param clazz the class of the script used to look up the cached value for return
* @return the PdbInfo
*/
public static PdbInfo getLastPdbInfoByScriptClass(Class<? extends GhidraScript> clazz) {
return pdbInfoByScriptClass.get(clazz);
}
/**
* Method for outputting a message to the console (if script is not null); otherwise outputs
* the message to Msg.info().
* @param script the script
* @param message the message to output to the console
*/
private static void println(GhidraScript script, String message) {
if (script != null) {
script.println(message);
}
else {
Msg.info(PdbFactory.class, message);
}
}
/**
* Information about a PDB used for specifying and uniquely identifying a PDB along with the
* parsed PDB itself and the PDB parsing metrics generated during the parse.
*/
public static class PdbInfo {
private String filename; // absolute pathname
private PdbIdentifiers identifiers;
private AbstractPdb pdb;
private PdbReaderMetrics metrics;
/**
* Constructor.
* @param filename PDB filename in absolute pathname format
* @param identifiers identifiers used to help identify versions of the PDB
* @param pdb the parsed PDB
* @param metrics the PDB metrics generated when the PDB was opened and parsed
*/
PdbInfo(String filename, PdbIdentifiers identifiers, AbstractPdb pdb,
PdbReaderMetrics metrics) {
this.filename = filename;
this.identifiers = identifiers;
this.pdb = pdb;
this.metrics = metrics;
}
/**
* Returns the PDB filename in absolute path format
* @return the filename
*/
public String getFilename() {
return filename;
}
/**
* Returns the parsed PDB
* @return the parsed PDB
*/
public AbstractPdb getPdb() {
return pdb;
}
/**
* Returns PDB identifiers that help specify its version
* @return the identifiers
*/
public PdbIdentifiers getIdentifiers() {
return identifiers;
}
/**
* Returns the metrics generated during PDB parsing
* @return the metrics
*/
public PdbReaderMetrics getPdbReaderMetrics() {
return metrics;
}
@Override
// The PDB and parsing metrics are purposefully not included in this output.
public String toString() {
return filename + "; " + identifiers;
}
}
}

View File

@ -0,0 +1,251 @@
/* ###
* 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 pdbquery;
import java.util.Map;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.PrimitiveMsType;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Helper class with static query methods available to PdbQuery set of scripts. The methods
* in this class allow the user to query particular components inside of a PDB.
*/
public class PdbQuery {
/**
* Returns the specified PDB data type record.
* @param script the script for which we are working
* @param pdb the PDB containing the record
* @param number the data type record number
* @return the data type record
*/
public static AbstractMsType getDataTypeRecord(GhidraScript script, AbstractPdb pdb,
int number) {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) {
println(script, "PDB does not contain a TPI... aborting search.");
return null;
}
if (number < 0 || number >= tpi.getTypeIndexMaxExclusive()) {
println(script, "Record number (" + number + ") out of range (" + 0 + " - " +
tpi.getTypeIndexMaxExclusive() + ")");
return null;
}
if (number < tpi.getTypeIndexMin()) {
// Created on the fly and is not cached. Moreover, it can add yet-unseen records to
// the PDB... so this might not be desired... Also... the record number could represent
// what is typically a "type" or an "item" and that cannot be distingushed here...
// there is not conflict between primitive type and primitive items... they come from
// the same pool, but we might return what is an item record in the request for a type
// record or vice versa. TODO: investigate all of these issues this further; might
// need to eliminate this report or add a lot more code.
return new PrimitiveMsType(pdb, number);
}
RecordNumber recordNumber = RecordNumber.typeRecordNumber(number);
AbstractMsType typeRecord = pdb.getTypeRecord(recordNumber);
return typeRecord;
}
/**
* Returns the specified PDB item record.
* @param script the script for which we are working
* @param pdb the PDB containing the record
* @param number the item record number
* @return the item record
*/
public static AbstractMsType getItemTypeRecord(GhidraScript script, AbstractPdb pdb,
int number) {
AbstractTypeProgramInterface ipi = pdb.getItemProgramInterface();
if (ipi == null) {
println(script, "PDB does not contain an IPI... aborting search.");
return null;
}
if (number < 0 || number >= ipi.getTypeIndexMaxExclusive()) {
println(script, "Record number (" + number + ") out of range (" + 0 + " - " +
ipi.getTypeIndexMaxExclusive() + ")");
return null;
}
if (number < ipi.getTypeIndexMin()) {
// Created on the fly and is not cached. Moreover, it can add yet-unseen records to
// the PDB... so this might not be desired... Also... the record number could represent
// what is typically a "type" or an "item" and that cannot be distingushed here...
// there is not conflict between primitive type and primitive items... they come from
// the same pool, but we might return what is an item record in the request for a type
// record or vice versa. TODO: investigate all of these issues this further; might
// need to eliminate this report or add a lot more code.
return new PrimitiveMsType(pdb, number);
}
RecordNumber recordNumber = RecordNumber.itemRecordNumber(number);
AbstractMsType typeRecord = pdb.getTypeRecord(recordNumber);
return typeRecord;
}
/**
* Searches PDB data type records that contain the search string. Outputs results to the
* console.
* @param script the script for which we are working
* @param pdb the PDB to search
* @param searchString the search string
* @throws CancelledException upon user cancellation
*/
public static void searchDataTypes(GhidraScript script, AbstractPdb pdb, String searchString)
throws CancelledException {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) {
println(script, "PDB does not contain a TPI... aborting search.");
}
StringBuilder results = new StringBuilder();
results.append('\n');
int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin();
TaskMonitor monitor = script.getMonitor();
monitor.initialize(num);
println(script, "Searching " + num + " PDB data type components...");
for (int indexNumber =
tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCanceled();
RecordNumber recordNumber = RecordNumber.typeRecordNumber(indexNumber);
AbstractMsType typeRecord = pdb.getTypeRecord(recordNumber);
String recordString = typeRecord.toString();
if (recordString.contains(searchString)) {
results.append("Data number " + indexNumber + ":\n");
results.append(recordString);
results.append('\n');
}
monitor.incrementProgress(1);
}
println(script, results.toString());
}
/**
* Searches PDB item records that contain the search string. Outputs results to the
* console.
* @param script the script for which we are working
* @param pdb the PDB to search
* @param searchString the search string
* @throws CancelledException upon user cancellation
*/
public static void searchItemTypes(GhidraScript script, AbstractPdb pdb, String searchString)
throws CancelledException {
AbstractTypeProgramInterface ipi = pdb.getItemProgramInterface();
if (ipi == null) {
println(script, "PDB does not contain an IPI... aborting search.");
return;
}
StringBuilder results = new StringBuilder();
results.append('\n');
int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin();
TaskMonitor monitor = script.getMonitor();
monitor.initialize(num);
println(script, "Searching " + num + " PDB item type components...");
for (int indexNumber =
ipi.getTypeIndexMin(); indexNumber < ipi.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCanceled();
RecordNumber recordNumber = RecordNumber.itemRecordNumber(indexNumber);
AbstractMsType typeRecord = pdb.getTypeRecord(recordNumber);
String recordString = typeRecord.toString();
if (recordString.contains(searchString)) {
results.append("Item number " + indexNumber + ":\n");
results.append(recordString);
results.append('\n');
}
monitor.incrementProgress(1);
}
println(script, results.toString());
}
/**
* Searches PDB symbol records that contain the search string. Outputs results to the
* console.
* @param script the script for which we are working
* @param pdb the PDB to search
* @param searchString the search string
* @throws CancelledException upon user cancellation
*/
public static void searchSymbols(GhidraScript script, AbstractPdb pdb, String searchString)
throws CancelledException {
StringBuilder results = new StringBuilder();
results.append('\n');
int numModules = pdb.getDebugInfo().getNumModules();
TaskMonitor monitor = script.getMonitor();
int numSymbols = 0;
for (int module = 0; module <= numModules; module++) {
monitor.checkCanceled();
try {
Map<Long, AbstractMsSymbol> symbols =
pdb.getDebugInfo().getModuleSymbolsByOffset(module);
numSymbols += symbols.size();
}
catch (PdbException e) {
// just skip the module... logging this in the next loop.
}
}
monitor.initialize(numSymbols);
println(script, "Searching " + numSymbols + " PDB symbol components...");
for (int module = 0; module <= numModules; module++) {
monitor.checkCanceled();
try {
Map<Long, AbstractMsSymbol> symbols =
pdb.getDebugInfo().getModuleSymbolsByOffset(module);
numSymbols += symbols.size();
for (Map.Entry<Long, AbstractMsSymbol> entry : symbols.entrySet()) {
monitor.checkCanceled();
AbstractMsSymbol symbol = entry.getValue();
String symbolString = symbol.toString();
if (symbolString.contains(searchString)) {
results.append("Module " + module + ", Offset " + entry.getKey() + ":\n");
results.append(symbolString);
results.append('\n');
}
monitor.incrementProgress(1);
}
}
catch (PdbException e) {
Msg.debug(PdbQuery.class, "Skipping module " + module + " due to exception.");
}
}
println(script, results.toString());
}
/**
* Method for outputting a message to the console (if script is not null); otherwise outputs
* the message to Msg.info().
* @param script the script
* @param message the message to output to the console
*/
private static void println(GhidraScript script, String message) {
if (script != null) {
script.println(message);
}
else {
Msg.info(PdbQuery.class, message);
}
}
}

View File

@ -739,7 +739,8 @@ public class PdbApplicator {
int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin();
monitor.initialize(num);
setMonitorMessage("PDB: Processing " + num + " item type components...");
for (int indexNumber = ipi.getTypeIndexMin(); indexNumber < num; indexNumber++) {
for (int indexNumber =
ipi.getTypeIndexMin(); indexNumber < ipi.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCanceled();
MsTypeApplier applier = getTypeApplier(RecordNumber.itemRecordNumber(indexNumber));
applier.apply();

View File

@ -18,7 +18,7 @@
<h1>Ghidra Installation Guide</h1>
<p>
The installation information provided is effective as of Ghidra 10.1 and is subject to change with
The installation information provided is effective as of Ghidra 10.1.2 and is subject to change with
future releases.
</p>
@ -318,7 +318,7 @@ Ghidra release includes native binaries for the following platforms:</p>
system:</p>
<ul>
<li>A <a href="#Requirements">supported</a> version of a Java Development Kit</li>
<li><a href="https://gradle.org/releases/">Gradle 6 or 7</a></li>
<li><a href="https://gradle.org/releases/">Gradle 6.8+ or 7.x</a></li>
<li>make, gcc, and g++ (Linux/macOS-only)</li>
<li>
<a href="https://visualstudio.microsoft.com/vs/community/">Microsoft Visual Studio</a>

View File

@ -44,7 +44,7 @@ To create the latest development build for your platform from this source reposi
##### Install build tools:
* [JDK 11 64-bit][jdk11]
* [Gradle 6.4+ or 7.x][gradle]
* [Gradle 6.8+ or 7.x][gradle]
* make, gcc, and g++ (Linux/macOS-only)
* [Microsoft Visual Studio][vs] (Windows-only)