GP-6891 Improved Debugger Trace import/export support and added packed DBTrace GZT file type.

This commit is contained in:
ghidra1
2026-06-10 12:26:44 -04:00
parent 5e22a03899
commit 1ea11b20df
44 changed files with 866 additions and 362 deletions

View File

@@ -37,7 +37,6 @@ import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FileDataTypeManager;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class IsfServer extends Thread {
@@ -102,13 +101,13 @@ public class IsfServer extends Thread {
try {
DataTypeManager dtm;
if (ns.endsWith(".gdt")) {
dtm = openAsArchive(ns);
dtm = openAsDataTypeArchive(ns);
}
else if (ns.endsWith(".gzf")) {
dtm = openAsDatabase(ns);
dtm = openAsProgramDatabase(ns);
}
else {
dtm = openAsDomainFile(ns);
dtm = openAsProgramFile(ns);
}
managers.put(ns, dtm);
return dtm;
@@ -120,43 +119,43 @@ public class IsfServer extends Thread {
}
}
private DataTypeManager openAsDomainFile(String ns) throws Exception {
private DataTypeManager openAsProgramFile(String ns) throws Exception {
ProjectData projectData = project.getProjectData();
DomainFile df = projectData.getFile(ns);
if (!Program.class.isAssignableFrom(df.getDomainObjectClass())) {
throw new IOException("File does not correspond to Program content: " + ns);
}
// FIXME: Need to track and release Program instance after DTM use is complete (GP-6895)
Program program = (Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
return program.getDataTypeManager();
}
private DataTypeManager openAsArchive(String ns) throws Exception {
private DataTypeManager openAsDataTypeArchive(String ns) throws Exception {
File gdt = new File(ns);
return FileDataTypeManager.openFileArchive(gdt, false);
}
private DataTypeManager openAsDatabase(String ns) throws Exception {
private DataTypeManager openAsProgramDatabase(String ns) throws Exception {
File gzf = new File(ns);
TaskMonitor dummy = TaskMonitor.DUMMY;
PackedDatabase db = PackedDatabase.getPackedDatabase(gzf, dummy);
DBHandle dbh = db.openForUpdate(dummy);
ProgramDB p = null;
Program p;
boolean success = false;
try {
p = new ProgramDB(dbh, OpenMode.UPDATE, dummy, this);
}
catch (VersionException e) {
if (!e.isUpgradable()) {
throw new RuntimeException(p + " uses an older version and is not upgradable.");
}
p = new ProgramDB(dbh, OpenMode.UPGRADE, dummy, this);
success = true;
}
finally {
dbh.close();
}
dbh = db.openForUpdate(dummy);
p = new ProgramDB(dbh, OpenMode.UPGRADE, dummy, this);
if (!p.isChanged()) {
throw new RuntimeException(p + " uses an older version and was not upgraded.");
if (!success) {
dbh.close();
}
}
// FIXME: Need to track and release Program instance after DTM use is complete (GP-6895)
return p.getListing().getDataTypeManager();
}

View File

@@ -1,27 +0,0 @@
/* ###
* 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 ghidra.app.plugin.core.debug.export;
import ghidra.app.util.exporter.AsciiExporter;
import ghidra.framework.model.DomainObject;
import ghidra.trace.model.Trace;
public class TraceViewAsciiExporter extends AsciiExporter {
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return Trace.class.isAssignableFrom(domainObjectClass);
}
}

View File

@@ -1,27 +0,0 @@
/* ###
* 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 ghidra.app.plugin.core.debug.export;
import ghidra.app.util.exporter.BinaryExporter;
import ghidra.framework.model.DomainObject;
import ghidra.trace.model.Trace;
public class TraceViewBinaryExporter extends BinaryExporter {
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return Trace.class.isAssignableFrom(domainObjectClass);
}
}

View File

@@ -1,27 +0,0 @@
/* ###
* 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 ghidra.app.plugin.core.debug.export;
import ghidra.app.util.exporter.HtmlExporter;
import ghidra.framework.model.DomainObject;
import ghidra.trace.model.Trace;
public class TraceViewHtmlExporter extends HtmlExporter {
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return Trace.class.isAssignableFrom(domainObjectClass);
}
}

View File

@@ -1,27 +0,0 @@
/* ###
* 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 ghidra.app.plugin.core.debug.export;
import ghidra.app.util.exporter.IntelHexExporter;
import ghidra.framework.model.DomainObject;
import ghidra.trace.model.Trace;
public class TraceViewIntelHexExporter extends IntelHexExporter {
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return Trace.class.isAssignableFrom(domainObjectClass);
}
}

View File

@@ -1,56 +0,0 @@
/* ###
* 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 ghidra.app.plugin.core.debug.export;
import java.util.*;
import java.util.stream.Collectors;
import ghidra.app.util.*;
import ghidra.app.util.exporter.XmlExporter;
import ghidra.framework.model.DomainObject;
import ghidra.trace.model.Trace;
// TODO: perhaps getApplicableExporters should use domainObject's class, not file's object class.
// TODO: Where un-supported, be less abrasive, e.g., present empty managers.
public class TraceViewXmlExporter extends XmlExporter {
private final Map<String, Object> hideOpts = Map.of(
"Properties", false,
"Relocation Table", false,
"External Libraries", false);
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return Trace.class.isAssignableFrom(domainObjectClass);
}
@Override
public List<Option> getOptions(DomainObjectService domainObjectService) {
List<Option> options = super.getOptions(domainObjectService);
return options.stream()
.filter(o -> !hideOpts.keySet().contains(o.getName()))
.collect(Collectors.toList());
}
@Override
public void setOptions(List<Option> options) throws OptionException {
List<Option> opts = new ArrayList<>(options);
options.stream().filter(o -> !hideOpts.keySet().contains(o.getName())).forEach(opts::add);
for (Map.Entry<String, Object> ent : hideOpts.entrySet()) {
opts.add(new Option(ent.getKey(), ent.getValue()));
}
super.setOptions(opts);
}
}

View File

@@ -0,0 +1,197 @@
/* ###
* 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 ghidra.app.plugin.core.debug.gui.export;
import java.io.File;
import java.util.Map;
import docking.ActionContext;
import docking.action.builder.ActionBuilder;
import docking.tool.ToolConstants;
import docking.widgets.OptionDialog;
import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.filechooser.GhidraFileChooserMode;
import ghidra.app.context.ProgramActionContext;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.utils.GztExporter;
import ghidra.app.plugin.core.help.AboutDomainObjectUtils;
import ghidra.app.services.CodeViewerService;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.framework.preferences.Preferences;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.Trace;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.util.Swing;
import ghidra.util.filechooser.ExtensionFileFilter;
import ghidra.util.filechooser.GhidraFileFilter;
import ghidra.util.task.TaskLauncher;
//@formatter:off
@PluginInfo(
status = PluginStatus.RELEASED,
category = PluginCategoryNames.DEBUGGER,
packageName = DebuggerPluginPackage.NAME,
shortDescription = "Export Debugger Trace",
description = "This plugin exports a Debugger Trace to an external file.",
servicesRequired = {
DebuggerTraceManagerService.class
}
)
//@formatter:on
public class TraceExportPlugin extends Plugin {
private DebuggerTraceManagerService traceMgrSvc;
public TraceExportPlugin(PluginTool tool) {
super(tool);
createToolAction();
}
@Override
protected void init() {
traceMgrSvc = tool.getService(DebuggerTraceManagerService.class);
}
private void createToolAction() {
new ActionBuilder("Export Trace", getName())
.description("Export Debbuger Trace as compressed GZT file.")
// .helpLocation(new HelpLocation("ExporterPlugin", "Export"))
.menuPath(ToolConstants.MENU_FILE, "Export Trace...")
.menuGroup("DomainObjectSaveExport")
.enabledWhen(c -> getTrace(c) != null)
.onAction(c -> exportTrace(c))
.buildAndInstall(tool);
}
private Trace getTrace(ActionContext ctx) {
if (ctx instanceof ProgramActionContext programCtx) {
Program p = programCtx.getProgram();
if (p instanceof TraceProgramView traceProgrmView) {
return traceProgrmView.getTrace();
}
}
return traceMgrSvc.getCurrentTrace();
}
private void exportTrace(ActionContext ctx) {
Trace trace = getTrace(ctx);
if (trace == null) {
return;
}
File file = chooseDestinationFile(ctx);
if (file == null) {
return; // file chooser cancelled
}
File gztFile = file;
GztExporter exporter = new GztExporter();
TaskLauncher.launchModal("Export Trace", m -> {
exporter.export(gztFile, trace, null, m);
});
displaySummaryResults(trace, gztFile, exporter.getMessageLog());
}
private File chooseDestinationFile(ActionContext ctx) {
GhidraFileChooser chooser = new GhidraFileChooser(ctx.getSourceComponent());
chooser.setCurrentDirectory(getLastExportDirectory());
chooser.setTitle("Select Trace Output File");
chooser.setApproveButtonText("Export Trace");
chooser.setApproveButtonToolTipText("Export Debugger Trace");
chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
chooser.setSelectedFileFilter(GhidraFileFilter.ALL);
chooser.setFileFilter(
new ExtensionFileFilter(GztExporter.EXTENSION, GztExporter.NAME));
File file;
while (true) {
file = chooser.getSelectedFile();
if (file == null) {
break;
}
setLastExportDirectory(file);
if (!file.getName().endsWith(GztExporter.SUFFIX)) {
file = new File(file.getParent(), file.getName() + GztExporter.SUFFIX);
}
if (!file.exists()) {
break; // continue with file return
}
if (!file.isFile()) {
chooser.setStatusText("Invalid File Selection");
continue;
}
int rc = OptionDialog.showYesNoCancelDialog(chooser.getComponent(),
"Overwrite Confirmation",
"Overwrite Trace export file?\n" + file);
if (rc == OptionDialog.YES_OPTION) {
break; // continue with file return
}
file = null; // don't overwrite
if (rc != OptionDialog.NO_OPTION) {
break; // continue with null return / export cancelled
}
}
chooser.dispose();
return file;
}
private File getLastExportDirectory() {
String lastDirStr = Preferences.getProperty(Preferences.LAST_EXPORT_DIRECTORY,
System.getProperty("user.home"), true);
return new File(lastDirStr);
}
private void setLastExportDirectory(File file) {
Preferences.setProperty(Preferences.LAST_EXPORT_DIRECTORY, file.getParent());
Preferences.store();
}
protected ProgramSelection getSelection() {
CodeViewerService service = tool.getService(CodeViewerService.class);
if (service != null) {
return service.getCurrentSelection();
}
return null;
}
private void displaySummaryResults(Trace trace, File outputFile, MessageLog log) {
StringBuffer resultsBuffer = new StringBuffer();
resultsBuffer.append("Destination file: " + outputFile.getAbsolutePath() + "\n\n");
resultsBuffer.append("Destination file Size: " + outputFile.length() + "\n");
resultsBuffer.append("Format: " + GztExporter.NAME + "\n\n");
resultsBuffer.append(log.toString());
Map<String, String> metadata = trace.getMetadata();
Swing.runLater(() -> {
AboutDomainObjectUtils.displayInformation(tool, trace.getDomainFile(), metadata,
"Trace Export Results Summary", resultsBuffer.toString(), null);
});
}
}

View File

@@ -555,7 +555,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
protected void contextChanged() {
Trace trace = current.getTrace();
String itemName = trace == null ? "..." : trace.getName();
String itemName = trace == null ? "..." : trace.getDomainFile().getName();
actionCloseTrace.getMenuBarData().setMenuItemName(CloseTraceAction.NAME_PREFIX + itemName);
actionSaveTrace.getMenuBarData().setMenuItemName(SaveTraceAction.NAME_PREFIX + itemName);
tool.contextChanged(null);
@@ -939,7 +939,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
@Override
public void run(TaskMonitor monitor) throws CancelledException {
String filename = trace.getName();
String filename = trace.getDomainFile().getName();
try (DomainObjectLockHold hold = maybeLock(trace, force)) {
for (int i = 1;; i++) {
try {
@@ -947,7 +947,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
break;
}
catch (DuplicateFileException e) {
filename = trace.getName() + "." + i;
filename = trace.getDomainFile().getName() + "." + i;
}
}
trace.save("Initial save", monitor);

View File

@@ -0,0 +1,122 @@
/* ###
* 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 ghidra.app.plugin.core.debug.utils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import ghidra.app.util.DomainObjectService;
import ghidra.app.util.Option;
import ghidra.app.util.exporter.Exporter;
import ghidra.app.util.exporter.ExporterException;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainObject;
import ghidra.program.model.address.AddressSetView;
import ghidra.trace.database.DBTrace;
import ghidra.util.HelpLocation;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class GztExporter extends Exporter {
public static final String EXTENSION = "gzt";
public static final String SUFFIX = "." + EXTENSION;
public static final String NAME = "Ghidra Trace Zip File";
public GztExporter() {
super(NAME, EXTENSION, new HelpLocation("ExporterPlugin", "gzt"));
}
@Override
public boolean canExportDomainFile(DomainFile domainFile) {
// Avoid exporting link-files or non-Trace files
return !domainFile.isLink() && canExportDomainObject(domainFile.getDomainObjectClass());
}
@Override
public boolean canExportDomainObject(Class<? extends DomainObject> domainObjectClass) {
return DBTrace.class.isAssignableFrom(domainObjectClass);
}
@Override
public boolean equals(Object obj) {
return (obj instanceof GztExporter);
}
@Override
public boolean export(File file, DomainObject domainObj, AddressSetView addrSet,
TaskMonitor monitor) {
if (!canExportDomainObject(domainObj.getClass())) {
throw new UnsupportedOperationException("only DBTrace objects are supported");
}
try {
file.delete();
domainObj.saveToPackedFile(file, monitor);
}
catch (UnsupportedOperationException e) {
log.appendMsg("Content does not support packed file export!");
log.appendException(e);
return false;
}
catch (CancelledException ce) {
return false;
}
catch (Exception e) {
log.appendMsg("Unexpected exception exporting file: " + e.getMessage());
return false;
}
return true;
}
@Override
public boolean export(File file, DomainFile domainFile, TaskMonitor monitor)
throws ExporterException, IOException {
if (!canExportDomainFile(domainFile)) {
throw new UnsupportedOperationException("only DBTrace files are supported");
}
try {
domainFile.packFile(file, monitor);
}
catch (CancelledException e) {
return false;
}
catch (Exception e) {
log.appendMsg("Unexpected exception exporting file: " + e.getMessage());
return false;
}
return true;
}
@Override
public List<Option> getOptions(DomainObjectService domainObjectService) {
return EMPTY_OPTIONS;
}
@Override
public void setOptions(List<Option> options) {
// no options for this exporter
}
/**
* Returns false. GZT export only supports entire database.
*/
@Override
public boolean supportsAddressRestrictedExport() {
return false;
}
}

View File

@@ -0,0 +1,177 @@
/* ###
* 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 ghidra.app.plugin.core.debug.utils;
import java.io.*;
import java.util.*;
import org.apache.commons.io.FilenameUtils;
import db.DBHandle;
import ghidra.app.util.Option;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.opinion.*;
import ghidra.framework.Application;
import ghidra.framework.data.OpenMode;
import ghidra.framework.model.DomainObject;
import ghidra.framework.store.db.PackedDatabase;
import ghidra.framework.store.local.ItemSerializer;
import ghidra.program.model.lang.LanguageNotFoundException;
import ghidra.program.model.listing.Program;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceContentHandler;
import ghidra.trace.model.Trace;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
import utilities.util.FileUtilities;
/**
* Loads a packed Ghidra Trace file.
*/
public class GztLoader implements Loader {
public final static String GZT_NAME = "GZT Input Format";
@Override
public LoaderTier getTier() {
return LoaderTier.SPECIALIZED_TARGET_LOADER;
}
@Override
public int getTierPriority() {
return 0;
}
@Override
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
Program program) {
if (options != null && options.size() > 0) {
return "GztLoader takes no options";
}
return null;
}
@Override
public List<Option> getDefaultOptions(ByteProvider provider, LoadSpec loadSpec,
DomainObject domainObject, boolean loadIntoProgram, boolean mirrorFsLayout) {
return List.of();
}
@Override
public LoadResults<? extends DomainObject> load(ImporterSettings settings)
throws IOException, CancelledException, VersionException {
Trace trace = loadPackedTraceDatabase(settings.provider(), settings.importName(),
settings.consumer(), settings.monitor());
return new LoadResults<>(new Loaded<>(trace, settings));
}
private Trace loadPackedTraceDatabase(ByteProvider provider, String traceName,
Object consumer, TaskMonitor monitor)
throws IOException, CancelledException, VersionException, LanguageNotFoundException {
Trace trace;
File file = provider.getFile();
File tmpFile = null;
if (file == null) {
file = tmpFile = createTmpFile(provider, monitor);
}
try {
PackedDatabase packedDatabase = PackedDatabase.getPackedDatabase(file, true, monitor);
boolean success = false;
DBHandle dbh = null;
try {
if (!DBTraceContentHandler.TRACE_CONTENT_TYPE
.equals(packedDatabase.getContentType())) {
throw new IOException("File imported is not a Trace: " + traceName);
}
monitor.setMessage("Restoring " + provider.getName());
dbh = packedDatabase.open(monitor);
trace = new DBTrace(dbh, OpenMode.UPGRADE, monitor, consumer);
success = true;
}
finally {
if (!success) {
if (dbh != null) {
dbh.close(); // also disposes packed database object
}
else {
packedDatabase.dispose();
}
}
}
return trace;
}
finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
}
@Override
public void loadInto(Program program, ImporterSettings settings)
throws IOException, LoadException, CancelledException {
throw new LoadException("Cannot add GZT to program");
}
@Override
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
List<LoadSpec> loadSpecs = new ArrayList<>();
if (isGztFile(provider)) {
loadSpecs.add(new LoadSpec(this, 0, false));
}
return loadSpecs;
}
@Override
public String getPreferredFileName(ByteProvider provider) {
return FilenameUtils.removeExtension(provider.getName());
}
private static File createTmpFile(ByteProvider provider, TaskMonitor monitor)
throws IOException {
File tmpFile = Application.createTempFile("ghidra_gzt_loader", null);
try (InputStream is = provider.getInputStream(0);
FileOutputStream fos = new FileOutputStream(tmpFile)) {
FileUtilities.copyStreamToStream(is, fos, monitor);
}
return tmpFile;
}
private static boolean isGztFile(ByteProvider provider) {
if (!provider.getName().toLowerCase().endsWith(".gzt")) {
return false;
}
boolean isGZT = false;
try (InputStream inputStream = provider.getInputStream(0)) {
isGZT = ItemSerializer.isPackedFile(inputStream);
}
catch (IOException e) {
// ignore
}
return isGZT;
}
@Override
public String getName() {
return GZT_NAME;
}
}

View File

@@ -814,7 +814,7 @@ public abstract class AbstractGhidraHeadedDebuggerTest
protected File pack(DomainObject object) throws Exception {
File tempDir = Files.createTempDirectory("ghidra-" + name.getMethodName()).toFile();
File pack = new File(tempDir, "obj" + System.identityHashCode(object) + ".gzf");
File pack = new File(tempDir, "obj" + System.identityHashCode(object) + ".gzt");
object.saveToPackedFile(pack, monitor);
return pack;
}

View File

@@ -236,9 +236,9 @@ public class ToyDBTraceBuilder implements AutoCloseable {
}
/**
* Open a .gzf compressed trace
* Open a .gzt packed trace
*
* @param file the .gzf file containing the trace
* @param file the .gzt file containing the trace
* @throws CancelledException never, since the monitor cannot be cancelled
* @throws VersionException if the trace's version is not as expected
* @throws LanguageNotFoundException if the trace's language cannot be found
@@ -936,7 +936,7 @@ public class ToyDBTraceBuilder implements AutoCloseable {
}
/**
* Save the trace to a temporary .gzf file
* Save the trace to a temporary packed .gzt file
*
* @return the new file
* @throws IOException if the trace could not be saved