GP-0: Certify and cleanup

This commit is contained in:
Ryan Kurtz 2025-04-02 09:21:37 -04:00
parent 90a16f9963
commit 8701d22356
9 changed files with 53 additions and 99 deletions

View file

@ -19,84 +19,46 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.format.omf.OmfException;
import ghidra.app.util.bin.format.omf.*; import ghidra.app.util.bin.format.omf.OmfString;
import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord.MemberHeader;
import ghidra.program.model.data.*;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
public class Omf51Library { public class Omf51Library {
private Omf51RecordFactory factory; private List<MemberHeader> members = new ArrayList<>();
private ArrayList<MemberHeader> members = new ArrayList<>();
public static class MemberHeader { public record MemberHeader(long offset, long size, String name) {}
public long offset;
public long size;
public String name;
}
/** /**
* Creates a new {@link Omf51Library} * Creates a new {@link Omf51Library}
* *
* @param reader A {@link BinaryReader} positioned at the start of the record * @param factory A {@link Omf51RecordFactory}
*/
public Omf51Library(Omf51RecordFactory factory) {
this.factory = factory;
}
/**
* Attempts to parse OMF-51 library members
*
* @throws IOException if an IO-related error occurred * @throws IOException if an IO-related error occurred
* @throws OmfException if the required OMF-51 records could not be read * @throws OmfException if the required OMF-51 records could not be read
*/ */
public void parseMembers() throws IOException, OmfException { public Omf51Library(Omf51RecordFactory factory) throws OmfException, IOException {
OmfRecord record = factory.readNextRecord(); if (!(factory.readNextRecord() instanceof Omf51LibraryHeaderRecord libraryHeader)) {
if (record == null || !(record instanceof Omf51LibraryHeaderRecord)) {
throw new OmfException("Unable to read library header record"); throw new OmfException("Unable to read library header record");
} }
Omf51LibraryHeaderRecord libraryHeader = (Omf51LibraryHeaderRecord)record;
factory.getReader().setPointerIndex(libraryHeader.getModNamesOffset()); factory.getReader().setPointerIndex(libraryHeader.getModNamesOffset());
record = factory.readNextRecord(); if (!(factory.readNextRecord() instanceof Omf51LibraryModuleNamesRecord modNamesRecord)) {
if (record == null || !(record instanceof Omf51LibraryModuleNamesRecord)) {
throw new OmfException("Unable to read library module names record"); throw new OmfException("Unable to read library module names record");
} }
Omf51LibraryModuleNamesRecord modNamesRecord = (Omf51LibraryModuleNamesRecord)record; if (!(factory.readNextRecord() instanceof Omf51LibraryModuleLocationsRecord modLocations)) {
record = factory.readNextRecord();
if (record == null || !(record instanceof Omf51LibraryModuleLocationsRecord)) {
throw new OmfException("Unable to read library module locations record"); throw new OmfException("Unable to read library module locations record");
} }
Omf51LibraryModuleLocationsRecord modLocations = (Omf51LibraryModuleLocationsRecord)record;
List<Omf51LibraryModuleLocation> locations = modLocations.getLocations(); List<Omf51LibraryModuleLocation> locations = modLocations.getLocations();
int index = 0; int index = 0;
Msg.info(this, "Iterating mod names");
for (OmfString moduleName : modNamesRecord.getNames()) { for (OmfString moduleName : modNamesRecord.getNames()) {
int size = 0; int currentOffset = locations.get(index).getOffset();
if (index + 1 < locations.size()) { int nextOffset = index + 1 < locations.size() ? locations.get(index + 1).getOffset()
size = locations.get(index + 1).getOffset() - locations.get(index).getOffset(); : libraryHeader.getModNamesOffset();
} else { int size = nextOffset - currentOffset;
size = libraryHeader.getModNamesOffset() - locations.get(index).getOffset(); members.add(new MemberHeader(currentOffset, size, moduleName.str()));
}
MemberHeader header = new MemberHeader();
header.name = moduleName.str();
header.size = size;
header.offset = locations.get(index).getOffset();
members.add(header);
index++; index++;
} }
} }
@ -104,7 +66,7 @@ public class Omf51Library {
/** /**
* {@return the list of members} * {@return the list of members}
*/ */
public ArrayList<MemberHeader> getMembers() { public List<MemberHeader> getMembers() {
return members; return members;
} }
} }

View file

@ -16,8 +16,8 @@
package ghidra.app.util.bin.format.omf.omf51; package ghidra.app.util.bin.format.omf.omf51;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*; import ghidra.app.util.bin.format.omf.*;
@ -29,7 +29,7 @@ public class Omf51LibraryDictionaryRecord extends OmfRecord {
private List<List<OmfString>> moduleSymbolMap = new ArrayList<>(); private List<List<OmfString>> moduleSymbolMap = new ArrayList<>();
/** /**
* Creates a new {@link Omf51LibraryDictionaryRecord} record * Creates a new {@link Omf51LibraryDictionaryRecord}
* *
* @param reader A {@link BinaryReader} positioned at the start of the record * @param reader A {@link BinaryReader} positioned at the start of the record
* @throws IOException if an IO-related error occurred * @throws IOException if an IO-related error occurred
@ -48,12 +48,12 @@ public class Omf51LibraryDictionaryRecord extends OmfRecord {
dataReader.readNextByte(); dataReader.readNextByte();
moduleSymbolMap.add(symbols); moduleSymbolMap.add(symbols);
symbols = new ArrayList<>(); symbols = new ArrayList<>();
continue;
} }
else {
symbols.add(OmfUtils.readString(dataReader)); symbols.add(OmfUtils.readString(dataReader));
} }
} }
}
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
@ -63,7 +63,8 @@ public class Omf51LibraryDictionaryRecord extends OmfRecord {
Integer moduleIndex = 0; Integer moduleIndex = 0;
for (List<OmfString> symbols : moduleSymbolMap) { for (List<OmfString> symbols : moduleSymbolMap) {
for (OmfString symbol : symbols) { for (OmfString symbol : symbols) {
struct.add(symbol.toDataType(), symbol.getDataTypeSize(), "symbol%d".formatted(moduleIndex), null); struct.add(symbol.toDataType(), symbol.getDataTypeSize(),
"symbol%d".formatted(moduleIndex), null);
} }
struct.add(BYTE, "terminator%d".formatted(moduleIndex), null); struct.add(BYTE, "terminator%d".formatted(moduleIndex), null);

View file

@ -16,11 +16,9 @@
package ghidra.app.util.bin.format.omf.omf51; package ghidra.app.util.bin.format.omf.omf51;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*; import ghidra.app.util.bin.format.omf.*;
import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord.MemberHeader;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;

View file

@ -19,9 +19,8 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter; import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.omf.*; import ghidra.app.util.bin.format.omf.OmfUtils;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
public class Omf51LibraryModuleLocation { public class Omf51LibraryModuleLocation {
@ -62,7 +61,7 @@ public class Omf51LibraryModuleLocation {
return (blockNumber * BLOCK_SIZE) + byteNumber; return (blockNumber * BLOCK_SIZE) + byteNumber;
} }
public static DataType toDataType() throws DuplicateNameException, IOException { public static DataType toDataType() {
StructureDataType struct = new StructureDataType("Omf51LibraryModuleLocation", 0); StructureDataType struct = new StructureDataType("Omf51LibraryModuleLocation", 0);
struct.add(StructConverter.WORD, "blockNumber", null); struct.add(StructConverter.WORD, "blockNumber", null);
struct.add(StructConverter.WORD, "byteNumber", null); struct.add(StructConverter.WORD, "byteNumber", null);

View file

@ -50,7 +50,6 @@ public class Omf51LibraryModuleLocationsRecord extends OmfRecord {
StructureDataType struct = new StructureDataType(Omf51RecordTypes.getName(recordType), 0); StructureDataType struct = new StructureDataType(Omf51RecordTypes.getName(recordType), 0);
struct.add(BYTE, "type", null); struct.add(BYTE, "type", null);
struct.add(WORD, "length", null); struct.add(WORD, "length", null);
struct.add(new ArrayDataType(Omf51LibraryModuleLocation.toDataType(), locations.size()), struct.add(new ArrayDataType(Omf51LibraryModuleLocation.toDataType(), locations.size()),
"locations", null); "locations", null);
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);

View file

@ -338,7 +338,6 @@ public class Omf51Loader extends AbstractProgramWrapperLoader {
if (record instanceof Omf51PublicDefsRecord publicDefRec) { if (record instanceof Omf51PublicDefsRecord publicDefRec) {
for (Omf51PublicDef def : publicDefRec.getDefinitions()) { for (Omf51PublicDef def : publicDefRec.getDefinitions()) {
if (def.getUsageType() == Omf51PublicDef.NUMBER) { if (def.getUsageType() == Omf51PublicDef.NUMBER) {
log.appendMsg("Skipping NUMBER public def");
continue; continue;
} }
Address segmentAddr = segmentToAddr.get(def.getSegId()); Address segmentAddr = segmentToAddr.get(def.getSegId());

View file

@ -18,19 +18,24 @@ package ghidra.file.formats.omf51;
import static ghidra.formats.gfilesystem.fileinfo.FileAttributeType.*; import static ghidra.formats.gfilesystem.fileinfo.FileAttributeType.*;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.List;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.ByteProviderWrapper; import ghidra.app.util.bin.ByteProviderWrapper;
import ghidra.app.util.bin.format.omf.OmfException; import ghidra.app.util.bin.format.omf.OmfException;
import ghidra.app.util.bin.format.omf.omf51.*; import ghidra.app.util.bin.format.omf.omf51.Omf51Library;
import ghidra.app.util.bin.format.omf.omf51.Omf51RecordFactory;
import ghidra.formats.gfilesystem.*; import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo; import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.formats.gfilesystem.fileinfo.FileAttributes; import ghidra.formats.gfilesystem.fileinfo.FileAttributes;
import ghidra.util.Msg; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@FileSystemInfo(type = "omf51", description = "OMF51 Library", factory = Omf51ArchiveFileSystemFactory.class) @FileSystemInfo(
type = "omf51",
description = "OMF51 Library",
factory = Omf51ArchiveFileSystemFactory.class
)
public class Omf51ArchiveFileSystem extends AbstractFileSystem<Omf51Library.MemberHeader> { public class Omf51ArchiveFileSystem extends AbstractFileSystem<Omf51Library.MemberHeader> {
private ByteProvider provider; private ByteProvider provider;
@ -40,18 +45,15 @@ public class Omf51ArchiveFileSystem extends AbstractFileSystem<Omf51Library.Memb
this.provider = provider; this.provider = provider;
} }
public void mount(TaskMonitor monitor) throws IOException, OmfException { public void mount(TaskMonitor monitor) throws IOException, OmfException, CancelledException {
Msg.debug(this, "Opening OMF51 library..."); monitor.setMessage("Opening OMF51 library...");
Omf51RecordFactory factory = new Omf51RecordFactory(provider); Omf51RecordFactory factory = new Omf51RecordFactory(provider);
Omf51Library library = new Omf51Library(factory); List<Omf51Library.MemberHeader> members = new Omf51Library(factory).getMembers();
library.parseMembers();
ArrayList<Omf51Library.MemberHeader> members = library.getMembers();
Msg.debug(this, "Found %d members".formatted(members.size()));
monitor.initialize(members.size(), "Opening OMF51 library...");
for (Omf51Library.MemberHeader member : members) { for (Omf51Library.MemberHeader member : members) {
Msg.debug(this, member.name); monitor.increment();
fsIndex.storeFile(member.name, fsIndex.getFileCount(), false, member.size, member); fsIndex.storeFile(member.name(), fsIndex.getFileCount(), false, member.size(), member);
} }
} }
@ -74,7 +76,7 @@ public class Omf51ArchiveFileSystem extends AbstractFileSystem<Omf51Library.Memb
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) { public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) {
Omf51Library.MemberHeader member = fsIndex.getMetadata(file); Omf51Library.MemberHeader member = fsIndex.getMetadata(file);
return (member != null) return (member != null)
? new ByteProviderWrapper(provider, member.offset, member.size, ? new ByteProviderWrapper(provider, member.offset(), member.size(),
file.getFSRL()) file.getFSRL())
: null; : null;
} }
@ -85,8 +87,8 @@ public class Omf51ArchiveFileSystem extends AbstractFileSystem<Omf51Library.Memb
Omf51Library.MemberHeader entry = fsIndex.getMetadata(file); Omf51Library.MemberHeader entry = fsIndex.getMetadata(file);
if (entry != null) { if (entry != null) {
result.add(NAME_ATTR, entry.name); result.add(NAME_ATTR, entry.name());
result.add(SIZE_ATTR, entry.size); result.add(SIZE_ATTR, entry.size());
} }
return result; return result;
} }

View file

@ -20,15 +20,13 @@ import java.io.IOException;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.omf.AbstractOmfRecordFactory; import ghidra.app.util.bin.format.omf.AbstractOmfRecordFactory;
import ghidra.app.util.bin.format.omf.OmfException; import ghidra.app.util.bin.format.omf.OmfException;
import ghidra.app.util.bin.format.omf.OmfRecord;
import ghidra.app.util.bin.format.omf.omf51.Omf51LibraryHeaderRecord; import ghidra.app.util.bin.format.omf.omf51.Omf51LibraryHeaderRecord;
import ghidra.app.util.bin.format.omf.omf51.Omf51RecordFactory; import ghidra.app.util.bin.format.omf.omf51.Omf51RecordFactory;
import ghidra.app.util.opinion.OmfLoader; import ghidra.app.util.opinion.Omf51Loader;
import ghidra.formats.gfilesystem.FSRLRoot; import ghidra.formats.gfilesystem.FSRLRoot;
import ghidra.formats.gfilesystem.FileSystemService; import ghidra.formats.gfilesystem.FileSystemService;
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider; import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider; import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -54,19 +52,15 @@ public class Omf51ArchiveFileSystemFactory implements
public boolean probe(ByteProvider byteProvider, FileSystemService fsService, public boolean probe(ByteProvider byteProvider, FileSystemService fsService,
TaskMonitor monitor) throws IOException, CancelledException { TaskMonitor monitor) throws IOException, CancelledException {
if (byteProvider.length() < OmfLoader.MIN_BYTE_LENGTH) { if (byteProvider.length() < Omf51Loader.MIN_BYTE_LENGTH) {
return false; return false;
} }
try { try {
AbstractOmfRecordFactory factory = new Omf51RecordFactory(byteProvider); AbstractOmfRecordFactory factory = new Omf51RecordFactory(byteProvider);
OmfRecord record = factory.readNextRecord(); return factory.readNextRecord() instanceof Omf51LibraryHeaderRecord;
return (record != null && record instanceof Omf51LibraryHeaderRecord);
} }
catch (OmfException e) { catch (OmfException | IOException e) {
return false;
}
catch (IOException e) {
return false; return false;
} }
} }