mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 13:43:00 +00:00
GT-2867 - PDB Universal changes
This commit is contained in:
parent
da72cbedf5
commit
f10a766506
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]," +
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue