mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-21 19:42:14 +00:00
GP-4729: More OmfLoader refactoring. Initial Omf51Loader framework.
This commit is contained in:
parent
07a9507d0f
commit
d58923419c
@ -0,0 +1,75 @@
|
||||
/* ###
|
||||
* 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.format.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
|
||||
/**
|
||||
* Classes that implement this interface can read various flavors of the OMF format
|
||||
*/
|
||||
public abstract class AbstractOmfRecordFactory {
|
||||
|
||||
protected BinaryReader reader;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractOmfRecordFactory}
|
||||
*
|
||||
* @param reader The {@link BinaryReader} used to read records
|
||||
*/
|
||||
protected AbstractOmfRecordFactory(BinaryReader reader) {
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next {@link OmfRecord} pointed to by the reader
|
||||
*
|
||||
* @return The next read {@link OmfRecord}
|
||||
* @throws IOException if there was an IO-related error
|
||||
* @throws OmfException if there was a problem with the OMF specification
|
||||
*/
|
||||
public abstract OmfRecord readNextRecord() throws IOException, OmfException;
|
||||
|
||||
/**
|
||||
* Gets a {@link List} of valid record types that can start a supported OMF binary
|
||||
*
|
||||
* @return A {@link List} of valid record types that can start a supported OMF binary
|
||||
*/
|
||||
public abstract List<Integer> getStartRecordTypes();
|
||||
|
||||
/**
|
||||
* Gets a valid record type that can end a supported OMF binary
|
||||
*
|
||||
* @return A valid record types that can end a supported OMF binary
|
||||
*/
|
||||
public abstract int getEndRecordType();
|
||||
|
||||
/**
|
||||
* {@return the reader associated with this factory}
|
||||
*/
|
||||
public BinaryReader getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this factory's reader to index 0
|
||||
*/
|
||||
public void reset() {
|
||||
reader.setPointerIndex(0);
|
||||
}
|
||||
}
|
@ -31,8 +31,12 @@ public class OmfObsoleteRecord extends OmfRecord {
|
||||
* @throws IOException If an IO-related error occurred
|
||||
*/
|
||||
public OmfObsoleteRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
// No record-specific data to read
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,31 +29,48 @@ public abstract class OmfRecord implements StructConverter {
|
||||
|
||||
protected int recordType;
|
||||
protected int recordLength;
|
||||
protected byte[] data;
|
||||
protected byte checkSum;
|
||||
|
||||
protected long recordOffset;
|
||||
protected BinaryReader dataReader;
|
||||
protected long dataEnd;
|
||||
|
||||
/**
|
||||
* Reads the record header (type and length fields)
|
||||
*
|
||||
*/
|
||||
public OmfRecord() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link OmfRecord}
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||
* @throws IOException if an IO-related problem occurred
|
||||
* @throws IOException if there was an IO-related error
|
||||
*/
|
||||
public void readRecordHeader(BinaryReader reader) throws IOException {
|
||||
recordOffset = reader.getPointerIndex();
|
||||
recordType = reader.readNextUnsignedByte();
|
||||
recordLength = reader.readNextUnsignedShort();
|
||||
public OmfRecord(BinaryReader reader) throws IOException {
|
||||
this.recordOffset = reader.getPointerIndex();
|
||||
|
||||
this.recordType = reader.readNextUnsignedByte();
|
||||
this.recordLength = reader.readNextUnsignedShort();
|
||||
this.data = reader.readNextByteArray(recordLength - 1);
|
||||
this.checkSum = reader.readNextByte();
|
||||
|
||||
this.dataReader = reader.clone(recordOffset + 3);
|
||||
this.dataEnd = recordOffset + 3 + recordLength - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the record checksum
|
||||
* Parses this {@link OmfRecord}'s type-spefic data
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the record checksum
|
||||
* @throws IOException if an IO-related problem occurred
|
||||
* @throws IOException if there was an IO-related error
|
||||
* @throws OmfException if there was a problem with the OMF specification
|
||||
*/
|
||||
public void readCheckSumByte(BinaryReader reader) throws IOException {
|
||||
checkSum = reader.readNextByte();
|
||||
}
|
||||
public abstract void parseData() throws IOException, OmfException;
|
||||
|
||||
@Override
|
||||
public abstract DataType toDataType() throws DuplicateNameException, IOException;
|
||||
|
||||
/**
|
||||
* {@return the record type}
|
||||
@ -76,36 +93,42 @@ public abstract class OmfRecord implements StructConverter {
|
||||
return recordOffset;
|
||||
}
|
||||
|
||||
public byte getRecordChecksum() {
|
||||
return checkSum;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the record's checksum
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of record
|
||||
* @return The record's checksum
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
public byte calcCheckSum(BinaryReader reader) throws IOException {
|
||||
byte res = reader.readNextByte();
|
||||
res += reader.readNextByte();
|
||||
res += reader.readNextByte(); // Sum the record header bytes
|
||||
for (int i = 0; i < recordLength; ++i) {
|
||||
res += reader.readNextByte();
|
||||
public byte calcCheckSum() throws IOException {
|
||||
byte sum = (byte) recordType;
|
||||
sum += (byte) recordLength + (byte) (recordLength >> 8);
|
||||
for (byte b : data) {
|
||||
sum += b;
|
||||
}
|
||||
return res;
|
||||
sum += checkSum;
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the record's checksum
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||
* @return True if the checksum is valid; otherwise, false
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
public boolean validCheckSum(BinaryReader reader) throws IOException {
|
||||
public boolean validCheckSum() throws IOException {
|
||||
if (checkSum == 0) {
|
||||
// Some compilers just set this to zero
|
||||
return true;
|
||||
}
|
||||
return (calcCheckSum(reader) == 0);
|
||||
return (calcCheckSum() == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,9 +138,6 @@ public abstract class OmfRecord implements StructConverter {
|
||||
return ((recordType & 1) != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract DataType toDataType() throws DuplicateNameException, IOException;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("type: 0x%x, offset: 0x%x, length: 0x%x", recordType, recordOffset,
|
||||
|
@ -54,6 +54,11 @@ public class OmfString implements StructConverter {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
if (length == 0) {
|
||||
|
@ -34,8 +34,12 @@ public class OmfUnknownRecord extends OmfRecord {
|
||||
* @throws IOException If an IO-related error occurred
|
||||
*/
|
||||
public OmfUnknownRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
// No record-specific data to read
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -36,9 +36,13 @@ public class OmfUnsupportedRecord extends OmfRecord {
|
||||
* @throws IOException If an IO-related error occurred
|
||||
*/
|
||||
public OmfUnsupportedRecord(BinaryReader reader, Class<?> recordTypesClass) throws IOException {
|
||||
super(reader);
|
||||
this.recordTypesClass = recordTypesClass;
|
||||
readRecordHeader(reader);
|
||||
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
// No record-specific data to read
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,6 +18,8 @@ package ghidra.app.util.bin.format.omf;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.data.*;
|
||||
@ -105,4 +107,29 @@ public class OmfUtils {
|
||||
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all the {@link OmfRecord records} associated with the given
|
||||
* {@link AbstractOmfRecordFactory}
|
||||
*
|
||||
* @param factory The {@link AbstractOmfRecordFactory}
|
||||
* @return A {@link List} of read {@link OmfRecord records}
|
||||
* @throws IOException if there was an IO-related error
|
||||
* @throws OmfException if there was a problem with the OMF specification
|
||||
*/
|
||||
public static List<OmfRecord> readRecords(AbstractOmfRecordFactory factory)
|
||||
throws OmfException, IOException {
|
||||
List<OmfRecord> records = new ArrayList<>();
|
||||
factory.reset();
|
||||
|
||||
while (true) {
|
||||
OmfRecord rec = factory.readNextRecord();
|
||||
records.add(rec);
|
||||
if (rec.getRecordType() == factory.getEndRecordType()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.OmfIndex;
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
|
||||
public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||
|
||||
@ -29,17 +28,17 @@ public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||
protected List<ExternalLookup> externalLookups = new ArrayList<>();
|
||||
|
||||
public OmfComdatExternalSymbol(BinaryReader reader) throws IOException {
|
||||
super(false);
|
||||
readRecordHeader(reader);
|
||||
super(reader, false);
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
OmfIndex nameIndex = OmfUtils.readIndex(reader);
|
||||
OmfIndex type = OmfUtils.readIndex(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
OmfIndex nameIndex = OmfUtils.readIndex(dataReader);
|
||||
OmfIndex type = OmfUtils.readIndex(dataReader);
|
||||
externalLookups.add(new ExternalLookup(nameIndex.value(), type.value()));
|
||||
}
|
||||
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
public void loadNames(List<String> nameList) {
|
||||
|
@ -22,28 +22,28 @@ import ghidra.app.util.bin.format.omf.*;
|
||||
|
||||
public class OmfComdefRecord extends OmfExternalSymbol {
|
||||
|
||||
public OmfComdefRecord(BinaryReader reader, boolean isStatic) throws IOException, OmfException {
|
||||
super(isStatic);
|
||||
readRecordHeader(reader);
|
||||
public OmfComdefRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
||||
super(reader, isStatic);
|
||||
}
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
OmfString name = OmfUtils.readString(reader);
|
||||
OmfIndex typeIndex = OmfUtils.readIndex(reader);
|
||||
byte dataType = reader.readNextByte();
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
OmfString name = OmfUtils.readString(dataReader);
|
||||
OmfIndex typeIndex = OmfUtils.readIndex(dataReader);
|
||||
byte dataType = dataReader.readNextByte();
|
||||
int byteLength = 0;
|
||||
if (dataType == 0x61) { // FAR data, reads numElements and elSize
|
||||
int numElements = readCommunalLength(reader);
|
||||
int elSize = readCommunalLength(reader);
|
||||
int numElements = readCommunalLength(dataReader);
|
||||
int elSize = readCommunalLength(dataReader);
|
||||
byteLength = numElements * elSize;
|
||||
}
|
||||
else {
|
||||
// Values 1 thru 5f plus 61, read the byte length
|
||||
byteLength = readCommunalLength(reader);
|
||||
byteLength = readCommunalLength(dataReader);
|
||||
}
|
||||
symbols.add(new OmfSymbol(name.str(), typeIndex.value(), 0, dataType, byteLength));
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
private static int readCommunalLength(BinaryReader reader) throws OmfException, IOException {
|
||||
|
@ -40,25 +40,27 @@ public class OmfCommentRecord extends OmfRecord {
|
||||
private OmfString value;
|
||||
|
||||
public OmfCommentRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
commentType = reader.readNextByte();
|
||||
commentClass = reader.readNextByte();
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
commentType = dataReader.readNextByte();
|
||||
commentClass = dataReader.readNextByte();
|
||||
|
||||
switch (commentClass) {
|
||||
case COMMENT_CLASS_TRANSLATOR:
|
||||
case COMMENT_CLASS_DEFAULT_LIBRARY:
|
||||
byte[] bytes = reader.readNextByteArray(getRecordLength() -
|
||||
byte[] bytes = dataReader.readNextByteArray(getRecordLength() -
|
||||
3 /* 3 = sizeof(commentType+commentClass+trailing_crcbyte*/);
|
||||
value = new OmfString(bytes.length, new String(bytes, StandardCharsets.US_ASCII)); // assuming ASCII
|
||||
break;
|
||||
case COMMENT_CLASS_LIBMOD:
|
||||
value = OmfUtils.readString(reader);
|
||||
value = OmfUtils.readString(dataReader);
|
||||
break;
|
||||
default:
|
||||
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength() - 3);
|
||||
break;
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
public byte getCommentType() {
|
||||
|
@ -27,6 +27,10 @@ public abstract class OmfData extends OmfRecord implements Comparable<OmfData> {
|
||||
protected OmfIndex segmentIndex;
|
||||
protected Omf2or4 dataOffset;
|
||||
|
||||
public OmfData(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return get the segments index for this datablock
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.omf.omf;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.OmfException;
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
@ -27,14 +28,16 @@ public class OmfEnumeratedData extends OmfData {
|
||||
private int streamLength; // Number of bytes of data
|
||||
|
||||
public OmfEnumeratedData(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
long start = reader.getPointerIndex();
|
||||
segmentIndex = OmfUtils.readIndex(reader);
|
||||
dataOffset = OmfUtils.readInt2Or4(reader, hasBigFields());
|
||||
streamOffset = reader.getPointerIndex();
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
long start = dataReader.getPointerIndex();
|
||||
segmentIndex = OmfUtils.readIndex(dataReader);
|
||||
dataOffset = OmfUtils.readInt2Or4(dataReader, hasBigFields());
|
||||
streamOffset = dataReader.getPointerIndex();
|
||||
streamLength = getRecordLength() - 1 - (int) (streamOffset - start);
|
||||
reader.setPointerIndex(streamOffset + streamLength); // Skip over the data when reading header
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,23 +33,19 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||
|
||||
private List<Reference> refs = new ArrayList<>();
|
||||
|
||||
protected OmfExternalSymbol(boolean isStatic) {
|
||||
public OmfExternalSymbol(BinaryReader reader, boolean isStatic) throws IOException {
|
||||
super(reader);
|
||||
this.isStatic = isStatic;
|
||||
}
|
||||
|
||||
public OmfExternalSymbol(BinaryReader reader, boolean isStatic) throws IOException {
|
||||
this.isStatic = isStatic;
|
||||
readRecordHeader(reader);
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
OmfString name = OmfUtils.readString(reader);
|
||||
OmfIndex type = OmfUtils.readIndex(reader);
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
OmfString name = OmfUtils.readString(dataReader);
|
||||
OmfIndex type = OmfUtils.readIndex(dataReader);
|
||||
refs.add(new Reference(name, type));
|
||||
symbols.add(new OmfSymbol(name.str(), type.value(), 0, 0, 0));
|
||||
}
|
||||
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
public List<OmfSymbol> getSymbols() {
|
||||
|
@ -20,7 +20,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.data.*;
|
||||
@ -45,12 +44,15 @@ public class OmfFileHeader extends OmfRecord {
|
||||
private boolean format16bit;
|
||||
|
||||
public OmfFileHeader(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
objectName = OmfUtils.readString(reader); // This is usually the source code filename
|
||||
readCheckSumByte(reader);
|
||||
super(reader);
|
||||
isLittleEndian = reader.isLittleEndian();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
objectName = OmfUtils.readString(dataReader); // This is usually the source code filename
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the list of records}
|
||||
*/
|
||||
@ -261,23 +263,23 @@ public class OmfFileHeader extends OmfRecord {
|
||||
|
||||
/**
|
||||
* Scan the object file, for the main header and comment records. Other records are parsed but not saved
|
||||
* @param reader is the byte stream
|
||||
* @param factory the {@link AbstractOmfRecordFactory}
|
||||
* @param monitor is checked for cancellation
|
||||
* @param fastscan is true if we only want to scan the header until first seghead,
|
||||
* @return the header record
|
||||
* @throws IOException for problems reading program data
|
||||
* @throws OmfException for malformed records
|
||||
*/
|
||||
public static OmfFileHeader scan(BinaryReader reader, TaskMonitor monitor, boolean fastscan)
|
||||
throws IOException, OmfException {
|
||||
OmfRecord record = OmfRecordFactory.readRecord(reader);
|
||||
public static OmfFileHeader scan(AbstractOmfRecordFactory factory, TaskMonitor monitor,
|
||||
boolean fastscan) throws IOException, OmfException {
|
||||
OmfRecord record = factory.readNextRecord();
|
||||
if (!(record instanceof OmfFileHeader)) {
|
||||
throw new OmfException("Object file does not start with proper header");
|
||||
}
|
||||
OmfFileHeader header = (OmfFileHeader) record;
|
||||
|
||||
while (true) {
|
||||
record = OmfRecordFactory.readRecord(reader);
|
||||
record = factory.readNextRecord();
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
@ -315,16 +317,16 @@ public class OmfFileHeader extends OmfRecord {
|
||||
/**
|
||||
* Parse the entire object file
|
||||
*
|
||||
* @param reader is the byte stream
|
||||
* @param factory the {@link AbstractOmfRecordFactory}
|
||||
* @param monitor is checked for cancel button
|
||||
* @param log the log
|
||||
* @return the header record as root of object
|
||||
* @throws IOException for problems reading data
|
||||
* @throws OmfException for malformed records
|
||||
*/
|
||||
public static OmfFileHeader parse(BinaryReader reader, TaskMonitor monitor, MessageLog log)
|
||||
public static OmfFileHeader parse(AbstractOmfRecordFactory factory, TaskMonitor monitor, MessageLog log)
|
||||
throws IOException, OmfException {
|
||||
OmfRecord record = OmfRecordFactory.readRecord(reader);
|
||||
OmfRecord record = factory.readNextRecord();
|
||||
if (!(record instanceof OmfFileHeader header)) {
|
||||
throw new OmfException("Object file does not start with proper header");
|
||||
}
|
||||
@ -332,7 +334,10 @@ public class OmfFileHeader extends OmfRecord {
|
||||
OmfData lastDataBlock = null;
|
||||
|
||||
while (true) {
|
||||
record = OmfRecordFactory.readRecord(reader);
|
||||
record = factory.readNextRecord();
|
||||
if (!record.validCheckSum()) {
|
||||
throw new OmfException("Invalid checksum!");
|
||||
}
|
||||
header.records.add(record);
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
@ -488,15 +493,6 @@ public class OmfFileHeader extends OmfRecord {
|
||||
return len == stringlen + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reader for a specific OMF file
|
||||
* @param provider is the underlying ByteProvider
|
||||
* @return the new reader
|
||||
*/
|
||||
public static BinaryReader createReader(ByteProvider provider) {
|
||||
return new BinaryReader(provider, true/* Always little endian */);
|
||||
}
|
||||
|
||||
private static void logRecord(String description, OmfRecord record, MessageLog log) {
|
||||
log.appendMsg(description + " (" + record + ")");
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfFixupRecord extends OmfRecord {
|
||||
private final Subrecord[] subrecs;
|
||||
private Subrecord[] subrecs;
|
||||
private OmfData lastData = null;
|
||||
|
||||
/**
|
||||
@ -33,16 +33,18 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
* @throws IOException if there was an IO-related error
|
||||
*/
|
||||
public OmfFixupRecord(BinaryReader reader) throws IOException {
|
||||
ArrayList<Subrecord> subreclist = new ArrayList<Subrecord>();
|
||||
super(reader);
|
||||
}
|
||||
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
subreclist.add(Subrecord.readSubrecord(reader, hasBigFields()));
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
ArrayList<Subrecord> subreclist = new ArrayList<>();
|
||||
long max = dataReader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (dataReader.getPointerIndex() < max) {
|
||||
subreclist.add(Subrecord.readSubrecord(dataReader, hasBigFields()));
|
||||
}
|
||||
subrecs = new Subrecord[subreclist.size()];
|
||||
subreclist.toArray(subrecs);
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,15 +34,17 @@ public class OmfGroupRecord extends OmfRecord {
|
||||
private GroupSubrecord[] group;
|
||||
|
||||
public OmfGroupRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
groupNameIndex = OmfUtils.readIndex(reader);
|
||||
ArrayList<GroupSubrecord> grouplist = new ArrayList<GroupSubrecord>();
|
||||
while (reader.getPointerIndex() < max) {
|
||||
GroupSubrecord subrec = GroupSubrecord.read(reader);
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
groupNameIndex = OmfUtils.readIndex(dataReader);
|
||||
ArrayList<GroupSubrecord> grouplist = new ArrayList<>();
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
GroupSubrecord subrec = GroupSubrecord.read(dataReader);
|
||||
grouplist.add(subrec);
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
group = new GroupSubrecord[grouplist.size()];
|
||||
grouplist.toArray(group);
|
||||
}
|
||||
|
@ -19,8 +19,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.Omf2or4;
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
@ -30,17 +29,19 @@ public class OmfIteratedData extends OmfData {
|
||||
private DataBlock[] datablock;
|
||||
|
||||
public OmfIteratedData(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
boolean hasBigFields = hasBigFields();
|
||||
segmentIndex = OmfUtils.readIndex(reader);
|
||||
dataOffset = OmfUtils.readInt2Or4(reader, hasBigFields);
|
||||
ArrayList<DataBlock> blocklist = new ArrayList<DataBlock>();
|
||||
while (reader.getPointerIndex() < max) {
|
||||
DataBlock block = DataBlock.read(reader, hasBigFields);
|
||||
segmentIndex = OmfUtils.readIndex(dataReader);
|
||||
dataOffset = OmfUtils.readInt2Or4(dataReader, hasBigFields);
|
||||
ArrayList<DataBlock> blocklist = new ArrayList<>();
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
DataBlock block = DataBlock.read(dataReader, hasBigFields);
|
||||
blocklist.add(block);
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
datablock = new DataBlock[blocklist.size()];
|
||||
blocklist.toArray(datablock);
|
||||
}
|
||||
|
@ -19,13 +19,14 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.app.util.bin.format.omf.AbstractOmfRecordFactory;
|
||||
import ghidra.app.util.bin.format.omf.OmfException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class OmfLibraryRecord extends OmfRecord {
|
||||
public class OmfLibraryRecord {
|
||||
private int recordType;
|
||||
private int recordLength;
|
||||
private int pageSize; // All archive members must start on a page boundary of this size
|
||||
private long dictionaryOffset;
|
||||
private int dictionarySize;
|
||||
@ -40,13 +41,14 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||
public String machineName;
|
||||
}
|
||||
|
||||
public OmfLibraryRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
public OmfLibraryRecord(BinaryReader reader) throws IOException, OmfException {
|
||||
recordType = reader.readNextUnsignedByte();
|
||||
recordLength = reader.readNextUnsignedShort();
|
||||
pageSize = recordLength + 3;
|
||||
dictionaryOffset = reader.readNextInt() & 0xffffffff;
|
||||
dictionarySize = reader.readNextShort() & 0xffff;
|
||||
flags = reader.readNextByte();
|
||||
// No checksum byte (just padding)
|
||||
// No checksum byte
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
@ -88,9 +90,10 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static OmfLibraryRecord parse(BinaryReader reader, TaskMonitor monitor)
|
||||
throws IOException {
|
||||
public static OmfLibraryRecord parse(AbstractOmfRecordFactory factory, TaskMonitor monitor)
|
||||
throws IOException, OmfException {
|
||||
OmfLibraryRecord res = null;
|
||||
BinaryReader reader = factory.getReader();
|
||||
byte type = reader.peekNextByte();
|
||||
if (type != (byte) 0xF0) {
|
||||
throw new IOException("Not an OMF Library record");
|
||||
@ -104,7 +107,7 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||
curheader.payloadOffset = reader.getPointerIndex();
|
||||
OmfFileHeader fileheader;
|
||||
try {
|
||||
fileheader = OmfFileHeader.scan(reader, monitor, false);
|
||||
fileheader = OmfFileHeader.scan(factory, monitor, false);
|
||||
}
|
||||
catch (OmfException e) {
|
||||
throw new IOException("Could not parse individual object file within archive");
|
||||
@ -122,9 +125,4 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
|
||||
}
|
||||
}
|
||||
|
@ -18,38 +18,20 @@ package ghidra.app.util.bin.format.omf.omf;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.OmfRecord;
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfModuleEnd extends OmfRecord {
|
||||
//private byte moduleType;
|
||||
//private OmfFixupRecord.FixupTarget startAddress;
|
||||
|
||||
public OmfModuleEnd(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
/* The record type is not handled so simply skip the information
|
||||
moduleType = reader.readNextByte();
|
||||
if (hasStartAddress()) {
|
||||
endData = reader.readNextByte();
|
||||
frameDatum = readInt1Or2(reader, hasBigFields());
|
||||
targetDatum = readInt1Or2(reader, hasBigFields());
|
||||
targetDisplacement readInt2Or4(reader, hasBigFields());
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
*/
|
||||
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||
}
|
||||
/*
|
||||
public boolean isMainProgramModule() {
|
||||
return ((moduleType & 0x80) != 0);
|
||||
super(reader);
|
||||
}
|
||||
|
||||
public boolean hasStartAddress() {
|
||||
return ((moduleType & 0x40) != 0);
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
// No record-specific data to read
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
|
@ -28,12 +28,14 @@ public class OmfNamesRecord extends OmfRecord {
|
||||
private List<OmfString> names = new ArrayList<>();
|
||||
|
||||
public OmfNamesRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
names.add(OmfUtils.readString(reader));
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
names.add(OmfUtils.readString(dataReader));
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
public void appendNames(List<String> namelist) {
|
||||
|
@ -18,15 +18,30 @@ package ghidra.app.util.bin.format.omf.omf;
|
||||
import static ghidra.app.util.bin.format.omf.omf.OmfRecordTypes.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
|
||||
public class OmfRecordFactory {
|
||||
/**
|
||||
* A class for reading/creating Relocatable OMF records
|
||||
*/
|
||||
public class OmfRecordFactory extends AbstractOmfRecordFactory {
|
||||
|
||||
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
|
||||
/**
|
||||
* Creates a new {@link OmfRecordFactory}
|
||||
*
|
||||
* @param provider The {@link ByteProvider} that contains the records
|
||||
*/
|
||||
public OmfRecordFactory(ByteProvider provider) {
|
||||
super(new BinaryReader(provider, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmfRecord readNextRecord() throws IOException, OmfException {
|
||||
int type = Byte.toUnsignedInt(reader.peekNextByte());
|
||||
return switch (type & 0xfffffffe) { // mask off the least significant bit (16/32 bit flag)
|
||||
OmfRecord record = switch (type & 0xfffffffe) { // mask off the least significant bit (16/32 bit flag)
|
||||
case THEADR:
|
||||
case LHEADR:
|
||||
yield new OmfFileHeader(reader);
|
||||
@ -91,5 +106,18 @@ public class OmfRecordFactory {
|
||||
default:
|
||||
yield new OmfUnknownRecord(reader);
|
||||
};
|
||||
|
||||
record.parseData();
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getStartRecordTypes() {
|
||||
return List.of(THEADR, LHEADR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndRecordType() {
|
||||
return MODEND;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,11 @@ package ghidra.app.util.bin.format.omf.omf;
|
||||
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
|
||||
/**
|
||||
* Relocatable OMF record types
|
||||
*
|
||||
* @see <a href="http://www.azillionmonkeys.com/qed/Omfg.pdf">OMF: Relocatable Object Module Format</a>
|
||||
*/
|
||||
public class OmfRecordTypes {
|
||||
|
||||
public final static int RHEADR = 0x6E; // Obsolete
|
||||
@ -62,6 +67,7 @@ public class OmfRecordTypes {
|
||||
public final static int LLNAMES = 0xCA;
|
||||
public final static int VERNUM = 0xCC;
|
||||
public final static int VENDEXT = 0xCE;
|
||||
|
||||
public final static int START = 0xF0;
|
||||
public final static int END = 0xF1;
|
||||
|
||||
|
@ -83,20 +83,23 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
}
|
||||
|
||||
public OmfSegmentHeader(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
boolean hasBigFields = hasBigFields();
|
||||
segAttr = reader.readNextByte();
|
||||
segAttr = dataReader.readNextByte();
|
||||
int A = (segAttr >> 5) & 7;
|
||||
if (A == 0) {
|
||||
frameNumber = reader.readNextShort() & 0xffff;
|
||||
offset = reader.readNextByte() & 0xff;
|
||||
frameNumber = dataReader.readNextShort() & 0xffff;
|
||||
offset = dataReader.readNextByte() & 0xff;
|
||||
vma = (long) frameNumber + offset;
|
||||
}
|
||||
segmentLength = OmfUtils.readInt2Or4(reader, hasBigFields);
|
||||
segmentNameIndex = OmfUtils.readIndex(reader);
|
||||
classNameIndex = OmfUtils.readIndex(reader);
|
||||
overlayNameIndex = OmfUtils.readIndex(reader);
|
||||
readCheckSumByte(reader);
|
||||
segmentLength = OmfUtils.readInt2Or4(dataReader, hasBigFields);
|
||||
segmentNameIndex = OmfUtils.readIndex(dataReader);
|
||||
classNameIndex = OmfUtils.readIndex(dataReader);
|
||||
overlayNameIndex = OmfUtils.readIndex(dataReader);
|
||||
int B = (segAttr >> 1) & 1;
|
||||
if (B == 1) { // Ignore the segmentLength field
|
||||
if (getRecordType() == OmfRecordTypes.SEGDEF) {
|
||||
@ -393,10 +396,10 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
*/
|
||||
private void establishNextBuffer() throws IOException {
|
||||
while (dataUpNext < dataBlocks.size()) {
|
||||
OmfData data = dataBlocks.get(dataUpNext);
|
||||
if (pointer < data.getDataOffset()) {
|
||||
OmfData omfData = dataBlocks.get(dataUpNext);
|
||||
if (pointer < omfData.getDataOffset()) {
|
||||
// We have some fill to produce before the next section
|
||||
long size = data.getDataOffset() - pointer;
|
||||
long size = omfData.getDataOffset() - pointer;
|
||||
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
||||
throw new IOException(
|
||||
"Unfilled hole in OMF data blocks for segment: " + segmentName);
|
||||
@ -408,8 +411,8 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
bufferpointer = 0;
|
||||
return;
|
||||
}
|
||||
else if (pointer == data.getDataOffset()) {
|
||||
buffer = data.getByteArray(reader);
|
||||
else if (pointer == omfData.getDataOffset()) {
|
||||
buffer = omfData.getByteArray(reader);
|
||||
bufferpointer = 0;
|
||||
dataUpNext++;
|
||||
if (buffer.length == 0) {
|
||||
@ -421,7 +424,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
dataUpNext++;
|
||||
throw new IOException(String.format(
|
||||
"Segment %s:%s has bad data offset (0x%x) in data block %d...skipping.",
|
||||
segmentName, className, data.getDataOffset(), dataUpNext - 1));
|
||||
segmentName, className, omfData.getDataOffset(), dataUpNext - 1));
|
||||
}
|
||||
}
|
||||
// We may have filler after the last block
|
||||
|
@ -35,26 +35,28 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||
private record Reference(OmfString name, Omf2or4 offset, OmfIndex type) {}
|
||||
|
||||
public OmfSymbolRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
||||
super(reader);
|
||||
this.isStatic = isStatic;
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException {
|
||||
boolean hasBigFields = hasBigFields();
|
||||
baseGroupIndex = OmfUtils.readIndex(reader);
|
||||
baseSegmentIndex = OmfUtils.readIndex(reader);
|
||||
baseGroupIndex = OmfUtils.readIndex(dataReader);
|
||||
baseSegmentIndex = OmfUtils.readIndex(dataReader);
|
||||
if (baseSegmentIndex.value() == 0) {
|
||||
baseFrame = reader.readNextUnsignedShort();
|
||||
baseFrame = dataReader.readNextUnsignedShort();
|
||||
}
|
||||
|
||||
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
||||
while (reader.getPointerIndex() < max) {
|
||||
OmfString name = OmfUtils.readString(reader);
|
||||
Omf2or4 offset = OmfUtils.readInt2Or4(reader, hasBigFields);
|
||||
OmfIndex type = OmfUtils.readIndex(reader);
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
OmfString name = OmfUtils.readString(dataReader);
|
||||
Omf2or4 offset = OmfUtils.readInt2Or4(dataReader, hasBigFields);
|
||||
OmfIndex type = OmfUtils.readIndex(dataReader);
|
||||
OmfSymbol subrec = new OmfSymbol(name.str(), type.value(), offset.value(), 0, 0);
|
||||
symbollist.add(subrec);
|
||||
refs.add(new Reference(name, offset, type));
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
symbol = new OmfSymbol[symbollist.size()];
|
||||
symbollist.toArray(symbol);
|
||||
}
|
||||
@ -107,5 +109,4 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf166;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class Omf166DepList extends OmfRecord {
|
||||
|
||||
private record Info(byte type, Byte mark, Integer time, OmfString name) {}
|
||||
|
||||
private List<Info> infoList = new ArrayList<>();
|
||||
|
||||
public Omf166DepList(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
while (dataReader.getPointerIndex() < dataEnd) {
|
||||
byte iTyp = dataReader.readNextByte();
|
||||
switch (iTyp) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
byte mark = dataReader.readNextByte();
|
||||
int time = dataReader.readNextInt();
|
||||
OmfString name = OmfUtils.readString(dataReader);
|
||||
infoList.add(new Info(iTyp, mark, time, name));
|
||||
break;
|
||||
case (byte) 0xff:
|
||||
OmfString invocation = OmfUtils.readString(dataReader);
|
||||
infoList.add(new Info(iTyp, null, null, invocation));
|
||||
break;
|
||||
default:
|
||||
throw new OmfException("Unexpected DEPLST iTyp: 0x%x".formatted(iTyp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(Omf166RecordTypes.getName(recordType), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", null);
|
||||
for (Info info : infoList) {
|
||||
struct.add(BYTE, "iTyp", null);
|
||||
if (info.mark != null) {
|
||||
struct.add(BYTE, "mark8", null);
|
||||
}
|
||||
if (info.time != null) {
|
||||
struct.add(DWORD, "time32", null);
|
||||
}
|
||||
struct.add(info.name.toDataType(), "name", null);
|
||||
}
|
||||
struct.add(BYTE, "checksum", null);
|
||||
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf166;
|
||||
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
|
||||
/**
|
||||
* OMF-166 record types
|
||||
*
|
||||
* @see <a href="https://www.keil.com/download/files/omf166.pdf">OMF-166 Description</a>
|
||||
*/
|
||||
public class Omf166RecordTypes {
|
||||
|
||||
public final static int RTXDEF = 0x30;
|
||||
public final static int DEPLST = 0x70;
|
||||
public final static int REGMSK = 0x72;
|
||||
public final static int TYPNEW = 0xF0;
|
||||
public final static int BLKEND = 0x7C;
|
||||
public final static int THEADR = 0x80;
|
||||
public final static int LHEADR = 0x82;
|
||||
public final static int COMMENT = 0x88;
|
||||
public final static int MODEND = 0x8A;
|
||||
public final static int LINNUM = 0x94;
|
||||
public final static int LNAMES = 0x96;
|
||||
public final static int LIBLOC = 0xA8;
|
||||
public final static int LIBNAMES = 0xA6;
|
||||
public final static int LIBDICT = 0xAA;
|
||||
public final static int LIBHDR = 0xBA;
|
||||
public final static int PHEADR = 0xE0;
|
||||
public final static int PECDEF = 0xE4;
|
||||
public final static int SSKDEF = 0xE5;
|
||||
public final static int MODINF = 0xE7;
|
||||
public final static int TSKDEF = 0xE1;
|
||||
public final static int REGDEF = 0xE3;
|
||||
public final static int SEDEF = 0xB0;
|
||||
public final static int TYPDEF = 0xB2;
|
||||
public final static int GRPDEF = 0xB1;
|
||||
public final static int PUBDEF = 0xB3;
|
||||
public final static int GLBDEF = 0xE6;
|
||||
public final static int EXTDEF = 0x8C;
|
||||
public final static int LOCSYM = 0xB5;
|
||||
public final static int BLKDEF = 0xB7;
|
||||
public final static int DEBSYM = 0xB6;
|
||||
public final static int LEDATA = 0xB8;
|
||||
public final static int PEDATA = 0xB9;
|
||||
public final static int VECTAB = 0xE9;
|
||||
public final static int FIXUPP = 0xB4;
|
||||
public final static int TSKEND = 0xE2;
|
||||
public final static int XSECDEF = 0xC5;
|
||||
|
||||
/**
|
||||
* Gets the name of the given record type
|
||||
*
|
||||
* @param type The record type
|
||||
* @return The name of the given record type
|
||||
*/
|
||||
public final static String getName(int type) {
|
||||
return OmfUtils.getRecordName(type, Omf166RecordTypes.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf51;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class Omf51ModuleEnd extends OmfRecord {
|
||||
|
||||
private OmfString moduleName;
|
||||
private byte regMsk;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Omf51ModuleEnd} record
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
public Omf51ModuleEnd(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
moduleName = OmfUtils.readString(dataReader);
|
||||
dataReader.readNextByte();
|
||||
dataReader.readNextByte();
|
||||
regMsk = dataReader.readNextByte();
|
||||
dataReader.readNextByte();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the register mask}
|
||||
*/
|
||||
public byte getRegisterMask() {
|
||||
return regMsk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(Omf51RecordTypes.getName(recordType), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", null);
|
||||
struct.add(moduleName.toDataType(), "name", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
struct.add(BYTE, "REG MSK", null);
|
||||
struct.add(BYTE, "padding", null);
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf51;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class Omf51ModuleHeader extends OmfRecord {
|
||||
|
||||
private OmfString moduleName;
|
||||
private byte trnId;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Omf51ModuleHeader} record
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
public Omf51ModuleHeader(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseData() throws IOException, OmfException {
|
||||
moduleName = OmfUtils.readString(dataReader);
|
||||
dataReader.readNextByte();
|
||||
trnId = dataReader.readNextByte();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the TRN ID}
|
||||
*/
|
||||
public byte getTrnId() {
|
||||
return trnId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(Omf51RecordTypes.getName(recordType), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", null);
|
||||
struct.add(moduleName.toDataType(), "name", null);
|
||||
struct.add(BYTE, "padding", null);
|
||||
struct.add(BYTE, "TRN ID", null);
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf51;
|
||||
|
||||
import static ghidra.app.util.bin.format.omf.omf51.Omf51RecordTypes.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.app.util.bin.format.omf.omf166.Omf166RecordTypes;
|
||||
import ghidra.app.util.bin.format.omf.omf166.Omf166DepList;
|
||||
|
||||
/**
|
||||
* A class for reading/creating OMF-51 records
|
||||
*/
|
||||
public class Omf51RecordFactory extends AbstractOmfRecordFactory {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Omf51RecordFactory}
|
||||
*
|
||||
* @param provider The {@link ByteProvider} that contains the records
|
||||
*/
|
||||
public Omf51RecordFactory(ByteProvider provider) {
|
||||
super(new BinaryReader(provider, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmfRecord readNextRecord() throws IOException, OmfException {
|
||||
int type = Byte.toUnsignedInt(reader.peekNextByte());
|
||||
OmfRecord record = switch (type) {
|
||||
case ModuleHDR:
|
||||
yield new Omf51ModuleHeader(reader);
|
||||
case ModuleEND:
|
||||
yield new Omf51ModuleEnd(reader);
|
||||
case Omf166RecordTypes.DEPLST:
|
||||
yield new Omf166DepList(reader);
|
||||
case Content:
|
||||
case Fixup:
|
||||
case SegmentDEF:
|
||||
case ScopeDEF:
|
||||
case DebugItem:
|
||||
case PublicDEF:
|
||||
case ExternalDEF:
|
||||
case LibModLocs:
|
||||
case LibModName:
|
||||
case LibDictionary:
|
||||
case LibHeader:
|
||||
yield new OmfUnsupportedRecord(reader, Omf51RecordTypes.class);
|
||||
default:
|
||||
yield new OmfUnknownRecord(reader);
|
||||
};
|
||||
|
||||
record.parseData();
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getStartRecordTypes() {
|
||||
return List.of(ModuleHDR, Omf166RecordTypes.DEPLST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndRecordType() {
|
||||
return ModuleEND;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* ###
|
||||
* 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.format.omf.omf51;
|
||||
|
||||
import ghidra.app.util.bin.format.omf.OmfUtils;
|
||||
|
||||
/**
|
||||
* OMF-51 record types
|
||||
*
|
||||
* @see <a href="https://turbo51.com/documentation/omf-51-object-module-format">OMF-51 Object Module Format</a>
|
||||
*/
|
||||
public class Omf51RecordTypes {
|
||||
|
||||
public final static int ModuleHDR = 0x02;
|
||||
public final static int ModuleEND = 0x04;
|
||||
public final static int Content = 0x06;
|
||||
public final static int Fixup = 0x08;
|
||||
public final static int SegmentDEF = 0x0e;
|
||||
public final static int ScopeDEF = 0x10;
|
||||
public final static int DebugItem = 0x12;
|
||||
public final static int PublicDEF = 0x16;
|
||||
public final static int ExternalDEF = 0x18;
|
||||
public final static int LibModLocs = 0x26;
|
||||
public final static int LibModName = 0x28;
|
||||
public final static int LibDictionary = 0x2a;
|
||||
public final static int LibHeader = 0x2c;
|
||||
|
||||
/**
|
||||
* Gets the name of the given record type
|
||||
*
|
||||
* @param type The record type
|
||||
* @return The name of the given record type
|
||||
*/
|
||||
public final static String getName(int type) {
|
||||
return OmfUtils.getRecordName(type, Omf51RecordTypes.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/* ###
|
||||
* 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.opinion;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.MemoryBlockUtils;
|
||||
import ghidra.app.util.Option;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.app.util.bin.format.omf.omf51.Omf51RecordFactory;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.DataUtilities;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A {@link Loader} for OMF-51 files
|
||||
*/
|
||||
public class Omf51Loader extends AbstractProgramWrapperLoader {
|
||||
public final static String OMF51_NAME = "Object Module Format (OMF-51)";
|
||||
public final static long MIN_BYTE_LENGTH = 11;
|
||||
|
||||
@Override
|
||||
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
||||
List<LoadSpec> loadSpecs = new ArrayList<>();
|
||||
|
||||
if (provider.length() < MIN_BYTE_LENGTH) {
|
||||
return loadSpecs;
|
||||
}
|
||||
|
||||
AbstractOmfRecordFactory factory = new Omf51RecordFactory(provider);
|
||||
try {
|
||||
OmfRecord first = factory.readNextRecord();
|
||||
if (factory.getStartRecordTypes().contains(first.getRecordType()) &&
|
||||
first.validCheckSum()) {
|
||||
List<QueryResult> results = QueryOpinionService.query(getName(), "8051", null);
|
||||
for (QueryResult result : results) {
|
||||
loadSpecs.add(new LoadSpec(this, 0, result));
|
||||
}
|
||||
if (loadSpecs.isEmpty()) {
|
||||
loadSpecs.add(new LoadSpec(this, 0, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | OmfException e) {
|
||||
// that's ok, not an OMF-51
|
||||
}
|
||||
return loadSpecs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
|
||||
Program program, TaskMonitor monitor, MessageLog log)
|
||||
throws IOException, CancelledException {
|
||||
|
||||
FileBytes fileBytes = MemoryBlockUtils.createFileBytes(program, provider, monitor);
|
||||
AbstractOmfRecordFactory factory = new Omf51RecordFactory(provider);
|
||||
try {
|
||||
List<OmfRecord> records = OmfUtils.readRecords(factory);
|
||||
markupRecords(program, fileBytes, records, log, monitor);
|
||||
}
|
||||
catch (OmfException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void markupRecords(Program program, FileBytes fileBytes, List<OmfRecord> records,
|
||||
MessageLog log, TaskMonitor monitor) {
|
||||
monitor.setMessage("Marking up records...");
|
||||
int size = records.stream().mapToInt(r -> r.getRecordLength() + 3).sum();
|
||||
try {
|
||||
Address recordSpaceAddr = AddressSpace.OTHER_SPACE.getAddress(0);
|
||||
MemoryBlock headerBlock = MemoryBlockUtils.createInitializedBlock(program, true,
|
||||
"RECORDS", recordSpaceAddr, fileBytes, 0, size, "", "", false, false, false, log);
|
||||
Address start = headerBlock.getStart();
|
||||
|
||||
for (OmfRecord record : records) {
|
||||
DataUtilities.createData(program, start.add(record.getRecordOffset()),
|
||||
record.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.appendMsg("Failed to markup records");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return OMF51_NAME;
|
||||
}
|
||||
}
|
@ -42,6 +42,9 @@ import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A {@link Loader} for Relocatable Object Module (OMF) files
|
||||
*/
|
||||
public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
public final static String OMF_NAME = "Relocatable Object Module Format (OMF)";
|
||||
public final static long MIN_BYTE_LENGTH = 11;
|
||||
@ -59,25 +62,14 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
* @return the "secondary constraint"
|
||||
*/
|
||||
private String mapTranslator(String record) {
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
if (record.startsWith("Borland")) {
|
||||
return "borlandcpp";
|
||||
}
|
||||
if (record.startsWith("Delphi")) {
|
||||
return "borlanddelphi";
|
||||
}
|
||||
if (record.startsWith("CodeGear")) {
|
||||
return "codegearcpp";
|
||||
}
|
||||
if (record.equals("MS C")) {
|
||||
return "windows";
|
||||
}
|
||||
if (record.startsWith("Watcom")) {
|
||||
return "watcom";
|
||||
}
|
||||
return null;
|
||||
return switch (record) {
|
||||
case String s when s.startsWith("Borland") -> "boarlandcpp";
|
||||
case String s when s.startsWith("Delphi") -> "borlanddelphi";
|
||||
case String s when s.startsWith("CodeGear") -> "codegearcpp";
|
||||
case String s when s.equals("MS C") -> "windows";
|
||||
case String s when s.startsWith("Watcom") -> "watcom";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -88,12 +80,12 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
return loadSpecs;
|
||||
}
|
||||
|
||||
BinaryReader reader = OmfFileHeader.createReader(provider);
|
||||
if (OmfFileHeader.checkMagicNumber(reader)) {
|
||||
reader.setPointerIndex(0);
|
||||
AbstractOmfRecordFactory factory = new OmfRecordFactory(provider);
|
||||
if (OmfFileHeader.checkMagicNumber(factory.getReader())) {
|
||||
factory.reset();
|
||||
OmfFileHeader scan;
|
||||
try {
|
||||
scan = OmfFileHeader.scan(reader, TaskMonitor.DUMMY, true);
|
||||
scan = OmfFileHeader.scan(factory, TaskMonitor.DUMMY, true);
|
||||
}
|
||||
catch (OmfException e) {
|
||||
throw new IOException("Bad header format: " + e.getMessage());
|
||||
@ -121,9 +113,9 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
throws IOException, CancelledException {
|
||||
|
||||
OmfFileHeader header = null;
|
||||
BinaryReader reader = OmfFileHeader.createReader(provider);
|
||||
AbstractOmfRecordFactory factory = new OmfRecordFactory(provider);
|
||||
try {
|
||||
header = OmfFileHeader.parse(reader, monitor, log);
|
||||
header = OmfFileHeader.parse(factory, monitor, log);
|
||||
header.resolveNames();
|
||||
header.sortSegmentDataBlocks();
|
||||
OmfFileHeader.doLinking(IMAGE_BASE, header.getSegments(), header.getGroups());
|
||||
@ -141,7 +133,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
FileBytes fileBytes = MemoryBlockUtils.createFileBytes(program, provider, monitor);
|
||||
|
||||
try {
|
||||
processSegmentHeaders(reader, header, program, monitor, log);
|
||||
processSegmentHeaders(factory.getReader(), header, program, monitor, log);
|
||||
processPublicSymbols(header, program, monitor, log);
|
||||
processExternalSymbols(header, program, monitor, log);
|
||||
processRelocations(header, program, monitor, log);
|
||||
|
@ -20,9 +20,11 @@ import static ghidra.formats.gfilesystem.fileinfo.FileAttributeType.*;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfFileHeader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.ByteProviderWrapper;
|
||||
import ghidra.app.util.bin.format.omf.OmfException;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfRecordFactory;
|
||||
import ghidra.formats.gfilesystem.*;
|
||||
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
|
||||
import ghidra.formats.gfilesystem.fileinfo.FileAttributes;
|
||||
@ -38,10 +40,10 @@ public class OmfArchiveFileSystem extends AbstractFileSystem<OmfLibraryRecord.Me
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public void mount(TaskMonitor monitor) throws IOException {
|
||||
public void mount(TaskMonitor monitor) throws IOException, OmfException {
|
||||
monitor.setMessage("Opening OMF archive...");
|
||||
BinaryReader reader = OmfFileHeader.createReader(provider);
|
||||
OmfLibraryRecord libraryRec = OmfLibraryRecord.parse(reader, monitor);
|
||||
OmfLibraryRecord libraryRec =
|
||||
OmfLibraryRecord.parse(new OmfRecordFactory(provider), monitor);
|
||||
ArrayList<OmfLibraryRecord.MemberHeader> memberHeaders = libraryRec.getMemberHeaders();
|
||||
for (OmfLibraryRecord.MemberHeader member : memberHeaders) {
|
||||
String name = member.name;
|
||||
|
@ -17,10 +17,11 @@ package ghidra.file.formats.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfFileHeader;
|
||||
import ghidra.app.util.bin.format.omf.AbstractOmfRecordFactory;
|
||||
import ghidra.app.util.bin.format.omf.OmfException;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord;
|
||||
import ghidra.app.util.bin.format.omf.omf.OmfRecordFactory;
|
||||
import ghidra.app.util.opinion.OmfLoader;
|
||||
import ghidra.formats.gfilesystem.FSRLRoot;
|
||||
import ghidra.formats.gfilesystem.FileSystemService;
|
||||
@ -38,7 +39,12 @@ public class OmfArchiveFileSystemFactory implements
|
||||
throws IOException, CancelledException {
|
||||
|
||||
OmfArchiveFileSystem fs = new OmfArchiveFileSystem(targetFSRL, byteProvider);
|
||||
fs.mount(monitor);
|
||||
try {
|
||||
fs.mount(monitor);
|
||||
}
|
||||
catch (OmfException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
@ -51,8 +57,8 @@ public class OmfArchiveFileSystemFactory implements
|
||||
}
|
||||
|
||||
try {
|
||||
BinaryReader reader = OmfFileHeader.createReader(byteProvider);
|
||||
return OmfLibraryRecord.checkMagicNumber(reader);
|
||||
AbstractOmfRecordFactory factory = new OmfRecordFactory(byteProvider);
|
||||
return OmfLibraryRecord.checkMagicNumber(factory.getReader());
|
||||
}
|
||||
catch (IOException e) {
|
||||
return false;
|
||||
|
@ -8,6 +8,7 @@ data/languages/80390.cspec||GHIDRA||||END|
|
||||
data/languages/80390.slaspec||GHIDRA||||END|
|
||||
data/languages/8051.cspec||GHIDRA||||END|
|
||||
data/languages/8051.ldefs||GHIDRA||||END|
|
||||
data/languages/8051.opinion||GHIDRA||||END|
|
||||
data/languages/8051.pspec||GHIDRA||||END|
|
||||
data/languages/8051.slaspec||GHIDRA||||END|
|
||||
data/languages/8051_archimedes.cspec||GHIDRA||||END|
|
||||
|
7
Ghidra/Processors/8051/data/languages/8051.opinion
Normal file
7
Ghidra/Processors/8051/data/languages/8051.opinion
Normal file
@ -0,0 +1,7 @@
|
||||
<opinions>
|
||||
<constraint loader="Object Module Format (OMF-51)">
|
||||
<constraint compilerSpecID="default">
|
||||
<constraint primary="8051" processor="8051" endian="big" size="16" />
|
||||
</constraint>
|
||||
</constraint>
|
||||
</opinions>
|
Loading…
Reference in New Issue
Block a user