diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/AppleSingleDoubleBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/AppleSingleDoubleBinaryAnalysisCommand.java
index 6e77bfcbe2..d0c06486d8 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/AppleSingleDoubleBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/AppleSingleDoubleBinaryAnalysisCommand.java
@@ -15,9 +15,10 @@
*/
package ghidra.app.cmd.formats;
-import java.io.IOException;
import java.util.List;
+import java.io.IOException;
+
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.util.bin.ByteProvider;
@@ -49,8 +50,8 @@ public class AppleSingleDoubleBinaryAnalysisCommand extends FlatProgramAPI
public boolean analysisWorkerCallback(Program program, Object workerContext,
TaskMonitor monitor) throws CancelledException, Exception {
try {
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
- currentProgram.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
AppleSingleDouble header = new AppleSingleDouble(provider);
Address address = toAddr(0);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffArchiveBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffArchiveBinaryAnalysisCommand.java
index c05e082d6f..93073cc677 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffArchiveBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffArchiveBinaryAnalysisCommand.java
@@ -44,8 +44,8 @@ public class CoffArchiveBinaryAnalysisCommand extends FlatProgramAPI
public boolean analysisWorkerCallback(Program program, Object workerContext,
TaskMonitor monitor) throws Exception, CancelledException {
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
- currentProgram.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
if (!CoffArchiveHeader.isMatch(provider)) {
return false;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffBinaryAnalysisCommand.java
index 61824951da..4e2f8e1932 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/CoffBinaryAnalysisCommand.java
@@ -66,9 +66,8 @@ public class CoffBinaryAnalysisCommand extends FlatProgramAPI
public boolean analysisWorkerCallback(Program program, Object workerContext,
TaskMonitor monitor) throws Exception, CancelledException {
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
- currentProgram.getAddressFactory().getDefaultAddressSpace());
-
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
CoffFileHeader header = new CoffFileHeader(provider);
if (!CoffMachineType.isMachineTypeDefined(header.getMagic())) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java
index 2bb23a25c3..7bb0256610 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java
@@ -77,8 +77,8 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
Listing listing = currentProgram.getListing();
SymbolTable symbolTable = currentProgram.getSymbolTable();
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
- currentProgram.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
try {
ElfHeader elf = new ElfHeader(provider, msg -> messages.appendMsg(msg));
elf.parse();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/MachoBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/MachoBinaryAnalysisCommand.java
index 4bd91357b4..e325c3d947 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/MachoBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/MachoBinaryAnalysisCommand.java
@@ -89,8 +89,8 @@ public class MachoBinaryAnalysisCommand extends FlatProgramAPI
BookmarkManager bookmarkManager = program.getBookmarkManager();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
try {
MachHeader header =
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PefBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PefBinaryAnalysisCommand.java
index c434147d76..5c7f93fee2 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PefBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PefBinaryAnalysisCommand.java
@@ -15,6 +15,10 @@
*/
package ghidra.app.cmd.formats;
+import java.util.List;
+
+import java.io.IOException;
+
import ghidra.app.cmd.data.CreateStringCmd;
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
@@ -32,9 +36,6 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
-import java.io.IOException;
-import java.util.List;
-
public class PefBinaryAnalysisCommand extends FlatProgramAPI implements BinaryAnalysisCommand,
AnalysisWorker {
private MessageLog messages = new MessageLog();
@@ -47,8 +48,7 @@ public class PefBinaryAnalysisCommand extends FlatProgramAPI implements BinaryAn
public boolean canApply(Program program) {
try {
ByteProvider provider =
- new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
new ContainerHeader(provider);
return true;
}
@@ -61,8 +61,7 @@ public class PefBinaryAnalysisCommand extends FlatProgramAPI implements BinaryAn
public boolean analysisWorkerCallback(Program program, Object workerContext, TaskMonitor monitor)
throws Exception, CancelledException {
ByteProvider provider =
- new MemoryByteProvider(currentProgram.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
try {
ContainerHeader header = new ContainerHeader(provider);
header.parse();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PortableExecutableBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PortableExecutableBinaryAnalysisCommand.java
index 230910c58f..072bf8cf3d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PortableExecutableBinaryAnalysisCommand.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/PortableExecutableBinaryAnalysisCommand.java
@@ -15,9 +15,10 @@
*/
package ghidra.app.cmd.formats;
-import java.io.IOException;
import java.util.List;
+import java.io.IOException;
+
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.util.bin.*;
@@ -32,7 +33,6 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
-import ghidra.program.model.mem.Memory;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
@@ -48,11 +48,8 @@ public class PortableExecutableBinaryAnalysisCommand extends FlatProgramAPI
@Override
public boolean canApply(Program program) {
try {
- Memory memory = program.getMemory();
-
- ByteProvider provider = new MemoryByteProvider(memory,
- program.getAddressFactory().getDefaultAddressSpace());
-
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
DOSHeader dosHeader = new DOSHeader(reader);
@@ -75,8 +72,8 @@ public class PortableExecutableBinaryAnalysisCommand extends FlatProgramAPI
public boolean analysisWorkerCallback(Program program, Object workerContext,
TaskMonitor monitor) throws Exception, CancelledException {
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
PortableExecutable pe = new PortableExecutable(provider, SectionLayout.FILE);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DwarfLineNumberAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DwarfLineNumberAnalyzer.java
index 66beaa74b5..9a124586f9 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DwarfLineNumberAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DwarfLineNumberAnalyzer.java
@@ -15,9 +15,10 @@
*/
package ghidra.app.plugin.core.analysis;
+import java.util.List;
+
import java.io.File;
import java.io.IOException;
-import java.util.List;
import ghidra.app.services.*;
import ghidra.app.util.bin.*;
@@ -46,6 +47,7 @@ public class DwarfLineNumberAnalyzer extends AbstractAnalyzer {
setSupportsOneTimeAnalysis();
}
+ @Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
@@ -59,7 +61,7 @@ public class DwarfLineNumberAnalyzer extends AbstractAnalyzer {
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
- while (!monitor.isCancelled() && reader.getPointerIndex() < provider.length()) {
+ while (!monitor.isCancelled() && reader.hasNext()) {
long startIndex = reader.getPointerIndex();
StatementProgramPrologue prologue = new StatementProgramPrologue(reader);
@@ -134,10 +136,9 @@ public class DwarfLineNumberAnalyzer extends AbstractAnalyzer {
else if (ElfLoader.ELF_NAME.equals(program.getExecutableFormat())) {
// We now load the .debug section as an overlay block, no need for the
// original file
- MemoryBlock block = null;
- block = program.getMemory().getBlock(sectionNames.SECTION_NAME_LINE());
+ MemoryBlock block = program.getMemory().getBlock(sectionNames.SECTION_NAME_LINE());
if (block != null) {
- return new MemoryByteProvider(program.getMemory(), block.getStart());
+ return MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), block);
}
// TODO: this will not handle the case where the .debug section is
// in a separate file. Can the file in a separate location?
@@ -147,6 +148,7 @@ public class DwarfLineNumberAnalyzer extends AbstractAnalyzer {
program.getExecutableFormat());
}
+ @Override
public boolean canAnalyze(Program program) {
return isElfOrMacho(program);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC1_ClassAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC1_ClassAnalyzer.java
index 17126e8f34..3cbb09be1a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC1_ClassAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC1_ClassAnalyzer.java
@@ -15,6 +15,11 @@
*/
package ghidra.app.plugin.core.analysis;
+import java.util.ArrayList;
+import java.util.List;
+
+import java.io.IOException;
+
import ghidra.app.services.*;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.MemoryByteProvider;
@@ -28,10 +33,6 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
public class ObjectiveC1_ClassAnalyzer extends AbstractAnalyzer {
private static final String DESCRIPTION =
"An analyzer for extracting Objective-C class structure information.";
@@ -46,13 +47,12 @@ public class ObjectiveC1_ClassAnalyzer extends AbstractAnalyzer {
setDefaultEnablement(true);
}
+ @Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
MemoryByteProvider provider =
- new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
-
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
ObjectiveC1_State state =
@@ -94,6 +94,7 @@ public class ObjectiveC1_ClassAnalyzer extends AbstractAnalyzer {
}
}
+ @Override
public boolean canAnalyze(Program program) {
return ObjectiveC1_Constants.isObjectiveC(program);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_ClassAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_ClassAnalyzer.java
index b5058dbf59..c9f146ffdb 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_ClassAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_ClassAnalyzer.java
@@ -15,9 +15,10 @@
*/
package ghidra.app.plugin.core.analysis;
-import java.io.IOException;
import java.util.*;
+import java.io.IOException;
+
import ghidra.app.services.*;
import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.macho.dyld.LibObjcOptimization;
@@ -67,8 +68,8 @@ public class ObjectiveC2_ClassAnalyzer extends AbstractAnalyzer {
ObjectiveC2_State state =
new ObjectiveC2_State(program, monitor, ObjectiveC2_Constants.CATEGORY_PATH);
- try (ByteProvider provider = new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace())) {
+ try (ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false)) {
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
// Create a map of Objective-C specific memory blocks. If this is a dyld_shared_cache
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/BinaryReader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/BinaryReader.java
index 6fbb274823..5867d96645 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/BinaryReader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/BinaryReader.java
@@ -28,6 +28,12 @@ import ghidra.util.*;
*
*/
public class BinaryReader {
+
+ // jvm's will typically refuse to allocate arrays that are exactly Integer.MAX_VALUE.
+ // This is a conservative stab at a max array element count since we don't have a requirement
+ // to reach exactly 2g elements
+ private static final int MAX_SANE_BUFFER = Integer.MAX_VALUE - 1024;
+
/**
* The size of a BYTE in Java.
*/
@@ -66,7 +72,7 @@ public class BinaryReader {
public BinaryReader(ByteProvider provider, boolean isLittleEndian) {
this(provider, DataConverter.getInstance(!isLittleEndian), 0);
}
-
+
/**
* Creates a BinaryReader instance.
*
@@ -147,6 +153,7 @@ public class BinaryReader {
/**
* Returns the length of the underlying file.
+ *
* @return returns the length of the underlying file
* @exception IOException if an I/O error occurs
*/
@@ -155,18 +162,19 @@ public class BinaryReader {
}
/**
- * Returns true if the specified index into
- * the underlying byte provider is valid.
- * @param index the index in the byte provider
+ * Returns true if the specified unsigned int32 index into the underlying byte provider is
+ * valid.
+ *
+ * @param index an integer that is treated as an unsigned int32 index into the byte provider
* @return returns true if the specified index is valid
*/
public boolean isValidIndex(int index) {
- return provider.isValidIndex(index & Conv.INT_MASK);
+ return provider.isValidIndex(Integer.toUnsignedLong(index));
}
/**
- * Returns true if the specified index into
- * the underlying byte provider is valid.
+ * Returns true if the specified index into the underlying byte provider is valid.
+ *
* @param index the index in the byte provider
* @return returns true if the specified index is valid
*/
@@ -175,19 +183,75 @@ public class BinaryReader {
}
/**
- * Aligns the current index on the specified alignment value.
- * For example, if current index was 123 and align value was
- * 16, then current index would become 128.
+ * Returns true if the specified range is valid and does not wrap around the end of the
+ * index space.
+ *
+ * @param startIndex the starting index to check, treated as an unsigned int64
+ * @param count the number of bytes to check
+ * @return boolean true if all bytes between startIndex to startIndex+count (exclusive) are
+ * valid (according to the underlying byte provider)
+ */
+ public boolean isValidRange(long startIndex, int count) {
+ if (count < 0) {
+ return false;
+ }
+ if (count > 1) {
+ // check the end of the range first to fail fast
+
+ long endIndex = startIndex + (count - 1);
+ if (Long.compareUnsigned(endIndex, startIndex) < 0) {
+ // the requested range [startIndex..startIndex+count] wraps around the int64 to 0, so fail
+ return false;
+ }
+
+ if (!provider.isValidIndex(endIndex)) {
+ return false;
+ }
+ count--; // don't check the last element twice
+ }
+ for (int i = 0; i < count; i++) {
+ if (!provider.isValidIndex(startIndex + i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if this stream has data that could be read at the current position.
+ *
+ * @return true if there are more bytes that could be read at the
+ * {@link #getPointerIndex() current index}.
+ */
+ public boolean hasNext() {
+ return provider.isValidIndex(currentIndex);
+ }
+
+ /**
+ * Returns true if this stream has data that could be read at the current position.
+ *
+ * @param count number of bytes to verify
+ * @return true if there are at least count more bytes that could be read at the
+ * {@link #getPointerIndex() current index}.
+ */
+ public boolean hasNext(int count) {
+ return isValidRange(currentIndex, count);
+ }
+
+ /**
+ * Advances the current index so that it aligns to the specified value (if not already
+ * aligned).
+ *
+ * For example, if current index was 123 and align value was 16, then current index would
+ * be advanced to 128.
+ *
* @param alignValue
- * @return the number of bytes required to align
+ * @return the number of bytes required to align (0..alignValue-1)
*/
public int align(int alignValue) {
- long align = currentIndex % alignValue;
- if (align == 0) {
- return 0;
- }
- currentIndex = currentIndex + (alignValue - align);
- return (int) (alignValue - align);
+ long prevIndex = currentIndex;
+ currentIndex = NumericUtilities.getUnsignedAlignedValue(currentIndex, alignValue);
+ return (int) (currentIndex - prevIndex);
}
////////////////////////////////////////////////////////////////////
@@ -279,7 +343,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public int readNextUnsignedByte() throws IOException {
- return readNextByte() & NumberUtil.UNSIGNED_BYTE_MASK;
+ return Byte.toUnsignedInt(readNextByte());
}
/**
@@ -301,7 +365,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public int readNextUnsignedShort() throws IOException {
- return readNextShort() & NumberUtil.UNSIGNED_SHORT_MASK;
+ return Short.toUnsignedInt(readNextShort());
}
/**
@@ -323,7 +387,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public long readNextUnsignedInt() throws IOException {
- return readNextInt() & NumberUtil.UNSIGNED_INT_MASK;
+ return Integer.toUnsignedLong(readNextInt());
}
/**
@@ -463,7 +527,6 @@ public class BinaryReader {
return result;
}
-
/**
* Reads a byte array of nElements
* starting at the current index and then increments the current
@@ -520,20 +583,33 @@ public class BinaryReader {
// String stuff
//--------------------------------------------------------------------------------------------
private byte[] readUntilNullTerm(long index, int charLen) throws IOException {
- long maxPos = provider.length() - charLen;
- if (index > maxPos) {
- throw new EOFException(String.format("Attempted to read string at 0x%x", index));
- }
- long curPos = index;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (; curPos <= maxPos; curPos += charLen) {
- byte[] bytes = readByteArray(curPos, charLen);
- if (isNullTerm(bytes, 0, charLen)) {
- return baos.toByteArray();
+ long curPos = index;
+ for (; Long.compareUnsigned(curPos, index) >= 0; curPos += charLen) {
+ // loop while we haven't wrapped the index value around to 0
+ if ((long) baos.size() + charLen >= MAX_SANE_BUFFER) {
+ // gracefully handle hitting the limit of the ByteArrayOutputStream before it fails
+ throw new EOFException("Run-on unterminated string at 0x%s..0x%s".formatted(
+ Long.toUnsignedString(index, 16), Long.toUnsignedString(curPos, 16)));
+ }
+ try {
+ byte[] bytes = readByteArray(curPos, charLen);
+ if (isNullTerm(bytes, 0, charLen)) {
+ return baos.toByteArray();
+ }
+ baos.write(bytes);
+ }
+ catch (IOException e) {
+ if (baos.size() == 0) {
+ // failed trying to read the first byte
+ throw new EOFException("Attempted to read string at 0x%s"
+ .formatted(Long.toUnsignedString(index, 16)));
+ }
+ break; // fall thru to throw new EOF(unterminate string)
}
- baos.write(bytes);
}
- throw new EOFException(String.format("Unterminated string at 0x%x..0x%x", index, curPos));
+ throw new EOFException("Unterminated string at 0x%s..0x%s"
+ .formatted(Long.toUnsignedString(index, 16), Long.toUnsignedString(curPos, 16)));
}
private boolean isNullTerm(byte[] bytes, int offset, int charLen) {
@@ -711,7 +787,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public int readUnsignedByte(long index) throws IOException {
- return readByte(index) & NumberUtil.UNSIGNED_BYTE_MASK;
+ return Byte.toUnsignedInt(readByte(index));
}
/**
@@ -732,7 +808,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public int readUnsignedShort(long index) throws IOException {
- return readShort(index) & NumberUtil.UNSIGNED_SHORT_MASK;
+ return Short.toUnsignedInt(readShort(index));
}
/**
@@ -753,7 +829,7 @@ public class BinaryReader {
* @exception IOException if an I/O error occurs
*/
public long readUnsignedInt(long index) throws IOException {
- return readInt(index) & NumberUtil.UNSIGNED_INT_MASK;
+ return Integer.toUnsignedLong(readInt(index));
}
/**
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/ByteProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/ByteProvider.java
index b871e35dd9..0e41572d2c 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/ByteProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/ByteProvider.java
@@ -74,6 +74,20 @@ public interface ByteProvider extends Closeable {
*/
public long length() throws IOException;
+ /**
+ * Returns true if this ByteProvider does not contain any bytes.
+ *
+ * @return boolean true if this provider is empty, false if contains bytes
+ */
+ default public boolean isEmpty() {
+ try {
+ return length() == 0;
+ }
+ catch (IOException e) {
+ return true;
+ }
+ }
+
/**
* Returns true if the specified index is valid.
*
@@ -127,4 +141,5 @@ public interface ByteProvider extends Closeable {
}
return new ByteProviderInputStream(this, index);
}
+
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/EmptyByteProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/EmptyByteProvider.java
index a45fbd58a5..266c837a72 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/EmptyByteProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/EmptyByteProvider.java
@@ -81,6 +81,11 @@ public class EmptyByteProvider implements ByteProvider {
return 0;
}
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
@Override
public boolean isValidIndex(long index) {
return false;
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 10023800e2..a4794fe773 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
@@ -18,11 +18,37 @@ package ghidra.app.util.bin;
import java.io.*;
import ghidra.program.model.address.*;
+import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
/**
* A {@link ByteProvider} implementation based on {@link Memory}.
+ *
+ * The bytes returned by this provider are indexed relative to the {@code baseAddress}
+ * supplied to the constructor, and are limited to {@link MemoryBlock memory blocks} of the
+ * same address space.
+ *
+ * Warnings:
+ *
+ * Using this ByteProvider with memory block/address spaces that are not simple "ram" initialized
+ * memory blocks is fraught with peril.
+ *
+ * Addresses and address spaces can use all 64 bits of a {@code long} as an offset, which
+ * causes a problem when trying to express the correct {@link #length()} of this ByteProvider as
+ * a long. (this is why address ranges deal with inclusive end values instead of exclusive).
+ *
+ * - The return value of {@link #length()} is constrained to a max of Long.MAX_VALUE
+ * - {@link #isValidIndex(long)} treats its argument as an unsigned int64, and works
+ * for the entire address space range.
+ *
+ *
+ * Not all byte provider index locations between 0 and {@link #length()} will be valid
+ * (because gaps between memory blocks), and may generate exceptions when those locations are read.
+ *
+ * - To avoid this situation, the caller will need to use information from the program's Memory
+ * manager to align reads to valid locations.
+ *
*/
public class MemoryByteProvider implements ByteProvider {
@@ -33,54 +59,149 @@ public class MemoryByteProvider implements ByteProvider {
* @param block {@link MemoryBlock} to read from
* @return new {@link ByteProvider} that contains the bytes of the specified MemoryBlock
*/
- public static ByteProvider createMemoryBlockByteProvider(Memory memory, MemoryBlock block) {
- long blockLen = block.getEnd().subtract(block.getStart()) + 1;
- ByteProvider bp = new MemoryByteProvider(memory, block.getStart());
- return new ByteProviderWrapper(bp, 0, blockLen);
+ public static MemoryByteProvider createMemoryBlockByteProvider(Memory memory,
+ MemoryBlock block) {
+ return new MemoryByteProvider(memory, block.getStart(), block.getEnd());
+ }
+
+ /**
+ * Create a {@link ByteProvider} that starts at the beginning of the specified
+ * {@link Program program's} memory, containing either just the first
+ * memory block, or all memory blocks (of the same address space).
+ *
+ * @param program {@link Program} to read
+ * @param firstBlockOnly boolean flag, if true, only the first memory block will be accessible
+ * via the returned provider, if false, all memory blocks of the address space will be accessible
+ * @return new {@link MemoryByteProvider}, starting at program's minAddress
+ */
+ public static MemoryByteProvider createProgramHeaderByteProvider(Program program,
+ boolean firstBlockOnly) {
+ return new MemoryByteProvider(program.getMemory(), program.getMinAddress(), firstBlockOnly);
+ }
+
+ /**
+ * Create a {@link ByteProvider} that starts at the beginning (e.g. 0) of the specified
+ * {@link Program program's} default address space memory, containing either the first memory
+ * block, or all memory blocks (of the same address space).
+ *
+ * @param program {@link Program} to read
+ * @param firstBlockOnly boolean flag, if true, only the first memory block will be accessible
+ * via the returned provider, if false, all memory blocks of the address space will be accessible
+ * @return new {@link MemoryByteProvider}, starting at program's minAddress
+ */
+ public static MemoryByteProvider createDefaultAddressSpaceByteProvider(Program program,
+ boolean firstBlockOnly) {
+ return new MemoryByteProvider(program.getMemory(),
+ program.getAddressFactory().getDefaultAddressSpace().getMinAddress(), firstBlockOnly);
}
protected Memory memory;
protected Address baseAddress;
+ protected long maxOffset; // max valid offset, inclusive
+ protected boolean isEmtpy; // empty is tracked separately because maxOffset == 0 does not mean empty
/**
- * Constructs a new {@link MemoryByteProvider} for a specific {@link AddressSpace}. Bytes will be
- * provided starting at address 0 in the space.
+ * Constructs a new {@link MemoryByteProvider} for a specific {@link AddressSpace}. Bytes
+ * will be provided relative to the minimum address (typically 0) in the space, and ranges
+ * to the highest address in the same address space currently found in the memory map.
+ *
+ *
*
* @param memory the {@link Memory}
* @param space the {@link AddressSpace}
*/
public MemoryByteProvider(Memory memory, AddressSpace space) {
- this(memory, space.getAddress(0));
+ this(memory, space.getMinAddress());
}
/**
- * Constructs a new {@link MemoryByteProvider} relative to the specified base address.
+ * Constructs a new {@link MemoryByteProvider} relative to the specified base address,
+ * containing the address range to the highest address in the same address space currently
+ * found in the memory map.
*
* @param memory the {@link Memory}
* @param baseAddress the base address
*/
public MemoryByteProvider(Memory memory, Address baseAddress) {
- this.memory = memory;
- this.baseAddress = baseAddress;
+ this(memory, baseAddress, false);
}
/**
- * Converts an index into this ByteProvider into an {@link Address}.
- *
+ * Constructs a new {@link MemoryByteProvider} relative to the specified base address,
+ * containing the address range to the end of the first memory block, or the highest address
+ * in the same address space, currently found in the memory map.
*
- * @param index absolute index in this ByteProvider to convert into an Address
- * @return {@link Address}
- * @throws AddressOutOfBoundsException if wrapping is not supported by the
- * corresponding address space and the addition causes an out-of-bounds
- * error
+ * @param memory the {@link Memory}
+ * @param baseAddress the base address
+ * @param firstBlockOnly boolean flag, if true, only the first memory block will be accessible,
+ * if false, all memory blocks of the address space will be accessible
*/
- public Address getAddress(long index) {
- return baseAddress.add(index);
+ public MemoryByteProvider(Memory memory, Address baseAddress, boolean firstBlockOnly) {
+ this(memory, baseAddress, firstBlockOnly
+ ? findEndOfBlock(memory, baseAddress)
+ : findAddressSpaceMax(memory, baseAddress));
+ }
+
+ /**
+ * Constructs a new {@link MemoryByteProvider} relative to the specified base address, with
+ * the specified length.
+ *
+ * @param memory the {@link Memory}
+ * @param baseAddress the base address
+ * @param maxAddress the highest address accessible by this provider (inclusive), or null
+ * if there is no memory
+ */
+ private MemoryByteProvider(Memory memory, Address baseAddress, Address maxAddress) {
+ this.memory = memory;
+ this.baseAddress = baseAddress;
+ this.maxOffset = maxAddress != null
+ ? maxAddress.subtract(baseAddress)
+ : 0;
+ this.isEmtpy = maxAddress == null;
+ }
+
+ private Address getAddress(long index) throws IOException {
+ if (index == 0) {
+ return baseAddress;
+ }
+ long base = baseAddress.getOffset();
+ long newAddress = base + index;
+ if (Long.compareUnsigned(base, newAddress) > 0) {
+ throw new IOException("Invalid index: %s".formatted(Long.toUnsignedString(index)));
+ }
+ return baseAddress.getNewAddress(newAddress);
+ }
+
+ /**
+ * Returns the address of the first byte of this provider.
+ *
+ * @return address of the first byte returned by this provider (at index 0)
+ */
+ public Address getStartAddress() {
+ return baseAddress;
+ }
+
+ /**
+ * Returns the address of the last byte of this provider.
+ *
+ * @return address of the last byte returned by this provider
+ */
+ public Address getEndAddress() {
+ return baseAddress.getNewAddress(baseAddress.getOffset() + maxOffset);
+ }
+
+ /**
+ * Returns the address range of the bytes of this provider.
+ *
+ * @return address range of first byte to last byte of this provider
+ */
+ public AddressSetView getAddressSet() {
+ return new AddressSet(baseAddress, getEndAddress());
}
@Override
- public InputStream getInputStream(long index) throws IOException {
- return new MemoryByteProviderInputStream(memory, baseAddress.add(index));
+ public boolean isEmpty() {
+ return isEmtpy;
}
@Override
@@ -100,28 +221,36 @@ public class MemoryByteProvider implements ByteProvider {
@Override
public long length() throws IOException {
- MemoryBlock block = memory.getBlock(baseAddress);
- if (block == null || !block.isInitialized()) {
+ if (isEmtpy) {
return 0;
}
- return block.getEnd().subtract(baseAddress) + 1;
+
+ // clamp the max length to Long.MAX_VALUE
+ return Long.compareUnsigned(maxOffset, Long.MAX_VALUE - 1) >= 0
+ ? Long.MAX_VALUE
+ : maxOffset + 1;
}
@Override
public boolean isValidIndex(long index) {
+ // this method treats the index as an unsigned int64, and will give accurate results
+ // for the entire range of the underlying AddressSpace
try {
- Address indexAddress = baseAddress.add(index);
- return memory.contains(indexAddress);
+ if (isEmtpy || Long.compareUnsigned(index, maxOffset) > 0) {
+ return false;
+ }
+ return memory.contains(getAddress(index));
}
- catch (AddressOutOfBoundsException e) {
+ catch (IOException | AddressOutOfBoundsException e) {
return false;
}
}
@Override
public byte readByte(long index) throws IOException {
+ ensureBounds(index, 1);
try {
- return memory.getByte(baseAddress.add(index));
+ return memory.getByte(getAddress(index));
}
catch (Exception e) {
throw new IOException(e.getMessage());
@@ -130,11 +259,13 @@ public class MemoryByteProvider implements ByteProvider {
@Override
public byte[] readBytes(long index, long length) throws IOException {
+ ensureBounds(index, length);
try {
byte[] bytes = new byte[(int) length];
- int nRead = memory.getBytes(baseAddress.add(index), bytes);
+ int nRead = memory.getBytes(getAddress(index), bytes);
if (nRead != length) {
- throw new IOException("Unable to read " + length + " bytes at index " + index);
+ throw new IOException("Unable to read %d bytes at index %s".formatted(length,
+ Long.toUnsignedString(index)));
}
return bytes;
}
@@ -150,4 +281,70 @@ public class MemoryByteProvider implements ByteProvider {
public void close() {
// don't do anything for now
}
+
+ //--------------------------------------------------------------------------------------------
+ private void ensureBounds(long index, long length) throws IOException {
+ // ensure length is valid
+ if (length < 0 || length > Integer.MAX_VALUE) {
+ throw new IOException(
+ "Unable to read more than Integer.MAX_VALUE bytes in one operation: %s"
+ .formatted(Long.toUnsignedString(length)));
+ }
+ if (index == 0 && length == 0) {
+ return; // success for read of 0 bytes at offset 0
+ }
+
+ // ensure read start index is valid
+ if (isEmtpy || Long.compareUnsigned(index, maxOffset) > 0) {
+ throw new EOFException("Invalid index: %s".formatted(Long.toUnsignedString(index)));
+ }
+
+ // NOTE: there should be a +1 on "remaining" to accurately model the count of remaining bytes
+ // Because it could cause an overflow, adjust "length" by -1 instead
+ long remaining = maxOffset - index /* + 1 -> becomes length - 1 */;
+
+ // ensure length of read is within bounds
+ if (length != 0 && Long.compareUnsigned(length - 1, remaining) > 0) {
+ throw new EOFException(
+ "Unable to read past EOF: %s, %d".formatted(Long.toUnsignedString(index), length));
+ }
+ }
+
+ private static Address findEndOfBlock(Memory memory, Address minAddr) {
+ MemoryBlock block = memory.getBlock(minAddr);
+ if (block != null) {
+ // address was inside a block, return it's end
+ return block.getEnd();
+ }
+
+ // address was outside all blocks. try to find a block that contains it and return its end
+ AddressSpace space = minAddr.getAddressSpace();
+ for (MemoryBlock block2 : memory.getBlocks()) {
+ Address end = block2.getEnd();
+ if (end.getAddressSpace().equals(space) && end.compareTo(minAddr) >= 0) {
+ return end;
+ }
+ }
+ return null;
+ }
+
+ private static Address findAddressSpaceMax(Memory memory, Address minAddr) {
+ if (minAddr == null) {
+ return null;
+ }
+ AddressSpace space = minAddr.getAddressSpace();
+ Address maxAddr = null;
+ for (AddressRange range : memory.getAddressRanges()) {
+ if (!range.getAddressSpace().equals(space)) {
+ continue;
+ }
+ Address rangeEnd = range.getMaxAddress();
+ if (rangeEnd.compareTo(minAddr) >= 0 &&
+ (maxAddr == null || rangeEnd.compareTo(maxAddr) >= 0)) {
+ maxAddr = rangeEnd;
+ }
+ }
+ return maxAddr;
+ }
+
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProviderInputStream.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProviderInputStream.java
deleted file mode 100644
index 8796e9f6aa..0000000000
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProviderInputStream.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/* ###
- * IP: GHIDRA
- * REVIEWED: YES
- *
- * 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.bin;
-
-import ghidra.program.model.address.Address;
-import ghidra.program.model.mem.Memory;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-class MemoryByteProviderInputStream extends InputStream {
- private Memory memory;
- private Address startAddress;
- private Address address;
-
- MemoryByteProviderInputStream(Memory memory, Address address) {
- this.memory = memory;
- this.startAddress = address;
- this.address = address;
- }
-
- @Override
- public int read() throws IOException {
- try {
- byte b = memory.getByte(address);
- address = address.add(1);
- return b & 0xff;
- }
- catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- }
-
- @Override
- public int read(byte [] b, int off, int len) throws IOException {
- try {
- int nRead = memory.getBytes(address, b, off, len);
- address = address.add(len);
- return nRead;
- }
- catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- }
-
- @Override
- public int available() throws IOException {
- return (int)memory.getMaxAddress().subtract(address);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- address = startAddress;
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- memory = null;
- address = null;
- }
-}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java
index 9c7d7a46d5..63fa871324 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java
@@ -849,7 +849,7 @@ public class DIEAggregate {
? getCompilationUnit().getCompileUnit().getLowPC().longValue()
: 0L;
- while (reader.getPointerIndex() < reader.length()) {
+ while (reader.hasNext()) {
// Read the beginning and ending addresses
Number beginning = DWARFUtil.readAddress(reader, pointerSize);
Number ending = DWARFUtil.readAddress(reader, pointerSize); // dwarf end addrs are exclusive
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java
index f0d0ee8b70..497fe9a9cd 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DWARFCompilationUnit.java
@@ -15,9 +15,10 @@
*/
package ghidra.app.util.bin.format.dwarf4;
-import java.io.IOException;
import java.util.*;
+import java.io.IOException;
+
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.dwarf4.DWARFUtil.LengthResult;
import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram;
@@ -195,7 +196,7 @@ public class DWARFCompilationUnit {
private static boolean isAllZerosUntilEOF(BinaryReader reader) throws IOException {
reader = reader.clone();
- while (reader.getPointerIndex() < reader.length()) {
+ while (reader.hasNext()) {
if (reader.readNextByte() != 0) {
return false;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java
index 3b27cfa59c..7dc220501f 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java
@@ -31,8 +31,6 @@ import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException;
import ghidra.app.util.bin.format.dwarf4.external.ExternalDebugInfo;
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.*;
import ghidra.app.util.opinion.*;
-import ghidra.program.model.address.Address;
-import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
@@ -289,12 +287,8 @@ public class DWARFProgram implements Closeable {
return false;
}
ByteProvider bp = br.getByteProvider();
- if (bp instanceof MemoryByteProvider && bp.length() > 0) {
- MemoryByteProvider mbp = (MemoryByteProvider) bp;
- Address startAddr = mbp.getAddress(0);
- Address endAddr = mbp.getAddress(mbp.length() - 1);
- if (program.getRelocationTable().getRelocations(
- new AddressSet(startAddr, endAddr)).hasNext()) {
+ if (bp instanceof MemoryByteProvider mbp && !mbp.isEmpty()) {
+ if (program.getRelocationTable().getRelocations(mbp.getAddressSet()).hasNext()) {
return true;
}
}
@@ -584,7 +578,7 @@ public class DWARFProgram implements Closeable {
BinaryReader br = debugInfoBR;
br.setPointerIndex(0);
- while (br.getPointerIndex() < br.getByteProvider().length()) {
+ while (br.hasNext()) {
monitor.checkCanceled();
monitor.setMessage("Bootstrapping DWARF Compilation Unit #" + compUnits.size());
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macos/rm/ResourceMap.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macos/rm/ResourceMap.java
index afbffa40e3..03eea1a149 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macos/rm/ResourceMap.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macos/rm/ResourceMap.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,13 +15,14 @@
*/
package ghidra.app.util.bin.format.macos.rm;
+import java.util.*;
+
+import java.io.IOException;
+
import ghidra.app.util.bin.*;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
-import java.io.IOException;
-import java.util.*;
-
public class ResourceMap implements StructConverter {
private ResourceHeader copy;
private int handleToNextResourceMap;
@@ -70,7 +70,7 @@ public class ResourceMap implements StructConverter {
private void parseResourceNameList(BinaryReader reader) throws IOException {
long start = _mapStartIndex + resourceNameListOffset;
reader.setPointerIndex(_mapStartIndex + resourceNameListOffset);
- while (reader.getPointerIndex() < reader.length()) {
+ while (reader.hasNext()) {
long offset = reader.getPointerIndex();
int length = reader.readNextByte() & 0xff;
String name = reader.readNextAsciiString(length);
@@ -125,6 +125,7 @@ public class ResourceMap implements StructConverter {
return _mapStartIndex;
}
+ @Override
public DataType toDataType() throws DuplicateNameException, IOException {
return StructConverterUtil.toDataType(ResourceMap.class);
}
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/bin/MemoryByteProviderTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/bin/MemoryByteProviderTest.java
new file mode 100644
index 0000000000..3d5fef9d96
--- /dev/null
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/bin/MemoryByteProviderTest.java
@@ -0,0 +1,240 @@
+/* ###
+ * 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.bin;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.*;
+
+import ghidra.program.database.ProgramBuilder;
+import ghidra.program.database.ProgramDB;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.address.AddressSpace;
+import ghidra.program.model.mem.Memory;
+import ghidra.program.model.mem.MemoryBlock;
+import ghidra.test.AbstractGhidraHeadedIntegrationTest;
+import ghidra.util.task.TaskMonitor;
+
+public class MemoryByteProviderTest extends AbstractGhidraHeadedIntegrationTest {
+ protected ProgramDB program;
+ protected AddressSpace space;
+ protected Memory memory;
+ protected TaskMonitor monitor = TaskMonitor.DUMMY;
+ private ProgramBuilder builder;
+
+ @Before
+ public void setUp() throws Exception {
+ builder = new ProgramBuilder(testName.getMethodName(), ProgramBuilder._X64, this);
+ program = builder.getProgram();
+ memory = program.getMemory();
+ space = program.getAddressFactory().getDefaultAddressSpace();
+ }
+
+ protected Address addr(long l) {
+ return space.getAddress(l);
+ }
+
+ private void setBlockStartEndBytes(MemoryBlock memblk, String start, String end)
+ throws Exception {
+ builder.setBytes(memblk.getStart().toString(true),
+ start.getBytes(StandardCharsets.US_ASCII));
+ byte[] endBytes = end.getBytes(StandardCharsets.US_ASCII);
+ builder.setBytes(memblk.getEnd().subtract(endBytes.length - 1).toString(true), endBytes);
+ }
+
+ private MemoryBlock addRam0() throws Exception {
+ MemoryBlock memblk = builder.createMemory(space.getName(), "0", 0x50);
+ setBlockStartEndBytes(memblk, "startram0\0", "endram0\0");
+ return memblk;
+ }
+
+ private MemoryBlock addRam1() throws Exception {
+ MemoryBlock memblk = builder.createMemory(space.getName(), "50", 0x50);
+ setBlockStartEndBytes(memblk, "startram1\0", "endram1\0");
+ return memblk;
+ }
+
+ private MemoryBlock addRam2() throws Exception {
+ MemoryBlock memblk = builder.createMemory(space.getName(), "a0", 0x50);
+ setBlockStartEndBytes(memblk, "startram2\0", "endram2\0");
+ return memblk;
+ }
+
+ private MemoryBlock addRamEnd() throws Exception {
+ MemoryBlock memblk = builder.createMemory(space.getName(), "ffffffffffffffb0", 0x50);
+ setBlockStartEndBytes(memblk, "highstart\0", "highend\0");
+ return memblk;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ builder.dispose();
+ }
+
+ @Test
+ public void testNoMemory() throws IOException {
+ MemoryByteProvider mbp = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+ assertEquals(0, mbp.length());
+
+ mbp = MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ assertEquals(0, mbp.length());
+ }
+
+ @Test
+ public void testCreateProgramHeader_Offset() throws Exception {
+ addRam1();
+ MemoryByteProvider mbp = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(0x50, mbp.length());
+ assertEquals("startram1", reader.readAsciiString(0));
+ }
+
+ @Test
+ public void testCreateDefaultAddressSpace_Offset() throws Exception {
+ addRam1();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(0x50 + 0x50, mbp.length());
+ assertEquals("startram1", reader.readAsciiString(0x50));
+ }
+
+ @Test
+ public void testMinAddrNotInBlock() throws Exception {
+ addRam1();
+ MemoryByteProvider mbp = new MemoryByteProvider(memory, addr(1));
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(0x50 + 0x50 - 1, mbp.length());
+ assertEquals("startram1", reader.readAsciiString(0x50 - 1));
+ }
+
+ @Test
+ public void testMinAddrInBlock() throws Exception {
+ addRam1();
+ MemoryByteProvider mbp = new MemoryByteProvider(memory, addr(0x51));
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(0x50 - 1, mbp.length());
+ assertEquals(/* missing 's' */ "tartram1", reader.readAsciiString(0));
+ }
+
+ @Test
+ public void testMinAddrAfterBlock() throws Exception {
+ addRam1();
+ MemoryByteProvider mbp = new MemoryByteProvider(memory, addr(0x5000));
+
+ assertEquals(0, mbp.length());
+ }
+
+ @Test
+ public void testMultiblock_adjacent() throws Exception {
+ MemoryBlock blk1 = addRam1();
+ MemoryBlock blk2 = addRam2();
+ setBlockStartEndBytes(blk1, "blah", "aaaa");
+ setBlockStartEndBytes(blk2, "bbbb", "blah");
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(blk2.getEnd().getOffset() - blk1.getStart().getOffset() + 1, mbp.length());
+ assertEquals(0x61616161, reader.readInt(0x50 - 4));
+ assertEquals(0x62626262, reader.readInt(0x50));
+ assertEquals(0x62626161, reader.readInt(0x50 - 2));
+ }
+
+ @Test
+ public void testMultiblockLength_disjoint() throws Exception {
+ MemoryBlock blk0 = addRam0();
+ MemoryBlock blk2 = addRam2();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+
+ assertEquals(blk2.getEnd().getOffset() - blk0.getStart().getOffset() + 1, mbp.length());
+ }
+
+ @Test
+ public void testLength_block_at_end_of_64bits() throws Exception {
+ MemoryBlock blk = addRamEnd();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+
+ assertEquals(blk.getEnd().getOffset() - blk.getStart().getOffset() + 1, mbp.length());
+ }
+
+ @Test
+ public void testLength_all64bits() throws Exception {
+ addRam0();
+ addRamEnd();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+
+ assertEquals(Long.MAX_VALUE, mbp.length());
+ }
+
+ @Test
+ public void testFull64bitAddressSpace() throws Exception {
+ addRamEnd();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals(Long.MAX_VALUE, mbp.length());
+ assertEquals("highstart", reader.readAsciiString(0xffffffffffffffb0L));
+ assertEquals("end", reader.readAsciiString(0xfffffffffffffffcL));
+ }
+
+ @Test(expected = EOFException.class)
+ public void testFull64bitAddressSpace_fail_when_wrap_string() throws Exception {
+ MemoryBlock blk = addRamEnd();
+ setBlockStartEndBytes(blk, "blah", "fail");
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ reader.readAsciiString(0xfffffffffffffffcL);
+ }
+
+ @Test(expected = EOFException.class)
+ public void testFull64bitAddressSpace_fail_when_wrap_int() throws Exception {
+ addRamEnd();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ reader.readInt(0xfffffffffffffffeL);
+ }
+
+ @Test(expected = EOFException.class)
+ public void testEOFExceptionWhenCrossingMemBlockBoundary() throws Exception {
+ MemoryBlock blk1 = addRam1();
+ addRamEnd();
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
+ BinaryReader reader = new BinaryReader(mbp, true);
+
+ assertEquals("endram1", reader.readAsciiString(blk1.getEnd().getOffset() - 7));
+
+ setBlockStartEndBytes(blk1, "blah", "fail");
+ reader.readAsciiString(blk1.getEnd().getOffset() - 3);
+ }
+}
diff --git a/Ghidra/Features/FileFormats/ghidra_scripts/BTreeAnnotationScript.java b/Ghidra/Features/FileFormats/ghidra_scripts/BTreeAnnotationScript.java
index 2a5f840340..cbfe6a1452 100644
--- a/Ghidra/Features/FileFormats/ghidra_scripts/BTreeAnnotationScript.java
+++ b/Ghidra/Features/FileFormats/ghidra_scripts/BTreeAnnotationScript.java
@@ -32,9 +32,8 @@ public class BTreeAnnotationScript extends GhidraScript {
@Override
public void run() throws Exception {
- Address address = currentProgram.getMinAddress();
-
- ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(), address);
+ ByteProvider provider =
+ MemoryByteProvider.createProgramHeaderByteProvider(currentProgram, false);
BinaryReader reader = new BinaryReader(provider, false);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootimg/BootImageAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootimg/BootImageAnalyzer.java
index 628dee3b6a..970ad23c08 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootimg/BootImageAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootimg/BootImageAnalyzer.java
@@ -19,9 +19,7 @@ import java.io.IOException;
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteProvider;
-import ghidra.app.util.bin.MemoryByteProvider;
+import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.file.analyzers.FileFormatAnalyzer;
import ghidra.program.model.address.Address;
@@ -30,9 +28,7 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
-import ghidra.util.exception.CancelledException;
-import ghidra.util.exception.DuplicateNameException;
-import ghidra.util.exception.NotFoundException;
+import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class BootImageAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
@@ -89,9 +85,7 @@ public class BootImageAnalyzer extends FileFormatAnalyzer implements AnalysisWor
TaskMonitor monitor)
throws Exception, CancelledException {
- Address address = program.getMinAddress();
-
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
if (BootImageUtil.isBootImage(program)) {
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootldr/AndroidBootLoaderAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootldr/AndroidBootLoaderAnalyzer.java
index 4bff86449c..5091f17557 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootldr/AndroidBootLoaderAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/bootldr/AndroidBootLoaderAnalyzer.java
@@ -58,7 +58,8 @@ public class AndroidBootLoaderAnalyzer extends AbstractAnalyzer {
AddressSpace addressSpace = program.getAddressFactory().getDefaultAddressSpace();
Address headerAddress = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), headerAddress);
+
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
try {
AndroidBootLoaderHeader header = new AndroidBootLoaderHeader(reader);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexCondenseFillerBytesAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexCondenseFillerBytesAnalyzer.java
index 154b46c608..5531535db7 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexCondenseFillerBytesAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexCondenseFillerBytesAnalyzer.java
@@ -74,8 +74,7 @@ public class DexCondenseFillerBytesAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexExceptionHandlersAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexExceptionHandlersAnalyzer.java
index 15ce673ca4..a7f824ef19 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexExceptionHandlersAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexExceptionHandlersAnalyzer.java
@@ -49,8 +49,7 @@ public class DexExceptionHandlersAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexHeaderFormatAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexHeaderFormatAnalyzer.java
index 9d3369ec8d..98fc84fc08 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexHeaderFormatAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexHeaderFormatAnalyzer.java
@@ -65,8 +65,7 @@ public class DexHeaderFormatAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupDataAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupDataAnalyzer.java
index 676e6e39a8..7d1d2322f5 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupDataAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupDataAnalyzer.java
@@ -69,8 +69,7 @@ public class DexMarkupDataAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupInstructionsAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupInstructionsAnalyzer.java
index 466ddc9095..b9b0cc6e68 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupInstructionsAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupInstructionsAnalyzer.java
@@ -45,8 +45,7 @@ public class DexMarkupInstructionsAnalyzer extends FileFormatAnalyzer {
DexHeader header = analysisState.getHeader();
// Set-up reader for fill_array_data
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
Listing listing = program.getListing();
@@ -145,8 +144,7 @@ public class DexMarkupInstructionsAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupSwitchTableAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupSwitchTableAnalyzer.java
index bb6b77436c..9423375089 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupSwitchTableAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/dex/analyzer/DexMarkupSwitchTableAnalyzer.java
@@ -18,29 +18,19 @@ package ghidra.file.formats.android.dex.analyzer;
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.services.AnalysisPriority;
import ghidra.app.services.AnalyzerType;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteProvider;
-import ghidra.app.util.bin.MemoryByteProvider;
+import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.file.analyzers.FileFormatAnalyzer;
import ghidra.file.formats.android.cdex.CDexConstants;
-import ghidra.file.formats.android.dex.format.DexConstants;
-import ghidra.file.formats.android.dex.format.PackedSwitchPayload;
-import ghidra.file.formats.android.dex.format.SparseSwitchPayload;
+import ghidra.file.formats.android.dex.format.*;
import ghidra.file.formats.android.dex.util.DexUtil;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.data.DataType;
-import ghidra.program.model.listing.CodeUnit;
-import ghidra.program.model.listing.Instruction;
-import ghidra.program.model.listing.InstructionIterator;
-import ghidra.program.model.listing.Listing;
-import ghidra.program.model.listing.Program;
+import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.scalar.Scalar;
-import ghidra.program.model.symbol.Namespace;
-import ghidra.program.model.symbol.RefType;
-import ghidra.program.model.symbol.SourceType;
+import ghidra.program.model.symbol.*;
import ghidra.util.task.TaskMonitor;
public class DexMarkupSwitchTableAnalyzer extends FileFormatAnalyzer {
@@ -51,8 +41,7 @@ public class DexMarkupSwitchTableAnalyzer extends FileFormatAnalyzer {
monitor.setMaximum(set == null ? program.getMemory().getSize() : set.getNumAddresses());
monitor.setProgress(0);
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
Listing listing = program.getListing();
@@ -126,8 +115,7 @@ public class DexMarkupSwitchTableAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return DexConstants.isDexFile(provider) || CDexConstants.isCDEX(program);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/fbpk/FBPK_Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/fbpk/FBPK_Analyzer.java
index 683324676f..46364c84a6 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/fbpk/FBPK_Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/fbpk/FBPK_Analyzer.java
@@ -15,9 +15,7 @@
*/
package ghidra.file.formats.android.fbpk;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteProvider;
-import ghidra.app.util.bin.MemoryByteProvider;
+import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.file.analyzers.FileFormatAnalyzer;
import ghidra.program.model.address.Address;
@@ -59,7 +57,8 @@ public class FBPK_Analyzer extends FileFormatAnalyzer {
throws Exception {
Address headerAddress = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), headerAddress);
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
+
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
try {
FBPK header = FBPK_Factory.getFBPK(reader);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/lz4/LZ4ArchiveFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/lz4/LZ4ArchiveFileSystem.java
index a286f19b88..8c8952e255 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/lz4/LZ4ArchiveFileSystem.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/lz4/LZ4ArchiveFileSystem.java
@@ -15,9 +15,10 @@
*/
package ghidra.file.formats.android.lz4;
-import java.io.*;
import java.util.*;
+import java.io.*;
+
import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream;
import ghidra.app.util.bin.BinaryReader;
@@ -89,7 +90,7 @@ public class LZ4ArchiveFileSystem extends GFileSystemBase {
upwtm.setMessage("Decompressing LZ4 archive...");
upwtm.setProgress(0);
- while (reader.getPointerIndex() < reader.length()) {
+ while (reader.hasNext()) {
monitor.checkCanceled();
int compressedChunkSize = reader.readNextInt();
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/bundle/FullOatBundle.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/bundle/FullOatBundle.java
index cb31d3073e..b15601f7e4 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/bundle/FullOatBundle.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/bundle/FullOatBundle.java
@@ -15,9 +15,10 @@
*/
package ghidra.file.formats.android.oat.bundle;
-import java.io.IOException;
import java.util.*;
+import java.io.IOException;
+
import org.apache.commons.io.FilenameUtils;
import ghidra.app.util.bin.*;
@@ -89,6 +90,7 @@ public class FullOatBundle implements OatBundle {
return null;//could NOT find matching dex header, probably not imported yet
}
+ @Override
public ArtHeader getArtHeader() {
return artHeader;
}
@@ -98,10 +100,12 @@ public class FullOatBundle implements OatBundle {
return oatHeader;
}
+ @Override
public List getDexHeaders() {
return dexHeaders;
}
+ @Override
public VdexHeader getVdexHeader() {
return vdexHeader;
}
@@ -208,7 +212,7 @@ public class FullOatBundle implements OatBundle {
try {
program = (Program) child.getDomainObject(this, true, true, monitor);
ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return makeHeader(type, programName, provider, monitor);
}
catch (Exception e) {
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/odex/OdexHeaderFormatAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/odex/OdexHeaderFormatAnalyzer.java
index c45516810c..2e8a773ac5 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/odex/OdexHeaderFormatAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/odex/OdexHeaderFormatAnalyzer.java
@@ -17,16 +17,12 @@ package ghidra.file.formats.android.odex;
import ghidra.app.services.AnalysisPriority;
import ghidra.app.services.AnalyzerType;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteProvider;
-import ghidra.app.util.bin.MemoryByteProvider;
+import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.file.analyzers.FileFormatAnalyzer;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
-import ghidra.program.model.data.DWordDataType;
-import ghidra.program.model.data.DataType;
-import ghidra.program.model.data.StringDataType;
+import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
@@ -51,8 +47,7 @@ public class OdexHeaderFormatAnalyzer extends FileFormatAnalyzer {
block.setWrite(false);
block.setExecute(false);
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
OdexHeader header = new OdexHeader(reader);
@@ -80,8 +75,7 @@ public class OdexHeaderFormatAnalyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
return OdexConstants.isOdexFile(provider);
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/vdex/VdexConstants.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/vdex/VdexConstants.java
index 6874a245b6..c17369326b 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/vdex/VdexConstants.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/vdex/VdexConstants.java
@@ -15,8 +15,6 @@
*/
package ghidra.file.formats.android.vdex;
-import java.io.IOException;
-
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.MemoryByteProvider;
import ghidra.program.model.address.Address;
@@ -112,7 +110,7 @@ public final class VdexConstants {
for (MemoryBlock block : program.getMemory().getBlocks()) {
try (ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), block.getStart())) {
+ MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), block)) {
String magic = new String(provider.readBytes(0, VdexConstants.MAGIC.length()));
if (VdexConstants.MAGIC.equals(magic)) {
return true;
@@ -127,30 +125,21 @@ public final class VdexConstants {
}
public final static Address findVDEX(Program program) {
- try {
- if (program != null) {
- for (MemoryBlock block : program.getMemory().getBlocks()) {
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), block.getStart());
- try {
- String magic =
- new String(provider.readBytes(0, VdexConstants.MAGIC.length()));
- if (VdexConstants.MAGIC.equals(magic)) {
- return block.getStart();
- }
- }
- catch (Exception e) {
- //ignore
- }
- finally {
- provider.close();
+ if (program != null) {
+ for (MemoryBlock block : program.getMemory().getBlocks()) {
+ try (ByteProvider provider = MemoryByteProvider
+ .createMemoryBlockByteProvider(program.getMemory(), block)) {
+ String magic =
+ new String(provider.readBytes(0, VdexConstants.MAGIC.length()));
+ if (VdexConstants.MAGIC.equals(magic)) {
+ return block.getStart();
}
}
+ catch (Exception e) {
+ //ignore
+ }
}
}
- catch (IOException e) {
- //ignore
- }
return null;
}
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4Analyzer.java
index b8ba92b2a2..54ead1ac16 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4Analyzer.java
@@ -49,7 +49,8 @@ public class Ext4Analyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze(Program program) {
- ByteProvider provider = new MemoryByteProvider( program.getMemory(), program.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
int start = getSuperBlockStart(reader);
if( start == -1 ) {
@@ -77,7 +78,8 @@ public class Ext4Analyzer extends FileFormatAnalyzer {
@Override
public boolean analyze(Program program, AddressSetView set,
TaskMonitor monitor, MessageLog log) throws Exception {
- ByteProvider provider = new MemoryByteProvider( program.getMemory(), program.getAddressFactory().getDefaultAddressSpace());
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
int start = getSuperBlockStart(reader);
int groupStart = 0;
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/NewExt4Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/NewExt4Analyzer.java
index f8920df620..c49435b12c 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/NewExt4Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/NewExt4Analyzer.java
@@ -15,23 +15,20 @@
*/
package ghidra.file.formats.ext4;
-import java.io.IOException;
import java.util.List;
+import java.io.IOException;
+
import ghidra.app.cmd.comments.SetCommentCmd;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.services.ProgramManager;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteProvider;
-import ghidra.app.util.bin.MemoryByteProvider;
+import ghidra.app.util.bin.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.file.analyzers.FileFormatAnalyzer;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.data.DataType;
-import ghidra.program.model.listing.CodeUnit;
-import ghidra.program.model.listing.Data;
-import ghidra.program.model.listing.Program;
+import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
@@ -63,7 +60,8 @@ public class NewExt4Analyzer extends FileFormatAnalyzer {
@Override
public boolean canAnalyze( Program program ) {
- ByteProvider provider = new MemoryByteProvider( program.getMemory( ), program.getAddressFactory( ).getDefaultAddressSpace( ) );
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader( provider, true );
int start = getSuperBlockStart( reader );
if ( start == -1 ) {
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/gzip/GZipUtil.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/gzip/GZipUtil.java
index 593695aab2..94fc58b7fe 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/gzip/GZipUtil.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/gzip/GZipUtil.java
@@ -15,17 +15,17 @@
*/
package ghidra.file.formats.gzip;
+import java.util.Arrays;
+
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.MemoryByteProvider;
import ghidra.program.model.listing.Program;
-import java.util.Arrays;
-
public class GZipUtil {
public final static boolean isGZip( Program program ) {
- ByteProvider provider = new MemoryByteProvider( program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace() );
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, true);
return isGZip( provider );
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/apple8900/Apple8900Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/apple8900/Apple8900Analyzer.java
index 49dc37f2a0..55029401a0 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/apple8900/Apple8900Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/apple8900/Apple8900Analyzer.java
@@ -27,33 +27,38 @@ import ghidra.util.task.TaskMonitor;
public class Apple8900Analyzer extends FileFormatAnalyzer {
+ @Override
public boolean canAnalyze(Program program) {
return Apple8900Util.is8900(program);
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return Apple8900Util.is8900(program);
}
+ @Override
public String getDescription() {
return "Annotates an Apple 8900 file.";
}
+ @Override
public String getName() {
return "Apple 8900 Annotation";
}
+ @Override
public boolean isPrototype() {
return true;
}
+ @Override
public boolean analyze(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws Exception {
monitor.setMessage("Processing Apple 8900 header...");
ByteProvider provider =
- new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
Apple8900Header header = new Apple8900Header(reader);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgAnalyzer.java
index 28dbaffc39..581402e068 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgAnalyzer.java
@@ -15,6 +15,8 @@
*/
package ghidra.file.formats.ios.dmg;
+import java.util.Arrays;
+
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.util.bin.*;
@@ -28,8 +30,6 @@ import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
-import java.util.Arrays;
-
public class DmgAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
@Override
@@ -44,7 +44,7 @@ public class DmgAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
throws Exception, CancelledException {
Address address = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, false);
DmgHeader header = new DmgHeaderV2(reader);
@@ -67,22 +67,27 @@ public class DmgAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
return getName();
}
+ @Override
public boolean canAnalyze(Program program) {
return DmgUtil.isDMG(program);
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return DmgUtil.isDMG(program);
}
+ @Override
public String getDescription() {
return "Annotates an DMG file.";
}
+ @Override
public String getName() {
return "DMG";
}
+ @Override
public boolean isPrototype() {
return true;
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheAnalyzer.java
index 59c150d1b2..d2c19679a5 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dyldcache/DyldCacheAnalyzer.java
@@ -39,8 +39,7 @@ public class DyldCacheAnalyzer extends FileFormatAnalyzer {
throws Exception {
Address headerAddress = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), headerAddress);
-
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
DyldArchitecture architecture = DyldArchitecture.getArchitecture(provider);
if (architecture == null) {
log.appendMsg("Invalid DYLD cache file.");
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/ibootim/iBootImAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/ibootim/iBootImAnalyzer.java
index f56aa6be48..9c5580eaf2 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/ibootim/iBootImAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/ibootim/iBootImAnalyzer.java
@@ -43,8 +43,7 @@ public class iBootImAnalyzer extends FileFormatAnalyzer implements AnalysisWorke
throws Exception, CancelledException {
Address address = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
-
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
iBootImHeader header = new iBootImHeader(provider);
if (!header.getSignature().equals(iBootImConstants.SIGNATURE)) {
@@ -69,22 +68,27 @@ public class iBootImAnalyzer extends FileFormatAnalyzer implements AnalysisWorke
return getName();
}
+ @Override
public boolean canAnalyze(Program program) {
return iBootImUtil.isiBootIm(program);
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return iBootImUtil.isiBootIm(program);
}
+ @Override
public String getDescription() {
return "Annotates an iBoot Image (iBootIm) file.";
}
+ @Override
public String getName() {
return "iBoot Image (iBootIm) Annotation";
}
+ @Override
public boolean isPrototype() {
return true;
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img2/Img2Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img2/Img2Analyzer.java
index 143b5fa595..cabad6d36e 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img2/Img2Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img2/Img2Analyzer.java
@@ -27,6 +27,7 @@ import ghidra.util.task.TaskMonitor;
public class Img2Analyzer extends FileFormatAnalyzer {
+ @Override
public boolean canAnalyze(Program program) {
try {
return Img2Util.isIMG2(program);
@@ -37,28 +38,32 @@ public class Img2Analyzer extends FileFormatAnalyzer {
return false;
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return Img2Util.isIMG2(program);
}
+ @Override
public String getDescription() {
return "Annotates an IMG2 file.";
}
+ @Override
public String getName() {
return "IMG2 Annotation";
}
+ @Override
public boolean isPrototype() {
return true;
}
+ @Override
public boolean analyze(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws Exception {
ByteProvider provider =
- new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
Img2 header = new Img2(reader);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img3/Img3Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img3/Img3Analyzer.java
index ff8e12129d..e14977ce2a 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img3/Img3Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/img3/Img3Analyzer.java
@@ -15,6 +15,8 @@
*/
package ghidra.file.formats.ios.img3;
+import java.util.List;
+
import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.util.bin.*;
@@ -28,30 +30,34 @@ import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
-import java.util.List;
-
public class Img3Analyzer extends FileFormatAnalyzer implements AnalysisWorker {
+ @Override
public boolean canAnalyze(Program program) {
return Img3Util.isIMG3(program);
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return Img3Util.isIMG3(program);
}
+ @Override
public String getDescription() {
return "Annotates an IMG3 file.";
}
+ @Override
public String getName() {
return "IMG3 Annotation";
}
+ @Override
public boolean isPrototype() {
return true;
}
+ @Override
public boolean analyze(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws Exception {
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
@@ -63,7 +69,7 @@ public class Img3Analyzer extends FileFormatAnalyzer implements AnalysisWorker {
throws Exception, CancelledException {
Address address = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
Img3 header = new Img3(reader);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Analyzer.java
deleted file mode 100644
index 5c52f833cf..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Analyzer.java
+++ /dev/null
@@ -1,488 +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.file.formats.iso9660;
-
-import java.io.IOException;
-import java.util.*;
-
-import ghidra.app.cmd.comments.SetCommentCmd;
-import ghidra.app.cmd.data.CreateDataCmd;
-import ghidra.app.cmd.data.CreateStringCmd;
-import ghidra.app.services.AbstractAnalyzer;
-import ghidra.app.services.AnalyzerType;
-import ghidra.app.util.bin.*;
-import ghidra.app.util.importer.MessageLog;
-import ghidra.app.util.opinion.BinaryLoader;
-import ghidra.framework.options.Options;
-import ghidra.program.model.address.*;
-import ghidra.program.model.data.*;
-import ghidra.program.model.listing.*;
-import ghidra.program.model.mem.MemoryBlock;
-import ghidra.util.Msg;
-import ghidra.util.exception.CancelledException;
-import ghidra.util.exception.DuplicateNameException;
-import ghidra.util.task.TaskMonitor;
-
-public class ISO9660Analyzer extends AbstractAnalyzer {
-
- private enum Offset {
- Offset1, //0x8001
- Offset2, //0x8801
- Offset3, //0x9001
- NotFound
- }
-
- public ISO9660Analyzer() {
- super("ISO9660 File Format Annotation", "Annotates an ISO9660 File Format",
- AnalyzerType.BYTE_ANALYZER);
- super.setPrototype();
-
- }
-
- @Override
- public boolean canAnalyze(Program program) {
-
- Offset result = checkSignatures(program);
- if (result.equals(Offset.NotFound)) {
- return false;
- }
- return true;
-
- }
-
- private Offset checkSignatures(Program program) {
- int magicLen = ISO9660Constants.MAGIC_BYTES.length;
- byte[] signatureArray = new byte[magicLen];
-
- try {
- Options options = program.getOptions("Program Information");
- String format = options.getString("Executable Format", null);
- if (!BinaryLoader.BINARY_NAME.equals(format)) {
- return Offset.NotFound;
- }
-
- MemoryBlock[] blocks = program.getMemory().getBlocks();
- if (blocks.length != 1) {
- return Offset.NotFound;
- }
-
- AddressSpace addressSpace = program.getAddressFactory().getDefaultAddressSpace();
- if (!(blocks[0].getStart().getAddressSpace().equals(addressSpace))) {
- return Offset.NotFound;
- }
-
- long blockSize = blocks[0].getSize();
-
- //block must start at zero
- if (blocks[0].getStart().getOffset() != 0L) {
- return Offset.NotFound;
- }
-
- //is the block initialized
- if (!blocks[0].isInitialized()) {
- return Offset.NotFound;
- }
-
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), addressSpace);
- BinaryReader reader = new BinaryReader(provider, true);
-
- //Make sure that the current programs max offset is at least big enough to check
- //for the ISO's max address location of a signature
- if (blockSize < ISO9660Constants.MIN_ISO_LENGTH1) {
- return Offset.NotFound;
- }
-
- //Check first possible signature location
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET1_0x8001);
- signatureArray = reader.readNextByteArray(magicLen);
- if (Arrays.equals(signatureArray, ISO9660Constants.MAGIC_BYTES)) {
- //Where to start the reader during mark up
- return Offset.Offset1;
- }
-
- if (blockSize < ISO9660Constants.MIN_ISO_LENGTH2) {
- return Offset.NotFound;
- }
-
- //Check second possible signature location
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET2_0x8801);
- signatureArray = reader.readNextByteArray(magicLen);
- if (Arrays.equals(signatureArray, ISO9660Constants.MAGIC_BYTES)) {
- //Where to start the reader during mark up
- return Offset.Offset2;
- }
-
- if (blockSize < ISO9660Constants.MIN_ISO_LENGTH3) {
- return Offset.NotFound;
- }
- //Check third possible signature location
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET3_0x9001);
- signatureArray = reader.readNextByteArray(magicLen);
- if (Arrays.equals(signatureArray, ISO9660Constants.MAGIC_BYTES)) {
- //Where to start the reader during mark up
- return Offset.Offset3;
- }
-
- }
- catch (Exception e) {
- Msg.error(this, "Error when checking for ISO9660 file signatures", e);
- }
-
- //Signature is not found at any of the three possible address locations
- return Offset.NotFound;
- }
-
- @Override
- public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
- throws CancelledException {
-
- ByteProvider provider = new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
- BinaryReader reader = new BinaryReader(provider, true);
- try {
-
- Offset signatureOffset = checkSignatures(program);
- setPointerOffset(signatureOffset, reader);
-
- monitor.setMessage("Processing ISO9660 Header");
-
- //Get the full header (contains all volume descriptors)
- ISO9660Header isoHeader = new ISO9660Header(reader);
-
- //Get the list of volumes from the header
- List volumes = isoHeader.getVolumeDescriptorSet();
-
- //Set the overall plate comment at the top of this file
- setPlateComment(program, toAddress(program, 0), isoHeader.toString());
-
- //Create a new module for the volume descriptor fragments
- ProgramModule descriptorModule =
- program.getListing().getDefaultRootModule().createModule("Volume Descriptors");
-
- //For each volume, set the volumes plate comment and data at the address it exists
- setDescriptorData(program, volumes, descriptorModule);
-
- processPathTables(isoHeader, reader, program);
-
- //Create an alignment over the null characters from start to the first volume
- int offset = getOffsetValue(signatureOffset);
- program.getListing().createData(toAddress(program, 0), new AlignmentDataType(),
- offset - 1);
-
- ISO9660VolumeDescriptor pvd = isoHeader.getPrimaryVolumeDescriptor();
- ISO9660Directory entryDir = isoHeader.getPrimaryDirectory();
-
- int logicalBlockSize = pvd.getLogicalBlockSizeLE();
-
- List dirList =
- createDirectoryList(reader, entryDir, logicalBlockSize);
-
- createDirectories(reader, program, dirList, logicalBlockSize);
-
- }
- catch (Exception e) {
- log.appendException(e);
- return false;
- }
- return true;
-
- }
-
- private void setPointerOffset(Offset offset, BinaryReader reader) {
- if (offset.equals(Offset.Offset1)) {
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET1_0x8001 - 1);
- }
- else if (offset.equals(Offset.Offset2)) {
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET2_0x8801 - 1);
- }
- else {
- reader.setPointerIndex(ISO9660Constants.SIGNATURE_OFFSET3_0x9001 - 1);
- }
- }
-
- private int getOffsetValue(Offset offsetEnum) {
-
- if (offsetEnum.equals(Offset.Offset1)) {
- return ISO9660Constants.SIGNATURE_OFFSET1_0x8001;
- }
- else if (offsetEnum.equals(Offset.Offset2)) {
- return ISO9660Constants.SIGNATURE_OFFSET2_0x8801;
- }
- else {
- return ISO9660Constants.SIGNATURE_OFFSET3_0x9001;
- }
- }
-
- private void setDescriptorData(Program program, List volumes,
- ProgramModule descriptorModule) throws DuplicateNameException, IOException, Exception {
-
- for (ISO9660BaseVolume descriptor : volumes) {
-
- long volumeIndex = descriptor.getVolumeIndex();
- DataType descriptorDataType = descriptor.toDataType();
- Address volumeAddress = toAddress(program, volumeIndex);
- Data descriptorData =
- createData(program, toAddress(program, volumeIndex), descriptorDataType);
-
- setPlateComment(program, volumeAddress, descriptor.toString());
-
- //Add fragment to module
- createFragment(program, descriptorModule, descriptorDataType.getName(),
- descriptorData.getMinAddress(), descriptorData.getMaxAddress().next());
- }
- }
-
- /*
- * Process the normal and supplementary path tables in the binary
- */
- private void processPathTables(ISO9660Header isoHeader, BinaryReader reader, Program program)
- throws DuplicateNameException {
-
- //Create module to add path table fragments to
- ProgramModule pathTableModule =
- program.getListing().getDefaultRootModule().createModule("Path Tables");
-
- try {
-
- //Get the tables which hold the index and size pairs of path tables
- //for little-endian values
- HashMap typeLTable = isoHeader.getTypeLIndexSizeTable();
- createPathTableData(reader, program, pathTableModule, typeLTable, true);
-
- //Get the tables which hold the index and size pairs of path tables
- //for big-endian values
- HashMap typeMTable = isoHeader.getTypeMIndexSizeTable();
- createPathTableData(reader, program, pathTableModule, typeMTable, false);
-
- //Get the tables which hold the index and size of supplementary path tables
- //for little-endian values
- HashMap supplTypeLTable = isoHeader.getSupplTypeLIndexSizeTable();
- createPathTableData(reader, program, pathTableModule, supplTypeLTable, true);
-
- //Get the tables which hold the index and size of supplementary path tables
- //for big-endian values
- HashMap supplTypeMTable = isoHeader.getSupplTypeMIndexSizeTable();
- createPathTableData(reader, program, pathTableModule, supplTypeMTable, false);
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /*
- * From a given parent directory create each child directory
- * under that parent directory and add them to a list
- */
- private List createDirectoryList(BinaryReader reader,
- ISO9660Directory parentDir, long blockSize) throws IOException {
-
- List directoryList = new ArrayList<>();
- ISO9660Directory childDir = null;
-
- //Get location from parent into child directory
- long dirIndex = parentDir.getLocationOfExtentLE() * blockSize;
- long endIndex = dirIndex + parentDir.getDataLengthLE();
-
- //while there is still more data in the current directory level
- while (dirIndex < endIndex) {
- reader.setPointerIndex(dirIndex);
-
- //If the next byte is not zero then create the directory
- if (reader.peekNextByte() != 0) {
- childDir = new ISO9660Directory(reader, parentDir);
- directoryList.add(childDir);
- }
-
- //Otherwise there is a gap in the data so keep looking forward
- //while still under the end index and create directory when data is
- //reached
- else {
- while (reader.peekNextByte() == 0) {
- //keep reading if all zeros until non zero is met or
- //end index reached
- if (reader.getPointerIndex() < endIndex) {
- reader.readNextByte();
- }
- else {
- break;
- }
- }
-
- //Create the data once the reader finds the next position
- //and not reached end index
- if (reader.getPointerIndex() < endIndex) {
- childDir = new ISO9660Directory(reader, parentDir);
- dirIndex = childDir.getVolumeIndex();
- directoryList.add(childDir);
- }
- }
-
- dirIndex += childDir.getDirectoryRecordLength();
- }
-
- return directoryList;
- }
-
- /*
- * Recurses though each level of a directory structure
- * in a depth-first manner
- * and creates each directory also marking them in the binary
- */
- private void createDirectories(BinaryReader reader, Program program,
- List directoryList, long blockSize)
- throws DuplicateNameException, Exception {
-
- Address volumeAddress;
-
- //If the directory size is over two then there are actual
- //new directories in that level. The first two are always
- //the 'self' directory and the parent directory
- if (directoryList.size() > 2) {
- ISO9660Directory selfDir = null;
- ISO9660Directory parentDir = null;
-
- // The 'self' describing directory entry
- selfDir = directoryList.remove(0);
- volumeAddress = toAddress(program, selfDir.getVolumeIndex());
- createDataAndPlateComment(program, selfDir, volumeAddress);
-
- // The parent directory
- parentDir = directoryList.remove(0);
- volumeAddress = toAddress(program, parentDir.getVolumeIndex());
- createDataAndPlateComment(program, parentDir, volumeAddress);
-
- //For everything else not a self or parent directory
- for (ISO9660Directory dir : directoryList) {
-
- //If this directory is not pointing to a file
- //Create the directory data
- if (selfDir.isDirectoryFlagSet()) {
- volumeAddress = toAddress(program, dir.getVolumeIndex());
- setPlateComment(program, volumeAddress, dir.toString());
- DataType volumeDataType = dir.toDataType();
- createData(program, volumeAddress, volumeDataType);
-
- //If the directory is a new level of directories
- //recurse down into the next level
- if (dir.isDirectoryFlagSet()) {
- List dirs;
- dirs = createDirectoryList(reader, dir, blockSize);
- createDirectories(reader, program, dirs, blockSize);
- }
- }
- }
- }
-
- return;
- }
-
- private void createDataAndPlateComment(Program program, ISO9660Directory dir,
- Address volumeAddress) throws DuplicateNameException, IOException, Exception {
-
- setPlateComment(program, volumeAddress, dir.toString());
- createData(program, volumeAddress, dir.toDataType());
- }
-
- /*
- * Creates path table plate comments and lays mark up data down on the binary
- */
- private void createPathTableData(BinaryReader reader, Program program, ProgramModule module,
- HashMap pathTableMap, boolean littleEndian) throws Exception {
-
- //Enumeration over the indexes of the path tables in the table
-
- Set pathTableIndexes = pathTableMap.keySet();
- Iterator pathIter = pathTableIndexes.iterator();
-
- while (pathIter.hasNext()) {
-
- //Index of current path table
- int pathTableIndex = pathIter.next();
-
- //Logical block size of current path table
- short logicalBlockSize = pathTableMap.get(pathTableIndex);
-
- //Calculate address from logical index
- int pathAddress = logicalBlockSize * pathTableIndex;
-
- //Move reader to the path table address
- reader.setPointerIndex(pathAddress);
-
- ISO9660PathTable pathTable = new ISO9660PathTable(reader, littleEndian);
- DataType pathTableDataType = pathTable.toDataType();
-
- Address volumeAddress = toAddress(program, pathTable.getVolumeIndex());
-
- setPlateComment(program, volumeAddress, pathTable.toString());
- Data pathTableData = createData(program, volumeAddress, pathTableDataType);
- createFragment(program, module, pathTableDataType.getName(),
- pathTableData.getMinAddress(), pathTableData.getMaxAddress().next());
- }
- }
-
- /*
- * Marks up the binary with data
- */
- private Data createData(Program program, Address address, DataType datatype) throws Exception {
- if (datatype instanceof StringDataType) {
- CreateStringCmd cmd = new CreateStringCmd(address);
- if (!cmd.applyTo(program)) {
- throw new RuntimeException(cmd.getStatusMsg());
- }
- }
- else {
- CreateDataCmd cmd = new CreateDataCmd(address, datatype);
- if (!cmd.applyTo(program)) {
- throw new RuntimeException(cmd.getStatusMsg());
- }
- }
- return program.getListing().getDefinedDataAt(address);
- }
-
- private Address toAddress(Program program, long offset) {
- return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
- }
-
- private boolean setPlateComment(Program program, Address address, String comment) {
- SetCommentCmd cmd = new SetCommentCmd(address, CodeUnit.PLATE_COMMENT, comment);
- return cmd.applyTo(program);
- }
-
- private ProgramFragment createFragment(Program program, ProgramModule module,
- String fragmentName, Address start, Address end) throws Exception {
-
- ProgramFragment fragment = getFragment(module, fragmentName);
- if (fragment == null) {
- fragment = module.createFragment(fragmentName);
- }
- fragment.move(start, end.subtract(1));
- return fragment;
- }
-
- private ProgramFragment getFragment(ProgramModule module, String fragmentName) {
- Group[] groups = module.getChildren();
- if (groups != null) {
- for (Group group : groups) {
- if (group.getName().equals(fragmentName) && group instanceof ProgramFragment) {
- return (ProgramFragment) group;
- }
- }
- }
-
- return null;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BaseVolume.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BaseVolume.java
deleted file mode 100644
index 83ceac8054..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BaseVolume.java
+++ /dev/null
@@ -1,105 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.StructConverter;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-
-/**
- * Parent class used for all other types of volume descriptors
- */
-public class ISO9660BaseVolume implements StructConverter {
-
- private long volumeIndex;
- private byte typeCode;
- private byte[] identifier;
- private byte version;
-
- public ISO9660BaseVolume(BinaryReader reader) throws IOException {
- volumeIndex = reader.getPointerIndex();
- typeCode = reader.readNextByte();
- identifier = reader.readNextByteArray(ISO9660Constants.MAGIC_BYTES.length);
- version = reader.readNextByte();
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc = new StructureDataType("ISO9660VolumeDescriptor", 0);
-
- struc.add(BYTE, "Type Code", "Type of volume descriptor");
- struc.add(new ArrayDataType(BYTE, identifier.length, 1), "Standard Identifier",
- "Always 'CD001'");
- struc.add(BYTE, "Version", "Always 0x01");
-
- return struc;
- }
-
- /**
- * Creates a string representation of this class filling in field specifics
- * when applicable.
- * @return the string representation of this class
- */
- @Override
- public String toString() {
- StringBuffer buff = new StringBuffer();
-
- buff.append("Type Code: 0x" + Integer.toHexString(typeCode) + " => " + getTypeCodeString() +
- "\n");
- buff.append("Standard Identifier: " + new String(identifier).trim() + "\n");
- buff.append("Version: 0x" + Integer.toHexString(version) + "\n");
-
- return buff.toString();
- }
-
- public String getTypeCodeString() {
-
- switch (typeCode) {
- case ISO9660Constants.VOLUME_DESC_BOOT_RECORD:
- return "Boot Record";
- case ISO9660Constants.VOLUME_DESC_PRIMARY_VOLUME_DESC:
- return "Primary Volume Descriptor";
- case ISO9660Constants.VOLUME_DESC_SUPPL_VOLUME_DESC:
- return "Supplementary Volume Descriptor";
- case ISO9660Constants.VOLUME_PARTITION_DESC:
- return "Volume Partition Descriptor";
- case ISO9660Constants.VOLUME_DESC_SET_TERMINATOR:
- return "Volume Descriptor Set Terminator";
- default:
- return "";
-
- }
- }
-
- public byte getTypeCode() {
- return typeCode;
- }
-
- public byte[] getIdentifier() {
- return identifier;
- }
-
- public byte getVersion() {
- return version;
- }
-
- public long getVolumeIndex() {
- return volumeIndex;
- }
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BootRecordVolumeDescriptor.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BootRecordVolumeDescriptor.java
deleted file mode 100644
index bdcbb27c5b..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660BootRecordVolumeDescriptor.java
+++ /dev/null
@@ -1,86 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-
-public class ISO9660BootRecordVolumeDescriptor extends ISO9660BaseVolume {
-
- private byte[] bootSystemIdentifier;// Length 0x20
- private byte[] bootIdentifier; // Length 0x20
- private byte[] bootSystemUse; // Length 0x7b9;
-
- public ISO9660BootRecordVolumeDescriptor(BinaryReader reader) throws IOException {
- super(reader);
- bootSystemIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_32);
- bootIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_32);
- bootSystemUse = reader.readNextByteArray(ISO9660Constants.BOOT_SYSTEM_USE_LENGTH);
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc = new StructureDataType("ISO9600BootRecord", 0);
-
- struc.add(BYTE, "Type", "Volume Descriptor Type");
- struc.add(new ArrayDataType(BYTE, super.getIdentifier().length, 1), "Identifier",
- "Identifier");
- struc.add(BYTE, "Version", "Volume Descriptor Version");
- struc.add(new ArrayDataType(BYTE, bootSystemIdentifier.length, 1),
- "Boot System Identifier", "ID of the system which can act on and boot the system");
- struc.add(new ArrayDataType(BYTE, bootIdentifier.length, 1), "Boot Identifier",
- "Identification of the boot system");
- struc.add(new ArrayDataType(BYTE, bootSystemUse.length, 1), "Boot System Use",
- "Custom - used by the boot system");
-
- return struc;
- }
-
- /**
- * Creates a string representation of this class filling in field specifics
- * when applicable.
- * @return the string representation of this class
- */
- @Override
- public String toString() {
- StringBuffer buff = new StringBuffer();
-
- buff.append("Type: 0x" + Integer.toHexString(super.getTypeCode()) + " => " +
- getTypeCodeString() + "\n");
- buff.append("Identifier: " + new String(super.getIdentifier()).trim() + "\n");
- buff.append("Version: 0x" + Integer.toHexString(super.getVersion()) + "\n");
- buff.append("Boot System Identifier: " + new String(bootSystemIdentifier).trim() + "\n");
- buff.append("Boot Identifier: " + new String(bootIdentifier).trim() + "\n");
-
- return buff.toString();
- }
-
- public byte[] getBootSystemIdentifier() {
- return bootSystemIdentifier;
- }
-
- public byte[] getBootIdentifier() {
- return bootIdentifier;
- }
-
- public byte[] getBootSystemUse() {
- return bootSystemUse;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Constants.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Constants.java
deleted file mode 100644
index ef536918a1..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Constants.java
+++ /dev/null
@@ -1,77 +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.file.formats.iso9660;
-
-/*
- * Documentation gathered from http://wiki.osdev.org/ISO_9660
- */
-public final class ISO9660Constants {
-
- /*
- * Volume Descriptor Type Codes
- */
- public final static byte VOLUME_DESC_BOOT_RECORD = 0x0;
- public final static byte VOLUME_DESC_PRIMARY_VOLUME_DESC = 0x1;
- public final static byte VOLUME_DESC_SUPPL_VOLUME_DESC = 0x2;
- public final static byte VOLUME_PARTITION_DESC = 0x3;
- public final static byte VOLUME_DESC_SET_TERMINATOR = (byte) 0xff;
-
- /*
- * Magic number identifier
- */
- public final static String MAGIC_STRING = "CD001";
- public final static byte[] MAGIC_BYTES = { 0x43, 0x44, 0x30, 0x30, 0x31 };
-
- public final static int HIDDEN_FILE_FLAG = 0;
- public final static int DIRECTORY_FLAG = 1;
- public final static int ASSOCIATED_FILE_FLAG = 2;
- public final static int EXTENDED_ATTRIBUTE_RECORD_INFO_FLAG = 3;
- public final static int OWNER_GROUP_PERMISSIONS_FLAG = 4;
- public final static int NOT_FINAL_DIRECTORY_RECORD_FLAG = 5;
-
- public final static Short SECTOR_LENGTH = 0x800;
-
- public final static Byte FILE_STRUCTURE_VERISON = 0x01;
-
- public final static Short APPLICATION_USED_LENGTH = 0x200;
-
- /*
- * Lists the three possible address offsets where the ISO9660
- * file signature can be located
- */
- public final static int SIGNATURE_OFFSET1_0x8001 = 0x8001;
- public final static int SIGNATURE_OFFSET2_0x8801 = 0x8801;
- public final static int SIGNATURE_OFFSET3_0x9001 = 0x9001;
-
- public final static int MIN_ISO_LENGTH1 = 0x8800;
- public final static int MIN_ISO_LENGTH2 = 0x9000;
- public final static int MIN_ISO_LENGTH3 = 0x9800;
-
- public final static byte BAD_TYPE = -2;
-
- public final static int UNUSED_SPACER_LEN_32 = 32;
- public final static int UNUSED_SPACER_LEN_512 = 512;
- public final static int RESERVED_SIZE = 653;
- public final static int IDENTIFIER_LENGTH_32 = 32;
- public final static int IDENTIFIER_LENGTH_36 = 36;
- public final static int IDENTIFIER_LENGTH_37 = 37;
- public final static int IDENTIFIER_LENGTH_38 = 38;
- public final static int IDENTIFIER_LENGTH_128 = 128;
- public final static int BOOT_SYSTEM_USE_LENGTH = 1977;
- public final static int DATE_TIME_LENGTH_7 = 7;
- public final static int DATE_TIME_LENGTH_17 = 17;
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Directory.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Directory.java
deleted file mode 100644
index e33764dde6..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Directory.java
+++ /dev/null
@@ -1,368 +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.file.formats.iso9660;
-
-import java.io.IOException;
-import java.time.DateTimeException;
-import java.time.LocalDateTime;
-
-import ghidra.app.util.bin.*;
-import ghidra.formats.gfilesystem.FSRL;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-public class ISO9660Directory implements StructConverter {
-
- private int directoryRecordLength;
- private byte extendedAttributeRecordLen;
- private int locationOfExtentLE;
- private int locationOfExtentBE;
- private int dataLengthLE;
- private int dataLengthBE;
- private byte[] recordingDateTime;
- private byte fileFlag;
- private byte fileUnitSize;
- private byte interleaveGapSize;
- private short volumeSequenceNumberLE;
- private short volumeSequenceNumberBE;
- private byte fileIdentLength;
- private byte[] fileIdentifier;
- private byte paddingField;
- private boolean paddingFieldPresent;
- private long volumeIndex;
- private String name;
- private ISO9660Directory parentDir;
-
- public ISO9660Directory(BinaryReader reader) throws IOException {
- this(reader, null);
- }
-
- public ISO9660Directory(BinaryReader reader, ISO9660Directory parentDir) throws IOException {
- this.parentDir = parentDir;
- volumeIndex = reader.getPointerIndex();
-
- directoryRecordLength = reader.readNextByte() & 0xff;
- extendedAttributeRecordLen = reader.readNextByte();
- locationOfExtentLE = reader.readNextInt();
- locationOfExtentBE = readIntBigEndian(reader);
- dataLengthLE = reader.readNextInt();
- dataLengthBE = readIntBigEndian(reader);
- recordingDateTime = reader.readNextByteArray(ISO9660Constants.DATE_TIME_LENGTH_7);
- fileFlag = reader.readNextByte();
- fileUnitSize = reader.readNextByte();
- interleaveGapSize = reader.readNextByte();
- volumeSequenceNumberLE = reader.readNextShort();
- volumeSequenceNumberBE = readShortBigEndian(reader);
- fileIdentLength = reader.readNextByte();
- fileIdentifier = reader.readNextByteArray(fileIdentLength);
- name = analyzeName(fileIdentifier);
-
- //The padding field will only be present if the
- //fileIdentLength is even, otherwise it is not used
- if (fileIdentLength % 2 == 0) {
- paddingField = reader.readNextByte();
- paddingFieldPresent = true;
- }
- else {
- paddingFieldPresent = false;
- }
- }
-
- private int readIntBigEndian(BinaryReader reader) throws IOException {
- setReaderToBigEndian(reader);
- int tmp = reader.readNextInt();
- setReaderToLittleEndian(reader);
-
- return tmp;
- }
-
- private short readShortBigEndian(BinaryReader reader) throws IOException {
- setReaderToBigEndian(reader);
- short tmp = reader.readNextShort();
- setReaderToLittleEndian(reader);
-
- return tmp;
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc;
- struc = new StructureDataType("ISO9600Directory", 0);
-
- struc.add(BYTE, "Directory Record Length", "Length of the Directory Record");
- struc.add(BYTE, "Extended Attribute Record Length",
- "Length of the Extended Attribute Record");
- struc.add(QWORD, "Location of Extent", "LBA in (Little/Big)Endian (4 bytes each)");
- struc.add(QWORD, "Data Length", "Size of extent. (Little/Big)Endian (4 bytes each");
- struc.add(new ArrayDataType(BYTE, recordingDateTime.length, 1), "Recording date/time",
- "Recording date and time");
- struc.add(BYTE, "File flags", "File flags");
- struc.add(BYTE, "File Unit Size", "File unit size for files recoraded in interleaved mode");
- struc.add(BYTE, "Interleave gap size",
- "Interleave gap size for files recorded in interleaved mode");
- struc.add(DWORD, "Volume Sequence Number", "The clume that this extent is recorded in");
- struc.add(BYTE, "File Identifier Length", "Length of the file identifier");
- struc.add(new ArrayDataType(BYTE, fileIdentifier.length, 1), "File Identifier",
- "File Identifier");
- if (paddingFieldPresent) {
- struc.add(BYTE, "Padding Field", "Padding Field");
- }
-
- return struc;
- }
-
- /**
- * Creates a string representation of this class filling in field specifics
- * when applicable.
- * @return the string representation of this class
- */
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder();
-
- buff.append("Directory Record Length: 0x" + Integer.toHexString(directoryRecordLength) +
- "\n");
- buff.append("Extended Attribute Record Length: 0x" +
- Integer.toHexString(extendedAttributeRecordLen) + "\n");
- buff.append("Extent Location: 0x" + Integer.toHexString(getLocationOfExtentLE()) + "\n");
- buff.append("Data Length: 0x" + Integer.toHexString(getDataLengthLE()) + "\n");
- buff.append("Recording Date/Time: " + createDateTimeString(recordingDateTime) + "\n");
- buff.append(getFileFlagString() + "\n");
- buff.append("File Unit Size Interleaved Mode: 0x" + Integer.toHexString(fileUnitSize) +
- "\n");
- buff.append("Interleave Gap Size: 0x" + Integer.toHexString(interleaveGapSize) + "\n");
- buff.append("Volume Sequence Number: 0x" +
- Integer.toHexString(getVolumeSequenceNumberLE()) + "\n");
- buff.append("Length of File Identifier: 0x" + Integer.toHexString(fileIdentLength) + "\n");
- buff.append("File Identifier: " + new String(fileIdentifier).trim() + "\n");
- if (paddingFieldPresent) {
- buff.append("Padding Field: 0x" + Integer.toHexString(paddingField) + "\n");
- }
-
- return buff.toString();
- }
-
- /*
- * Looks at the fileIdentifier and checks if it is made up
- * of visible not null ascii characters otherwise returns null
- */
- private String analyzeName(byte[] bArr) {
- for (int i = 0; i < bArr.length; i++) {
- if (bArr[i] < 32) {
- return null;
- }
- }
- String tmp = new String(bArr);
- return tmp;
- }
-
- public boolean isDirectoryFlagSet() {
- if (getFlagBit(fileFlag, ISO9660Constants.DIRECTORY_FLAG) == 1) {
- return true;
- }
- return false;
- }
-
- ByteProvider getByteProvider(ByteProvider provider, long logicalBlockSize, FSRL fsrl) {
-
- if (!this.isDirectoryFlagSet()) {
- long index = locationOfExtentLE * logicalBlockSize;
- return new ByteProviderWrapper(provider, index, dataLengthLE, fsrl);
- }
- return null;
- }
-
- /*
- * Parses the flag byte to return the string representation
- * of the flags bits which are set
- */
- private String getFileFlagString() {
- String flagString = "";
- flagString += "File Flags:\n";
- if (getFlagBit(fileFlag, ISO9660Constants.HIDDEN_FILE_FLAG) == 1) {
- flagString += "\tHidden File Flag Set";
- }
- if (getFlagBit(fileFlag, ISO9660Constants.DIRECTORY_FLAG) == 1) {
- flagString += "\tDirectory Flag Set";
- }
- if (getFlagBit(fileFlag, ISO9660Constants.ASSOCIATED_FILE_FLAG) == 1) {
- flagString += "\tAssociated File Flag Set";
- }
- if (getFlagBit(fileFlag, ISO9660Constants.EXTENDED_ATTRIBUTE_RECORD_INFO_FLAG) == 1) {
- flagString += "\tExtended Attribute Record Info Flag Set";
- }
- if (getFlagBit(fileFlag, ISO9660Constants.NOT_FINAL_DIRECTORY_RECORD_FLAG) == 1) {
- flagString += "\tNot Final Directory Record Flag";
- }
-
- return flagString;
- }
-
- private byte getFlagBit(byte flagByte, int flagIndex) {
- return (byte) ((flagByte >>> flagIndex) & 1);
- }
-
- /**
- * Parses the given buffer as an ISO9660 timestamp and returns it as a
- * human readable string representation.
- *
- * Invalid buffers that are still big enough to hold a timestamp are
- * still parsed and converted, albeit they are marked as invalid when
- * presented to the user.
- *
- * @param byteArray the buffer to parse (both standard and extended
- * formats are handled).
- * @return a string with the human readable timestamp.
- */
- private String createDateTimeString(byte[] byteArray) {
- if (byteArray == null || byteArray.length < 7) {
- return "INVALID (truncated or missing)";
- }
-
- // Time zone offset from GMT in 15 minute intervals,
- // starting at interval -48 (west) and running up to
- // interval 52 (east)
- int timeOffset = byteArray[byteArray.length - 1];
-
- int i1, i2, i3, i4, i5, i6;
- i1 = 1900 + byteArray[0]; // Years since 1900
- i2 = byteArray[1]; // Month of year
- i3 = byteArray[2]; // Day of month
- i4 = byteArray[3]; // Hour of day
- i5 = byteArray[4]; // Minute of hour
- i6 = byteArray[5]; // Second of minute
-
- // The buffer contains an invalid timezone offset.
- boolean validBuffer = true;
- if (timeOffset < -48 || timeOffset > 52) {
- validBuffer = false;
- }
-
- // The buffer contains an invalid date/time.
- try {
- LocalDateTime.of(i1, i2, i3, i4, i5, i6);
- } catch (DateTimeException exception) {
- validBuffer = false;
- }
-
- StringBuilder builder = new StringBuilder();
- if (!validBuffer) {
- builder.append("INVALID (");
- }
- int timezoneIntegral = timeOffset / 4;
- int timezoneFractional = (Math.abs(timeOffset) % 4) * 15;
- builder.append(String.format("%04d-%02d-%02d %02d:%02d:%02d GMT%c%02d%02d", i1, i2, i3,
- i4, i5, i6, timezoneIntegral < 0 ? '-' : '+', timezoneIntegral, timezoneFractional));
- if (!validBuffer) {
- builder.append(")");
- }
-
- return builder.toString();
- }
-
- private void setReaderToBigEndian(BinaryReader reader) {
- reader.setLittleEndian(false);
- }
-
- private void setReaderToLittleEndian(BinaryReader reader) {
- reader.setLittleEndian(true);
- }
-
- public long getVolumeIndex() {
- return volumeIndex;
- }
-
- public int getDirectoryRecordLength() {
- return directoryRecordLength;
- }
-
- public byte getExtendedAttributeRecordLen() {
- return extendedAttributeRecordLen;
- }
-
- public byte[] getRecordingDateTime() {
- return recordingDateTime;
- }
-
- public byte getFileFlag() {
- return fileFlag;
- }
-
- public byte getFileUnitSize() {
- return fileUnitSize;
- }
-
- public byte getInterleaveGapSize() {
- return interleaveGapSize;
- }
-
- public int getLocationOfExtentLE() {
- return locationOfExtentLE;
- }
-
- public int getLocationOfExtentBE() {
- return locationOfExtentBE;
- }
-
- public int getDataLengthLE() {
- return dataLengthLE;
- }
-
- public int getDataLengthBE() {
- return dataLengthBE;
- }
-
- public short getVolumeSequenceNumberLE() {
- return volumeSequenceNumberLE;
- }
-
- public short getVolumeSequenceNumberBE() {
- return volumeSequenceNumberBE;
- }
-
- public byte getFileIdentLength() {
- return fileIdentLength;
- }
-
- public byte[] getFileIdentifier() {
- return fileIdentifier;
- }
-
- public byte getPaddingField() {
- return paddingField;
- }
-
- public boolean isPaddingFieldPresent() {
- return paddingFieldPresent;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public ISO9660Directory getParentDirectory() {
- return parentDir;
- }
-
- public void setParentDirectory(ISO9660Directory parentDir) {
- this.parentDir = parentDir;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660FileSystemFactory.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660FileSystemFactory.java
index c3c88b4bbb..5c09a8aa49 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660FileSystemFactory.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660FileSystemFactory.java
@@ -15,9 +15,10 @@
*/
package ghidra.file.formats.iso9660;
-import java.io.IOException;
import java.util.Arrays;
+import java.io.IOException;
+
import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.FSRLRoot;
import ghidra.formats.gfilesystem.FileSystemService;
@@ -28,6 +29,8 @@ import ghidra.util.task.TaskMonitor;
public class ISO9660FileSystemFactory
implements GFileSystemFactoryByteProvider, GFileSystemProbeByteProvider {
+ private static final byte[] MAGIC_BYTES = { 0x43, 0x44, 0x30, 0x30, 0x31 }; // "CD001"
+
private static final long[] SIGNATURE_PROBE_OFFSETS = new long[] { 0x8000L, 0x8800L, 0x9000L };
@Override
@@ -43,10 +46,10 @@ public class ISO9660FileSystemFactory
}
private boolean isMagicSignatureAt(ByteProvider provider, long offset) throws IOException {
- int magicLen = ISO9660Constants.MAGIC_BYTES.length;
+ int magicLen = MAGIC_BYTES.length;
long providerLen = provider.length();
return (providerLen > offset + magicLen) &&
- Arrays.equals(provider.readBytes(offset, magicLen), ISO9660Constants.MAGIC_BYTES);
+ Arrays.equals(provider.readBytes(offset, magicLen), MAGIC_BYTES);
}
@Override
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Header.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Header.java
deleted file mode 100644
index cd3e09ed51..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660Header.java
+++ /dev/null
@@ -1,160 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.StructConverter;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class ISO9660Header implements StructConverter {
-
- //Hold all volume descriptors
- private ArrayList volumeDescriptorSet;
- //HashMaps to hold the LBA index and index size of each path table location
- private HashMap typeLIndexSizeTable;
- private HashMap typeMIndexSizeTable;
- private HashMap supplTypeLIndexSizeTable;
- private HashMap supplTypeMIndexSizeTable;
-
- //Hold the directory from the primary volume descriptor
- //This will be used as a starting point to recurse though the directory tree structure
- //inside of the analyzer
- private ISO9660Directory directory;
- private ISO9660VolumeDescriptor primaryDesc;
-
- private byte type;
-
- public ISO9660Header(BinaryReader reader) throws IOException {
- volumeDescriptorSet = new ArrayList();
- typeLIndexSizeTable = new HashMap();
- typeMIndexSizeTable = new HashMap();
- supplTypeLIndexSizeTable = new HashMap();
- supplTypeMIndexSizeTable = new HashMap();
-
- type = ISO9660Constants.BAD_TYPE; //Bad type to fall into loop
-
- while (type != ISO9660Constants.VOLUME_DESC_SET_TERMINATOR) {
-
- // not terminator set
- type = reader.readNextByte();
- reader.setPointerIndex(reader.getPointerIndex() - 1);
- if (type == ISO9660Constants.VOLUME_DESC_BOOT_RECORD) {
-
- volumeDescriptorSet.add(new ISO9660BootRecordVolumeDescriptor(reader));
- }
- else if (type == ISO9660Constants.VOLUME_DESC_PRIMARY_VOLUME_DESC) {
- primaryDesc = new ISO9660VolumeDescriptor(reader);
-
- directory = primaryDesc.getDirectoryEntry();
-
- volumeDescriptorSet.add(primaryDesc);
-
- typeLIndexSizeTable.put(primaryDesc.getTypeLPathTableLocation(),
- primaryDesc.getLogicalBlockSizeLE());
-
- typeMIndexSizeTable.put(primaryDesc.getTypeMPathTableLocation(),
- primaryDesc.getLogicalBlockSizeBE());
-
- if (primaryDesc.getDirectoryEntry().isPaddingFieldPresent()) {
- reader.setPointerIndex(reader.getPointerIndex() - 1);
- }
- }
- else if (type == ISO9660Constants.VOLUME_DESC_SUPPL_VOLUME_DESC) {
- ISO9660VolumeDescriptor supplDesc = new ISO9660VolumeDescriptor(reader);
-
- volumeDescriptorSet.add(supplDesc);
-
- supplTypeLIndexSizeTable.put(supplDesc.getTypeLPathTableLocation(),
- supplDesc.getLogicalBlockSizeLE());
-
- supplTypeMIndexSizeTable.put(supplDesc.getTypeMPathTableLocation(),
- supplDesc.getLogicalBlockSizeBE());
-
- if (supplDesc.getDirectoryEntry().isPaddingFieldPresent()) {
- reader.setPointerIndex(reader.getPointerIndex() - 1);
- }
- }
- }
- // got terminator set
- volumeDescriptorSet.add(new ISO9660SetTerminator(reader));
- }
-
- public ISO9660Directory getPrimaryDirectory() {
-
- return directory;
- }
-
- public ArrayList getVolumeDescriptorSet() {
- return volumeDescriptorSet;
- }
-
- public HashMap getTypeLIndexSizeTable() {
- return typeLIndexSizeTable;
- }
-
- public HashMap getTypeMIndexSizeTable() {
- return typeMIndexSizeTable;
- }
-
- public HashMap getSupplTypeLIndexSizeTable() {
- return supplTypeLIndexSizeTable;
- }
-
- public HashMap getSupplTypeMIndexSizeTable() {
- return supplTypeMIndexSizeTable;
- }
-
- public ISO9660VolumeDescriptor getPrimaryVolumeDescriptor() {
- return primaryDesc;
- }
-
- /**
- * Creates a string representation of this class filling in field specifics
- * when applicable.
- * @return the string representation of this class
- */
- @Override
- public String toString() {
- StringBuffer buff = new StringBuffer();
-
- for (ISO9660BaseVolume volume : volumeDescriptorSet) {
-
- buff.append(volume.toString());
- }
-
- return buff.toString();
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc = new StructureDataType("ISO9660Header", 0);
- DataType data;
- for (ISO9660BaseVolume volume : volumeDescriptorSet) {
-
- data = volume.toDataType();
-
- struc.add(data);
- }
-
- return struc;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660PathTable.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660PathTable.java
deleted file mode 100644
index 01ec178583..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660PathTable.java
+++ /dev/null
@@ -1,140 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.StructConverter;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-
-public class ISO9660PathTable implements StructConverter {
-
- private byte dirIdentifierLength;
- private byte extendedAttributeRecordLength;
- private int locationOfExtent;
- private short directoryNumberPathIndex;
- private byte[] directoryIdentifier;
- private byte paddingField;
- private boolean paddingFieldPresent;
- private long volumeIndex;
- private boolean littleEndian;
-
- public ISO9660PathTable(BinaryReader reader, boolean littleEndian) throws IOException {
- reader.setLittleEndian(littleEndian);
- this.littleEndian = littleEndian;
- volumeIndex = reader.getPointerIndex();
- dirIdentifierLength = reader.readNextByte();
- extendedAttributeRecordLength = reader.readNextByte();
- locationOfExtent = reader.readNextInt();
- directoryNumberPathIndex = reader.readNextShort();
- directoryIdentifier = reader.readNextByteArray(dirIdentifierLength);
-
- //The padding field is only present if the directoryIdentifierLength
- //is odd, otherwise it is not used.
- if (dirIdentifierLength % 2 != 0) {
- paddingField = reader.readNextByte();
- paddingFieldPresent = true;
- }
- else {
- paddingFieldPresent = false;
- }
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc;
- if (littleEndian) {
- struc = new StructureDataType("ISO9660TypeLPathTable", 0);
- }
- else {
- struc = new StructureDataType("ISO9660TypeMPathTable", 0);
- }
-
- struc.add(BYTE, "Directory Identifier Length", "Length of Directory Identifier");
- struc.add(BYTE, "Extended Attribute Record Length", "Length of Extended Attribute Record");
- struc.add(DWORD, "Location of Extent", "Location of Extent in Little-endian format");
- struc.add(WORD, "Directory Number",
- "Number of parent directory (an index in to the path table)");
- struc.add(new ArrayDataType(BYTE, directoryIdentifier.length, 1), "Directory Identifier",
- "Directory Identifier");
- if (paddingFieldPresent) {
- struc.add(BYTE, "Padding Field", "Padding Field");
- }
- return struc;
- }
-
- /**
- * Creates a string representation of this class filling in field specifics
- * when applicable.
- * @return the string representation of this class
- */
- @Override
- public String toString() {
- StringBuffer buff = new StringBuffer();
-
- buff.append("Directory Identifier Length: 0x" + Integer.toHexString(dirIdentifierLength) +
- "\n");
- buff.append("Extended Attribute Record Length: " +
- Integer.toHexString(extendedAttributeRecordLength) + "\n");
- buff.append("Location of Extent (LBA): 0x" + Integer.toHexString(locationOfExtent) + "\n");
- buff.append("Directory Number: 0x" + Integer.toHexString(directoryNumberPathIndex) + "\n");
- buff.append("Directory Identifier: " + new String(directoryIdentifier).trim() + "\n");
- if (paddingFieldPresent) {
- buff.append("PaddingF ield: 0x" + Integer.toHexString(paddingField) + "\n");
- }
-
- return buff.toString();
- }
-
- public byte getDirIdentifierLength() {
- return dirIdentifierLength;
- }
-
- public byte getExtendedAttributeRecordLength() {
- return extendedAttributeRecordLength;
- }
-
- public int getLocationOfExtent() {
- return locationOfExtent;
- }
-
- public short getDirectoryNumberPathIndex() {
- return directoryNumberPathIndex;
- }
-
- public byte[] getDirectoryIdentifier() {
- return directoryIdentifier;
- }
-
- public byte getPaddingField() {
- return paddingField;
- }
-
- public boolean isPaddingFieldPresent() {
- return paddingFieldPresent;
- }
-
- public long getVolumeIndex() {
- return volumeIndex;
- }
-
- public boolean isLittleEndian() {
- return littleEndian;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660SetTerminator.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660SetTerminator.java
deleted file mode 100644
index 2974dd7837..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660SetTerminator.java
+++ /dev/null
@@ -1,54 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-
-/**
- * The terminator flag to note the end of the set of volume descriptors
- * on this ISO
- */
-public class ISO9660SetTerminator extends ISO9660BaseVolume {
-
- private long endVolumeIndex;
-
- public ISO9660SetTerminator(BinaryReader reader) throws IOException {
-
- super(reader);
- endVolumeIndex = reader.getPointerIndex();
-
- }
-
- public long getEndVolumeIndex() {
- return endVolumeIndex;
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc = new StructureDataType("ISO9600SetTerminator", 0);
- struc.add(BYTE, "Type", "Volume Descriptor Type");
- struc.add(new ArrayDataType(BYTE, super.getIdentifier().length, 1), "Identifier",
- "Identifier");
- struc.add(BYTE, "Version", "Volume Descriptor Version");
-
- return struc;
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660VolumeDescriptor.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660VolumeDescriptor.java
deleted file mode 100644
index b1811b6af9..0000000000
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/iso9660/ISO9660VolumeDescriptor.java
+++ /dev/null
@@ -1,489 +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.file.formats.iso9660;
-
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.program.model.data.*;
-import ghidra.util.exception.DuplicateNameException;
-
-import java.io.IOException;
-import java.time.DateTimeException;
-import java.time.LocalDateTime;
-
-public class ISO9660VolumeDescriptor extends ISO9660BaseVolume {
- private byte unused; // Always 0x00
- private byte[] systemIdentifier; // Length 0x20
- private byte[] volumeIdentifier; // Length 0x20
- private long unused2; // All 0x00
- private int volumeSpaceSizeLE; // Little-endian
- private int volumeSpaceSizeBE; // Big-endian
- private byte[] unused3; // Length 0x20
- private short volumeSetSizeLE; // Little-endian
- private short volumeSetSizeBE; // Big-endian
- private short volumeSeqNumberLE; // Little-endian
- private short volumeSeqNumberBE; // Big-endian
- private short logicalBlockSizeLE; // Little-endian
- private short logicalBlockSizeBE; // Big-endian
- private int pathTableSizeLE; // Litte-endian
- private int pathTableSizeBE; // Big-endian
- private int typeLPathTableLocation; // -int32_LSB-
- private int optionalTypeLPathTableLocation; // -int32_LSB-
- private int typeMPathTableLocation; // -int32_MSB-
- private int optionalTypeMPathTableLocation; // -int32_MSB-
- private ISO9660Directory directoryEntry; // Length 0x20
- private byte[] volumeSetIdentifier; // Length 0x80
- private byte[] publisherIdentifier; // Length 0x80
- private byte[] dataPreparerIdentifier; // Length 0x80
- private byte[] applicationIdentifier; // Length 0x80
- private byte[] copyrightFileIdentifier; // Length 0x26
- private byte[] abstractFileIdentifier; // Length 0x24
- private byte[] bibliographicFileIdentifier; // Length 0x25
- private byte[] volumeCreationDateTime; // Length 0x11
- private byte[] volumeModifyDateTime; // Length 0x11
- private byte[] volumeExpirationDateTime; // Length 0x11
- private byte[] volumeEffectiveDateTime; // length 0x11
- private byte fileStructureVersion; // -int8-
- private byte unused4; // Always 0x00
- private byte[] applicationUsed; // Length 0x200
- private byte[] reserved; // Length 0x28D
-
- public ISO9660VolumeDescriptor(BinaryReader reader) throws IOException {
-
- super(reader);
- unused = reader.readNextByte();
- systemIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_32);
- volumeIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_32);
- unused2 = reader.readNextLong();
- volumeSpaceSizeLE = reader.readNextInt();
- volumeSpaceSizeBE = readIntBigEndian(reader);
- unused3 = reader.readNextByteArray(ISO9660Constants.UNUSED_SPACER_LEN_32);
- volumeSetSizeLE = reader.readNextShort();
- volumeSetSizeBE = readShortBigEndian(reader);
- volumeSeqNumberLE = reader.readNextShort();
- volumeSeqNumberBE = readShortBigEndian(reader);
- logicalBlockSizeLE = reader.readNextShort();
- logicalBlockSizeBE = readShortBigEndian(reader);
- pathTableSizeLE = reader.readNextInt();
- pathTableSizeBE = readIntBigEndian(reader);
- typeLPathTableLocation = reader.readNextInt();
- optionalTypeLPathTableLocation = reader.readNextInt();
- typeMPathTableLocation = readIntBigEndian(reader);
- optionalTypeMPathTableLocation = readIntBigEndian(reader);
- directoryEntry = new ISO9660Directory(reader);
- volumeSetIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_128);
- publisherIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_128);
- dataPreparerIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_128);
- applicationIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_128);
- copyrightFileIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_38);
- abstractFileIdentifier = reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_36);
- bibliographicFileIdentifier =
- reader.readNextByteArray(ISO9660Constants.IDENTIFIER_LENGTH_37);
- volumeCreationDateTime = reader.readNextByteArray(ISO9660Constants.DATE_TIME_LENGTH_17);
- volumeModifyDateTime = reader.readNextByteArray(ISO9660Constants.DATE_TIME_LENGTH_17);
- volumeExpirationDateTime = reader.readNextByteArray(ISO9660Constants.DATE_TIME_LENGTH_17);
- volumeEffectiveDateTime = reader.readNextByteArray(ISO9660Constants.DATE_TIME_LENGTH_17);
- fileStructureVersion = reader.readNextByte();
- unused4 = reader.readNextByte();
- applicationUsed = reader.readNextByteArray(ISO9660Constants.UNUSED_SPACER_LEN_512);
- reserved = reader.readNextByteArray(ISO9660Constants.RESERVED_SIZE);
-
- }
-
- private int readIntBigEndian(BinaryReader reader) throws IOException {
-
- setReaderToBigEndian(reader);
- int tmp = reader.readNextInt();
- setReaderToLittleEndian(reader);
-
- return tmp;
- }
-
- private short readShortBigEndian(BinaryReader reader) throws IOException {
-
- setReaderToBigEndian(reader);
- short tmp = reader.readNextShort();
- setReaderToLittleEndian(reader);
-
- return tmp;
- }
-
- @Override
- public DataType toDataType() throws DuplicateNameException, IOException {
- Structure struc;
- if (super.getTypeCode() == ISO9660Constants.VOLUME_DESC_PRIMARY_VOLUME_DESC) {
- struc = new StructureDataType("ISO9600PrimaryVolumeDescriptor", 0);
- }
- else if (super.getTypeCode() == ISO9660Constants.VOLUME_DESC_SUPPL_VOLUME_DESC) {
- struc = new StructureDataType("ISO9600SupplementaryVolumeDescriptor", 0);
- }
- else {
- struc = null;
- }
-
- struc.add(BYTE, "Type Code", "Type of volume descriptor");
- struc.add(new ArrayDataType(BYTE, super.getIdentifier().length, 1), "Standard Identifier",
- "Always 'CD001'");
- struc.add(BYTE, "Version", "Always 0x01");
- struc.add(BYTE, "Unused", "Always 0x00");
- struc.add(new ArrayDataType(BYTE, systemIdentifier.length, 1), "System Identifier",
- "Name of the system to act upon sectors 0x00-0x0F");
- struc.add(new ArrayDataType(BYTE, volumeIdentifier.length, 1), "Volume Identifier",
- "Identification for this volume");
- struc.add(QWORD, "Unused", "Always 0x00");
- struc.add(QWORD, "Volume Space Size", "Number of logical blocks the volume is recorded");
- struc.add(new ArrayDataType(BYTE, unused3.length, 1), "Unused", "Always 0x00");
- struc.add(DWORD, "Volume Set Size", "Size of the set in this logical volume");
- struc.add(DWORD, "Volume Sequence Number", "Number of disks in volume set");
- struc.add(DWORD, "Logical block Size", "Size of the logical block");
- struc.add(QWORD, "Path Table Size", "Size of the path table");
- struc.add(DWORD, "Location of Type-L Path Dable",
- "LBA location of the path table containing only litle-endian values");
- struc.add(DWORD, "Location of Optional Type-L Path Table",
- "LBA location of the optional path table containing only little-endian values");
- struc.add(DWORD, "Location of Type-M Path Table",
- "LBA location of the path table containing only big-endian values");
- struc.add(DWORD, "Location of Optional Type-M Path Table",
- "LBA location of the optional path table containing only big-endian values");
- struc.add(directoryEntry.toDataType());
- struc.add(new ArrayDataType(BYTE, volumeSetIdentifier.length, 1), "Volume Set Identifier",
- "Identifier of the volume set which this volume is a member");
- struc.add(new ArrayDataType(BYTE, publisherIdentifier.length, 1), "Publisher Identifier",
- "The volume publisher");
- struc.add(new ArrayDataType(BYTE, dataPreparerIdentifier.length, 1),
- "Data Preparer Identifier", "Identifier of person(s) who prepared data for this volume");
- struc.add(new ArrayDataType(BYTE, applicationIdentifier.length, 1),
- "Application Identifier", "How the data are recorded on this volume");
- struc.add(new ArrayDataType(BYTE, copyrightFileIdentifier.length, 1),
- "Copyright File Identifier",
- "Filename of file that contains copyright information on volume set");
- struc.add(new ArrayDataType(BYTE, abstractFileIdentifier.length, 1),
- "Abstract File Identifier",
- "Filename of file that contains abstract information on volume set");
- struc.add(new ArrayDataType(BYTE, bibliographicFileIdentifier.length, 1),
- "Bibliographic File Identifier",
- "Filename of file that contians bibliographic information on volume set");
- struc.add(new ArrayDataType(BYTE, volumeCreationDateTime.length, 1),
- "Volume Creation Date and Time", "Date and time volume was created");
- struc.add(new ArrayDataType(BYTE, volumeModifyDateTime.length, 1),
- "Volume Modification Date and Time", "Date and time volume was modified");
- struc.add(new ArrayDataType(BYTE, volumeExpirationDateTime.length, 1),
- "Volume Expiration Date and Time", "Date and time volume was created");
- struc.add(new ArrayDataType(BYTE, volumeEffectiveDateTime.length, 1),
- "Volume Effective Date and Time", "Date and time after which the volume may be used");
- struc.add(BYTE, "File Structure Version", "Directory records and path table version");
- struc.add(BYTE, "Unused", "Always 0x00");
- struc.add(new ArrayDataType(BYTE, applicationUsed.length, 1), "Application Used",
- "Contents not defined by ISO 9660");
- struc.add(new ArrayDataType(BYTE, reserved.length, 1), "Reserved", "Reserved by ISO");
-
- return struc;
- }
-
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder();
-
- buff.append("Type Code: 0x" + Integer.toHexString(super.getTypeCode()) + " => " +
- getTypeCodeString() + "\n");
- buff.append("Standard Identifier: " + new String(super.getIdentifier()).trim() + "\n");
- buff.append("Version: 0x" + Integer.toHexString(super.getVersion()) + "\n");
- buff.append("Unused: 0x" + Integer.toHexString(unused) + "\n");
- buff.append("System Identifier: " + new String(systemIdentifier).trim() + "\n");
- buff.append("Volume Identifier: " + new String(volumeIdentifier).trim() + "\n");
- buff.append("Unused Field: 0x" + Long.toHexString(unused2) + "\n");
- buff.append("Volume Space Size: 0x" + Integer.toHexString(getVolumeSpaceSizeLE()) + "\n");
- buff.append("Unused: " + new String(unused3).trim() + "\n");
- buff.append("Volume Set Size: 0x" + Integer.toHexString(getVolumeSetSizeLE()) + "\n");
- buff.append("Volume Sequence Number: 0x" + Integer.toHexString(getVolumeSeqNumberLE()) +
- "\n");
- buff.append("Logical Block Size: 0x" + Integer.toHexString(getLogicalBlockSizeLE()) + "\n");
- buff.append("Path Table Size: 0x" + Integer.toHexString(getPathTableSizeLE()) + "\n");
- buff.append("LBA Location of Type-L Path Table: 0x" +
- Integer.toHexString(typeLPathTableLocation) + "\n");
- buff.append("LBA Location of Optional Type-L Path Table: 0x" +
- Integer.toHexString(optionalTypeLPathTableLocation) + "\n");
- buff.append("LBA Location of Type-M Path Table: 0x" +
- Integer.toHexString(typeMPathTableLocation) + "\n");
- buff.append("LBA Location of Optional Type-M Path Table: 0x" +
- Integer.toHexString(optionalTypeMPathTableLocation) + "\n");
- buff.append("Calculated Location of Type-L Path Table: 0x" +
- Integer.toHexString(typeLPathTableLocation * getLogicalBlockSizeLE()) + "\n");
- buff.append("Calculated Location of Type-M Path Table: 0x" +
- Integer.toHexString(typeMPathTableLocation * getLogicalBlockSizeBE()) + "\n");
- buff.append("Directory Entry for Root Directory: \n" + directoryEntry.toString() + "\n");
- buff.append("Volume Set Identifier: " + new String(volumeSetIdentifier).trim() + "\n");
- buff.append("Publisher Identifier: " + new String(publisherIdentifier).trim() + "\n");
- buff.append("Data Preparer Identifier: " + new String(dataPreparerIdentifier).trim() + "\n");
- buff.append("Application Identifier: " + new String(applicationIdentifier).trim() + "\n");
- buff.append("Copyright File Identifier: " + new String(copyrightFileIdentifier).trim() +
- "\n");
- buff.append("Abstract File Identifier: " + new String(abstractFileIdentifier).trim() + "\n");
- buff.append("Biliographic File Identifier: " + new String(bibliographicFileIdentifier) +
- "\n");
- buff.append("Volume Creation Date/Time: " + createDateTimeString(volumeCreationDateTime) +
- "\n");
- buff.append("Volume Modification Date/Time: " + createDateTimeString(volumeModifyDateTime) +
- "\n");
- buff.append("Volume Expiration Date/Time: " + createDateTimeString(volumeCreationDateTime) +
- "\n");
- buff.append("Volume Effective Date/Time: " + createDateTimeString(volumeEffectiveDateTime) +
- "\n");
- buff.append("File Structure Version: 0x" + Integer.toHexString(fileStructureVersion) + "\n");
- buff.append("Unused: 0x" + Integer.toHexString(unused4) + "\n");
-
- return buff.toString();
- }
-
- /**
- * Checks whether the given string is entirely made up of ASCII digits.
- *
- * @param string the string to check.
- * @return true if all characters in the string are ASCII digits, false
- * otherwise.
- */
- private boolean isDigitsStringValid(String string) {
- for (int i = 0; i < string.length(); i++) {
- char c = string.charAt(i);
- if (c < '0' || c > '9') {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Parses the given buffer as an ISO9660 timestamp and returns it as a
- * human readable string representation.
- *
- * Invalid buffers that are still big enough to hold a timestamp are
- * still parsed and converted, albeit they are marked as invalid when
- * presented to the user.
- *
- * @param byteArray the buffer to parse (only extended timestamp format
- * is handled).
- * @return a string with the human readable timestamp.
- */
- protected String createDateTimeString(byte[] byteArray) {
- if (byteArray == null || byteArray.length < 17) {
- return "INVALID (truncated or missing)";
- }
-
- String s1, s2, s3, s4, s5, s6, s7;
-
- // Time zone offset from GMT in 15 minute intervals,
- // starting at interval -48 (west) and running up to
- // interval 52 (east)
- int timeOffset = byteArray[byteArray.length - 1];
-
- String bString = new String(byteArray);
- s1 = bString.substring(0, 4); //year 1 to 9999
- s2 = bString.substring(4, 6); //month 1 to 12
- s3 = bString.substring(6, 8); //day 1 to 31
- s4 = bString.substring(8, 10); //hour 0 to 23
- s5 = bString.substring(10, 12); //minute 0 to 59
- s6 = bString.substring(12, 14); //second 0 to 59
- s7 = bString.substring(14, 16); //ms 0 to 99
-
- // Validate strings first.
- boolean validBuffer = isDigitsStringValid(s1) && isDigitsStringValid(s2) && isDigitsStringValid(s3) &&
- isDigitsStringValid(s4) && isDigitsStringValid(s5) && isDigitsStringValid(s6) && isDigitsStringValid(s7);
-
- try {
- // The buffer contains an invalid date/time.
- LocalDateTime.of(Integer.parseInt(s1), Integer.parseInt(s2), Integer.parseInt(s3),
- Integer.parseInt(s4), Integer.parseInt(s5), Integer.parseInt(s6));
- } catch (NumberFormatException | DateTimeException e) {
- validBuffer = false;
- }
-
- // The buffer contains an invalid timezone offset.
- if (timeOffset < -48 || timeOffset > 52) {
- validBuffer = false;
- }
-
- /*
- * Time zone offset from GMT in 15 minute intervals,
- * starting at interval -48 (west) and running up to
- * interval 52 (east).
- */
- int timezoneIntegral = timeOffset / 4;
- int timezoneFractional = (Math.abs(timeOffset) % 4) * 15;
-
- StringBuilder builder = new StringBuilder();
- if (!validBuffer) {
- builder.append("INVALID(");
- }
-
- builder.append(String.format("%s-%s-%s %s:%s:%s.%s GMT%c%02d%02d", s1, s2, s3, s4, s5, s6, s7,
- timezoneIntegral < 0 ? '-' : '+', timezoneIntegral, timezoneFractional));
-
- if (!validBuffer) {
- builder.append(")");
- }
-
- return builder.toString();
- }
-
- public byte getUnused() {
- return unused;
- }
-
- public byte[] getSystemIdentifier() {
- return systemIdentifier;
- }
-
- public byte[] getVolumeIdentifier() {
- return volumeIdentifier;
- }
-
- public long getUnused2() {
- return unused2;
- }
-
- public byte[] getUnused3() {
- return unused3;
- }
-
- public int getVolumeSpaceSizeLE() {
- return volumeSpaceSizeLE;
- }
-
- public int getVolumeSpaceSizeBE() {
- return volumeSpaceSizeBE;
- }
-
- public short getVolumeSetSizeLE() {
- return volumeSetSizeLE;
- }
-
- public short getVolumeSetSizeBE() {
- return volumeSetSizeBE;
- }
-
- public short getVolumeSeqNumberLE() {
- return volumeSeqNumberLE;
- }
-
- public short getVolumeSeqNumberBE() {
- return volumeSeqNumberBE;
- }
-
- public short getLogicalBlockSizeLE() {
- return logicalBlockSizeLE;
- }
-
- public short getLogicalBlockSizeBE() {
- return logicalBlockSizeBE;
- }
-
- public int getPathTableSizeLE() {
- return pathTableSizeLE;
- }
-
- public int getPathTableSizeBE() {
- return pathTableSizeBE;
- }
-
- public int getTypeLPathTableLocation() {
- return typeLPathTableLocation;
- }
-
- public int getOptionalTypeLPathTableLocation() {
- return optionalTypeLPathTableLocation;
- }
-
- public int getTypeMPathTableLocation() {
- return typeMPathTableLocation;
- }
-
- public int getOptionalTypeMPathTableLocation() {
- return optionalTypeMPathTableLocation;
- }
-
- public ISO9660Directory getDirectoryEntry() {
- return directoryEntry;
- }
-
- public byte[] getVolumeSetIdentifier() {
- return volumeSetIdentifier;
- }
-
- public byte[] getPublisherIdentifier() {
- return publisherIdentifier;
- }
-
- public byte[] getDataPreparerIdentifier() {
- return dataPreparerIdentifier;
- }
-
- public byte[] getApplicationIdentifier() {
- return applicationIdentifier;
- }
-
- public byte[] getCopyrightFileIdentifier() {
- return copyrightFileIdentifier;
- }
-
- public byte[] getAbstractFileIdentifier() {
- return abstractFileIdentifier;
- }
-
- public byte[] getBibliographicFileIdentifier() {
- return bibliographicFileIdentifier;
- }
-
- public byte[] getVolumeCreationDateTime() {
- return volumeCreationDateTime;
- }
-
- public byte[] getVolumeModifyDateTime() {
- return volumeModifyDateTime;
- }
-
- public byte[] getVolumeExpirationDateTime() {
- return volumeExpirationDateTime;
- }
-
- public byte[] getVolumeEffectiveDateTime() {
- return volumeEffectiveDateTime;
- }
-
- public byte getFileStructureVersion() {
- return fileStructureVersion;
- }
-
- public byte getUnused4() {
- return unused4;
- }
-
- public byte[] getApplicationUsed() {
- return applicationUsed;
- }
-
- public byte[] getReserved() {
- return reserved;
- }
-
- private void setReaderToBigEndian(BinaryReader reader) {
- reader.setLittleEndian(false);
- }
-
- private void setReaderToLittleEndian(BinaryReader reader) {
- reader.setLittleEndian(true);
- }
-
-}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/lzss/LzssAnalyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/lzss/LzssAnalyzer.java
index 778d402d9f..1917c140e1 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/lzss/LzssAnalyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/lzss/LzssAnalyzer.java
@@ -43,8 +43,7 @@ public class LzssAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
throws Exception, CancelledException {
Address address = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
-
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
LzssCompressionHeader header = new LzssCompressionHeader(provider);
if (header.getSignature() != LzssConstants.SIGNATURE_COMPRESSION) {
@@ -72,22 +71,27 @@ public class LzssAnalyzer extends FileFormatAnalyzer implements AnalysisWorker {
return getName();
}
+ @Override
public boolean canAnalyze(Program program) {
return LzssUtil.isLZSS(program);
}
+ @Override
public boolean getDefaultEnablement(Program program) {
return LzssUtil.isLZSS(program);
}
+ @Override
public String getDescription() {
return "Annotates an LZSS compression file.";
}
+ @Override
public String getName() {
return "LZSS Compression Annotation";
}
+ @Override
public boolean isPrototype() {
return true;
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/xar/XARUtil.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/xar/XARUtil.java
index 2d2cca748a..8cf375f4cb 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/xar/XARUtil.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/xar/XARUtil.java
@@ -15,17 +15,17 @@
*/
package ghidra.file.formats.xar;
+import java.util.Arrays;
+
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.MemoryByteProvider;
import ghidra.program.model.listing.Program;
-import java.util.Arrays;
-
public class XARUtil {
public final static boolean isXAR( Program program ) {
- ByteProvider provider = new MemoryByteProvider( program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace() );
+ ByteProvider provider =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, true);
return isXAR( provider );
}
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/yaffs2/YAFFS2Analyzer.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/yaffs2/YAFFS2Analyzer.java
index 6a1e12a945..c9e923c94c 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/yaffs2/YAFFS2Analyzer.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/yaffs2/YAFFS2Analyzer.java
@@ -81,7 +81,7 @@ public class YAFFS2Analyzer extends FileFormatAnalyzer implements AnalysisWorker
Address address = program.getMinAddress();
- ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, true);
int index = 0;
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/PEUtil.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/PEUtil.java
index 0a1d163c38..da46056d63 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/PEUtil.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/PEUtil.java
@@ -34,8 +34,8 @@ public class PEUtil {
return true;
}
if (format.equals(BinaryLoader.BINARY_NAME)) {
- MemoryByteProvider mbp = new MemoryByteProvider(program.getMemory(),
- program.getAddressFactory().getDefaultAddressSpace());
+ MemoryByteProvider mbp =
+ MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
try {
BinaryReader reader = new BinaryReader(mbp, true/*LittleEndian*/);
DOSHeader dosHeader = new DOSHeader(reader);
diff --git a/Ghidra/Processors/JVM/src/main/java/ghidra/javaclass/analyzers/JvmSwitchAnalyzer.java b/Ghidra/Processors/JVM/src/main/java/ghidra/javaclass/analyzers/JvmSwitchAnalyzer.java
index 902e7bede4..d4feea8c22 100644
--- a/Ghidra/Processors/JVM/src/main/java/ghidra/javaclass/analyzers/JvmSwitchAnalyzer.java
+++ b/Ghidra/Processors/JVM/src/main/java/ghidra/javaclass/analyzers/JvmSwitchAnalyzer.java
@@ -15,10 +15,11 @@
*/
package ghidra.javaclass.analyzers;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.io.IOException;
+
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.services.AnalysisPriority;
@@ -97,8 +98,7 @@ public class JvmSwitchAnalyzer extends AbstractJavaAnalyzer {
monitor.setMaximum(set.getNumAddresses());
monitor.setProgress(0);
- ByteProvider provider =
- new MemoryByteProvider(program.getMemory(), program.getMinAddress());
+ ByteProvider provider = MemoryByteProvider.createProgramHeaderByteProvider(program, false);
BinaryReader reader = new BinaryReader(provider, false);
Listing listing = program.getListing();