GT-2867 - PDB Universal changes

This commit is contained in:
ghizard 2019-05-14 16:28:56 -04:00
parent da72cbedf5
commit f10a766506
28 changed files with 1664 additions and 345 deletions

View file

@ -111,7 +111,7 @@ public abstract class AbstractDatabaseInterface {
throws IOException, PdbException, CancelledException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor);
deserializeHeader(reader);
deserializeInternalSubstreams(reader);
deserializeInternalSubstreams(reader, monitor);
deserializeAdditionalSubstreams(monitor);
return versionNumber;
@ -259,9 +259,12 @@ public abstract class AbstractDatabaseInterface {
/**
* Deserializes the SubStreams internal to the Database Interface stream.
* @param reader {@link PdbByteReader} from which to deserialize the data.
* @param monitor {@link TaskMonitor} used for checking cancellation.
* @throws PdbException upon error parsing a field.
* @throws CancelledException Upon user cancellation.
*/
protected abstract void deserializeInternalSubstreams(PdbByteReader reader) throws PdbException;
protected abstract void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor)
throws PdbException, CancelledException;
/**
* Deserializes the AdditionalSubstreams components.

View file

@ -63,7 +63,7 @@ public abstract class AbstractPdb implements AutoCloseable {
protected AbstractTypeProgramInterface typeProgramInterface;
protected AbstractDatabaseInterface databaseInterface;
protected int targetProcessorIndexNumber = 0xffff;
protected Processor targetProcessor = Processor.UNKNOWN;
// Items below begin in Pdb400
protected boolean minimalDebugInfo = false;
@ -220,20 +220,29 @@ public abstract class AbstractPdb implements AutoCloseable {
/**
* Get the index number of the target processor used for compilation. Also see
* {@link ProcessorName} and {@link RegisterName}.
* {@link Processor} and {@link RegisterName}.
* @return Index number of the target processor used for compilation.
*/
public int getTargetProcessorIndexNumber() {
return targetProcessorIndexNumber;
public Processor getTargetProcessor() {
return targetProcessor;
}
/**
* Set the index number of the target processor used for compilation. Also see
* {@link ProcessorName} and {@link RegisterName}.
* @param targetProcessorIndexNumberIn Processor identifier.
* {@link Processor} and {@link RegisterName}.
* @param targetProcessorIn Processor identifier.
*/
public void setTargetProcessorIndexNumber(int targetProcessorIndexNumberIn) {
targetProcessorIndexNumber = targetProcessorIndexNumberIn;
public void setTargetProcessor(Processor targetProcessorIn) {
/**
* Should we allow an overwrite? The {@link DatabaseInterfaceNew} value (mapped from
* {@link ImageFileMachine} should be processed and laid down first. Subsequent values
* can come from {@link AbstractCompile2MsSymbol} and {@link Compile3MsSymbol}. Note:
* {@link DatabaseInterface} does not carry {@link ImageFileMachine}, and thus no mapping
* is applied.
*/
if (targetProcessor == Processor.UNKNOWN) {
targetProcessor = targetProcessorIn;
}
}
/**

View file

@ -24,7 +24,7 @@ package ghidra.pdb.pdbreader;
* index is just a record number (as in the case of data type or item type; it is a made up,
* one-up number for symbols).
*/
public class CategoryIndex {
public class CategoryIndex implements Comparable<CategoryIndex> {
/**
* Enum for categories: DATA, ITEM, and SYMBOL.
@ -115,4 +115,10 @@ public class CategoryIndex {
string += index;
return string;
}
@Override
public int compareTo(CategoryIndex other) {
int catVal = this.category.compareTo(other.getCategory());
return (catVal != 0) ? catVal : this.index - other.index;
}
}

View file

@ -57,7 +57,8 @@ class DatabaseInterface extends AbstractDatabaseInterface {
}
@Override
protected void deserializeInternalSubstreams(PdbByteReader reader) throws PdbException {
protected void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor)
throws PdbException, CancelledException {
processModuleInformation(reader, false);
processSectionContributions(reader, false);
processSegmentMap(reader, false);

View file

@ -50,11 +50,12 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
protected int lengthEditAndContinueSubstream = 0; // signed 32-bit
protected int flags = 0; // unsigned 16-bit
protected int machineType = 0; // unsigned 16-bit
protected ImageFileMachine machineType; // parsed unsigned 16-bit and interpreted.
protected long padReserve = 0; // unsigned 32-bit
protected List<String> editAndContinueNameList = new ArrayList<>();
protected List<Integer> debugStreamList = new ArrayList<>(); // TODO: this is a guess.
protected DebugData debugData;
//==============================================================================================
// API
@ -66,6 +67,23 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
*/
public DatabaseInterfaceNew(AbstractPdb pdb, int streamNumber) {
super(pdb, streamNumber);
debugData = new DebugData(pdb);
}
/**
* Returns the {@link ImageFileMachine} machine type.
* @return the machine type.
*/
public ImageFileMachine getMachineType() {
return machineType;
}
/**
* Returns the {@link DebugData} for this {@link DatabaseInterfaceNew}.
* @return the {@link DebugData}.
*/
public DebugData getDebugData() {
return debugData;
}
//==============================================================================================
@ -99,23 +117,25 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
lengthEditAndContinueSubstream = reader.parseInt();
flags = reader.parseUnsignedShortVal();
machineType = reader.parseUnsignedShortVal();
machineType = ImageFileMachine.fromValue(reader.parseUnsignedShortVal());
pdb.setTargetProcessor(machineType.getProcessor());
padReserve = reader.parseUnsignedIntVal();
}
@Override
protected void deserializeInternalSubstreams(PdbByteReader reader) throws PdbException {
protected void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor)
throws PdbException, CancelledException {
processModuleInformation(reader, false);
processSectionContributions(reader, false);
processSegmentMap(reader, false);
processFileInformation(reader, false);
// super.deserializeInternalSubstreams(reader);
processTypeServerMap(reader, false);
//Note that the next two are in reverse order from their length fields in the header.
processEditAndContinueInformation(reader, false);
processDebugHeader(reader, false);
//processDebugHeader(reader, false);
debugData.deserializeHeader(reader, monitor);
}
@Override
@ -126,8 +146,8 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
// globalSymbolInformation.deserialize(monitor);
symbolRecords.deserialize(monitor);
//TODO: Process further information that might be found from ProcessTypeServerMap,
// processEditAndContinueInformation, and processDebugHeader. The last of these created
// a list of debug streams (also seen in each SectionContributionInformation).
// and processEditAndContinueInformation.
debugData.deserialize(monitor);
}
@Override
@ -186,7 +206,7 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
builder.append("\nlengthEditAndContinueSubstream: ");
builder.append(lengthEditAndContinueSubstream);
builder.append(String.format("\nflags: 0x%04x", flags));
builder.append(String.format("\nmachineType: 0x%04x", machineType));
builder.append(String.format("\nmachineType: %s", machineType.toString()));
builder.append("\npadReserve: ");
builder.append(padReserve);
writer.write(builder.toString());
@ -203,13 +223,10 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
writer.write("SegmentMap--------------------------------------------------\n");
dumpSegmentMap(writer);
writer.write("\nEnd SegmentMap----------------------------------------------\n");
// super.dumpInternalSubstreams();
writer.write("EditAndContinueNameList-------------------------------------\n");
dumpEditAndContinueNameList(writer);
writer.write("\nEditAndContinueNameList-------------------------------------\n");
writer.write("DebugStreamList---------------------------------------------\n");
dumpDebugStreamList(writer);
writer.write("\nEnd DebugStreamList-----------------------------------------\n");
writer.write("\nEnd EditAndContinueNameList---------------------------------\n");
debugData.dump(writer);
}
//==============================================================================================
@ -304,28 +321,6 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
}
}
/**
* Deserializes/Processes the DebugHeader.
* @param reader {@link PdbByteReader} from which to deserialize the data.
* @param skip Skip over the data in the {@link PdbByteReader}.
* @throws PdbException Upon not enough data left to parse.
*/
protected void processDebugHeader(PdbByteReader reader, boolean skip) throws PdbException {
if (lengthOptionalDebugHeader == 0) {
return;
}
if (skip) {
reader.skip(lengthOptionalDebugHeader);
return;
}
PdbByteReader substreamReader = reader.getSubPdbByteReader(lengthOptionalDebugHeader);
//System.out.println(substreamReader.dump(0x1000));
while (substreamReader.hasMore()) {
int debugStreamNumber = substreamReader.parseUnsignedShortVal();
debugStreamList.add(debugStreamNumber);
}
}
/**
* Dumps the EditAndContinueNameList. This package-protected method is for debugging only.
* @param writer {@link Writer} to which to write the debug dump.
@ -337,15 +332,4 @@ public class DatabaseInterfaceNew extends AbstractDatabaseInterface {
}
}
/**
* Dumps the DebugStreamList. This package-protected method is for debugging only.
* @param writer {@link Writer} to which to write the debug dump.
* @throws IOException On issue writing to the {@link Writer}.
*/
protected void dumpDebugStreamList(Writer writer) throws IOException {
for (int strmNumber : debugStreamList) {
writer.write(String.format("StrmNumber: %04x\n", strmNumber));
}
}
}

View file

@ -0,0 +1,328 @@
/* ###
* 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.pdb.pdbreader;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Debug Data structures for PDB files. There are a number of debug streams that can be processed.
* <P>
* NOTE: The processing that falls under DebugData is only partially done. We have implemented
* and viewed the results of real data for:
* <LI> SECTION_HEADER.</LI>
* <P>
* We have partially implemented the following:
* <li> FRAME_POINTER_OMISSION</LI>
* <li> X_DATA</LI>
* <li> P_DATA</LI>
*/
public class DebugData {
public enum DebugType {
FRAME_POINTER_OMISSION(0),
EXCEPTION(1),
FIXUP(2),
OMAP_TO_SOURCE(3),
OMAP_FROM_SOURCE(4),
SECTION_HEADER(5),
TOKEN_RID_MAP(6),
X_DATA(7),
P_DATA(8),
NEW_FRAME_POINTER_OMISSION(9),
SECTION_HEADER_ORIG(10);
private final int value;
private DebugType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
//==============================================================================================
// Internals
//==============================================================================================
private AbstractPdb pdb;
private List<Integer> debugStreamList = new ArrayList<>();
private List<FramePointerOmissionRecord> framePointerOmissionData = new ArrayList<>();
private List<ImageSectionHeader> imageSectionHeaders = new ArrayList<>();
private List<ImageFunctionEntry> pData = new ArrayList<>();
private RvaVaDebugHeader xDataHeader;
private PdbByteReader xDataReader;
//==============================================================================================
// API
//==============================================================================================
/**
* Constructor.
* @param pdb {@link AbstractPdb} that owns this {@link DebugData}.
*/
public DebugData(AbstractPdb pdb) {
this.pdb = pdb;
}
/**
* Returns the {@link List}<{@link ImageSectionHeader}>.
* @return the imageSectionHeaders.
*/
public List<ImageSectionHeader> getImageSectionHeaders() {
return imageSectionHeaders;
}
/**
* Deserialized {@link DebugData} header from the {@link PdbByteReader} input. This parses
* stream numbers for varying Debug Types--the order/location of the stream number is for
* each particular debug type (i.e., the first stream number read is for the stream containing
* Frame Pointer Omission debug data. I stream number of 0XFFFF says that there is no data
* for that debug type; else the stream number represents the stream that should
* be deserialized to retrieve the debug data of that type. The
* {@link #deserialize(TaskMonitor)} method deserializes each of these streams
* that are valid to the corresponding debug data type.
* @param reader {@link PdbByteReader} from which to parse the header.
* @param monitor {@link TaskMonitor} used for checking cancellation.
* @throws PdbException PdbException Upon error in processing components.
* @throws CancelledException Upon user cancellation.
*/
public void deserializeHeader(PdbByteReader reader, TaskMonitor monitor)
throws PdbException, CancelledException {
while (reader.hasMore()) {
monitor.checkCanceled();
int debugStreamNumber = reader.parseUnsignedShortVal();
debugStreamList.add(debugStreamNumber);
}
if (debugStreamList.size() != DebugType.values().length) {
// TODO: implement something.
//log.appendMsg("Unrecognized extra debug streams");
}
}
/**
* Deserialized each valid {@link DebugData} stream, based upon valid stream numbers found while
* parsing the {@link DebugData} header.
* @param monitor {@link TaskMonitor} used for checking cancellation.
* @throws PdbException PdbException Upon error in processing components.
* @throws CancelledException Upon user cancellation.
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes.
*/
public void deserialize(TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
if (debugStreamList.isEmpty()) {
throw new PdbException(
"DebugData Header had not been deserialized at the appropriate time");
}
for (DebugType dbg : DebugType.values()) {
int streamNum = debugStreamList.get(dbg.getValue());
if (streamNum == 0XFFFF) {
continue;
}
switch (dbg) {
case FRAME_POINTER_OMISSION:
// TODO: implement.
deserializeFramePointerOmissionData(streamNum, monitor);
break;
case EXCEPTION:
// TODO: implement.
break;
case FIXUP:
// TODO: implement.
break;
case OMAP_TO_SOURCE:
// TODO: implement.
break;
case OMAP_FROM_SOURCE:
// TODO: implement.
break;
case SECTION_HEADER:
deserializeSectionHeader(streamNum, monitor);
break;
case TOKEN_RID_MAP:
// TODO: implement.
break;
case X_DATA:
deserializeXData(streamNum, monitor);
break;
case P_DATA:
deserializePData(streamNum, monitor);
break;
case NEW_FRAME_POINTER_OMISSION:
// TODO: implement.
break;
case SECTION_HEADER_ORIG:
// TODO: implement.
break;
}
}
}
private void deserializeFramePointerOmissionData(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
while (reader.hasMore()) {
FramePointerOmissionRecord framePointerOmissionRecord =
new FramePointerOmissionRecord();
framePointerOmissionRecord.parse(reader);
framePointerOmissionData.add(framePointerOmissionRecord);
}
}
private void deserializeSectionHeader(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
while (reader.hasMore()) {
ImageSectionHeader imageSectionHeader = new ImageSectionHeader();
imageSectionHeader.parse(reader);
imageSectionHeaders.add(imageSectionHeader);
}
}
/**
* See the {@link LinkerUnwindInfo} class that was built for and is pertinent to
* processing XData.
*/
private void deserializeXData(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
// TODO: implement.
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
int streamLength = reader.getLimit();
//System.out.println(reader.dump(0x20));
RvaVaDebugHeader header = new RvaVaDebugHeader();
xDataHeader = header;
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return; // Silent... TODO: add logging event.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug XData");
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
xDataReader = reader.getSubPdbByteReader(reader.numRemaining());
// TODO: This is a partial implementation. We need to figure out more to know
// how to deal with it. The only API information regarding the XData is with
// regard to processing PData when the "machine" is IA64 or AMD64. The interpretation
// for these machines is not real clear (or a bit of work), and there is no other
// interpretation available when the machine is different.
}
private void deserializePData(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
int streamLength = reader.getLimit();
RvaVaDebugHeader header = new RvaVaDebugHeader();
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return; // Silent... TODO: add logging event.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug PData");
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
while (reader.hasMore()) {
ImageFunctionEntry entry = new ImageFunctionEntry();
entry.deserialize(reader);
pData.add(entry);
long endPrologue = entry.getEndOfPrologueAddress();
long base = xDataHeader.getRelativeVirtualAddressDataBase();
long index = endPrologue - base;
xDataReader.setIndex((int) index);
//System.out.println(xDataReader.dumpBytes(0x20));
}
// TODO: More work possible. See XData processing and notes there.
if (pdb.getDatabaseInterface() instanceof DatabaseInterfaceNew) {
//Processor target = pdb.getTargetProcessor();
DatabaseInterfaceNew dbi = (DatabaseInterfaceNew) pdb.getDatabaseInterface();
ImageFileMachine machine = dbi.getMachineType();
switch (machine) {
case IA64:
break;
case AMD64:
break;
default:
break;
}
}
}
/**
* Dumps the {@link DebugData}. This package-protected method is for debugging only.
* @param writer {@link Writer} to which to write the debug dump.
* @throws IOException On issue writing to the {@link Writer}.
*/
void dump(Writer writer) throws IOException {
writer.write("DebugData---------------------------------------------------\n");
dumpDebugStreamList(writer);
writer.write("FramePointerOmissionData------------------------------------\n");
for (FramePointerOmissionRecord framePointerOmissionRecord : framePointerOmissionData) {
framePointerOmissionRecord.dump(writer);
}
writer.write("End FramePointerOmissionData--------------------------------\n");
int sectionNum = 0;
writer.write("ImageSectionHeaders-----------------------------------------\n");
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
imageSectionHeader.dump(writer, sectionNum++);
}
writer.write("End ImageSectionHeaders-------------------------------------\n");
writer.write("PData-------------------------------------------------------\n");
for (ImageFunctionEntry entry : pData) {
// TODO: need to output more if/when more PData is available (e.g., interpretation
// of XData.
writer.append(entry.toString());
}
writer.write("End PData---------------------------------------------------\n");
writer.write("End DebugData-----------------------------------------------\n");
}
/**
* Dumps the DebugStreamList. This package-protected method is for debugging only.
* @param writer {@link Writer} to which to write the debug dump.
* @throws IOException On issue writing to the {@link Writer}.
*/
private void dumpDebugStreamList(Writer writer) throws IOException {
writer.write("StreamList--------------------------------------------------\n");
int i = 0;
for (int strmNumber : debugStreamList) {
writer.write(String.format("StrmNumber[%02d]: %04x\n", i++, strmNumber));
}
writer.write("End StreamList----------------------------------------------\n");
}
}

View file

@ -0,0 +1,96 @@
/* ###
* 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.pdb.pdbreader;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* Debug header for various, yet-to-be-determined debug structures. {@link RvaVaDebugHeader}, an
* extension of this class, is used for PData and XData within {@link DebugData}.
*/
public class DebugHeader {
//==============================================================================================
// Internals
//==============================================================================================
private long headerVersion;
private long headerLength;
private long dataLength;
//==============================================================================================
// API
//==============================================================================================
/**
* Returns the version of the header.
* @return the header version.
*/
public long getHeaderVersion() {
return headerVersion;
}
/**
* Returns the header length.
* @return the header length.
*/
public long getHeaderLength() {
return headerLength;
}
/**
* Returns the data length.
* @return the data length.
*/
public long getDataLength() {
return dataLength;
}
/**
* Deserializes the {@link DebugHeader} information from a {@link PdbByteReader}
* @param reader the {@link PdbByteReader} from which to parse the data.
* @throws PdbException upon problem parsing the data.
*/
public void deserialize(PdbByteReader reader) throws PdbException {
headerVersion = reader.parseUnsignedIntVal();
headerLength = reader.parseUnsignedIntVal();
dataLength = reader.parseUnsignedIntVal();
}
@Override
public String toString() {
return dump();
}
/**
* Dumps this class. This package-protected method is for debugging only.
* @return the {@link String} output.
*/
String dump() {
StringBuilder builder = new StringBuilder();
builder.append("DebugHeader-------------------------------------------------\n");
dumpInternal(builder);
builder.append("End DebugHeader---------------------------------------------\n");
return builder.toString();
}
protected void dumpInternal(StringBuilder builder) {
builder.append(String.format("headerVersion: 0X%08X\n", headerVersion));
builder.append(String.format("headerLength: 0X%08X\n", headerLength));
builder.append(String.format("dataLength: 0X%08X\n", dataLength));
}
}

View file

@ -0,0 +1,217 @@
/* ###
* 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.pdb.pdbreader;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* Frame Pointer Omission Data, according to API, represents stack frame layout on x86 when
* frame pointer omission optimization is used. This structure is used to locate the call frame.
* See <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_fpo_data">
* MSFT Documentation</a>, which specifies:
* <PRE>
* typedef struct _FPO_DATA {
* DWORD ulOffStart;
* DWORD cbProcSize;
* DWORD cdwLocals;
* WORD cdwParams;
* WORD cbProlog : 8;
* WORD cbRegs : 3;
* WORD fHasSEH : 1;
* WORD fUseBP : 1;
* WORD reserved : 1;
* WORD cbFrame : 2;
* } FPO_DATA, *PFPO_DATA;
*
* where...
* ulOffStart = The offset of the first byte of the function code.
* cbProcSize = The number of bytes in the function.
* cdwLocals = the number of local variables.
* cdwParams = The size of the parameters, in DWORDs.
* cbProlog = The number of bytes in the function prolog code.
* cbRegs = The number of registers saved.
* fHasSEH = A variable that indicates whether the function used structured exeception handling.
* fUseBP = A variable that indicates whether the EBP register has been allocated.
* reserved = Reserved for future use.
* cbFrame = A variable that indicates the frame type, where...
* FRAME_FPO (0) = FPO frame
* FRAME_TRAP (1) = Trap frame
* FRAME_TSS (2) = TSS frame
* FRAME_NONFPO (3) = non-FPO frame
* </PRE>
*/
public class FramePointerOmissionRecord {
public enum FrameType {
FPO("fpo", 0), TRAP("trap", 1), TSS("tss", 2), NON_FPO("std", 3);
private static final Map<Integer, FrameType> BY_VALUE = new HashMap<>();
static {
for (FrameType val : values()) {
BY_VALUE.put(val.value, val);
}
}
public final String label;
private final int value;
@Override
public String toString() {
return label;
}
public static FrameType fromValue(int val) {
return BY_VALUE.getOrDefault(val, FPO);
}
private FrameType(String label, int value) {
this.label = label;
this.value = value;
}
}
private long firstFunctionByteOffset;
private long numFunctionBytes;
private long numLocalVariables;
private int sizeOfParametersInDwords;
private int numFunctionPrologBytes;
private boolean hasStructuredExceptionHandling;
private boolean EBPAllocatedAndUsed;
private int reserved;
private FrameType frameType;
/**
* Returns the offset of the first byte of the function.
* @return the offset.
*/
public long getFirstFunctionByteOffset() {
return firstFunctionByteOffset;
}
/**
* Returns the number of bytes in the function.
* @return the number of bytes in the function.
*/
public long getNumberOfFunctionBytes() {
return numFunctionBytes;
}
/**
* Returns the number of local variables.
* @return the number of local variables.
*/
public long getNumberLocalVariables() {
return numLocalVariables;
}
/**
* Returns the size of the parameter as the number of DWORDs.
* @return the size of the parameters in DWORDs.
*/
public int getSizeOfParametersInDwords() {
return sizeOfParametersInDwords;
}
/**
* Returns the number of bytes in the function prolog.
* @return the number of bytes in the prolog.
*/
public int getNumberFunctionPrologBytes() {
return numFunctionPrologBytes;
}
/**
* Returns whether there the function has structured exception handling.
* @return whether structure handling is used.
*/
public boolean hasStructuredExceptionHandling() {
return hasStructuredExceptionHandling;
}
/**
* Returns whether the EBP is allocated/used.
* @return whether EBP is allocated/used.
*/
public boolean EBPAllocatedAndUsed() {
return EBPAllocatedAndUsed;
}
/**
* Returns the value of the reserved 1-bit field..
* @return the value of the reserved field.
*/
public int reserved() {
return reserved;
}
/**
* Returns the {@link FrameType} being specified.
* @return the {@link FrameType} being specified.
*/
public FrameType getFrameType() {
return frameType;
}
public void parse(PdbByteReader reader) throws PdbException {
if (reader.numRemaining() < 16) {
throw new PdbException("Not enough data for FramePointerOmissionRecord");
}
firstFunctionByteOffset = reader.parseUnsignedIntVal();
numFunctionBytes = reader.parseUnsignedIntVal();
numLocalVariables = reader.parseUnsignedIntVal();
sizeOfParametersInDwords = reader.parseUnsignedShortVal();
int data = reader.parseUnsignedShortVal();
numFunctionPrologBytes = (data & 0xff);
data >>= 8;
hasStructuredExceptionHandling = (data & 0x01) == 0x01;
data >>= 1;
EBPAllocatedAndUsed = (data & 0x01) == 0x01;
data >>= 1;
reserved = data & 0x01;
data >>= 1;
frameType = FrameType.fromValue(data & 0x03);
}
/**
* Dumps the {@link FramePointerOmissionRecord}. This package-protected method is for
* debugging only.
* @param writer {@link Writer} to which to write the debug dump.
* @throws IOException On issue writing to the {@link Writer}.
*/
void dump(Writer writer) throws IOException {
writer.write("FramePointerOmissionRecord----------------------------------\n");
writer.write(String.format("firstFunctionByteOffset: 0X%08X\n", firstFunctionByteOffset));
writer.write(String.format("firstFunctionByteOffset: 0X%08X\n", firstFunctionByteOffset));
writer.write(String.format("numFunctionBytes: 0X%08XX\n", numFunctionBytes));
writer.write(String.format("numLocalVariables: 0X%08X\n", numLocalVariables));
writer.write(String.format("sizeOfParametersInDwords: 0X%08X\n", sizeOfParametersInDwords));
writer.write(String.format("numFunctionPrologBytes: 0X%04X\n", numFunctionPrologBytes));
writer.write(String.format("hasStructuredExceptionHandling: %s\n",
Boolean.toString(hasStructuredExceptionHandling)));
writer.write(
String.format("EBPAllocatedAndUsed: %s\n", Boolean.toString(EBPAllocatedAndUsed)));
writer.write(String.format("reserved: 0X%01X\n", reserved));
writer.write(String.format("frameType: %s\n", frameType.toString()));
writer.write("End FramePointerOmissionRecord------------------------------\n");
}
}

View file

@ -0,0 +1,104 @@
/* ###
* 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.pdb.pdbreader;
import java.util.HashMap;
import java.util.Map;
import ghidra.pdb.pdbreader.symbol.*;
/**
* Machine Type seen in the {@link DatabaseInterfaceNew} header. We also map in the Processor.
* We are not exactly sure about why there are different but similar items: Machine Type and
* Processor. The {@link Processor} is what is specified in {@link AbstractCompile2MsSymbol} and
* {@link Compile3MsSymbol} and what we save off in {@link AbstractPdb}, but
* {@link ImageFileMachine} is what we see in the header of {@link DatabaseInterfaceNew}.
* See <a href="https://docs.microsoft.com/en-us/windows/desktop/sysinfo/image-file-machine-constants">
* Image File Machine Constants</a>.
* See <a href="http://metadataconsulting.blogspot.com/2014/06/imagefilemachine-extensive-machine-type.html">
* Also</a>.
* Also see <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-image_file_header">
* Other use</a>.
*/
public enum ImageFileMachine {
UNKNOWN("Unknown", 0x0000, Processor.UNKNOWN),
// Processor Guess
TARGET_HOST("Interacts with the host and not a WOW64 guest", 0x0001, Processor.UNKNOWN),
I386("Intel 386", 0x014c, Processor.I80386),
I860("Intel I860", 0x014d, Processor.UNKNOWN), // Processor Guess
R3000("MIPS little-endian, 0x160 big-endian", 0x0162, Processor.MIPS_MIPSR4000),
R4000("MIPS little-endian", 0x0166, Processor.MIPS_MIPSR4000),
R10000("MIPS little-endian", 0x0168, Processor.MIPS_MIPSR4000),
WCEMIPSV2("MIPS little-endian WCE v2", 0x0169, Processor.MIPS_MIPSR4000), // Processor Guess
ALPHA("Alpha_AXP", 0x0184, Processor.ALPHA_21064), // Processor Guess
SH3("SH3 little-endian", 0x01a2, Processor.SH3),
SH3DSP("SH3DSP", 0x01a3, Processor.SH3DSP), //
SH3E("SH3E little-endian", 0x01a4, Processor.SH3), // Processor Guess
SH4("SH4 little-endian", 0x01a6, Processor.SH4),
SH5("SH5", 0x01a8, Processor.SH4),
ARM("ARM Little-Endian", 0x01c0, Processor.ARM3),
THUMB("ARM Thumb/Thumb-2 Little-Endian", 0x01c2, Processor.THUMB),
ARMNT("ARM Thumb-2 Little-Endian", 0x01c4, Processor.ARMNT),
AM33("TAM33BD", 0x01d3, Processor.AM33),
POWERPC("IBM PowerPC Little-Endian", 0x01F0, Processor.PPC601),
POWERPCFP("POWERPCFP", 0x01f1, Processor.PPCFP),
POWERPCBE("POWERPCBE", 0x01f2, Processor.PPCBE),
IA64("Intel 64", 0x0200, Processor.IA64_IA64_1),
M68K("Motorola 68000", 0x0268, Processor.M68000), // Processor Guess
MIPS16("MIPS16", 0x0266, Processor.MIPS16), // Set Processor diff than MSFT
ALPHA64("ALPHA64", 0x0284, Processor.ALPHA_21064), // Processor Guess
MIPSFPU("MIPSFPU", 0x0366, Processor.MIPS_MIPSR4000),
MIPSFPU16("MIPSFPU16", 0x0466, Processor.MIPS_MIPSR4000),
AXP64("AXP64", 0x0284, Processor.UNKNOWN), // Processor Guess
TRICORE("Infineon", 0x0520, Processor.TRICORE),
CEF("CEF", 0x0CEF, Processor.UNKNOWN), // Processor Guess
EBC("EFI Byte Code", 0x0EBC, Processor.EBC),
AMD64("AMD64 (K8)", 0x8664, Processor.X64_AMD64),
M32R("M32R little-endian", 0x9041, Processor.M32R),
ARM64("ARM64 Little-Endian", 0xAA64, Processor.ARM64),
CEE("CEE", 0xC0EE, Processor.CEE);
private static final Map<Integer, ImageFileMachine> BY_VALUE = new HashMap<>();
static {
for (ImageFileMachine val : values()) {
BY_VALUE.put(val.value, val);
}
}
private final String label;
private final int value;
private Processor processor;
@Override
public String toString() {
return label;
}
public static ImageFileMachine fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
public Processor getProcessor() {
return processor;
}
private ImageFileMachine(String label, int value, Processor processor) {
this.label = label;
this.value = value;
this.processor = processor;
}
}

View file

@ -0,0 +1,91 @@
/* ###
* 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.pdb.pdbreader;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* Image Function Entry data seems to be the main data PData record of the {@link DebugData}.
*/
public class ImageFunctionEntry {
//==============================================================================================
// Internals
//==============================================================================================
private long startingAddress;
private long endingAddress;
private long endOfPrologueAddress;
//==============================================================================================
// API
//==============================================================================================
/**
* Returns the starting address.
* @return the starting address.
*/
public long getStartingAddress() {
return startingAddress;
}
/**
* Returns the ending address.
* @return the ending address.
*/
public long getEndingAddress() {
return endingAddress;
}
/**
* Returns the end-of-prologue address.
* @return the end-of-prologue address.
*/
public long getEndOfPrologueAddress() {
return endOfPrologueAddress;
}
/**
* Deserializes the {@link ImageFunctionEntry} information from a {@link PdbByteReader}
* @param reader the {@link PdbByteReader} from which to parse the data.
* @throws PdbException upon problem parsing the data.
*/
public void deserialize(PdbByteReader reader) throws PdbException {
startingAddress = reader.parseUnsignedIntVal();
endingAddress = reader.parseUnsignedIntVal();
endOfPrologueAddress = reader.parseUnsignedIntVal();
}
@Override
public String toString() {
return dump();
}
/**
* Dumps this class. This package-protected method is for debugging only.
* @return the {@link String} output.
*/
String dump() {
StringBuilder builder = new StringBuilder();
builder.append("ImageFunctionEntry------------------------------------------\n");
builder.append(String.format("startingAddress: 0X%08X\n", startingAddress));
builder.append(String.format("endingAddress: 0X%08X\n", endingAddress));
builder.append(String.format("endOfPrologueAddress: 0X%08X\n", endOfPrologueAddress));
builder.append("End ImageFunctionEntry--------------------------------------\n");
return builder.toString();
}
}

View file

@ -0,0 +1,169 @@
/* ###
* 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.pdb.pdbreader;
import java.io.IOException;
import java.io.Writer;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* Image Section Header information, as part of {@link DebugData} structures within
* {@link DatabaseInterfaceNew} of {@link AbstractPdb} types. Contains section information;
* an older set of section information seems to be located in {@link SegmentMapDescription},
* which might be used for {@link DatabaseInterface} types, but we do not yet have data to
* confirm this.
*/
public class ImageSectionHeader {
/**
* Returns the {@link ImageSectionHeader} name.
* @return the name.
*/
public String getName() {
return name;
}
/**
* Returns the {@link ImageSectionHeader} unionPAVS, which is either Physical Address or
* Virtual Size.
* @return the unionPAVS.
*/
public long getUnionPAVS() {
return unionPAVS;
}
/**
* Returns the {@link ImageSectionHeader} virtualAddress.
* @return the virtualAddress.
*/
public long getVirtualAddress() {
return virtualAddress;
}
/**
* Returns the {@link ImageSectionHeader} rawDataSize.
* @return the rawDataSize.
*/
public long getRawDataSize() {
return rawDataSize;
}
/**
* Returns the {@link ImageSectionHeader} rawDataPointer.
* @return the rawDataPointer.
*/
public long getRawDataPointer() {
return rawDataPointer;
}
/**
* Returns the {@link ImageSectionHeader} relocationsPointer.
* @return the relocationsPointer.
*/
public long getRelocationsPointer() {
return relocationsPointer;
}
/**
* Returns the {@link ImageSectionHeader} lineNumbersPointer.
* @return the lineNumbersPointer.
*/
public long getLineNumbersPointer() {
return lineNumbersPointer;
}
/**
* Returns the {@link ImageSectionHeader} numRelocations.
* @return the numRelocations.
*/
public int getNumRelocations() {
return numRelocations;
}
/**
* Returns the {@link ImageSectionHeader} numLineNumbers.
* @return the numLineNumbers.
*/
public int getNumLineNumbers() {
return numLineNumbers;
}
/**
* Returns the {@link ImageSectionHeader} characteristics.
* @return the characteristics.
*/
public long getCharacteristics() {
return characteristics;
}
private String name;
// TODO:
// unionPAVS: DWORD (unsigned 32-bit). Either Physical Address of Virtual Size--not sure
// what to key off of to interpret one over the other. Guess that it has to do with
// VirtualAddress--perhaps a value of 0x00000000 or 0xffffffff.
// See the to-do below (in dump()) regarding unionPAVS.
private long unionPAVS;
private long virtualAddress; // DWORD (unsigned 32-bit)
private long rawDataSize; // DWORD (unsigned 32-bit)
private long rawDataPointer; // DWORD (unsigned 32-bit)
private long relocationsPointer; // DWORD (unsigned 32-bit)
private long lineNumbersPointer; // DWORD (unsigned 32-bit)
private int numRelocations; // WORD (unsigned 16-bit)
private int numLineNumbers; // WORD (unsigned 16-bit)
private long characteristics; // DWORD (unsigned 32-bit)
public void parse(PdbByteReader reader) throws PdbException {
if (reader.numRemaining() < 40) {
throw new PdbException("Not enough data for ImageSectionHeader");
}
PdbByteReader nameReader = reader.getSubPdbByteReader(8);
name = nameReader.parseNullTerminatedString();
unionPAVS = reader.parseUnsignedIntVal();
virtualAddress = reader.parseUnsignedIntVal();
rawDataSize = reader.parseUnsignedIntVal();
rawDataPointer = reader.parseUnsignedIntVal();
relocationsPointer = reader.parseUnsignedIntVal();
lineNumbersPointer = reader.parseUnsignedIntVal();
numRelocations = reader.parseUnsignedShortVal();
numLineNumbers = reader.parseUnsignedShortVal();
characteristics = reader.parseUnsignedIntVal();
}
/**
* Dumps the {@link ImageSectionHeader}. This package-protected method is for
* debugging only.
* @param writer {@link Writer} to which to write the debug dump.
* @param sectionNum the section number to include in the output.
* @throws IOException On issue writing to the {@link Writer}.
*/
void dump(Writer writer, int sectionNum) throws IOException {
writer.write("ImageSectionHeader------------------------------------------\n");
writer.write(String.format("Section Number: %04X\n", sectionNum));
writer.write(String.format("name: %s\n", name));
// TODO: See the to-do above regarding unionPAVS.
writer.write(String.format("unionPAVS: 0X%08X\n", unionPAVS));
writer.write(String.format("virtualAddress: 0X%08X\n", virtualAddress));
writer.write(String.format("rawDataSize: 0X%08XX\n", rawDataSize));
writer.write(String.format("rawDataPointer: 0X%08X\n", rawDataPointer));
writer.write(String.format("relocationsPointer: 0X%08X\n", relocationsPointer));
writer.write(String.format("lineNumbersPointer: 0X%08X\n", lineNumbersPointer));
writer.write(String.format("numRelocations: 0X%04X\n", numRelocations));
writer.write(String.format("numLineNumbers: 0X%04X\n", numLineNumbers));
writer.write(String.format("characteristics: 0X%08X\n", characteristics));
writer.write("End ImageSectionHeader--------------------------------------\n");
}
}

View file

@ -0,0 +1,94 @@
/* ###
* 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.pdb.pdbreader;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* Linker Unwind Information that seems to be used in some XData types within {@link DebugData}.
*/
public class LinkerUnwindInfo {
//==============================================================================================
// Internals
//==============================================================================================
private int version; // unsigned short
private int flags; // unsigned short
private long dataLength; // unsigned int
//==============================================================================================
// API
//==============================================================================================
/**
* Returns the version.
* @return the version.
*/
public int getVersion() {
return version;
}
/**
* Returns the flags.
* @return the flags.
*/
public int getFlags() {
return flags;
}
/**
* Returns the data length.
* @return the data length.
*/
public long getDataLength() {
return dataLength;
}
/**
* Deserializes the {@link ImageFunctionEntry} information from a {@link PdbByteReader}
* @param reader the {@link PdbByteReader} from which to parse the data.
* @throws PdbException upon problem parsing the data.
*/
public void deserialize(PdbByteReader reader) throws PdbException {
version = reader.parseUnsignedShortVal();
flags = reader.parseUnsignedShortVal();
dataLength = reader.parseUnsignedIntVal();
}
@Override
public String toString() {
return dump();
}
/**
* Dumps this class. This package-protected method is for debugging only.
* @return the {@link String} output.
*/
String dump() {
StringBuilder builder = new StringBuilder();
builder.append("LinkerUnwindInfo--------------------------------------------\n");
dumpInternal(builder);
builder.append("End LinkerUnwindInfo----------------------------------------\n");
return builder.toString();
}
protected void dumpInternal(StringBuilder builder) {
builder.append(String.format("version: 0X%04X\n", version));
builder.append(String.format("flags: 0X%04X\n", flags));
builder.append(String.format("dataLength: 0X%08X\n", dataLength));
}
}

View file

@ -0,0 +1,107 @@
/* ###
* 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.pdb.pdbreader;
import java.math.BigInteger;
import ghidra.pdb.PdbByteReader;
import ghidra.pdb.PdbException;
/**
* A debug header that is known (others may be known in the future) to be used for PData and XData
* within the {@link DebugData} class.
*/
public class RvaVaDebugHeader extends DebugHeader {
//==============================================================================================
// Internals
//==============================================================================================
private long relativeVirtualAddressDataBase;
private BigInteger virtualAddressImageBase;
private long unsignedIntReserved1;
private long unsignedIntReserved2;
//==============================================================================================
// API
//==============================================================================================
/**
* Returns the relative virtual address data base.
* @return the relative virtual address data base.
*/
public long getRelativeVirtualAddressDataBase() {
return relativeVirtualAddressDataBase;
}
/**
* Returns the virtual address image base.
* @return the virtual address image base.
*/
public BigInteger getVirtualAddressImageBase() {
return virtualAddressImageBase;
}
/**
* Returns the reserved1 unsigned int stored in a long.
* @return the reserved1 unsigned int stored in a long.
*/
public long getReserved1() {
return unsignedIntReserved1;
}
/**
* Returns the reserved2 unsigned int stored in a long.
* @return the reserved2 unsigned int stored in a long.
*/
public long getReserved2() {
return unsignedIntReserved2;
}
/**
* Deserializes the {@link RvaVaDebugHeader} information from a {@link PdbByteReader}
* @param reader the {@link PdbByteReader} from which to parse the data.
* @throws PdbException upon problem parsing the data.
*/
@Override
public void deserialize(PdbByteReader reader) throws PdbException {
super.deserialize(reader);
relativeVirtualAddressDataBase = reader.parseUnsignedIntVal();
virtualAddressImageBase = reader.parseUnsignedLongVal();
unsignedIntReserved1 = reader.parseUnsignedIntVal();
unsignedIntReserved2 = reader.parseUnsignedIntVal();
}
@Override
String dump() {
StringBuilder builder = new StringBuilder();
builder.append("RvaVaDebugHeader--------------------------------------------\n");
dumpInternal(builder);
builder.append("End RvaVaDebugHeader----------------------------------------\n");
return builder.toString();
}
@Override
protected void dumpInternal(StringBuilder builder) {
super.dumpInternal(builder);
builder.append(String.format("relativeVirtualAddressDataBase: 0X%08X\n",
relativeVirtualAddressDataBase));
builder.append(
String.format("virtualAddressImageBase: 0X%016X\n", virtualAddressImageBase));
builder.append(String.format("unsignedIntReserved1: 0X%08X\n", unsignedIntReserved1));
builder.append(String.format("unsignedIntReserved2: 0X%08X\n", unsignedIntReserved2));
}
}

View file

@ -42,6 +42,23 @@ public class SegmentMapDescription {
//==============================================================================================
// API
//==============================================================================================
/**
* Returns the segment offset.
* @return The offset of the segment.
*/
public long getSegmentOffset() {
return segOffset;
}
/**
* Returns the segment length.
* @return The length of the segment.
*/
public long getLength() {
return segLength;
}
/**
* Deserializes the {@link SegmentMapDescription}.
* @param substreamReader {@link PdbByteReader} from which to deserialize the data.

View file

@ -42,7 +42,7 @@ public abstract class AbstractCompile2MsSymbol extends AbstractMsSymbol {
protected boolean convertedWithCvtcil;
protected boolean microsoftIntermediateLanguageNetModule;
protected int processorIndex;
protected ProcessorName processor;
protected Processor processor;
protected int frontEndMajorVersionNumber;
protected int frontEndMinorVersionNumber;
protected int frontEndBuildVersionNumber;
@ -63,7 +63,7 @@ public abstract class AbstractCompile2MsSymbol extends AbstractMsSymbol {
create();
processFlags(reader.parseUnsignedIntVal());
processorIndex = reader.parseUnsignedShortVal();
processor = new ProcessorName(processorIndex);
processor = Processor.fromValue(processorIndex);
frontEndMajorVersionNumber = reader.parseUnsignedShortVal();
frontEndMinorVersionNumber = reader.parseUnsignedShortVal();
frontEndBuildVersionNumber = reader.parseUnsignedShortVal();
@ -84,7 +84,7 @@ public abstract class AbstractCompile2MsSymbol extends AbstractMsSymbol {
// Very important: Store target machine information. It is used elsewhere, including
// in RegisterName.
pdb.setTargetProcessorIndexNumber(processorIndex);
pdb.setTargetProcessor(processor);
}
/**

View file

@ -44,6 +44,14 @@ public class AnnotationReferenceMsSymbol extends AbstractReferenceMsSymbol {
return PDB_ID;
}
/**
* Returns the name field of this symbol.
* @return the name.
*/
public String getName() {
return ((ReferenceSymbolInternals2) internals).getName();
}
@Override
protected void create() {
internals = new ReferenceSymbolInternals2(pdb);

View file

@ -44,7 +44,7 @@ public class Compile3MsSymbol extends AbstractMsSymbol {
protected boolean compiledWithLtcgPgoOrPgu;
protected boolean dotExpModule;
protected int processorIndex;
protected ProcessorName processor;
protected Processor processor;
protected int frontEndMajorVersionNumber;
protected int frontEndMinorVersionNumber;
protected int frontEndBuildVersionNumber;
@ -66,7 +66,7 @@ public class Compile3MsSymbol extends AbstractMsSymbol {
compilerVersionString = new StringUtf8Nt();
processFlags(reader.parseUnsignedIntVal());
processorIndex = reader.parseUnsignedShortVal();
processor = new ProcessorName(processorIndex);
processor = Processor.fromValue(processorIndex);
frontEndMajorVersionNumber = reader.parseUnsignedShortVal();
frontEndMinorVersionNumber = reader.parseUnsignedShortVal();
frontEndBuildVersionNumber = reader.parseUnsignedShortVal();
@ -79,7 +79,7 @@ public class Compile3MsSymbol extends AbstractMsSymbol {
// Very important: sStore target machine information. It is used elsewhere, including
// in RegisterName.
pdb.setTargetProcessorIndexNumber(processorIndex);
pdb.setTargetProcessor(processor);
}
@Override

View file

@ -30,7 +30,7 @@ public class CompileFlagsMsSymbol extends AbstractMsSymbol {
public static final int PDB_ID = 0x0001;
protected int processorIndex;
protected ProcessorName processor;
protected Processor processor;
protected LanguageName language;
protected boolean pcodePresent;
protected int floatingPrecision;
@ -49,7 +49,7 @@ public class CompileFlagsMsSymbol extends AbstractMsSymbol {
public CompileFlagsMsSymbol(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
processorIndex = reader.parseUnsignedByteVal();
processor = new ProcessorName(processorIndex);
processor = Processor.fromValue(processorIndex);
//Possible padding here for structure???
byte[] flags = reader.parseBytes(3);
processFlags(flags);
@ -57,7 +57,7 @@ public class CompileFlagsMsSymbol extends AbstractMsSymbol {
// Very important: sStore target machine information. It is used elsewhere, including
// in RegisterName.
pdb.setTargetProcessorIndexNumber(processorIndex);
pdb.setTargetProcessor(processor);
}
@Override

View file

@ -39,6 +39,14 @@ public class DataReferenceMsSymbol extends AbstractDataReferenceMsSymbol {
super(pdb, reader);
}
/**
* Returns the name field of this symbol.
* @return the name.
*/
public String getName() {
return ((ReferenceSymbolInternals2) internals).getName();
}
@Override
protected void create() {
internals = new ReferenceSymbolInternals2(pdb);

View file

@ -45,6 +45,14 @@ public class LocalProcedureReferenceMsSymbol extends AbstractLocalProcedureRefer
return PDB_ID;
}
/**
* Returns the name field of this symbol.
* @return the name.
*/
public String getName() {
return ((ReferenceSymbolInternals2) internals).getName();
}
@Override
protected void create() {
internals = new ReferenceSymbolInternals2(pdb);

View file

@ -39,6 +39,14 @@ public class ProcedureReferenceMsSymbol extends AbstractProcedureReferenceMsSymb
super(pdb, reader);
}
/**
* Returns the name field of this symbol.
* @return the name.
*/
public String getName() {
return ((ReferenceSymbolInternals2) internals).getName();
}
@Override
public int getPdbId() {
return PDB_ID;

View file

@ -0,0 +1,137 @@
/* ###
* 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.pdb.pdbreader.symbol;
import java.util.HashMap;
import java.util.Map;
/**
* Target Processor (CPU Type).
*/
public enum Processor {
UNKNOWN("???", -1),
I8080("8080", 0x00),
I8086("8086", 0x01),
I80286("80286", 0x02),
I80386("80386", 0x03),
I80486("80486", 0x04),
PENTIUM("Pentium", 0x05),
PENTIUMPRO_PENTIUMII("Pentium Pro/Pentium II", 0x06),
PENTIUMIII("Pentium III", 0x07),
MIPS_MIPSR4000("MIPS (Generic)/R4000", 0x10),
MIPS16("MIPS16", 0x11),
MIPS32("MIPS32", 0x12),
MIPS64("MIPS64", 0x13),
MIPSI("MIPS I", 0x14),
MIPSII("MIPS II", 0x15),
MIPSIII("MIPS III", 0x16),
MIPSIV("MIPS IV", 0x17),
MIPSV("MIPS V", 0x18),
M68000("M68000", 0x20),
M68010("M68010", 0x21),
M68020("M68020", 0x22),
M68030("M68030", 0x23),
M68040("M68040", 0x24),
ALPHA_21064("Alpha/Alpha 21064", 0x30),
ALPHA_21164("Alpha 21164", 0x31),
ALPHA_21164A("Alpha 21164a", 0x32),
ALPHA_21264("Alpha 21264", 0x33),
ALPHA_21364("Alpha 21364", 0x34),
PPC601("PPC 601", 0x40),
PPC603("PPC 603", 0x41),
PPC604("PPC 604", 0x42),
PPC620("PPC 620", 0x43),
PPCFP("PPC w/FP", 0x44),
PPCBE("PPC (Big Endian)", 0x45),
SH3("SH3", 0x50),
SH3E("SH3E", 0x51),
SH3DSP("SH3DSP", 0x52),
SH4("SH4", 0x53),
SHMEDIA("SHmedia", 0x54),
ARM3("ARMv3 (CE)", 0x60),
ARM4("ARMv4 (CE)", 0x61),
ARM4T("ARMv4T (CE)", 0x62),
ARM5("ARMv5 (CE)", 0x63),
ARM5T("ARMv5T (CE)", 0x64),
ARM6("ARMv6 (CE)", 0x65),
ARM_XMAC("ARM (XMAC) (CE)", 0x66),
ARM_WMMX("ARM (XMMX) (CE)", 0x67),
ARM7("ARMv7 (CE)", 0x68),
OMNI("Omni", 0x70),
IA64_IA64_1("Itanium", 0x80),
IA64_2("Itanium (McKinley)", 0x81),
CEE("CEE", 0x90),
AM33("AM33", 0xA0),
M32R("M32R", 0xB0),
TRICORE("TriCore", 0xC0),
X64_AMD64("x64", 0xD0),
EBC("EBC", 0xE0),
THUMB("Thumb (CE)", 0xF0),
ARMNT("ARM", 0xF4),
ARM64("ARM64", 0xF6),
D3D11_SHADER("D3D11_SHADER", 0x100),
// Extras seen while processing files. TODO: Evaluate these more later.
UNK1AB("Unknown1ab", 0x1ab),
UNK304("Unknown304", 0x304);
private static final Map<Integer, Processor> BY_VALUE = new HashMap<>();
static {
for (Processor val : values()) {
BY_VALUE.put(val.value, val);
}
}
public final String label;
private final int value;
@Override
public String toString() {
return label;
}
public int getValue() {
return value;
}
public static Processor fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
private Processor(String label, int value) {
this.label = label;
this.value = value;
}
}

View file

@ -1,139 +0,0 @@
/* ###
* 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.pdb.pdbreader.symbol;
import java.util.HashMap;
import java.util.Map;
import ghidra.pdb.AbstractParsableItem;
/**
* Procedure Name component for certain PDB symbols.
*/
public class ProcessorName extends AbstractParsableItem {
private static final Map<Integer, String> processorStringMap = new HashMap<>();
static {
processorStringMap.put(0x00, "8080");
processorStringMap.put(0x01, "8086");
processorStringMap.put(0x02, "80286");
processorStringMap.put(0x03, "80386");
processorStringMap.put(0x04, "80486");
processorStringMap.put(0x05, "Pentium");
processorStringMap.put(0x06, "Pentium Pro/Pentium II");
processorStringMap.put(0x07, "Pentium III");
processorStringMap.put(0x10, "MIPS (Generic)");
processorStringMap.put(0x11, "MIPS16");
processorStringMap.put(0x12, "MIPS32");
processorStringMap.put(0x13, "MIPS64");
processorStringMap.put(0x14, "MIPS I");
processorStringMap.put(0x15, "MIPS II");
processorStringMap.put(0x16, "MIPS III");
processorStringMap.put(0x17, "MIPS IV");
processorStringMap.put(0x18, "MIPS V");
processorStringMap.put(0x20, "M68000");
processorStringMap.put(0x21, "M68010");
processorStringMap.put(0x22, "M68020");
processorStringMap.put(0x23, "M68030");
processorStringMap.put(0x24, "M68040");
processorStringMap.put(0x30, "Alpha 21064");
processorStringMap.put(0x31, "Alpha 21164");
processorStringMap.put(0x32, "Alpha 21164a");
processorStringMap.put(0x33, "Alpha 21264");
processorStringMap.put(0x34, "Alpha 21364");
processorStringMap.put(0x40, "PPC 601");
processorStringMap.put(0x41, "PPC 603");
processorStringMap.put(0x42, "PPC 604");
processorStringMap.put(0x43, "PPC 620");
processorStringMap.put(0x44, "PPC w/FP");
processorStringMap.put(0x45, "PPC (Big Endian)");
processorStringMap.put(0x50, "SH3");
processorStringMap.put(0x51, "SH3E");
processorStringMap.put(0x52, "SH3DSP");
processorStringMap.put(0x53, "SH4");
processorStringMap.put(0x54, "SHmedia");
processorStringMap.put(0x60, "ARMv3 (CE)");
processorStringMap.put(0x61, "ARMv4 (CE)");
processorStringMap.put(0x62, "ARMv4T (CE)");
processorStringMap.put(0x63, "ARMv5 (CE)");
processorStringMap.put(0x64, "ARMv5T (CE)");
processorStringMap.put(0x65, "ARMv6 (CE)");
processorStringMap.put(0x66, "ARM (XMAC) (CE)");
processorStringMap.put(0x67, "ARM (XMMX) (CE)");
processorStringMap.put(0x68, "ARMv7 (CE)");
processorStringMap.put(0x70, "Omni");
processorStringMap.put(0x80, "Itanium");
processorStringMap.put(0x81, "Itanium (McKinley)");
processorStringMap.put(0x90, "CEE");
processorStringMap.put(0xa0, "AM33");
processorStringMap.put(0xb0, "M32R");
processorStringMap.put(0xc0, "TriCore");
processorStringMap.put(0xd0, "x64");
processorStringMap.put(0xe0, "EBC");
processorStringMap.put(0xf0, "Thumb (CE)");
processorStringMap.put(0xf4, "ARM");
processorStringMap.put(0xf6, "ARM64");
processorStringMap.put(0x100, "D3D11_SHADER");
}
private static final String badProcessor = "???";
//==============================================================================================
private int processorIndex;
//==============================================================================================
/**
* Constructor for this symbol component. Requires argument for the processor index.
* @param processorIndexIn Processor index.
*/
public ProcessorName(int processorIndexIn) {
this.processorIndex = processorIndexIn;
}
/**
* Returns the processor index.
* @return Processor index.
*/
public int getProcessorIndex() {
return processorIndex;
}
@Override
public void emit(StringBuilder builder) {
builder.append(getProcessorName());
}
private String getProcessorName() {
return processorStringMap.getOrDefault(processorIndex, badProcessor);
}
}

View file

@ -38,6 +38,14 @@ public class ReferenceSymbolInternals2 extends AbstractReferenceSymbolInternals
super(pdb);
}
/**
* Returns the name field of this symbol internals.
* @return the name.
*/
public String getName() {
return name.get();
}
@Override
public void emit(StringBuilder builder) {
super.emit(builder);

View file

@ -874,43 +874,141 @@ public class RegisterName extends AbstractParsableItem {
@Override
public void emit(StringBuilder builder) {
builder.append(getRegisterName(pdb.getTargetProcessorIndexNumber(), register));
builder.append(getRegisterName(pdb.getTargetProcessor(), register));
}
private String getRegisterName(int processorIn, int registerIn) {
if (registerIn < 0) {
return badRegister;
}
if (processorIn >= 0x00 && processorIn <= 0x07 && registerIn < regX86.length) {
return regX86[registerIn];
}
else if (processorIn >= 0x10 && processorIn <= 0x18 && registerIn < regMips.length) {
return regMips[registerIn];
}
else if (processorIn >= 0x20 && processorIn <= 0x24 && registerIn < reg68k.length) {
return reg68k[registerIn];
}
else if (processorIn >= 0x30 && processorIn <= 0x34 && registerIn < regAlpha.length) {
return regAlpha[registerIn];
}
else if (processorIn >= 0x40 && processorIn <= 0x45 && registerIn < regPpc.length) {
return regPpc[registerIn];
}
else if (processorIn >= 0x50 && processorIn <= 0x54 && registerIn < regSh.length) {
return regSh[registerIn];
}
private String getRegisterName(Processor processorIn, int registerIn) {
// We do not have registers for many of the processors... set the default.
String registerName = badRegister;
switch (processorIn) {
case UNKNOWN:
case UNK1AB:
case UNK304:
break;
case I8080:
case I8086:
case I80286:
case I80386:
case I80486:
case PENTIUM:
case PENTIUMPRO_PENTIUMII:
case PENTIUMIII:
if (registerIn < regX86.length) {
registerName = regX86[registerIn];
}
break;
case MIPS_MIPSR4000:
case MIPS16:
case MIPS32:
case MIPS64:
case MIPSI:
case MIPSII:
case MIPSIII:
case MIPSIV:
case MIPSV:
if (registerIn < regMips.length) {
registerName = regMips[registerIn];
}
break;
case M68000:
case M68010:
case M68020:
case M68030:
case M68040:
if (registerIn < reg68k.length) {
registerName = reg68k[registerIn];
}
break;
case ALPHA_21064:
case ALPHA_21164:
case ALPHA_21164A:
case ALPHA_21264:
case ALPHA_21364:
if (registerIn < regAlpha.length) {
registerName = regAlpha[registerIn];
}
break;
case PPC601:
case PPC603:
case PPC604:
case PPC620:
case PPCFP:
case PPCBE:
if (registerIn < regPpc.length) {
registerName = regPpc[registerIn];
}
break;
case SH3:
case SH3E:
case SH3DSP:
case SH4:
case SHMEDIA:
if (registerIn < regSh.length) {
registerName = regSh[registerIn];
}
break;
case ARM3:
case ARM4:
case ARM4T:
case ARM5:
case ARM5T:
case ARM6:
case ARM_XMAC:
case ARM_WMMX:
case ARM7:
break;
case OMNI:
break;
case IA64_IA64_1:
case IA64_2:
if (registerIn < regIa64Map.size()) {
registerName = regIa64Map.get(registerIn);
}
break;
case CEE:
break;
case AM33:
break;
case M32R:
break;
case TRICORE:
break;
case X64_AMD64:
if (registerIn < regAmd64.length) {
registerName = regAmd64[registerIn];
}
break;
case EBC:
break;
case THUMB:
case ARMNT:
case ARM64:
break;
case D3D11_SHADER:
break;
else if (processorIn == 0xd0 && registerIn < regAmd64.length) {
return regAmd64[registerIn];
}
else if (processorIn >= 0x80 && processorIn <= 0x81 && registerIn < regIa64Map.size()) {
String val = regIa64Map.get(registerIn);
if (val != null) {
return val;
}
}
// TODO: Don't have anything for arm, and other processors. See API for possibilities.
return badRegister;
return registerName;
}
}

View file

@ -40,6 +40,14 @@ public class TokenReferenceToManagedProcedureMsSymbol extends AbstractReferenceM
super(pdb, reader);
}
/**
* Returns the name field of this symbol.
* @return the name.
*/
public String getName() {
return ((ReferenceSymbolInternals2) internals).getName();
}
@Override
public int getPdbId() {
return PDB_ID;

View file

@ -35,14 +35,14 @@ public class SymbolsTest extends AbstractGenericTest {
// ensure consistency across the tests. We are setting it int the pdb here (in the static
// assignment block), but we do not know the order that any tests are run, so having the
// same value will ensure consistent results.
private int processorIndex;
private Processor processor;
private SymbolParser symbolParser;
public SymbolsTest() {
try (DummyPdb700 dummyPdb700 = new DummyPdb700(4096, 4096, 4096, 4096)) {
pdb = dummyPdb700;
processorIndex = 0x0000;
pdb.setTargetProcessorIndexNumber(processorIndex);
processor = Processor.I8080;
pdb.setTargetProcessor(processor);
symbolParser = pdb.getSymbolParser();
AbstractMsType type;
@ -290,7 +290,7 @@ public class SymbolsTest extends AbstractGenericTest {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Compile2StMsSymbol.PDB_ID);
writer.putUnsignedInt(0); // flags
writer.putUnsignedShort(processorIndex); // Processor value.
writer.putUnsignedShort(processor.getValue()); // Processor value.
writer.putUnsignedShort(0x0001); // front end major version number
writer.putUnsignedShort(0x0002); // front end minor version number
writer.putUnsignedShort(0x0003); // front end build version number
@ -322,7 +322,7 @@ public class SymbolsTest extends AbstractGenericTest {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Compile2MsSymbol.PDB_ID);
writer.putUnsignedInt(0); // flags
writer.putUnsignedShort(processorIndex); // Processor value.
writer.putUnsignedShort(processor.getValue()); // Processor value.
writer.putUnsignedShort(0x0001); // front end major version number
writer.putUnsignedShort(0x0002); // front end minor version number
writer.putUnsignedShort(0x0003); // front end build version number
@ -354,7 +354,7 @@ public class SymbolsTest extends AbstractGenericTest {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Compile3MsSymbol.PDB_ID);
writer.putUnsignedInt(0); // flags
writer.putUnsignedShort(processorIndex); // Processor value.
writer.putUnsignedShort(processor.getValue()); // Processor value.
writer.putUnsignedShort(0x0001); // front end major version number
writer.putUnsignedShort(0x0002); // front end minor version number
writer.putUnsignedShort(0x0003); // front end build version number
@ -2612,72 +2612,57 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testLocalSlotIndexFieldedLILStMsSymbol()
throws PdbException {
public void testLocalSlotIndexFieldedLILStMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
LocalSlotIndexFieldedLILStMsSymbol.PDB_ID);
writer.putUnsignedShort(LocalSlotIndexFieldedLILStMsSymbol.PDB_ID);
writer.putUnsignedInt(0x10); // slot index
writer.putInt(4096); // type index or metadata token
writer.putByteLengthPrefixedUtf8String("LocalSlotName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof LocalSlotIndexFieldedLILStMsSymbol,
true);
assertEquals(symbol instanceof LocalSlotIndexFieldedLILStMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("LOCALSLOT_ST: [00000010], Type: DummyMsType, LocalSlotName", result);
}
@Test
public void testLocalSlotIndexFieldedLILMsSymbol()
throws PdbException {
public void testLocalSlotIndexFieldedLILMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
LocalSlotIndexFieldedLILMsSymbol.PDB_ID);
writer.putUnsignedShort(LocalSlotIndexFieldedLILMsSymbol.PDB_ID);
writer.putUnsignedInt(0x10); // slot index
writer.putInt(4096); // type index or metadata token
writer.putNullTerminatedUtf8String("LocalSlotName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof LocalSlotIndexFieldedLILMsSymbol, true);
assertEquals(symbol instanceof LocalSlotIndexFieldedLILMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("LOCALSLOT: [00000010], Type: DummyMsType, LocalSlotName", result);
}
@Test
public void testParameterSlotIndexFieldedLILStMsSymbol()
throws PdbException {
public void testParameterSlotIndexFieldedLILStMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ParameterSlotIndexFieldedLILStMsSymbol.PDB_ID);
writer.putUnsignedShort(ParameterSlotIndexFieldedLILStMsSymbol.PDB_ID);
writer.putUnsignedInt(0x10); // slot index
writer.putInt(4096); // type index or metadata token
writer.putByteLengthPrefixedUtf8String("ParamSlotName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof ParameterSlotIndexFieldedLILStMsSymbol,
true);
assertEquals(symbol instanceof ParameterSlotIndexFieldedLILStMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("PARAMSLOT_ST: [00000010], Type: DummyMsType, ParamSlotName", result);
}
@Test
public void testParameterSlotIndexFieldedLILMsSymbol()
throws PdbException {
public void testParameterSlotIndexFieldedLILMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ParameterSlotIndexFieldedLILMsSymbol.PDB_ID);
writer.putUnsignedShort(ParameterSlotIndexFieldedLILMsSymbol.PDB_ID);
writer.putUnsignedInt(0x10); // slot index
writer.putInt(4096); // type index or metadata token
writer.putNullTerminatedUtf8String("ParamSlotName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof ParameterSlotIndexFieldedLILMsSymbol,
true);
assertEquals(symbol instanceof ParameterSlotIndexFieldedLILMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("PARAMSLOT: [00000010], Type: DummyMsType, ParamSlotName", result);
}
@ -2865,11 +2850,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testManLocOrParamReltoVFPStMsSymbol()
throws PdbException {
public void testManLocOrParamReltoVFPStMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ManLocOrParamReltoVFPStMsSymbol.PDB_ID);
writer.putUnsignedShort(ManLocOrParamReltoVFPStMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
byte[] localVarFlags = createLocalVariableFlagsBuffer(true, true, true, true, true, true,
@ -2879,8 +2862,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putByteLengthPrefixedUtf8String("ManagedFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof ManLocOrParamReltoVFPStMsSymbol, true);
assertEquals(symbol instanceof ManLocOrParamReltoVFPStMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("MANFRAMEREL_ST: [00003000], [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -2888,11 +2870,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testManLocOrParamReltoVFPMsSymbol()
throws PdbException {
public void testManLocOrParamReltoVFPMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ManLocOrParamReltoVFPMsSymbol.PDB_ID);
writer.putUnsignedShort(ManLocOrParamReltoVFPMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
byte[] localVarFlags = createLocalVariableFlagsBuffer(true, true, true, true, true, true,
@ -2902,8 +2882,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putNullTerminatedUtf8String("ManagedFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof ManLocOrParamReltoVFPMsSymbol,
true);
assertEquals(symbol instanceof ManLocOrParamReltoVFPMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("MANFRAMEREL: [00003000], [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -2911,11 +2890,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testAttribLocOrParamReltoVFPMsSymbol()
throws PdbException {
public void testAttribLocOrParamReltoVFPMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
AttribLocOrParamReltoVFPMsSymbol.PDB_ID);
writer.putUnsignedShort(AttribLocOrParamReltoVFPMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
byte[] localVarFlags = createLocalVariableFlagsBuffer(true, true, true, true, true, true,
@ -2925,9 +2902,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putNullTerminatedUtf8String("AttributedFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof AttribLocOrParamReltoVFPMsSymbol,
true);
assertEquals(symbol instanceof AttribLocOrParamReltoVFPMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("ATTR_MANFRAMEREL: [00003000], [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -3092,8 +3067,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putByteLengthPrefixedUtf8String("ManagedManyRegister2Name");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof ManagedLocalOrParameterSIMR2StMsSymbol,
true);
assertEquals(symbol instanceof ManagedLocalOrParameterSIMR2StMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("MANMANYREG2_ST: al, cl, dl DummyMsType ManagedManyRegister2Name", result);
}
@ -3135,18 +3109,15 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putNullTerminatedUtf8String("ManagedManyRegister2Name");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof AttributedLocalOrParameterSIMRMsSymbol,
true);
assertEquals(symbol instanceof AttributedLocalOrParameterSIMRMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("ATTR_MANYREG: al, cl, dl DummyMsType ManagedManyRegister2Name", result);
}
@Test
public void testManLocOrParamReltoAMPStMsSymbol()
throws PdbException {
public void testManLocOrParamReltoAMPStMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ManLocOrParamReltoAMPStMsSymbol.PDB_ID);
writer.putUnsignedShort(ManLocOrParamReltoAMPStMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
writer.putUnsignedShort(1); // Register index
@ -3157,9 +3128,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putByteLengthPrefixedUtf8String("ManagedAltFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof ManLocOrParamReltoAMPStMsSymbol,
true);
assertEquals(symbol instanceof ManLocOrParamReltoAMPStMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("MANREGREL_ST: al+00003000, [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -3167,11 +3136,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testManLocOrParamReltoAMPMsSymbol()
throws PdbException {
public void testManLocOrParamReltoAMPMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
ManLocOrParamReltoAMPMsSymbol.PDB_ID);
writer.putUnsignedShort(ManLocOrParamReltoAMPMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
writer.putUnsignedShort(1); // Register index
@ -3182,8 +3149,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putNullTerminatedUtf8String("ManagedAltFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof ManLocOrParamReltoAMPMsSymbol, true);
assertEquals(symbol instanceof ManLocOrParamReltoAMPMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("MANREGREL: al+00003000, [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -3191,11 +3157,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testAttribLocOrParamReltoAMPMsSymbol()
throws PdbException {
public void testAttribLocOrParamReltoAMPMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
AttribLocOrParamReltoAMPMsSymbol.PDB_ID);
writer.putUnsignedShort(AttribLocOrParamReltoAMPMsSymbol.PDB_ID);
writer.putUnsignedInt(0x3000); // Frame-relative offset
writer.putInt(4096); // type index or mdatadata token
writer.putUnsignedShort(1); // Register index
@ -3206,9 +3170,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putNullTerminatedUtf8String("AttributedAltFrameName");
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof AttribLocOrParamReltoAMPMsSymbol,
true);
assertEquals(symbol instanceof AttribLocOrParamReltoAMPMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("ATTR_REGREL: al+00003000, [0001:00001000]: Param: 4096 Address Taken," +
" Compiler Generated, aggregate, aggregated, aliased, alias, return value," +
@ -3518,8 +3480,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putBytes(gap2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof EnregisteredSymbolDARMsSymbol,
true);
assertEquals(symbol instanceof EnregisteredSymbolDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("DEFRANGE_REGISTER:Attributes: MayAvailable al" +
" Range: [0001:00002000] - [0001:00003000]," +
@ -3539,8 +3500,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putBytes(gap2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof FramePointerRelativeDARMsSymbol,
true);
assertEquals(symbol instanceof FramePointerRelativeDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("DEFRANGE_FRAMEPOINTER_REL: FrameOffset: 1000" +
" Range: [0001:00002000] - [0001:00003000]," +
@ -3548,11 +3508,9 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testEnregisteredFieldOfSymbolDARMsSymbol()
throws PdbException {
public void testEnregisteredFieldOfSymbolDARMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
EnregisteredFieldOfSymbolDARMsSymbol.PDB_ID);
writer.putUnsignedShort(EnregisteredFieldOfSymbolDARMsSymbol.PDB_ID);
writer.putUnsignedShort(1); // register holding the value of the symbol
// attribute (bit 0: 1=may have no user name on one of the control flow paths
writer.putUnsignedShort(0x01);
@ -3566,8 +3524,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putBytes(gap2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof EnregisteredFieldOfSymbolDARMsSymbol, true);
assertEquals(symbol instanceof EnregisteredFieldOfSymbolDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("DEFRANGE_SUBFIELD_REGISTER: offset at 0010: Attributes: MayAvailable al" +
" Range: [0001:00002000] - [0001:00003000]," +
@ -3575,27 +3532,21 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testFramePointerRelativeFullScopeDARMsSymbol()
throws PdbException {
public void testFramePointerRelativeFullScopeDARMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
FramePointerRelativeFullScopeDARMsSymbol.PDB_ID);
writer.putUnsignedShort(FramePointerRelativeFullScopeDARMsSymbol.PDB_ID);
writer.putInt(0x0100); // offset to frame pointer
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof FramePointerRelativeFullScopeDARMsSymbol,
true);
assertEquals(symbol instanceof FramePointerRelativeFullScopeDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: FrameOffset: 0100 FULL_SCOPE", result);
}
@Test
public void testEnregisteredSymbolRelativeDARMsSymbol()
throws PdbException {
public void testEnregisteredSymbolRelativeDARMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(
EnregisteredSymbolRelativeDARMsSymbol.PDB_ID);
writer.putUnsignedShort(EnregisteredSymbolRelativeDARMsSymbol.PDB_ID);
writer.putUnsignedShort(1); // register holding base pointer of symbol
// spilled member for s.i. (1 bit)
// padding for future (3 bits)
@ -3610,8 +3561,7 @@ public class SymbolsTest extends AbstractGenericTest {
writer.putBytes(gap2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(
symbol instanceof EnregisteredSymbolRelativeDARMsSymbol, true);
assertEquals(symbol instanceof EnregisteredSymbolRelativeDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals(
"DEFRANGE_REGISTER_REL: [al + 0100] spilledUserDefinedTypeMember offset at 16" +
@ -3767,8 +3717,7 @@ public class SymbolsTest extends AbstractGenericTest {
}
@Test
public void testDeferredProcedureCallPointerTagRegDimDARMsSymbol()
throws PdbException {
public void testDeferredProcedureCallPointerTagRegDimDARMsSymbol() throws PdbException {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(DeferredProcedureCallPointerTagRegDimDARMsSymbol.PDB_ID);
writer.putUnsignedShort(1); // register type from HLSLREG
@ -3792,8 +3741,7 @@ public class SymbolsTest extends AbstractGenericTest {
}
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsSymbol symbol = symbolParser.parse(reader);
assertEquals(symbol instanceof DeferredProcedureCallPointerTagRegDimDARMsSymbol,
true);
assertEquals(symbol instanceof DeferredProcedureCallPointerTagRegDimDARMsSymbol, true);
String result = symbol.toString().trim();
assertEquals("DEFRANGE_DPC_PTR_TAG: al, RegisterIndices = 2, SAMPLER" +
" Range: [0001:00002000] - [0001:00003000]," +

View file

@ -24,6 +24,7 @@ import org.junit.Test;
import generic.test.AbstractGenericTest;
import ghidra.pdb.*;
import ghidra.pdb.pdbreader.*;
import ghidra.pdb.pdbreader.symbol.Processor;
import ghidra.pdb.pdbreader.symbol.RegisterMsSymbol;
import ghidra.util.Msg;
@ -36,7 +37,7 @@ public class TypesTest extends AbstractGenericTest {
// ensure consistency across the tests. We are setting it int the pdb here (in the static
// assignment block), but we do not know the order that any tests are run, so having the
// same value will ensure consistent results.
private int processorIndex;
private Processor processor;
private int stringIdMsType1;
private int stringIdMsType2;
private int substringListMsType1;
@ -49,8 +50,8 @@ public class TypesTest extends AbstractGenericTest {
public TypesTest() {
try (DummyPdb700 dummyPdb700 = new DummyPdb700(4096, 4096, 4096, 4096)) {
pdb = dummyPdb700;
processorIndex = 0x0000;
pdb.setTargetProcessorIndexNumber(processorIndex);
processor = Processor.I8080;
pdb.setTargetProcessor(processor);
typeParser = pdb.getTypeParser();
AbstractMsType type;