mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
186 lines
5.6 KiB
Java
186 lines
5.6 KiB
Java
/* ###
|
|
* 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 pdb;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
import ghidra.app.plugin.core.analysis.*;
|
|
import ghidra.app.plugin.core.datamgr.archive.DuplicateIdException;
|
|
import ghidra.app.services.DataTypeManagerService;
|
|
import ghidra.app.util.bin.format.pdb.PdbException;
|
|
import ghidra.app.util.bin.format.pdb.PdbParser;
|
|
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
|
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbReaderOptions;
|
|
import ghidra.app.util.importer.MessageLog;
|
|
import ghidra.app.util.pdb.pdbapplicator.*;
|
|
import ghidra.framework.options.Options;
|
|
import ghidra.program.model.address.AddressSetView;
|
|
import ghidra.program.model.listing.Program;
|
|
import ghidra.util.exception.CancelledException;
|
|
import ghidra.util.task.*;
|
|
|
|
class LoadPdbTask extends Task {
|
|
private File pdbFile;
|
|
private DataTypeManagerService service;
|
|
private final Program program;
|
|
private final boolean useMsDiaParser;
|
|
private final PdbApplicatorControl control; // PDB Universal Parser only
|
|
private String resultMessages;
|
|
private Exception resultException;
|
|
|
|
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
|
|
DataTypeManagerService service) {
|
|
super("Load PDB", true, false, true, true);
|
|
this.program = program;
|
|
this.pdbFile = pdbFile;
|
|
this.useMsDiaParser = useMsDiaParser;
|
|
this.control = control;
|
|
this.service = service;
|
|
}
|
|
|
|
@Override
|
|
public void run(TaskMonitor monitor) {
|
|
|
|
WrappingTaskMonitor wrappedMonitor = new WrappingTaskMonitor(monitor) {
|
|
@Override
|
|
public void initialize(long max) {
|
|
// don't let called clients change our monitor type; we don't show progress
|
|
}
|
|
};
|
|
|
|
MessageLog log = new MessageLog();
|
|
AnalysisWorker worker = new AnalysisWorker() {
|
|
|
|
@Override
|
|
public String getWorkerName() {
|
|
return "Load PDB";
|
|
}
|
|
|
|
@Override
|
|
public boolean analysisWorkerCallback(Program currentProgram, Object workerContext,
|
|
TaskMonitor currentMonitor) throws CancelledException {
|
|
|
|
try {
|
|
if (useMsDiaParser) {
|
|
if (!parseWithMsDiaParser(log, wrappedMonitor)) {
|
|
return false;
|
|
}
|
|
}
|
|
else if (!parseWithNewParser(log, wrappedMonitor)) {
|
|
return false;
|
|
}
|
|
scheduleAdditionalAnalysis();
|
|
}
|
|
catch (IOException e) {
|
|
log.appendMsg("PDB IO Error: " + e.getMessage());
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
try {
|
|
AutoAnalysisManager.getAnalysisManager(program)
|
|
.scheduleWorker(worker, null, true, wrappedMonitor);
|
|
}
|
|
catch (InterruptedException | CancelledException e) {
|
|
// ignore
|
|
}
|
|
catch (InvocationTargetException e) {
|
|
resultException = e;
|
|
}
|
|
if (log.hasMessages()) {
|
|
resultMessages = log.toString();
|
|
}
|
|
|
|
}
|
|
|
|
String getResultMessages() {
|
|
return resultMessages;
|
|
}
|
|
|
|
Exception getResultException() {
|
|
return resultException;
|
|
}
|
|
|
|
private boolean parseWithMsDiaParser(MessageLog log, TaskMonitor monitor)
|
|
throws IOException, CancelledException {
|
|
PdbParser parser = new PdbParser(pdbFile, program, service, true, true, monitor);
|
|
try {
|
|
parser.parse();
|
|
parser.openDataTypeArchives();
|
|
parser.applyTo(log);
|
|
return true;
|
|
}
|
|
catch (PdbException | DuplicateIdException e) {
|
|
log.appendMsg("PDB Error: " + e.getMessage());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean parseWithNewParser(MessageLog log, TaskMonitor monitor)
|
|
throws IOException, CancelledException {
|
|
|
|
PdbReaderOptions pdbReaderOptions = new PdbReaderOptions(); // use defaults
|
|
|
|
PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions();
|
|
|
|
pdbApplicatorOptions.setProcessingControl(control);
|
|
|
|
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse(pdbFile,
|
|
pdbReaderOptions, monitor)) {
|
|
monitor.setMessage("PDB: Parsing " + pdbFile + "...");
|
|
pdb.deserialize();
|
|
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb);
|
|
applicator.applyTo(program, program.getDataTypeManager(), program.getImageBase(),
|
|
pdbApplicatorOptions, log);
|
|
|
|
return true;
|
|
}
|
|
catch (ghidra.app.util.bin.format.pdb2.pdbreader.PdbException e) {
|
|
log.appendMsg("PDB Error: " + e.getMessage());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// We need to kick off any byte analyzers (like getting import symbols), as they typically
|
|
// won't get kicked off by our loading of the PDB.
|
|
private void scheduleAdditionalAnalysis() {
|
|
|
|
AddressSetView addrs = program.getMemory();
|
|
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
|
|
Options analysisProperties = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
|
|
|
//other planned analysis here.
|
|
|
|
scheduleDemangler(manager, analysisProperties, addrs);
|
|
}
|
|
|
|
private void scheduleDemangler(AutoAnalysisManager manager, Options analysisProperties,
|
|
AddressSetView addrs) {
|
|
MicrosoftDemanglerAnalyzer demanglerAnalyzer = new MicrosoftDemanglerAnalyzer();
|
|
String analyzerName = demanglerAnalyzer.getName();
|
|
String valueAsString = analysisProperties.getValueAsString(analyzerName);
|
|
|
|
// Only schedule analyzer if enabled
|
|
if (!Boolean.parseBoolean(valueAsString)) {
|
|
return;
|
|
}
|
|
manager.scheduleOneTimeAnalysis(demanglerAnalyzer, addrs);
|
|
}
|
|
|
|
}
|