Merge remote-tracking branch 'origin/GP-952_ryanmkurtz_pdata' (#3803)

This commit is contained in:
Ryan Kurtz
2022-08-08 13:19:16 -04:00
8 changed files with 354 additions and 246 deletions

View File

@@ -15,6 +15,8 @@
*/
package ghidra.app.util.bin.format.pe;
import static ghidra.app.util.bin.format.pe.FileHeader.*;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
@@ -23,15 +25,18 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
public class ExceptionDataDirectory extends DataDirectory {
private final static String NAME = "IMAGE_DIRECTORY_ENTRY_EXCEPTION";
private ImageRuntimeFunctionEntries functionEntries;
ExceptionDataDirectory(NTHeader ntHeader, BinaryReader reader) throws IOException {
processDataDirectory(ntHeader, reader);
}
}
@Override
public String getDirectoryName() {
@@ -39,11 +44,31 @@ public class ExceptionDataDirectory extends DataDirectory {
}
@Override
public boolean parse() {
public boolean parse() throws IOException {
int ptr = getPointer();
if (ptr < 0) {
return false;
}
long oldIndex = reader.getPointerIndex();
reader.setPointerIndex(ptr);
functionEntries = switch (ntHeader.getFileHeader().getMachine() & IMAGE_FILE_MACHINE_MASK) {
case IMAGE_FILE_MACHINE_I386:
case IMAGE_FILE_MACHINE_IA64:
case IMAGE_FILE_MACHINE_AMD64:
yield new ImageRuntimeFunctionEntries_X86(reader, size, ntHeader);
case IMAGE_FILE_MACHINE_ARM:
case IMAGE_FILE_MACHINE_ARM64:
case IMAGE_FILE_MACHINE_ARMNT:
yield new ImageRuntimeFunctionEntries_ARM(reader, size, ntHeader);
default:
Msg.error(this, String.format("Exception Data unsupported architecture: 0x%02x",
ntHeader.getFileHeader().getMachine()));
yield null;
};
reader.setPointerIndex(oldIndex);
return true;
}
@@ -52,17 +77,16 @@ public class ExceptionDataDirectory extends DataDirectory {
NTHeader ntHeader)
throws DuplicateNameException, CodeUnitInsertionException, IOException {
monitor.setMessage(program.getName()+": exceptions...");
Address addr = PeUtils.getMarkupAddress(program, isBinary, ntHeader, virtualAddress);
if (!program.getMemory().contains(addr)) {
return;
}
createDirectoryBookmark(program, addr);
if (functionEntries != null) {
functionEntries.markup(program, addr);
}
}
/**
* @see ghidra.app.util.bin.StructConverter#toDataType()
*/
@Override
public DataType toDataType() throws DuplicateNameException {
StructureDataType struct = new StructureDataType(NAME, size);

View File

@@ -22,7 +22,6 @@ import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY;
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol;
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbolAux;
import ghidra.program.model.data.*;
@@ -179,9 +178,6 @@ public class FileHeader implements StructConverter {
private SectionHeader[] sectionHeaders;
private List<DebugCOFFSymbol> symbols = new ArrayList<>();
// TODO: This is x86-64 architecture-specific and needs to be generalized.
private List<_IMAGE_RUNTIME_FUNCTION_ENTRY> irfes = new ArrayList<>();
private BinaryReader reader;
private int startIndex;
private NTHeader ntHeader;
@@ -238,15 +234,6 @@ public class FileHeader implements StructConverter {
return symbols;
}
/**
* Returns the array of RUNTIME_INFO entries, if any are present.
* @return An array of _IMAGE_RUNTIME_FUNCTION_ENTRY. The array can be empty.
* TODO: This is x86-64 architecture-specific and needs to be generalized.
*/
public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getImageRuntimeFunctionEntries() {
return irfes;
}
/**
* Returns the section header that contains the specified virtual address.
* @param virtualAddr the virtual address
@@ -379,36 +366,6 @@ public class FileHeader implements StructConverter {
reader.setPointerIndex(oldIndex);
}
void processImageRuntimeFunctionEntries() throws IOException {
FileHeader fh = ntHeader.getFileHeader();
SectionHeader[] sections = fh.getSectionHeaders();
// Look for an exception handler section for an array of
// RUNTIME_FUNCTION structures, bail if one isn't found
SectionHeader irfeHeader = null;
for (SectionHeader header : sections) {
if (header.getName().equals(".pdata")) {
irfeHeader = header;
break;
}
}
if (irfeHeader == null) {
return;
}
long oldIndex = reader.getPointerIndex();
int start = ntHeader.rvaToPointer(irfeHeader.getVirtualAddress());
reader.setPointerIndex(start);
ImageRuntimeFunctionEntries entries =
new ImageRuntimeFunctionEntries(reader, start, ntHeader);
irfes = entries.getRuntimeFunctionEntries();
reader.setPointerIndex(oldIndex);
}
void processSymbols() throws IOException {
if (isLordPE()) {
return;

View File

@@ -16,160 +16,27 @@
package ghidra.app.util.bin.format.pe;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
/**
* typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
* DWORD BeginAddress;
* DWORD EndAddress;
* union {
* DWORD UnwindInfoAddress;
* DWORD UnwindData;
* } DUMMYUNIONNAME;
* } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION, _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
*
* #define UNW_FLAG_NHANDLER 0x0
* #define UNW_FLAG_EHANDLER 0x1
* #define UNW_FLAG_UHANDLER 0x2
* #define UNW_FLAG_CHAININFO 0x4
*
* typedef struct _UNWIND_INFO {
* UCHAR Version : 3;
* UCHAR Flags : 5;
* UCHAR SizeOfProlog;
* UCHAR CountOfUnwindCodes;
* UCHAR FrameRegister : 4;
* UCHAR FrameOffset : 4;
* UNWIND_CODE UnwindCode[1];
*
* //
* // The unwind codes are followed by an optional DWORD aligned field that
* // contains the exception handler address or the address of chained unwind
* // information. If an exception handler address is specified, then it is
* // followed by the language specified exception handler data.
* //
* // union {
* // ULONG ExceptionHandler;
* // ULONG FunctionEntry;
* // };
* //
* // ULONG ExceptionData[];
* //
* } UNWIND_INFO, *PUNWIND_INFO;
* An interface for working with function table entries used for exception handling, which are found
* in the .pdata section. The actual implementations are architecture-specific.
*/
public class ImageRuntimeFunctionEntries {
private final static int UNWIND_INFO_SIZE = 0x0C;
List<_IMAGE_RUNTIME_FUNCTION_ENTRY> functionEntries = new ArrayList<>();
ImageRuntimeFunctionEntries(BinaryReader reader, long index, NTHeader ntHeader)
throws IOException {
int entryCount = 0;
// Find the exception handler data section. This is an unbounded array of
// RUNTIME_INFO structures one after another and there's no count field
// to tell us how many there are, so get the maximum number there could be
// based on the size of the section.
FileHeader fh = ntHeader.getFileHeader();
for (SectionHeader section : fh.getSectionHeaders()) {
if (section.getName().contentEquals(".pdata")) {
entryCount = section.getSizeOfRawData() / UNWIND_INFO_SIZE;
break;
}
}
if (entryCount == 0) {
return;
}
long origIndex = reader.getPointerIndex();
reader.setPointerIndex(index);
for (int i = 0; i < entryCount; i++) {
_IMAGE_RUNTIME_FUNCTION_ENTRY entry = new _IMAGE_RUNTIME_FUNCTION_ENTRY();
entry.beginAddress = reader.readNextUnsignedInt();
entry.endAddress = reader.readNextUnsignedInt();
entry.unwindInfoAddressOrData = reader.readNextUnsignedInt();
// When the size of the section is bigger than the number of structures
// the structure data fields will all be null, signaling the end of the
// array of structures. Break out here.
if (entry.beginAddress == 0 && entry.endAddress == 0 &&
entry.unwindInfoAddressOrData == 0) {
break;
}
// Read and process the UNWIND_INFO structures the RUNTIME_INFO
// structures point to
entry.unwindInfo =
PEx64UnwindInfo.readUnwindInfo(reader, entry.unwindInfoAddressOrData, ntHeader);
functionEntries.add(entry);
}
reader.setPointerIndex(origIndex);
}
public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getRuntimeFunctionEntries() {
return functionEntries;
}
public static void createData(Program program, Address headerStart,
List<_IMAGE_RUNTIME_FUNCTION_ENTRY> irfes) {
// TODO: This is x86-64 architecture-specific and needs to be generalized.
StructureDataType dt = new StructureDataType(".PDATA", 0);
dt.setCategoryPath(new CategoryPath("/PE"));
// Lay an array of RUNTIME_INFO structure out over the data
StructureDataType irfeStruct = new StructureDataType("_IMAGE_RUNTIME_FUNCTION_ENTRY", 0);
irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "BeginAddress", null);
irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "EndAddress", null);
irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "UnwindInfoAddressOrData", null);
ArrayDataType irfeArray =
new ArrayDataType(irfeStruct, irfes.size(), irfeStruct.getLength());
try {
DataUtilities.createData(program, headerStart, irfeArray, irfeArray.getLength(), true,
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
}
catch (CodeUnitInsertionException e) {
return;
}
}
// FIXME: change name to conform to Java naming standards
// FIXME: If public visibility is required improved member protection is needed
public static class _IMAGE_RUNTIME_FUNCTION_ENTRY {
long beginAddress;
long endAddress;
long unwindInfoAddressOrData;
PEx64UnwindInfo unwindInfo;
public void createData(Program program) {
if (unwindInfoAddressOrData > 0) {
try {
DataType dt = unwindInfo.toDataType();
Address start = program.getImageBase().add(unwindInfoAddressOrData);
DataUtilities.createData(program, start, dt, dt.getLength(), true,
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
}
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
// ignore
}
}
}
}
public interface ImageRuntimeFunctionEntries {
/**
* Marks up an {@link ImageRuntimeFunctionEntries}
*
* @param program The {@link Program}
* @param start The start {@link Address}
* @throws IOException If there was an IO-related error creating the data
* @throws DuplicateNameException If a data type of the same name already exists
* @throws CodeUnitInsertionException If data creation failed
*/
public void markup(Program program, Address start) throws CodeUnitInsertionException,
IOException, DuplicateNameException;
}

View File

@@ -0,0 +1,147 @@
/* ###
* 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.pe;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
/**
* <pre>
* typedef struct _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY {
* DWORD BeginAddress;
* union {
* DWORD UnwindData;
* struct {
* DWORD Flag : 2;
* DWORD FunctionLength : 11;
* DWORD Ret : 2;
* DWORD H : 1;
* DWORD Reg : 3;
* DWORD R : 1;
* DWORD L : 1;
* DWORD C : 1;
* DWORD StackAdjust : 10;
* } DUMMYSTRUCTNAME;
* } DUMMYUNIONNAME;
* } IMAGE_ARM_RUNTIME_FUNCTION_ENTRY, * PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY;
* </pre>
* @see <a href="https://github.com/MicrosoftDocs/cpp-docs/blob/main/docs/build/arm-exception-handling.md">arm-exception-handling.md</a>
*/
public class ImageRuntimeFunctionEntries_ARM implements ImageRuntimeFunctionEntries {
private final static int ENTRY_SIZE = 0x08;
private List<ImageRuntimeFunctionEntry_ARM> functionEntries = new ArrayList<>();
/**
* Creates a new {@link ImageRuntimeFunctionEntries_X86}
*
* @param reader A {@link BinaryReader} positioned at the start of the exception data directory
* @param size The size of the exception data directory
* @param ntHeader The {@link NTHeader}
* @throws IOException If there was an issue parsing the exception data directory
*/
ImageRuntimeFunctionEntries_ARM(BinaryReader reader, int size, NTHeader ntHeader)
throws IOException {
int numEntries = size / ENTRY_SIZE;
for (int i = 0; i < numEntries; i++) {
long beginAddress = reader.readNextUnsignedInt() & ~0x1L; // low bit is set when thumb
int data = reader.readNextInt();
if (beginAddress == 0 && data == 0) {
break;
}
functionEntries.add(new ImageRuntimeFunctionEntry_ARM(beginAddress, data));
}
}
@Override
public void markup(Program program, Address headerStart) throws CodeUnitInsertionException,
IOException, DuplicateNameException {
StructureDataType exceptionInfoStruct = new StructureDataType("_IMAGE_RUNTIME_FUNCTION_ENTRY", 0);
exceptionInfoStruct.setPackingEnabled(true);
exceptionInfoStruct.add(StructConverter.IBO32, "BeginAddress", null);
exceptionInfoStruct.add(StructConverter.IBO32, "ExceptionInfo", null);
StructureDataType unwindDataStruct = new StructureDataType("_IMAGE_RUNTIME_FUNCTION_ENTRY_2", 0);
unwindDataStruct.setPackingEnabled(true);
unwindDataStruct.add(StructConverter.IBO32, "BeginAddress", null);
try {
unwindDataStruct.addBitField(StructConverter.DWORD, 2, "Flag", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 11, "FunctionLength", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 2, "Ret", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 1, "H", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 3, "Reg", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 1, "R", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 1, "L", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 1, "C", null);
unwindDataStruct.addBitField(StructConverter.DWORD, 10, "StackAdjust", null);
}
catch (InvalidDataTypeException e) {
throw new IOException(e);
}
Address addr = headerStart;
for (ImageRuntimeFunctionEntry_ARM entry : functionEntries) {
DataType struct = entry.isExceptionInfoRVA() ? exceptionInfoStruct : unwindDataStruct;
DataUtilities.createData(program, addr, struct, struct.getLength(), true,
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
addr = addr.add(ENTRY_SIZE);
}
}
/**
* Creates a new {@link ImageRuntimeFunctionEntries_ARM}
*
* @param beginAddress The RVA of the corresponding function
* @param data The exception info RVA or the packed unwind data, depending on lower 2 bit flag
*/
record ImageRuntimeFunctionEntry_ARM(long beginAddress, int data) {
/**
* Checks whether or not this entry is an exception info RVA or packed unwind data
*
* @return True if this entry is an exception info RVA, or false if it's packed unwind data
*/
public boolean isExceptionInfoRVA() {
return (data & 0x3) == 0;
}
/**
* Marks up this entry
*
* @param program The {@link Program}
* @throws IOException If there was an IO-related error creating the data
* @throws DuplicateNameException If a data type of the same name already exists
* @throws CodeUnitInsertionException If data creation failed
*/
public void markup(Program program)
throws DuplicateNameException, IOException, CodeUnitInsertionException {
if (isExceptionInfoRVA()) {
// TODO
}
}
}
}

View File

@@ -0,0 +1,155 @@
/* ###
* 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.pe;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.DuplicateNameException;
/**
* <pre>
* typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
* DWORD BeginAddress;
* DWORD EndAddress;
* union {
* DWORD UnwindInfoAddress;
* DWORD UnwindData;
* } DUMMYUNIONNAME;
* } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION, _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
*
* #define UNW_FLAG_NHANDLER 0x0
* #define UNW_FLAG_EHANDLER 0x1
* #define UNW_FLAG_UHANDLER 0x2
* #define UNW_FLAG_CHAININFO 0x4
*
* typedef struct _UNWIND_INFO {
* UCHAR Version : 3;
* UCHAR Flags : 5;
* UCHAR SizeOfProlog;
* UCHAR CountOfUnwindCodes;
* UCHAR FrameRegister : 4;
* UCHAR FrameOffset : 4;
* UNWIND_CODE UnwindCode[1];
*
* //
* // The unwind codes are followed by an optional DWORD aligned field that
* // contains the exception handler address or the address of chained unwind
* // information. If an exception handler address is specified, then it is
* // followed by the language specified exception handler data.
* //
* // union {
* // ULONG ExceptionHandler;
* // ULONG FunctionEntry;
* // };
* //
* // ULONG ExceptionData[];
* //
* } UNWIND_INFO, *PUNWIND_INFO;
* </pre>
*/
public class ImageRuntimeFunctionEntries_X86 implements ImageRuntimeFunctionEntries {
private final static int ENTRY_SIZE = 0x0C;
private List<ImageRuntimeFunctionEntry_X86> functionEntries = new ArrayList<>();
/**
* Creates a new {@link ImageRuntimeFunctionEntries_X86}
*
* @param reader A {@link BinaryReader} positioned at the start of the exception data directory
* @param size The size of the exception data directory
* @param ntHeader The {@link NTHeader}
* @throws IOException If there was an issue parsing the exception data directory
*/
ImageRuntimeFunctionEntries_X86(BinaryReader reader, int size, NTHeader ntHeader)
throws IOException {
int numEntries = size / ENTRY_SIZE;
for (int i = 0; i < numEntries; i++) {
long beginAddress = reader.readNextUnsignedInt();
long endAddress = reader.readNextUnsignedInt();
long unwindInfoAddressOrData = reader.readNextUnsignedInt();
if (beginAddress == 0 && endAddress == 0 && unwindInfoAddressOrData == 0) {
break;
}
PEx64UnwindInfo unwindInfo =
PEx64UnwindInfo.readUnwindInfo(reader, unwindInfoAddressOrData, ntHeader);
ImageRuntimeFunctionEntry_X86 entry = new ImageRuntimeFunctionEntry_X86(beginAddress,
endAddress, unwindInfoAddressOrData, unwindInfo);
functionEntries.add(entry);
}
}
@Override
public void markup(Program program, Address headerStart) throws CodeUnitInsertionException,
IOException, DuplicateNameException {
StructureDataType struct = new StructureDataType("_IMAGE_RUNTIME_FUNCTION_ENTRY", 0);
struct.add(StructConverter.IBO32, "BeginAddress", null);
struct.add(StructConverter.IBO32, "EndAddress", null);
struct.add(StructConverter.IBO32, "UnwindInfoAddressOrData", null);
ArrayDataType arr = new ArrayDataType(struct, functionEntries.size(), struct.getLength());
DataUtilities.createData(program, headerStart, arr, arr.getLength(), true,
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
for (ImageRuntimeFunctionEntry_X86 entry : functionEntries) {
entry.markup(program);
}
}
/**
* Creates a new {@link ImageRuntimeFunctionEntries_X86}
*
* @param beginAddress The RVA of the corresponding function
* @param endAddress The RVA of the end of the function
* @param unwindInfoAddressOrData The RVA of the unwind information
* @param unwindInfo The parsed {@link PEx64UnwindInfo unwind information}
*/
record ImageRuntimeFunctionEntry_X86(long beginAddress, long endAddress,
long unwindInfoAddressOrData, PEx64UnwindInfo unwindInfo) {
/**
* Marks up this entry
*
* @param program The {@link Program}
* @throws IOException If there was an IO-related error creating the data
* @throws DuplicateNameException If a data type of the same name already exists
* @throws CodeUnitInsertionException If data creation failed
*/
public void markup(Program program)
throws DuplicateNameException, IOException, CodeUnitInsertionException {
if (unwindInfoAddressOrData > 0) {
DataType dt = unwindInfo.toDataType();
Address start = program.getImageBase().add(unwindInfoAddressOrData);
DataUtilities.createData(program, start, dt, dt.getLength(), true,
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
}
}
}
}

View File

@@ -254,10 +254,6 @@ public class NTHeader implements StructConverter, OffsetValidator {
fileHeader.processSections(optionalHeader);
fileHeader.processSymbols();
if ((fileHeader.getMachine() &
FileHeader.IMAGE_FILE_MACHINE_MASK) == FileHeader.IMAGE_FILE_MACHINE_AMD64) {
fileHeader.processImageRuntimeFunctionEntries();
}
if (advancedProcess) {
optionalHeader.processDataDirectories(TaskMonitorAdapter.DUMMY_MONITOR);

View File

@@ -19,7 +19,7 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY;
import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries_X86.ImageRuntimeFunctionEntry_X86;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
@@ -48,7 +48,7 @@ class PEx64UnwindInfo implements StructConverter {
byte frameOffset;
UNWIND_CODE[] unwindCodes;
int exceptionHandlerFunction;
_IMAGE_RUNTIME_FUNCTION_ENTRY unwindHandlerChainInfo;
ImageRuntimeFunctionEntry_X86 unwindHandlerChainInfo;
long startOffset;
@@ -199,16 +199,15 @@ class PEx64UnwindInfo implements StructConverter {
unwindInfo.exceptionHandlerFunction = reader.readNextInt();
}
else if (unwindInfo.hasChainedUnwindInfo()) {
unwindInfo.unwindHandlerChainInfo =
new _IMAGE_RUNTIME_FUNCTION_ENTRY();
unwindInfo.unwindHandlerChainInfo.beginAddress = reader.readNextInt();
unwindInfo.unwindHandlerChainInfo.endAddress = reader.readNextInt();
unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData = reader.readNextInt();
long beginAddress = reader.readNextUnsignedInt();
long endAddress = reader.readNextUnsignedInt();
long unwindInfoAddressOrData = reader.readNextUnsignedInt();
// Follow the chain to the referenced UNWIND_INFO structure until we
// get to the end
unwindInfo.unwindHandlerChainInfo.unwindInfo = readUnwindInfo(reader,
unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData, ntHeader);
PEx64UnwindInfo info = readUnwindInfo(reader, unwindInfoAddressOrData, ntHeader);
unwindInfo.unwindHandlerChainInfo = new ImageRuntimeFunctionEntry_X86(beginAddress,
endAddress, unwindInfoAddressOrData, info);
}
reader.setPointerIndex(origIndex);

View File

@@ -26,7 +26,6 @@ import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.mz.DOSHeader;
import ghidra.app.util.bin.format.pe.*;
import ghidra.app.util.bin.format.pe.ImageCor20Header.ImageCor20Flags;
import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY;
import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout;
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol;
import ghidra.app.util.bin.format.pe.debug.DebugDirectoryParser;
@@ -144,7 +143,6 @@ public class PeLoader extends AbstractPeDebugLoader {
processProperties(optionalHeader, program, monitor);
processComments(program.getListing(), monitor);
processSymbols(ntHeader, sectionToAddress, program, monitor, log);
processImageRuntimeFunctionEntries(fileHeader, program, monitor, log);
processEntryPoints(ntHeader, program, monitor);
String compiler = CompilerOpinion.getOpinion(pe, provider).toString();
@@ -259,41 +257,6 @@ public class PeLoader extends AbstractPeDebugLoader {
}
}
private void processImageRuntimeFunctionEntries(FileHeader fileHeader, Program program,
TaskMonitor monitor, MessageLog log) {
// Check to see that we have exception data to process
SectionHeader irfeHeader = null;
for (SectionHeader header : fileHeader.getSectionHeaders()) {
if (header.getName().contains(".pdata")) {
irfeHeader = header;
break;
}
}
if (irfeHeader == null) {
return;
}
Address start = program.getImageBase().add(irfeHeader.getVirtualAddress());
List<_IMAGE_RUNTIME_FUNCTION_ENTRY> irfes = fileHeader.getImageRuntimeFunctionEntries();
if (irfes.isEmpty()) {
return;
}
// TODO: This is x86-64 architecture-specific and needs to be generalized.
ImageRuntimeFunctionEntries.createData(program, start, irfes);
// Each RUNTIME_INFO contains an address to an UNWIND_INFO structure
// which also needs to be laid out. When they contain chaining data
// they're recursive but the toDataType() function handles that.
for (_IMAGE_RUNTIME_FUNCTION_ENTRY entry : irfes) {
entry.createData(program);
}
}
private void processSymbols(NTHeader ntHeader, Map<SectionHeader, Address> sectionToAddress,
Program program, TaskMonitor monitor, MessageLog log) {
FileHeader fileHeader = ntHeader.getFileHeader();