From b164bbe94b2ff425a25ff4564a8fe4131a18f8be Mon Sep 17 00:00:00 2001 From: Date: Mon, 18 Apr 2022 16:03:16 +0200 Subject: [PATCH] Addes support to load unbound LEs --- extension.properties | 2 +- .../java/yetmorecode/ghidra/LxLoader.java | 3 +- .../ghidra/format/lx/model/LxExecutable.java | 112 +++++++++--------- 3 files changed, 62 insertions(+), 55 deletions(-) diff --git a/extension.properties b/extension.properties index 613eac2..eeff7ea 100644 --- a/extension.properties +++ b/extension.properties @@ -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 diff --git a/src/main/java/yetmorecode/ghidra/LxLoader.java b/src/main/java/yetmorecode/ghidra/LxLoader.java index 71d49f7..5763a7b 100644 --- a/src/main/java/yetmorecode/ghidra/LxLoader.java +++ b/src/main/java/yetmorecode/ghidra/LxLoader.java @@ -89,6 +89,7 @@ public Collection 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; } @@ -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), diff --git a/src/main/java/yetmorecode/ghidra/format/lx/model/LxExecutable.java b/src/main/java/yetmorecode/ghidra/format/lx/model/LxExecutable.java index eae78d0..857f585 100644 --- a/src/main/java/yetmorecode/ghidra/format/lx/model/LxExecutable.java +++ b/src/main/java/yetmorecode/ghidra/format/lx/model/LxExecutable.java @@ -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 { @@ -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); } /**