1876 Improved support for MZ executables

- Fixed incorrect header
- Gracefully handle segment overflows
- Added missing segment relocations
- Create uninitiallized memory according to header
This commit is contained in:
Lukas Kempf
2020-05-19 17:20:34 +02:00
committed by Ryan Kurtz
parent 991f84686c
commit 8797fcfbea
4 changed files with 388 additions and 239 deletions

View File

@@ -61,26 +61,11 @@ import ghidra.util.exception.DuplicateNameException;
*
*
*/
public class DOSHeader implements StructConverter, Writeable {
public class DOSHeader extends OldDOSHeader implements StructConverter, Writeable {
/** The name to use when converting into a structure data type. */
public final static String NAME = "IMAGE_DOS_HEADER";
public final static int IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
public final static int SIZEOF_DOS_HEADER = 64;
private short e_magic; // Magic number
private short e_cblp; // Bytes on last page of file
private short e_cp; // Pages in file
private short e_crlc; // Relocations
private short e_cparhdr; // Size of header in paragraphs
private short e_minalloc; // Minimum extra paragraphs needed
private short e_maxalloc; // Maximum extra paragraphs needed
private short e_ss; // Initial (relative) SS value
private short e_sp; // Initial SP value
private short e_csum; // Checksum
private short e_ip; // Initial IP value
private short e_cs; // Initial (relative) CS value
private short e_lfarlc; // File address of relocation table
private short e_ovno; // Overlay number
private short [] e_res = new short[4]; // Reserved words
private short e_oemid; // OEM identifier (for e_oeminfo)
private short e_oeminfo; // OEM information; e_oemid specific
@@ -96,116 +81,10 @@ public class DOSHeader implements StructConverter, Writeable {
* @param reader the binary reader
*/
public DOSHeader(BinaryReader reader) throws IOException {
this.reader = reader;
parse();
super(reader);
}
/**
* Returns the processor name.
* @return the processor name
*/
public String getProcessorName() {
return "x86";
}
/**
* Returns the magic number.
* @return the magic number
*/
public short e_magic() {
return e_magic;
}
/**
* Returns the number of bytes on the last page of file.
* @return the number of bytes on the last page of the file
*/
public short e_cblp() {
return e_cblp;
}
/**
* Returns the number of pages in the file.
* @return the number of pages in the file
*/
public short e_cp() {
return e_cp;
}
/**
* Returns the number of relocations.
* @return the number of relocations
*/
public short e_crlc() {
return e_crlc;
}
/**
* Returns the size of header in paragraphs.
* @return the size of header in paragraphs
*/
public short e_cparhdr() {
return e_cparhdr;
}
/**
* Returns the minimum extra paragraphs needed.
* @return the minimum extra paragraphs needed
*/
public short e_minalloc() {
return e_minalloc;
}
/**
* Returns the maximum extra paragraphs needed.
* @return the maximum extra paragraphs needed
*/
public short e_maxalloc() {
return e_maxalloc;
}
/**
* Returns the initial (relative) SS value.
* @return the initial (relative) SS value
*/
public short e_ss() {
return e_ss;
}
/**
* Returns the initial SP value.
* @return the initial SP value
*/
public short e_sp() {
return e_sp;
}
/**
* Returns the checksum.
* @return the checksum
*/
public short e_csum() {
return e_csum;
}
/**
* Returns the initial IP value.
* @return the initial IP value
*/
public short e_ip() {
return e_ip;
}
/**
* Returns the initial (relative) CS value.
* @return the initial (relative) CS value
*/
public short e_cs() {
return e_cs;
}
/**
* Returns the file address of relocation table.
* @return the file address of relocation table
*/
public short e_lfarlc() {
return e_lfarlc;
}
/**
* Returns the overlay number.
* @return the overlay number
*/
public short e_ovno() {
return e_ovno;
}
/**
/**
* Returns the reserved words.
* @return the reserved words
*/
@@ -245,9 +124,10 @@ public class DOSHeader implements StructConverter, Writeable {
* Returns true if a new EXE header exists.
* @return true if a new EXE header exists
*/
@Override
public boolean hasNewExeHeader() {
if (e_lfanew >= 0 && e_lfanew <= 0x10000) {
if (e_lfarlc == 0x40) {
if (e_lfarlc() == 0x40) {
// There are some non-NE files out there than may have e_lfarlc == 0x40, so we need
// to actually read the bytes at e_lfanew and check for the required NE signature.
try {
@@ -266,6 +146,7 @@ public class DOSHeader implements StructConverter, Writeable {
* Returns true if a PE header exists.
* @return true if a PE header exists
*/
@Override
public boolean hasPeHeader() {
if (e_lfanew >= 0 && e_lfanew <= 0x1000000) {
try {
@@ -282,24 +163,13 @@ public class DOSHeader implements StructConverter, Writeable {
return false;
}
/**
* Returns true if the DOS magic number is correct
* @return true if the DOS magic number is correct
*/
public boolean isDosSignature() {
return e_magic == IMAGE_DOS_SIGNATURE;
}
/**
* @see ghidra.app.util.bin.StructConverter#toDataType()
*/
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(NAME, 0);
struct.add(new ArrayDataType(ASCII,2,1));
for (int i=1; i <= 13; i++) {
struct.add(WORD);
}
StructureDataType struct = (StructureDataType)super.toDataType();
struct.add(new ArrayDataType(WORD,4,2));
struct.add(WORD);
struct.add(WORD);
@@ -309,20 +179,6 @@ public class DOSHeader implements StructConverter, Writeable {
struct.add(new ArrayDataType(BYTE, getProgramLen(), 1));
}
struct.getComponent( 0).setFieldName("e_magic");
struct.getComponent( 1).setFieldName("e_cblp");
struct.getComponent( 2).setFieldName("e_cp");
struct.getComponent( 3).setFieldName("e_crlc");
struct.getComponent( 4).setFieldName("e_cparhdr");
struct.getComponent( 5).setFieldName("e_minalloc");
struct.getComponent( 6).setFieldName("e_maxalloc");
struct.getComponent( 7).setFieldName("e_ss");
struct.getComponent( 8).setFieldName("e_sp");
struct.getComponent( 9).setFieldName("e_csum");
struct.getComponent(10).setFieldName("e_ip");
struct.getComponent(11).setFieldName("e_cs");
struct.getComponent(12).setFieldName("e_lfarlc");
struct.getComponent(13).setFieldName("e_ovno");
struct.getComponent(14).setFieldName("e_res[4]");
struct.getComponent(15).setFieldName("e_oemid");
struct.getComponent(16).setFieldName("e_oeminfo");
@@ -332,20 +188,6 @@ public class DOSHeader implements StructConverter, Writeable {
struct.getComponent(19).setFieldName("e_program");
}
struct.getComponent( 0).setComment("Magic number");
struct.getComponent( 1).setComment("Bytes of last page");
struct.getComponent( 2).setComment("Pages in file");
struct.getComponent( 3).setComment("Relocations");
struct.getComponent( 4).setComment("Size of header in paragraphs");
struct.getComponent( 5).setComment("Minimum extra paragraphs needed");
struct.getComponent( 6).setComment("Maximum extra paragraphs needed");
struct.getComponent( 7).setComment("Initial (relative) SS value");
struct.getComponent( 8).setComment("Initial SP value");
struct.getComponent( 9).setComment("Checksum");
struct.getComponent(10).setComment("Initial IP value");
struct.getComponent(11).setComment("Initial (relative) CS value");
struct.getComponent(12).setComment("File address of relocation table");
struct.getComponent(13).setComment("Overlay number");
struct.getComponent(14).setComment("Reserved words");
struct.getComponent(15).setComment("OEM identifier (for e_oeminfo)");
struct.getComponent(16).setComment("OEM information; e_oemid specific");
@@ -355,10 +197,17 @@ public class DOSHeader implements StructConverter, Writeable {
struct.getComponent(19).setComment("Actual DOS program");
}
struct.setCategoryPath(new CategoryPath("/DOS"));
return struct;
}
/**
* Helper to override the value of name
* @return The name of the header
*/
@Override
public String getName() {
return NAME;
}
/**
* Returns the length (in bytes) of the DOS
@@ -373,35 +222,21 @@ public class DOSHeader implements StructConverter, Writeable {
return stubBytes == null ? 0 : stubBytes.length;
}
private void parse() throws IOException {
reader.setPointerIndex(0);
e_magic = reader.readNextShort();
if (e_magic != IMAGE_DOS_SIGNATURE) {
@Override
protected void parse() throws IOException {
super.parse();
if (!isDosSignature()) {
return;
}
e_cblp = reader.readNextShort();
e_cp = reader.readNextShort();
e_crlc = reader.readNextShort();
e_cparhdr = reader.readNextShort();
e_minalloc = reader.readNextShort();
e_maxalloc = reader.readNextShort();
e_ss = reader.readNextShort();
e_sp = reader.readNextShort();
e_csum = reader.readNextShort();
e_ip = reader.readNextShort();
e_cs = reader.readNextShort();
e_lfarlc = reader.readNextShort();
e_ovno = reader.readNextShort();
e_res = reader.readNextShortArray(4);
e_oemid = reader.readNextShort();
e_oeminfo = reader.readNextShort();
e_res2 = reader.readNextShortArray(10);
e_lfanew = reader.readNextInt();
if (isDosSignature() && e_lfanew < 0x10000) {
if (e_lfanew < 0x10000) {
try {
stubBytes = e_lfanew > SIZEOF_DOS_HEADER ?
reader.readByteArray(SIZEOF_DOS_HEADER, e_lfanew - SIZEOF_DOS_HEADER) : new byte[0];
@@ -432,20 +267,7 @@ public class DOSHeader implements StructConverter, Writeable {
*/
@Override
public void write(RandomAccessFile raf, DataConverter dc) throws IOException {
raf.write(dc.getBytes(e_magic));
raf.write(dc.getBytes(e_cblp));
raf.write(dc.getBytes(e_cp));
raf.write(dc.getBytes(e_crlc));
raf.write(dc.getBytes(e_cparhdr));
raf.write(dc.getBytes(e_minalloc));
raf.write(dc.getBytes(e_maxalloc));
raf.write(dc.getBytes(e_ss));
raf.write(dc.getBytes(e_sp));
raf.write(dc.getBytes(e_csum));
raf.write(dc.getBytes(e_ip));
raf.write(dc.getBytes(e_cs));
raf.write(dc.getBytes(e_lfarlc));
raf.write(dc.getBytes(e_ovno));
super.write(raf, dc);
for (short e_re : e_res) {
raf.write(dc.getBytes(e_re));
}

View File

@@ -0,0 +1,325 @@
/* ###
* 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.mz;
import java.io.IOException;
import java.io.RandomAccessFile;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.Writeable;
import ghidra.program.model.data.*;
import ghidra.util.DataConverter;
import ghidra.util.exception.DuplicateNameException;
/**
* This class represents a DOS Header
* <br>
* <pre>
* WORD e_magic; // Magic number // MANDATORY
* WORD e_cblp; // Bytes on last page of file
* WORD e_cp; // Pages in file
* WORD e_crlc; // Relocations
* WORD e_cparhdr; // Size of header in paragraphs
* WORD e_minalloc; // Minimum extra paragraphs needed
* WORD e_maxalloc; // Maximum extra paragraphs needed
* WORD e_ss; // Initial (relative) SS value
* WORD e_sp; // Initial SP value
* WORD e_csum; // Checksum
* WORD e_ip; // Initial IP value
* WORD e_cs; // Initial (relative) CS value
* WORD e_lfarlc; // File address of relocation table
* WORD e_ovno; // Overlay number
*
* </pre>
*/
public class OldDOSHeader implements StructConverter, Writeable {
/** The name to use when converting into a structure data type. */
public static final String NAME = "OLD_IMAGE_DOS_HEADER";
public static final int IMAGE_DOS_SIGNATURE = 0x5A4D;
public static final int SIZEOF_DOS_HEADER = 28;
private short e_magic;
private short e_cblp;
private short e_cp;
private short e_crlc;
private short e_cparhdr;
private short e_minalloc;
private short e_maxalloc;
private short e_ss;
private short e_sp;
private short e_csum;
private short e_ip;
private short e_cs;
private short e_lfarlc;
private short e_ovno;
protected BinaryReader reader;
/**
* Constructs a new DOS header.
* @param reader the binary reader
*/
public OldDOSHeader(BinaryReader reader) throws IOException {
this.reader = reader;
parse();
}
/**
* Returns the processor name.
* @return the processor name
*/
public String getProcessorName() {
return "x86";
}
/**
* Returns the magic number.
* @return the magic number
*/
public short e_magic() {
return e_magic;
}
/**
* Returns the number of bytes on the last page of file.
* @return the number of bytes on the last page of the file
*/
public short e_cblp() {
return e_cblp;
}
/**
* Returns the number of pages in the file.
* @return the number of pages in the file
*/
public short e_cp() {
return e_cp;
}
/**
* Returns the number of relocations.
* @return the number of relocations
*/
public short e_crlc() {
return e_crlc;
}
/**
* Returns the size of header in paragraphs.
* @return the size of header in paragraphs
*/
public short e_cparhdr() {
return e_cparhdr;
}
/**
* Returns the minimum extra paragraphs needed.
* @return the minimum extra paragraphs needed
*/
public short e_minalloc() {
return e_minalloc;
}
/**
* Returns the maximum extra paragraphs needed.
* @return the maximum extra paragraphs needed
*/
public short e_maxalloc() {
return e_maxalloc;
}
/**
* Returns the initial (relative) SS value.
* @return the initial (relative) SS value
*/
public short e_ss() {
return e_ss;
}
/**
* Returns the initial SP value.
* @return the initial SP value
*/
public short e_sp() {
return e_sp;
}
/**
* Returns the checksum.
* @return the checksum
*/
public short e_csum() {
return e_csum;
}
/**
* Returns the initial IP value.
* @return the initial IP value
*/
public short e_ip() {
return e_ip;
}
/**
* Returns the initial (relative) CS value.
* @return the initial (relative) CS value
*/
public short e_cs() {
return e_cs;
}
/**
* Returns the file address of relocation table.
* @return the file address of relocation table
*/
public short e_lfarlc() {
return e_lfarlc;
}
/**
* Returns the overlay number.
* @return the overlay number
*/
public short e_ovno() {
return e_ovno;
}
/**
* Returns true if a new EXE header exists.
* @return true if a new EXE header exists
*/
public boolean hasNewExeHeader() {
return false;
}
/**
* Returns true if a PE header exists.
* @return true if a PE header exists
*/
public boolean hasPeHeader() {
return false;
}
/**
* Returns true if the DOS magic number is correct
* @return true if the DOS magic number is correct
*/
public boolean isDosSignature() {
return e_magic == IMAGE_DOS_SIGNATURE;
}
/**
* @see ghidra.app.util.bin.StructConverter#toDataType()
*/
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(getName(), 0);
struct.add(new ArrayDataType(ASCII,2,1));
for (int i=1; i <= 13; i++) {
struct.add(WORD);
}
struct.getComponent( 0).setFieldName("e_magic");
struct.getComponent( 1).setFieldName("e_cblp");
struct.getComponent( 2).setFieldName("e_cp");
struct.getComponent( 3).setFieldName("e_crlc");
struct.getComponent( 4).setFieldName("e_cparhdr");
struct.getComponent( 5).setFieldName("e_minalloc");
struct.getComponent( 6).setFieldName("e_maxalloc");
struct.getComponent( 7).setFieldName("e_ss");
struct.getComponent( 8).setFieldName("e_sp");
struct.getComponent( 9).setFieldName("e_csum");
struct.getComponent(10).setFieldName("e_ip");
struct.getComponent(11).setFieldName("e_cs");
struct.getComponent(12).setFieldName("e_lfarlc");
struct.getComponent(13).setFieldName("e_ovno");
struct.getComponent( 0).setComment("Magic number");
struct.getComponent( 1).setComment("Bytes of last page");
struct.getComponent( 2).setComment("Pages in file");
struct.getComponent( 3).setComment("Relocations");
struct.getComponent( 4).setComment("Size of header in paragraphs");
struct.getComponent( 5).setComment("Minimum extra paragraphs needed");
struct.getComponent( 6).setComment("Maximum extra paragraphs needed");
struct.getComponent( 7).setComment("Initial (relative) SS value");
struct.getComponent( 8).setComment("Initial SP value");
struct.getComponent( 9).setComment("Checksum");
struct.getComponent(10).setComment("Initial IP value");
struct.getComponent(11).setComment("Initial (relative) CS value");
struct.getComponent(12).setComment("File address of relocation table");
struct.getComponent(13).setComment("Overlay number");
struct.setCategoryPath(new CategoryPath("/DOS"));
return struct;
}
/**
* Helper to override the value of name
* @return The name of the header
*/
protected String getName() {
return NAME;
}
protected void parse() throws IOException {
reader.setPointerIndex(0);
e_magic = reader.readNextShort();
if (!isDosSignature()) {
return;
}
e_cblp = reader.readNextShort();
e_cp = reader.readNextShort();
e_crlc = reader.readNextShort();
e_cparhdr = reader.readNextShort();
e_minalloc = reader.readNextShort();
e_maxalloc = reader.readNextShort();
e_ss = reader.readNextShort();
e_sp = reader.readNextShort();
e_csum = reader.readNextShort();
e_ip = reader.readNextShort();
e_cs = reader.readNextShort();
e_lfarlc = reader.readNextShort();
e_ovno = reader.readNextShort();
}
/**
* @see ghidra.app.util.bin.format.Writeable#write(java.io.RandomAccessFile, ghidra.util.DataConverter)
*/
@Override
public void write(RandomAccessFile raf, DataConverter dc) throws IOException {
raf.write(dc.getBytes(e_magic));
raf.write(dc.getBytes(e_cblp));
raf.write(dc.getBytes(e_cp));
raf.write(dc.getBytes(e_crlc));
raf.write(dc.getBytes(e_cparhdr));
raf.write(dc.getBytes(e_minalloc));
raf.write(dc.getBytes(e_maxalloc));
raf.write(dc.getBytes(e_ss));
raf.write(dc.getBytes(e_sp));
raf.write(dc.getBytes(e_csum));
raf.write(dc.getBytes(e_ip));
raf.write(dc.getBytes(e_cs));
raf.write(dc.getBytes(e_lfarlc));
raf.write(dc.getBytes(e_ovno));
}
}

View File

@@ -27,7 +27,7 @@ import ghidra.app.util.bin.ByteProvider;
*/
public class OldStyleExecutable {
private BinaryReader reader;
private DOSHeader dosHeader;
private OldDOSHeader dosHeader;
/**
* Constructs a new instance of an old-style executable
@@ -36,7 +36,7 @@ public class OldStyleExecutable {
*/
public OldStyleExecutable(ByteProvider bp) throws IOException {
reader = new BinaryReader(bp, true);
dosHeader = new DOSHeader(reader);
dosHeader = new OldDOSHeader(reader);
}
/**
@@ -51,7 +51,7 @@ public class OldStyleExecutable {
* Returns the DOS Header from this old-style executable.
* @return the DOS Header from this old-style executable
*/
public DOSHeader getDOSHeader() {
public OldDOSHeader getOldDOSHeader() {
return dosHeader;
}
}

View File

@@ -23,7 +23,7 @@ import ghidra.app.util.MemoryBlockUtils;
import ghidra.app.util.Option;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.mz.DOSHeader;
import ghidra.app.util.bin.format.mz.OldDOSHeader;
import ghidra.app.util.bin.format.mz.OldStyleExecutable;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.store.LockException;
@@ -67,7 +67,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
return loadSpecs;
}
OldStyleExecutable ose = new OldStyleExecutable(provider);
DOSHeader dos = ose.getDOSHeader();
OldDOSHeader dos = ose.getOldDOSHeader();
if (dos.isDosSignature() && !dos.hasNewExeHeader() && !dos.hasPeHeader()) {
List<QueryResult> results =
QueryOpinionService.query(getName(), "" + dos.e_magic(), null);
@@ -98,7 +98,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
Memory memory = prog.getMemory();
OldStyleExecutable ose = new OldStyleExecutable(provider);
DOSHeader dos = ose.getDOSHeader();
OldDOSHeader dos = ose.getOldDOSHeader();
BinaryReader reader = ose.getBinaryReader();
if (monitor.isCancelled()) {
@@ -117,7 +117,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
return;
}
monitor.setMessage("Processing relocations...");
doRelocations(prog, reader, dos);
doRelocations(prog, reader, dos, log);
if (monitor.isCancelled()) {
return;
@@ -137,7 +137,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
}
private void setRegisters(ProgramContext context, Symbol entry, MemoryBlock[] blocks,
DOSHeader dos) {
OldDOSHeader dos) {
if (entry == null) {
return;
}
@@ -170,7 +170,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
context.setValue(sp, entry.getAddress(), entry.getAddress(),
BigInteger.valueOf(Conv.shortToLong(dos.e_sp())));
context.setValue(ss, entry.getAddress(), entry.getAddress(),
BigInteger.valueOf(Conv.shortToLong(dos.e_ss())));
BigInteger.valueOf(Conv.intToLong((dos.e_ss() + INITIAL_SEGMENT_VAL) & Conv.SHORT_MASK)));
BigInteger csValue = BigInteger.valueOf(
Conv.intToLong(((SegmentedAddress) entry.getAddress()).getSegment()));
@@ -245,15 +245,16 @@ public class MzLoader extends AbstractLibrarySupportLoader {
}
private void processSegments(Program program, FileBytes fileBytes, SegmentedAddressSpace space,
BinaryReader reader, DOSHeader dos, MessageLog log, TaskMonitor monitor) {
BinaryReader reader, OldDOSHeader dos, MessageLog log, TaskMonitor monitor) {
try {
int relocationTableOffset = Conv.shortToInt(dos.e_lfarlc());
int csStart = INITIAL_SEGMENT_VAL;
int dataStart = dos.e_cparhdr() << 4;
HashMap<Address, Address> segMap = new HashMap<Address, Address>();
// Handle overflow
SegmentedAddress codeAddress =
space.getAddress(Conv.shortToInt(dos.e_cs()) + csStart, 0);
space.getAddress((Conv.shortToInt((dos.e_cs())) + csStart) & Conv.SHORT_MASK, 0);
segMap.put(codeAddress, codeAddress);
codeAddress = space.getAddress(csStart, 0);
segMap.put(codeAddress, codeAddress); // This is there data starts loading
@@ -264,7 +265,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
int seg = Conv.shortToInt(reader.readNextShort());
// compute the new segment referenced at the location
SegmentedAddress segStartAddr = space.getAddress(seg + csStart, 0);
SegmentedAddress segStartAddr = space.getAddress((seg + csStart) & Conv.SHORT_MASK, 0);
segMap.put(segStartAddr, segStartAddr);
int location = (seg << 4) + off;
@@ -331,6 +332,13 @@ public class MzLoader extends AbstractLibrarySupportLoader {
" extra bytes starting at file offset 0x" + Integer.toHexString(exeEndOffset));
}
// create the allocated memory
Memory mem = program.getMemory();
Address end = mem.getMaxAddress().add(1);
// TODO: Handle overflow, consider minalloc
MemoryBlockUtils.createUninitializedBlock(program, false, "Alloc", end,
dos.e_maxalloc() * 16, "", "mz", true, true, false, log);
// // create the stack segment
// SegmentedAddress stackStart = space.getAddress((dos.e_ss() + csStart), 0);
// mbu.createUninitializedBlock(false, "Stack", stackStart, dos.e_sp(), "", "", true, true, false);
@@ -344,7 +352,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
}
}
private void doRelocations(Program prog, BinaryReader reader, DOSHeader dos) {
private void doRelocations(Program prog, BinaryReader reader, OldDOSHeader dos, MessageLog log) {
try {
Memory mem = prog.getMemory();
SegmentedAddressSpace space =
@@ -360,40 +368,34 @@ public class MzLoader extends AbstractLibrarySupportLoader {
int off = Conv.shortToInt(reader.readNextShort());
int seg = Conv.shortToInt(reader.readNextShort());
//SegmentedAddress segStartAddr = space.getAddress(seg + csStart, 0);
int location = (seg << 4) + off;
int location = ((seg << 4) + off) & Conv.SHORT_MASK;
int locOffset = location + dataStart;
// compute the new segment referenced at the location
SegmentedAddress fixupAddr = space.getAddress(seg + csStart, off);
int value = Conv.shortToInt(reader.readShort(locOffset));
int fixupAddrSeg = (value + csStart) & Conv.SHORT_MASK;
mem.setShort(fixupAddr, (short) fixupAddrSeg);
try {
// compute the new segment referenced at the location
SegmentedAddress fixupAddr = space.getAddress((seg + csStart) & Conv.SHORT_MASK, off);
int value = Conv.shortToInt(reader.readShort(locOffset));
int fixupAddrSeg = (value + csStart) & Conv.SHORT_MASK;
mem.setShort(fixupAddr, (short) fixupAddrSeg);
// Add to relocation table
prog.getRelocationTable()
.add(fixupAddr, 0, new long[] { off, seg }, null, null);
// Add to relocation table
prog.getRelocationTable()
.add(fixupAddr, 0, new long[] { off, seg }, null, null);
}
catch (AddressOutOfBoundsException|IOException|MemoryAccessException e) {
log.error("MzLoader", "Failed to process relocation " + i + ": " + e.getMessage());
}
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
catch (MemoryAccessException e) {
throw new RuntimeException(e);
log.error("MzLoader", "Failed to process relocation table: " + e.getMessage());
}
}
private void createSymbols(SegmentedAddressSpace space, SymbolTable symbolTable,
DOSHeader dos) {
OldDOSHeader dos) {
int ipValue = Conv.shortToInt(dos.e_ip());
int codeSegment = Conv.shortToInt(dos.e_cs()) + INITIAL_SEGMENT_VAL;
if (codeSegment > Conv.SHORT_MASK) {
System.out.println("Invalid entry point location: " + Integer.toHexString(codeSegment) +
":" + Integer.toHexString(ipValue));
return;
}
int codeSegment = (Conv.shortToInt(dos.e_cs()) + INITIAL_SEGMENT_VAL) & Conv.SHORT_MASK;
Address addr = space.getAddress(codeSegment, ipValue);