From 079241797945cc2965886a2cbce7be449e7bda2c Mon Sep 17 00:00:00 2001 From: ghidravore Date: Mon, 6 May 2019 12:44:51 -0400 Subject: [PATCH] GT-2845: Storing original program bytes in the program database. --- .../topics/MemoryMapPlugin/Memory_Map.htm | 21 +- .../MemoryMapPlugin/images/AddMappedBlock.png | Bin 14943 -> 18719 bytes .../MemoryMapPlugin/images/AddMemoryBlock.png | Bin 15664 -> 19470 bytes .../MemoryMapPlugin/images/MemoryMap.png | Bin 24313 -> 28090 bytes .../images/SplitMemoryBlock.png | Bin 14859 -> 16885 bytes .../cmd/memory/AbstractAddMemoryBlockCmd.java | 135 +++ .../memory/AddBitMappedMemoryBlockCmd.java | 57 ++ .../memory/AddByteMappedMemoryBlockCmd.java | 57 ++ .../memory/AddFileBytesMemoryBlockCmd.java | 65 ++ .../memory/AddInitializedMemoryBlockCmd.java | 63 ++ .../app/cmd/memory/AddMemoryBlockCmd.java | 174 ---- .../AddUninitializedMemoryBlockCmd.java | 58 ++ .../plugin/core/memory/AddBlockDialog.java | 514 ++++++----- .../app/plugin/core/memory/AddBlockModel.java | 292 ++++-- .../plugin/core/memory/MemoryMapModel.java | 66 +- .../java/ghidra/app/util/MemoryBlockUtil.java | 23 +- .../ghidra/app/util/MemoryBlockUtils.java | 263 ++++++ .../ghidra/app/util/opinion/BinaryLoader.java | 45 +- .../app/util/opinion/ElfProgramBuilder.java | 5 +- .../ghidra/app/util/xml/MemoryMapXmlMgr.java | 9 +- .../plugin/core/memory/AddBlockModelTest.java | 39 +- .../core/memory/MemoryMapPluginTest.java | 18 +- .../core/memory/MemoryMapProvider1Test.java | 24 +- .../core/memory/MemoryMapProvider2Test.java | 44 +- .../database/map/AddressMapDB64BitTest.java | 100 +- .../database/mem/InitializedMemoryBlock.java | 424 --------- .../database/mem/MemoryManagerTest.java | 60 +- .../app/cmd/memory/AddMemoryBlockCmdTest.java | 32 +- .../plugin/core/checksums/MyTestMemory.java | 37 +- .../core/checksums/MyTestMemoryBlock.java | 12 + .../ghidra/feature/vt/db/MemoryTestDummy.java | 52 +- .../DB/src/main/java/db/DBBuffer.java | 4 +- .../DB/src/main/java/db/DBHandle.java | 86 +- .../data/DomainObjectChangeSupport.java | 4 +- .../app/emulator/memory/ProgramLoadImage.java | 20 +- .../emulator/memory/ProgramMappedMemory.java | 22 +- .../program/database/map/AddressMapDB.java | 48 +- .../mem/BitMappedByteSourceRange.java | 49 + .../database/mem/BitMappedSubMemoryBlock.java | 228 +++++ .../database/mem/BufferSubMemoryBlock.java | 129 +++ .../mem/ByteMappedSubMemoryBlock.java | 204 +++++ .../program/database/mem/ByteSourceRange.java | 126 +++ .../database/mem/ByteSourceRangeList.java | 220 +++++ .../program/database/mem/FileBytes.java | 362 ++++++++ .../database/mem/FileBytesAdapter.java | 125 +++ .../database/mem/FileBytesAdapterNoTable.java | 59 ++ .../database/mem/FileBytesAdapterV0.java | 165 ++++ .../database/mem/FileBytesSubMemoryBlock.java | 140 +++ .../program/database/mem/MemoryBlockDB.java | 799 ++++++++-------- .../database/mem/MemoryBlockInputStream.java | 21 +- .../program/database/mem/MemoryMapDB.java | 566 ++++++++---- .../database/mem/MemoryMapDBAdapter.java | 205 +++-- .../database/mem/MemoryMapDBAdapterV0.java | 194 ++-- .../database/mem/MemoryMapDBAdapterV1.java | 7 +- .../database/mem/MemoryMapDBAdapterV2.java | 368 ++++---- .../database/mem/MemoryMapDBAdapterV3.java | 447 +++++++++ .../database/mem/OverlayMemoryBlockDB.java | 261 ------ .../program/database/mem/SourceInfo.java | 117 +++ .../program/database/mem/SubMemoryBlock.java | 251 +++++ .../mem/UninitializedSubMemoryBlock.java | 106 +++ .../model/address/AddressRangeImpl.java | 2 +- .../program/model/mem/MappedMemoryBlock.java | 36 - .../java/ghidra/program/model/mem/Memory.java | 89 +- .../ghidra/program/model/mem/MemoryBlock.java | 23 +- .../program/model/mem/MemoryBlockStub.java | 16 +- .../ghidra/program/model/mem/MemoryStub.java | 25 + .../program/model/symbol/RefTypeFactory.java | 41 +- .../database/mem/ByteSourceRangeListTest.java | 194 ++++ .../database/mem/ByteSourceRangeTest.java | 119 +++ .../program/database/mem/FileBytesTest.java | 249 +++++ .../program/database/mem/MemBlockDBTest.java | 857 ++++++++++++++++++ .../screenshot/NavigationScreenShots.java | 30 +- certification.local.manifest | 1 + 73 files changed, 7129 insertions(+), 2575 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddBitMappedMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddByteMappedMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddFileBytesMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddInitializedMemoryBlockCmd.java delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddUninitializedMemoryBlockCmd.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtils.java delete mode 100644 Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/InitializedMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/BitMappedByteSourceRange.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/BitMappedSubMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/BufferSubMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/ByteMappedSubMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/ByteSourceRange.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/ByteSourceRangeList.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytes.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesAdapter.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesAdapterNoTable.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesAdapterV0.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesSubMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java delete mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/OverlayMemoryBlockDB.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SourceInfo.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SubMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/UninitializedSubMemoryBlock.java delete mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MappedMemoryBlock.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/ByteSourceRangeListTest.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/ByteSourceRangeTest.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/FileBytesTest.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/MemBlockDBTest.java diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm index 57e9d68bfa..548206be92 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm @@ -99,6 +99,13 @@

Initialized - Indicates whether the block has been initialized with values; this property applies to Default and Overlay blocks.

+ +

Byte Source - Provides information about the source of the bytes in this + block. If the bytes were originally imported from a file, then this will indicate which file + and the offset into that file. If the bytes are mapped to another region of memory, it will + provide the address for the mapping. Blocks may consist of regions that have different + sources. In that case, source information about the first several regions will be d + displayed.

Source - The name of the file that produced the bytes that make up this block as set by the file importer; for Bit Mapped or

  • Default  - A normal memory block within the processor's address space.  These blocks cannot overlap any other default block.  Default blocks - can be either initialized or uninitialized. If you select Initialized you can - enter a byte value that will be used to fill all the bytes in the new memory - block.
  • - + can be one of the following types: +
  • Overlay - An overlay block is used to give an alternative set of bytes (and related information) for a range in memory.  This is achieved by creating a new address space related to the actual processor address space and placing diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png index 4272b752fa94ed38ee13629a8d168a5ba62a8c2c..e8fa300a2226b5f7aeff827f7549eaacb272d834 100644 GIT binary patch literal 18719 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 diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png index d615a569cffc3dcf81f9f46b80dbefea7c46d646..94073d9ac88a8e7821497b51eda0945c63d3632c 100644 GIT binary patch literal 19470 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 Pf4z}ZkSG+>_x`^C30BM& literal 15664 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 diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png index 06218d1ee58e99099f3f9b08d9beac8daae7ed5a..9346e1cc339339bebaae9d97f8abca7aa88fec04 100644 GIT binary patch literal 28090 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 Wz1v^e1HaAz;f0i?y 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 PCxU{kicFQ1ap3;~GPxl; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java new file mode 100644 index 0000000000..4ddaf1a515 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java @@ -0,0 +1,135 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.cmd.Command; +import ghidra.framework.model.DomainObject; +import ghidra.framework.store.LockException; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.listing.*; +import ghidra.program.model.mem.*; +import ghidra.util.Msg; +import ghidra.util.exception.*; + +/** + * Base command class for adding memory blocks. + */ +abstract class AbstractAddMemoryBlockCmd implements Command { + protected String message; + protected final String name; + protected final String comment; + protected final String source; + protected final Address start; + protected final long length; + + protected final boolean read; + protected final boolean write; + protected final boolean execute; + protected final boolean isVolatile; + + AbstractAddMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile) { + this.name = name; + this.comment = comment; + this.source = source; + this.start = start; + this.length = length; + this.read = read; + this.write = write; + this.execute = execute; + this.isVolatile = isVolatile; + } + + @Override + public String getStatusMsg() { + return message; + } + + @Override + public String getName() { + return "Add Memory Block"; + } + + protected abstract MemoryBlock createMemoryBlock(Memory memory) + throws LockException, MemoryConflictException, AddressOverflowException, + DuplicateNameException, CancelledException; + + @Override + public boolean applyTo(DomainObject obj) { + Program program = (Program) obj; + try { + Memory memory = program.getMemory(); + MemoryBlock block = createMemoryBlock(memory); + block.setComment(comment); + block.setRead(read); + block.setWrite(write); + block.setExecute(execute); + block.setVolatile(isVolatile); + block.setSourceName(source); + renameFragment(program, block.getStart()); + return true; + } + catch (IllegalArgumentException e) { + message = e.getMessage(); + } + catch (AddressOverflowException e) { + message = e.getMessage(); + } + catch (MemoryConflictException e) { + message = e.getMessage(); + } + catch (DuplicateNameException e) { + message = "Duplicate Name: " + e.getMessage(); + } + catch (IllegalStateException e) { + message = e.getMessage(); + } + catch (Throwable t) { + message = "Create block failed"; + Msg.showError(this, null, "Create Block Failed", t.getMessage(), t); + } + throw new RollbackException(message); + } + + private void renameFragment(Program program, Address blockStartAddr) { + Listing listing = program.getListing(); + String[] treeNames = listing.getTreeNames(); + for (String treeName : treeNames) { + ProgramFragment frag = listing.getFragment(treeName, blockStartAddr); + renameFragment(frag, name); + } + } + + private void renameFragment(ProgramFragment fragment, String fragmentName) { + String newName = fragmentName; + int count = 1; + while (!doRenameFragment(fragment, newName)) { + newName = fragmentName + "_" + count; + count++; + } + } + + private boolean doRenameFragment(ProgramFragment fragment, String fragmentName) { + try { + fragment.setName(fragmentName); + return true; + } + catch (DuplicateNameException e) { + return false; + } + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddBitMappedMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddBitMappedMemoryBlockCmd.java new file mode 100644 index 0000000000..9c00677354 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddBitMappedMemoryBlockCmd.java @@ -0,0 +1,57 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.store.LockException; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.*; + +/** + * Command for adding Bit-mapped memory blocks + */ +public class AddBitMappedMemoryBlockCmd extends AbstractAddMemoryBlockCmd { + + private final Address mappedAddress; + + /** + * Create a new AddBitMappedMemoryBlockCmd + * @param name the name for the new memory block. + * @param comment the comment for the block + * @param source indicates what is creating the block + * @param start the start address for the the block + * @param length the length of the new block + * @param read sets the block's read permission flag + * @param write sets the block's write permission flag + * @param execute sets the block's execute permission flag + * @param isVolatile sets the block's volatile flag + * @param mappedAddress the address in memory that will serve as the bytes source for the block + */ + public AddBitMappedMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile, + Address mappedAddress) { + super(name, comment, source, start, length, read, write, execute, isVolatile); + this.mappedAddress = mappedAddress; + + } + + @Override + protected MemoryBlock createMemoryBlock(Memory memory) + throws LockException, MemoryConflictException, AddressOverflowException { + return memory.createBitMappedBlock(name, start, mappedAddress, length); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddByteMappedMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddByteMappedMemoryBlockCmd.java new file mode 100644 index 0000000000..8ebfd7ac39 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddByteMappedMemoryBlockCmd.java @@ -0,0 +1,57 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.store.LockException; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.*; + +/** + * Command for adding byte-mapped memory blocks + */ +public class AddByteMappedMemoryBlockCmd extends AbstractAddMemoryBlockCmd { + + private final Address mappedAddress; + + /** + * Create a new AddByteMappedMemoryBlockCmd + * @param name the name for the new memory block. + * @param comment the comment for the block + * @param source indicates what is creating the block + * @param start the start address for the the block + * @param length the length of the new block + * @param read sets the block's read permission flag + * @param write sets the block's write permission flag + * @param execute sets the block's execute permission flag + * @param isVolatile sets the block's volatile flag + * @param mappedAddress the address in memory that will serve as the bytes source for the block + */ + public AddByteMappedMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile, + Address mappedAddress) { + super(name, comment, source, start, length, read, write, execute, isVolatile); + this.mappedAddress = mappedAddress; + + } + + @Override + protected MemoryBlock createMemoryBlock(Memory memory) + throws LockException, MemoryConflictException, AddressOverflowException { + return memory.createByteMappedBlock(name, start, mappedAddress, length); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddFileBytesMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddFileBytesMemoryBlockCmd.java new file mode 100644 index 0000000000..c4b9ff1542 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddFileBytesMemoryBlockCmd.java @@ -0,0 +1,65 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.store.LockException; +import ghidra.program.database.mem.FileBytes; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.*; +import ghidra.util.exception.DuplicateNameException; + +/** + * Command for adding a new memory block using bytes from an imported {@link FileBytes} object. + */ +public class AddFileBytesMemoryBlockCmd extends AbstractAddMemoryBlockCmd { + + private final FileBytes fileBytes; + private final long offset; + private final boolean isOverlay; + + /** + * Create a new AddFileBytesMemoryBlockCmd + * @param name the name for the new memory block. + * @param comment the comment for the block + * @param source indicates what is creating the block + * @param start the start address for the the block + * @param length the length of the new block + * @param read sets the block's read permission flag + * @param write sets the block's write permission flag + * @param execute sets the block's execute permission flag + * @param isVolatile sets the block's volatile flag + * @param fileBytes the {@link FileBytes} object that provides the byte source for this block. + * @param offset the offset into the {@link FileBytes} object for the first byte in this block. + * @param isOverlay if true, the block will be created in a new overlay address space. + */ + public AddFileBytesMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile, + FileBytes fileBytes, long offset, boolean isOverlay) { + super(name, comment, source, start, length, read, write, execute, isVolatile); + this.fileBytes = fileBytes; + this.offset = offset; + this.isOverlay = isOverlay; + } + + @Override + protected MemoryBlock createMemoryBlock(Memory memory) throws LockException, + MemoryConflictException, AddressOverflowException, DuplicateNameException { + + return memory.createInitializedBlock(name, start, fileBytes, offset, length, isOverlay); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddInitializedMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddInitializedMemoryBlockCmd.java new file mode 100644 index 0000000000..050aa5bbe5 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddInitializedMemoryBlockCmd.java @@ -0,0 +1,63 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.store.LockException; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.*; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.DuplicateNameException; + +/** + * Command for adding a new memory block initialized with a specific byte. + */ +public class AddInitializedMemoryBlockCmd extends AbstractAddMemoryBlockCmd { + + private final byte initialValue; + private final boolean isOverlay; + + /** + * Create a new AddFileBytesMemoryBlockCmd + * @param name the name for the new memory block. + * @param comment the comment for the block + * @param source indicates what is creating the block + * @param start the start address for the the block + * @param length the length of the new block + * @param read sets the block's read permission flag + * @param write sets the block's write permission flag + * @param execute sets the block's execute permission flag + * @param isVolatile sets the block's volatile flag + * @param initialValue the bytes value to use throught the new block. + * @param isOverlay if true, the block will be created in a new overlay address space. + */ + public AddInitializedMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile, + byte initialValue, boolean isOverlay) { + super(name, comment, source, start, length, read, write, execute, isVolatile); + + this.initialValue = initialValue; + this.isOverlay = isOverlay; + } + + @Override + protected MemoryBlock createMemoryBlock(Memory memory) + throws LockException, MemoryConflictException, AddressOverflowException, + DuplicateNameException, CancelledException { + return memory.createInitializedBlock(name, start, length, initialValue, null, isOverlay); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddMemoryBlockCmd.java deleted file mode 100644 index 9df9c8974c..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddMemoryBlockCmd.java +++ /dev/null @@ -1,174 +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.cmd.memory; - -import ghidra.framework.cmd.Command; -import ghidra.framework.model.DomainObject; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressOverflowException; -import ghidra.program.model.listing.*; -import ghidra.program.model.mem.*; -import ghidra.util.Msg; -import ghidra.util.exception.DuplicateNameException; -import ghidra.util.exception.RollbackException; - -/** - * - * Command to add a memory block. - * - * - */ -public class AddMemoryBlockCmd implements Command { - - private String name; - private String comment; - private String source; - private Address start; - private int length; - private boolean read; - private boolean write; - private boolean execute; - private boolean isVolatile; - private byte initialValue; - private MemoryBlockType blockType; - private Address baseAddr; - private Program program; - private String message; - private boolean isInitialized; - - /** - * - * Construct a new AddMemoryBlockCmd - * @param name block name - * @param comment block comments - * @param source block source - * @param start starting address of the block - * @param length block length - * @param read read permissions - * @param write write permissions - * @param execute execute permissions - * @param isVolatile volatile setting - * @param initialValue initial byte value - * @param blockType type of block to add: MemoryBlockType.DEFAULT, - * MemoryBlockType.OVERLAY, or MemoryBlockType.BIT_MAPPED or MemoryBlockType.BYTE_MAPPED - * @param baseAddr base address for the source address if the block type - * is TYPE_BIT_MAPPED or TYPE_BYTE_MAPPED; otherwise, null - */ - public AddMemoryBlockCmd(String name, String comment, String source, Address start, int length, - boolean read, boolean write, boolean execute, boolean isVolatile, byte initialValue, - MemoryBlockType blockType, Address baseAddr, boolean isInitialized) { - this.name = name; - this.comment = comment; - this.source = source; - this.start = start; - this.length = length; - this.read = read; - this.write = write; - this.execute = execute; - this.isVolatile = isVolatile; - this.initialValue = initialValue; - this.blockType = blockType; - this.baseAddr = baseAddr; - this.isInitialized = isInitialized; - - } - - /** - * @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject) - */ - @Override - public boolean applyTo(DomainObject obj) { - program = (Program) obj; - try { - Memory memory = program.getMemory(); - MemoryBlock block = null; - if (isInitialized) { - block = memory.createInitializedBlock(name, start, length, initialValue, null, - (blockType == MemoryBlockType.OVERLAY)); - } - else if (blockType == MemoryBlockType.DEFAULT || blockType == MemoryBlockType.OVERLAY) { - block = memory.createUninitializedBlock(name, start, length, - (blockType == MemoryBlockType.OVERLAY)); - } - else if (blockType == MemoryBlockType.BIT_MAPPED) { - block = memory.createBitMappedBlock(name, start, baseAddr, length); - } - else { - block = memory.createByteMappedBlock(name, start, baseAddr, length); - } - block.setComment(comment); - block.setRead(read); - block.setWrite(write); - block.setExecute(execute); - block.setVolatile(isVolatile); - block.setSourceName(source); - renameFragment(block.getStart()); - return true; - } - catch (IllegalArgumentException e) { - message = e.getMessage(); - } - catch (AddressOverflowException e) { - message = e.getMessage(); - } - catch (MemoryConflictException e) { - message = e.getMessage(); - } - catch (OutOfMemoryError e) { - message = "Not enough memory to create block"; - } - catch (DuplicateNameException e) { - message = "Duplicate Name: " + e.getMessage(); - } - catch (IllegalStateException e) { - message = e.getMessage(); - } - catch (Throwable t) { - message = "Create block failed"; - Msg.showError(this, null, "Create Block Failed", t.getMessage(), t); - } - throw new RollbackException(message); - } - - /** - * @see ghidra.framework.cmd.Command#getName() - */ - @Override - public String getName() { - return "Add Memory Block"; - } - - /** - * @see ghidra.framework.cmd.Command#getStatusMsg() - */ - @Override - public String getStatusMsg() { - return message; - } - - private void renameFragment(Address blockStartAddr) { - Listing listing = program.getListing(); - String[] treeNames = listing.getTreeNames(); - for (int i = 0; i < treeNames.length; i++) { - try { - ProgramFragment frag = listing.getFragment(treeNames[i], blockStartAddr); - frag.setName(name); - } - catch (DuplicateNameException exc) { - } - } - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddUninitializedMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddUninitializedMemoryBlockCmd.java new file mode 100644 index 0000000000..2e7b5df4c4 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AddUninitializedMemoryBlockCmd.java @@ -0,0 +1,58 @@ +/* ### + * 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.cmd.memory; + +import ghidra.framework.store.LockException; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.*; +import ghidra.util.exception.DuplicateNameException; + +/** + * Command for adding uninitialized memory blocks + */ +public class AddUninitializedMemoryBlockCmd extends AbstractAddMemoryBlockCmd { + + private final boolean isOverlay; + + /** + * Create a new AddUninitializedMemoryBlockCmd + * @param name the name for the new memory block. + * @param comment the comment for the block + * @param source indicates what is creating the block + * @param start the start address for the the block + * @param length the length of the new block + * @param read sets the block's read permission flag + * @param write sets the block's write permission flag + * @param execute sets the block's execute permission flag + * @param isVolatile sets the block's volatile flag + * @param isOverlay if true, the block will be created in a new overlay address space. + */ + public AddUninitializedMemoryBlockCmd(String name, String comment, String source, Address start, + long length, boolean read, boolean write, boolean execute, boolean isVolatile, + boolean isOverlay) { + super(name, comment, source, start, length, read, write, execute, isVolatile); + + this.isOverlay = isOverlay; + } + + @Override + protected MemoryBlock createMemoryBlock(Memory memory) throws LockException, + MemoryConflictException, AddressOverflowException, DuplicateNameException { + return memory.createUninitializedBlock(name, start, length, isOverlay); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java index 00ee426751..8da90fed94 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java @@ -15,8 +15,8 @@ */ package ghidra.app.plugin.core.memory; -import java.awt.BorderLayout; -import java.awt.CardLayout; +import java.awt.*; +import java.util.List; import javax.swing.*; import javax.swing.event.*; @@ -27,14 +27,18 @@ import docking.widgets.checkbox.GCheckBox; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GDLabel; import docking.widgets.label.GLabel; +import ghidra.app.plugin.core.memory.AddBlockModel.InitializedType; import ghidra.app.plugin.core.misc.RegisterField; import ghidra.app.util.*; import ghidra.framework.plugintool.PluginTool; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlockType; import ghidra.util.HelpLocation; +import ghidra.util.layout.HorizontalLayout; import ghidra.util.layout.PairLayout; /** @@ -50,10 +54,9 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { private JTextField commentField; private JPanel viewPanel; - private CardLayout cardLayout; - private JPanel initializedPanel; - private JPanel bottomPanel; + private CardLayout typeCardLayout; private JRadioButton initializedRB; + private GRadioButton initializedFromFileBytesRB; private JRadioButton uninitializedRB; private JCheckBox readCB; @@ -68,13 +71,25 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { private AddBlockModel model; private GhidraComboBox comboBox; private boolean updatingInitializedRB; + private CardLayout initializedTypeCardLayout; private final static String MAPPED = "Mapped"; - private final static String OTHER = "Other"; + private final static String UNMAPPED = "Unmapped"; + private static final String UNITIALIZED = "UNITIALIZED"; + private static final String INITIALIZED = "INITIALIZED"; + private static final String FILE_BYTES = "FILE_BYTES"; + private JPanel inializedTypePanel; + private RegisterField fileOffsetField; + private GhidraComboBox fileBytesComboBox; AddBlockDialog(AddBlockModel model) { super("Add Memory Block", true, true, true, false); - init(model); + this.model = model; + model.setChangeListener(this); + setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP, "Add Block")); + addWorkPanel(buildWorkPanel()); + addOKButton(); + addCancelButton(); } /** @@ -84,150 +99,197 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { public void stateChanged(ChangeEvent e) { setStatusText(model.getMessage()); setOkEnabled(model.isValidInfo()); - readCB.setEnabled(model.isReadEnabled()); - writeCB.setEnabled(model.isWriteEnabled()); - executeCB.setEnabled(model.isExecuteEnabled()); - volatileCB.setEnabled(model.isVolatileEnabled()); - if (initializedRB != null) { - updatingInitializedRB = true; - try { - initializedRB.setSelected(model.getInitializedState()); - } - finally { - updatingInitializedRB = false; - } - } - } - - private void init(AddBlockModel blockModel) { - this.model = blockModel; - blockModel.setChangeListener(this); - create(); - setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP, "Add Block")); + readCB.setSelected(model.isRead()); + writeCB.setSelected(model.isWrite()); + executeCB.setSelected(model.isExecute()); + volatileCB.setSelected(model.isVolatile()); } /** * Define the Main panel for the dialog here. */ - private void create() { - cardLayout = new CardLayout(); - viewPanel = new JPanel(cardLayout); + private JComponent buildWorkPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + panel.add(buildMainPanel(), BorderLayout.NORTH); + panel.add(buildVariablePanel(), BorderLayout.CENTER); + return panel; + } - nameField = new JTextField(); - nameField.setName("Block Name"); + private Component buildMainPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(buildBasicInfoPanel(), BorderLayout.NORTH); + panel.add(buildPermissionsPanel(), BorderLayout.CENTER); + panel.add(buildTypesPanel(), BorderLayout.SOUTH); - addrField = new AddressInput(); - addrField.setName("Start Addr"); + return panel; + } - lengthField = new RegisterField(32, null, false); - lengthField.setName("Length"); + private Component buildBasicInfoPanel() { + JPanel panel = new JPanel(new PairLayout(4, 10, 150)); + panel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5)); - commentField = new JTextField(); - commentField.setName("Comment"); + panel.add(new GLabel("Block Name:", SwingConstants.RIGHT)); + panel.add(buildNameField()); + panel.add(new GLabel("Start Addr:", SwingConstants.RIGHT)); + panel.add(buildAddressField()); + panel.add(new GLabel("Length:", SwingConstants.RIGHT)); + panel.add(buildLengthField()); + panel.add(new GLabel("Comment:", SwingConstants.RIGHT)); + panel.add(buildCommentField()); - addrFactory = model.getProgram().getAddressFactory(); - addrField.setAddressFactory(addrFactory, true); + return panel; + } - nameField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - nameChanged(); - } + private Component buildPermissionsPanel() { - @Override - public void removeUpdate(DocumentEvent e) { - nameChanged(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - nameChanged(); - } - }); - - lengthField.setChangeListener(e -> lengthChanged()); - addrField.addChangeListener(ev -> addrChanged()); - - readCB = new GCheckBox(); + readCB = new GCheckBox("Read"); readCB.setName("Read"); + readCB.setSelected(model.isRead()); + readCB.addActionListener(e -> model.setRead(readCB.isSelected())); - writeCB = new GCheckBox(); + writeCB = new GCheckBox("Write"); writeCB.setName("Write"); + writeCB.setSelected(model.isWrite()); + writeCB.addActionListener(e -> model.setWrite(writeCB.isSelected())); - executeCB = new GCheckBox(); + executeCB = new GCheckBox("Execute"); executeCB.setName("Execute"); + executeCB.setSelected(model.isExecute()); + executeCB.addActionListener(e -> model.setExecute(executeCB.isSelected())); - volatileCB = new GCheckBox(); + volatileCB = new GCheckBox("Volatile"); volatileCB.setName("Volatile"); + volatileCB.setSelected(model.isVolatile()); + volatileCB.addActionListener(e -> model.setVolatile(volatileCB.isSelected())); - JPanel topPanel = new JPanel(new PairLayout(4, 10, 150)); - topPanel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5)); - topPanel.add(new GLabel("Block Name:", SwingConstants.RIGHT)); - topPanel.add(nameField); - topPanel.add(new GLabel("Start Addr:", SwingConstants.RIGHT)); - topPanel.add(addrField); - topPanel.add(new GLabel("Length:", SwingConstants.RIGHT)); - topPanel.add(lengthField); - topPanel.add(new GLabel("Comment:", SwingConstants.RIGHT)); - topPanel.add(commentField); + JPanel panel = new JPanel(new HorizontalLayout(10)); + panel.setBorder(BorderFactory.createEmptyBorder(10, 30, 20, 30)); + panel.add(readCB); + panel.add(writeCB); + panel.add(executeCB); + panel.add(volatileCB); - JPanel execPanel = new JPanel(); - BoxLayout bl = new BoxLayout(execPanel, BoxLayout.X_AXIS); - execPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + return panel; + } - execPanel.setLayout(bl); - execPanel.add(Box.createHorizontalStrut(10)); - execPanel.add(new GLabel("Read")); - execPanel.add(readCB); - execPanel.add(Box.createHorizontalStrut(10)); + private Component buildTypesPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createTitledBorder("Block Types")); - execPanel.add(new GLabel("Write")); - execPanel.add(writeCB); - execPanel.add(Box.createHorizontalStrut(10)); + MemoryBlockType[] items = new MemoryBlockType[] { MemoryBlockType.DEFAULT, + MemoryBlockType.OVERLAY, MemoryBlockType.BIT_MAPPED, MemoryBlockType.BYTE_MAPPED }; - execPanel.add(new GLabel("Execute")); - execPanel.add(executeCB); - execPanel.add(Box.createHorizontalStrut(10)); + comboBox = new GhidraComboBox<>(items); + comboBox.addItemListener(e -> blockTypeSelected()); + panel.add(comboBox); + return panel; + } - execPanel.add(new GLabel("Volatile")); - execPanel.add(volatileCB); + private Component buildVariablePanel() { + typeCardLayout = new CardLayout(); + viewPanel = new JPanel(typeCardLayout); + viewPanel.setBorder(BorderFactory.createEtchedBorder()); - JPanel panel = new JPanel(); - panel.add(execPanel); + viewPanel.add(buildMappedPanel(), MAPPED); + viewPanel.add(buildUnmappedPanel(), UNMAPPED); + typeCardLayout.show(viewPanel, UNMAPPED); + return viewPanel; + } - JPanel outerTopPanel = new JPanel(new BorderLayout()); - outerTopPanel.add(topPanel, BorderLayout.NORTH); - outerTopPanel.add(panel, BorderLayout.CENTER); + private Component buildUnmappedPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(buildInitializedRadioButtonPanel(), BorderLayout.NORTH); + panel.add(buildVariableInitializedPanel()); + return panel; + } - bottomPanel = new JPanel(); - BoxLayout layout = new BoxLayout(bottomPanel, BoxLayout.Y_AXIS); - bottomPanel.setLayout(layout); - bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 7, 4, 5)); - bottomPanel.add(createComboBoxPanel()); - bottomPanel.add(viewPanel); + private Component buildInitializedRadioButtonPanel() { + JPanel panel = new JPanel(new HorizontalLayout(10)); - JPanel mainPanel = new JPanel(); - layout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS); - mainPanel.setLayout(layout); - mainPanel.add(outerTopPanel); - mainPanel.add(bottomPanel); - mainPanel.validate(); + ButtonGroup radioGroup = new ButtonGroup(); + initializedRB = new GRadioButton("Initialized", false); + initializedRB.setName(initializedRB.getText()); + initializedRB.addActionListener(ev -> initializeRBChanged()); - JPanel mainPanel2 = new JPanel(new BorderLayout()); - mainPanel2.add(mainPanel, BorderLayout.NORTH); - mainPanel2.add(new JPanel(), BorderLayout.CENTER); + initializedFromFileBytesRB = new GRadioButton("File Bytes", false); + initializedFromFileBytesRB.setName(initializedRB.getText()); + initializedFromFileBytesRB.addActionListener(ev -> initializeRBChanged()); - createCardPanels(); + uninitializedRB = new GRadioButton("Uninitialized", true); + uninitializedRB.setName(uninitializedRB.getText()); + uninitializedRB.addActionListener(ev -> initializeRBChanged()); - addWorkPanel(mainPanel2); - addOKButton(); - addCancelButton(); + radioGroup.add(initializedRB); + radioGroup.add(initializedFromFileBytesRB); + radioGroup.add(uninitializedRB); + + panel.add(initializedRB); + panel.add(initializedFromFileBytesRB); + panel.add(uninitializedRB); + + return panel; + } + + private Component buildVariableInitializedPanel() { + initializedTypeCardLayout = new CardLayout(); + + inializedTypePanel = new JPanel(initializedTypeCardLayout); + inializedTypePanel.add(new JPanel(), UNITIALIZED); + inializedTypePanel.add(buildInitalValuePanel(), INITIALIZED); + inializedTypePanel.add(buildFileBytesPanel(), FILE_BYTES); + return inializedTypePanel; + } + + private Component buildInitalValuePanel() { + initialValueLabel = new GDLabel("Initial Value"); + initialValueField = new RegisterField(8, null, false); + initialValueField.setName("Initial Value"); + + initialValueField.setChangeListener(e -> initialValueChanged()); + + JPanel panel = new JPanel(new PairLayout(4, 10)); + panel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5)); + panel.add(initialValueLabel); + panel.add(initialValueField); + return panel; + } + + private Component buildFileBytesPanel() { + JPanel panel = new JPanel(new PairLayout(5, 5)); + panel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5)); + + panel.add(new GLabel("File Bytes:")); + panel.add(buildFileBytesCombo()); + panel.add(new GLabel("File Offset:")); + panel.add(buildFileOffsetField()); + + return panel; + } + + private Component buildFileBytesCombo() { + Memory memory = model.getProgram().getMemory(); + List allFileBytes = memory.getAllFileBytes(); + FileBytes[] fileBytes = allFileBytes.toArray(new FileBytes[allFileBytes.size()]); + + fileBytesComboBox = new GhidraComboBox<>(fileBytes) { + public Dimension getPreferredSize() { + Dimension preferredSize = super.getPreferredSize(); + preferredSize.width = 100; + return preferredSize; + } + }; + fileBytesComboBox.addItemListener(e -> fileBytesChanged()); + if (!allFileBytes.isEmpty()) { + model.setFileBytes(allFileBytes.get(0)); + } + return fileBytesComboBox; } /** * Display the dialog filled with default values. * Used to enter a new MemoryBlock. - * @param nlines default value displayed in the text field. + * @param tool the tool that owns this dialog */ void showDialog(PluginTool tool) { @@ -237,17 +299,16 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { lengthField.setValue(Long.valueOf(0)); model.setLength(0); commentField.setText(""); - - readCB.setSelected(true); - writeCB.setSelected(true); - executeCB.setSelected(false); - volatileCB.setSelected(false); - initialValueField.setValue(Long.valueOf(0)); model.setBlockType(MemoryBlockType.DEFAULT); - model.setIsInitialized(initializedRB.isSelected()); + model.setInitializedType(AddBlockModel.InitializedType.UNITIALIZED); model.setInitialValue(0); + readCB.setSelected(model.isRead()); + writeCB.setSelected(model.isWrite()); + executeCB.setSelected(model.isExecute()); + volatileCB.setSelected(model.isVolatile()); + setOkEnabled(false); tool.showDialog(this, tool.getComponentProvider(PluginConstants.MEMORY_MAP)); } @@ -262,9 +323,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { */ @Override protected void okCallback() { - - if (model.execute(commentField.getText(), readCB.isSelected(), writeCB.isSelected(), - executeCB.isSelected(), volatileCB.isSelected())) { + if (model.execute()) { close(); } else { @@ -277,27 +336,17 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { if (updatingInitializedRB) { return; } - boolean selected = initializedRB.isSelected(); - model.setIsInitialized(selected); - initialValueField.setEnabled(selected); - initialValueLabel.setEnabled(selected); - if (!selected) { - initialValueField.setValue(new Long(0)); - model.setInitialValue(0); + if (initializedRB.isSelected()) { + model.setInitializedType(InitializedType.INITIALIZED_FROM_VALUE); + initializedTypeCardLayout.show(inializedTypePanel, INITIALIZED); } - } - - private void uninitializedRBChanged() { - if (updatingInitializedRB) { - return; + else if (uninitializedRB.isSelected()) { + model.setInitializedType(InitializedType.UNITIALIZED); + initializedTypeCardLayout.show(inializedTypePanel, UNITIALIZED); } - boolean selected = uninitializedRB.isSelected(); - model.setIsInitialized(!selected); - initialValueField.setEnabled(!selected); - initialValueLabel.setEnabled(!selected); - if (!selected) { - initialValueField.setValue(new Long(0)); - model.setInitialValue(0); + else if (initializedFromFileBytesRB.isSelected()) { + model.setInitializedType(InitializedType.INITIALIZED_FROM_FILE_BYTES); + initializedTypeCardLayout.show(inializedTypePanel, FILE_BYTES); } } @@ -318,21 +367,40 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { model.setBlockName(name); } + private void commentChanged() { + String comment = commentField.getText().trim(); + model.setComment(comment); + } + private void lengthChanged() { - int length = 0; + long length = 0; Long val = lengthField.getValue(); if (val != null) { - length = val.intValue(); + length = val.longValue(); } model.setLength(length); } + private void fileOffsetChanged() { + long fileOffset = -1; + Long val = fileOffsetField.getValue(); + if (val != null) { + fileOffset = val.longValue(); + } + model.setFileOffset(fileOffset); + } + + private void fileBytesChanged() { + model.setFileBytes((FileBytes) fileBytesComboBox.getSelectedItem()); + } + private void addrChanged() { Address addr = null; try { addr = addrField.getAddress(); } catch (IllegalArgumentException e) { + // just let it be null } model.setStartAddress(addr); } @@ -342,90 +410,19 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { model.setBaseAddress(baseAddress); } - private JPanel createComboBoxPanel() { - JPanel panel = new JPanel(new BorderLayout()); - panel.setBorder(BorderFactory.createTitledBorder("Block Types")); - - MemoryBlockType[] items = new MemoryBlockType[] { MemoryBlockType.DEFAULT, - MemoryBlockType.OVERLAY, MemoryBlockType.BIT_MAPPED, MemoryBlockType.BYTE_MAPPED }; - - comboBox = new GhidraComboBox<>(items); - comboBox.addItemListener(e -> blockTypeSelected()); - panel.add(comboBox); - return panel; - } - private void blockTypeSelected() { - MemoryBlockType blockType = (MemoryBlockType) comboBox.getSelectedItem(); model.setBlockType(blockType); - if (blockType == MemoryBlockType.DEFAULT) { - cardLayout.show(viewPanel, OTHER); - } - else if (blockType == MemoryBlockType.OVERLAY) { - cardLayout.show(viewPanel, OTHER); - } - else if (blockType == MemoryBlockType.BIT_MAPPED) { - cardLayout.show(viewPanel, MAPPED); + if (blockType == MemoryBlockType.DEFAULT || blockType == MemoryBlockType.OVERLAY) { + typeCardLayout.show(viewPanel, UNMAPPED); } else { - // type is Byte mapped - cardLayout.show(viewPanel, MAPPED); + typeCardLayout.show(viewPanel, MAPPED); } } - private JPanel createRadioPanel() { - JPanel panel = new JPanel(); - BoxLayout bl = new BoxLayout(panel, BoxLayout.X_AXIS); - panel.setLayout(bl); - - ButtonGroup radioGroup = new ButtonGroup(); - initializedRB = new GRadioButton("Initialized", false); - initializedRB.setName(initializedRB.getText()); - initializedRB.addActionListener(ev -> initializeRBChanged()); - - uninitializedRB = new GRadioButton("Uninitialized", true); - uninitializedRB.setName(uninitializedRB.getText()); - uninitializedRB.addActionListener(ev -> uninitializedRBChanged()); - - radioGroup.add(initializedRB); - radioGroup.add(uninitializedRB); - - panel.add(initializedRB); - panel.add(uninitializedRB); - - JPanel outerPanel = new JPanel(); - BoxLayout bl2 = new BoxLayout(outerPanel, BoxLayout.Y_AXIS); - outerPanel.setLayout(bl2); - outerPanel.add(panel); - createInitializedPanel(); - outerPanel.add(initializedPanel); - outerPanel.setBorder(BorderFactory.createEtchedBorder()); - return outerPanel; - } - - private void createCardPanels() { - viewPanel.add(createAddressPanel(), MAPPED); - viewPanel.add(createRadioPanel(), OTHER); - cardLayout.show(viewPanel, OTHER); - } - - private void createInitializedPanel() { - initialValueLabel = new GDLabel("Initial Value"); - initialValueField = new RegisterField(8, null, false); - initialValueField.setName("Initial Value"); - initialValueField.setEnabled(false); - - initialValueField.setChangeListener(e -> initialValueChanged()); - - initializedPanel = new JPanel(new PairLayout(4, 10)); - initializedPanel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5)); - initializedPanel.add(initialValueLabel); - initializedPanel.add(initialValueField); - } - - private JPanel createAddressPanel() { - JPanel addressPanel = new JPanel(new PairLayout()); + private JPanel buildMappedPanel() { + JPanel panel = new JPanel(new PairLayout()); baseAddrField = new AddressInput(); baseAddrField.setAddressFactory(addrFactory); @@ -440,10 +437,77 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener { } baseAddrField.setAddress(minAddr); model.setBaseAddress(minAddr); - addressPanel.add(new GLabel("Source Addr:")); - addressPanel.add(baseAddrField); - addressPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); - return addressPanel; + panel.add(new GLabel("Source Addr:")); + panel.add(baseAddrField); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return panel; + } + + private Component buildCommentField() { + commentField = new JTextField(); + commentField.setName("Comment"); + commentField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + commentChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + commentChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + commentChanged(); + } + }); + return commentField; + } + + private Component buildLengthField() { + lengthField = new RegisterField(36, null, false); + lengthField.setName("Length"); + lengthField.setChangeListener(e -> lengthChanged()); + return lengthField; + } + + private Component buildFileOffsetField() { + fileOffsetField = new RegisterField(60, null, false); + fileOffsetField.setName("File Offset"); + fileOffsetField.setChangeListener(e -> fileOffsetChanged()); + return fileOffsetField; + } + + private Component buildAddressField() { + addrField = new AddressInput(); + addrField.setName("Start Addr"); + addrFactory = model.getProgram().getAddressFactory(); + addrField.setAddressFactory(addrFactory, true); + addrField.addChangeListener(ev -> addrChanged()); + return addrField; + } + + private Component buildNameField() { + nameField = new JTextField(); + nameField.setName("Block Name"); + nameField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + nameChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + nameChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + nameChanged(); + } + }); + return nameField; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java index 836ee087f5..017cc39ca8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java @@ -17,13 +17,16 @@ package ghidra.app.plugin.core.memory; import javax.swing.event.ChangeListener; -import ghidra.app.cmd.memory.AddMemoryBlockCmd; +import ghidra.app.cmd.memory.*; +import ghidra.framework.cmd.Command; import ghidra.framework.plugintool.PluginTool; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.*; import ghidra.util.NamingUtilities; import ghidra.util.datastruct.StringKeyIndexer; +import ghidra.util.exception.AssertException; /** * @@ -39,23 +42,25 @@ class AddBlockModel { private String blockName; private Address startAddr; private Address baseAddr; - private int length; + private long length; private MemoryBlockType blockType; private int initialValue; private String message; private ChangeListener listener; private boolean isValid; - private boolean readEnabled; - private boolean writeEnabled; - private boolean executeEnabled; - private boolean volatileEnabled; - private boolean isInitialized; + private boolean isRead; + private boolean isWrite; + private boolean isExecute; + private boolean isVolatile; + private InitializedType initializedType; + private String comment; + private FileBytes fileBytes; + private long fileBytesOffset = -1; + + enum InitializedType { + UNITIALIZED, INITIALIZED_FROM_VALUE, INITIALIZED_FROM_FILE_BYTES; + } - /** - * Construct a new model. - * @param tool - * @param program - */ AddBlockModel(PluginTool tool, Program program) { this.tool = tool; this.program = program; @@ -64,10 +69,6 @@ class AddBlockModel { startAddr = program.getImageBase(); blockType = MemoryBlockType.DEFAULT; initialValue = 0; - readEnabled = true; - writeEnabled = true; - executeEnabled = true; - volatileEnabled = true; } void setChangeListener(ChangeListener listener) { @@ -80,18 +81,34 @@ class AddBlockModel { listener.stateChanged(null); } + public void setComment(String comment) { + this.comment = comment; + } + void setStartAddress(Address addr) { startAddr = addr; validateInfo(); listener.stateChanged(null); } - void setLength(int length) { + void setLength(long length) { this.length = length; validateInfo(); listener.stateChanged(null); } + void setFileOffset(long fileOffset) { + this.fileBytesOffset = fileOffset; + validateInfo(); + listener.stateChanged(null); + } + + void setFileBytes(FileBytes fileBytes) { + this.fileBytes = fileBytes; + validateInfo(); + listener.stateChanged(null); + } + void setInitialValue(int initialValue) { this.initialValue = initialValue; validateInfo(); @@ -100,16 +117,35 @@ class AddBlockModel { void setBlockType(MemoryBlockType blockType) { this.blockType = blockType; - readEnabled = true; - writeEnabled = true; - executeEnabled = true; - volatileEnabled = true; + isRead = true; + isWrite = true; + isExecute = false; + isVolatile = false; + initializedType = InitializedType.UNITIALIZED; validateInfo(); listener.stateChanged(null); } - void setIsInitialized(boolean isInitialized) { - this.isInitialized = isInitialized; + void setRead(boolean b) { + this.isRead = b; + } + + void setWrite(boolean b) { + this.isWrite = b; + } + + void setExecute(boolean b) { + this.isExecute = b; + } + + void setVolatile(boolean b) { + this.isVolatile = b; + } + + void setInitializedType(InitializedType type) { + this.initializedType = type; + validateInfo(); + listener.stateChanged(null); } void setBaseAddress(Address baseAddr) { @@ -142,45 +178,33 @@ class AddBlockModel { return program; } - boolean isReadEnabled() { - return readEnabled; + boolean isRead() { + return isRead; } - boolean isWriteEnabled() { - return writeEnabled; + boolean isWrite() { + return isWrite; } - boolean isExecuteEnabled() { - return executeEnabled; + boolean isExecute() { + return isExecute; } - boolean isVolatileEnabled() { - return volatileEnabled; + boolean isVolatile() { + return isVolatile; } - boolean getInitializedState() { - return isInitialized; + InitializedType getInitializedType() { + return initializedType; } - /** - * Add the block. - * @param comment block comment - * @param isRead read permissions - * @param isWrite write permissions - * @param isExecute execute permissions - * @param isVolatile volatile setting - * @return true if the block was successfully added - */ - boolean execute(String comment, boolean isRead, boolean isWrite, boolean isExecute, - boolean isVolatile) { + boolean execute() { validateInfo(); if (!isValid) { return false; } - AddMemoryBlockCmd cmd = new AddMemoryBlockCmd(blockName, comment, "- none -", startAddr, - length, isRead, isWrite, isExecute, isVolatile, (byte) initialValue, blockType, - baseAddr, isInitialized); + Command cmd = createAddBlockCommand(); if (!tool.execute(cmd, program)) { message = cmd.getStatusMsg(); return false; @@ -188,60 +212,162 @@ class AddBlockModel { return true; } + Command createAddBlockCommand() { + String source = ""; + switch (blockType) { + case BIT_MAPPED: + return new AddBitMappedMemoryBlockCmd(blockName, comment, source, startAddr, length, + isRead, isWrite, isExecute, isVolatile, baseAddr); + case BYTE_MAPPED: + return new AddByteMappedMemoryBlockCmd(blockName, comment, source, startAddr, + length, isRead, isWrite, isExecute, isVolatile, baseAddr); + case DEFAULT: + return createNonMappedMemoryBlock(source, false); + case OVERLAY: + return createNonMappedMemoryBlock(source, true); + default: + throw new AssertException("Encountered unexpected block type: " + blockType); + + } + } + + private Command createNonMappedMemoryBlock(String source, boolean isOverlay) { + switch (initializedType) { + case INITIALIZED_FROM_FILE_BYTES: + return new AddFileBytesMemoryBlockCmd(blockName, comment, source, startAddr, length, + isRead, isWrite, isExecute, isVolatile, fileBytes, fileBytesOffset, isOverlay); + case INITIALIZED_FROM_VALUE: + return new AddInitializedMemoryBlockCmd(blockName, comment, source, startAddr, + length, isRead, isWrite, isExecute, isVolatile, (byte) initialValue, isOverlay); + case UNITIALIZED: + return new AddUninitializedMemoryBlockCmd(blockName, comment, source, startAddr, + length, isRead, isWrite, isExecute, isVolatile, isOverlay); + default: + throw new AssertException( + "Encountered unexpected intialized type: " + initializedType); + + } + } + void dispose() { tool = null; program = null; } private void validateInfo() { - message = ""; - isValid = false; - if (initialValue < 0 && isInitialized) { - message = "Please enter a valid initial byte value"; - return; + isValid = hasValidName() && hasValidStartAddress() && hasValidLength() && + hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasUniqueNameIfOverlay() && + hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded(); + } + + private boolean hasFileBytesInfoIfNeeded() { + + if (initializedType != InitializedType.INITIALIZED_FROM_FILE_BYTES) { + return true; } - if (blockName == null || blockName.length() == 0) { - message = "Please enter a name"; - return; + + if (fileBytes == null) { + message = "Please select a FileBytes entry"; + return false; } - if (nameExists(blockName)) { - message = "Block name already exists"; - return; + + if (fileBytesOffset < 0 || fileBytesOffset >= fileBytes.getSize()) { + message = + "Please enter a valid file bytes offset (0 - " + (fileBytes.getSize() - 1) + ")"; + return false; } - if (!NamingUtilities.isValidName(blockName)) { - message = "Block name is invalid"; - return; + + if (fileBytesOffset + length > fileBytes.getSize()) { + message = "File bytes offset + length exceeds file bytes size: " + fileBytes.getSize(); + return false; } - if (startAddr == null) { - message = "Please enter a valid starting address"; - return; + return true; + } + + private boolean hasInitialValueIfNeeded() { + + if (initializedType != InitializedType.INITIALIZED_FROM_VALUE) { + return true; } + + if (initialValue >= 0 && initialValue <= 255) { + return true; + } + message = "Please enter a valid initial byte value"; + return false; + } + + private boolean hasUniqueNameIfOverlay() { + if (blockType != MemoryBlockType.OVERLAY) { + return true; + } + AddressFactory factory = program.getAddressFactory(); + AddressSpace[] spaces = factory.getAddressSpaces(); + for (AddressSpace space : spaces) { + if (space.getName().equals(blockName)) { + message = "Address Space named " + blockName + " already exists"; + return false; + } + } + return true; + } + + private boolean hasMappedAddressIfNeeded() { if (blockType == MemoryBlockType.BIT_MAPPED || blockType == MemoryBlockType.BYTE_MAPPED) { - isInitialized = false; if (baseAddr == null) { String blockTypeStr = (blockType == MemoryBlockType.BIT_MAPPED) ? "bit" : "overlay"; message = "Please enter a source address for the " + blockTypeStr + " block"; - return; + return false; } } - long sizeLimit = - isInitialized ? Memory.MAX_INITIALIZED_BLOCK_SIZE : Memory.MAX_UNINITIALIZED_BLOCK_SIZE; - if (length <= 0 || length > sizeLimit) { - message = "Please enter a valid length > 0 and <= 0x" + Long.toHexString(sizeLimit); - return; - } + return true; + } + private boolean hasNoMemoryConflicts() { if (blockType == MemoryBlockType.OVERLAY) { - AddressFactory factory = program.getAddressFactory(); - AddressSpace[] spaces = factory.getAddressSpaces(); - for (int i = 0; i < spaces.length; i++) { - if (spaces[i].getName().equals(blockName)) { - message = "Address Space named " + blockName + " already exists"; - return; - } - } + return true; } - isValid = true; + Address endAddr = startAddr.add(length - 1); + AddressSet intersectRange = program.getMemory().intersectRange(startAddr, endAddr); + if (!intersectRange.isEmpty()) { + AddressRange firstRange = intersectRange.getFirstRange(); + message = "Block address conflict: " + firstRange; + return false; + } + return true; + } + + private boolean hasValidLength() { + long sizeLimit = Memory.MAX_BLOCK_SIZE; + if (length > 0 && length <= sizeLimit) { + return true; + } + message = "Please enter a valid length between 0 and 0x" + Long.toHexString(sizeLimit); + return false; + } + + private boolean hasValidStartAddress() { + if (startAddr != null) { + return true; + } + message = "Please enter a valid starting address"; + return false; + } + + private boolean hasValidName() { + if (blockName == null || blockName.length() == 0) { + message = "Please enter a name"; + return false; + } + if (nameExists(blockName)) { + message = "Block name already exists"; + return false; + } + if (!NamingUtilities.isValidName(blockName)) { + message = "Block name is invalid"; + return false; + } + return true; } /** @@ -258,8 +384,8 @@ class AddBlockModel { Memory memory = program.getMemory(); MemoryBlock[] blocks = memory.getBlocks(); - for (int i = 0; i < blocks.length; i++) { - nameIndexer.put(blocks[i].getName()); + for (MemoryBlock block : blocks) { + nameIndexer.put(block.getName()); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java index 5745da6b37..cc0bd55c68 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java @@ -16,6 +16,7 @@ package ghidra.app.plugin.core.memory; import java.util.*; +import java.util.stream.Collectors; import javax.swing.JTable; import javax.swing.SwingUtilities; @@ -32,6 +33,7 @@ import docking.widgets.table.AbstractSortedTableModel; import ghidra.framework.model.DomainFile; import ghidra.framework.store.LockException; +import ghidra.program.database.mem.SourceInfo; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.*; @@ -51,8 +53,9 @@ class MemoryMapModel extends AbstractSortedTableModel { final static byte VOLATILE = 7; final static byte BLOCK_TYPE = 8; final static byte INIT = 9; - final static byte SOURCE = 10; - final static byte COMMENT = 11; + final static byte BYTE_SOURCE = 10; + final static byte SOURCE = 11; + final static byte COMMENT = 12; final static String NAME_COL = "Name"; final static String START_COL = "Start"; @@ -64,6 +67,7 @@ class MemoryMapModel extends AbstractSortedTableModel { final static String VOLATILE_COL = "Volatile"; final static String BLOCK_TYPE_COL = "Type"; final static String INIT_COL = "Initialized"; + final static String BYTE_SOURCE_COL = "Byte Source"; final static String SOURCE_COL = "Source"; final static String COMMENT_COL = "Comment"; @@ -74,7 +78,7 @@ class MemoryMapModel extends AbstractSortedTableModel { private final static String COLUMN_NAMES[] = { NAME_COL, START_COL, END_COL, LENGTH_COL, READ_COL, WRITE_COL, EXECUTE_COL, VOLATILE_COL, - BLOCK_TYPE_COL, INIT_COL, SOURCE_COL, COMMENT_COL }; + BLOCK_TYPE_COL, INIT_COL, BYTE_SOURCE_COL, SOURCE_COL, COMMENT_COL }; MemoryMapModel(MemoryMapProvider provider, Program program) { super(START); @@ -146,38 +150,10 @@ class MemoryMapModel extends AbstractSortedTableModel { */ @Override public int findColumn(String columnName) { - if (columnName.equals(NAME_COL)) { - return NAME; - } - if (columnName.equals(START_COL)) { - return START; - } - if (columnName.equals(END_COL)) { - return END; - } - if (columnName.equals(LENGTH_COL)) { - return LENGTH; - } - if (columnName.equals(READ_COL)) { - return READ; - } - if (columnName.equals(WRITE_COL)) { - return WRITE; - } - if (columnName.equals(EXECUTE_COL)) { - return EXECUTE; - } - if (columnName.equals(VOLATILE_COL)) { - return VOLATILE; - } - if (columnName.equals(SOURCE_COL)) { - return SOURCE; - } - if (columnName.equals(COMMENT_COL)) { - return COMMENT; - } - if (columnName.equals(BLOCK_TYPE_COL)) { - return BLOCK_TYPE; + for (int i = 0; i < COLUMN_NAMES.length; i++) { + if (COLUMN_NAMES[i].equals(columnName)) { + return i; + } } return 0; } @@ -523,10 +499,13 @@ class MemoryMapModel extends AbstractSortedTableModel { return null; } return (block.isInitialized() ? Boolean.TRUE : Boolean.FALSE); + case BYTE_SOURCE: + return getByteSourceDescription(block.getSourceInfos()); case SOURCE: if ((block.getType() == MemoryBlockType.BIT_MAPPED) || (block.getType() == MemoryBlockType.BYTE_MAPPED)) { - return ((MappedMemoryBlock) block).getOverlayedMinAddress().toString(); + SourceInfo info = block.getSourceInfos().get(0); + return info.getMappedRange().get().getMinAddress().toString(); } return block.getSourceName(); case COMMENT: @@ -543,6 +522,21 @@ class MemoryMapModel extends AbstractSortedTableModel { return null; } + private String getByteSourceDescription(List sourceInfos) { + List limited = sourceInfos.size() < 5 ? sourceInfos : sourceInfos.subList(0, 4); + + //@formatter:off + String description = limited + .stream() + .map(info -> info.getDescription()) + .collect(Collectors.joining(", ")); + //@formatter:on + if (limited != sourceInfos) { + description += "..."; + } + return description; + } + @Override public List getModelData() { return memList; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtil.java index cd382bd70e..dd349e6be9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtil.java @@ -26,6 +26,7 @@ import ghidra.program.model.listing.*; import ghidra.program.model.mem.*; import ghidra.program.model.symbol.*; import ghidra.program.model.util.AddressLabelInfo; +import ghidra.util.Msg; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitorAdapter; @@ -187,6 +188,7 @@ public class MemoryBlockUtil { comment, source, r, w, x, monitor); } + /** * Creates an initialized memory block using the specified input stream. If the length * of the block is greater than the maximum size of a memory block (0x40000000), then @@ -241,7 +243,7 @@ public class MemoryBlockUtil { long blockLength = 0; // special case first time through loop, don't change start address while (dataLength > 0) { start = start.add(blockLength); - blockLength = Math.min(dataLength, Memory.MAX_INITIALIZED_BLOCK_SIZE); + blockLength = Math.min(dataLength, Memory.MAX_BLOCK_SIZE); String blockName = getBlockName(name, blockNum); monitor.setMessage( "Creating memory block \"" + blockName + "\" at 0x" + start + "..."); @@ -301,8 +303,8 @@ public class MemoryBlockUtil { //remove their ranges from our address set. // MemoryBlock[] existingBlocks = memory.getBlocks(); - for (int i = 0; i < existingBlocks.length; ++i) { - set.deleteRange(existingBlocks[i].getStart(), existingBlocks[i].getEnd()); + for (MemoryBlock existingBlock : existingBlocks) { + set.deleteRange(existingBlock.getStart(), existingBlock.getEnd()); } appendMessage("WARNING!!\n\tMemory block [" + name + @@ -605,16 +607,21 @@ public class MemoryBlockUtil { messages.append(msg); } - private void renameFragment(Address blockStart, String blockName) { + private void renameFragment(Address address, String name) { + adjustFragment(listing, address, name); + } + + public static void adjustFragment(Listing listing, Address address, String name) { String[] treeNames = listing.getTreeNames(); - for (int i = 0; i < treeNames.length; ++i) { + for (String treeName : treeNames) { try { - ProgramFragment frag = listing.getFragment(treeNames[i], blockStart); - frag.setName(blockName); + ProgramFragment frag = listing.getFragment(treeName, address); + frag.setName(name); } catch (DuplicateNameException e) { + Msg.warn(MemoryBlockUtil.class, + "Could not rename fragment to match newly created block because of name conflict"); } } } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtils.java new file mode 100644 index 0000000000..670bfb8816 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/MemoryBlockUtils.java @@ -0,0 +1,263 @@ +/* ### + * 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.util; + +import java.io.IOException; +import java.io.InputStream; + +import ghidra.app.util.bin.ByteProvider; +import ghidra.app.util.importer.MessageLog; +import ghidra.framework.store.LockException; +import ghidra.program.database.mem.FileBytes; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.listing.*; +import ghidra.program.model.mem.*; +import ghidra.util.Msg; +import ghidra.util.exception.DuplicateNameException; + +/** + * Convenience methods for creating memory blocks. + */ +public class MemoryBlockUtils { + + /** + * Creates a new uninitialized memory block. + * @param program the program in which to create the block. + * @param isOverlay if true, the block will be created in a new overlay space for that block + * @param name the name of the new block. + * @param start the starting address of the new block. + * @param length the length of the new block + * @param comment the comment text to associate with the new block. + * @param source the source of the block (This field is not well defined - currently another comment) + * @param r the read permission for the new block. + * @param w the write permission for the new block. + * @param x the execute permission for the new block. + * @param log a {@link MessageLog} for appending error messages + * @return the newly created block or null if the operation failed. + */ + public static MemoryBlock createUninitializedBlock(Program program, boolean isOverlay, + String name, Address start, long length, String comment, String source, boolean r, + boolean w, boolean x, MessageLog log) { + + Memory memory = program.getMemory(); + try { + MemoryBlock block = memory.createUninitializedBlock(name, start, length, isOverlay); + setBlockAttributes(block, comment, source, r, w, x); + adjustFragment(program, start, name); + return block; + } + catch (LockException e) { + log.appendMsg("Failed to create memory block: exclusive lock/checkout required"); + } + catch (Exception e) { + log.appendMsg("Failed to create '" + name + "' memory block: " + e.getMessage()); + } + return null; + } + + /** + * Creates a new bit mapped memory block. (A bit mapped block is a block where each byte value + * is either 1 or 0 and the value is taken from a bit in a byte at some other address in memory) + * + * @param program the program in which to create the block. + * @param name the name of the new block. + * @param start the starting address of the new block. + * @param base the address of the region in memory to map to. + * @param length the length of the new block + * @param comment the comment text to associate with the new block. + * @param source the source of the block (This field is not well defined - currently another comment) + * @param r the read permission for the new block. + * @param w the write permission for the new block. + * @param x the execute permission for the new block. + * @param log a {@link StringBuffer} for appending error messages + * @return the new created block + */ + public static MemoryBlock createBitMappedBlock(Program program, String name, + Address start, Address base, int length, String comment, String source, boolean r, + boolean w, boolean x, MessageLog log) { + + Memory memory = program.getMemory(); + try { + + MemoryBlock block = memory.createBitMappedBlock(name, start, base, length); + + setBlockAttributes(block, comment, source, r, w, x); + adjustFragment(program, start, name); + return block; + } + catch (LockException e) { + log.appendMsg("Failed to create '" + name + + "'bit mapped memory block: exclusive lock/checkout required"); + } + catch (Exception e) { + log.appendMsg("Failed to create '" + name + "' mapped memory block: " + e.getMessage()); + } + return null; + } + + /** + * Creates a new byte mapped memory block. (A byte mapped block is a block where each byte value + * is taken from a byte at some other address in memory) + * + * @param program the program in which to create the block. + * @param name the name of the new block. + * @param start the starting address of the new block. + * @param base the address of the region in memory to map to. + * @param length the length of the new block + * @param comment the comment text to associate with the new block. + * @param source the source of the block (This field is not well defined - currently another comment) + * @param r the read permission for the new block. + * @param w the write permission for the new block. + * @param x the execute permission for the new block. + * @param log a {@link MessageLog} for appending error messages + * @return the new created block + */ + public static MemoryBlock createByteMappedBlock(Program program, String name, Address start, + Address base, int length, String comment, String source, boolean r, boolean w, + boolean x, MessageLog log) { + + Memory memory = program.getMemory(); + try { + + MemoryBlock block = memory.createByteMappedBlock(name, start, base, length); + + setBlockAttributes(block, comment, source, r, w, x); + adjustFragment(program, start, name); + return block; + } + catch (LockException e) { + log.appendMsg("Failed to create '" + name + + "' byte mapped memory block: exclusive lock/checkout required"); + } + catch (Exception e) { + log.appendMsg("Failed to create '" + name + "' mapped memory block: " + e.getMessage()); + } + return null; + } + + /** + * Creates a new initialized block in memory using the bytes from a {@link FileBytes} object. + * + * @param program the program in which to create the block. + * @param isOverlay if true, the block will be created in a new overlay space for that block + * @param name the name of the new block. + * @param start the starting address of the new block. + * @param fileBytes the {@link FileBytes} object that supplies the bytes for this block. + * @param offset the offset into the {@link FileBytes} object where the bytes for this block reside. + * @param length the length of the new block + * @param comment the comment text to associate with the new block. + * @param source the source of the block (This field is not well defined - currently another comment) + * @param r the read permission for the new block. + * @param w the write permission for the new block. + * @param x the execute permission for the new block. + * @param log a {@link MessageLog} for appending error messages + * @return the new created block + * @throws AddressOverflowException if the address + */ + + public static MemoryBlock createInitializedBlock(Program program, boolean isOverlay, + String name, Address start, FileBytes fileBytes, long offset, long length, + String comment, String source, boolean r, boolean w, boolean x, MessageLog log) + throws AddressOverflowException { + + if (!program.hasExclusiveAccess()) { + log.appendMsg("Failed to create memory block: exclusive access/checkout required"); + return null; + } + MemoryBlock block; + try { + block = program.getMemory().createInitializedBlock(name, start, fileBytes, offset, + length, isOverlay); + } + catch (MemoryConflictException e) { + try { + block = program.getMemory().createInitializedBlock(name, start, fileBytes, offset, + length, true); + } + catch (LockException | DuplicateNameException | MemoryConflictException e1) { + throw new RuntimeException(e); + } + } + catch (LockException | DuplicateNameException e) { + throw new RuntimeException(e); + } + + setBlockAttributes(block, comment, source, r, w, x); + adjustFragment(program, start, name); + return block; + } + + /** + * Adjusts the name of the fragment at the given address to the given name. + * @param program the program whose fragment is to be renamed. + * @param address the address of the fragment to be renamed. + * @param name the new name for the fragment. + */ + public static void adjustFragment(Program program, Address address, String name) { + Listing listing = program.getListing(); + String[] treeNames = listing.getTreeNames(); + for (String treeName : treeNames) { + try { + ProgramFragment frag = listing.getFragment(treeName, address); + frag.setName(name); + } + catch (DuplicateNameException e) { + Msg.warn(MemoryBlockUtil.class, + "Could not rename fragment to match newly created block because of name conflict"); + } + } + } + + /** + * Creates a new {@link FileBytes} object using all the bytes from a {@link ByteProvider} + * @param program the program in which to create a new FileBytes object + * @param provider the ByteProvider from which to get the bytes. + * @return the newly created FileBytes object. + * @throws IOException if an IOException occurred. + */ + public static FileBytes createFileBytes(Program program, ByteProvider provider) + throws IOException { + return createFileBytes(program, provider, 0, provider.length()); + } + + /** + * Creates a new {@link FileBytes} object using a portion of the bytes from a {@link ByteProvider} + * @param program the program in which to create a new FileBytes object + * @param provider the ByteProvider from which to get the bytes. + * @param offset the offset into the ByteProvider from which to start loading bytes. + * @param length the number of bytes to load + * @return the newly created FileBytes object. + * @throws IOException if an IOException occurred. + */ + public static FileBytes createFileBytes(Program program, ByteProvider provider, long offset, + long length) throws IOException { + Memory memory = program.getMemory(); + try (InputStream fis = provider.getInputStream(offset)) { + return memory.createFileBytes(provider.getName(), offset, length, fis); + } + } + + private static void setBlockAttributes(MemoryBlock block, String comment, String source, + boolean r, + boolean w, boolean x) { + block.setComment(comment); + block.setSourceName(source); + block.setRead(r); + block.setWrite(w); + block.setExecute(x); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/BinaryLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/BinaryLoader.java index 2dd06c60d3..068a50292f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/BinaryLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/BinaryLoader.java @@ -16,7 +16,6 @@ package ghidra.app.util.opinion; import java.io.IOException; -import java.io.InputStream; import java.util.*; import ghidra.app.util.*; @@ -25,10 +24,12 @@ import ghidra.app.util.importer.MemoryConflictHandler; import ghidra.app.util.importer.MessageLog; import ghidra.framework.model.DomainFolder; import ghidra.framework.model.DomainObject; +import ghidra.framework.store.LockException; +import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.*; import ghidra.program.model.lang.*; import ghidra.program.model.listing.Program; -import ghidra.program.model.mem.Memory; +import ghidra.program.model.mem.*; import ghidra.util.Msg; import ghidra.util.NumericUtilities; import ghidra.util.exception.CancelledException; @@ -265,8 +266,7 @@ public class BinaryLoader extends AbstractProgramLoader { @Override protected List loadProgram(ByteProvider provider, String programName, DomainFolder programFolder, LoadSpec loadSpec, List