Compare commits

...

5 Commits

Author SHA1 Message Date
Brian Wright
fea7544703
Merge 5963669eac into 93eed8011c 2024-06-28 08:45:26 -04:00
Ryan Kurtz
93eed8011c GP-4729: Refactor existing OMF support 2024-06-28 07:50:37 -04:00
ghidra1
3cffe5c168 Merge remote-tracking branch 'origin/patch' 2024-06-27 12:30:15 -04:00
ghidra1
b78c975ee3 GP-4508 applied critical portion of stored context fix for patch release 2024-06-27 12:20:04 -04:00
Brian
5963669eac add support for Arm stack limit register instructions 2024-06-24 16:38:10 +02:00
31 changed files with 616 additions and 295 deletions

View File

@ -21,20 +21,35 @@ import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/**
* An OMF value that is either 2 or 4 bytes
*/
public class Omf2or4 implements StructConverter { public class Omf2or4 implements StructConverter {
private int length; private int length;
private long value; private long value;
/**
* Creates a new {@link Omf2or4}
*
* @param length 2 or 4
* @param value The 2 or 4 byte value
*/
public Omf2or4(int length, long value) { public Omf2or4(int length, long value) {
this.length = length; this.length = length;
this.value = value; this.value = value;
} }
/**
* {@return the length of the value (2 or 4)}
*/
public int length() { public int length() {
return length; return length;
} }
/**
* {@return the value}
*/
public long value() { public long value() {
return value; return value;
} }

View File

@ -15,8 +15,16 @@
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf;
/**
* An {@link Exception} used to indicate there was a problem parsing an OMF record
*/
public class OmfException extends Exception { public class OmfException extends Exception {
/**
* Creates a new {@link OmfException}
*
* @param message The exception message
*/
public OmfException(String message) { public OmfException(String message) {
super(message); super(message);
} }

View File

@ -21,20 +21,35 @@ import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/**
* An OMF index that is either 1 or 2 bytes
*/
public class OmfIndex implements StructConverter { public class OmfIndex implements StructConverter {
private int length; private int length;
private int value; private int value;
/**
* Creates a new {@link OmfIndex}
*
* @param length 1 or 2
* @param value The 1 or 2 byte index value
*/
public OmfIndex(int length, int value) { public OmfIndex(int length, int value) {
this.length = length; this.length = length;
this.value = value; this.value = value;
} }
/**
* {@return the length of the index (1 or 2)}
*/
public int length() { public int length() {
return length; return length;
} }
/**
* {@return the index value}
*/
public int value() { public int value() {
return value; return value;
} }

View File

@ -18,6 +18,9 @@ package ghidra.app.util.bin.format.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.omf.OmfRecordTypes;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
public class OmfObsoleteRecord extends OmfRecord { public class OmfObsoleteRecord extends OmfRecord {
@ -31,4 +34,9 @@ public class OmfObsoleteRecord extends OmfRecord {
readRecordHeader(reader); readRecordHeader(reader);
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength()); reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -16,258 +16,111 @@
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
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.program.model.data.*; import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/**
* A generic OMF record
*/
public abstract class OmfRecord implements StructConverter { public abstract class OmfRecord implements StructConverter {
public final static byte RHEADR = (byte) 0x6E; // Obsolete
public final static byte REGINT = (byte) 0x70; // Obsolete
public final static byte REDATA = (byte) 0x72; // Obsolete
public final static byte RIDATA = (byte) 0x74; // Obsolete
public final static byte OVLDEF = (byte) 0x76; // Obsolete
public final static byte ENDREC = (byte) 0x78; // Obsolete
public final static byte BLKDEF = (byte) 0x7A; // Obsolete
public final static byte BLKEND = (byte) 0x7C; // Obsolete
public final static byte DEBSYM = (byte) 0x7E; // Obsolete
public final static byte THEADR = (byte) 0x80;
public final static byte LHEADR = (byte) 0x82;
public final static byte PEDATA = (byte) 0x84; // Obsolete
public final static byte PIDATA = (byte) 0x86; // Obsolete
public final static byte COMENT = (byte) 0x88;
public final static byte MODEND = (byte) 0x8A;
public final static byte EXTDEF = (byte) 0x8C;
public final static byte TYPDEF = (byte) 0x8E; // Obsolete
public final static byte PUBDEF = (byte) 0x90;
public final static byte LOCSYM = (byte) 0x92; // Obsolete
public final static byte LINNUM = (byte) 0x94;
public final static byte LNAMES = (byte) 0x96;
public final static byte SEGDEF = (byte) 0x98;
public final static byte GRPDEF = (byte) 0x9A;
public final static byte FIXUPP = (byte) 0x9C;
public final static byte LEDATA = (byte) 0xA0;
public final static byte LIDATA = (byte) 0xA2;
public final static byte LIBHED = (byte) 0xA4; // Obsolete
public final static byte LIBNAM = (byte) 0xA6; // Obsolete
public final static byte LIBLOC = (byte) 0xA8; // Obsolete
public final static byte LIBDIC = (byte) 0xAA; // Obsolete
public final static byte COMDEF = (byte) 0xB0;
public final static byte BAKPAT = (byte) 0xB2;
public final static byte LEXTDEF = (byte) 0xB4;
public final static byte LPUBDEF = (byte) 0xB6;
public final static byte LCOMDEF = (byte) 0xB8;
public final static byte CEXTDEF = (byte) 0xBC;
public final static byte COMDAT = (byte) 0xC2;
public final static byte LINSYM = (byte) 0xC4;
public final static byte ALIAS = (byte) 0xC6;
public final static byte NBKPAT = (byte) 0xC8;
public final static byte LLNAMES = (byte) 0xCA;
public final static byte VERNUM = (byte) 0xCC;
public final static byte VENDEXT = (byte) 0xCE;
public final static byte START = (byte) 0xF0;
public final static byte END = (byte) 0xF1;
protected static final String CATEGORY_PATH = "/OMF"; protected int recordType;
protected byte recordType;
protected int recordLength; protected int recordLength;
protected long recordOffset;
protected byte checkSum; protected byte checkSum;
public byte getRecordType() { protected long recordOffset;
return recordType;
}
public int getRecordLength() {
return recordLength;
}
public long getRecordOffset() {
return recordOffset;
}
/**
* Reads the record header (type and length fields)
*
* @param reader A {@link BinaryReader} positioned at the start of the record
* @throws IOException if an IO-related problem occurred
*/
public void readRecordHeader(BinaryReader reader) throws IOException { public void readRecordHeader(BinaryReader reader) throws IOException {
recordOffset = reader.getPointerIndex(); recordOffset = reader.getPointerIndex();
recordType = reader.readNextByte(); recordType = reader.readNextUnsignedByte();
recordLength = reader.readNextShort() & 0xffff; recordLength = reader.readNextUnsignedShort();
} }
/**
* Reads the record checksum
*
* @param reader A {@link BinaryReader} positioned at the start of the record checksum
* @throws IOException if an IO-related problem occurred
*/
public void readCheckSumByte(BinaryReader reader) throws IOException { public void readCheckSumByte(BinaryReader reader) throws IOException {
checkSum = reader.readNextByte(); checkSum = reader.readNextByte();
} }
/**
* {@return the record type}
*/
public int getRecordType() {
return recordType;
}
/**
* {@return the record length}
*/
public int getRecordLength() {
return recordLength;
}
/**
* {@return the record offset}
*/
public long getRecordOffset() {
return recordOffset;
}
/**
* 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 { public byte calcCheckSum(BinaryReader reader) throws IOException {
byte res = reader.readNextByte(); byte res = reader.readNextByte();
res += reader.readNextByte(); res += reader.readNextByte();
res += reader.readNextByte(); // Sum the record header bytes res += reader.readNextByte(); // Sum the record header bytes
for (int i = 0; i < recordLength; ++i) for (int i = 0; i < recordLength; ++i) {
res += reader.readNextByte(); res += reader.readNextByte();
}
return res; return res;
} }
/**
* 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(BinaryReader reader) throws IOException {
if (checkSum == 0) if (checkSum == 0) {
return true; // Sum compilers just set this to zero // Some compilers just set this to zero
return true;
}
return (calcCheckSum(reader) == 0); return (calcCheckSum(reader) == 0);
} }
/**
* {@return true if this record has big fields; otherwise, false}
*/
public boolean hasBigFields() { public boolean hasBigFields() {
return ((recordType & 1) != 0); return ((recordType & 1) != 0);
} }
public static int readInt1Or2(BinaryReader reader, boolean isBig) throws IOException { @Override
if (isBig) public abstract DataType toDataType() throws DuplicateNameException, IOException;
return (reader.readNextShort() & 0xffff);
return (reader.readNextByte() & 0xff);
}
public static Omf2or4 readInt2Or4(BinaryReader reader, boolean isBig) throws IOException {
if (isBig) {
return new Omf2or4(4, reader.readNextInt());
}
return new Omf2or4(2, reader.readNextUnsignedShort());
}
public static OmfIndex readIndex(BinaryReader reader) throws IOException {
int length;
int indexWord;
byte firstByte = reader.readNextByte();
if ((firstByte & 0x80) != 0) {
indexWord = (firstByte & 0x7f) * 0x100 + (reader.readNextByte() & 0xff);
length = 2;
}
else {
indexWord = firstByte;
length = 1;
}
return new OmfIndex(length, indexWord);
}
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
byte type = reader.peekNextByte();
type &= 0xfe; // Mask off the least significant bit (16/32 bit flag)
return switch (type) {
case THEADR:
case LHEADR:
yield new OmfFileHeader(reader);
case COMENT:
yield new OmfCommentRecord(reader);
case MODEND:
yield new OmfModuleEnd(reader);
case EXTDEF:
yield new OmfExternalSymbol(reader, false);
case PUBDEF:
yield new OmfSymbolRecord(reader, false);
case LNAMES:
yield new OmfNamesRecord(reader);
case SEGDEF:
yield new OmfSegmentHeader(reader);
case GRPDEF:
yield new OmfGroupRecord(reader);
case FIXUPP:
yield new OmfFixupRecord(reader);
case LEDATA:
yield new OmfEnumeratedData(reader);
case LIDATA:
yield new OmfIteratedData(reader);
case COMDEF:
yield new OmfComdefRecord(reader, false);
case LEXTDEF:
yield new OmfExternalSymbol(reader, true);
case LPUBDEF:
yield new OmfSymbolRecord(reader, true);
case LCOMDEF:
yield new OmfComdefRecord(reader, true);
case CEXTDEF:
yield new OmfComdatExternalSymbol(reader);
case RHEADR:
case REGINT:
case REDATA:
case RIDATA:
case OVLDEF:
case ENDREC:
case BLKDEF:
case BLKEND:
case DEBSYM:
case LINNUM:
case PEDATA:
case PIDATA:
case LIBHED:
case LIBNAM:
case LIBLOC:
case LIBDIC:
yield new OmfObsoleteRecord(reader);
case LOCSYM:
case TYPDEF:
case COMDAT:
case LINSYM:
case ALIAS:
case BAKPAT:
case NBKPAT:
case LLNAMES:
case VERNUM:
case VENDEXT:
yield new OmfUnsupportedRecord(reader);
default:
yield new OmfUnknownRecord(reader);
};
}
/**
* Read the OMF string format: 1-byte length, followed by that many ascii characters
*
* @param reader A {@link BinaryReader} positioned at the start of the string
* @return the read OMF string
* @throws IOException if an IO-related error occurred
*/
public static OmfString readString(BinaryReader reader) throws IOException {
int count = reader.readNextByte() & 0xff;
return new OmfString(count, reader.readNextAsciiString(count));
}
/**
* 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 getRecordName(int type) {
for (Field field : OmfRecord.class.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
try {
Byte value = (Byte) field.get(null);
if (type == value) {
return field.getName();
}
}
catch (Exception e) {
break;
}
}
}
return "<UNKNOWN>";
}
@Override @Override
public String toString() { public String toString() {
return String.format("name: %s, type: 0x%x, offset: 0x%x, length: 0x%x", return String.format("type: 0x%x, offset: 0x%x, length: 0x%x", recordType, recordOffset,
getRecordName(recordType & (byte) 0xfe), recordType, recordOffset, recordLength); recordLength);
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0);
struct.add(BYTE, "type", null);
struct.add(WORD, "length", null);
struct.add(new ArrayDataType(BYTE, getRecordLength() - 1, 1), "contents", null);
struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(CATEGORY_PATH));
return struct;
} }
} }

View File

@ -21,20 +21,35 @@ import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/**
* An variable length OMF string
*/
public class OmfString implements StructConverter { public class OmfString implements StructConverter {
private int length; private int length;
private String str; private String str;
/**
* Creates a new {@link OmfString}
*
* @param length The length of the string
* @param str The string
*/
public OmfString(int length, String str) { public OmfString(int length, String str) {
this.length = length; this.length = length;
this.str = str; this.str = str;
} }
/**
* {@return the length of the string}
*/
public int length() { public int length() {
return length; return length;
} }
/**
* {@return the string}
*/
public String str() { public String str() {
return str; return str;
} }
@ -48,7 +63,7 @@ public class OmfString implements StructConverter {
StructureDataType struct = new StructureDataType("OmfString", 0); StructureDataType struct = new StructureDataType("OmfString", 0);
struct.add(BYTE, "length", ""); struct.add(BYTE, "length", "");
struct.add(new StringDataType(), length, "str", null); struct.add(new StringDataType(), length, "str", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -18,7 +18,13 @@ package ghidra.app.util.bin.format.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.omf.OmfRecordTypes;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* An unknown OMF record
*/
public class OmfUnknownRecord extends OmfRecord { public class OmfUnknownRecord extends OmfRecord {
/** /**
@ -31,4 +37,9 @@ public class OmfUnknownRecord extends OmfRecord {
readRecordHeader(reader); readRecordHeader(reader);
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength()); reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -18,17 +18,32 @@ package ghidra.app.util.bin.format.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* A known but currently unsupported OMF record
*/
public class OmfUnsupportedRecord extends OmfRecord { public class OmfUnsupportedRecord extends OmfRecord {
private Class<?> recordTypesClass;
/** /**
* Create a new {@link OmfUnsupportedRecord} * Create a new {@link OmfUnsupportedRecord}
* *
* @param reader A {@link BinaryReader} positioned at the start of the record * @param reader A {@link BinaryReader} positioned at the start of the record
* @param recordTypesClass The class that contains accessible OMF type fields
* @throws IOException If an IO-related error occurred * @throws IOException If an IO-related error occurred
*/ */
public OmfUnsupportedRecord(BinaryReader reader) throws IOException { public OmfUnsupportedRecord(BinaryReader reader, Class<?> recordTypesClass) throws IOException {
this.recordTypesClass = recordTypesClass;
readRecordHeader(reader); readRecordHeader(reader);
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength()); reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this,
OmfUtils.getRecordName(recordType, recordTypesClass));
}
} }

View File

@ -0,0 +1,108 @@
/* ###
* 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.lang.reflect.Field;
import java.lang.reflect.Modifier;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
/**
* Utility class for OMF-based file formats
*/
public class OmfUtils {
/** Data type category */
public static final String CATEGORY_PATH = "/OMF";
public static Omf2or4 readInt2Or4(BinaryReader reader, boolean isBig) throws IOException {
return isBig ? new Omf2or4(4, reader.readNextInt())
: new Omf2or4(2, reader.readNextUnsignedShort());
}
public static OmfIndex readIndex(BinaryReader reader) throws IOException {
int length;
int indexWord;
byte firstByte = reader.readNextByte();
if ((firstByte & 0x80) != 0) {
indexWord = (firstByte & 0x7f) * 0x100 + (reader.readNextByte() & 0xff);
length = 2;
}
else {
indexWord = firstByte;
length = 1;
}
return new OmfIndex(length, indexWord);
}
/**
* Read the OMF string format: 1-byte length, followed by that many ascii characters
*
* @param reader A {@link BinaryReader} positioned at the start of the string
* @return the read OMF string
* @throws IOException if an IO-related error occurred
*/
public static OmfString readString(BinaryReader reader) throws IOException {
int count = reader.readNextUnsignedByte();
return new OmfString(count, reader.readNextAsciiString(count));
}
/**
* Gets the name of the given record type
*
* @param type The record type
* @param recordTypesClass The class that contains accessible OMF type fields
* @return The name of the given record type
*/
public final static String getRecordName(int type, Class<?> recordTypesClass) {
for (Field field : recordTypesClass.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
try {
Integer value = (Integer) field.get(null);
if (type == value) {
return field.getName();
}
}
catch (Exception e) {
break;
}
}
}
return "<UNKNOWN>";
}
/**
* Converts the given {@link OmfRecord} to a generic OMF record {@link DataType}
*
* @param record The OMF record to convert
* @param name The name of the OMF record
* @return A {@link DataType} for the given OMF record
*/
public static DataType toOmfRecordDataType(OmfRecord record, String name) {
StructureDataType struct = new StructureDataType(name, 0);
struct.add(ByteDataType.dataType, "type", null);
struct.add(WordDataType.dataType, "length", null);
struct.add(new ArrayDataType(ByteDataType.dataType, record.getRecordLength() - 1, 1),
"contents", null);
struct.add(ByteDataType.dataType, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct;
}
}

View File

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; 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.BinaryReader;
import ghidra.app.util.bin.format.omf.OmfIndex;
import ghidra.app.util.bin.format.omf.OmfUtils;
public class OmfComdatExternalSymbol extends OmfExternalSymbol { public class OmfComdatExternalSymbol extends OmfExternalSymbol {
@ -32,8 +34,8 @@ public class OmfComdatExternalSymbol extends OmfExternalSymbol {
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
OmfIndex nameIndex = OmfRecord.readIndex(reader); OmfIndex nameIndex = OmfUtils.readIndex(reader);
OmfIndex type = OmfRecord.readIndex(reader); OmfIndex type = OmfUtils.readIndex(reader);
externalLookups.add(new ExternalLookup(nameIndex.value(), type.value())); externalLookups.add(new ExternalLookup(nameIndex.value(), type.value()));
} }

View File

@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
public class OmfComdefRecord extends OmfExternalSymbol { public class OmfComdefRecord extends OmfExternalSymbol {
@ -27,8 +28,8 @@ public class OmfComdefRecord extends OmfExternalSymbol {
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
OmfString name = OmfRecord.readString(reader); OmfString name = OmfUtils.readString(reader);
OmfIndex typeIndex = OmfRecord.readIndex(reader); OmfIndex typeIndex = OmfUtils.readIndex(reader);
byte dataType = reader.readNextByte(); byte dataType = reader.readNextByte();
int byteLength = 0; int byteLength = 0;
if (dataType == 0x61) { // FAR data, reads numElements and elSize if (dataType == 0x61) { // FAR data, reads numElements and elSize

View File

@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -51,7 +52,7 @@ public class OmfCommentRecord extends OmfRecord {
value = new OmfString(bytes.length, new String(bytes, StandardCharsets.US_ASCII)); // assuming ASCII value = new OmfString(bytes.length, new String(bytes, StandardCharsets.US_ASCII)); // assuming ASCII
break; break;
case COMMENT_CLASS_LIBMOD: case COMMENT_CLASS_LIBMOD:
value = readString(reader); value = OmfUtils.readString(reader);
break; break;
default: default:
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength() - 3); reader.setPointerIndex(reader.getPointerIndex() + getRecordLength() - 3);
@ -76,7 +77,7 @@ public class OmfCommentRecord extends OmfRecord {
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
int strlen = getRecordLength() - 3; int strlen = getRecordLength() - 3;
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.getName(recordType), 0);
struct.add(BYTE, "type", null); struct.add(BYTE, "type", null);
struct.add(WORD, "length", ""); struct.add(WORD, "length", "");
struct.add(BYTE, "comment_type", null); struct.add(BYTE, "comment_type", null);
@ -86,7 +87,7 @@ public class OmfCommentRecord extends OmfRecord {
} }
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
/** /**
* Object representing data loaded directly into the final image. * Object representing data loaded directly into the final image.

View File

@ -13,11 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.OmfUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
public class OmfEnumeratedData extends OmfData { public class OmfEnumeratedData extends OmfData {
private long streamOffset; // Position in stream where data starts private long streamOffset; // Position in stream where data starts
@ -26,8 +29,8 @@ public class OmfEnumeratedData extends OmfData {
public OmfEnumeratedData(BinaryReader reader) throws IOException { public OmfEnumeratedData(BinaryReader reader) throws IOException {
readRecordHeader(reader); readRecordHeader(reader);
long start = reader.getPointerIndex(); long start = reader.getPointerIndex();
segmentIndex = OmfRecord.readIndex(reader); segmentIndex = OmfUtils.readIndex(reader);
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields()); dataOffset = OmfUtils.readInt2Or4(reader, hasBigFields());
streamOffset = reader.getPointerIndex(); streamOffset = reader.getPointerIndex();
streamLength = getRecordLength() - 1 - (int) (streamOffset - start); streamLength = getRecordLength() - 1 - (int) (streamOffset - start);
reader.setPointerIndex(streamOffset + streamLength); // Skip over the data when reading header reader.setPointerIndex(streamOffset + streamLength); // Skip over the data when reading header
@ -50,4 +53,9 @@ public class OmfEnumeratedData extends OmfData {
public boolean isAllZeroes() { public boolean isAllZeroes() {
return false; return false;
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; 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.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -42,8 +43,8 @@ public class OmfExternalSymbol extends OmfRecord {
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
OmfString name = OmfRecord.readString(reader); OmfString name = OmfUtils.readString(reader);
OmfIndex type = OmfRecord.readIndex(reader); OmfIndex type = OmfUtils.readIndex(reader);
refs.add(new Reference(name, type)); refs.add(new Reference(name, type));
symbols.add(new OmfSymbol(name.str(), type.value(), 0, 0, 0)); symbols.add(new OmfSymbol(name.str(), type.value(), 0, 0, 0));
} }
@ -61,7 +62,7 @@ public class OmfExternalSymbol extends OmfRecord {
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.getName(recordType), 0);
struct.add(BYTE, "type", null); struct.add(BYTE, "type", null);
struct.add(WORD, "length", null); struct.add(WORD, "length", null);
for (Reference ref : refs) { for (Reference ref : refs) {
@ -70,7 +71,7 @@ public class OmfExternalSymbol extends OmfRecord {
} }
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -21,6 +21,7 @@ import java.util.List;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.omf.*;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -45,7 +46,7 @@ public class OmfFileHeader extends OmfRecord {
public OmfFileHeader(BinaryReader reader) throws IOException { public OmfFileHeader(BinaryReader reader) throws IOException {
readRecordHeader(reader); readRecordHeader(reader);
objectName = readString(reader); // This is usually the source code filename objectName = OmfUtils.readString(reader); // This is usually the source code filename
readCheckSumByte(reader); readCheckSumByte(reader);
isLittleEndian = reader.isLittleEndian(); isLittleEndian = reader.isLittleEndian();
} }
@ -269,14 +270,14 @@ public class OmfFileHeader extends OmfRecord {
*/ */
public static OmfFileHeader scan(BinaryReader reader, TaskMonitor monitor, boolean fastscan) public static OmfFileHeader scan(BinaryReader reader, TaskMonitor monitor, boolean fastscan)
throws IOException, OmfException { throws IOException, OmfException {
OmfRecord record = OmfRecord.readRecord(reader); OmfRecord record = OmfRecordFactory.readRecord(reader);
if (!(record instanceof OmfFileHeader)) { if (!(record instanceof OmfFileHeader)) {
throw new OmfException("Object file does not start with proper header"); throw new OmfException("Object file does not start with proper header");
} }
OmfFileHeader header = (OmfFileHeader) record; OmfFileHeader header = (OmfFileHeader) record;
while (true) { while (true) {
record = OmfRecord.readRecord(reader); record = OmfRecordFactory.readRecord(reader);
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
break; break;
@ -323,7 +324,7 @@ public class OmfFileHeader extends OmfRecord {
*/ */
public static OmfFileHeader parse(BinaryReader reader, TaskMonitor monitor, MessageLog log) public static OmfFileHeader parse(BinaryReader reader, TaskMonitor monitor, MessageLog log)
throws IOException, OmfException { throws IOException, OmfException {
OmfRecord record = OmfRecord.readRecord(reader); OmfRecord record = OmfRecordFactory.readRecord(reader);
if (!(record instanceof OmfFileHeader header)) { if (!(record instanceof OmfFileHeader header)) {
throw new OmfException("Object file does not start with proper header"); throw new OmfException("Object file does not start with proper header");
} }
@ -331,7 +332,7 @@ public class OmfFileHeader extends OmfRecord {
OmfData lastDataBlock = null; OmfData lastDataBlock = null;
while (true) { while (true) {
record = OmfRecord.readRecord(reader); record = OmfRecordFactory.readRecord(reader);
header.records.add(record); header.records.add(record);
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
@ -392,7 +393,7 @@ public class OmfFileHeader extends OmfRecord {
} }
else if (record instanceof OmfUnsupportedRecord) { else if (record instanceof OmfUnsupportedRecord) {
// TODO: Should we always set lastDataBlock to null? // TODO: Should we always set lastDataBlock to null?
if (record.getRecordType() == COMDAT) { if (record.getRecordType() == OmfRecordTypes.COMDAT) {
lastDataBlock = null; lastDataBlock = null;
} }
logRecord("Unsupported OMF record", record, log); logRecord("Unsupported OMF record", record, log);
@ -477,16 +478,14 @@ public class OmfFileHeader extends OmfRecord {
* @throws IOException for problems reading bytes * @throws IOException for problems reading bytes
*/ */
public static boolean checkMagicNumber(BinaryReader reader) throws IOException { public static boolean checkMagicNumber(BinaryReader reader) throws IOException {
byte first = reader.readNextByte(); int type = reader.readNextUnsignedByte();
if ((first & 0xfc) != 0x80) { type &= 0xfffffffe; // mask off the least significant bit (16/32 bit flag)
if (type != OmfRecordTypes.THEADR && type != OmfRecordTypes.LHEADR) {
return false; return false;
} }
int len = reader.readNextShort() & 0xffff; int len = reader.readNextUnsignedShort();
int stringlen = reader.readNextByte() & 0xff; int stringlen = reader.readNextUnsignedByte();
if (len != stringlen + 2) { return len == stringlen + 2;
return false;
}
return true;
} }
/** /**
@ -504,13 +503,13 @@ public class OmfFileHeader extends OmfRecord {
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.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(objectName.toDataType(), "name", null); struct.add(objectName.toDataType(), "name", null);
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -13,12 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; 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.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
public class OmfFixupRecord extends OmfRecord { public class OmfFixupRecord extends OmfRecord {
private final Subrecord[] subrecs; private final Subrecord[] subrecs;
@ -27,7 +30,7 @@ public class OmfFixupRecord extends OmfRecord {
/** /**
* Read a Fixup record from the input reader * Read a Fixup record from the input reader
* @param reader The actual reader * @param reader The actual reader
* @throws IOException * @throws IOException if there was an IO-related error
*/ */
public OmfFixupRecord(BinaryReader reader) throws IOException { public OmfFixupRecord(BinaryReader reader) throws IOException {
ArrayList<Subrecord> subreclist = new ArrayList<Subrecord>(); ArrayList<Subrecord> subreclist = new ArrayList<Subrecord>();
@ -63,6 +66,7 @@ public class OmfFixupRecord extends OmfRecord {
return subrecs; return subrecs;
} }
@SuppressWarnings("unused")
public static class Subrecord { public static class Subrecord {
private byte first; private byte first;
private byte hiFixup; private byte hiFixup;
@ -78,7 +82,7 @@ public class OmfFixupRecord extends OmfRecord {
* @param reader The input file * @param reader The input file
* @param hasBigFields Is this 16 or 32 bit values * @param hasBigFields Is this 16 or 32 bit values
* @return The read subrecord * @return The read subrecord
* @throws IOException * @throws IOException if there was an IO-related error
*/ */
public static Subrecord readSubrecord(BinaryReader reader, boolean hasBigFields) public static Subrecord readSubrecord(BinaryReader reader, boolean hasBigFields)
throws IOException { throws IOException {
@ -89,7 +93,7 @@ public class OmfFixupRecord extends OmfRecord {
if (rec.isThreadSubrecord()) { if (rec.isThreadSubrecord()) {
method = rec.getThreadMethod(); method = rec.getThreadMethod();
if (method < 4) { if (method < 4) {
rec.index = readIndex(reader); rec.index = OmfUtils.readIndex(reader);
} }
return rec; return rec;
} }
@ -99,13 +103,13 @@ public class OmfFixupRecord extends OmfRecord {
rec.fixData = reader.readNextByte(); rec.fixData = reader.readNextByte();
method = rec.getFrameMethod(); method = rec.getFrameMethod();
if (!rec.isFrameThread() && method < 3) { // F=0 (explicit frame method (and datum)) if (!rec.isFrameThread() && method < 3) { // F=0 (explicit frame method (and datum))
rec.frameDatum = readIndex(reader); rec.frameDatum = OmfUtils.readIndex(reader);
} }
if (!rec.isTargetThread()) { // T=0 (explicit target) if (!rec.isTargetThread()) { // T=0 (explicit target)
rec.targetDatum = readIndex(reader); rec.targetDatum = OmfUtils.readIndex(reader);
} }
if ((rec.fixData & 0x04) == 0) { // P=0 if ((rec.fixData & 0x04) == 0) { // P=0
rec.targetDisplacement = readInt2Or4(reader, hasBigFields); rec.targetDisplacement = OmfUtils.readInt2Or4(reader, hasBigFields);
} }
return rec; return rec;
} }
@ -190,4 +194,9 @@ public class OmfFixupRecord extends OmfRecord {
} }
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,16 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; 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.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.util.exception.DuplicateNameException;
public class OmfGroupRecord extends OmfRecord { public class OmfGroupRecord extends OmfRecord {
private OmfIndex groupNameIndex; private OmfIndex groupNameIndex;
@ -33,7 +36,7 @@ public class OmfGroupRecord extends OmfRecord {
public OmfGroupRecord(BinaryReader reader) throws IOException { public OmfGroupRecord(BinaryReader reader) throws IOException {
readRecordHeader(reader); readRecordHeader(reader);
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
groupNameIndex = OmfRecord.readIndex(reader); groupNameIndex = OmfUtils.readIndex(reader);
ArrayList<GroupSubrecord> grouplist = new ArrayList<GroupSubrecord>(); ArrayList<GroupSubrecord> grouplist = new ArrayList<GroupSubrecord>();
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
GroupSubrecord subrec = GroupSubrecord.read(reader); GroupSubrecord subrec = GroupSubrecord.read(reader);
@ -98,8 +101,13 @@ public class OmfGroupRecord extends OmfRecord {
public static GroupSubrecord read(BinaryReader reader) throws IOException { public static GroupSubrecord read(BinaryReader reader) throws IOException {
GroupSubrecord subrec = new GroupSubrecord(); GroupSubrecord subrec = new GroupSubrecord();
subrec.componentType = reader.readNextByte(); subrec.componentType = reader.readNextByte();
subrec.segmentIndex = OmfRecord.readIndex(reader); subrec.segmentIndex = OmfUtils.readIndex(reader);
return subrec; return subrec;
} }
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.Omf2or4;
import ghidra.app.util.bin.format.omf.OmfUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
public class OmfIteratedData extends OmfData { public class OmfIteratedData extends OmfData {
@ -29,8 +33,8 @@ public class OmfIteratedData extends OmfData {
readRecordHeader(reader); readRecordHeader(reader);
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
boolean hasBigFields = hasBigFields(); boolean hasBigFields = hasBigFields();
segmentIndex = OmfRecord.readIndex(reader); segmentIndex = OmfUtils.readIndex(reader);
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields); dataOffset = OmfUtils.readInt2Or4(reader, hasBigFields);
ArrayList<DataBlock> blocklist = new ArrayList<DataBlock>(); ArrayList<DataBlock> blocklist = new ArrayList<DataBlock>();
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
DataBlock block = DataBlock.read(reader, hasBigFields); DataBlock block = DataBlock.read(reader, hasBigFields);
@ -85,7 +89,7 @@ public class OmfIteratedData extends OmfData {
public static DataBlock read(BinaryReader reader, boolean hasBigFields) throws IOException { public static DataBlock read(BinaryReader reader, boolean hasBigFields) throws IOException {
DataBlock subblock = new DataBlock(); DataBlock subblock = new DataBlock();
subblock.repeatCount = OmfRecord.readInt2Or4(reader, hasBigFields); subblock.repeatCount = OmfUtils.readInt2Or4(reader, hasBigFields);
subblock.blockCount = reader.readNextUnsignedShort(); subblock.blockCount = reader.readNextUnsignedShort();
if (subblock.blockCount == 0) { if (subblock.blockCount == 0) {
int size = reader.readNextByte() & 0xff; int size = reader.readNextByte() & 0xff;
@ -163,4 +167,9 @@ public class OmfIteratedData extends OmfData {
return true; return true;
} }
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,14 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; 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.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@SuppressWarnings("unused")
public class OmfLibraryRecord extends OmfRecord { public class OmfLibraryRecord extends OmfRecord {
private int pageSize; // All archive members must start on a page boundary of this size private int pageSize; // All archive members must start on a page boundary of this size
private long dictionaryOffset; private long dictionaryOffset;
@ -118,4 +122,9 @@ public class OmfLibraryRecord extends OmfRecord {
} }
return res; return res;
} }
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,11 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.OmfRecord;
import ghidra.app.util.bin.format.omf.OmfUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
public class OmfModuleEnd extends OmfRecord { public class OmfModuleEnd extends OmfRecord {
//private byte moduleType; //private byte moduleType;
@ -46,4 +50,9 @@ public class OmfModuleEnd extends OmfRecord {
return ((moduleType & 0x40) != 0); return ((moduleType & 0x40) != 0);
} }
*/ */
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return OmfUtils.toOmfRecordDataType(this, OmfRecordTypes.getName(recordType));
}
} }

View File

@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; 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.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -30,7 +31,7 @@ public class OmfNamesRecord extends OmfRecord {
readRecordHeader(reader); readRecordHeader(reader);
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
names.add(OmfRecord.readString(reader)); names.add(OmfUtils.readString(reader));
} }
readCheckSumByte(reader); readCheckSumByte(reader);
} }
@ -41,7 +42,7 @@ public class OmfNamesRecord extends OmfRecord {
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.getName(recordType), 0);
struct.add(BYTE, "type", null); struct.add(BYTE, "type", null);
struct.add(WORD, "length", null); struct.add(WORD, "length", null);
for (OmfString name : names) { for (OmfString name : names) {
@ -49,7 +50,7 @@ public class OmfNamesRecord extends OmfRecord {
} }
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -0,0 +1,95 @@
/* ###
* 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.omf;
import static ghidra.app.util.bin.format.omf.omf.OmfRecordTypes.*;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
public class OmfRecordFactory {
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
int type = Byte.toUnsignedInt(reader.peekNextByte());
return switch (type & 0xfffffffe) { // mask off the least significant bit (16/32 bit flag)
case THEADR:
case LHEADR:
yield new OmfFileHeader(reader);
case COMENT:
yield new OmfCommentRecord(reader);
case MODEND:
yield new OmfModuleEnd(reader);
case EXTDEF:
yield new OmfExternalSymbol(reader, false);
case PUBDEF:
yield new OmfSymbolRecord(reader, false);
case LNAMES:
yield new OmfNamesRecord(reader);
case SEGDEF:
yield new OmfSegmentHeader(reader);
case GRPDEF:
yield new OmfGroupRecord(reader);
case FIXUPP:
yield new OmfFixupRecord(reader);
case LEDATA:
yield new OmfEnumeratedData(reader);
case LIDATA:
yield new OmfIteratedData(reader);
case COMDEF:
yield new OmfComdefRecord(reader, false);
case LEXTDEF:
yield new OmfExternalSymbol(reader, true);
case LPUBDEF:
yield new OmfSymbolRecord(reader, true);
case LCOMDEF:
yield new OmfComdefRecord(reader, true);
case CEXTDEF:
yield new OmfComdatExternalSymbol(reader);
case RHEADR:
case REGINT:
case REDATA:
case RIDATA:
case OVLDEF:
case ENDREC:
case BLKDEF:
case BLKEND:
case DEBSYM:
case LINNUM:
case PEDATA:
case PIDATA:
case LIBHED:
case LIBNAM:
case LIBLOC:
case LIBDIC:
yield new OmfObsoleteRecord(reader);
case LOCSYM:
case TYPDEF:
case COMDAT:
case LINSYM:
case ALIAS:
case BAKPAT:
case NBKPAT:
case LLNAMES:
case VERNUM:
case VENDEXT:
yield new OmfUnsupportedRecord(reader, OmfRecordTypes.class);
default:
yield new OmfUnknownRecord(reader);
};
}
}

View File

@ -0,0 +1,77 @@
/* ###
* 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.omf;
import ghidra.app.util.bin.format.omf.OmfUtils;
public class OmfRecordTypes {
public final static int RHEADR = 0x6E; // Obsolete
public final static int REGINT = 0x70; // Obsolete
public final static int REDATA = 0x72; // Obsolete
public final static int RIDATA = 0x74; // Obsolete
public final static int OVLDEF = 0x76; // Obsolete
public final static int ENDREC = 0x78; // Obsolete
public final static int BLKDEF = 0x7A; // Obsolete
public final static int BLKEND = 0x7C; // Obsolete
public final static int DEBSYM = 0x7E; // Obsolete
public final static int THEADR = 0x80;
public final static int LHEADR = 0x82;
public final static int PEDATA = 0x84; // Obsolete
public final static int PIDATA = 0x86; // Obsolete
public final static int COMENT = 0x88;
public final static int MODEND = 0x8A;
public final static int EXTDEF = 0x8C;
public final static int TYPDEF = 0x8E; // Obsolete
public final static int PUBDEF = 0x90;
public final static int LOCSYM = 0x92; // Obsolete
public final static int LINNUM = 0x94;
public final static int LNAMES = 0x96;
public final static int SEGDEF = 0x98;
public final static int GRPDEF = 0x9A;
public final static int FIXUPP = 0x9C;
public final static int LEDATA = 0xA0;
public final static int LIDATA = 0xA2;
public final static int LIBHED = 0xA4; // Obsolete
public final static int LIBNAM = 0xA6; // Obsolete
public final static int LIBLOC = 0xA8; // Obsolete
public final static int LIBDIC = 0xAA; // Obsolete
public final static int COMDEF = 0xB0;
public final static int BAKPAT = 0xB2;
public final static int LEXTDEF = 0xB4;
public final static int LPUBDEF = 0xB6;
public final static int LCOMDEF = 0xB8;
public final static int CEXTDEF = 0xBC;
public final static int COMDAT = 0xC2;
public final static int LINSYM = 0xC4;
public final static int ALIAS = 0xC6;
public final static int NBKPAT = 0xC8;
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;
/**
* 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, OmfRecordTypes.class);
}
}

View File

@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.OmfLoader; import ghidra.app.util.opinion.OmfLoader;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -91,14 +92,14 @@ public class OmfSegmentHeader extends OmfRecord {
offset = reader.readNextByte() & 0xff; offset = reader.readNextByte() & 0xff;
vma = (long) frameNumber + offset; vma = (long) frameNumber + offset;
} }
segmentLength = OmfRecord.readInt2Or4(reader, hasBigFields); segmentLength = OmfUtils.readInt2Or4(reader, hasBigFields);
segmentNameIndex = OmfRecord.readIndex(reader); segmentNameIndex = OmfUtils.readIndex(reader);
classNameIndex = OmfRecord.readIndex(reader); classNameIndex = OmfUtils.readIndex(reader);
overlayNameIndex = OmfRecord.readIndex(reader); overlayNameIndex = OmfUtils.readIndex(reader);
readCheckSumByte(reader); readCheckSumByte(reader);
int B = (segAttr >> 1) & 1; int B = (segAttr >> 1) & 1;
if (B == 1) { // Ignore the segmentLength field if (B == 1) { // Ignore the segmentLength field
if (getRecordType() == OmfRecord.SEGDEF) { if (getRecordType() == OmfRecordTypes.SEGDEF) {
segmentLength = new Omf2or4(segmentLength.length(), 0x10000L); // Exactly 64K segment segmentLength = new Omf2or4(segmentLength.length(), 0x10000L); // Exactly 64K segment
} }
else { else {
@ -458,7 +459,7 @@ public class OmfSegmentHeader extends OmfRecord {
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.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(BYTE, "segment_attr", null); struct.add(BYTE, "segment_attr", null);
@ -473,7 +474,7 @@ public class OmfSegmentHeader extends OmfRecord {
struct.add(overlayNameIndex.toDataType(), "overlay_name_index", null); struct.add(overlayNameIndex.toDataType(), "overlay_name_index", null);
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }
} }

View File

@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.util.Set; import java.util.Set;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@SuppressWarnings("unused")
public class OmfSymbol { public class OmfSymbol {
private String symbolName; private String symbolName;
private int typeIndex; private int typeIndex;

View File

@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.app.util.bin.format.omf; package ghidra.app.util.bin.format.omf.omf;
import java.io.IOException; 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.BinaryReader;
import ghidra.app.util.bin.format.omf.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -38,17 +39,17 @@ public class OmfSymbolRecord extends OmfRecord {
readRecordHeader(reader); readRecordHeader(reader);
long max = reader.getPointerIndex() + getRecordLength() - 1; long max = reader.getPointerIndex() + getRecordLength() - 1;
boolean hasBigFields = hasBigFields(); boolean hasBigFields = hasBigFields();
baseGroupIndex = OmfRecord.readIndex(reader); baseGroupIndex = OmfUtils.readIndex(reader);
baseSegmentIndex = OmfRecord.readIndex(reader); baseSegmentIndex = OmfUtils.readIndex(reader);
if (baseSegmentIndex.value() == 0) { if (baseSegmentIndex.value() == 0) {
baseFrame = reader.readNextUnsignedShort(); baseFrame = reader.readNextUnsignedShort();
} }
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>(); ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
while (reader.getPointerIndex() < max) { while (reader.getPointerIndex() < max) {
OmfString name = OmfRecord.readString(reader); OmfString name = OmfUtils.readString(reader);
Omf2or4 offset = OmfRecord.readInt2Or4(reader, hasBigFields); Omf2or4 offset = OmfUtils.readInt2Or4(reader, hasBigFields);
OmfIndex type = OmfRecord.readIndex(reader); OmfIndex type = OmfUtils.readIndex(reader);
OmfSymbol subrec = new OmfSymbol(name.str(), type.value(), offset.value(), 0, 0); OmfSymbol subrec = new OmfSymbol(name.str(), type.value(), offset.value(), 0, 0);
symbollist.add(subrec); symbollist.add(subrec);
refs.add(new Reference(name, offset, type)); refs.add(new Reference(name, offset, type));
@ -88,7 +89,7 @@ public class OmfSymbolRecord extends OmfRecord {
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0); StructureDataType struct = new StructureDataType(OmfRecordTypes.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(baseGroupIndex.toDataType(), "base_group_index", null); struct.add(baseGroupIndex.toDataType(), "base_group_index", null);
@ -103,7 +104,7 @@ public class OmfSymbolRecord extends OmfRecord {
} }
struct.add(BYTE, "checksum", null); struct.add(BYTE, "checksum", null);
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH)); struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
return struct; return struct;
} }

View File

@ -24,7 +24,8 @@ import ghidra.app.util.Option;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.omf.*; import ghidra.app.util.bin.format.omf.*;
import ghidra.app.util.bin.format.omf.OmfFixupRecord.Subrecord; import ghidra.app.util.bin.format.omf.omf.*;
import ghidra.app.util.bin.format.omf.omf.OmfFixupRecord.Subrecord;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.program.database.function.OverlappingFunctionException; import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;

View File

@ -21,8 +21,8 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.util.bin.*; import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.omf.OmfFileHeader; import ghidra.app.util.bin.format.omf.omf.OmfFileHeader;
import ghidra.app.util.bin.format.omf.OmfLibraryRecord; import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord;
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;

View File

@ -19,8 +19,8 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.omf.OmfFileHeader; import ghidra.app.util.bin.format.omf.omf.OmfFileHeader;
import ghidra.app.util.bin.format.omf.OmfLibraryRecord; import ghidra.app.util.bin.format.omf.omf.OmfLibraryRecord;
import ghidra.app.util.opinion.OmfLoader; import ghidra.app.util.opinion.OmfLoader;
import ghidra.formats.gfilesystem.FSRLRoot; import ghidra.formats.gfilesystem.FSRLRoot;
import ghidra.formats.gfilesystem.FileSystemService; import ghidra.formats.gfilesystem.FileSystemService;

View File

@ -2858,6 +2858,45 @@ control: "control" is epsilon {}
Rd0811 = zext((altStackMode << 1) | notPrivileged); Rd0811 = zext((altStackMode << 1) | notPrivileged);
} }
@endif
@if defined(CORTEX)
define pcodeop setMainStackPointerLimit;
msplim: "msplim" is epsilon {}
:msr^ItCond msplim,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=10 & msplim
{
build ItCond;
setMainStackPointerLimit(Rn0003);
}
define pcodeop setProcStackPointerLimit;
psplim: "psplim" is epsilon {}
:msr^ItCond psplim,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=11 & psplim
{
build ItCond;
setProcStackPointerLimit(Rn0003);
}
define pcodeop getMainStackPointerLimit;
:mrs^ItCond Rd0811,msplim is TMode=1 & ItCond & op0=0xf3ff; op12=0x8 & Rd0811 & sysm=10 & msplim
{
build ItCond;
Rd0811 = getMainStackPointerLimit();
}
define pcodeop getProcessStackPointerLimit;
:mrs^ItCond Rd0811,psplim is TMode=1 & ItCond & op0=0xf3ff; op12=0x8 & Rd0811 & sysm=11 & psplim
{
build ItCond;
Rd0811 = getProcessStackPointerLimit();
}
@endif @endif
:mrs^ItCond Rd0811,cpsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=0 & cpsr :mrs^ItCond Rd0811,cpsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=0 & cpsr