mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge branch 'GP-2997_ryanmkurtz_PR-4857_Gravelbones_omf_alias'
(Closes #4856, Closes #4857)
This commit is contained in:
commit
1a36ad806e
20 changed files with 714 additions and 556 deletions
|
@ -22,17 +22,17 @@ import ghidra.app.util.bin.BinaryReader;
|
||||||
|
|
||||||
public class OmfComdefRecord extends OmfExternalSymbol {
|
public class OmfComdefRecord extends OmfExternalSymbol {
|
||||||
|
|
||||||
public OmfComdefRecord(BinaryReader reader,boolean isStatic) throws IOException, OmfException {
|
public OmfComdefRecord(BinaryReader reader, boolean isStatic) throws IOException, OmfException {
|
||||||
super(isStatic);
|
super(isStatic);
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||||
|
|
||||||
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
||||||
while(reader.getPointerIndex() < max) {
|
while (reader.getPointerIndex() < max) {
|
||||||
String name = OmfRecord.readString(reader);
|
String name = OmfRecord.readString(reader);
|
||||||
int typeIndex = OmfRecord.readIndex(reader);
|
int typeIndex = OmfRecord.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
|
||||||
int numElements = readCommunalLength(reader);
|
int numElements = readCommunalLength(reader);
|
||||||
int elSize = readCommunalLength(reader);
|
int elSize = readCommunalLength(reader);
|
||||||
|
@ -42,18 +42,19 @@ public class OmfComdefRecord extends OmfExternalSymbol {
|
||||||
// Values 1 thru 5f plus 61, read the byte length
|
// Values 1 thru 5f plus 61, read the byte length
|
||||||
byteLength = readCommunalLength(reader);
|
byteLength = readCommunalLength(reader);
|
||||||
}
|
}
|
||||||
OmfSymbol sym = new OmfSymbol(name,typeIndex,0,dataType,byteLength);
|
OmfSymbol sym = new OmfSymbol(name, typeIndex, 0, dataType, byteLength);
|
||||||
symbollist.add(sym);
|
symbollist.add(sym);
|
||||||
}
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
symbol = new OmfSymbol[symbollist.size()];
|
symbol = new OmfSymbol[symbollist.size()];
|
||||||
symbollist.toArray(symbol);
|
symbollist.toArray(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int readCommunalLength(BinaryReader reader) throws OmfException, IOException {
|
private static int readCommunalLength(BinaryReader reader) throws OmfException, IOException {
|
||||||
int val = reader.readNextByte() & 0xff;
|
int val = reader.readNextByte() & 0xff;
|
||||||
if (val <= 128)
|
if (val <= 128) {
|
||||||
return val;
|
return val;
|
||||||
|
}
|
||||||
if (val == 0x81) {
|
if (val == 0x81) {
|
||||||
val = reader.readNextShort() & 0xffff;
|
val = reader.readNextShort() & 0xffff;
|
||||||
}
|
}
|
||||||
|
@ -65,9 +66,10 @@ public class OmfComdefRecord extends OmfExternalSymbol {
|
||||||
else if (val == 0x88) {
|
else if (val == 0x88) {
|
||||||
val = reader.readNextInt();
|
val = reader.readNextInt();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
throw new OmfException("Illegal communal length encoding");
|
throw new OmfException("Illegal communal length encoding");
|
||||||
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class OmfCommentRecord extends OmfRecord {
|
||||||
private byte commentType;
|
private byte commentType;
|
||||||
private byte commentClass;
|
private byte commentClass;
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
public OmfCommentRecord(BinaryReader reader) throws IOException {
|
public OmfCommentRecord(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
commentType = reader.readNextByte();
|
commentType = reader.readNextByte();
|
||||||
|
@ -45,11 +45,15 @@ public class OmfCommentRecord extends OmfRecord {
|
||||||
}
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte getCommentType() {
|
||||||
|
return commentType;
|
||||||
|
}
|
||||||
|
|
||||||
public byte getCommentClass() {
|
public byte getCommentClass() {
|
||||||
return commentClass;
|
return commentClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,11 @@ public class OmfEnumeratedData extends OmfRecord implements OmfData {
|
||||||
segmentIndex = OmfRecord.readIndex(reader);
|
segmentIndex = OmfRecord.readIndex(reader);
|
||||||
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields()) & 0xffffffffL;
|
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields()) & 0xffffffffL;
|
||||||
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
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSegmentIndex() {
|
public int getSegmentIndex() {
|
||||||
return segmentIndex;
|
return segmentIndex;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public class OmfEnumeratedData extends OmfRecord implements OmfData {
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
return streamLength;
|
return streamLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(OmfData o) {
|
public int compareTo(OmfData o) {
|
||||||
long otherOffset = o.getDataOffset();
|
long otherOffset = o.getDataOffset();
|
||||||
|
|
|
@ -15,32 +15,32 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.omf;
|
package ghidra.app.util.bin.format.omf;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
|
|
||||||
public class OmfExternalSymbol extends OmfRecord {
|
public class OmfExternalSymbol extends OmfRecord {
|
||||||
private boolean isStatic;
|
private boolean isStatic;
|
||||||
protected OmfSymbol[] symbol;
|
protected OmfSymbol[] symbol;
|
||||||
|
|
||||||
protected OmfExternalSymbol(boolean isStatic) {
|
protected OmfExternalSymbol(boolean isStatic) {
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OmfExternalSymbol(BinaryReader reader,boolean isStatic) throws IOException {
|
public OmfExternalSymbol(BinaryReader reader, boolean isStatic) throws IOException {
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||||
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
||||||
|
|
||||||
while(reader.getPointerIndex() < max) {
|
while (reader.getPointerIndex() < max) {
|
||||||
String name = OmfRecord.readString(reader);
|
String name = OmfRecord.readString(reader);
|
||||||
int type = OmfRecord.readIndex(reader);
|
int type = OmfRecord.readIndex(reader);
|
||||||
OmfSymbol subrec = new OmfSymbol(name,type,0,0,0);
|
OmfSymbol subrec = new OmfSymbol(name, type, 0, 0, 0);
|
||||||
symbollist.add(subrec);
|
symbollist.add(subrec);
|
||||||
}
|
}
|
||||||
|
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
symbol = new OmfSymbol[symbollist.size()];
|
symbol = new OmfSymbol[symbollist.size()];
|
||||||
symbollist.toArray(symbol);
|
symbollist.toArray(symbol);
|
||||||
|
@ -49,7 +49,7 @@ public class OmfExternalSymbol extends OmfRecord {
|
||||||
public OmfSymbol[] getSymbols() {
|
public OmfSymbol[] getSymbols() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStatic() {
|
public boolean isStatic() {
|
||||||
return isStatic;
|
return isStatic;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,19 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.omf;
|
package ghidra.app.util.bin.format.omf;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class OmfFileHeader extends OmfRecord {
|
public class OmfFileHeader extends OmfRecord {
|
||||||
|
|
||||||
private String objectName; // Name of the object module
|
private String objectName; // Name of the object module
|
||||||
private String libModuleName=null; // Name of the module (within a library)
|
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 String translator = null; // Usually the compiler/linker used to produce this object
|
||||||
private boolean isLittleEndian;
|
private boolean isLittleEndian;
|
||||||
private ArrayList<String> nameList = new ArrayList<String>(); // Indexable List of segment, group, ... names
|
private ArrayList<String> nameList = new ArrayList<String>(); // Indexable List of segment, group, ... names
|
||||||
private ArrayList<OmfSegmentHeader> segments = new ArrayList<OmfSegmentHeader>();
|
private ArrayList<OmfSegmentHeader> segments = new ArrayList<OmfSegmentHeader>();
|
||||||
|
@ -36,7 +36,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
private ArrayList<OmfSymbolRecord> symbols = new ArrayList<OmfSymbolRecord>();
|
private ArrayList<OmfSymbolRecord> symbols = new ArrayList<OmfSymbolRecord>();
|
||||||
private ArrayList<OmfFixupRecord> fixup = new ArrayList<OmfFixupRecord>();
|
private ArrayList<OmfFixupRecord> fixup = new ArrayList<OmfFixupRecord>();
|
||||||
private ArrayList<OmfSegmentHeader> extraSeg = null; // Holds implied segments that don't have official header record
|
private ArrayList<OmfSegmentHeader> extraSeg = null; // Holds implied segments that don't have official header record
|
||||||
// private OmfModuleEnd endModule = null;
|
// private OmfModuleEnd endModule = null;
|
||||||
|
|
||||||
public OmfFileHeader(BinaryReader reader) throws IOException {
|
public OmfFileHeader(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
|
@ -44,7 +44,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
isLittleEndian = reader.isLittleEndian();
|
isLittleEndian = reader.isLittleEndian();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is usually the original source filename
|
* This is usually the original source filename
|
||||||
* @return the name
|
* @return the name
|
||||||
|
@ -52,7 +52,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return objectName;
|
return objectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the object module (within a library)
|
* The name of the object module (within a library)
|
||||||
* @return the name
|
* @return the name
|
||||||
|
@ -60,14 +60,14 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public String getLibraryModuleName() {
|
public String getLibraryModuleName() {
|
||||||
return libModuleName;
|
return libModuleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the string identifying the architecture this object was compiled for
|
* @return the string identifying the architecture this object was compiled for
|
||||||
*/
|
*/
|
||||||
public String getMachineName() {
|
public String getMachineName() {
|
||||||
return "i386"; // This is the only possibility
|
return "i386"; // This is the only possibility
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the OMF file contains a "translator" record, this is usually a string
|
* If the OMF file contains a "translator" record, this is usually a string
|
||||||
* indicating the compiler which produced the file.
|
* indicating the compiler which produced the file.
|
||||||
|
@ -76,14 +76,14 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public String getTranslator() {
|
public String getTranslator() {
|
||||||
return translator;
|
return translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the file describes the load image for a little endian architecture
|
* @return true if the file describes the load image for a little endian architecture
|
||||||
*/
|
*/
|
||||||
public boolean isLittleEndian() {
|
public boolean isLittleEndian() {
|
||||||
return isLittleEndian;
|
return isLittleEndian;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of segments in this file
|
* @return the list of segments in this file
|
||||||
*/
|
*/
|
||||||
|
@ -97,7 +97,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public ArrayList<OmfSegmentHeader> getExtraSegments() {
|
public ArrayList<OmfSegmentHeader> getExtraSegments() {
|
||||||
return extraSeg;
|
return extraSeg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of group records for this file
|
* @return the list of group records for this file
|
||||||
*/
|
*/
|
||||||
|
@ -111,31 +111,31 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public ArrayList<OmfExternalSymbol> getExternalSymbols() {
|
public ArrayList<OmfExternalSymbol> getExternalSymbols() {
|
||||||
return externsymbols;
|
return externsymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of symbols exported by this file
|
* @return the list of symbols exported by this file
|
||||||
*/
|
*/
|
||||||
public ArrayList<OmfSymbolRecord> getPublicSymbols() {
|
public ArrayList<OmfSymbolRecord> getPublicSymbols() {
|
||||||
return symbols;
|
return symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of relocation records for this file
|
* @return the list of relocation records for this file
|
||||||
*/
|
*/
|
||||||
public ArrayList<OmfFixupRecord> getFixups() {
|
public ArrayList<OmfFixupRecord> getFixups() {
|
||||||
return fixup;
|
return fixup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the explicit data-blocks for each segment into address order.
|
* Sort the explicit data-blocks for each segment into address order.
|
||||||
*/
|
*/
|
||||||
public void sortSegmentDataBlocks() {
|
public void sortSegmentDataBlocks() {
|
||||||
if (extraSeg != null) {
|
if (extraSeg != null) {
|
||||||
for(int i=0;i<extraSeg.size();++i) {
|
for (int i = 0; i < extraSeg.size(); ++i) {
|
||||||
segments.add(extraSeg.get(i));
|
segments.add(extraSeg.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i=0;i<segments.size();++i) {
|
for (int i = 0; i < segments.size(); ++i) {
|
||||||
segments.get(i).sortData();
|
segments.get(i).sortData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,16 +149,16 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
int index = datablock.getSegmentIndex();
|
int index = datablock.getSegmentIndex();
|
||||||
int subindex = -1;
|
int subindex = -1;
|
||||||
OmfSegmentHeader segment;
|
OmfSegmentHeader segment;
|
||||||
if ((index & 0x4000)!=0) {
|
if ((index & 0x4000) != 0) {
|
||||||
subindex = index & 0x3fff;
|
subindex = index & 0x3fff;
|
||||||
index = 1;
|
index = 1;
|
||||||
segment = createOrFindBorlandSegment(subindex, 1);
|
segment = createOrFindBorlandSegment(subindex, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((index <=0)||(index>segments.size())) {
|
if ((index <= 0) || (index > segments.size())) {
|
||||||
throw new OmfException("Bad segment index");
|
throw new OmfException("Bad segment index");
|
||||||
}
|
}
|
||||||
segment = segments.get(index-1);
|
segment = segments.get(index - 1);
|
||||||
}
|
}
|
||||||
if (subindex != -1) {
|
if (subindex != -1) {
|
||||||
segment.appendEnumeratedData(datablock);
|
segment.appendEnumeratedData(datablock);
|
||||||
|
@ -167,7 +167,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
segment.addEnumeratedData(datablock);
|
segment.addEnumeratedData(datablock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an index, retrieve the specific segment it refers to. This
|
* Given an index, retrieve the specific segment it refers to. This
|
||||||
* incorporates the special Borland segments, where the index has
|
* incorporates the special Borland segments, where the index has
|
||||||
|
@ -179,21 +179,21 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
public OmfSegmentHeader resolveSegment(int index) throws OmfException {
|
public OmfSegmentHeader resolveSegment(int index) throws OmfException {
|
||||||
int subindex = -1;
|
int subindex = -1;
|
||||||
OmfSegmentHeader res;
|
OmfSegmentHeader res;
|
||||||
if ((index & 0x4000)!=0) {
|
if ((index & 0x4000) != 0) {
|
||||||
subindex = index & 0x3fff;
|
subindex = index & 0x3fff;
|
||||||
if ((subindex<=0)||(subindex>extraSeg.size())) {
|
if ((subindex <= 0) || (subindex > extraSeg.size())) {
|
||||||
throw new OmfException("Bad extra segment index");
|
throw new OmfException("Bad extra segment index");
|
||||||
}
|
}
|
||||||
res = extraSeg.get(subindex - 1);
|
res = extraSeg.get(subindex - 1);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if ((index <=0)||(index>segments.size())) {
|
if ((index <= 0) || (index > segments.size())) {
|
||||||
throw new OmfException("Bad segment index");
|
throw new OmfException("Bad segment index");
|
||||||
}
|
}
|
||||||
res = segments.get(index-1);
|
res = segments.get(index - 1);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve special names associated with each segment: segment, class, overlay names
|
* Resolve special names associated with each segment: segment, class, overlay names
|
||||||
* and group: group name
|
* and group: group name
|
||||||
|
@ -201,15 +201,15 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
* @throws OmfException if any name indices are malformed
|
* @throws OmfException if any name indices are malformed
|
||||||
*/
|
*/
|
||||||
public void resolveNames() throws OmfException {
|
public void resolveNames() throws OmfException {
|
||||||
for(int i=0;i<segments.size();++i) {
|
for (int i = 0; i < segments.size(); ++i) {
|
||||||
segments.get(i).resolveNames(nameList);
|
segments.get(i).resolveNames(nameList);
|
||||||
}
|
}
|
||||||
// extraSeg segments already have names
|
// extraSeg segments already have names
|
||||||
for(int i=0;i<groups.size();++i) {
|
for (int i = 0; i < groups.size(); ++i) {
|
||||||
groups.get(i).resolveNames(nameList);
|
groups.get(i).resolveNames(nameList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an index, either find an existing Borland segment, or create a new one.
|
* Given an index, either find an existing Borland segment, or create a new one.
|
||||||
* Borland compilers can introduce special segments with a separate indexing
|
* Borland compilers can introduce special segments with a separate indexing
|
||||||
|
@ -219,30 +219,30 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
* @param datatype is the type of (new) segment
|
* @param datatype is the type of (new) segment
|
||||||
* @return the corresponding OmfSegmentHeader
|
* @return the corresponding OmfSegmentHeader
|
||||||
*/
|
*/
|
||||||
private OmfSegmentHeader createOrFindBorlandSegment(int index,int datatype) {
|
private OmfSegmentHeader createOrFindBorlandSegment(int index, int datatype) {
|
||||||
if (extraSeg == null) {
|
if (extraSeg == null) {
|
||||||
extraSeg = new ArrayList<OmfSegmentHeader>();
|
extraSeg = new ArrayList<OmfSegmentHeader>();
|
||||||
}
|
}
|
||||||
while(extraSeg.size() < index) {
|
while (extraSeg.size() < index) {
|
||||||
extraSeg.add(null);
|
extraSeg.add(null);
|
||||||
}
|
}
|
||||||
OmfSegmentHeader segment = extraSeg.get(index-1);
|
OmfSegmentHeader segment = extraSeg.get(index - 1);
|
||||||
if (segment == null) {
|
if (segment == null) {
|
||||||
segment = new OmfSegmentHeader(index,datatype);
|
segment = new OmfSegmentHeader(index, datatype);
|
||||||
extraSeg.set(index-1,segment);
|
extraSeg.set(index - 1, segment);
|
||||||
}
|
}
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evaluateComdef(OmfComdefRecord comdef) {
|
private void evaluateComdef(OmfComdefRecord comdef) {
|
||||||
OmfSymbol[] coms = comdef.getSymbols();
|
OmfSymbol[] coms = comdef.getSymbols();
|
||||||
for (OmfSymbol sym : coms) {
|
for (OmfSymbol sym : coms) {
|
||||||
int dt = sym.getDataType();
|
int dt = sym.getDataType();
|
||||||
if (dt >0 && dt < 0x60) { // A special borland segment symbol
|
if (dt > 0 && dt < 0x60) { // A special borland segment symbol
|
||||||
int count = (extraSeg==null) ? 1 : extraSeg.size()+1;
|
int count = (extraSeg == null) ? 1 : extraSeg.size() + 1;
|
||||||
createOrFindBorlandSegment(count,dt);
|
createOrFindBorlandSegment(count, dt);
|
||||||
sym.setSegmentRef(count);
|
sym.setSegmentRef(count);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,128 +256,127 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
* @throws IOException for problems reading program data
|
* @throws IOException for problems reading program data
|
||||||
* @throws OmfException for malformed records
|
* @throws OmfException for malformed records
|
||||||
*/
|
*/
|
||||||
public static OmfFileHeader scan(BinaryReader reader,TaskMonitor monitor,boolean initialCommentsOnly) throws IOException, OmfException {
|
public static OmfFileHeader scan(BinaryReader reader, TaskMonitor monitor,
|
||||||
|
boolean initialCommentsOnly) throws IOException, OmfException {
|
||||||
OmfRecord record = OmfRecord.readRecord(reader);
|
OmfRecord record = OmfRecord.readRecord(reader);
|
||||||
if ((record.getRecordType() & (byte)0xfc)!=OmfRecord.THEADR) {
|
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;
|
||||||
byte type = record.getRecordType();
|
|
||||||
type &= 0xfe;
|
while (true) {
|
||||||
while(type != MODEND) {
|
|
||||||
if (monitor.isCancelled()) {
|
|
||||||
break; // Return what we have
|
|
||||||
}
|
|
||||||
record = OmfRecord.readRecord(reader);
|
record = OmfRecord.readRecord(reader);
|
||||||
type = record.getRecordType();
|
|
||||||
type &= 0xfe; // Mask off the least significant bit
|
if (monitor.isCancelled()) {
|
||||||
if (initialCommentsOnly && (type != COMENT)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(type) {
|
if (record instanceof OmfModuleEnd) {
|
||||||
case COMENT:
|
break;
|
||||||
byte commentClass = ((OmfCommentRecord)record).getCommentClass();
|
}
|
||||||
|
|
||||||
|
if (record instanceof OmfCommentRecord comment) {
|
||||||
|
byte commentClass = comment.getCommentClass();
|
||||||
if (commentClass == OmfCommentRecord.COMMENT_CLASS_TRANSLATOR) {
|
if (commentClass == OmfCommentRecord.COMMENT_CLASS_TRANSLATOR) {
|
||||||
header.translator = ((OmfCommentRecord)record).getValue();
|
header.translator = comment.getValue();
|
||||||
}
|
}
|
||||||
else if (commentClass == OmfCommentRecord.COMMENT_CLASS_LIBMOD) {
|
else if (commentClass == OmfCommentRecord.COMMENT_CLASS_LIBMOD) {
|
||||||
header.libModuleName = ((OmfCommentRecord)record).getValue();
|
header.libModuleName = comment.getValue();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (initialCommentsOnly) {
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break; // Skip most records
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the entire object file
|
* Parse the entire object file
|
||||||
|
*
|
||||||
* @param reader is the byte stream
|
* @param reader is the byte stream
|
||||||
* @param monitor is checked for cancel button
|
* @param monitor is checked for cancel button
|
||||||
|
* @param log the log
|
||||||
* @return the header record as root of object
|
* @return the header record as root of object
|
||||||
* @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(BinaryReader reader,TaskMonitor monitor) throws IOException, OmfException {
|
public static OmfFileHeader parse(BinaryReader reader, TaskMonitor monitor, MessageLog log)
|
||||||
|
throws IOException, OmfException {
|
||||||
OmfRecord record = OmfRecord.readRecord(reader);
|
OmfRecord record = OmfRecord.readRecord(reader);
|
||||||
if ((record.getRecordType() & (byte)0xfc)!=OmfRecord.THEADR) {
|
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;
|
||||||
Object lastDataBlock = null;
|
Object lastDataBlock = null;
|
||||||
|
|
||||||
while((record.getRecordType() & (byte)0xfe) != OmfRecord.MODEND) {
|
while (true) {
|
||||||
if (monitor.isCancelled()) {
|
|
||||||
break; // Return what we have
|
|
||||||
}
|
|
||||||
record = OmfRecord.readRecord(reader);
|
record = OmfRecord.readRecord(reader);
|
||||||
byte type = record.getRecordType();
|
|
||||||
type &= 0xfe; // Mask off the least significant bit
|
if (monitor.isCancelled()) {
|
||||||
switch(type) {
|
break;
|
||||||
case COMENT:
|
}
|
||||||
byte commentClass = ((OmfCommentRecord)record).getCommentClass();
|
if (record instanceof OmfModuleEnd) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record instanceof OmfCommentRecord comment) {
|
||||||
|
byte commentClass = comment.getCommentClass();
|
||||||
if (commentClass == OmfCommentRecord.COMMENT_CLASS_TRANSLATOR) {
|
if (commentClass == OmfCommentRecord.COMMENT_CLASS_TRANSLATOR) {
|
||||||
header.translator = ((OmfCommentRecord)record).getValue();
|
header.translator = comment.getValue();
|
||||||
}
|
}
|
||||||
else if (commentClass == OmfCommentRecord.COMMENT_CLASS_LIBMOD) {
|
else if (commentClass == OmfCommentRecord.COMMENT_CLASS_LIBMOD) {
|
||||||
header.libModuleName = ((OmfCommentRecord)record).getValue();
|
header.libModuleName = comment.getValue();
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case MODEND:
|
else if (record instanceof OmfComdefRecord comdef) {
|
||||||
// header.endModule = (OmfModuleEnd)record;
|
header.evaluateComdef(comdef);
|
||||||
// We are not currently examining the end module record
|
header.externsymbols.add((OmfExternalSymbol) record);
|
||||||
break;
|
}
|
||||||
case COMDEF:
|
else if (record instanceof OmfExternalSymbol external) {
|
||||||
case LCOMDEF:
|
header.externsymbols.add(external);
|
||||||
header.evaluateComdef((OmfComdefRecord)record);
|
}
|
||||||
header.externsymbols.add((OmfExternalSymbol)record);
|
else if (record instanceof OmfSymbolRecord symbol) {
|
||||||
break;
|
header.symbols.add(symbol);
|
||||||
case LEXTDEF:
|
}
|
||||||
case EXTDEF:
|
else if (record instanceof OmfNamesRecord names) {
|
||||||
header.externsymbols.add((OmfExternalSymbol)record);
|
names.appendNames(header.nameList); // Keep names, otherwise don't save record
|
||||||
break;
|
}
|
||||||
case PUBDEF:
|
else if (record instanceof OmfSegmentHeader seghead) {
|
||||||
case LPUBDEF:
|
header.segments.add(seghead);
|
||||||
header.symbols.add((OmfSymbolRecord)record);
|
}
|
||||||
break;
|
else if (record instanceof OmfGroupRecord group) {
|
||||||
case LINNUM:
|
header.groups.add(group);
|
||||||
break; // Not saving this information currently
|
}
|
||||||
case LNAMES:
|
else if (record instanceof OmfFixupRecord fixuprec) {
|
||||||
((OmfNamesRecord)record).appendNames(header.nameList); // Keep names, otherwise don't save record
|
|
||||||
break;
|
|
||||||
case SEGDEF:
|
|
||||||
header.segments.add((OmfSegmentHeader)record);
|
|
||||||
break;
|
|
||||||
case GRPDEF:
|
|
||||||
header.groups.add((OmfGroupRecord)record);
|
|
||||||
break;
|
|
||||||
case FIXUPP:
|
|
||||||
OmfFixupRecord fixuprec = (OmfFixupRecord)record;
|
|
||||||
fixuprec.setDataBlock(lastDataBlock);
|
fixuprec.setDataBlock(lastDataBlock);
|
||||||
header.fixup.add(fixuprec);
|
header.fixup.add(fixuprec);
|
||||||
break;
|
}
|
||||||
case LEDATA:
|
else if (record instanceof OmfEnumeratedData enumheader) {
|
||||||
OmfEnumeratedData enumheader = (OmfEnumeratedData)record;
|
|
||||||
header.addEnumeratedBlock(enumheader);
|
header.addEnumeratedBlock(enumheader);
|
||||||
lastDataBlock = enumheader;
|
lastDataBlock = enumheader;
|
||||||
break;
|
}
|
||||||
case LIDATA:
|
else if (record instanceof OmfIteratedData iterheader) {
|
||||||
OmfIteratedData iterheader = (OmfIteratedData)record;
|
if (iterheader.getSegmentIndex() <= 0 ||
|
||||||
if (iterheader.getSegmentIndex() <= 0 || iterheader.getSegmentIndex() > header.segments.size()) {
|
iterheader.getSegmentIndex() > header.segments.size()) {
|
||||||
throw new OmfException("Bad segment index on LIDATA");
|
throw new OmfException("Bad segment index on LIDATA");
|
||||||
}
|
}
|
||||||
OmfSegmentHeader segheader2 = header.segments.get(iterheader.getSegmentIndex()-1);
|
OmfSegmentHeader segheader2 = header.segments.get(iterheader.getSegmentIndex() - 1);
|
||||||
segheader2.addIteratedData(iterheader);
|
segheader2.addIteratedData(iterheader);
|
||||||
lastDataBlock = iterheader;
|
lastDataBlock = iterheader;
|
||||||
break;
|
}
|
||||||
default:
|
else if (record instanceof OmfUnsupportedRecord) {
|
||||||
// Should never reach here
|
logRecord("Unsupported OMF record", record, log);
|
||||||
|
}
|
||||||
|
else if (record instanceof OmfObsoleteRecord) {
|
||||||
|
logRecord("Obsolete OMF record", record, log);
|
||||||
|
}
|
||||||
|
else if (record instanceof OmfUnknownRecord) {
|
||||||
|
logRecord("Unknown OMF record", record, log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign a load image address to each segment. Follow OMF rules for grouping and ordering
|
* Assign a load image address to each segment. Follow OMF rules for grouping and ordering
|
||||||
* the segments in memory.
|
* the segments in memory.
|
||||||
|
@ -386,7 +385,8 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
* @param groups is the list of specific segments that are grouped together in memory
|
* @param groups is the list of specific segments that are grouped together in memory
|
||||||
* @throws OmfException for malformed index/alignment/combining fields
|
* @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, ArrayList<OmfSegmentHeader> segments,
|
||||||
|
ArrayList<OmfGroupRecord> groups) throws OmfException {
|
||||||
// Link anything in groups first
|
// Link anything in groups first
|
||||||
for (int i = 0; i < groups.size(); ++i) {
|
for (int i = 0; i < groups.size(); ++i) {
|
||||||
OmfGroupRecord group = groups.get(i);
|
OmfGroupRecord group = groups.get(i);
|
||||||
|
@ -396,14 +396,15 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
try {
|
try {
|
||||||
OmfSegmentHeader segment = segments.get(index - 1);
|
OmfSegmentHeader segment = segments.get(index - 1);
|
||||||
startAddress = segment.relocateSegment(startAddress, -1);
|
startAddress = segment.relocateSegment(startAddress, -1);
|
||||||
} catch (IndexOutOfBoundsException ex) {
|
}
|
||||||
|
catch (IndexOutOfBoundsException ex) {
|
||||||
throw new OmfException(ex.getMessage());
|
throw new OmfException(ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in any remaining segments
|
// Fill in any remaining segments
|
||||||
for(int i=0;i<segments.size();++i) {
|
for (int i = 0; i < segments.size(); ++i) {
|
||||||
OmfSegmentHeader segment = segments.get(i);
|
OmfSegmentHeader segment = segments.get(i);
|
||||||
if (segment.getStartAddress() != -1) {
|
if (segment.getStartAddress() != -1) {
|
||||||
continue; // Address already assigned
|
continue; // Address already assigned
|
||||||
|
@ -411,7 +412,7 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
|
|
||||||
startAddress = segment.relocateSegment(startAddress, -1);
|
startAddress = segment.relocateSegment(startAddress, -1);
|
||||||
// Look for any segments with same name,class which should be officially "combined" with this segment
|
// Look for any segments with same name,class which should be officially "combined" with this segment
|
||||||
for(int j=i+1;j<segments.size();++j) {
|
for (int j = i + 1; j < segments.size(); ++j) {
|
||||||
OmfSegmentHeader combineSeg = segments.get(j);
|
OmfSegmentHeader combineSeg = segments.get(j);
|
||||||
if (combineSeg.getStartAddress() != -1) {
|
if (combineSeg.getStartAddress() != -1) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -426,19 +427,19 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
if (C == 0) {
|
if (C == 0) {
|
||||||
continue; // Private segment
|
continue; // Private segment
|
||||||
}
|
}
|
||||||
if (C==2 || C==4 || C==7) {
|
if (C == 2 || C == 4 || C == 7) {
|
||||||
startAddress = combineSeg.relocateSegment(startAddress, -1);
|
startAddress = combineSeg.relocateSegment(startAddress, -1);
|
||||||
}
|
}
|
||||||
else if (C==5) {
|
else if (C == 5) {
|
||||||
startAddress = combineSeg.relocateSegment(startAddress, 1);
|
startAddress = combineSeg.relocateSegment(startAddress, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new OmfException("Combine type not supported");
|
throw new OmfException("Combine type not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the file has the specific OMF magic number
|
* Check that the file has the specific OMF magic number
|
||||||
* @param reader accesses the bytes of the file
|
* @param reader accesses the bytes of the file
|
||||||
|
@ -457,13 +458,17 @@ public class OmfFileHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a reader for a specific OMF file
|
* Create a reader for a specific OMF file
|
||||||
* @param provider is the underlying ByteProvider
|
* @param provider is the underlying ByteProvider
|
||||||
* @return the new reader
|
* @return the new reader
|
||||||
*/
|
*/
|
||||||
public static BinaryReader createReader(ByteProvider provider) {
|
public static BinaryReader createReader(ByteProvider provider) {
|
||||||
return new BinaryReader(provider,true/* Always little endian */);
|
return new BinaryReader(provider, true/* Always little endian */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logRecord(String description, OmfRecord record, MessageLog log) {
|
||||||
|
log.appendMsg(description + " (" + record + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,16 +27,16 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
private Subrecord[] subrecs;
|
private Subrecord[] subrecs;
|
||||||
private OmfEnumeratedData lastLEData = null;
|
private OmfEnumeratedData lastLEData = null;
|
||||||
private OmfIteratedData lastLIData = null;
|
private OmfIteratedData lastLIData = null;
|
||||||
|
|
||||||
public OmfFixupRecord(BinaryReader reader) throws IOException {
|
public OmfFixupRecord(BinaryReader reader) throws IOException {
|
||||||
ArrayList<Subrecord> subreclist = new ArrayList<Subrecord>();
|
ArrayList<Subrecord> subreclist = new ArrayList<Subrecord>();
|
||||||
boolean hasBigFields = ((getRecordType() & 1)!=0);
|
boolean hasBigFields = ((getRecordType() & 1) != 0);
|
||||||
|
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||||
while(reader.getPointerIndex() < max) {
|
while (reader.getPointerIndex() < max) {
|
||||||
byte peek = reader.peekNextByte();
|
byte peek = reader.peekNextByte();
|
||||||
if ((peek & 0x80)==0) {
|
if ((peek & 0x80) == 0) {
|
||||||
ThreadSubrecord subrec = ThreadSubrecord.readThreadSubrecord(reader, hasBigFields);
|
ThreadSubrecord subrec = ThreadSubrecord.readThreadSubrecord(reader, hasBigFields);
|
||||||
subreclist.add(subrec);
|
subreclist.add(subrec);
|
||||||
}
|
}
|
||||||
|
@ -49,18 +49,18 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
subreclist.toArray(subrecs);
|
subreclist.toArray(subrecs);
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDataBlock(Object last) {
|
public void setDataBlock(Object last) {
|
||||||
if (last instanceof OmfEnumeratedData) {
|
if (last instanceof OmfEnumeratedData) {
|
||||||
lastLEData = (OmfEnumeratedData)last;
|
lastLEData = (OmfEnumeratedData) last;
|
||||||
lastLIData = null;
|
lastLIData = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastLIData = (OmfIteratedData)last;
|
lastLIData = (OmfIteratedData) last;
|
||||||
lastLEData = null;
|
lastLEData = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subrecord[] getSubrecords() {
|
public Subrecord[] getSubrecords() {
|
||||||
return subrecs;
|
return subrecs;
|
||||||
}
|
}
|
||||||
|
@ -78,9 +78,9 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
public Address locAddress; // Location of data to be patched
|
public Address locAddress; // Location of data to be patched
|
||||||
public boolean M; // true for segment-relative, false for self-relative
|
public boolean M; // true for segment-relative, false for self-relative
|
||||||
public int locationType;
|
public int locationType;
|
||||||
|
|
||||||
public FixupState(OmfFileHeader header,ArrayList<OmfSymbol> externsyms,Language lang) {
|
public FixupState(OmfFileHeader header, ArrayList<OmfSymbol> externsyms, Language lang) {
|
||||||
for(int i=0;i<4;++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
frameThreads[i] = null;
|
frameThreads[i] = null;
|
||||||
targetThreads[i] = null;
|
targetThreads[i] = null;
|
||||||
}
|
}
|
||||||
|
@ -89,26 +89,26 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
externals = externsyms;
|
externals = externsyms;
|
||||||
language = lang;
|
language = lang;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
targetState = -1;
|
targetState = -1;
|
||||||
locAddress = null;
|
locAddress = null;
|
||||||
locationType = -1;
|
locationType = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Subrecord {
|
public static class Subrecord {
|
||||||
private boolean isThread;
|
private boolean isThread;
|
||||||
|
|
||||||
public Subrecord(boolean isthread) {
|
public Subrecord(boolean isthread) {
|
||||||
isThread = isthread;
|
isThread = isthread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isThread() {
|
public boolean isThread() {
|
||||||
return isThread;
|
return isThread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ThreadSubrecord extends Subrecord {
|
public static class ThreadSubrecord extends Subrecord {
|
||||||
private byte type;
|
private byte type;
|
||||||
private int index;
|
private int index;
|
||||||
|
@ -116,42 +116,47 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
public ThreadSubrecord() {
|
public ThreadSubrecord() {
|
||||||
super(true);
|
super(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMethod() {
|
public int getMethod() {
|
||||||
return (type>>2) & 7;
|
return (type >> 2) & 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFrameThread() {
|
public boolean isFrameThread() {
|
||||||
return ((type>>6)&1)!=0;
|
return ((type >> 6) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getThreadNum() {
|
public int getThreadNum() {
|
||||||
return (type & 3);
|
return (type & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateState(FixupState state) {
|
public void updateState(FixupState state) {
|
||||||
if (isFrameThread())
|
if (isFrameThread()) {
|
||||||
state.frameThreads[getThreadNum()] = this;
|
state.frameThreads[getThreadNum()] = this;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
state.targetThreads[getThreadNum()] = this;
|
state.targetThreads[getThreadNum()] = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ThreadSubrecord readThreadSubrecord(BinaryReader reader,boolean hasBigFields) throws IOException {
|
public static ThreadSubrecord readThreadSubrecord(BinaryReader reader, boolean hasBigFields)
|
||||||
|
throws IOException {
|
||||||
ThreadSubrecord thread = new ThreadSubrecord();
|
ThreadSubrecord thread = new ThreadSubrecord();
|
||||||
thread.type = reader.readNextByte();
|
thread.type = reader.readNextByte();
|
||||||
int method = thread.getMethod();
|
int method = thread.getMethod();
|
||||||
if (method < 4)
|
if (method < 4) {
|
||||||
thread.index = OmfRecord.readInt1Or2(reader, hasBigFields);
|
thread.index = OmfRecord.readInt1Or2(reader, hasBigFields);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
thread.index = -1;
|
thread.index = -1;
|
||||||
|
}
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FixupTarget {
|
public static class FixupTarget {
|
||||||
private byte fixData;
|
private byte fixData;
|
||||||
private int frameDatum;
|
private int frameDatum;
|
||||||
|
@ -159,28 +164,28 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
private int targetDisplacement;
|
private int targetDisplacement;
|
||||||
|
|
||||||
public boolean isFrameThread() {
|
public boolean isFrameThread() {
|
||||||
return ((fixData>>7)&1)!=0;
|
return ((fixData >> 7) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTargetThread() {
|
public boolean isTargetThread() {
|
||||||
return ((fixData>>3)&1)!=0;
|
return ((fixData >> 3) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFrameMethod() {
|
public int getFrameMethod() {
|
||||||
return ((fixData>>4)&7);
|
return ((fixData >> 4) & 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getP() {
|
public int getP() {
|
||||||
int res = (fixData >>2)&1;
|
int res = (fixData >> 2) & 1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveFrame(FixupState state) throws OmfException {
|
public void resolveFrame(FixupState state) throws OmfException {
|
||||||
int method;
|
int method;
|
||||||
int index;
|
int index;
|
||||||
if (isFrameThread()) {
|
if (isFrameThread()) {
|
||||||
// Frame datum from a thread
|
// Frame datum from a thread
|
||||||
int threadnum = ((fixData>>4)&3);
|
int threadnum = ((fixData >> 4) & 3);
|
||||||
ThreadSubrecord subrec = state.frameThreads[threadnum];
|
ThreadSubrecord subrec = state.frameThreads[threadnum];
|
||||||
method = subrec.getMethod();
|
method = subrec.getMethod();
|
||||||
index = subrec.getIndex();
|
index = subrec.getIndex();
|
||||||
|
@ -189,31 +194,33 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
method = getFrameMethod();
|
method = getFrameMethod();
|
||||||
index = frameDatum;
|
index = frameDatum;
|
||||||
}
|
}
|
||||||
switch(method) {
|
switch (method) {
|
||||||
case 0: // Index is for a segment
|
case 0: // Index is for a segment
|
||||||
state.frameState = state.header.resolveSegment(index).getFrameDatum();
|
state.frameState = state.header.resolveSegment(index).getFrameDatum();
|
||||||
break;
|
break;
|
||||||
case 1: // Index is for a group
|
case 1: // Index is for a group
|
||||||
state.frameState = state.groups.get(index-1).getFrameDatum();
|
state.frameState = state.groups.get(index - 1).getFrameDatum();
|
||||||
break;
|
break;
|
||||||
case 2: // Index is for an external symbol
|
case 2: // Index is for an external symbol
|
||||||
state.frameState = state.externals.get(index-1).getFrameDatum();
|
state.frameState = state.externals.get(index - 1).getFrameDatum();
|
||||||
break;
|
break;
|
||||||
case 4: // Segment Index grabbed from datablock
|
case 4: // Segment Index grabbed from datablock
|
||||||
if (state.currentFixupRecord.lastLEData != null)
|
if (state.currentFixupRecord.lastLEData != null) {
|
||||||
index = state.currentFixupRecord.lastLEData.getSegmentIndex();
|
index = state.currentFixupRecord.lastLEData.getSegmentIndex();
|
||||||
else
|
}
|
||||||
index = state.currentFixupRecord.lastLIData.getSegmentIndex();
|
else {
|
||||||
state.frameState = state.header.resolveSegment(index).getFrameDatum();
|
index = state.currentFixupRecord.lastLIData.getSegmentIndex();
|
||||||
break;
|
}
|
||||||
case 5: // Frame determined by target
|
state.frameState = state.header.resolveSegment(index).getFrameDatum();
|
||||||
// TODO: Fill this in properly
|
break;
|
||||||
break;
|
case 5: // Frame determined by target
|
||||||
default:
|
// TODO: Fill this in properly
|
||||||
state.frameState = -1; // Indicate an error condition
|
break;
|
||||||
|
default:
|
||||||
|
state.frameState = -1; // Indicate an error condition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveTarget(FixupState state) throws OmfException {
|
public void resolveTarget(FixupState state) throws OmfException {
|
||||||
int method;
|
int method;
|
||||||
int index;
|
int index;
|
||||||
|
@ -230,67 +237,68 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
index = targetDatum;
|
index = targetDatum;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(method) {
|
switch (method) {
|
||||||
case 0: // Index is for a segment
|
case 0: // Index is for a segment
|
||||||
state.targetState = state.header.resolveSegment(index).getStartAddress();
|
state.targetState = state.header.resolveSegment(index).getStartAddress();
|
||||||
state.targetState += targetDisplacement;
|
state.targetState += targetDisplacement;
|
||||||
break;
|
break;
|
||||||
case 1: // Index is for a group
|
case 1: // Index is for a group
|
||||||
state.targetState = state.groups.get(index-1).getStartAddress();
|
state.targetState = state.groups.get(index - 1).getStartAddress();
|
||||||
state.targetState += targetDisplacement;
|
state.targetState += targetDisplacement;
|
||||||
break;
|
break;
|
||||||
case 2: // Index is for an external symbol
|
case 2: // Index is for an external symbol
|
||||||
state.targetState = state.externals.get(index-1).getAddress().getOffset();
|
state.targetState = state.externals.get(index - 1).getAddress().getOffset();
|
||||||
state.targetState += targetDisplacement;
|
state.targetState += targetDisplacement;
|
||||||
break;
|
break;
|
||||||
// case 3: // Not supported by many linkers
|
// case 3: // Not supported by many linkers
|
||||||
case 4: // segment only, no displacement
|
case 4: // segment only, no displacement
|
||||||
state.targetState = state.header.resolveSegment(index).getStartAddress();
|
state.targetState = state.header.resolveSegment(index).getStartAddress();
|
||||||
break;
|
break;
|
||||||
case 5: // group only, no displacement
|
case 5: // group only, no displacement
|
||||||
state.targetState = state.groups.get(index-1).getStartAddress();
|
state.targetState = state.groups.get(index - 1).getStartAddress();
|
||||||
break;
|
break;
|
||||||
case 6: // external only, no displacement
|
case 6: // external only, no displacement
|
||||||
state.targetState = state.externals.get(index-1).getAddress().getOffset();
|
state.targetState = state.externals.get(index - 1).getAddress().getOffset();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state.targetState = -1; // This indicates an unresolved target
|
state.targetState = -1; // This indicates an unresolved target
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FixupTarget readFixupTarget(BinaryReader reader,boolean hasBigFields) throws IOException {
|
public static FixupTarget readFixupTarget(BinaryReader reader, boolean hasBigFields)
|
||||||
|
throws IOException {
|
||||||
FixupTarget fixupTarget = new FixupTarget();
|
FixupTarget fixupTarget = new FixupTarget();
|
||||||
fixupTarget.fixData = reader.readNextByte();
|
fixupTarget.fixData = reader.readNextByte();
|
||||||
if ((fixupTarget.fixData & 0x80)==0) { // F=0 (explicit frame method (and datum))
|
if ((fixupTarget.fixData & 0x80) == 0) { // F=0 (explicit frame method (and datum))
|
||||||
int method = (fixupTarget.fixData >> 4)&7;
|
int method = (fixupTarget.fixData >> 4) & 7;
|
||||||
if (method <3) {
|
if (method < 3) {
|
||||||
fixupTarget.frameDatum = OmfRecord.readIndex(reader);
|
fixupTarget.frameDatum = OmfRecord.readIndex(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((fixupTarget.fixData & 0x08)==0) { // T=0 (explicit target)
|
if ((fixupTarget.fixData & 0x08) == 0) { // T=0 (explicit target)
|
||||||
fixupTarget.targetDatum = OmfRecord.readIndex(reader);
|
fixupTarget.targetDatum = OmfRecord.readIndex(reader);
|
||||||
}
|
}
|
||||||
if ((fixupTarget.fixData & 0x04)==0) // P=0
|
if ((fixupTarget.fixData & 0x04) == 0) // P=0
|
||||||
fixupTarget.targetDisplacement = OmfRecord.readInt2Or4(reader, hasBigFields);
|
fixupTarget.targetDisplacement = OmfRecord.readInt2Or4(reader, hasBigFields);
|
||||||
return fixupTarget;
|
return fixupTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FixupSubrecord extends Subrecord {
|
public static class FixupSubrecord extends Subrecord {
|
||||||
private byte lobyte; // lo-byte of location
|
private byte lobyte; // lo-byte of location
|
||||||
private byte hibyte; // hi-byte of location
|
private byte hibyte; // hi-byte of location
|
||||||
private FixupTarget target;
|
private FixupTarget target;
|
||||||
|
|
||||||
public FixupSubrecord() {
|
public FixupSubrecord() {
|
||||||
super(false);
|
super(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveFixup(FixupState state) throws OmfException {
|
public void resolveFixup(FixupState state) throws OmfException {
|
||||||
|
|
||||||
target.resolveTarget(state); // Resolve target first as frame may need to reference results
|
target.resolveTarget(state); // Resolve target first as frame may need to reference results
|
||||||
target.resolveFrame(state);
|
target.resolveFrame(state);
|
||||||
state.M = ((lobyte>>6)&1)!=0;
|
state.M = ((lobyte >> 6) & 1) != 0;
|
||||||
state.locationType = ((lobyte>>2)&0xf);
|
state.locationType = ((lobyte >> 2) & 0xf);
|
||||||
int dataRecordOffset = lobyte & 3;
|
int dataRecordOffset = lobyte & 3;
|
||||||
dataRecordOffset <<= 8;
|
dataRecordOffset <<= 8;
|
||||||
dataRecordOffset |= (hibyte) & 0xff;
|
dataRecordOffset |= (hibyte) & 0xff;
|
||||||
|
@ -305,15 +313,16 @@ public class OmfFixupRecord extends OmfRecord {
|
||||||
segIndex = state.currentFixupRecord.lastLIData.getSegmentIndex();
|
segIndex = state.currentFixupRecord.lastLIData.getSegmentIndex();
|
||||||
}
|
}
|
||||||
OmfSegmentHeader seg = state.header.resolveSegment(segIndex);
|
OmfSegmentHeader seg = state.header.resolveSegment(segIndex);
|
||||||
state.locAddress = seg.getAddress(state.language).add(blockDisplace + dataRecordOffset);
|
state.locAddress = seg.getAddress(state.language).add(blockDisplace + dataRecordOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FixupSubrecord readFixupSubrecord(BinaryReader reader,boolean hasBigFields) throws IOException {
|
public static FixupSubrecord readFixupSubrecord(BinaryReader reader, boolean hasBigFields)
|
||||||
|
throws IOException {
|
||||||
FixupSubrecord fixupSubrecord = new FixupSubrecord();
|
FixupSubrecord fixupSubrecord = new FixupSubrecord();
|
||||||
fixupSubrecord.lobyte = reader.readNextByte();
|
fixupSubrecord.lobyte = reader.readNextByte();
|
||||||
fixupSubrecord.hibyte = reader.readNextByte();
|
fixupSubrecord.hibyte = reader.readNextByte();
|
||||||
fixupSubrecord.target = FixupTarget.readFixupTarget(reader, hasBigFields);
|
fixupSubrecord.target = FixupTarget.readFixupTarget(reader, hasBigFields);
|
||||||
return fixupSubrecord;
|
return fixupSubrecord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -29,21 +28,21 @@ public class OmfGroupRecord extends OmfRecord {
|
||||||
private String groupName;
|
private String groupName;
|
||||||
private long vma = -1; // Assigned (by linker) starting address of the whole group
|
private long vma = -1; // Assigned (by linker) starting address of the whole group
|
||||||
private GroupSubrecord[] group;
|
private GroupSubrecord[] group;
|
||||||
|
|
||||||
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 = OmfRecord.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);
|
||||||
grouplist.add(subrec);
|
grouplist.add(subrec);
|
||||||
}
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
group = new GroupSubrecord[ grouplist.size() ];
|
group = new GroupSubrecord[grouplist.size()];
|
||||||
grouplist.toArray(group);
|
grouplist.toArray(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return groupName;
|
return groupName;
|
||||||
}
|
}
|
||||||
|
@ -51,48 +50,50 @@ public class OmfGroupRecord extends OmfRecord {
|
||||||
public void setStartAddress(long val) {
|
public void setStartAddress(long val) {
|
||||||
vma = val;
|
vma = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getStartAddress() {
|
public long getStartAddress() {
|
||||||
return vma;
|
return vma;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the segment selector needed for this object
|
* This is the segment selector needed for this object
|
||||||
* @return
|
* @return The segment selector
|
||||||
*/
|
*/
|
||||||
public int getFrameDatum() {
|
public int getFrameDatum() {
|
||||||
return 0; // TODO: Need to fill in a real segment selector
|
return 0; // TODO: Need to fill in a real segment selector
|
||||||
}
|
}
|
||||||
|
|
||||||
public int numSegments() {
|
public int numSegments() {
|
||||||
return group.length;
|
return group.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getSegmentComponentType(int i) {
|
public byte getSegmentComponentType(int i) {
|
||||||
return group[i].componentType;
|
return group[i].componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSegmentIndex(int i) {
|
public int getSegmentIndex(int i) {
|
||||||
return group[i].segmentIndex;
|
return group[i].segmentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address getAddress(Language language) {
|
public Address getAddress(Language language) {
|
||||||
AddressSpace addrSpace = language.getDefaultSpace();
|
AddressSpace addrSpace = language.getDefaultSpace();
|
||||||
return addrSpace.getAddress(vma);
|
return addrSpace.getAddress(vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveNames(ArrayList<String> nameList) throws OmfException {
|
public void resolveNames(ArrayList<String> nameList) throws OmfException {
|
||||||
if (groupNameIndex <= 0)
|
if (groupNameIndex <= 0) {
|
||||||
throw new OmfException("Cannot have unused group name");
|
throw new OmfException("Cannot have unused group name");
|
||||||
if (groupNameIndex > nameList.size())
|
}
|
||||||
|
if (groupNameIndex > nameList.size()) {
|
||||||
throw new OmfException("Group name index out of bounds");
|
throw new OmfException("Group name index out of bounds");
|
||||||
|
}
|
||||||
groupName = nameList.get(groupNameIndex - 1);
|
groupName = nameList.get(groupNameIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GroupSubrecord {
|
public static class GroupSubrecord {
|
||||||
private byte componentType;
|
private byte componentType;
|
||||||
private int segmentIndex;
|
private int segmentIndex;
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class OmfIteratedData extends OmfRecord implements OmfData {
|
||||||
segmentIndex = OmfRecord.readIndex(reader);
|
segmentIndex = OmfRecord.readIndex(reader);
|
||||||
dataOffset = OmfRecord.readInt2Or4(reader, hasBigFields);
|
dataOffset = OmfRecord.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);
|
||||||
blocklist.add(block);
|
blocklist.add(block);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public class OmfIteratedData extends OmfRecord implements OmfData {
|
||||||
datablock = new DataBlock[blocklist.size()];
|
datablock = new DataBlock[blocklist.size()];
|
||||||
blocklist.toArray(datablock);
|
blocklist.toArray(datablock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSegmentIndex() {
|
public int getSegmentIndex() {
|
||||||
return segmentIndex;
|
return segmentIndex;
|
||||||
}
|
}
|
||||||
|
@ -99,22 +99,22 @@ public class OmfIteratedData extends OmfRecord implements OmfData {
|
||||||
private int blockCount;
|
private int blockCount;
|
||||||
private byte[] simpleBlock = null;
|
private byte[] simpleBlock = null;
|
||||||
private DataBlock[] nestedBlock = null;
|
private DataBlock[] nestedBlock = null;
|
||||||
|
|
||||||
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 = OmfRecord.readInt2Or4(reader, hasBigFields);
|
||||||
subblock.blockCount = reader.readNextShort() & 0xffff;
|
subblock.blockCount = reader.readNextShort() & 0xffff;
|
||||||
if (subblock.blockCount == 0) {
|
if (subblock.blockCount == 0) {
|
||||||
int size = reader.readNextByte() & 0xff;
|
int size = reader.readNextByte() & 0xff;
|
||||||
subblock.simpleBlock = new byte[ size ];
|
subblock.simpleBlock = new byte[size];
|
||||||
for(int i=0;i<size;++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
subblock.simpleBlock[i] = reader.readNextByte();
|
subblock.simpleBlock[i] = reader.readNextByte();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subblock.nestedBlock = new DataBlock[subblock.blockCount];
|
subblock.nestedBlock = new DataBlock[subblock.blockCount];
|
||||||
for(int i=0;i<subblock.blockCount;++i) {
|
for (int i = 0; i < subblock.blockCount; ++i) {
|
||||||
subblock.nestedBlock[i] = read(reader,hasBigFields); // Recursive definition
|
subblock.nestedBlock[i] = read(reader, hasBigFields); // Recursive definition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return subblock;
|
return subblock;
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.omf;
|
package ghidra.app.util.bin.format.omf;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
|
||||||
import ghidra.util.task.TaskMonitor;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -35,7 +35,7 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||||
public String translator;
|
public String translator;
|
||||||
public String machineName;
|
public String machineName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OmfLibraryRecord(BinaryReader reader) throws IOException {
|
public OmfLibraryRecord(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
pageSize = recordLength + 3;
|
pageSize = recordLength + 3;
|
||||||
|
@ -44,62 +44,75 @@ public class OmfLibraryRecord extends OmfRecord {
|
||||||
flags = reader.readNextByte();
|
flags = reader.readNextByte();
|
||||||
// No checksum byte (just padding)
|
// No checksum byte (just padding)
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPageSize() {
|
public int getPageSize() {
|
||||||
return pageSize;
|
return pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<MemberHeader> getMemberHeaders() {
|
public ArrayList<MemberHeader> getMemberHeaders() {
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkMagicNumer(BinaryReader reader) throws IOException {
|
public static boolean checkMagicNumer(BinaryReader reader) throws IOException {
|
||||||
byte type = reader.readNextByte();
|
byte type = reader.readNextByte();
|
||||||
if (type != (byte)0xF0)
|
if (type != (byte) 0xF0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int pageSize = (reader.readNextShort() & 0xffff) + 3;
|
int pageSize = (reader.readNextShort() & 0xffff) + 3;
|
||||||
// Make sure page size is a power of 2, 2^4 - 2^15
|
// Make sure page size is a power of 2, 2^4 - 2^15
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int mask = pageSize;
|
int mask = pageSize;
|
||||||
while((mask & 1)==0) {
|
while ((mask & 1) == 0) {
|
||||||
count += 1;
|
count += 1;
|
||||||
mask >>>= 1;
|
mask >>>= 1;
|
||||||
}
|
}
|
||||||
if (mask != 1) return false; // Test if this is a power of 2
|
if (mask != 1) {
|
||||||
if (count < 4) return false;
|
return false; // Test if this is a power of 2
|
||||||
if (count > 15) return false;
|
}
|
||||||
|
if (count < 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (count > 15) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
reader.align(pageSize);
|
reader.align(pageSize);
|
||||||
type = reader.readNextByte();
|
type = reader.readNextByte();
|
||||||
if ((type & 0xfc) != 0x80) return false;
|
if ((type & 0xfc) != 0x80) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OmfLibraryRecord parse(BinaryReader reader,TaskMonitor monitor) throws IOException {
|
public static OmfLibraryRecord parse(BinaryReader reader, TaskMonitor monitor)
|
||||||
|
throws IOException {
|
||||||
OmfLibraryRecord res = null;
|
OmfLibraryRecord res = null;
|
||||||
byte type = reader.peekNextByte();
|
byte type = reader.peekNextByte();
|
||||||
if (type != (byte)0xF0)
|
if (type != (byte) 0xF0) {
|
||||||
throw new IOException("Not an OMF Library record");
|
throw new IOException("Not an OMF Library record");
|
||||||
|
}
|
||||||
res = new OmfLibraryRecord(reader);
|
res = new OmfLibraryRecord(reader);
|
||||||
res.members = new ArrayList<MemberHeader>();
|
res.members = new ArrayList<MemberHeader>();
|
||||||
reader.align(res.pageSize); // Skip padding to get to next page boundary
|
reader.align(res.pageSize); // Skip padding to get to next page boundary
|
||||||
type = reader.peekNextByte();
|
type = reader.peekNextByte();
|
||||||
while(type != (byte)0xF1) { // Until we see the official "end of library" record
|
while (type != (byte) 0xF1) { // Until we see the official "end of library" record
|
||||||
MemberHeader curheader = new MemberHeader();
|
MemberHeader curheader = new MemberHeader();
|
||||||
curheader.payloadOffset = reader.getPointerIndex();
|
curheader.payloadOffset = reader.getPointerIndex();
|
||||||
OmfFileHeader fileheader;
|
OmfFileHeader fileheader;
|
||||||
try {
|
try {
|
||||||
fileheader = OmfFileHeader.scan(reader, monitor,false);
|
fileheader = OmfFileHeader.scan(reader, monitor, false);
|
||||||
} catch (OmfException e) {
|
}
|
||||||
|
catch (OmfException e) {
|
||||||
throw new IOException("Could not parse individual object file within archive");
|
throw new IOException("Could not parse individual object file within archive");
|
||||||
}
|
}
|
||||||
curheader.name = fileheader.getLibraryModuleName(); // (preferred) name of the object module
|
curheader.name = fileheader.getLibraryModuleName(); // (preferred) name of the object module
|
||||||
if (curheader.name == null)
|
if (curheader.name == null) {
|
||||||
curheader.name = fileheader.getName(); // As a back-up, this is usually the name of the original source
|
curheader.name = fileheader.getName(); // As a back-up, this is usually the name of the original source
|
||||||
|
}
|
||||||
curheader.machineName = fileheader.getMachineName();
|
curheader.machineName = fileheader.getMachineName();
|
||||||
curheader.translator = fileheader.getTranslator();
|
curheader.translator = fileheader.getTranslator();
|
||||||
curheader.size = (int)(reader.getPointerIndex() - curheader.payloadOffset);
|
curheader.size = (int) (reader.getPointerIndex() - curheader.payloadOffset);
|
||||||
res.members.add(curheader);
|
res.members.add(curheader);
|
||||||
reader.align(res.pageSize); // Skip padding to get to next page boundary
|
reader.align(res.pageSize); // Skip padding to get to next page boundary
|
||||||
type = reader.peekNextByte();
|
type = reader.peekNextByte();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.app.util.bin.format.omf;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
|
||||||
|
|
||||||
public class OmfLineNumberRecord extends OmfRecord {
|
|
||||||
private int baseGroup;
|
|
||||||
private int baseSegment;
|
|
||||||
private LineSubrecord[] linenumber;
|
|
||||||
|
|
||||||
public OmfLineNumberRecord(BinaryReader reader) throws IOException {
|
|
||||||
readRecordHeader(reader);
|
|
||||||
boolean hasBigFields = hasBigFields();
|
|
||||||
baseGroup = OmfRecord.readIndex(reader);
|
|
||||||
baseSegment = OmfRecord.readIndex(reader);
|
|
||||||
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
|
||||||
ArrayList<LineSubrecord> linelist = new ArrayList<LineSubrecord>();
|
|
||||||
while(reader.getPointerIndex() < max) {
|
|
||||||
LineSubrecord subrec = LineSubrecord.read(reader,hasBigFields);
|
|
||||||
linelist.add(subrec);
|
|
||||||
}
|
|
||||||
readCheckSumByte(reader);
|
|
||||||
linenumber = new LineSubrecord[linelist.size()];
|
|
||||||
linelist.toArray(linenumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class LineSubrecord {
|
|
||||||
private int lineNumber;
|
|
||||||
private int lineNumberOffset;
|
|
||||||
|
|
||||||
public static LineSubrecord read(BinaryReader reader,boolean hasBigFields) throws IOException {
|
|
||||||
LineSubrecord subrec = new LineSubrecord();
|
|
||||||
subrec.lineNumber = reader.readNextShort() & 0xffff;
|
|
||||||
subrec.lineNumberOffset = OmfRecord.readInt2Or4(reader, hasBigFields);
|
|
||||||
return subrec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,20 +22,21 @@ import ghidra.app.util.bin.BinaryReader;
|
||||||
public class OmfModuleEnd extends OmfRecord {
|
public class OmfModuleEnd extends OmfRecord {
|
||||||
private byte moduleType;
|
private byte moduleType;
|
||||||
private OmfFixupRecord.FixupTarget startAddress;
|
private OmfFixupRecord.FixupTarget startAddress;
|
||||||
|
|
||||||
public OmfModuleEnd(BinaryReader reader) throws IOException {
|
public OmfModuleEnd(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
moduleType = reader.readNextByte();
|
moduleType = reader.readNextByte();
|
||||||
if (hasStartAddress())
|
if (hasStartAddress()) {
|
||||||
startAddress = OmfFixupRecord.FixupTarget.readFixupTarget(reader,hasBigFields());
|
startAddress = OmfFixupRecord.FixupTarget.readFixupTarget(reader, hasBigFields());
|
||||||
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMainProgramModule() {
|
public boolean isMainProgramModule() {
|
||||||
return ((moduleType & 0x80)!=0);
|
return ((moduleType & 0x80) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasStartAddress() {
|
public boolean hasStartAddress() {
|
||||||
return ((moduleType & 0x40)!=0);
|
return ((moduleType & 0x40) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,18 +22,18 @@ import ghidra.app.util.bin.BinaryReader;
|
||||||
|
|
||||||
public class OmfNamesRecord extends OmfRecord {
|
public class OmfNamesRecord extends OmfRecord {
|
||||||
private ArrayList<String> name;
|
private ArrayList<String> name;
|
||||||
|
|
||||||
public OmfNamesRecord(BinaryReader reader) throws IOException {
|
public OmfNamesRecord(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
long max = reader.getPointerIndex() + getRecordLength() -1;
|
long max = reader.getPointerIndex() + getRecordLength() - 1;
|
||||||
name = new ArrayList<String>();
|
name = new ArrayList<String>();
|
||||||
while(reader.getPointerIndex() < max) {
|
while (reader.getPointerIndex() < max) {
|
||||||
String nm = OmfRecord.readString(reader);
|
String nm = OmfRecord.readString(reader);
|
||||||
name.add(nm);
|
name.add(nm);
|
||||||
}
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendNames(ArrayList<String> namelist) {
|
public void appendNames(ArrayList<String> namelist) {
|
||||||
namelist.addAll(name);
|
namelist.addAll(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* ###
|
||||||
|
* 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.BinaryReader;
|
||||||
|
|
||||||
|
public class OmfObsoleteRecord extends OmfRecord {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link OmfObsoleteRecord}
|
||||||
|
*
|
||||||
|
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||||
|
* @throws IOException If an IO-related error occurred
|
||||||
|
*/
|
||||||
|
public OmfObsoleteRecord(BinaryReader reader) throws IOException {
|
||||||
|
readRecordHeader(reader);
|
||||||
|
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,156 +16,236 @@
|
||||||
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;
|
||||||
|
|
||||||
public abstract class OmfRecord {
|
public abstract class OmfRecord {
|
||||||
public final static byte THEADR = (byte)0x80;
|
public final static byte RHEADR = (byte) 0x6E; // Obsolete
|
||||||
public final static byte LHEADR = (byte)0x82;
|
public final static byte REGINT = (byte) 0x70; // Obsolete
|
||||||
public final static byte COMENT = (byte)0x88;
|
public final static byte REDATA = (byte) 0x72; // Obsolete
|
||||||
public final static byte MODEND = (byte)0x8A;
|
public final static byte RIDATA = (byte) 0x74; // Obsolete
|
||||||
public final static byte EXTDEF = (byte)0x8C;
|
public final static byte OVLDEF = (byte) 0x76; // Obsolete
|
||||||
public final static byte PUBDEF = (byte)0x90;
|
public final static byte ENDREC = (byte) 0x78; // Obsolete
|
||||||
public final static byte LINNUM = (byte)0x94;
|
public final static byte BLKDEF = (byte) 0x7A; // Obsolete
|
||||||
public final static byte LNAMES = (byte)0x96;
|
public final static byte BLKEND = (byte) 0x7C; // Obsolete
|
||||||
public final static byte SEGDEF = (byte)0x98;
|
public final static byte DEBSYM = (byte) 0x7E; // Obsolete
|
||||||
public final static byte GRPDEF = (byte)0x9A;
|
public final static byte THEADR = (byte) 0x80;
|
||||||
public final static byte FIXUPP = (byte)0x9C;
|
public final static byte LHEADR = (byte) 0x82;
|
||||||
public final static byte LEDATA = (byte)0xA0;
|
public final static byte PEDATA = (byte) 0x84; // Obsolete
|
||||||
public final static byte LIDATA = (byte)0xA2;
|
public final static byte PIDATA = (byte) 0x86; // Obsolete
|
||||||
public final static byte COMDEF = (byte)0xB0;
|
public final static byte COMENT = (byte) 0x88;
|
||||||
public final static byte LEXTDEF = (byte)0xB4;
|
public final static byte MODEND = (byte) 0x8A;
|
||||||
public final static byte LPUBDEF = (byte)0xB6;
|
public final static byte EXTDEF = (byte) 0x8C;
|
||||||
public final static byte LCOMDEF = (byte)0xB8;
|
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 byte recordType;
|
protected byte recordType;
|
||||||
protected int recordLength;
|
protected int recordLength;
|
||||||
|
protected long recordOffset;
|
||||||
protected byte checkSum;
|
protected byte checkSum;
|
||||||
|
|
||||||
public byte getRecordType() {
|
public byte getRecordType() {
|
||||||
return recordType;
|
return recordType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRecordLength() {
|
public int getRecordLength() {
|
||||||
return recordLength;
|
return recordLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getRecordOffset() {
|
||||||
|
return recordOffset;
|
||||||
|
}
|
||||||
|
|
||||||
public void readRecordHeader(BinaryReader reader) throws IOException {
|
public void readRecordHeader(BinaryReader reader) throws IOException {
|
||||||
|
recordOffset = reader.getPointerIndex();
|
||||||
recordType = reader.readNextByte();
|
recordType = reader.readNextByte();
|
||||||
recordLength = reader.readNextShort() & 0xffff;
|
recordLength = reader.readNextShort() & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readCheckSumByte(BinaryReader reader) throws IOException {
|
public void readCheckSumByte(BinaryReader reader) throws IOException {
|
||||||
checkSum = reader.readNextByte();
|
checkSum = reader.readNextByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validCheckSum(BinaryReader reader) throws IOException {
|
public boolean validCheckSum(BinaryReader reader) throws IOException {
|
||||||
if (checkSum == 0) return true; // Sum compilers just set this to zero
|
if (checkSum == 0)
|
||||||
|
return true; // Sum compilers just set this to zero
|
||||||
return (calcCheckSum(reader) == 0);
|
return (calcCheckSum(reader) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBigFields() {
|
public boolean hasBigFields() {
|
||||||
return ((recordType & 1)!=0);
|
return ((recordType & 1) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readInt1Or2(BinaryReader reader,boolean isBig) throws IOException {
|
public static int readInt1Or2(BinaryReader reader, boolean isBig) throws IOException {
|
||||||
if (isBig)
|
if (isBig)
|
||||||
return (reader.readNextShort() & 0xffff);
|
return (reader.readNextShort() & 0xffff);
|
||||||
return (reader.readNextByte() & 0xff);
|
return (reader.readNextByte() & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readInt2Or4(BinaryReader reader,boolean isBig) throws IOException {
|
public static int readInt2Or4(BinaryReader reader, boolean isBig) throws IOException {
|
||||||
if (isBig)
|
if (isBig)
|
||||||
return reader.readNextInt();
|
return reader.readNextInt();
|
||||||
return (reader.readNextShort() & 0xffff);
|
return (reader.readNextShort() & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readIndex(BinaryReader reader) throws IOException {
|
public static int readIndex(BinaryReader reader) throws IOException {
|
||||||
int indexWord;
|
int indexWord;
|
||||||
byte firstByte = reader.readNextByte();
|
byte firstByte = reader.readNextByte();
|
||||||
if ((firstByte & 0x80)!=0)
|
if ((firstByte & 0x80) != 0) {
|
||||||
indexWord = (firstByte & 0x7f) * 0x100 + (reader.readNextByte() & 0xff);
|
indexWord = (firstByte & 0x7f) * 0x100 + (reader.readNextByte() & 0xff);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
indexWord = firstByte;
|
indexWord = firstByte;
|
||||||
|
}
|
||||||
return indexWord;
|
return indexWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
|
public static OmfRecord readRecord(BinaryReader reader) throws IOException, OmfException {
|
||||||
OmfRecord res = null;
|
|
||||||
byte type = reader.peekNextByte();
|
byte type = reader.peekNextByte();
|
||||||
type &= 0xfe; // Mask off the least significant bit
|
type &= 0xfe; // Mask off the least significant bit (16/32 bit flag)
|
||||||
switch(type) {
|
return switch (type) {
|
||||||
case THEADR:
|
case THEADR:
|
||||||
case LHEADR:
|
case LHEADR:
|
||||||
res = new OmfFileHeader(reader);
|
yield new OmfFileHeader(reader);
|
||||||
break;
|
case COMENT:
|
||||||
case COMENT:
|
yield new OmfCommentRecord(reader);
|
||||||
res = new OmfCommentRecord(reader);
|
case MODEND:
|
||||||
break;
|
yield new OmfModuleEnd(reader);
|
||||||
case MODEND:
|
case EXTDEF:
|
||||||
res = new OmfModuleEnd(reader);
|
yield new OmfExternalSymbol(reader, false);
|
||||||
break;
|
case PUBDEF:
|
||||||
case EXTDEF:
|
yield new OmfSymbolRecord(reader, false);
|
||||||
res = new OmfExternalSymbol(reader,false);
|
case LNAMES:
|
||||||
break;
|
yield new OmfNamesRecord(reader);
|
||||||
case PUBDEF:
|
case SEGDEF:
|
||||||
res = new OmfSymbolRecord(reader,false);
|
yield new OmfSegmentHeader(reader);
|
||||||
break;
|
case GRPDEF:
|
||||||
case LINNUM:
|
yield new OmfGroupRecord(reader);
|
||||||
res = new OmfLineNumberRecord(reader);
|
case FIXUPP:
|
||||||
break;
|
yield new OmfFixupRecord(reader);
|
||||||
case LNAMES:
|
case LEDATA:
|
||||||
res = new OmfNamesRecord(reader);
|
yield new OmfEnumeratedData(reader);
|
||||||
break;
|
case LIDATA:
|
||||||
case SEGDEF:
|
yield new OmfIteratedData(reader);
|
||||||
res = new OmfSegmentHeader(reader);
|
case COMDEF:
|
||||||
break;
|
yield new OmfComdefRecord(reader, false);
|
||||||
case GRPDEF:
|
case LEXTDEF:
|
||||||
res = new OmfGroupRecord(reader);
|
yield new OmfExternalSymbol(reader, true);
|
||||||
break;
|
case LPUBDEF:
|
||||||
case FIXUPP:
|
yield new OmfSymbolRecord(reader, true);
|
||||||
res = new OmfFixupRecord(reader);
|
case LCOMDEF:
|
||||||
break;
|
yield new OmfComdefRecord(reader, true);
|
||||||
case LEDATA:
|
case RHEADR:
|
||||||
res = new OmfEnumeratedData(reader);
|
case REGINT:
|
||||||
break;
|
case REDATA:
|
||||||
case LIDATA:
|
case RIDATA:
|
||||||
res = new OmfIteratedData(reader);
|
case OVLDEF:
|
||||||
break;
|
case ENDREC:
|
||||||
case COMDEF:
|
case BLKDEF:
|
||||||
res = new OmfComdefRecord(reader,false);
|
case BLKEND:
|
||||||
break;
|
case DEBSYM:
|
||||||
case LEXTDEF:
|
case LINNUM:
|
||||||
res = new OmfExternalSymbol(reader,true);
|
case PEDATA:
|
||||||
break;
|
case PIDATA:
|
||||||
case LPUBDEF:
|
case LIBHED:
|
||||||
res = new OmfSymbolRecord(reader,true);
|
case LIBNAM:
|
||||||
break;
|
case LIBLOC:
|
||||||
case LCOMDEF:
|
case LIBDIC:
|
||||||
res = new OmfComdefRecord(reader,true);
|
yield new OmfObsoleteRecord(reader);
|
||||||
break;
|
case LOCSYM:
|
||||||
default:
|
case TYPDEF:
|
||||||
throw new OmfException("Unrecognized record type");
|
case CEXTDEF:
|
||||||
}
|
case COMDAT:
|
||||||
return res;
|
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
|
* Read the OMF string format: 1-byte length, followed by that many ascii characters
|
||||||
* @param reader
|
*
|
||||||
* @return
|
* @param reader A {@link BinaryReader} positioned at the start of the string
|
||||||
* @throws IOException
|
* @return the read OMF string
|
||||||
|
* @throws IOException if an IO-related error occurred
|
||||||
*/
|
*/
|
||||||
public static String readString(BinaryReader reader) throws IOException {
|
public static String readString(BinaryReader reader) throws IOException {
|
||||||
int count = reader.readNextByte() & 0xff;
|
int count = reader.readNextByte() & 0xff;
|
||||||
return reader.readNextAsciiString(count);
|
return 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
|
||||||
|
public String toString() {
|
||||||
|
return String.format("name: %s, type: 0x%x, offset: 0x%x, length: 0x%x",
|
||||||
|
getRecordName(recordType), recordType, recordOffset, recordLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
private long vma = -1; // assigned (by linker) starting address of segment -1 means unset
|
private long vma = -1; // assigned (by linker) starting address of segment -1 means unset
|
||||||
private ArrayList<OmfData> dataBlocks = new ArrayList<OmfData>();
|
private ArrayList<OmfData> dataBlocks = new ArrayList<OmfData>();
|
||||||
|
|
||||||
OmfSegmentHeader(int num,int datatype) {
|
OmfSegmentHeader(int num, int datatype) {
|
||||||
// generate a special Borland header
|
// generate a special Borland header
|
||||||
segAttr = (byte)0xa9;
|
segAttr = (byte) 0xa9;
|
||||||
segmentLength = 0;
|
segmentLength = 0;
|
||||||
segmentNameIndex = 0;
|
segmentNameIndex = 0;
|
||||||
classNameIndex = 0;
|
classNameIndex = 0;
|
||||||
|
@ -62,7 +62,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
else {
|
else {
|
||||||
segmentName = "EXTRA_";
|
segmentName = "EXTRA_";
|
||||||
}
|
}
|
||||||
segmentName = segmentName+Integer.toString(num);
|
segmentName = segmentName + Integer.toString(num);
|
||||||
if (datatype == 1) {
|
if (datatype == 1) {
|
||||||
// Treat as a text segment
|
// Treat as a text segment
|
||||||
className = "TEXT";
|
className = "TEXT";
|
||||||
|
@ -79,7 +79,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
isExecutable = false;
|
isExecutable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OmfSegmentHeader(BinaryReader reader) throws IOException {
|
public OmfSegmentHeader(BinaryReader reader) throws IOException {
|
||||||
readRecordHeader(reader);
|
readRecordHeader(reader);
|
||||||
boolean hasBigFields = hasBigFields();
|
boolean hasBigFields = hasBigFields();
|
||||||
|
@ -88,15 +88,15 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
if (A == 0) {
|
if (A == 0) {
|
||||||
frameNumber = reader.readNextShort() & 0xffff;
|
frameNumber = reader.readNextShort() & 0xffff;
|
||||||
offset = reader.readNextByte() & 0xff;
|
offset = reader.readNextByte() & 0xff;
|
||||||
vma = (long)frameNumber + offset;
|
vma = (long) frameNumber + offset;
|
||||||
}
|
}
|
||||||
segmentLength = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
segmentLength = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
||||||
segmentNameIndex = OmfRecord.readIndex(reader);
|
segmentNameIndex = OmfRecord.readIndex(reader);
|
||||||
classNameIndex = OmfRecord.readIndex(reader);
|
classNameIndex = OmfRecord.readIndex(reader);
|
||||||
overlayNameIndex = OmfRecord.readIndex(reader);
|
overlayNameIndex = OmfRecord.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() == OmfRecord.SEGDEF) {
|
||||||
segmentLength = 0x10000L; // Exactly 64K segment
|
segmentLength = 0x10000L; // Exactly 64K segment
|
||||||
}
|
}
|
||||||
|
@ -105,28 +105,28 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this is a code segment
|
* @return true if this is a code segment
|
||||||
*/
|
*/
|
||||||
public boolean isCode() {
|
public boolean isCode() {
|
||||||
return isCode;
|
return isCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this segment is readable
|
* @return true if this segment is readable
|
||||||
*/
|
*/
|
||||||
public boolean isReadable() {
|
public boolean isReadable() {
|
||||||
return isReadable;
|
return isReadable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this segment is writable
|
* @return true if this segment is writable
|
||||||
*/
|
*/
|
||||||
public boolean isWritable() {
|
public boolean isWritable() {
|
||||||
return isWritable;
|
return isWritable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this segment is executable
|
* @return true if this segment is executable
|
||||||
*/
|
*/
|
||||||
|
@ -140,7 +140,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
public int getFrameDatum() {
|
public int getFrameDatum() {
|
||||||
return 0; // TODO: Need to fill in a real segment selector
|
return 0; // TODO: Need to fill in a real segment selector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param language is the Program language for this binary
|
* @param language is the Program language for this binary
|
||||||
* @return the starting Address for this segment
|
* @return the starting Address for this segment
|
||||||
|
@ -150,26 +150,27 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
|
|
||||||
if (isCode) {
|
if (isCode) {
|
||||||
addrSpace = language.getDefaultSpace();
|
addrSpace = language.getDefaultSpace();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
addrSpace = language.getDefaultDataSpace();
|
addrSpace = language.getDefaultDataSpace();
|
||||||
}
|
}
|
||||||
return addrSpace.getAddress(vma);
|
return addrSpace.getAddress(vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the name of this segment
|
* @return the name of this segment
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return segmentName;
|
return segmentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the class name of this segment
|
* @return the class name of this segment
|
||||||
*/
|
*/
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the name of the overlay, or the empty string
|
* @return the name of the overlay, or the empty string
|
||||||
*/
|
*/
|
||||||
|
@ -183,21 +184,21 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
public long getStartAddress() {
|
public long getStartAddress() {
|
||||||
return vma;
|
return vma;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the length of the segment in bytes
|
* @return the length of the segment in bytes
|
||||||
*/
|
*/
|
||||||
public long getSegmentLength() {
|
public long getSegmentLength() {
|
||||||
return segmentLength;
|
return segmentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the alignment required for this segment
|
* @return the alignment required for this segment
|
||||||
*/
|
*/
|
||||||
public int getAlignment() {
|
public int getAlignment() {
|
||||||
return (segAttr >> 5) & 0x7;
|
return (segAttr >> 5) & 0x7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return special combining rules for this segment
|
* @return special combining rules for this segment
|
||||||
*/
|
*/
|
||||||
|
@ -223,7 +224,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
protected void sortData() {
|
protected void sortData() {
|
||||||
Collections.sort(dataBlocks);
|
Collections.sort(dataBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an InputStream that reads in the raw data for this segment
|
* Get an InputStream that reads in the raw data for this segment
|
||||||
* @param reader is the image file reader
|
* @param reader is the image file reader
|
||||||
|
@ -234,7 +235,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
public InputStream getRawDataStream(BinaryReader reader, MessageLog log) throws IOException {
|
public InputStream getRawDataStream(BinaryReader reader, MessageLog log) throws IOException {
|
||||||
return new SectionStream(reader, log);
|
return new SectionStream(reader, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the first possible address where this segment can reside, relocate the
|
* Given the first possible address where this segment can reside, relocate the
|
||||||
* segment based on this address and alignment considerations.
|
* segment based on this address and alignment considerations.
|
||||||
|
@ -244,35 +245,35 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
* @throws OmfException for bad alignment information
|
* @throws OmfException for bad alignment information
|
||||||
*/
|
*/
|
||||||
protected long relocateSegment(long firstValidAddress, int alignOverride) throws OmfException {
|
protected long relocateSegment(long firstValidAddress, int alignOverride) throws OmfException {
|
||||||
int align = getAlignment();
|
int align = getAlignment();
|
||||||
if (alignOverride >= 0) {
|
if (alignOverride >= 0) {
|
||||||
align = alignOverride;
|
align = alignOverride;
|
||||||
}
|
}
|
||||||
switch(align) {
|
switch (align) {
|
||||||
case 0: // Absolute segment, not relocatable
|
case 0: // Absolute segment, not relocatable
|
||||||
throw new OmfException("Trying to relocate an absolute segment");
|
throw new OmfException("Trying to relocate an absolute segment");
|
||||||
case 1: // Byte aligned
|
case 1: // Byte aligned
|
||||||
break; // Keep the first valid address
|
break; // Keep the first valid address
|
||||||
case 2: // 2-byte aligned
|
case 2: // 2-byte aligned
|
||||||
firstValidAddress = (firstValidAddress+1 ) & 0xfffffffffffffffeL;
|
firstValidAddress = (firstValidAddress + 1) & 0xfffffffffffffffeL;
|
||||||
break;
|
break;
|
||||||
case 3: // 16-byte aligned
|
case 3: // 16-byte aligned
|
||||||
firstValidAddress = (firstValidAddress+15) & 0xfffffffffffffff0L;
|
firstValidAddress = (firstValidAddress + 15) & 0xfffffffffffffff0L;
|
||||||
break;
|
break;
|
||||||
case 4: // "page" aligned, assume 4096
|
case 4: // "page" aligned, assume 4096
|
||||||
firstValidAddress = (firstValidAddress+4095) & 0xfffffffffffff000L;
|
firstValidAddress = (firstValidAddress + 4095) & 0xfffffffffffff000L;
|
||||||
break;
|
break;
|
||||||
case 5: // 4-byte aligned
|
case 5: // 4-byte aligned
|
||||||
firstValidAddress = (firstValidAddress+3) & 0xfffffffffffffffcL;
|
firstValidAddress = (firstValidAddress + 3) & 0xfffffffffffffffcL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new OmfException("Unsupported alignment type");
|
throw new OmfException("Unsupported alignment type");
|
||||||
}
|
}
|
||||||
vma = firstValidAddress;
|
vma = firstValidAddress;
|
||||||
firstValidAddress = vma + segmentLength;
|
firstValidAddress = vma + segmentLength;
|
||||||
return firstValidAddress;
|
return firstValidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve special names from the name list such as: segment, class, overlay, names.
|
* Resolve special names from the name list such as: segment, class, overlay, names.
|
||||||
* This routine also determines the read/write/execute permissions for the segment
|
* This routine also determines the read/write/execute permissions for the segment
|
||||||
|
@ -308,7 +309,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
overlayName = nameList.get(overlayNameIndex - 1);
|
overlayName = nameList.get(overlayNameIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we know the class name, we can make some educated guesses about read/write/exec permissions
|
// Once we know the class name, we can make some educated guesses about read/write/exec permissions
|
||||||
isReadable = true;
|
isReadable = true;
|
||||||
if (className.equals("CODE") || className.equals("code")) {
|
if (className.equals("CODE") || className.equals("code")) {
|
||||||
|
@ -322,7 +323,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
isExecutable = false;
|
isExecutable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an explicit data-block to this segment.
|
* Add an explicit data-block to this segment.
|
||||||
* @param rec is the data-block
|
* @param rec is the data-block
|
||||||
|
@ -330,7 +331,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
protected void addEnumeratedData(OmfEnumeratedData rec) {
|
protected void addEnumeratedData(OmfEnumeratedData rec) {
|
||||||
dataBlocks.add(rec);
|
dataBlocks.add(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an explicit data-block to this segment that might extend
|
* Add an explicit data-block to this segment that might extend
|
||||||
* the length of this segment. Borland compilers in particular produce
|
* the length of this segment. Borland compilers in particular produce
|
||||||
|
@ -344,7 +345,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
dataBlocks.add(rec);
|
dataBlocks.add(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a compressed-form data-block to this segment
|
* Add a compressed-form data-block to this segment
|
||||||
* @param rec is the data-block
|
* @param rec is the data-block
|
||||||
|
@ -352,7 +353,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
protected void addIteratedData(OmfIteratedData rec) {
|
protected void addIteratedData(OmfIteratedData rec) {
|
||||||
dataBlocks.add(rec);
|
dataBlocks.add(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An InputStream that produces the bytes for the dataBlocks in this segment.
|
* An InputStream that produces the bytes for the dataBlocks in this segment.
|
||||||
* It runs through the ordered {@link OmfData} in turn. It pads with zeroes,
|
* It runs through the ordered {@link OmfData} in turn. It pads with zeroes,
|
||||||
|
@ -365,7 +366,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
private byte[] buffer; // Current buffer
|
private byte[] buffer; // Current buffer
|
||||||
private int bufferpointer; // current index into buffer
|
private int bufferpointer; // current index into buffer
|
||||||
private int dataUpNext; // Index of next data section OmfIteratedData/OmfEnumeratedData to be buffered
|
private int dataUpNext; // Index of next data section OmfIteratedData/OmfEnumeratedData to be buffered
|
||||||
|
|
||||||
public SectionStream(BinaryReader reader, MessageLog log) throws IOException {
|
public SectionStream(BinaryReader reader, MessageLog log) throws IOException {
|
||||||
super();
|
super();
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
|
@ -376,7 +377,7 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
establishNextBuffer();
|
establishNextBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the next buffer of bytes being provided by this stream.
|
* Fill the next buffer of bytes being provided by this stream.
|
||||||
* @throws IOException for problems with the file image reader
|
* @throws IOException for problems with the file image reader
|
||||||
|
@ -388,10 +389,11 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
// We have some fill to produce before the next section
|
// We have some fill to produce before the next section
|
||||||
long size = data.getDataOffset() - pointer;
|
long size = data.getDataOffset() - pointer;
|
||||||
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
||||||
throw new IOException("Unfilled hole in OMF data blocks for segment: "+segmentName);
|
throw new IOException(
|
||||||
|
"Unfilled hole in OMF data blocks for segment: " + segmentName);
|
||||||
}
|
}
|
||||||
buffer = new byte[(int)size];
|
buffer = new byte[(int) size];
|
||||||
for(int i=0;i<size;++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
buffer[i] = 0;
|
buffer[i] = 0;
|
||||||
}
|
}
|
||||||
bufferpointer = 0;
|
bufferpointer = 0;
|
||||||
|
@ -416,15 +418,15 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
// We may have filler after the last block
|
// We may have filler after the last block
|
||||||
long size = segmentLength - pointer;
|
long size = segmentLength - pointer;
|
||||||
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
if (size > OmfLoader.MAX_UNINITIALIZED_FILL) {
|
||||||
throw new IOException("Large hole at the end of OMF segment: "+segmentName);
|
throw new IOException("Large hole at the end of OMF segment: " + segmentName);
|
||||||
}
|
}
|
||||||
buffer = new byte[(int)size];
|
buffer = new byte[(int) size];
|
||||||
for(int i=0;i<size;++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
buffer[i] = 0;
|
buffer[i] = 0;
|
||||||
}
|
}
|
||||||
bufferpointer = 0;
|
bufferpointer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (pointer < segmentLength) {
|
if (pointer < segmentLength) {
|
||||||
|
@ -443,6 +445,6 @@ public class OmfSegmentHeader extends OmfRecord {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,46 +22,46 @@ public class OmfSymbol {
|
||||||
private int typeIndex;
|
private int typeIndex;
|
||||||
private int dataType; // 0=unused
|
private int dataType; // 0=unused
|
||||||
private int byteLength; // 0=unused
|
private int byteLength; // 0=unused
|
||||||
private int segmentRef=0; // Symbol is really reference to extra segment
|
private int segmentRef = 0; // Symbol is really reference to extra segment
|
||||||
private long offset;
|
private long offset;
|
||||||
private Address address;
|
private Address address;
|
||||||
|
|
||||||
public OmfSymbol(String name,int type,long off,int dT,int bL) {
|
public OmfSymbol(String name, int type, long off, int dT, int bL) {
|
||||||
symbolName = name;
|
symbolName = name;
|
||||||
typeIndex = type;
|
typeIndex = type;
|
||||||
offset = off;
|
offset = off;
|
||||||
dataType = dT;
|
dataType = dT;
|
||||||
byteLength = bL;
|
byteLength = bL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return symbolName;
|
return symbolName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDataType() {
|
public int getDataType() {
|
||||||
return dataType;
|
return dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getOffset() {
|
public long getOffset() {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSegmentRef() {
|
public int getSegmentRef() {
|
||||||
return segmentRef;
|
return segmentRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSegmentRef(int val) {
|
public void setSegmentRef(int val) {
|
||||||
segmentRef = val;
|
segmentRef = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(Address addr) {
|
public void setAddress(Address addr) {
|
||||||
address = addr;
|
address = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address getAddress() {
|
public Address getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFrameDatum() {
|
public int getFrameDatum() {
|
||||||
return 0; // This is currently unused
|
return 0; // This is currently unused
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -27,23 +26,24 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||||
private int baseFrame;
|
private int baseFrame;
|
||||||
private boolean isStatic;
|
private boolean isStatic;
|
||||||
private OmfSymbol[] symbol;
|
private OmfSymbol[] symbol;
|
||||||
|
|
||||||
public OmfSymbolRecord(BinaryReader reader,boolean isStatic) throws IOException {
|
public OmfSymbolRecord(BinaryReader reader, boolean isStatic) throws IOException {
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
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 = OmfRecord.readIndex(reader);
|
||||||
baseSegmentIndex = OmfRecord.readIndex(reader);
|
baseSegmentIndex = OmfRecord.readIndex(reader);
|
||||||
if (baseSegmentIndex == 0)
|
if (baseSegmentIndex == 0) {
|
||||||
baseFrame = reader.readNextShort() & 0xffff;
|
baseFrame = reader.readNextShort() & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
|
||||||
while(reader.getPointerIndex() < max) {
|
while (reader.getPointerIndex() < max) {
|
||||||
String name = OmfRecord.readString(reader);
|
String name = OmfRecord.readString(reader);
|
||||||
long offset = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
long offset = OmfRecord.readInt2Or4(reader, hasBigFields) & 0xffffffffL;
|
||||||
int type = OmfRecord.readIndex(reader);
|
int type = OmfRecord.readIndex(reader);
|
||||||
OmfSymbol subrec = new OmfSymbol(name,type,offset,0,0);
|
OmfSymbol subrec = new OmfSymbol(name, type, offset, 0, 0);
|
||||||
symbollist.add(subrec);
|
symbollist.add(subrec);
|
||||||
}
|
}
|
||||||
readCheckSumByte(reader);
|
readCheckSumByte(reader);
|
||||||
|
@ -54,19 +54,19 @@ public class OmfSymbolRecord extends OmfRecord {
|
||||||
public boolean isStatic() {
|
public boolean isStatic() {
|
||||||
return isStatic;
|
return isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getGroupIndex() {
|
public int getGroupIndex() {
|
||||||
return baseGroupIndex;
|
return baseGroupIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSegmentIndex() {
|
public int getSegmentIndex() {
|
||||||
return baseSegmentIndex;
|
return baseSegmentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int numSymbols() {
|
public int numSymbols() {
|
||||||
return symbol.length;
|
return symbol.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OmfSymbol getSymbol(int i) {
|
public OmfSymbol getSymbol(int i) {
|
||||||
return symbol[i];
|
return symbol[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* ###
|
||||||
|
* 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.BinaryReader;
|
||||||
|
|
||||||
|
public class OmfUnknownRecord extends OmfRecord {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link OmfUnknownRecord}
|
||||||
|
*
|
||||||
|
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||||
|
* @throws IOException If an IO-related error occurred
|
||||||
|
*/
|
||||||
|
public OmfUnknownRecord(BinaryReader reader) throws IOException {
|
||||||
|
readRecordHeader(reader);
|
||||||
|
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* ###
|
||||||
|
* 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.BinaryReader;
|
||||||
|
|
||||||
|
public class OmfUnsupportedRecord extends OmfRecord {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link OmfUnsupportedRecord}
|
||||||
|
*
|
||||||
|
* @param reader A {@link BinaryReader} positioned at the start of the record
|
||||||
|
* @throws IOException If an IO-related error occurred
|
||||||
|
*/
|
||||||
|
public OmfUnsupportedRecord(BinaryReader reader) throws IOException {
|
||||||
|
readRecordHeader(reader);
|
||||||
|
reader.setPointerIndex(reader.getPointerIndex() + getRecordLength());
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,6 @@ import ghidra.util.DataConverter;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
|
|
||||||
public class OmfLoader extends AbstractProgramWrapperLoader {
|
public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||||
public final static String OMF_NAME = "Relocatable Object Module Format (OMF)";
|
public final static String OMF_NAME = "Relocatable Object Module Format (OMF)";
|
||||||
|
@ -115,7 +114,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||||
OmfFileHeader header = null;
|
OmfFileHeader header = null;
|
||||||
BinaryReader reader = OmfFileHeader.createReader(provider);
|
BinaryReader reader = OmfFileHeader.createReader(provider);
|
||||||
try {
|
try {
|
||||||
header = OmfFileHeader.parse(reader, monitor);
|
header = OmfFileHeader.parse(reader, monitor, log);
|
||||||
header.resolveNames();
|
header.resolveNames();
|
||||||
header.sortSegmentDataBlocks();
|
header.sortSegmentDataBlocks();
|
||||||
OmfFileHeader.doLinking(IMAGE_BASE, header.getSegments(), header.getGroups());
|
OmfFileHeader.doLinking(IMAGE_BASE, header.getSegments(), header.getGroups());
|
||||||
|
@ -284,7 +283,6 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
|
||||||
* @param reader is a reader for the underlying file
|
* @param reader is a reader for the underlying file
|
||||||
* @param header is the OMF file header
|
* @param header is the OMF file header
|
||||||
* @param program is the Program
|
* @param program is the Program
|
||||||
* @param mbu is the block creation utility
|
|
||||||
* @param monitor is checked for cancellation
|
* @param monitor is checked for cancellation
|
||||||
* @param log receives error messages
|
* @param log receives error messages
|
||||||
* @throws AddressOverflowException if the underlying data stream causes an address to wrap
|
* @throws AddressOverflowException if the underlying data stream causes an address to wrap
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue