From f10a766506a3ae8c1161900f47299c82632c7f0d Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Tue, 14 May 2019 16:28:56 -0400 Subject: [PATCH] GT-2867 - PDB Universal changes --- .../pdbreader/AbstractDatabaseInterface.java | 7 +- .../ghidra/pdb/pdbreader/AbstractPdb.java | 25 +- .../ghidra/pdb/pdbreader/CategoryIndex.java | 8 +- .../pdb/pdbreader/DatabaseInterface.java | 3 +- .../pdb/pdbreader/DatabaseInterfaceNew.java | 76 ++-- .../java/ghidra/pdb/pdbreader/DebugData.java | 328 ++++++++++++++++++ .../ghidra/pdb/pdbreader/DebugHeader.java | 96 +++++ .../pdbreader/FramePointerOmissionRecord.java | 217 ++++++++++++ .../pdb/pdbreader/ImageFileMachine.java | 104 ++++++ .../pdb/pdbreader/ImageFunctionEntry.java | 91 +++++ .../pdb/pdbreader/ImageSectionHeader.java | 169 +++++++++ .../pdb/pdbreader/LinkerUnwindInfo.java | 94 +++++ .../pdb/pdbreader/RvaVaDebugHeader.java | 107 ++++++ .../pdb/pdbreader/SegmentMapDescription.java | 17 + .../symbol/AbstractCompile2MsSymbol.java | 6 +- .../symbol/AnnotationReferenceMsSymbol.java | 8 + .../pdbreader/symbol/Compile3MsSymbol.java | 6 +- .../symbol/CompileFlagsMsSymbol.java | 6 +- .../symbol/DataReferenceMsSymbol.java | 8 + .../LocalProcedureReferenceMsSymbol.java | 8 + .../symbol/ProcedureReferenceMsSymbol.java | 8 + .../pdb/pdbreader/symbol/Processor.java | 137 ++++++++ .../pdb/pdbreader/symbol/ProcessorName.java | 139 -------- .../symbol/ReferenceSymbolInternals2.java | 8 + .../pdb/pdbreader/symbol/RegisterName.java | 164 +++++++-- ...enReferenceToManagedProcedureMsSymbol.java | 8 + .../pdb/pdbreader/symbol/SymbolsTest.java | 154 +++----- .../ghidra/pdb/pdbreader/type/TypesTest.java | 7 +- 28 files changed, 1664 insertions(+), 345 deletions(-) create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugData.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugHeader.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/FramePointerOmissionRecord.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFileMachine.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFunctionEntry.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageSectionHeader.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/LinkerUnwindInfo.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/RvaVaDebugHeader.java create mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Processor.java delete mode 100644 Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcessorName.java diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractDatabaseInterface.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractDatabaseInterface.java index b033a6cc3a..305ff40595 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractDatabaseInterface.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractDatabaseInterface.java @@ -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. diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractPdb.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractPdb.java index 5cd112bc8e..f2b27d4def 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractPdb.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/AbstractPdb.java @@ -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; + } } /** diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/CategoryIndex.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/CategoryIndex.java index b8bb9774ed..7a8796e0b8 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/CategoryIndex.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/CategoryIndex.java @@ -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 { /** * 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; + } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterface.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterface.java index fe62e3d887..9eb56aed69 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterface.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterface.java @@ -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); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterfaceNew.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterfaceNew.java index 2756cc5a07..027b9090cb 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterfaceNew.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DatabaseInterfaceNew.java @@ -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 editAndContinueNameList = new ArrayList<>(); protected List 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)); - } - } - } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugData.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugData.java new file mode 100644 index 0000000000..1c3942e6db --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugData.java @@ -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. + *

+ * NOTE: The processing that falls under DebugData is only partially done. We have implemented + * and viewed the results of real data for: + *

  • SECTION_HEADER.
  • + *

    + * We have partially implemented the following: + *

  • FRAME_POINTER_OMISSION
  • + *
  • X_DATA
  • + *
  • P_DATA
  • + */ +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 debugStreamList = new ArrayList<>(); + + private List framePointerOmissionData = new ArrayList<>(); + private List imageSectionHeaders = new ArrayList<>(); + + private List 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 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"); + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugHeader.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugHeader.java new file mode 100644 index 0000000000..72581d8ee0 --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/DebugHeader.java @@ -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)); + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/FramePointerOmissionRecord.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/FramePointerOmissionRecord.java new file mode 100644 index 0000000000..b74d9ed515 --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/FramePointerOmissionRecord.java @@ -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 + * MSFT Documentation, which specifies: + *
    + *   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
    + * 
    + */ +public class FramePointerOmissionRecord { + + public enum FrameType { + FPO("fpo", 0), TRAP("trap", 1), TSS("tss", 2), NON_FPO("std", 3); + + private static final Map 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"); + } +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFileMachine.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFileMachine.java new file mode 100644 index 0000000000..fc64d3d1dc --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFileMachine.java @@ -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 + * Image File Machine Constants. + * See + * Also. + * Also see + * Other use. + */ +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 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; + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFunctionEntry.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFunctionEntry.java new file mode 100644 index 0000000000..696d8beb2c --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageFunctionEntry.java @@ -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(); + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageSectionHeader.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageSectionHeader.java new file mode 100644 index 0000000000..14daf7aba4 --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/ImageSectionHeader.java @@ -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"); + } +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/LinkerUnwindInfo.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/LinkerUnwindInfo.java new file mode 100644 index 0000000000..fcfa734e4c --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/LinkerUnwindInfo.java @@ -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)); + } +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/RvaVaDebugHeader.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/RvaVaDebugHeader.java new file mode 100644 index 0000000000..e7e0b5c189 --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/RvaVaDebugHeader.java @@ -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)); + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/SegmentMapDescription.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/SegmentMapDescription.java index beaebe372b..02110647c5 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/SegmentMapDescription.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/SegmentMapDescription.java @@ -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. diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AbstractCompile2MsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AbstractCompile2MsSymbol.java index 6e26527478..5f96d42bb9 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AbstractCompile2MsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AbstractCompile2MsSymbol.java @@ -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); } /** diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AnnotationReferenceMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AnnotationReferenceMsSymbol.java index 8352c16410..903b300d31 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AnnotationReferenceMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/AnnotationReferenceMsSymbol.java @@ -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); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Compile3MsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Compile3MsSymbol.java index 2a67f658e0..81b29b6d83 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Compile3MsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Compile3MsSymbol.java @@ -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 diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/CompileFlagsMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/CompileFlagsMsSymbol.java index 70e15f8972..c6bb2597ea 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/CompileFlagsMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/CompileFlagsMsSymbol.java @@ -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 diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/DataReferenceMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/DataReferenceMsSymbol.java index 3943419dbe..f5165fca6b 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/DataReferenceMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/DataReferenceMsSymbol.java @@ -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); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/LocalProcedureReferenceMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/LocalProcedureReferenceMsSymbol.java index d7dc9efa86..c0d6527cfe 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/LocalProcedureReferenceMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/LocalProcedureReferenceMsSymbol.java @@ -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); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcedureReferenceMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcedureReferenceMsSymbol.java index cedb134847..9d2ada1e33 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcedureReferenceMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcedureReferenceMsSymbol.java @@ -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; diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Processor.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Processor.java new file mode 100644 index 0000000000..12970dae6b --- /dev/null +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/Processor.java @@ -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 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; + } + +} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcessorName.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcessorName.java deleted file mode 100644 index 6699059196..0000000000 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ProcessorName.java +++ /dev/null @@ -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 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); - } - -} diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ReferenceSymbolInternals2.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ReferenceSymbolInternals2.java index b1eb5c569b..0791435d6b 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ReferenceSymbolInternals2.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/ReferenceSymbolInternals2.java @@ -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); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/RegisterName.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/RegisterName.java index 0723fa9a04..bf879e761d 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/RegisterName.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/RegisterName.java @@ -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; + } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/TokenReferenceToManagedProcedureMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/TokenReferenceToManagedProcedureMsSymbol.java index 191321b694..aad8079f02 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/TokenReferenceToManagedProcedureMsSymbol.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/pdb/pdbreader/symbol/TokenReferenceToManagedProcedureMsSymbol.java @@ -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; diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/symbol/SymbolsTest.java b/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/symbol/SymbolsTest.java index 134d72bc7a..05f78be558 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/symbol/SymbolsTest.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/symbol/SymbolsTest.java @@ -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]," + diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/type/TypesTest.java b/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/type/TypesTest.java index 9b2afcd04c..36269392db 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/type/TypesTest.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/pdb/pdbreader/type/TypesTest.java @@ -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;