Add OmfRecord support for CEXTDEF

Make OmfLoader add dummy functions at entrypoints

Fix conditional read when parsing FIXUP records

Fix typo in function name
This commit is contained in:
Scott Percival
2023-01-07 18:08:46 +08:00
committed by Ryan Kurtz
parent e77410ce03
commit c4088db81c
7 changed files with 100 additions and 12 deletions
@@ -0,0 +1,66 @@
/* ###
* 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 ghidra.app.util.bin.BinaryReader;
import java.io.IOException;
import java.util.ArrayList;
public class OmfComdatExternalSymbol extends OmfExternalSymbol {
public static class ExternalLookup {
public int nameIndex;
public int type;
public ExternalLookup(int ni, int t) {
this.nameIndex = ni;
this.type = t;
}
}
protected ArrayList<ExternalLookup> externalLookups;
protected OmfSymbol[] symbol;
public OmfComdatExternalSymbol(BinaryReader reader) throws IOException {
super(false);
readRecordHeader(reader);
long max = reader.getPointerIndex() + getRecordLength() - 1;
this.externalLookups = new ArrayList<ExternalLookup>();
while(reader.getPointerIndex() < max) {
int nameIndex = OmfRecord.readIndex(reader);
int type = OmfRecord.readIndex(reader);
this.externalLookups.add(new ExternalLookup(nameIndex, type));
}
readCheckSumByte(reader);
}
public void loadNames(ArrayList<String> namelist) {
ArrayList<OmfSymbol> symbollist = new ArrayList<OmfSymbol>();
for (ExternalLookup ext : this.externalLookups) {
String name = namelist.get(ext.nameIndex-1);
symbollist.add(new OmfSymbol(name, ext.type, 0, 0, 0));
}
this.symbol = new OmfSymbol[symbollist.size()];
symbollist.toArray(this.symbol);
}
public OmfSymbol[] getSymbols() {
return symbol;
}
}
@@ -332,6 +332,10 @@ public class OmfFileHeader extends OmfRecord {
header.evaluateComdef(comdef);
header.externsymbols.add((OmfExternalSymbol) record);
}
else if (record instanceof OmfComdatExternalSymbol comdat) {
((OmfComdatExternalSymbol)record).loadNames(header.nameList);
header.externsymbols.add((OmfExternalSymbol)record);
}
else if (record instanceof OmfExternalSymbol external) {
header.externsymbols.add(external);
}
@@ -147,12 +147,10 @@ public class OmfFixupRecord extends OmfRecord {
ThreadSubrecord thread = new ThreadSubrecord();
thread.type = reader.readNextByte();
int method = thread.getMethod();
if (method < 4) {
thread.index = OmfRecord.readInt1Or2(reader, hasBigFields);
}
else {
if ((method >= 4) && thread.isFrameThread())
thread.index = -1;
}
else
thread.index = OmfRecord.readInt1Or2(reader, hasBigFields);
return thread;
}
}
@@ -52,8 +52,8 @@ public class OmfLibraryRecord extends OmfRecord {
public ArrayList<MemberHeader> getMemberHeaders() {
return members;
}
public static boolean checkMagicNumer(BinaryReader reader) throws IOException {
public static boolean checkMagicNumber(BinaryReader reader) throws IOException {
byte type = reader.readNextByte();
if (type != (byte) 0xF0) {
return false;
@@ -173,6 +173,8 @@ public abstract class OmfRecord {
yield new OmfSymbolRecord(reader, true);
case LCOMDEF:
yield new OmfComdefRecord(reader, true);
case CEXTDEF:
yield new OmfComdatExternalSymbol(reader);
case RHEADR:
case REGINT:
case REDATA:
@@ -192,7 +194,6 @@ public abstract class OmfRecord {
yield new OmfObsoleteRecord(reader);
case LOCSYM:
case TYPDEF:
case CEXTDEF:
case COMDAT:
case LINSYM:
case ALIAS:
@@ -25,8 +25,11 @@ import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.omf.*;
import ghidra.app.util.bin.format.omf.OmfFixupRecord.Subrecord;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.Undefined;
import ghidra.program.model.lang.Language;
@@ -390,12 +393,14 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
break;
}
Address addrBase = null;
boolean tagFunction = false;
if (symbolrec.getSegmentIndex() != 0) {
// TODO: What does it mean if both the segment and group index are non-zero?
// Is the segment index group relative?
// For now we assume if a segment index is present, we don't need the group index
OmfSegmentHeader baseSegment = segments.get(symbolrec.getSegmentIndex() - 1);
addrBase = baseSegment.getAddress(language);
tagFunction = baseSegment.isCode();
}
else if (symbolrec.getGroupIndex() != 0) {
OmfGroupRecord baseGroup = groups.get(symbolrec.getGroupIndex() - 1);
@@ -409,10 +414,24 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
int numSymbols = symbolrec.numSymbols();
for (int i = 0; i < numSymbols; ++i) {
OmfSymbol symbol = symbolrec.getSymbol(i);
Address address = addrBase.add(symbol.getOffset());
symbol.setAddress(address);
try {
Address address = addrBase.add(symbol.getOffset());
symbol.setAddress(address);
createSymbol(symbol, address, symbolTable, log);
createSymbol(symbol, address, symbolTable, log);
if (tagFunction) {
// Create a dummy function so that EntryPointAnalyzer will disassemble it
try {
program.getFunctionManager().createFunction(symbol.getName(), address, new AddressSet(address), SourceType.IMPORTED);
} catch (OverlappingFunctionException e) {
log.appendMsg("Function already exists at address " + address.toString() + ": " + e.toString());
} catch (InvalidInputException e) {
log.appendMsg("Unable to create function with invalid name " + symbol.getName() + ": " + e.toString());
}
}
} catch (AddressOutOfBoundsException e) {
log.appendMsg("Unable to create symbol " + symbol.getName() + ": " + e.toString());
}
}
}
}
@@ -52,7 +52,7 @@ public class OmfArchiveFileSystemFactory implements
try {
BinaryReader reader = OmfFileHeader.createReader(byteProvider);
return OmfLibraryRecord.checkMagicNumer(reader);
return OmfLibraryRecord.checkMagicNumber(reader);
}
catch (IOException e) {
return false;