Skip to content

Commit

Permalink
Addes support to load unbound LEs
Browse files Browse the repository at this point in the history
  • Loading branch information
yetmorecode committed Apr 18, 2022
1 parent 2dd83ff commit b164bbe
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 55 deletions.
2 changes: 1 addition & 1 deletion extension.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name=LXLoader
name=@extname@
description=Linear Executable (LX/LE/LC) loader with various customization options
author=https://github.com/yetmorecode
createdOn=2021-12-13
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/yetmorecode/ghidra/LxLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws
e.printStackTrace();
} catch (InvalidHeaderException e) {
// Everything is ok, but the provided data is not a valid LX/LE/LC
System.out.println("foobar");
}
return loadSpecs;
}
Expand Down Expand Up @@ -379,7 +380,7 @@ private byte[] createObjectBlock(Program program, LxExecutable le, ObjectTableEn
fixupsHandled++;
} else {
Msg.warn(this, String.format(
"WARNING: unhandled fixup #%x_%s at %08x (type %02x, page %03x): %s -> object#%x:%x",
"WARNING: unhandled fixup #%x_%s at %08x (type %02x): %s -> object#%x:%x",
f.index, f.shortname(), f.getSourceAddress(),
index,
f.hasSourceList() ? "source list " + f.sourceCount : String.format("%x", f.sourceOffset),
Expand Down
112 changes: 59 additions & 53 deletions src/main/java/yetmorecode/ghidra/format/lx/model/LxExecutable.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,55 +23,61 @@ public class LxExecutable extends yetmorecode.file.format.lx.LxExecutable {

public LxExecutable(GenericFactory factory, ByteProvider bp, LoaderOptions options) throws IOException, InvalidHeaderException {
reader = new FactoryBundledWithBinaryReader(factory, bp, true);
// Try reading MZ header
mzHeader = DOSHeader.createDOSHeader(reader);

if (mzHeader.isDosSignature()) {
// Try reading LX header
header = new LxHeader(reader, (short) mzHeader.e_lfanew());

// Read object table
int objectTableOffset = mzHeader.e_lfanew() + header.objectTableOffset;
for (int i = 0; i < header.objectCount; i++) {
var offset = objectTableOffset + i * yetmorecode.file.format.lx.ObjectTableEntry.SIZE;
ObjectTableEntry e = new ObjectTableEntry(reader, offset);
e.number = i+1;
objects.add(e);
}

// Read fixup page table
fixupPageTable = new int[header.pageCount+1];
var tableOffset = getDosHeader().e_lfanew() + header.fixupPageTableOffset;
for (int i = 0; i <= header.pageCount; i++) {
fixupPageTable[i] = getReader().readInt(tableOffset + i * 4);
}

// Read fixups
var fixupRecordOffset = getDosHeader().e_lfanew() + header.fixupRecordTableOffset;
fixupCount = 0;
//for (int i = 1; i <= header.pageCount; i++) {
for (var object : objects) {
for (var i = 0; i < object.pageCount; i++) {
var page = object.pageTableIndex + i;
fixups.put(page, new ArrayList<>());
var fixupBegin = getFixupBegin(page);
var fixupEnd = getFixupEnd(page);
var fixupDataSize = fixupEnd - fixupBegin;
var current = 0;
while (current < fixupDataSize) {
var fixup = new FixupRecord(
reader,
fixupRecordOffset + fixupBegin + current,
++fixupCount,
options.getBaseAddress(object),
i
);
fixups.get(page).add(fixup);
current += fixup.size;
}
}
}
}
var lfanew = 0;
try {
// Try reading MZ header
mzHeader = DOSHeader.createDOSHeader(reader);
if (mzHeader.isDosSignature()) {
lfanew = mzHeader.e_lfanew();
}
} catch (Exception e) {

}

// Try reading LX header
header = new LxHeader(reader, (short) lfanew);

// Read object table
int objectTableOffset = lfanew + header.objectTableOffset;
for (int i = 0; i < header.objectCount; i++) {
var offset = objectTableOffset + i * yetmorecode.file.format.lx.ObjectTableEntry.SIZE;
ObjectTableEntry e = new ObjectTableEntry(reader, offset);
e.number = i+1;
objects.add(e);
}

// Read fixup page table
fixupPageTable = new int[header.pageCount+1];
var tableOffset = lfanew + header.fixupPageTableOffset;
for (int i = 0; i <= header.pageCount; i++) {
fixupPageTable[i] = getReader().readInt(tableOffset + i * 4);
}

// Read fixups
var fixupRecordOffset = lfanew + header.fixupRecordTableOffset;
fixupCount = 0;
//for (int i = 1; i <= header.pageCount; i++) {
for (var object : objects) {
for (var i = 0; i < object.pageCount; i++) {
var page = object.pageTableIndex + i;
fixups.put(page, new ArrayList<>());
var fixupBegin = getFixupBegin(page);
var fixupEnd = getFixupEnd(page);
var fixupDataSize = fixupEnd - fixupBegin;
var current = 0;
while (current < fixupDataSize) {
var fixup = new FixupRecord(
reader,
fixupRecordOffset + fixupBegin + current,
++fixupCount,
options.getBaseAddress(object),
i
);
fixups.get(page).add(fixup);
current += fixup.size;
}
}
}
}

public static void checkProvider(GenericFactory factory, ByteProvider provider) throws InvalidHeaderException, IOException {
Expand All @@ -82,12 +88,12 @@ public static void checkProvider(GenericFactory factory, ByteProvider provider)

// Try parsing MZ header
var mzHeader = DOSHeader.createDOSHeader(reader);
if (!mzHeader.isDosSignature()) {
throw new InvalidHeaderException("No MS-DOS header found (invalid signature)");
var lfanew = 0;
if (mzHeader.isDosSignature()) {
lfanew = mzHeader.e_lfanew();
}

// Try parsing LX Header
new LxHeader(reader, (short) mzHeader.e_lfanew());
new LxHeader(reader, (short) lfanew);
}

/**
Expand Down

0 comments on commit b164bbe

Please sign in to comment.