mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-955 Transitioned UNWIND_INFO to DynamicDataType. Corrected
DynamicDataType issues related to use of bitfields and trailing flex array.
This commit is contained in:
parent
6bb36e5f16
commit
73b07e4f48
4 changed files with 455 additions and 324 deletions
|
@ -19,10 +19,12 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.StructConverter;
|
|
||||||
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.DataUtilities;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,12 +67,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
* } UNWIND_INFO, *PUNWIND_INFO;
|
* } UNWIND_INFO, *PUNWIND_INFO;
|
||||||
*/
|
*/
|
||||||
public class ImageRuntimeFunctionEntries {
|
public class ImageRuntimeFunctionEntries {
|
||||||
private final static int UNWIND_INFO_VERSION_BITMASK = 0x07;
|
|
||||||
private final static int UNWIND_INFO_FLAGS_SHIFT = 0x03;
|
|
||||||
private final static int UNWIND_INFO_FRAME_REGISTER_MASK = 0x0F;
|
|
||||||
private final static int UNWIND_INFO_FRAME_OFFSET_SHIFT = 0x04;
|
|
||||||
private final static int UNWIND_INFO_OPCODE_MASK = 0x0F;
|
|
||||||
private final static int UNWIND_INFO_OPCODE_INFO_SHIFT = 0x04;
|
|
||||||
private final static int UNWIND_INFO_SIZE = 0x0C;
|
private final static int UNWIND_INFO_SIZE = 0x0C;
|
||||||
|
|
||||||
List<_IMAGE_RUNTIME_FUNCTION_ENTRY> functionEntries = new ArrayList<>();
|
List<_IMAGE_RUNTIME_FUNCTION_ENTRY> functionEntries = new ArrayList<>();
|
||||||
|
@ -132,7 +129,8 @@ public class ImageRuntimeFunctionEntries {
|
||||||
|
|
||||||
// Read and process the UNWIND_INFO structures the RUNTIME_INFO
|
// Read and process the UNWIND_INFO structures the RUNTIME_INFO
|
||||||
// structures point to
|
// structures point to
|
||||||
entry.unwindInfo = readUnwindInfo(reader, entry.unwindInfoAddressOrData, ntHeader);
|
entry.unwindInfo =
|
||||||
|
PEx64UnwindInfo.readUnwindInfo(reader, entry.unwindInfoAddressOrData, ntHeader);
|
||||||
|
|
||||||
functionEntries.add(entry);
|
functionEntries.add(entry);
|
||||||
}
|
}
|
||||||
|
@ -140,317 +138,32 @@ public class ImageRuntimeFunctionEntries {
|
||||||
reader.setPointerIndex(origIndex);
|
reader.setPointerIndex(origIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UNWIND_INFO readUnwindInfo(FactoryBundledWithBinaryReader reader, long offset,
|
|
||||||
NTHeader ntHeader) throws IOException {
|
|
||||||
long origIndex = reader.getPointerIndex();
|
|
||||||
|
|
||||||
long pointer = ntHeader.rvaToPointer(offset);
|
|
||||||
UNWIND_INFO unwindInfo = new UNWIND_INFO(pointer);
|
|
||||||
|
|
||||||
if (pointer < 0) {
|
|
||||||
return unwindInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.setPointerIndex(pointer);
|
|
||||||
byte splitByte = reader.readNextByte();
|
|
||||||
unwindInfo.version = (byte) (splitByte & UNWIND_INFO_VERSION_BITMASK);
|
|
||||||
unwindInfo.flags = (byte) (splitByte >> UNWIND_INFO_FLAGS_SHIFT);
|
|
||||||
|
|
||||||
unwindInfo.sizeOfProlog = reader.readNextUnsignedByte();
|
|
||||||
unwindInfo.countOfUnwindCodes = reader.readNextUnsignedByte();
|
|
||||||
|
|
||||||
splitByte = reader.readNextByte();
|
|
||||||
unwindInfo.frameRegister = (byte) (splitByte & UNWIND_INFO_FRAME_REGISTER_MASK);
|
|
||||||
unwindInfo.frameOffset = (byte) (splitByte >> UNWIND_INFO_FRAME_OFFSET_SHIFT);
|
|
||||||
|
|
||||||
unwindInfo.unwindCodes = new UNWIND_CODE[unwindInfo.countOfUnwindCodes];
|
|
||||||
for (int i = 0; i < unwindInfo.countOfUnwindCodes; i++) {
|
|
||||||
UNWIND_CODE code = new UNWIND_CODE();
|
|
||||||
code.offsetInProlog = reader.readNextByte();
|
|
||||||
|
|
||||||
int opCodeData = reader.readNextUnsignedByte();
|
|
||||||
code.opCode = UNWIND_CODE_OPCODE.fromInt((opCodeData & UNWIND_INFO_OPCODE_MASK));
|
|
||||||
code.opInfoRegister =
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.fromInt(opCodeData >> UNWIND_INFO_OPCODE_INFO_SHIFT);
|
|
||||||
|
|
||||||
unwindInfo.unwindCodes[i] = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can have an exception handler or you can have chained exception handling info only.
|
|
||||||
if (unwindInfo.hasExceptionHandler() || unwindInfo.hasUnwindHandler()) {
|
|
||||||
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();
|
|
||||||
|
|
||||||
// Follow the chain to the referenced UNWIND_INFO structure until we
|
|
||||||
// get to the end
|
|
||||||
unwindInfo.unwindHandlerChainInfo.unwindInfo = readUnwindInfo(reader,
|
|
||||||
unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData, ntHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.setPointerIndex(origIndex);
|
|
||||||
|
|
||||||
return unwindInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getRuntimeFunctionEntries() {
|
public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getRuntimeFunctionEntries() {
|
||||||
return functionEntries;
|
return functionEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class _IMAGE_RUNTIME_FUNCTION_ENTRY {
|
// FIXME: change name to conform to Java naming standards
|
||||||
public long beginAddress;
|
// FIXME: If public visibility is required improved member protection is needed
|
||||||
public long endAddress;
|
public static class _IMAGE_RUNTIME_FUNCTION_ENTRY {
|
||||||
public long unwindInfoAddressOrData;
|
long beginAddress;
|
||||||
public UNWIND_INFO unwindInfo;
|
long endAddress;
|
||||||
}
|
long unwindInfoAddressOrData;
|
||||||
|
PEx64UnwindInfo unwindInfo;
|
||||||
|
|
||||||
public enum UNWIND_CODE_OPCODE {
|
public void createData(Program program) {
|
||||||
UWOP_PUSH_NONVOL(0x00),
|
if (unwindInfoAddressOrData > 0) {
|
||||||
UWOP_ALLOC_LARGE(0x01),
|
|
||||||
UWOP_ALLOC_SMALL(0x02),
|
|
||||||
UWOP_SET_FPREG(0x03),
|
|
||||||
UWOP_SAVE_NONVOL(0x04),
|
|
||||||
UWOP_SAVE_NONVOL_FAR(0x05),
|
|
||||||
UWOP_SAVE_XMM(0x06),
|
|
||||||
UWOP_SAVE_XMM_FAR(0x07),
|
|
||||||
UWOP_SAVE_XMM128(0x08),
|
|
||||||
UWOP_SAVE_XMM128_FAR(0x09),
|
|
||||||
UWOP_PUSH_MACHFRAME(0x0A);
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
UNWIND_CODE_OPCODE(int value) {
|
|
||||||
id = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int id() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UNWIND_CODE_OPCODE fromInt(int id) {
|
|
||||||
UNWIND_CODE_OPCODE[] values = UNWIND_CODE_OPCODE.values();
|
|
||||||
for (UNWIND_CODE_OPCODE value : values) {
|
|
||||||
if (value.id == id) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum UNWIND_CODE_OPINFO_REGISTER {
|
|
||||||
UNWIND_OPINFO_REGISTER_RAX(0x00),
|
|
||||||
UNWIND_OPINFO_REGISTER_RCX(0x01),
|
|
||||||
UNWIND_OPINFO_REGISTER_RDX(0x02),
|
|
||||||
UNWIND_OPINFO_REGISTER_RBX(0x03),
|
|
||||||
UNWIND_OPINFO_REGISTER_RSP(0x04),
|
|
||||||
UNWIND_OPINFO_REGISTER_RBP(0x05),
|
|
||||||
UNWIND_OPINFO_REGISTER_RSI(0x06),
|
|
||||||
UNWIND_OPINFO_REGISTER_RDI(0x07),
|
|
||||||
UNWIND_OPINFO_REGISTER_R8(0x08),
|
|
||||||
UNWIND_OPINFO_REGISTER_R9(0x09),
|
|
||||||
UNWIND_OPINFO_REGISTER_R10(0x0A),
|
|
||||||
UNWIND_OPINFO_REGISTER_R11(0x0B),
|
|
||||||
UNWIND_OPINFO_REGISTER_R12(0x0C),
|
|
||||||
UNWIND_OPINFO_REGISTER_R13(0x0D),
|
|
||||||
UNWIND_OPINFO_REGISTER_R14(0x0E),
|
|
||||||
UNWIND_OPINFO_REGISTER_R15(0x0F);
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER(int value) {
|
|
||||||
id = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int id() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UNWIND_CODE_OPINFO_REGISTER fromInt(int id) {
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER[] values = UNWIND_CODE_OPINFO_REGISTER.values();
|
|
||||||
for (UNWIND_CODE_OPINFO_REGISTER value : values) {
|
|
||||||
if (value.id == id) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UNWIND_CODE {
|
|
||||||
public byte offsetInProlog;
|
|
||||||
public UNWIND_CODE_OPCODE opCode;
|
|
||||||
public UNWIND_CODE_OPINFO_REGISTER opInfoRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UNWIND_INFO implements StructConverter {
|
|
||||||
private static final String NAME = "UNWIND_INFO";
|
|
||||||
|
|
||||||
private final static int UNW_FLAG_NHANDLER = 0x0;
|
|
||||||
private final static int UNW_FLAG_EHANDLER = 0x1;
|
|
||||||
private final static int UNW_FLAG_UHANDLER = 0x2;
|
|
||||||
private final static int UNW_FLAG_CHAININFO = 0x4;
|
|
||||||
|
|
||||||
private final static int UNWIND_VERSION_FIELD_LENGTH = 0x03;
|
|
||||||
private final static int UNWIND_FLAGS_FIELD_LENGTH = 0x05;
|
|
||||||
private final static int UNWIND_FRAME_REGISTER_LENGTH = 0x04;
|
|
||||||
private final static int UNWIND_FRAME_OFFSET_LENGTH = 0x04;
|
|
||||||
private final static int UNWIND_OP_FIELD_LENGTH = 0x04;
|
|
||||||
private final static int UNWIND_OP_INFO_FIELD_LENGTH = 0x04;
|
|
||||||
|
|
||||||
byte version;
|
|
||||||
byte flags;
|
|
||||||
int sizeOfProlog;
|
|
||||||
int countOfUnwindCodes;
|
|
||||||
byte frameRegister;
|
|
||||||
byte frameOffset;
|
|
||||||
UNWIND_CODE[] unwindCodes;
|
|
||||||
int exceptionHandlerFunction;
|
|
||||||
_IMAGE_RUNTIME_FUNCTION_ENTRY unwindHandlerChainInfo;
|
|
||||||
|
|
||||||
long startOffset;
|
|
||||||
|
|
||||||
public UNWIND_INFO(long offset) {
|
|
||||||
startOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
|
||||||
|
|
||||||
StructureDataType struct = new StructureDataType(NAME + "_" + startOffset, 0);
|
|
||||||
struct.setPackingEnabled(true);
|
|
||||||
try {
|
try {
|
||||||
struct.addBitField(BYTE, UNWIND_VERSION_FIELD_LENGTH, "Version", null);
|
DataType dt = unwindInfo.toDataType();
|
||||||
struct.addBitField(defineFlagsEnum(), UNWIND_FLAGS_FIELD_LENGTH, "Flags", null);
|
Address start = program.getImageBase().add(unwindInfoAddressOrData);
|
||||||
struct.add(BYTE, "SizeOfProlog", null);
|
|
||||||
struct.add(BYTE, "CountOfUnwindCodes", null);
|
|
||||||
struct.addBitField(BYTE, UNWIND_FRAME_REGISTER_LENGTH, "FrameRegister", null);
|
|
||||||
struct.addBitField(BYTE, UNWIND_FRAME_OFFSET_LENGTH, "FrameOffset", null);
|
|
||||||
|
|
||||||
if (countOfUnwindCodes > 0) {
|
DataUtilities.createData(program, start, dt, dt.getLength(), true,
|
||||||
ArrayDataType unwindInfoArray =
|
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
||||||
new ArrayDataType(defineUnwindCodeStructure(), countOfUnwindCodes, -1);
|
}
|
||||||
struct.add(unwindInfoArray, "UnwindCodes", null);
|
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (InvalidDataTypeException e) {
|
|
||||||
throw new AssertException(e); // should never happen with byte bit-fields
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasExceptionHandler() || hasUnwindHandler()) {
|
|
||||||
struct.add(IBO32, "ExceptionHandler", null);
|
|
||||||
if (hasUnwindHandler()) {
|
|
||||||
struct.setFlexibleArrayComponent(UnsignedLongDataType.dataType, "ExceptionData",
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (hasChainedUnwindInfo()) {
|
|
||||||
struct.add(IBO32, "FunctionStartAddress", null);
|
|
||||||
struct.add(IBO32, "FunctionEndAddress", null);
|
|
||||||
struct.add(IBO32, "FunctionUnwindInfoAddress", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasExceptionHandler() {
|
|
||||||
return (flags & UNW_FLAG_EHANDLER) == UNW_FLAG_EHANDLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasUnwindHandler() {
|
|
||||||
return (flags & UNW_FLAG_UHANDLER) == UNW_FLAG_UHANDLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasChainedUnwindInfo() {
|
|
||||||
return (flags & UNW_FLAG_CHAININFO) == UNW_FLAG_CHAININFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumDataType defineFlagsEnum() {
|
|
||||||
EnumDataType flagsField = new EnumDataType("UNW_FLAGS", 1);
|
|
||||||
flagsField.add("UNW_FLAG_NHANDLER", UNW_FLAG_NHANDLER);
|
|
||||||
flagsField.add("UNW_FLAG_EHANDLER", UNW_FLAG_EHANDLER);
|
|
||||||
flagsField.add("UNW_FLAG_UHANDLER", UNW_FLAG_UHANDLER);
|
|
||||||
flagsField.add("UNW_FLAG_CHAININFO", UNW_FLAG_CHAININFO);
|
|
||||||
return flagsField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Structure defineUnwindCodeStructure() {
|
|
||||||
StructureDataType unwindCode = new StructureDataType("UnwindCode", 0);
|
|
||||||
unwindCode.setPackingEnabled(true);
|
|
||||||
try {
|
|
||||||
unwindCode.add(BYTE, "OffsetInProlog", null);
|
|
||||||
unwindCode.addBitField(defineUnwindOpCodeField(), UNWIND_OP_FIELD_LENGTH,
|
|
||||||
"UnwindOpCode", null);
|
|
||||||
unwindCode.addBitField(defineUnwindCodeRegisterField(), UNWIND_OP_INFO_FIELD_LENGTH,
|
|
||||||
"OpInfo", null);
|
|
||||||
}
|
|
||||||
catch (InvalidDataTypeException e) {
|
|
||||||
throw new AssertException(e); // should never happen with byte bit-fields
|
|
||||||
}
|
|
||||||
return unwindCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumDataType defineUnwindOpCodeField() {
|
|
||||||
EnumDataType unwindOpCodeField = new EnumDataType("UNWIND_CODE_OPCODE", 1);
|
|
||||||
unwindOpCodeField.add("UWOP_PUSH_NONVOL", UNWIND_CODE_OPCODE.UWOP_PUSH_NONVOL.id);
|
|
||||||
unwindOpCodeField.add("UWOP_ALLOC_LARGE", UNWIND_CODE_OPCODE.UWOP_ALLOC_LARGE.id);
|
|
||||||
unwindOpCodeField.add("UWOP_ALLOC_SMALL", UNWIND_CODE_OPCODE.UWOP_ALLOC_SMALL.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SET_FPREG", UNWIND_CODE_OPCODE.UWOP_SET_FPREG.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_NONVOL", UNWIND_CODE_OPCODE.UWOP_SAVE_NONVOL.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_NONVOL_FAR",
|
|
||||||
UNWIND_CODE_OPCODE.UWOP_SAVE_NONVOL_FAR.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_XMM", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_XMM_FAR", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM_FAR.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_XMM128", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM128.id);
|
|
||||||
unwindOpCodeField.add("UWOP_SAVE_XMM128_FAR",
|
|
||||||
UNWIND_CODE_OPCODE.UWOP_SAVE_XMM128_FAR.id);
|
|
||||||
unwindOpCodeField.add("UWOP_PUSH_MACHFRAME", UNWIND_CODE_OPCODE.UWOP_PUSH_MACHFRAME.id);
|
|
||||||
|
|
||||||
return unwindOpCodeField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumDataType defineUnwindCodeRegisterField() {
|
|
||||||
EnumDataType unwindCodeRegisterField =
|
|
||||||
new EnumDataType("UNWIND_CODE_OPINFO_REGISTER", 1);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RAX",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RAX.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RCX",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RCX.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RDX",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RDX.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RBX",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RBX.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RSP",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RSP.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RBP",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RBP.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RSI",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RSI.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RDI",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RDI.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R8",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R8.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R9",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R9.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R10",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R10.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R11",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R11.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R12",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R12.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R13",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R13.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R14",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R14.id);
|
|
||||||
unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R15",
|
|
||||||
UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R15.id);
|
|
||||||
|
|
||||||
return unwindCodeRegisterField;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
/* ###
|
||||||
|
* 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 ghidra.app.util.bin.StructConverter;
|
||||||
|
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
||||||
|
import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
// TODO: If public visibility is required improved member protection is needed
|
||||||
|
class PEx64UnwindInfo implements StructConverter {
|
||||||
|
|
||||||
|
final static int UNW_FLAG_NHANDLER = 0x0;
|
||||||
|
final static int UNW_FLAG_EHANDLER = 0x1;
|
||||||
|
final static int UNW_FLAG_UHANDLER = 0x2;
|
||||||
|
final static int UNW_FLAG_CHAININFO = 0x4;
|
||||||
|
|
||||||
|
private final static int UNWIND_INFO_VERSION_MASK = 0x07;
|
||||||
|
private final static int UNWIND_INFO_FLAGS_MASK = 0x1F;
|
||||||
|
private final static int UNWIND_INFO_FLAGS_SHIFT = 0x03;
|
||||||
|
private final static int UNWIND_INFO_FRAME_REGISTER_MASK = 0x0F;
|
||||||
|
private final static int UNWIND_INFO_FRAME_OFFSET_SHIFT = 0x04;
|
||||||
|
private final static int UNWIND_INFO_OPCODE_MASK = 0x0F;
|
||||||
|
private final static int UNWIND_INFO_OPCODE_INFO_SHIFT = 0x04;
|
||||||
|
private final static int UNWIND_INFO_OPCODE_INFO_MASK = 0x0F;
|
||||||
|
|
||||||
|
byte version;
|
||||||
|
byte flags;
|
||||||
|
int sizeOfProlog;
|
||||||
|
int countOfUnwindCodes;
|
||||||
|
byte frameRegister;
|
||||||
|
byte frameOffset;
|
||||||
|
UNWIND_CODE[] unwindCodes;
|
||||||
|
int exceptionHandlerFunction;
|
||||||
|
_IMAGE_RUNTIME_FUNCTION_ENTRY unwindHandlerChainInfo;
|
||||||
|
|
||||||
|
long startOffset;
|
||||||
|
|
||||||
|
public PEx64UnwindInfo(long offset) {
|
||||||
|
startOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
return PEx64UnwindInfoDataType.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasExceptionHandler() {
|
||||||
|
return (flags & UNW_FLAG_EHANDLER) == UNW_FLAG_EHANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasUnwindHandler() {
|
||||||
|
return (flags & UNW_FLAG_UHANDLER) == UNW_FLAG_UHANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasChainedUnwindInfo() {
|
||||||
|
return (flags & UNW_FLAG_CHAININFO) == UNW_FLAG_CHAININFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: change name to conform to Java naming standards
|
||||||
|
public static enum UNWIND_CODE_OPCODE {
|
||||||
|
UWOP_PUSH_NONVOL(0x00),
|
||||||
|
UWOP_ALLOC_LARGE(0x01),
|
||||||
|
UWOP_ALLOC_SMALL(0x02),
|
||||||
|
UWOP_SET_FPREG(0x03),
|
||||||
|
UWOP_SAVE_NONVOL(0x04),
|
||||||
|
UWOP_SAVE_NONVOL_FAR(0x05),
|
||||||
|
UWOP_SAVE_XMM(0x06),
|
||||||
|
UWOP_SAVE_XMM_FAR(0x07),
|
||||||
|
UWOP_SAVE_XMM128(0x08),
|
||||||
|
UWOP_SAVE_XMM128_FAR(0x09),
|
||||||
|
UWOP_PUSH_MACHFRAME(0x0A);
|
||||||
|
|
||||||
|
public final int id;
|
||||||
|
|
||||||
|
UNWIND_CODE_OPCODE(int value) {
|
||||||
|
id = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UNWIND_CODE_OPCODE fromInt(int id) {
|
||||||
|
UNWIND_CODE_OPCODE[] values = UNWIND_CODE_OPCODE.values();
|
||||||
|
for (UNWIND_CODE_OPCODE value : values) {
|
||||||
|
if (value.id == id) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: change name to conform to Java naming standards
|
||||||
|
// public static enum UNWIND_INFO_REGISTER {
|
||||||
|
// RAX(0x00),
|
||||||
|
// RCX(0x01),
|
||||||
|
// RDX(0x02),
|
||||||
|
// RBX(0x03),
|
||||||
|
// RSP(0x04),
|
||||||
|
// RBP(0x05),
|
||||||
|
// RSI(0x06),
|
||||||
|
// RDI(0x07),
|
||||||
|
// R8(0x08),
|
||||||
|
// R9(0x09),
|
||||||
|
// R10(0x0A),
|
||||||
|
// R11(0x0B),
|
||||||
|
// R12(0x0C),
|
||||||
|
// R13(0x0D),
|
||||||
|
// R14(0x0E),
|
||||||
|
// R15(0x0F);
|
||||||
|
//
|
||||||
|
// public final int id;
|
||||||
|
//
|
||||||
|
// UNWIND_INFO_REGISTER(int value) {
|
||||||
|
// id = value;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public int id() {
|
||||||
|
// return id;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static UNWIND_INFO_REGISTER fromInt(int id) {
|
||||||
|
// UNWIND_INFO_REGISTER[] values = UNWIND_INFO_REGISTER.values();
|
||||||
|
// for (UNWIND_INFO_REGISTER value : values) {
|
||||||
|
// if (value.id == id) {
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// FIXME: change name to conform to Java naming standards
|
||||||
|
// TODO: If public visibility is required improved member protection is needed
|
||||||
|
static class UNWIND_CODE {
|
||||||
|
byte offsetInProlog;
|
||||||
|
UNWIND_CODE_OPCODE opCode;
|
||||||
|
byte opInfo; // encoding varies based upon opCode
|
||||||
|
}
|
||||||
|
|
||||||
|
static PEx64UnwindInfo readUnwindInfo(FactoryBundledWithBinaryReader reader,
|
||||||
|
long offset, NTHeader ntHeader) throws IOException {
|
||||||
|
long origIndex = reader.getPointerIndex();
|
||||||
|
|
||||||
|
long pointer = ntHeader.rvaToPointer(offset);
|
||||||
|
PEx64UnwindInfo unwindInfo = new PEx64UnwindInfo(pointer);
|
||||||
|
|
||||||
|
if (pointer < 0) {
|
||||||
|
return unwindInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.setPointerIndex(pointer);
|
||||||
|
byte splitByte = reader.readNextByte();
|
||||||
|
unwindInfo.version = (byte) (splitByte & UNWIND_INFO_VERSION_MASK);
|
||||||
|
unwindInfo.flags = (byte) ((splitByte >> UNWIND_INFO_FLAGS_SHIFT) & UNWIND_INFO_FLAGS_MASK);
|
||||||
|
|
||||||
|
unwindInfo.sizeOfProlog = reader.readNextUnsignedByte();
|
||||||
|
unwindInfo.countOfUnwindCodes = reader.readNextUnsignedByte();
|
||||||
|
|
||||||
|
splitByte = reader.readNextByte();
|
||||||
|
unwindInfo.frameRegister = (byte) (splitByte & UNWIND_INFO_FRAME_REGISTER_MASK);
|
||||||
|
unwindInfo.frameOffset = (byte) (splitByte >> UNWIND_INFO_FRAME_OFFSET_SHIFT);
|
||||||
|
|
||||||
|
unwindInfo.unwindCodes = new UNWIND_CODE[unwindInfo.countOfUnwindCodes];
|
||||||
|
for (int i = 0; i < unwindInfo.countOfUnwindCodes; i++) {
|
||||||
|
UNWIND_CODE code = new UNWIND_CODE();
|
||||||
|
code.offsetInProlog = reader.readNextByte();
|
||||||
|
|
||||||
|
int opCodeData = reader.readNextUnsignedByte();
|
||||||
|
code.opCode = UNWIND_CODE_OPCODE.fromInt((opCodeData & UNWIND_INFO_OPCODE_MASK));
|
||||||
|
code.opInfo = (byte) ((opCodeData >> UNWIND_INFO_OPCODE_INFO_SHIFT) &
|
||||||
|
UNWIND_INFO_OPCODE_INFO_MASK);
|
||||||
|
// code.opInfoRegister =
|
||||||
|
// UNWIND_CODE_OPINFO_REGISTER.fromInt(opCodeData >> UNWIND_INFO_OPCODE_INFO_SHIFT);
|
||||||
|
|
||||||
|
unwindInfo.unwindCodes[i] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can have an exception handler or you can have chained exception handling info only.
|
||||||
|
if (unwindInfo.hasExceptionHandler() || unwindInfo.hasUnwindHandler()) {
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Follow the chain to the referenced UNWIND_INFO structure until we
|
||||||
|
// get to the end
|
||||||
|
unwindInfo.unwindHandlerChainInfo.unwindInfo = readUnwindInfo(reader,
|
||||||
|
unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData, ntHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.setPointerIndex(origIndex);
|
||||||
|
|
||||||
|
return unwindInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
/* ###
|
||||||
|
* 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 ghidra.app.util.bin.format.pe.PEx64UnwindInfo.UNWIND_CODE_OPCODE;
|
||||||
|
import ghidra.docking.settings.Settings;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
|
public class PEx64UnwindInfoDataType extends DynamicDataType {
|
||||||
|
|
||||||
|
public static final PEx64UnwindInfoDataType INSTANCE = new PEx64UnwindInfoDataType();
|
||||||
|
|
||||||
|
private final static int UNWIND_VERSION_FIELD_LENGTH = 0x03;
|
||||||
|
private final static int UNWIND_FLAGS_FIELD_LENGTH = 0x05;
|
||||||
|
private final static int UNWIND_FRAME_REGISTER_LENGTH = 0x04;
|
||||||
|
private final static int UNWIND_FRAME_OFFSET_LENGTH = 0x04;
|
||||||
|
private final static int UNWIND_OP_FIELD_LENGTH = 0x04;
|
||||||
|
private final static int UNWIND_OP_INFO_FIELD_LENGTH = 0x04;
|
||||||
|
|
||||||
|
private final static DataType BYTE = ByteDataType.dataType;
|
||||||
|
private final static DataType IBO32 = new ImageBaseOffset32DataType();
|
||||||
|
|
||||||
|
public PEx64UnwindInfoDataType() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PEx64UnwindInfoDataType(DataTypeManager dtm) {
|
||||||
|
super("PEx64_UnwindInfo", dtm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType clone(DataTypeManager dtm) {
|
||||||
|
if (dtm == getDataTypeManager()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return new PEx64UnwindInfoDataType(dtm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Dynamic structure for PE Exception UNWIND_INFO";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMnemonic(Settings settings) {
|
||||||
|
return "UNWIND_INFO";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultLabelPrefix() {
|
||||||
|
return "UNWIND_INFO";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||||
|
return null; // TODO: Should we return filled-out structure? Caching?
|
||||||
|
}
|
||||||
|
|
||||||
|
private Structure getStructure(MemBuffer buf) {
|
||||||
|
|
||||||
|
StructureDataType struct;
|
||||||
|
try {
|
||||||
|
byte flags = (byte) (buf.getByte(0) >> UNWIND_VERSION_FIELD_LENGTH);
|
||||||
|
|
||||||
|
struct = new StructureDataType("UNWIND_INFO", 0, dataMgr);
|
||||||
|
struct.setPackingEnabled(true);
|
||||||
|
try {
|
||||||
|
struct.addBitField(BYTE, UNWIND_VERSION_FIELD_LENGTH, "Version", null);
|
||||||
|
struct.addBitField(defineUnwindInfoFlags(), UNWIND_FLAGS_FIELD_LENGTH, "Flags",
|
||||||
|
null);
|
||||||
|
struct.add(BYTE, "SizeOfProlog", null);
|
||||||
|
struct.add(BYTE, "CountOfUnwindCodes", null);
|
||||||
|
struct.addBitField(BYTE, UNWIND_FRAME_REGISTER_LENGTH, "FrameRegister", null);
|
||||||
|
struct.addBitField(BYTE, UNWIND_FRAME_OFFSET_LENGTH, "FrameOffset", null);
|
||||||
|
|
||||||
|
int countOfUnwindCodes = buf.getByte(2);
|
||||||
|
if (countOfUnwindCodes > 0) {
|
||||||
|
ArrayDataType unwindInfoArray =
|
||||||
|
new ArrayDataType(defineUnwindCodeStructure(), countOfUnwindCodes, -1);
|
||||||
|
struct.add(unwindInfoArray, "UnwindCodes", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidDataTypeException e) {
|
||||||
|
throw new AssertException(e); // should never happen with byte bit-fields
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasExceptionHandler(flags) || hasUnwindHandler(flags)) {
|
||||||
|
struct.add(IBO32, "ExceptionHandler", null);
|
||||||
|
if (hasUnwindHandler(flags)) {
|
||||||
|
// NOTE: Dynamic structure does not reflect flex-array
|
||||||
|
struct.setFlexibleArrayComponent(UnsignedLongDataType.dataType, "ExceptionData",
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hasChainedUnwindInfo(flags)) {
|
||||||
|
struct.add(IBO32, "FunctionStartAddress", null);
|
||||||
|
struct.add(IBO32, "FunctionEndAddress", null);
|
||||||
|
struct.add(IBO32, "FunctionUnwindInfoAddress", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MemoryAccessException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DataTypeComponent[] getAllComponents(MemBuffer buf) {
|
||||||
|
Structure struct = getStructure(buf);
|
||||||
|
if (struct == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DataTypeComponent[] components = struct.getComponents();
|
||||||
|
if (struct.hasFlexibleArrayComponent()) {
|
||||||
|
DataTypeComponent[] newArray = new DataTypeComponent[components.length + 1];
|
||||||
|
System.arraycopy(components, 0, newArray, 0, components.length);
|
||||||
|
newArray[components.length] = struct.getFlexibleArrayComponent();
|
||||||
|
components = newArray;
|
||||||
|
}
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasExceptionHandler(int flags) {
|
||||||
|
return (flags & PEx64UnwindInfo.UNW_FLAG_EHANDLER) == PEx64UnwindInfo.UNW_FLAG_EHANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasUnwindHandler(int flags) {
|
||||||
|
return (flags & PEx64UnwindInfo.UNW_FLAG_UHANDLER) == PEx64UnwindInfo.UNW_FLAG_UHANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasChainedUnwindInfo(int flags) {
|
||||||
|
return (flags & PEx64UnwindInfo.UNW_FLAG_CHAININFO) == PEx64UnwindInfo.UNW_FLAG_CHAININFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Structure defineUnwindCodeStructure() {
|
||||||
|
StructureDataType unwindCode = new StructureDataType("UnwindCode", 0);
|
||||||
|
unwindCode.setPackingEnabled(true);
|
||||||
|
try {
|
||||||
|
unwindCode.add(BYTE, "OffsetInProlog", null);
|
||||||
|
unwindCode.addBitField(defineUnwindOpCodeEnum(), UNWIND_OP_FIELD_LENGTH, "UnwindOpCode",
|
||||||
|
null);
|
||||||
|
// UnwindOpInfo encoding varies with UnwindOpCode
|
||||||
|
unwindCode.addBitField(BYTE, UNWIND_OP_INFO_FIELD_LENGTH, "UnwindOpInfo", null);
|
||||||
|
}
|
||||||
|
catch (InvalidDataTypeException e) {
|
||||||
|
throw new AssertException(e); // should never happen with byte bit-fields
|
||||||
|
}
|
||||||
|
return unwindCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EnumDataType unwindInfoFlagsEnum;
|
||||||
|
|
||||||
|
private EnumDataType defineUnwindInfoFlags() {
|
||||||
|
if (unwindInfoFlagsEnum == null) {
|
||||||
|
unwindInfoFlagsEnum = new EnumDataType("UNW_FLAGS", 1);
|
||||||
|
unwindInfoFlagsEnum.add("UNW_FLAG_NHANDLER", PEx64UnwindInfo.UNW_FLAG_NHANDLER);
|
||||||
|
unwindInfoFlagsEnum.add("UNW_FLAG_EHANDLER", PEx64UnwindInfo.UNW_FLAG_EHANDLER);
|
||||||
|
unwindInfoFlagsEnum.add("UNW_FLAG_UHANDLER", PEx64UnwindInfo.UNW_FLAG_UHANDLER);
|
||||||
|
unwindInfoFlagsEnum.add("UNW_FLAG_CHAININFO", PEx64UnwindInfo.UNW_FLAG_CHAININFO);
|
||||||
|
}
|
||||||
|
return unwindInfoFlagsEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EnumDataType unwindCodeOpcodeEnum;
|
||||||
|
|
||||||
|
private static synchronized EnumDataType defineUnwindOpCodeEnum() {
|
||||||
|
if (unwindCodeOpcodeEnum == null) {
|
||||||
|
unwindCodeOpcodeEnum = new EnumDataType("UNWIND_CODE_OPCODE", 1);
|
||||||
|
for (UNWIND_CODE_OPCODE value : UNWIND_CODE_OPCODE.values()) {
|
||||||
|
unwindCodeOpcodeEnum.add(value.name(), value.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unwindCodeOpcodeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private static EnumDataType unwindRegisterEnum;
|
||||||
|
//
|
||||||
|
// private static EnumDataType defineUnwindRegisterEnum() {
|
||||||
|
// if (unwindRegisterEnum == null) {
|
||||||
|
// unwindRegisterEnum = new EnumDataType("UNWIND_CODE_OPINFO_REGISTER", 1);
|
||||||
|
// for (UNWIND_INFO_REGISTER value : UNWIND_INFO_REGISTER.values()) {
|
||||||
|
// unwindRegisterEnum.add(value.name(), value.id);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return unwindRegisterEnum;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
|
@ -304,18 +304,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
||||||
// which also needs to be laid out. When they contain chaining data
|
// which also needs to be laid out. When they contain chaining data
|
||||||
// they're recursive but the toDataType() function handles that.
|
// they're recursive but the toDataType() function handles that.
|
||||||
for (_IMAGE_RUNTIME_FUNCTION_ENTRY entry : irfes) {
|
for (_IMAGE_RUNTIME_FUNCTION_ENTRY entry : irfes) {
|
||||||
if (entry.unwindInfoAddressOrData > 0) {
|
entry.createData(program);
|
||||||
try {
|
|
||||||
dt = (StructureDataType) entry.unwindInfo.toDataType();
|
|
||||||
start = program.getImageBase().add(entry.unwindInfoAddressOrData);
|
|
||||||
|
|
||||||
DataUtilities.createData(program, start, dt, dt.getLength(), true,
|
|
||||||
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
|
|
||||||
}
|
|
||||||
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue