mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 12:11:55 +00:00
GP-4722: Marking up OMF records
This commit is contained in:
parent
4b30e484b0
commit
36a707471e
@ -0,0 +1,46 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class Omf2or4 implements StructConverter {
|
||||
|
||||
private int length;
|
||||
private long value;
|
||||
|
||||
public Omf2or4(int length, long value) {
|
||||
this.length = length;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public long value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
return length == 2 ? WORD : DWORD;
|
||||
}
|
||||
}
|
@ -32,9 +32,9 @@ public class OmfComdatExternalSymbol extends OmfExternalSymbol {
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
int nameIndex = OmfRecord.readIndex(reader);
|
||||
int type = OmfRecord.readIndex(reader);
|
||||
externalLookups.add(new ExternalLookup(nameIndex, type));
|
||||
OmfIndex nameIndex = OmfRecord.readIndex(reader);
|
||||
OmfIndex type = OmfRecord.readIndex(reader);
|
||||
externalLookups.add(new ExternalLookup(nameIndex.value(), type.value()));
|
||||
}
|
||||
|
||||
readCheckSumByte(reader);
|
||||
|
@ -27,8 +27,8 @@ public class OmfComdefRecord extends OmfExternalSymbol {
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
String name = OmfRecord.readString(reader);
|
||||
int typeIndex = OmfRecord.readIndex(reader);
|
||||
OmfString name = OmfRecord.readString(reader);
|
||||
OmfIndex typeIndex = OmfRecord.readIndex(reader);
|
||||
byte dataType = reader.readNextByte();
|
||||
int byteLength = 0;
|
||||
if (dataType == 0x61) { // FAR data, reads numElements and elSize
|
||||
@ -40,7 +40,7 @@ public class OmfComdefRecord extends OmfExternalSymbol {
|
||||
// Values 1 thru 5f plus 61, read the byte length
|
||||
byteLength = readCommunalLength(reader);
|
||||
}
|
||||
symbols.add(new OmfSymbol(name, typeIndex, 0, dataType, byteLength));
|
||||
symbols.add(new OmfSymbol(name.str(), typeIndex.value(), 0, dataType, byteLength));
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfCommentRecord extends OmfRecord {
|
||||
// Language translator comment
|
||||
@ -34,7 +36,7 @@ public class OmfCommentRecord extends OmfRecord {
|
||||
|
||||
private byte commentType;
|
||||
private byte commentClass;
|
||||
private String value;
|
||||
private OmfString value;
|
||||
|
||||
public OmfCommentRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
@ -46,7 +48,7 @@ public class OmfCommentRecord extends OmfRecord {
|
||||
case COMMENT_CLASS_DEFAULT_LIBRARY:
|
||||
byte[] bytes = reader.readNextByteArray(getRecordLength() -
|
||||
3 /* 3 = sizeof(commentType+commentClass+trailing_crcbyte*/);
|
||||
value = new String(bytes, StandardCharsets.US_ASCII); // assuming ASCII
|
||||
value = new OmfString(bytes.length, new String(bytes, StandardCharsets.US_ASCII)); // assuming ASCII
|
||||
break;
|
||||
case COMMENT_CLASS_LIBMOD:
|
||||
value = readString(reader);
|
||||
@ -67,6 +69,24 @@ public class OmfCommentRecord extends OmfRecord {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
return value.str();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
int strlen = getRecordLength() - 3;
|
||||
|
||||
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", "");
|
||||
struct.add(BYTE, "comment_type", null);
|
||||
struct.add(BYTE, "comment_class", null);
|
||||
if (strlen > 0) {
|
||||
struct.add(new StringDataType(), strlen, "str", null);
|
||||
}
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
|
@ -23,21 +23,21 @@ import ghidra.app.util.bin.BinaryReader;
|
||||
* Object representing data loaded directly into the final image.
|
||||
*/
|
||||
public abstract class OmfData extends OmfRecord implements Comparable<OmfData> {
|
||||
protected int segmentIndex;
|
||||
protected long dataOffset;
|
||||
protected OmfIndex segmentIndex;
|
||||
protected Omf2or4 dataOffset;
|
||||
|
||||
/**
|
||||
* @return get the segments index for this datablock
|
||||
*/
|
||||
public int getSegmentIndex() {
|
||||
return segmentIndex;
|
||||
return segmentIndex.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the starting offset, within the loaded image, of this data
|
||||
*/
|
||||
public long getDataOffset() {
|
||||
return dataOffset;
|
||||
return dataOffset.value();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,7 +47,7 @@ public abstract class OmfData extends OmfRecord implements Comparable<OmfData> {
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(OmfData o) {
|
||||
return Long.compare(dataOffset, o.dataOffset);
|
||||
return Long.compare(dataOffset.value(), o.dataOffset.value());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ public class OmfEnumeratedData extends OmfData {
|
||||
readRecordHeader(reader);
|
||||
long start = reader.getPointerIndex();
|
||||
segmentIndex = OmfRecord.readIndex(reader);
|
||||
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields()) & 0xffffffffL;
|
||||
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields());
|
||||
streamOffset = reader.getPointerIndex();
|
||||
streamLength = getRecordLength() - 1 - (int) (streamOffset - start);
|
||||
reader.setPointerIndex(streamOffset + streamLength); // Skip over the data when reading header
|
||||
|
@ -20,12 +20,18 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfExternalSymbol extends OmfRecord {
|
||||
|
||||
private boolean isStatic;
|
||||
protected List<OmfSymbol> symbols = new ArrayList<>();
|
||||
|
||||
private record Reference(OmfString name, OmfIndex type) {}
|
||||
|
||||
private List<Reference> refs = new ArrayList<>();
|
||||
|
||||
protected OmfExternalSymbol(boolean isStatic) {
|
||||
this.isStatic = isStatic;
|
||||
}
|
||||
@ -36,9 +42,10 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
while (reader.getPointerIndex() < max) {
|
||||
String name = OmfRecord.readString(reader);
|
||||
int type = OmfRecord.readIndex(reader);
|
||||
symbols.add(new OmfSymbol(name, type, 0, 0, 0));
|
||||
OmfString name = OmfRecord.readString(reader);
|
||||
OmfIndex type = OmfRecord.readIndex(reader);
|
||||
refs.add(new Reference(name, type));
|
||||
symbols.add(new OmfSymbol(name.str(), type.value(), 0, 0, 0));
|
||||
}
|
||||
|
||||
readCheckSumByte(reader);
|
||||
@ -51,4 +58,19 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", null);
|
||||
for (Reference ref : refs) {
|
||||
struct.add(ref.name.toDataType(), "name", null);
|
||||
struct.add(ref.type.toDataType(), "type", null);
|
||||
}
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
|
@ -17,41 +17,52 @@ package ghidra.app.util.bin.format.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class OmfFileHeader extends OmfRecord {
|
||||
|
||||
private String objectName; // Name of the object module
|
||||
private String libModuleName = null; // Name of the module (within a library)
|
||||
private String translator = null; // Usually the compiler/linker used to produce this object
|
||||
private OmfString objectName; // Name of the object module
|
||||
private String libModuleName = null; // Name of the module (within a library)
|
||||
private String translator = null; // Usually the compiler/linker used to produce this object
|
||||
private boolean isLittleEndian;
|
||||
private ArrayList<String> nameList = new ArrayList<String>(); // Indexable List of segment, group, ... names
|
||||
private ArrayList<OmfSegmentHeader> segments = new ArrayList<OmfSegmentHeader>();
|
||||
private ArrayList<OmfGroupRecord> groups = new ArrayList<OmfGroupRecord>();
|
||||
private ArrayList<OmfExternalSymbol> externsymbols = new ArrayList<OmfExternalSymbol>();
|
||||
private ArrayList<OmfSymbolRecord> symbols = new ArrayList<OmfSymbolRecord>();
|
||||
private ArrayList<OmfFixupRecord> fixup = new ArrayList<OmfFixupRecord>();
|
||||
private ArrayList<OmfSegmentHeader> extraSeg = null; // Holds implied segments that don't have official header record
|
||||
private List<OmfRecord> records = new ArrayList<>();
|
||||
private List<String> nameList = new ArrayList<>(); // Indexable List of segment, group, ... names
|
||||
private List<OmfSegmentHeader> segments = new ArrayList<>();
|
||||
private List<OmfGroupRecord> groups = new ArrayList<>();
|
||||
private List<OmfExternalSymbol> externsymbols = new ArrayList<>();
|
||||
private List<OmfSymbolRecord> symbols = new ArrayList<>();
|
||||
private List<OmfFixupRecord> fixup = new ArrayList<>();
|
||||
private List<OmfSegmentHeader> extraSeg = null; // Holds implied segments that don't have official header record
|
||||
// private OmfModuleEnd endModule = null;
|
||||
private boolean format16bit;
|
||||
|
||||
public OmfFileHeader(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
objectName = readString(reader); // This is usually the source code filename
|
||||
objectName = readString(reader); // This is usually the source code filename
|
||||
readCheckSumByte(reader);
|
||||
isLittleEndian = reader.isLittleEndian();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the list of records}
|
||||
*/
|
||||
public List<OmfRecord> getRecords() {
|
||||
return records;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is usually the original source filename
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return objectName;
|
||||
return objectName.str();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,42 +99,42 @@ public class OmfFileHeader extends OmfRecord {
|
||||
/**
|
||||
* @return the list of segments in this file
|
||||
*/
|
||||
public ArrayList<OmfSegmentHeader> getSegments() {
|
||||
public List<OmfSegmentHeader> getSegments() {
|
||||
return segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of segments which are Borland extensions
|
||||
*/
|
||||
public ArrayList<OmfSegmentHeader> getExtraSegments() {
|
||||
public List<OmfSegmentHeader> getExtraSegments() {
|
||||
return extraSeg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of group records for this file
|
||||
*/
|
||||
public ArrayList<OmfGroupRecord> getGroups() {
|
||||
public List<OmfGroupRecord> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of symbols that are external to this file
|
||||
*/
|
||||
public ArrayList<OmfExternalSymbol> getExternalSymbols() {
|
||||
public List<OmfExternalSymbol> getExternalSymbols() {
|
||||
return externsymbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of symbols exported by this file
|
||||
*/
|
||||
public ArrayList<OmfSymbolRecord> getPublicSymbols() {
|
||||
public List<OmfSymbolRecord> getPublicSymbols() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of relocation records for this file
|
||||
*/
|
||||
public ArrayList<OmfFixupRecord> getFixups() {
|
||||
public List<OmfFixupRecord> getFixups() {
|
||||
return fixup;
|
||||
}
|
||||
|
||||
@ -313,14 +324,15 @@ public class OmfFileHeader extends OmfRecord {
|
||||
public static OmfFileHeader parse(BinaryReader reader, TaskMonitor monitor, MessageLog log)
|
||||
throws IOException, OmfException {
|
||||
OmfRecord record = OmfRecord.readRecord(reader);
|
||||
if (!(record instanceof OmfFileHeader)) {
|
||||
if (!(record instanceof OmfFileHeader header)) {
|
||||
throw new OmfException("Object file does not start with proper header");
|
||||
}
|
||||
OmfFileHeader header = (OmfFileHeader) record;
|
||||
header.records.add(header);
|
||||
OmfData lastDataBlock = null;
|
||||
|
||||
while (true) {
|
||||
record = OmfRecord.readRecord(reader);
|
||||
header.records.add(record);
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
@ -403,8 +415,8 @@ public class OmfFileHeader extends OmfRecord {
|
||||
* @param groups is the list of specific segments that are grouped together in memory
|
||||
* @throws OmfException for malformed index/alignment/combining fields
|
||||
*/
|
||||
public static void doLinking(long startAddress, ArrayList<OmfSegmentHeader> segments,
|
||||
ArrayList<OmfGroupRecord> groups) throws OmfException {
|
||||
public static void doLinking(long startAddress, List<OmfSegmentHeader> segments,
|
||||
List<OmfGroupRecord> groups) throws OmfException {
|
||||
// Link anything in groups first
|
||||
for (int i = 0; i < groups.size(); ++i) {
|
||||
OmfGroupRecord group = groups.get(i);
|
||||
@ -489,4 +501,16 @@ public class OmfFileHeader extends OmfRecord {
|
||||
private static void logRecord(String description, OmfRecord record, MessageLog log) {
|
||||
log.appendMsg(description + " (" + record + ")");
|
||||
}
|
||||
|
||||
@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(objectName.toDataType(), "name", null);
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
|
@ -67,10 +67,10 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
private byte first;
|
||||
private byte hiFixup;
|
||||
private byte fixData;
|
||||
private int index;
|
||||
private int frameDatum;
|
||||
private int targetDatum;
|
||||
private int targetDisplacement;
|
||||
private OmfIndex index;
|
||||
private OmfIndex frameDatum;
|
||||
private OmfIndex targetDatum;
|
||||
private Omf2or4 targetDisplacement;
|
||||
|
||||
/**
|
||||
* Read the next subrecord from the input reader
|
||||
@ -85,7 +85,7 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
int method;
|
||||
final var rec = new Subrecord();
|
||||
rec.first = reader.readNextByte();
|
||||
rec.index = -1;
|
||||
rec.index = new OmfIndex(1, -1);
|
||||
if (rec.isThreadSubrecord()) {
|
||||
method = rec.getThreadMethod();
|
||||
if (method < 4) {
|
||||
@ -93,8 +93,8 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
rec.targetDisplacement = 0;
|
||||
rec.targetDatum = 0;
|
||||
rec.targetDisplacement = new Omf2or4(2, 0);
|
||||
rec.targetDatum = new OmfIndex(1, 0);
|
||||
rec.hiFixup = reader.readNextByte();
|
||||
rec.fixData = reader.readNextByte();
|
||||
method = rec.getFrameMethod();
|
||||
@ -135,7 +135,7 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
* @return Get the index for explicit thread or frame
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
return index.value();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,11 +170,11 @@ public class OmfFixupRecord extends OmfRecord {
|
||||
}
|
||||
|
||||
public int getTargetDatum() {
|
||||
return targetDatum;
|
||||
return targetDatum.value();
|
||||
}
|
||||
|
||||
public int getTargetDisplacement() {
|
||||
return targetDisplacement;
|
||||
return (int) targetDisplacement.value();
|
||||
}
|
||||
|
||||
public int getLocationType() {
|
||||
|
@ -17,6 +17,7 @@ package ghidra.app.util.bin.format.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.address.Address;
|
||||
@ -24,7 +25,7 @@ import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.Language;
|
||||
|
||||
public class OmfGroupRecord extends OmfRecord {
|
||||
private int groupNameIndex;
|
||||
private OmfIndex groupNameIndex;
|
||||
private String groupName;
|
||||
private long vma = -1; // Assigned (by linker) starting address of the whole group
|
||||
private GroupSubrecord[] group;
|
||||
@ -72,7 +73,7 @@ public class OmfGroupRecord extends OmfRecord {
|
||||
}
|
||||
|
||||
public int getSegmentIndex(int i) {
|
||||
return group[i].segmentIndex;
|
||||
return group[i].segmentIndex.value();
|
||||
}
|
||||
|
||||
public Address getAddress(Language language) {
|
||||
@ -80,19 +81,19 @@ public class OmfGroupRecord extends OmfRecord {
|
||||
return addrSpace.getAddress(vma);
|
||||
}
|
||||
|
||||
public void resolveNames(ArrayList<String> nameList) throws OmfException {
|
||||
if (groupNameIndex <= 0) {
|
||||
public void resolveNames(List<String> nameList) throws OmfException {
|
||||
if (groupNameIndex.value() <= 0) {
|
||||
throw new OmfException("Cannot have unused group name");
|
||||
}
|
||||
if (groupNameIndex > nameList.size()) {
|
||||
if (groupNameIndex.value() > nameList.size()) {
|
||||
throw new OmfException("Group name index out of bounds");
|
||||
}
|
||||
groupName = nameList.get(groupNameIndex - 1);
|
||||
groupName = nameList.get(groupNameIndex.value() - 1);
|
||||
}
|
||||
|
||||
public static class GroupSubrecord {
|
||||
private byte componentType;
|
||||
private int segmentIndex;
|
||||
private OmfIndex segmentIndex;
|
||||
|
||||
public static GroupSubrecord read(BinaryReader reader) throws IOException {
|
||||
GroupSubrecord subrec = new GroupSubrecord();
|
||||
|
@ -0,0 +1,46 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfIndex implements StructConverter {
|
||||
|
||||
private int length;
|
||||
private int value;
|
||||
|
||||
public OmfIndex(int length, int value) {
|
||||
this.length = length;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
return length == 2 ? WORD : BYTE;
|
||||
}
|
||||
}
|
@ -78,7 +78,7 @@ public class OmfIteratedData extends OmfData {
|
||||
* Contain the definition of one part of a datablock with possible recursion
|
||||
*/
|
||||
public static class DataBlock {
|
||||
private int repeatCount;
|
||||
private Omf2or4 repeatCount;
|
||||
private int blockCount;
|
||||
private byte[] simpleBlock = null;
|
||||
private DataBlock[] nestedBlock = null;
|
||||
@ -86,7 +86,7 @@ public class OmfIteratedData extends OmfData {
|
||||
public static DataBlock read(BinaryReader reader, boolean hasBigFields) throws IOException {
|
||||
DataBlock subblock = new DataBlock();
|
||||
subblock.repeatCount = OmfRecord.readInt2Or4(reader, hasBigFields);
|
||||
subblock.blockCount = reader.readNextShort() & 0xffff;
|
||||
subblock.blockCount = reader.readNextUnsignedShort();
|
||||
if (subblock.blockCount == 0) {
|
||||
int size = reader.readNextByte() & 0xff;
|
||||
subblock.simpleBlock = new byte[size];
|
||||
@ -110,7 +110,7 @@ public class OmfIteratedData extends OmfData {
|
||||
* @return The position after the block
|
||||
*/
|
||||
public int fillBuffer(byte[] buffer, int pos) {
|
||||
for (int i = 0; i < repeatCount; ++i) {
|
||||
for (int i = 0; i < (int) repeatCount.value(); ++i) {
|
||||
if (simpleBlock != null) {
|
||||
for (byte element : simpleBlock) {
|
||||
buffer[pos] = element;
|
||||
@ -139,7 +139,7 @@ public class OmfIteratedData extends OmfData {
|
||||
length += block.getLength();
|
||||
}
|
||||
}
|
||||
return length * repeatCount;
|
||||
return length * (int) repeatCount.value();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,24 +17,39 @@ package ghidra.app.util.bin.format.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfNamesRecord extends OmfRecord {
|
||||
private ArrayList<String> name;
|
||||
private List<OmfString> names = new ArrayList<>();
|
||||
|
||||
public OmfNamesRecord(BinaryReader reader) throws IOException {
|
||||
readRecordHeader(reader);
|
||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||
name = new ArrayList<String>();
|
||||
while (reader.getPointerIndex() < max) {
|
||||
String nm = OmfRecord.readString(reader);
|
||||
name.add(nm);
|
||||
names.add(OmfRecord.readString(reader));
|
||||
}
|
||||
readCheckSumByte(reader);
|
||||
}
|
||||
|
||||
public void appendNames(ArrayList<String> namelist) {
|
||||
namelist.addAll(name);
|
||||
public void appendNames(List<String> namelist) {
|
||||
namelist.addAll(names.stream().map(name -> name.str()).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(getRecordName(getRecordType()), 0);
|
||||
struct.add(BYTE, "type", null);
|
||||
struct.add(WORD, "length", null);
|
||||
for (OmfString name : names) {
|
||||
struct.add(name.toDataType(), -1, "name", null);
|
||||
}
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,11 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public abstract class OmfRecord {
|
||||
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
|
||||
@ -68,6 +71,8 @@ public abstract class OmfRecord {
|
||||
public final static byte START = (byte) 0xF0;
|
||||
public final static byte END = (byte) 0xF1;
|
||||
|
||||
protected static final String CATEGORY_PATH = "/OMF";
|
||||
|
||||
protected byte recordType;
|
||||
protected int recordLength;
|
||||
protected long recordOffset;
|
||||
@ -120,22 +125,26 @@ public abstract class OmfRecord {
|
||||
return (reader.readNextByte() & 0xff);
|
||||
}
|
||||
|
||||
public static int readInt2Or4(BinaryReader reader, boolean isBig) throws IOException {
|
||||
if (isBig)
|
||||
return reader.readNextInt();
|
||||
return (reader.readNextShort() & 0xffff);
|
||||
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 int readIndex(BinaryReader reader) throws IOException {
|
||||
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 indexWord;
|
||||
return new OmfIndex(length, indexWord);
|
||||
}
|
||||
|
||||
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
|
||||
@ -215,9 +224,9 @@ public abstract class OmfRecord {
|
||||
* @return the read OMF string
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
public static String readString(BinaryReader reader) throws IOException {
|
||||
public static OmfString readString(BinaryReader reader) throws IOException {
|
||||
int count = reader.readNextByte() & 0xff;
|
||||
return reader.readNextAsciiString(count);
|
||||
return new OmfString(count, reader.readNextAsciiString(count));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,4 +258,16 @@ public abstract class OmfRecord {
|
||||
return String.format("name: %s, type: 0x%x, offset: 0x%x, length: 0x%x",
|
||||
getRecordName(recordType & (byte) 0xfe), recordType, recordOffset, 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;
|
||||
}
|
||||
}
|
||||
|
@ -17,24 +17,25 @@ package ghidra.app.util.bin.format.omf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.opinion.OmfLoader;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfSegmentHeader extends OmfRecord {
|
||||
private byte segAttr; // first byte of Segment Attributes
|
||||
private int frameNumber;
|
||||
private int offset;
|
||||
private long segmentLength;
|
||||
private int segmentNameIndex;
|
||||
private int classNameIndex;
|
||||
private int overlayNameIndex;
|
||||
private Omf2or4 segmentLength;
|
||||
private OmfIndex segmentNameIndex;
|
||||
private OmfIndex classNameIndex;
|
||||
private OmfIndex overlayNameIndex;
|
||||
private String segmentName;
|
||||
private String className;
|
||||
private String overlayName;
|
||||
@ -48,10 +49,10 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
OmfSegmentHeader(int num, int datatype) {
|
||||
// generate a special Borland header
|
||||
segAttr = (byte) 0xa9;
|
||||
segmentLength = 0;
|
||||
segmentNameIndex = 0;
|
||||
classNameIndex = 0;
|
||||
overlayNameIndex = 0;
|
||||
segmentLength = new Omf2or4(2,0);
|
||||
segmentNameIndex = new OmfIndex(1, 0);
|
||||
classNameIndex = new OmfIndex(1, 0);
|
||||
overlayNameIndex = new OmfIndex(1, 0);
|
||||
overlayName = "";
|
||||
if (datatype == 1) {
|
||||
segmentName = "EXTRATEXT_";
|
||||
@ -90,7 +91,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
offset = reader.readNextByte() & 0xff;
|
||||
vma = (long) frameNumber + offset;
|
||||
}
|
||||
segmentLength = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
||||
segmentLength = OmfRecord.readInt2Or4(reader, hasBigFields);
|
||||
segmentNameIndex = OmfRecord.readIndex(reader);
|
||||
classNameIndex = OmfRecord.readIndex(reader);
|
||||
overlayNameIndex = OmfRecord.readIndex(reader);
|
||||
@ -98,10 +99,10 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
int B = (segAttr >> 1) & 1;
|
||||
if (B == 1) { // Ignore the segmentLength field
|
||||
if (getRecordType() == OmfRecord.SEGDEF) {
|
||||
segmentLength = 0x10000L; // Exactly 64K segment
|
||||
segmentLength = new Omf2or4(segmentLength.length(), 0x10000L); // Exactly 64K segment
|
||||
}
|
||||
else {
|
||||
segmentLength = 0x100000000L; // Exactly 4G segment
|
||||
segmentLength = new Omf2or4(segmentLength.length(), 0x100000000L); // Exactly 4G segment
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,7 +190,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
* @return the length of the segment in bytes
|
||||
*/
|
||||
public long getSegmentLength() {
|
||||
return segmentLength;
|
||||
return segmentLength.value();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,7 +278,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
throw new OmfException("Unsupported alignment type");
|
||||
}
|
||||
vma = firstValidAddress;
|
||||
firstValidAddress = vma + segmentLength;
|
||||
firstValidAddress = vma + segmentLength.value();
|
||||
return firstValidAddress;
|
||||
}
|
||||
|
||||
@ -288,33 +289,33 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
* @param nameList is the array of names associated with the file
|
||||
* @throws OmfException for improper name indices
|
||||
*/
|
||||
protected void resolveNames(ArrayList<String> nameList) throws OmfException {
|
||||
if (segmentNameIndex == 0) {
|
||||
protected void resolveNames(List<String> nameList) throws OmfException {
|
||||
if (segmentNameIndex.value() == 0) {
|
||||
segmentName = ""; // Name is unused
|
||||
}
|
||||
else {
|
||||
if (segmentNameIndex > nameList.size()) {
|
||||
if (segmentNameIndex.value() > nameList.size()) {
|
||||
throw new OmfException("Segment name index out of bounds");
|
||||
}
|
||||
segmentName = nameList.get(segmentNameIndex - 1);
|
||||
segmentName = nameList.get(segmentNameIndex.value() - 1);
|
||||
}
|
||||
if (classNameIndex == 0) {
|
||||
if (classNameIndex.value() == 0) {
|
||||
className = "";
|
||||
}
|
||||
else {
|
||||
if (classNameIndex > nameList.size()) {
|
||||
if (classNameIndex.value() > nameList.size()) {
|
||||
throw new OmfException("Class name index out of bounds");
|
||||
}
|
||||
className = nameList.get(classNameIndex - 1);
|
||||
className = nameList.get(classNameIndex.value() - 1);
|
||||
}
|
||||
if (overlayNameIndex == 0) {
|
||||
if (overlayNameIndex.value() == 0) {
|
||||
overlayName = "";
|
||||
}
|
||||
else {
|
||||
if (overlayNameIndex > nameList.size()) {
|
||||
if (overlayNameIndex.value() > nameList.size()) {
|
||||
throw new OmfException("Overlay name index out of bounds");
|
||||
}
|
||||
overlayName = nameList.get(overlayNameIndex - 1);
|
||||
overlayName = nameList.get(overlayNameIndex.value() - 1);
|
||||
}
|
||||
|
||||
// Once we know the class name, we can make some educated guesses about read/write/exec permissions
|
||||
@ -347,8 +348,8 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
*/
|
||||
protected void appendEnumeratedData(OmfEnumeratedData rec) {
|
||||
long blockend = rec.getDataOffset() + rec.getLength();
|
||||
if (blockend > segmentLength) {
|
||||
segmentLength = blockend;
|
||||
if (blockend > segmentLength.value()) {
|
||||
segmentLength = new Omf2or4(segmentLength.length(), blockend);
|
||||
}
|
||||
dataBlocks.add(rec);
|
||||
}
|
||||
@ -380,7 +381,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
this.log = log;
|
||||
pointer = 0;
|
||||
dataUpNext = 0;
|
||||
if (pointer < segmentLength) {
|
||||
if (pointer < segmentLength.value()) {
|
||||
establishNextBuffer();
|
||||
}
|
||||
}
|
||||
@ -423,7 +424,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
}
|
||||
}
|
||||
// We may have filler after the last block
|
||||
long size = segmentLength - pointer;
|
||||
long size = segmentLength.value() - pointer;
|
||||
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
||||
throw new IOException("Large hole at the end of OMF segment: " + segmentName);
|
||||
}
|
||||
@ -436,7 +437,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (pointer < segmentLength) {
|
||||
if (pointer < segmentLength.value()) {
|
||||
if (bufferpointer < buffer.length) {
|
||||
pointer++;
|
||||
return buffer[bufferpointer++] & 0xff;
|
||||
@ -454,4 +455,25 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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(BYTE, "segment_attr", null);
|
||||
int A = (segAttr >> 5) & 7;
|
||||
if (A == 0) {
|
||||
struct.add(WORD, "frame_number", null);
|
||||
struct.add(BYTE, "offset", null);
|
||||
}
|
||||
struct.add(segmentLength.toDataType(), "segment_length", null);
|
||||
struct.add(segmentNameIndex.toDataType(), "segment_name_index", null);
|
||||
struct.add(classNameIndex.toDataType(), "class_name_index", null);
|
||||
struct.add(overlayNameIndex.toDataType(), "overlay_name_index", null);
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfString implements StructConverter {
|
||||
|
||||
private int length;
|
||||
private String str;
|
||||
|
||||
public OmfString(int length, String str) {
|
||||
this.length = length;
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public String str() {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
if (length == 0) {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
StructureDataType struct = new StructureDataType("OmfString", 0);
|
||||
struct.add(BYTE, "length", "");
|
||||
struct.add(new StringDataType(), length, "str", null);
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
}
|
@ -20,13 +20,18 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class OmfSymbolRecord extends OmfRecord {
|
||||
private int baseGroupIndex;
|
||||
private int baseSegmentIndex;
|
||||
private OmfIndex baseGroupIndex;
|
||||
private OmfIndex baseSegmentIndex;
|
||||
private int baseFrame;
|
||||
private boolean isStatic;
|
||||
private OmfSymbol[] symbol;
|
||||
private List<Reference> refs = new ArrayList<>();
|
||||
|
||||
private record Reference(OmfString name, Omf2or4 offset, OmfIndex type) {}
|
||||
|
||||
public OmfSymbolRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
||||
this.isStatic = isStatic;
|
||||
@ -35,17 +40,18 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||
boolean hasBigFields = hasBigFields();
|
||||
baseGroupIndex = OmfRecord.readIndex(reader);
|
||||
baseSegmentIndex = OmfRecord.readIndex(reader);
|
||||
if (baseSegmentIndex == 0) {
|
||||
baseFrame = reader.readNextShort() & 0xffff;
|
||||
if (baseSegmentIndex.value() == 0) {
|
||||
baseFrame = reader.readNextUnsignedShort();
|
||||
}
|
||||
|
||||
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
||||
while (reader.getPointerIndex() < max) {
|
||||
String name = OmfRecord.readString(reader);
|
||||
long offset = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
||||
int type = OmfRecord.readIndex(reader);
|
||||
OmfSymbol subrec = new OmfSymbol(name, type, offset, 0, 0);
|
||||
OmfString name = OmfRecord.readString(reader);
|
||||
Omf2or4 offset = OmfRecord.readInt2Or4(reader, hasBigFields);
|
||||
OmfIndex type = OmfRecord.readIndex(reader);
|
||||
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()];
|
||||
@ -57,11 +63,11 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||
}
|
||||
|
||||
public int getGroupIndex() {
|
||||
return baseGroupIndex;
|
||||
return baseGroupIndex.value();
|
||||
}
|
||||
|
||||
public int getSegmentIndex() {
|
||||
return baseSegmentIndex;
|
||||
return baseSegmentIndex.value();
|
||||
}
|
||||
|
||||
public int numSymbols() {
|
||||
@ -76,4 +82,29 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||
return List.of(symbol);
|
||||
}
|
||||
|
||||
public int getBaseFrame() {
|
||||
return baseFrame;
|
||||
}
|
||||
|
||||
@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(baseGroupIndex.toDataType(), "base_group_index", null);
|
||||
struct.add(baseSegmentIndex.toDataType(), "base_segment_index", null);
|
||||
if (baseSegmentIndex.value() == 0) {
|
||||
struct.add(WORD, "base_frame", null);
|
||||
}
|
||||
for (Reference ref : refs) {
|
||||
struct.add(ref.name.toDataType(), "name", null);
|
||||
struct.add(ref.offset.toDataType(), "offset", null);
|
||||
struct.add(ref.type.toDataType(), "type", null);
|
||||
}
|
||||
struct.add(BYTE, "checksum", null);
|
||||
|
||||
struct.setCategoryPath(new CategoryPath(OmfRecord.CATEGORY_PATH));
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ import ghidra.app.util.bin.format.omf.*;
|
||||
import ghidra.app.util.bin.format.omf.OmfFixupRecord.Subrecord;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Undefined;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
@ -47,7 +47,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
public final static long IMAGE_BASE = 0x2000; // Base offset to start loading segments
|
||||
public final static long MAX_UNINITIALIZED_FILL = 0x2000; // Maximum zero bytes added to pad initialized segments
|
||||
|
||||
private ArrayList<OmfSymbol> externsyms = new ArrayList<>();
|
||||
private List<OmfSymbol> externsyms = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* OMF usually stores a string describing the compiler that produced it in a
|
||||
@ -137,19 +137,42 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
// We don't use the file bytes to create block because the bytes are manipulated before
|
||||
// forming the block. Creating the FileBytes anyway in case later we want access to all
|
||||
// the original bytes.
|
||||
MemoryBlockUtils.createFileBytes(program, provider, monitor);
|
||||
FileBytes fileBytes = MemoryBlockUtils.createFileBytes(program, provider, monitor);
|
||||
|
||||
try {
|
||||
processSegmentHeaders(reader, header, program, monitor, log);
|
||||
processPublicSymbols(header, program, monitor, log);
|
||||
processExternalSymbols(header, program, monitor, log);
|
||||
processRelocations(header, program, monitor, log);
|
||||
markupRecords(program, fileBytes, header, log, monitor);
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void markupRecords(Program program, FileBytes fileBytes, OmfFileHeader fileHeader,
|
||||
MessageLog log, TaskMonitor monitor) {
|
||||
monitor.setMessage("Marking up records...");
|
||||
int size =
|
||||
fileHeader.getRecords().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 : fileHeader.getRecords()) {
|
||||
DataUtilities.createData(program, start.add(record.getRecordOffset()),
|
||||
record.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.appendMsg("Failed to markup records");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a (hopefully) descriptive error, if we can't process a specific relocation
|
||||
* @param program is the Program
|
||||
@ -181,7 +204,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
MessageLog log) {
|
||||
Language language = program.getLanguage();
|
||||
OmfFixupRecord.Subrecord[] targetThreads = new Subrecord[4];
|
||||
ArrayList<OmfGroupRecord> groups = header.getGroups();
|
||||
List<OmfGroupRecord> groups = header.getGroups();
|
||||
long targetAddr; // Address of item being referred to
|
||||
Address locAddress; // Location of data to be patched
|
||||
DataConverter converter = DataConverter.getInstance(!header.isLittleEndian());
|
||||
@ -364,7 +387,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
|
||||
final Language language = program.getLanguage();
|
||||
|
||||
ArrayList<OmfSegmentHeader> segments = header.getSegments();
|
||||
List<OmfSegmentHeader> segments = header.getSegments();
|
||||
for (OmfSegmentHeader segment : segments) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
@ -432,9 +455,9 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
MessageLog log) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
|
||||
ArrayList<OmfSymbolRecord> symbols = header.getPublicSymbols();
|
||||
ArrayList<OmfSegmentHeader> segments = header.getSegments();
|
||||
ArrayList<OmfGroupRecord> groups = header.getGroups();
|
||||
List<OmfSymbolRecord> symbols = header.getPublicSymbols();
|
||||
List<OmfSegmentHeader> segments = header.getSegments();
|
||||
List<OmfGroupRecord> groups = header.getGroups();
|
||||
Language language = program.getLanguage();
|
||||
|
||||
monitor.setMessage("Creating Public Symbols");
|
||||
@ -536,7 +559,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||
private void processExternalSymbols(OmfFileHeader header, Program program, TaskMonitor monitor,
|
||||
MessageLog log) {
|
||||
|
||||
ArrayList<OmfExternalSymbol> symbolrecs = header.getExternalSymbols();
|
||||
List<OmfExternalSymbol> symbolrecs = header.getExternalSymbols();
|
||||
if (symbolrecs.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user