mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4722: More OMF header markup
This commit is contained in:
parent
27c162ee8f
commit
bc46e577b7
5 changed files with 139 additions and 47 deletions
|
@ -21,12 +21,17 @@ import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.format.omf.*;
|
import ghidra.app.util.bin.format.omf.*;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||||
|
|
||||||
public record ExternalLookup(int nameIndex, int type) {}
|
public record ExternalLookup(int nameIndex, int type) {}
|
||||||
protected List<ExternalLookup> externalLookups = new ArrayList<>();
|
protected List<ExternalLookup> externalLookups = new ArrayList<>();
|
||||||
|
|
||||||
|
private record Reference(OmfIndex nameIndex, OmfIndex typeIndex) {}
|
||||||
|
private List<Reference> refs = new ArrayList<>();
|
||||||
|
|
||||||
public OmfComdatExternalSymbol(BinaryReader reader) throws IOException {
|
public OmfComdatExternalSymbol(BinaryReader reader) throws IOException {
|
||||||
super(reader, false);
|
super(reader, false);
|
||||||
|
|
||||||
|
@ -37,6 +42,7 @@ public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||||
while (dataReader.getPointerIndex() < dataEnd) {
|
while (dataReader.getPointerIndex() < dataEnd) {
|
||||||
OmfIndex nameIndex = OmfUtils.readIndex(dataReader);
|
OmfIndex nameIndex = OmfUtils.readIndex(dataReader);
|
||||||
OmfIndex type = OmfUtils.readIndex(dataReader);
|
OmfIndex type = OmfUtils.readIndex(dataReader);
|
||||||
|
refs.add(new Reference(nameIndex, type));
|
||||||
externalLookups.add(new ExternalLookup(nameIndex.value(), type.value()));
|
externalLookups.add(new ExternalLookup(nameIndex.value(), type.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,4 +53,19 @@ public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||||
symbols.add(new OmfSymbol(name, ext.type, 0, 0, 0));
|
symbols.add(new OmfSymbol(name, ext.type, 0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType struct = new StructureDataType(OmfRecordTypes.getName(recordType), 0);
|
||||||
|
struct.add(BYTE, "type", null);
|
||||||
|
struct.add(WORD, "length", null);
|
||||||
|
for (Reference ref : refs) {
|
||||||
|
struct.add(ref.nameIndex.toDataType(), "logical_name_index", null);
|
||||||
|
struct.add(ref.typeIndex.toDataType(), "type_index", null);
|
||||||
|
}
|
||||||
|
struct.add(BYTE, "checksum", null);
|
||||||
|
|
||||||
|
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||||
|
return struct;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,21 @@
|
||||||
package ghidra.app.util.bin.format.omf.omf;
|
package ghidra.app.util.bin.format.omf.omf;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.app.util.bin.format.omf.*;
|
import ghidra.app.util.bin.format.omf.*;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
public class OmfComdefRecord extends OmfExternalSymbol {
|
public class OmfComdefRecord extends OmfExternalSymbol {
|
||||||
|
|
||||||
|
private record Reference(OmfString name, OmfIndex typeIndex, OmfCommunalLength communalLength1,
|
||||||
|
OmfCommunalLength communalLength2) {}
|
||||||
|
private List<Reference> refs = new ArrayList<>();
|
||||||
|
|
||||||
public OmfComdefRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
public OmfComdefRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
||||||
super(reader, isStatic);
|
super(reader, isStatic);
|
||||||
}
|
}
|
||||||
|
@ -34,38 +43,96 @@ public class OmfComdefRecord extends OmfExternalSymbol {
|
||||||
byte dataType = dataReader.readNextByte();
|
byte dataType = dataReader.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
|
||||||
int numElements = readCommunalLength(dataReader);
|
OmfCommunalLength numElements = new OmfCommunalLength(dataReader);
|
||||||
int elSize = readCommunalLength(dataReader);
|
OmfCommunalLength elSize = new OmfCommunalLength(dataReader);
|
||||||
byteLength = numElements * elSize;
|
byteLength = numElements.value * elSize.value;
|
||||||
|
refs.add(new Reference(name, typeIndex, numElements, elSize));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Values 1 thru 5f plus 61, read the byte length
|
// Values 1 thru 5f plus 61, read the byte length
|
||||||
byteLength = readCommunalLength(dataReader);
|
OmfCommunalLength communalLength = new OmfCommunalLength(dataReader);
|
||||||
|
byteLength = communalLength.value;
|
||||||
|
refs.add(new Reference(name, typeIndex, communalLength, null));
|
||||||
}
|
}
|
||||||
symbols.add(new OmfSymbol(name.str(), typeIndex.value(), 0, dataType, byteLength));
|
symbols.add(new OmfSymbol(name.str(), typeIndex.value(), 0, dataType, byteLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int readCommunalLength(BinaryReader reader) throws OmfException, IOException {
|
@Override
|
||||||
int val = reader.readNextByte() & 0xff;
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
if (val <= 128) {
|
StructureDataType struct = new StructureDataType(OmfRecordTypes.getName(recordType), 0);
|
||||||
return val;
|
struct.add(BYTE, "type", null);
|
||||||
|
struct.add(WORD, "length", null);
|
||||||
|
for (Reference ref : refs) {
|
||||||
|
struct.add(ref.name.toDataType(), "name", null);
|
||||||
|
struct.add(ref.typeIndex.toDataType(), "type_index", null);
|
||||||
|
struct.add(BYTE, "data_type", null);
|
||||||
|
struct.add(ref.communalLength1.toDataType(), "communal_length", null);
|
||||||
|
if (ref.communalLength2 != null) {
|
||||||
|
struct.add(ref.communalLength2.toDataType(), "communal_length", null);
|
||||||
}
|
}
|
||||||
if (val == 0x81) {
|
|
||||||
val = reader.readNextShort() & 0xffff;
|
|
||||||
}
|
}
|
||||||
else if (val == 0x84) {
|
struct.add(BYTE, "checksum", null);
|
||||||
val = reader.readNextShort() & 0xffff;
|
|
||||||
int hithird = reader.readNextByte() & 0xff;
|
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||||
val += (hithird << 16);
|
return struct;
|
||||||
}
|
}
|
||||||
else if (val == 0x88) {
|
|
||||||
val = reader.readNextInt();
|
/**
|
||||||
|
* A OMF COMDEF "communal length"
|
||||||
|
*/
|
||||||
|
private static class OmfCommunalLength implements StructConverter {
|
||||||
|
|
||||||
|
private int numBytes;
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public OmfCommunalLength(BinaryReader reader) throws OmfException, IOException {
|
||||||
|
long origIndex = reader.getPointerIndex();
|
||||||
|
int b = reader.readNextUnsignedByte();
|
||||||
|
if (b <= 128) {
|
||||||
|
value = b;
|
||||||
|
}
|
||||||
|
else if (b == 0x81) {
|
||||||
|
value = reader.readNextUnsignedShort();
|
||||||
|
}
|
||||||
|
else if (b == 0x84) {
|
||||||
|
value = reader.readNextUnsignedShort();
|
||||||
|
int hithird = reader.readNextUnsignedByte();
|
||||||
|
value += (hithird << 16);
|
||||||
|
}
|
||||||
|
else if (b == 0x88) {
|
||||||
|
value = reader.readNextInt();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new OmfException("Illegal communal length encoding");
|
throw new OmfException("Illegal communal length encoding");
|
||||||
}
|
}
|
||||||
return val;
|
numBytes = (int)(reader.getPointerIndex() - origIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType struct =
|
||||||
|
new StructureDataType(OmfCommunalLength.class.getSimpleName(), 0);
|
||||||
|
switch (numBytes) {
|
||||||
|
case 1:
|
||||||
|
struct.add(BYTE, "value", null);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
struct.add(BYTE, "type", null);
|
||||||
|
struct.add(WORD, "value", null);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
struct.add(BYTE, "type", null);
|
||||||
|
struct.add(Integer3DataType.dataType, "value", null);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
struct.add(BYTE, "type", null);
|
||||||
|
struct.add(DWORD, "value", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
struct.setCategoryPath(new CategoryPath(OmfUtils.CATEGORY_PATH));
|
||||||
|
return struct;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,7 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||||
private boolean isStatic;
|
private boolean isStatic;
|
||||||
protected List<OmfSymbol> symbols = new ArrayList<>();
|
protected List<OmfSymbol> symbols = new ArrayList<>();
|
||||||
|
|
||||||
private record Reference(OmfString name, OmfIndex type) {}
|
private record Reference(OmfString name, OmfIndex typeIndex) {}
|
||||||
|
|
||||||
private List<Reference> refs = new ArrayList<>();
|
private List<Reference> refs = new ArrayList<>();
|
||||||
|
|
||||||
public OmfExternalSymbol(BinaryReader reader, boolean isStatic) throws IOException {
|
public OmfExternalSymbol(BinaryReader reader, boolean isStatic) throws IOException {
|
||||||
|
@ -42,9 +41,9 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||||
public void parseData() throws IOException, OmfException {
|
public void parseData() throws IOException, OmfException {
|
||||||
while (dataReader.getPointerIndex() < dataEnd) {
|
while (dataReader.getPointerIndex() < dataEnd) {
|
||||||
OmfString name = OmfUtils.readString(dataReader);
|
OmfString name = OmfUtils.readString(dataReader);
|
||||||
OmfIndex type = OmfUtils.readIndex(dataReader);
|
OmfIndex typeIndex = OmfUtils.readIndex(dataReader);
|
||||||
refs.add(new Reference(name, type));
|
refs.add(new Reference(name, typeIndex));
|
||||||
symbols.add(new OmfSymbol(name.str(), type.value(), 0, 0, 0));
|
symbols.add(new OmfSymbol(name.str(), typeIndex.value(), 0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +61,8 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||||
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) {
|
||||||
struct.add(ref.name.toDataType(), "name", null);
|
struct.add(ref.name.toDataType(), "external_name", null);
|
||||||
struct.add(ref.type.toDataType(), "type", null);
|
struct.add(ref.typeIndex.toDataType(), "type_index", null);
|
||||||
}
|
}
|
||||||
struct.add(BYTE, "checksum", null);
|
struct.add(BYTE, "checksum", null);
|
||||||
|
|
||||||
|
|
|
@ -324,19 +324,22 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
* @throws IOException for problems reading data
|
* @throws IOException for problems reading data
|
||||||
* @throws OmfException for malformed records
|
* @throws OmfException for malformed records
|
||||||
*/
|
*/
|
||||||
public static OmfFileHeader parse(AbstractOmfRecordFactory factory, TaskMonitor monitor, MessageLog log)
|
public static OmfFileHeader parse(AbstractOmfRecordFactory factory, TaskMonitor monitor,
|
||||||
throws IOException, OmfException {
|
MessageLog log) throws IOException, OmfException {
|
||||||
OmfRecord record = factory.readNextRecord();
|
OmfRecord record = factory.readNextRecord();
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
if (!record.validCheckSum()) {
|
||||||
|
logRecord("Invalid checksum", record, log);
|
||||||
|
}
|
||||||
header.records.add(header);
|
header.records.add(header);
|
||||||
OmfData lastDataBlock = null;
|
OmfData lastDataBlock = null;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
record = factory.readNextRecord();
|
record = factory.readNextRecord();
|
||||||
if (!record.validCheckSum()) {
|
if (!record.validCheckSum()) {
|
||||||
throw new OmfException("Invalid checksum!");
|
logRecord("Invalid checksum", record, log);
|
||||||
}
|
}
|
||||||
header.records.add(record);
|
header.records.add(record);
|
||||||
|
|
||||||
|
@ -358,7 +361,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
else if (record instanceof OmfComdefRecord comdef) {
|
else if (record instanceof OmfComdefRecord comdef) {
|
||||||
header.evaluateComdef(comdef);
|
header.evaluateComdef(comdef);
|
||||||
header.externsymbols.add((OmfExternalSymbol) record);
|
header.externsymbols.add(comdef);
|
||||||
}
|
}
|
||||||
else if (record instanceof OmfComdatExternalSymbol comdat) {
|
else if (record instanceof OmfComdatExternalSymbol comdat) {
|
||||||
comdat.loadNames(header.nameList);
|
comdat.loadNames(header.nameList);
|
||||||
|
@ -494,7 +497,8 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logRecord(String description, OmfRecord record, MessageLog log) {
|
private static void logRecord(String description, OmfRecord record, MessageLog log) {
|
||||||
log.appendMsg(description + " (" + record + ")");
|
log.appendMsg("%s (0x%x - %s @ 0x%x)".formatted(description, record.getRecordType(),
|
||||||
|
OmfRecordTypes.getName(record.getRecordType()), record.getRecordOffset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||||
case String s when s.startsWith("CodeGear") -> "codegearcpp";
|
case String s when s.startsWith("CodeGear") -> "codegearcpp";
|
||||||
case String s when s.equals("MS C") -> "windows";
|
case String s when s.equals("MS C") -> "windows";
|
||||||
case String s when s.startsWith("Watcom") -> "watcom";
|
case String s when s.startsWith("Watcom") -> "watcom";
|
||||||
|
case null -> null;
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,9 +121,9 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||||
header.sortSegmentDataBlocks();
|
header.sortSegmentDataBlocks();
|
||||||
OmfFileHeader.doLinking(IMAGE_BASE, header.getSegments(), header.getGroups());
|
OmfFileHeader.doLinking(IMAGE_BASE, header.getSegments(), header.getGroups());
|
||||||
}
|
}
|
||||||
catch (OmfException ex) {
|
catch (OmfException e) {
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
throw new IOException("OMF File header was corrupted");
|
throw new IOException("OMF File header was corrupted. " + e.getMessage());
|
||||||
}
|
}
|
||||||
log.appendMsg("File was corrupted - leaving partial program " + provider.getName());
|
log.appendMsg("File was corrupted - leaving partial program " + provider.getName());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue