diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProvider.java index c1fe10fcc3..6421a9bca1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProvider.java @@ -125,6 +125,9 @@ public class MemoryByteProvider implements ByteProvider { } return bytes; } + catch (IOException e) { + throw e; + } catch (Exception e) { throw new IOException(e.getMessage()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java index 5a05e9bbf7..a7b3ed51d8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java @@ -226,7 +226,7 @@ public class FileSystemService { * @return true if local, false if the path points to an embedded file in a container. */ public boolean isLocal(FSRL fsrl) { - return fsrl.getFS().hasContainer() == false; + return localFS.isSameFS(fsrl); } /** @@ -519,6 +519,25 @@ public class FileSystemService { return fileCache.createCacheEntryBuilder(sizeHint); } + /** + * Returns a {@link ByteProvider} for the specified {@link FileCacheEntry}, using the + * specified filename. + *

+ * The returned ByteProvider's FSRL will be decorative and does not allow returning to + * the same ByteProvider at a later time. + * + * @param tempFileCacheEntry {@link FileCacheEntry} (returned by {@link #createTempFile(long)}) + * @param name desired name + * @return new {@link ByteProvider} with decorative {@link FSRL} + * @throws IOException if io error + */ + public ByteProvider getNamedTempFile(FileCacheEntry tempFileCacheEntry, String name) + throws IOException { + FSRL resultFSRL = FSRLRoot.makeRoot("tmp") + .withPathMD5(FSUtilities.appendPath("/", name), tempFileCacheEntry.getMD5()); + return tempFileCacheEntry.asByteProvider(resultFSRL); + } + /** * Allows the resources used by caching the specified file to be released. * diff --git a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/LocalFileSystem.java b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/LocalFileSystem.java index 313f407ec7..253e4f3e0c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/LocalFileSystem.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/LocalFileSystem.java @@ -65,7 +65,7 @@ public class LocalFileSystem implements GFileSystem, GFileHashProvider { this.fsFSRL = fsrl; } - private boolean isSameFS(FSRL fsrl) { + boolean isSameFS(FSRL fsrl) { return fsFSRL.equals(fsrl.getFS()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java index a5b5c70c22..071babbb16 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java @@ -17,7 +17,8 @@ package ghidra.plugin.importer; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.util.*; import docking.ActionContext; @@ -29,8 +30,13 @@ import ghidra.app.context.ListingActionContext; import ghidra.app.events.ProgramActivatedPluginEvent; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.services.*; +import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.importer.LibrarySearchPathManager; +import ghidra.app.util.opinion.LoaderMap; +import ghidra.app.util.opinion.LoaderService; import ghidra.formats.gfilesystem.FSRL; +import ghidra.formats.gfilesystem.FileCache.FileCacheEntry; +import ghidra.formats.gfilesystem.FileCache.FileCacheEntryBuilder; import ghidra.formats.gfilesystem.FileSystemService; import ghidra.framework.main.*; import ghidra.framework.main.datatree.DomainFolderNode; @@ -385,20 +391,30 @@ public class ImporterPlugin extends Plugin return; } - Memory memory = program.getMemory(); - MemoryBlock block = memory.getBlock(range.getMinAddress()); - String tempFileName = - block.getName() + "_[" + range.getMinAddress() + "," + range.getMaxAddress() + "]_"; try { - File tempFile = File.createTempFile(tempFileName, ".tmp"); - try (OutputStream outputStream = new FileOutputStream(tempFile)) { + Memory memory = program.getMemory(); + FileSystemService fsService = FileSystemService.getInstance(); + + // create a tmp ByteProvider that contains the bytes from the selected region + FileCacheEntry tmpFile; + try (FileCacheEntryBuilder tmpFileBuilder = + fsService.createTempFile(range.getLength())) { byte[] bytes = new byte[(int) range.getLength()]; memory.getBytes(range.getMinAddress(), bytes); - outputStream.write(bytes); + tmpFileBuilder.write(bytes); + tmpFile = tmpFileBuilder.finish(); } - DomainFolder folder = AppInfo.getActiveProject().getProjectData().getRootFolder(); - importFile(folder, tempFile); + MemoryBlock block = memory.getBlock(range.getMinAddress()); + String rangeName = + block.getName() + "[" + range.getMinAddress() + "," + range.getMaxAddress() + "]"; + ByteProvider bp = + fsService.getNamedTempFile(tmpFile, program.getName() + " " + rangeName); + LoaderMap loaderMap = LoaderService.getAllSupportedLoadSpecs(bp); + + ImporterDialog importerDialog = + new ImporterDialog(tool, programManager, loaderMap, bp, null); + tool.showDialog(importerDialog); } catch (IOException e) { Msg.showError(this, null, "I/O Error Occurred", e.getMessage(), e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java index 65bcee3784..31a28ac370 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java @@ -462,9 +462,9 @@ public interface Memory extends AddressSetView { * @param destIndex the offset into dest to place the bytes. * @param size the number of bytes to get. * @return the number of bytes put into dest. May be less than - * size if the requested number extends beyond available memory. + * size if the requested number extends beyond initialized / available memory. * @throws MemoryAccessException if the starting address is - * not contained in any memory block. + * not contained in any memory block or is an uninitialized location. */ public int getBytes(Address addr, byte[] dest, int destIndex, int size) throws MemoryAccessException;