Let AddressSpace do segment selector assignment in NeLoader

This commit is contained in:
caheckman 2019-08-26 10:55:12 -04:00
parent 017537be35
commit b0d90cf36f
5 changed files with 60 additions and 35 deletions

View File

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,12 +15,13 @@
*/
package ghidra.app.util.bin.format.ne;
import generic.continues.*;
import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.*;
import ghidra.app.util.bin.format.mz.*;
import java.io.IOException;
import java.io.*;
import generic.continues.GenericFactory;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.app.util.bin.format.mz.DOSHeader;
import ghidra.program.model.address.SegmentedAddress;
/**
* A class to manage loading New Executables (NE).
@ -34,17 +34,20 @@ public class NewExecutable {
private WindowsHeader winHeader;
/**
* Constructs a new instance of an new executable.
* @param bp the byte provider
* @throws IOException if an I/O error occurs.
*/
public NewExecutable(GenericFactory factory, ByteProvider bp) throws IOException {
* Constructs a new instance of an new executable.
* @param factory is the object factory to bundle with the reader
* @param bp the byte provider
* @param baseAddr the image base of the executable
* @throws IOException if an I/O error occurs.
*/
public NewExecutable(GenericFactory factory, ByteProvider bp, SegmentedAddress baseAddr)
throws IOException {
reader = new FactoryBundledWithBinaryReader(factory, bp, true);
dosHeader = DOSHeader.createDOSHeader(reader);
if (dosHeader.isDosSignature()) {
try {
winHeader = new WindowsHeader(reader, (short)dosHeader.e_lfanew());
winHeader = new WindowsHeader(reader, baseAddr, (short) dosHeader.e_lfanew());
}
catch (InvalidWindowsHeaderException e) {
}

View File

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,7 +17,9 @@ package ghidra.app.util.bin.format.ne;
import java.io.IOException;
import ghidra.app.util.bin.format.*;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.program.model.address.SegmentedAddress;
import ghidra.program.model.address.SegmentedAddressSpace;
import ghidra.util.Conv;
/**
@ -28,7 +29,8 @@ import ghidra.util.Conv;
public class SegmentTable {
private Segment [] segments;
SegmentTable(FactoryBundledWithBinaryReader reader, short index, short segmentCount, short shiftAlignCount) throws IOException {
SegmentTable(FactoryBundledWithBinaryReader reader, SegmentedAddress baseAddr, short index,
short segmentCount, short shiftAlignCount) throws IOException {
long oldIndex = reader.getPointerIndex();
reader.setPointerIndex(Conv.shortToInt(index));
@ -39,14 +41,29 @@ public class SegmentTable {
segments = new Segment[segmentCountInt];
int startOffset = 0;
SegmentedAddressSpace space;
int curSegment;
if (baseAddr != null) {
space = (SegmentedAddressSpace) baseAddr.getAddressSpace();
curSegment = baseAddr.getSegment();
}
else {
space = null;
curSegment = 0;
}
for (int i = 0 ; i < segmentCountInt ; ++i) {
segments[i] = new Segment(reader, shiftAlignCount, startOffset >> 4);
segments[i] = new Segment(reader, shiftAlignCount, curSegment);
int size = segments[i].getMinAllocSize() & 0xffff;
if (size == 0) {
size = 0x10000;
}
startOffset = (startOffset + size + 0xf) & ~0xf;
if (space != null) {
SegmentedAddress endAddr = space.getAddress(curSegment, size - 1);
curSegment = space.getNextOpenSegment(endAddr);
}
else {
curSegment += 1;
}
}
reader.setPointerIndex(oldIndex);

View File

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +15,11 @@
*/
package ghidra.app.util.bin.format.ne;
import ghidra.app.util.bin.format.*;
import java.io.IOException;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.program.model.address.SegmentedAddress;
/**
* A class to represent and parse the
* Windows new-style executable (NE) header.
@ -39,20 +40,22 @@ public class WindowsHeader {
private NonResidentNameTable nonResNameTable;
/**
* Constructor
* @param reader the binary reader
* @param index the index where the windows headers begins
* @throws InvalidWindowsHeaderException if the bytes defined in the binary reader at
* the specified index do not constitute a valid windows header.
*/
public WindowsHeader(FactoryBundledWithBinaryReader reader, short index) throws InvalidWindowsHeaderException, IOException {
* Constructor
* @param reader the binary reader
* @param baseAddr the image base address
* @param index the index where the windows headers begins
* @throws InvalidWindowsHeaderException if the bytes defined in the binary reader at
* the specified index do not constitute a valid windows header.
* @throws IOException for problems reading the header bytes
*/
public WindowsHeader(FactoryBundledWithBinaryReader reader, SegmentedAddress baseAddr,
short index) throws InvalidWindowsHeaderException, IOException {
this.infoBlock = new InformationBlock(reader, index);
short segTableIndex = (short)(infoBlock.getSegmentTableOffset() + index);
this.segTable = new SegmentTable(reader,
segTableIndex,
infoBlock.getSegmentCount(),
infoBlock.getSegmentAlignmentShiftCount());
baseAddr, segTableIndex, infoBlock.getSegmentCount(),
infoBlock.getSegmentAlignmentShiftCount());
//if resource table offset == resident name table offset, then
//we do not have any resources...

View File

@ -51,6 +51,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
private static final String TAB = " ";
private static final long MIN_BYTE_LENGTH = 4;
private static final int SEGMENT_START = 0x1000;
private ArrayList<Address> entryPointList = new ArrayList<>();
private Comparator<String> comparator = new CallNameComparator();
@ -65,7 +66,7 @@ public class NeLoader extends AbstractLibrarySupportLoader {
if (provider.length() < MIN_BYTE_LENGTH) {
return loadSpecs;
}
NewExecutable ne = new NewExecutable(RethrowContinuesFactory.INSTANCE, provider);
NewExecutable ne = new NewExecutable(RethrowContinuesFactory.INSTANCE, provider, null);
WindowsHeader wh = ne.getWindowsHeader();
if (wh != null) {
List<QueryResult> results = QueryOpinionService.query(getName(),
@ -99,7 +100,9 @@ public class NeLoader extends AbstractLibrarySupportLoader {
// the original bytes.
MemoryBlockUtils.createFileBytes(prog, provider, monitor);
NewExecutable ne = new NewExecutable(factory, provider);
SegmentedAddressSpace space =
(SegmentedAddressSpace) prog.getAddressFactory().getDefaultAddressSpace();
NewExecutable ne = new NewExecutable(factory, provider, space.getAddress(SEGMENT_START, 0));
WindowsHeader wh = ne.getWindowsHeader();
InformationBlock ib = wh.getInformationBlock();
SegmentTable st = wh.getSegmentTable();
@ -113,8 +116,6 @@ public class NeLoader extends AbstractLibrarySupportLoader {
Listing listing = prog.getListing();
SymbolTable symbolTable = prog.getSymbolTable();
Memory memory = prog.getMemory();
SegmentedAddressSpace space =
(SegmentedAddressSpace) prog.getAddressFactory().getDefaultAddressSpace();
ProgramContext context = prog.getProgramContext();
RelocationTable relocTable = prog.getRelocationTable();

View File

@ -69,7 +69,8 @@ public class ProtectedAddressSpace extends SegmentedAddressSpace {
@Override
public int getNextOpenSegment(Address addr) {
int res = getDefaultSegmentFromFlat(addr.getOffset());
res += 1;
// Advance the selector by 8, accounting for the descriptor table bit and the privilege level bits
res = (res + 8) & 0xfff8;
return res;
}
}