mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/GP-4017_dev747368_pdb_symbolserver_fsrl'
This commit is contained in:
commit
7fa03c9719
8 changed files with 350 additions and 19 deletions
|
@ -0,0 +1,161 @@
|
|||
/* ###
|
||||
* 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.symbolserver;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.formats.gfilesystem.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Companion to the {@link SameDirSymbolStore}, handles the case where the imported binary
|
||||
* was located in a container file (eg. zip file).
|
||||
* <p>
|
||||
* Instances of this class are conditionally created by the
|
||||
* {@link SameDirSymbolStore#createInstance(String, SymbolServerInstanceCreatorContext) registry factory method}
|
||||
* when it detects that the imported binary's {@link FSRL} isn't a simple local file.
|
||||
*/
|
||||
public class ContainerFileSymbolServer implements SymbolServer {
|
||||
|
||||
private final FileSystemService fsService;
|
||||
private final FSRLRoot fsFSRL;
|
||||
private final String subdir;
|
||||
|
||||
public ContainerFileSymbolServer(FSRL programFSRL) {
|
||||
this.fsFSRL = programFSRL.getFS();
|
||||
this.subdir = FilenameUtils.getFullPath(programFSRL.getPath());
|
||||
this.fsService = FileSystemService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ".";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescriptiveName() {
|
||||
return SameDirSymbolStore.PROGRAMS_IMPORT_LOCATION_DESCRIPTION_STR + " - " +
|
||||
fsFSRL.toPrettyFullpathString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(TaskMonitor monitor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String filename, TaskMonitor monitor) {
|
||||
try (RefdFile file = getFile(filename, monitor)) {
|
||||
return file != null;
|
||||
}
|
||||
catch (IOException e1) {
|
||||
// fall thru
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private RefdFile getFile(String filename, TaskMonitor monitor) {
|
||||
try (FileSystemRef fsRef = fsService.getFilesystem(fsFSRL, monitor)) {
|
||||
if (fsRef != null) {
|
||||
GFileSystem fs = fsRef.getFilesystem();
|
||||
String path = FSUtilities.appendPath(subdir, filename);
|
||||
GFile file = fs.lookup(path);
|
||||
if (file != null && !file.isDirectory()) {
|
||||
return new RefdFile(fsRef.dup(), file);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | CancelledException e) {
|
||||
// fall thru
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SymbolFileLocation> find(SymbolFileInfo fileInfo, Set<FindOption> findOptions,
|
||||
TaskMonitor monitor) {
|
||||
|
||||
try (RefdFile fref = getFile(fileInfo.getName(), monitor)) {
|
||||
// TODO: need to be able to read info from candidate pdb file using some type of stream
|
||||
if (fref != null) {
|
||||
GFile file = fref.file;
|
||||
GFileSystem fs = file.getFilesystem();
|
||||
try (ByteProvider bp = fs.getByteProvider(file, monitor)) {
|
||||
File tmpPdbFile = fsService.createPlaintextTempFile(bp, "temp_pdb", monitor);
|
||||
File tmpPdbDir =
|
||||
Files.createTempDirectory(tmpPdbFile.getParentFile().toPath(), "temp_pdb")
|
||||
.toFile();
|
||||
File destPdbFile = new File(tmpPdbDir, file.getName()).getCanonicalFile();
|
||||
if (!destPdbFile.getParentFile().equals(tmpPdbDir)) {
|
||||
throw new IOException("Bad filename: " + destPdbFile);
|
||||
}
|
||||
if (!tmpPdbFile.renameTo(destPdbFile)) {
|
||||
throw new IOException(
|
||||
"Unable to move file: " + tmpPdbFile + " to " + destPdbFile);
|
||||
}
|
||||
SymbolFileInfo foundInfo = SymbolFileInfo.fromFile(destPdbFile, monitor);
|
||||
destPdbFile.delete();
|
||||
tmpPdbDir.delete();
|
||||
return List.of(new SymbolFileLocation(file.getName(), this, foundInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | CancelledException e) {
|
||||
// fall thru
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolServerInputStream getFileStream(String filename, TaskMonitor monitor)
|
||||
throws IOException {
|
||||
try (RefdFile fref = getFile(filename, monitor)) {
|
||||
if (fref != null) {
|
||||
GFile file = fref.file;
|
||||
InputStream is = file.getFilesystem().getInputStream(file, monitor);
|
||||
is = new RefdInputStream(fref.fsRef.dup(), is);
|
||||
return new SymbolServerInputStream(is, file.getLength());
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// fall thru
|
||||
}
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileLocation(String filename) {
|
||||
return fsFSRL.withPath(filename).toPrettyFullpathString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ContainerFileSymbolServer: [ fsrl: %s ]".formatted(fsFSRL);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ package pdb.symbolserver;
|
|||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.formats.gfilesystem.FSRL;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +62,23 @@ public class SameDirSymbolStore implements SymbolStore {
|
|||
return symbolFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SymbolServer} for the "Program's Import Location" item. May return either
|
||||
* a {@link SameDirSymbolStore} instance, or a {@link ContainerFileSymbolServer}.
|
||||
*
|
||||
* @param locationString will be "."
|
||||
* @param context {@link SymbolServerInstanceCreatorContext}
|
||||
* @return new {@link SymbolServer}
|
||||
*/
|
||||
public static SymbolServer createInstance(String locationString,
|
||||
SymbolServerInstanceCreatorContext context) {
|
||||
FSRL programFSRL = context.getProgramFSRL();
|
||||
if (programFSRL != null && programFSRL.getNestingDepth() != 1) {
|
||||
return new ContainerFileSymbolServer(programFSRL);
|
||||
}
|
||||
return new SameDirSymbolStore(context.getRootDir());
|
||||
}
|
||||
|
||||
private final File rootDir;
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,11 @@ package pdb.symbolserver;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import ghidra.formats.gfilesystem.FSRL;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* Context for the {@link SymbolServerInstanceCreatorRegistry} when creating new
|
||||
* {@link SymbolServer} instances.
|
||||
|
@ -30,6 +35,7 @@ import java.io.File;
|
|||
*/
|
||||
public class SymbolServerInstanceCreatorContext {
|
||||
private final File rootDir;
|
||||
private final FSRL programFSRL;
|
||||
private final SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry;
|
||||
|
||||
SymbolServerInstanceCreatorContext(
|
||||
|
@ -37,9 +43,16 @@ public class SymbolServerInstanceCreatorContext {
|
|||
this(null, symbolServerInstanceCreatorRegistry);
|
||||
}
|
||||
|
||||
SymbolServerInstanceCreatorContext(File rootDir,
|
||||
SymbolServerInstanceCreatorContext(Program program,
|
||||
SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry) {
|
||||
this.rootDir = rootDir;
|
||||
if (program != null) {
|
||||
this.programFSRL = FSRL.fromProgram(program);
|
||||
this.rootDir = new File(FilenameUtils.getFullPath(program.getExecutablePath()));
|
||||
}
|
||||
else {
|
||||
this.programFSRL = null;
|
||||
this.rootDir = null;
|
||||
}
|
||||
this.symbolServerInstanceCreatorRegistry = symbolServerInstanceCreatorRegistry;
|
||||
}
|
||||
|
||||
|
@ -61,4 +74,13 @@ public class SymbolServerInstanceCreatorContext {
|
|||
return rootDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FSRL of imported binary.
|
||||
*
|
||||
* @return {@link FSRL} of the imported binary, or null if not present
|
||||
*/
|
||||
public FSRL getProgramFSRL() {
|
||||
return programFSRL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,10 @@
|
|||
*/
|
||||
package pdb.symbolserver;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -163,8 +160,7 @@ public class SymbolServerInstanceCreatorRegistry {
|
|||
* @return new {@link SymbolServerInstanceCreatorContext}
|
||||
*/
|
||||
public SymbolServerInstanceCreatorContext getContext(Program program) {
|
||||
File exeLocation = new File(FilenameUtils.getFullPath(program.getExecutablePath()));
|
||||
return new SymbolServerInstanceCreatorContext(exeLocation, this);
|
||||
return new SymbolServerInstanceCreatorContext(program, this);
|
||||
}
|
||||
|
||||
private void registerDefaultSymbolServerInstanceCreators() {
|
||||
|
@ -173,7 +169,7 @@ public class SymbolServerInstanceCreatorRegistry {
|
|||
registerSymbolServerInstanceCreator(100, HttpSymbolServer::isHttpSymbolServerLocation,
|
||||
(loc, context) -> new HttpSymbolServer(URI.create(loc)));
|
||||
registerSymbolServerInstanceCreator(200, SameDirSymbolStore::isSameDirLocation,
|
||||
(loc, context) -> new SameDirSymbolStore(context.getRootDir()));
|
||||
SameDirSymbolStore::createInstance);
|
||||
registerSymbolServerInstanceCreator(300, LocalSymbolStore::isLocalSymbolStoreLocation,
|
||||
(loc, context) -> new LocalSymbolStore(new File(loc)));
|
||||
}
|
||||
|
|
|
@ -787,10 +787,9 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
|||
return null;
|
||||
}
|
||||
SymbolServer symbolServer = symbolFileLocation.getSymbolServer();
|
||||
if (!(symbolServer instanceof SymbolStore)) {
|
||||
if (!(symbolServer instanceof SymbolStore symbolStore)) {
|
||||
return null;
|
||||
}
|
||||
SymbolStore symbolStore = (SymbolStore) symbolServer;
|
||||
File file = symbolStore.getFile(symbolFileLocation.getPath());
|
||||
return SymbolStore.isCompressedFilename(file.getName()) ? null : file;
|
||||
}
|
||||
|
|
|
@ -91,10 +91,9 @@ class SymbolServerPanel extends JPanel {
|
|||
|
||||
SymbolServerService temporarySymbolServerService =
|
||||
PdbPlugin.getSymbolServerService(symbolServerInstanceCreatorContext);
|
||||
if (temporarySymbolServerService.getSymbolStore() instanceof LocalSymbolStore) {
|
||||
setSymbolStorageLocation(
|
||||
((LocalSymbolStore) temporarySymbolServerService.getSymbolStore()).getRootDir(),
|
||||
false);
|
||||
if (temporarySymbolServerService
|
||||
.getSymbolStore() instanceof LocalSymbolStore tempLocalSymbolStore) {
|
||||
setSymbolStorageLocation(tempLocalSymbolStore.getRootDir(), false);
|
||||
}
|
||||
tableModel.addSymbolServers(temporarySymbolServerService.getSymbolServers());
|
||||
setConfigChanged(false);
|
||||
|
@ -368,8 +367,8 @@ class SymbolServerPanel extends JPanel {
|
|||
SymbolServer symbolServer =
|
||||
symbolServerInstanceCreatorContext.getSymbolServerInstanceCreatorRegistry()
|
||||
.newSymbolServer(firstSearchPath, symbolServerInstanceCreatorContext);
|
||||
if (symbolServer instanceof LocalSymbolStore &&
|
||||
((LocalSymbolStore) symbolServer).isValid()) {
|
||||
if (symbolServer instanceof LocalSymbolStore localSymbolStore &&
|
||||
localSymbolStore.isValid()) {
|
||||
int choice = OptionDialog.showYesNoCancelDialog(this, "Set Symbol Storage Location",
|
||||
"Set symbol storage location to " + firstSearchPath + "?");
|
||||
if (choice == OptionDialog.CANCEL_OPTION) {
|
||||
|
@ -378,7 +377,7 @@ class SymbolServerPanel extends JPanel {
|
|||
if (choice == OptionDialog.YES_OPTION) {
|
||||
symbolServerPaths.remove(0);
|
||||
configChanged = true;
|
||||
setSymbolStorageLocation(((LocalSymbolStore) symbolServer).getRootDir(), true);
|
||||
setSymbolStorageLocation(localSymbolStore.getRootDir(), true);
|
||||
symbolStorageLocationTextField.setText(symbolServer.getName());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue