diff --git a/Ghidra/Features/PDB/developer_scripts/pdbquery/PdbQuery.java b/Ghidra/Features/PDB/developer_scripts/pdbquery/PdbQuery.java
index 41778c89af..6ec81dd06e 100644
--- a/Ghidra/Features/PDB/developer_scripts/pdbquery/PdbQuery.java
+++ b/Ghidra/Features/PDB/developer_scripts/pdbquery/PdbQuery.java
@@ -200,7 +200,7 @@ public class PdbQuery {
TaskMonitor monitor = script.getMonitor();
monitor.initialize(numModules);
- println(script, "Searching " + numModules + "PDB modules' symbol components...");
+ println(script, "Searching " + numModules + " PDB modules' symbol components...");
for (int module = 0; module <= numModules; module++) {
monitor.checkCancelled();
SymbolGroup symbolGroup = new SymbolGroup(pdb, module);
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/Module.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/Module.java
index 7c8f7309bf..a26365e166 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/Module.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/Module.java
@@ -125,10 +125,9 @@ public class Module {
* Returns an MsSymbolIterator for the symbols of this module
* @return the iterator
* @throws CancelledException upon user cancellation
- * @throws IOException upon error reading stream
* @throws PdbException upon invalid cvSignature
*/
- public MsSymbolIterator iterator() throws CancelledException, IOException, PdbException {
+ public MsSymbolIterator getSymbolIterator() throws CancelledException, PdbException {
int startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber);
int lengthSymbols = moduleInformation.getSizeLocalSymbolsDebugInformation();
return new MsSymbolIterator(pdb, streamNumber, startingOffset, lengthSymbols);
@@ -329,7 +328,7 @@ public class Module {
private void dumpSymbols(Writer writer) throws IOException, CancelledException, PdbException {
writer.write("Symbols-----------------------------------------------------");
- MsSymbolIterator symbolIter = iterator();
+ MsSymbolIterator symbolIter = getSymbolIterator();
while (symbolIter.hasNext()) {
pdb.checkCancelled();
AbstractMsSymbol symbol = symbolIter.next();
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/PdbDebugInfo.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/PdbDebugInfo.java
index a3c3fdd508..0f2a0ffa30 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/PdbDebugInfo.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/PdbDebugInfo.java
@@ -560,6 +560,7 @@ public abstract class PdbDebugInfo {
for (ModuleInformation moduleInformation : moduleInformationList) {
pdb.checkCancelled();
Module module = new Module(pdb, moduleInformation);
+ // Indices: module #1 goes into index 0 and so on.
modules.add(module);
}
}
@@ -574,7 +575,8 @@ public abstract class PdbDebugInfo {
* @return the module
*/
public Module getModule(int moduleNum) {
- return modules.get(moduleNum);
+ // Indices: module #1 goes into index 0 and so on.
+ return modules.get(moduleNum - 1);
}
/**
@@ -583,7 +585,7 @@ public abstract class PdbDebugInfo {
* @throws CancelledException upon user cancellation
* @throws PdbException upon not enough data left to parse
*/
- MsSymbolIterator getSymbolIterator() throws CancelledException, PdbException {
+ public MsSymbolIterator getSymbolIterator() throws CancelledException, PdbException {
return new MsSymbolIterator(pdb, streamNumberSymbolRecords, 0, MsfStream.MAX_STREAM_LENGTH);
}
@@ -593,12 +595,11 @@ public abstract class PdbDebugInfo {
* @return an iterator over all symbols of the module
* @throws CancelledException upon user cancellation
* @throws PdbException upon not enough data left to parse
- * @throws IOException upon issue reading the stream
*/
- MsSymbolIterator getSymbolIterator(int moduleNum)
- throws CancelledException, PdbException, IOException {
- Module module = modules.get(moduleNum);
- return module.iterator();
+ public MsSymbolIterator getSymbolIterator(int moduleNum)
+ throws CancelledException, PdbException {
+ Module module = getModule(moduleNum);
+ return module.getSymbolIterator();
}
private void dumpSymbols(Writer writer) throws CancelledException, IOException, PdbException {
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SymbolRecords.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SymbolRecords.java
index 36ba5ec90e..000bb2a6f0 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SymbolRecords.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SymbolRecords.java
@@ -4,9 +4,9 @@
* 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.
@@ -175,15 +175,20 @@ public class SymbolRecords {
* @param streamNumber the stream number
* @return the space
* @throws CancelledException upon user cancellation
- * @throws IOException upon error reading from file
* @throws PdbException upon processing error
*/
public int getCvSigLength(int streamNumber)
- throws CancelledException, IOException, PdbException {
+ throws CancelledException, PdbException {
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
return 0; // returning inconsequential value; fact of NIL will be dealt with elsewhere
}
- PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, 4);
+ PdbByteReader reader;
+ try {
+ reader = pdb.getReaderForStreamNumber(streamNumber, 0, 4);
+ }
+ catch (IOException e) {
+ throw new PdbException("PDB Error: Not enough data to read CvSigLength");
+ }
if (getSig) {
cvSignature = reader.parseInt();
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/AbstractThunkMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/AbstractThunkMsSymbol.java
index b1b7618a25..f06ccd0d33 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/AbstractThunkMsSymbol.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/AbstractThunkMsSymbol.java
@@ -26,9 +26,7 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.*;
* Note: we do not necessarily understand each of these symbol type classes. Refer to the
* base class for more information.
*/
-public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
- implements AddressMsSymbol, NameMsSymbol {
-
+public abstract class AbstractThunkMsSymbol extends AbstractProcedureMsSymbol {
public enum Ordinal {
NOTYPE("", 0),
@@ -115,6 +113,7 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the parent pointer.
* @return Parent pointer.
*/
+ @Override
public long getParentPointer() {
return parentPointer;
}
@@ -123,6 +122,7 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the end pointer.
* @return End pointer.
*/
+ @Override
public long getEndPointer() {
return endPointer;
}
@@ -131,10 +131,47 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the next pointer
* @return Next pointer.
*/
+ @Override
public long getNextPointer() {
return nextPointer;
}
+ /**
+ * Returns the procedure length. For thunk, we think procedure length is the length field
+ * @return Length.
+ */
+ @Override
+ public long getProcedureLength() {
+ return length;
+ }
+
+ /**
+ * Returns the debug start offset. This is dummied-in as the zero offset
+ * @return Debug start offset.
+ */
+ @Override
+ public long getDebugStartOffset() {
+ return 0L;
+ }
+
+ /**
+ * Returns the debug end offset. This is dummied-in as the length of the method
+ * @return Debug end offset.
+ */
+ @Override
+ public long getDebugEndOffset() {
+ return length;
+ }
+
+ /**
+ * Returns the type record number. We dummied-in NO_TYPE, as there is not type record number
+ * @return Type record number.
+ */
+ @Override
+ public RecordNumber getTypeRecordNumber() {
+ return RecordNumber.NO_TYPE;
+ }
+
/**
* Returns the offset.
* @return Offset.
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/SeparatedCodeFromCompilerSupportMsSymbol.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/SeparatedCodeFromCompilerSupportMsSymbol.java
index f2f4109d65..ac0149b59e 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/SeparatedCodeFromCompilerSupportMsSymbol.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/symbol/SeparatedCodeFromCompilerSupportMsSymbol.java
@@ -141,7 +141,7 @@ public class SeparatedCodeFromCompilerSupportMsSymbol extends AbstractMsSymbol
* Returns the parent segment.
* @return Parent segment.
*/
- public long getSegmentParent() {
+ public int getSegmentParent() {
return sectionParent;
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractBlockContextApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractBlockContextApplier.java
new file mode 100644
index 0000000000..855662e679
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractBlockContextApplier.java
@@ -0,0 +1,203 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ghidra.app.cmd.function.CallDepthChangeInfo;
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.address.AddressSet;
+import ghidra.program.model.lang.Register;
+import ghidra.program.model.listing.Function;
+import ghidra.util.exception.CancelledException;
+import ghidra.util.task.TaskMonitor;
+
+/**
+ * Abstract applier for symbols that need block context.
+ *
+ * Note that this class as well as its children all need to be massaged to find the appropriate
+ * mechanisms to do the work. Whether all children belong under this class or not is a question,
+ * and whether this current class name is appropriate is all in question. Even whether
+ * this class is for nesting or more for functions is unknown... perhaps two of the children
+ * that do functions should have an intermediate parent (for functions) and the other
+ * (SeparatedCode) might be a direct child??? TODO, TODO, TODO
+ */
+public abstract class AbstractBlockContextApplier extends MsSymbolApplier
+ implements DeferrableFunctionSymbolApplier, NestingSymbolApplier {
+
+ protected BlockNestingContext context;
+ protected long specifiedFrameSize = 0;
+
+ /**
+ * Constructor
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working.
+ */
+ public AbstractBlockContextApplier(DefaultPdbApplicator applicator) {
+ super(applicator);
+ }
+
+ void initContext() {
+ context = new BlockNestingContext(applicator);
+ }
+
+ @Override
+ public void beginBlock(Address startAddress, String name, long length) {
+ context.beginBlock(startAddress, name, length);
+ }
+
+ @Override
+ public void endBlock() {
+ context.endBlock();
+ }
+
+ /**
+ * Set the specified frame size.
+ * @param specifiedFrameSize the frame size.
+ */
+ void setSpecifiedFrameSize(long specifiedFrameSize) {
+ this.specifiedFrameSize = specifiedFrameSize;
+ }
+
+ protected boolean notDone(BlockNestingContext blockNestingContext, MsSymbolIterator iter) {
+ return blockNestingContext.notDone() && iter.hasNext();
+ }
+
+ protected boolean processEndSymbol(long endOffset, MsSymbolIterator iter) {
+
+ // Jump to what should be the END symbol, but this might not be necessary, depending on
+ // what the caller is doing; for instance, if already doing an initGetByOffset() from
+ // "globals" offsets, then unnecessary, but it is safer that we do it here for now.
+ iter.initGetByOffset(endOffset);
+
+ AbstractMsSymbol subSymbol = iter.peek();
+ boolean success = (subSymbol instanceof EndMsSymbol endSymbol);
+ if (success) {
+ iter.next();
+ }
+ else {
+ applicator.appendLogMsg("PDB: Expecting EndMsSymbol termation of function but found " +
+ subSymbol.getClass().getSimpleName());
+ }
+ return success;
+ }
+
+ protected void deferredProcessing(MsSymbolIterator iter, String name, Address address,
+ Address blockAddress, long length)
+ throws CancelledException, PdbException {
+
+ long currentFrameSize = 0;
+
+// symbolBlockNestingLevel = 0;
+// BlockCommentsManager comments = new BlockCommentsManager();
+// currentBlockAddress = null;
+
+ initContext();
+
+ context.beginBlock(blockAddress, name, length);
+
+// TaskMonitor monitor = applicator.getCancelOnlyWrappingMonitor();
+// RegisterChangeCalculator registerChangeCalculator =
+// new RegisterChangeCalculator(symbol, function, monitor);
+
+// // TODO: need to decide how/where these get passed around... either we pass the function
+// // around or pass things in the blockNestingContext or other
+// int baseParamOffset = VariableUtilities.getBaseStackParamOffset(function_x);
+// long currentFrameSize = 0;
+
+// boolean foundUnsupported = false;
+ while (notDone(context, iter)) {
+ applicator.checkCancelled();
+ AbstractMsSymbol subSymbol = iter.peek();
+
+ // TODO: msSymbol, subSymbol, comments, currentFrameSize, baseParmOffset
+
+ MsSymbolApplier applier = applicator.getSymbolApplier(subSymbol, iter);
+ if (applier instanceof NestableSymbolApplier nestingApplier) {
+ nestingApplier.applyTo(this, iter);
+ }
+ else {
+ applicator.getPdbApplicatorMetrics().witnessNonNestableSymbolType(subSymbol);
+// foundUnsupported = true;
+ iter.next();
+ }
+ }
+// if (foundUnsupported) {
+// pdbLogAndInfoMessage(this, "One or or more non-nestable symbols skipped for: " + name);
+// }
+
+ // comments
+ //TODO: deal with specifiedAddress vs. address... do we still want to do any of this
+// long addressDelta = address_x.subtract(specifiedAddress_x);
+// blockNestingContext.getComments().applyTo(applicator.getProgram(), addressDelta);
+ context.getComments().applyTo(applicator.getProgram(), 0);
+
+// // line numbers
+// // TODO: not done yet
+//// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
+//// applyLineNumbers.applyTo(monitor, log);
+
+ }
+
+ abstract long getStartOffset();
+
+ abstract long getEndOffset();
+
+ //==============================================================================================
+ protected static class RegisterChangeCalculator {
+
+ private Map registerChangeByRegisterName = new HashMap<>();
+ private CallDepthChangeInfo callDepthChangeInfo;
+ private Address debugStart;
+
+ RegisterChangeCalculator(AbstractProcedureMsSymbol procedureSymbol,
+ Function function, TaskMonitor monitor) throws CancelledException {
+ callDepthChangeInfo = createCallDepthChangInfo(procedureSymbol, function, monitor);
+ }
+
+ private CallDepthChangeInfo createCallDepthChangInfo(
+ AbstractProcedureMsSymbol procedureSymbol, Function function, TaskMonitor monitor)
+ throws CancelledException {
+ if (procedureSymbol == null) {
+ return null;
+ }
+ Register frameReg = function.getProgram().getCompilerSpec().getStackPointer();
+ Address entryAddr = function.getEntryPoint();
+ debugStart = entryAddr.add(procedureSymbol.getDebugStartOffset());
+ AddressSet scopeSet = new AddressSet();
+ scopeSet.addRange(entryAddr, debugStart);
+ return new CallDepthChangeInfo(function, scopeSet, frameReg, monitor);
+ }
+
+ Integer getRegChange(DefaultPdbApplicator applicator, Register register) {
+ if (callDepthChangeInfo == null || register == null) {
+ return null;
+ }
+ Integer change = registerChangeByRegisterName.get(register);
+ if (change != null) {
+ return change;
+ }
+ change = callDepthChangeInfo.getRegDepth(debugStart, register);
+ registerChangeByRegisterName.put(register, change);
+ return change;
+ }
+
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockCommentsManager.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockCommentsManager.java
index 64eeab4bf0..a217341fc2 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockCommentsManager.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockCommentsManager.java
@@ -22,6 +22,7 @@ import ghidra.app.cmd.comments.SetCommentCmd;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
+import ghidra.util.Msg;
/**
* Manages the nesting of scoping blocks for functions and scoped variables.
@@ -120,10 +121,17 @@ public class BlockCommentsManager {
CodeUnit.PRE_COMMENT);
}
for (Map.Entry entry : blockPostComments.entrySet()) {
- Address endCodeUnitAddress = program.getListing().getCodeUnitContaining(
- entry.getKey().add(addressDelta)).getAddress();
- appendBlockComment(program, endCodeUnitAddress, entry.getValue(),
- CodeUnit.POST_COMMENT);
+ CodeUnit codeUnit = program.getListing()
+ .getCodeUnitContaining(
+ entry.getKey().add(addressDelta));
+ if (codeUnit == null) {
+ Msg.warn(this, "PDB error: null Code unit");
+ }
+ else {
+ Address endCodeUnitAddress = codeUnit.getAddress();
+ appendBlockComment(program, endCodeUnitAddress, entry.getValue(),
+ CodeUnit.POST_COMMENT);
+ }
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingContext.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingContext.java
new file mode 100644
index 0000000000..cebf589b9f
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingContext.java
@@ -0,0 +1,87 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.program.model.address.Address;
+
+/**
+ * Manages block nesting for function-related symbols
+ */
+public class BlockNestingContext {
+
+ private static final String BLOCK_INDENT = " ";
+
+ private DefaultPdbApplicator applicator;
+ private BlockCommentsManager comments;
+ private int nestingLevel;
+ private Address currentBlockAddress;
+
+ public BlockNestingContext(DefaultPdbApplicator applicator) {
+ this.applicator = applicator;
+ nestingLevel = 0;
+ comments = new BlockCommentsManager();
+ }
+
+ public boolean notDone() {
+ return nestingLevel > 0;
+ }
+
+ public Address getCurrentBlockAddress() {
+ return currentBlockAddress;
+ }
+
+ public BlockCommentsManager getComments() {
+ return comments;
+ }
+
+ public int endBlock() {
+ if (--nestingLevel < 0) {
+ applicator.appendLogMsg("Block Nesting went negative for ending block that began at " +
+ currentBlockAddress);
+ }
+ if (nestingLevel == 0) {
+ //currentFunctionSymbolApplier = null;
+ }
+ return nestingLevel;
+ }
+
+ public void beginBlock(Address startAddress, String name, long length) {
+ ++nestingLevel;
+ currentBlockAddress = startAddress;
+ if (!applicator.getPdbApplicatorOptions().applyCodeScopeBlockComments()) {
+ return;
+ }
+ if (applicator.isInvalidAddress(startAddress, name)) {
+ return;
+ }
+ String indent = getIndent(nestingLevel);
+ String baseComment = "level " + nestingLevel + ", length " + length;
+ String preComment = indent + "PDB: Block Beg, " + baseComment;
+ if (name != null && !name.isEmpty()) {
+ preComment += " (" + name + ")";
+ }
+ comments.addPreComment(startAddress, preComment);
+
+ String postComment = indent + "PDB: Block End, " + baseComment;
+ Address endAddress = startAddress.add(((length <= 0) ? 0 : length - 1));
+ comments.addPostComment(endAddress, postComment);
+ }
+
+ public String getIndent(int indentLevel) {
+ return BLOCK_INDENT.repeat(indentLevel);
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingSymbolApplier.java
new file mode 100644
index 0000000000..30762ace2f
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockNestingSymbolApplier.java
@@ -0,0 +1,24 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+/**
+ * Interface class for MsSymbolApplier that not only can do nesting but that responsible for
+ * block-nesting (start and end of block).
+ */
+interface BlockNestingSymbolApplier extends NestingSymbolApplier {
+ // Empty
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockSymbolApplier.java
index c44d1f6e16..1ce4221afc 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/BlockSymbolApplier.java
@@ -26,52 +26,38 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractBlockMsSymbol} symbols.
*/
-public class BlockSymbolApplier extends MsSymbolApplier {
+public class BlockSymbolApplier extends MsSymbolApplier
+ implements BlockNestingSymbolApplier, NestableSymbolApplier {
private AbstractBlockMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public BlockSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractBlockMsSymbol)) {
+ public BlockSymbolApplier(DefaultPdbApplicator applicator, AbstractBlockMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ Address address = applicator.getAddress(symbol);
+ applier.beginBlock(address, symbol.getName(), symbol.getLength());
+ }
+ }
+
+ private AbstractBlockMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractBlockMsSymbol blockSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
- symbol = (AbstractBlockMsSymbol) abstractSymbol;
+ return blockSymbol;
}
- @Override
- void apply() throws PdbException, CancelledException {
- pdbLogAndInfoMessage(this,
- "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing
- }
-
- @Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- Address address = applicator.getAddress(symbol);
- if (applierParam instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applierParam;
- functionSymbolApplier.beginBlock(address, symbol.getName(), symbol.getLength());
- }
- else if (applierParam instanceof SeparatedCodeSymbolApplier) {
- SeparatedCodeSymbolApplier separatedCodeSymbolApplier =
- (SeparatedCodeSymbolApplier) applierParam;
- separatedCodeSymbolApplier.beginBlock(address);
- }
- else if (applierParam instanceof ManagedProcedureSymbolApplier) {
- ManagedProcedureSymbolApplier procedureSymbolApplier =
- (ManagedProcedureSymbolApplier) applierParam;
- procedureSymbolApplier.beginBlock(address, symbol.getName(), symbol.getLength());
- }
- }
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DataSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DataSymbolApplier.java
index 80cf1e081f..6f938002fd 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DataSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DataSymbolApplier.java
@@ -4,9 +4,9 @@
* 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.
@@ -29,27 +29,39 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractDataMsSymbol} symbols.
*/
-public class DataSymbolApplier extends MsSymbolApplier {
+public class DataSymbolApplier extends MsSymbolApplier
+ implements DirectSymbolApplier, NestableSymbolApplier {
private AbstractDataMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public DataSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractDataMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractDataMsSymbol) abstractSymbol;
+ public DataSymbolApplier(DefaultPdbApplicator applicator, AbstractDataMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ Address symbolAddress = applicator.getAddress(symbol);
+ if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
+ return;
+ }
+ RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
+ if (!createData(symbol, symbolAddress, typeRecordNumber)) {
+ return;
+ }
+ applicator.createSymbol(symbolAddress, symbol.getName(), true);
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
if (applyToApplier instanceof FunctionSymbolApplier) {
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
DataType dataType = applicator.getCompletedDataType(symbol.getTypeRecordNumber());
@@ -57,37 +69,28 @@ public class DataSymbolApplier extends MsSymbolApplier {
return; // silently return.
}
Address address = applicator.getAddress(symbol);
- if (!createData(address, dataType)) {
+ if (!createData(symbol, address, dataType)) {
return;
}
functionSymbolApplier.setLocalVariable(address, symbol.getName(), dataType);
}
}
- @Override
- void apply() throws CancelledException, PdbException {
- Address symbolAddress = applicator.getAddress(symbol);
- if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
- return;
+ MsTypeApplier getTypeApplier(AbstractMsSymbol abstractSymbol) {
+ if (!(abstractSymbol instanceof AbstractDataMsSymbol symbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
- RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
- if (!createData(symbolAddress, typeRecordNumber)) {
- return;
- }
- applicator.createSymbol(symbolAddress, symbol.getName(), true);
- }
-
- MsTypeApplier getTypeApplier() {
return applicator.getTypeApplier(symbol.getTypeRecordNumber());
}
- boolean createData(Address address, RecordNumber typeRecordNumber)
+ boolean createData(AbstractDataMsSymbol symbol, Address address, RecordNumber typeRecordNumber)
throws CancelledException, PdbException {
- DataType dataType = applicator.getCompletedDataType(symbol.getTypeRecordNumber());
- return createData(address, dataType);
+ DataType dataType = applicator.getCompletedDataType(typeRecordNumber);
+ return createData(symbol, address, dataType);
}
- boolean createData(Address address, DataType dataType) {
+ boolean createData(AbstractDataMsSymbol symbol, Address address, DataType dataType) {
if (applicator.isInvalidAddress(address, symbol.getName())) {
return false;
}
@@ -266,4 +269,13 @@ public class DataSymbolApplier extends MsSymbolApplier {
return datatype1.isEquivalent(datatype2);
}
+ private AbstractDataMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractDataMsSymbol dataSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return dataSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java
index 9dd4d1932e..d42ffb9be0 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java
@@ -4,9 +4,9 @@
* 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.
@@ -141,6 +141,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
private PdbCategories categoryUtils;
private PdbPrimitiveTypeApplicator pdbPrimitiveTypeApplicator;
private TypeApplierFactory typeApplierParser;
+ // We may need to put one or more of the following maps into the "analysis state" for access by
+ // a second PDB analyzer to do the "deferred" processing of functions. Then a mandatory
+ // second PDB analyzer would, at a minimum, remove the maps from the analysis state.
private Map dataTypeIdByMsTypeNum;
private Map dataTypeImplByMsTypeNum;
private Map classTypeByMsTypeNum;
@@ -223,6 +226,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
if (program != null) {
+ // TODO: if I'm PDB Universal Analyzer #1, schedule PDD Universal Analyzer #2; for now,
+ // just calling doDeferred here.
doDeferredProgramProcessing();
// Mark PDB analysis as complete.
Options options = program.getOptions(Program.PROGRAM_INFO);
@@ -237,7 +242,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
//==============================================================================================
- private void doDeferredProgramProcessing() throws CancelledException {
+ private void doDeferredProgramProcessing() throws CancelledException, PdbException {
disassembleFunctions();
doDeferredFunctionProcessing();
}
@@ -288,12 +293,19 @@ public class DefaultPdbApplicator implements PdbApplicator {
/**
* Do work, such as create parameters or local variables and scopes
* @throws CancelledException upon user cancellation
+ * @throws PdbException upon not enough data left to parse
*/
- private void doDeferredFunctionProcessing() throws CancelledException {
- for (DeferrableFunctionSymbolApplier applier : deferredFunctionWorkAppliers) {
- cancelOnlyWrappingMonitor.checkCancelled();
- applier.doDeferredProcessing();
+ private void doDeferredFunctionProcessing() throws CancelledException, PdbException {
+ if (applicatorOptions.getProcessingControl() == PdbApplicatorControl.DATA_TYPES_ONLY) {
+ return;
}
+ doDeferredProcessGlobalSymbolsNoTypedefs();
+ doDeferredProcessModuleSymbols();
+//
+// for (DeferrableFunctionSymbolApplier applier : deferredFunctionWorkAppliers) {
+// cancelOnlyWrappingMonitor.checkCancelled();
+// applier.doDeferredProcessing();
+// }
}
//==============================================================================================
@@ -1319,11 +1331,17 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
//==============================================================================================
- void scheduleDeferredFunctionWork(DeferrableFunctionSymbolApplier applier) {
+// void scheduleDeferredFunctionWork(DeferrableFunctionSymbolApplier applier) {
+// // Not using normalized address is OK, as we should have already set the context and
+// // used the normalized address when creating the one-byte function
+// disassembleAddresses.add(applier.getAddress());
+// //deferredFunctionWorkAppliers.add(applier);
+// }
+//
+ void scheduleDisassembly(Address address) {
// Not using normalized address is OK, as we should have already set the context and
// used the normalized address when creating the one-byte function
- disassembleAddresses.add(applier.getAddress());
- //deferredFunctionWorkAppliers.add(applier);
+ disassembleAddresses.add(address);
}
//==============================================================================================
@@ -1536,6 +1554,61 @@ public class DefaultPdbApplicator implements PdbApplicator {
currentModuleNumber = moduleNumber;
}
+ private void doDeferredProcessModuleSymbols() throws CancelledException, PdbException {
+ PdbDebugInfo debugInfo = pdb.getDebugInfo();
+ if (debugInfo == null) {
+ return;
+ }
+
+ int totalCount = 0;
+ int num = debugInfo.getNumModules();
+ TaskMonitor monitor = getMonitor();
+ for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) {
+ monitor.checkCancelled();
+ SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber);
+ if (symbolGroup == null) {
+ continue; // should not happen
+ }
+ totalCount++;
+ //totalCount += symbolGroup.size();
+ }
+ monitor.setMessage("PDB: Deferred-applying module symbol components...");
+ //monitor.setMessage("PDB: Applying " + totalCount + " module symbol components...");
+ monitor.initialize(totalCount);
+
+ // Process symbols list for each module
+ for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) {
+ monitor.checkCancelled();
+ setCurrentModuleNumber(moduleNumber);
+ // Process module symbols list
+ SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber);
+ if (symbolGroup == null) {
+ continue; // should not happen
+ }
+ MsSymbolIterator iter = symbolGroup.getSymbolIterator();
+ doDeferredModuleSymbolGroup(moduleNumber, iter);
+ monitor.increment();
+ }
+ }
+
+ private void doDeferredModuleSymbolGroup(int moduleNumber, MsSymbolIterator iter)
+ throws CancelledException {
+ iter.initGet();
+ TaskMonitor monitor = getMonitor();
+ while (iter.hasNext()) {
+ monitor.checkCancelled();
+ AbstractMsSymbol symbol = iter.peek();
+ // During deferred processing, we are revisiting the module symbols so do not
+ // need to repeat the pdbApplicatorMetrics.witnessGlobalSymbolType(symbol) call
+ if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here
+ procSymDeferred(iter);
+ }
+ else {
+ iter.next();
+ }
+ }
+ }
+
private void processModuleSymbols() throws CancelledException, PdbException {
PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo == null) {
@@ -1596,7 +1669,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) {
monitor.checkCancelled();
- procSym(iter);
+ procSymNew(iter);
monitor.incrementProgress(1);
}
}
@@ -1635,7 +1708,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
break;
}
pdbApplicatorMetrics.witnessPublicSymbolType(iter.peek());
- procSym(iter);
+ procSymNew(iter);
monitor.incrementProgress(1);
}
@@ -1674,15 +1747,16 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
- SymbolGroup symbolGroup = getSymbolGroup();
- if (symbolGroup == null) {
- return;
- }
-
+// SymbolGroup symbolGroup = getSymbolGroup();
+// if (symbolGroup == null) {
+// return;
+// }
+//
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying global symbols...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
- MsSymbolIterator iter = symbolGroup.getSymbolIterator();
+// MsSymbolIterator iter = symbolGroup.getSymbolIterator();
+ MsSymbolIterator iter = debugInfo.getSymbolIterator();
List offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
monitor.initialize(offsets.size());
@@ -1695,7 +1769,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
AbstractMsSymbol symbol = iter.peek();
pdbApplicatorMetrics.witnessGlobalSymbolType(symbol);
if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here
- procSym(iter);
+// procSym(iter);
+ procSymNew(iter);
}
monitor.incrementProgress(1);
}
@@ -1723,6 +1798,33 @@ public class DefaultPdbApplicator implements PdbApplicator {
// }
}
+ private void doDeferredProcessGlobalSymbolsNoTypedefs()
+ throws CancelledException, PdbException {
+ PdbDebugInfo debugInfo = pdb.getDebugInfo();
+ if (debugInfo == null) {
+ return;
+ }
+ GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
+ MsSymbolIterator iter = debugInfo.getSymbolIterator();
+ List offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
+ TaskMonitor monitor = getMonitor();
+ monitor.initialize(offsets.size(), "PDB: Performing deferred global symbols processing...");
+ for (long offset : offsets) {
+ monitor.checkCancelled();
+ iter.initGetByOffset(offset);
+ if (!iter.hasNext()) {
+ break;
+ }
+ AbstractMsSymbol symbol = iter.peek();
+ // During deferred processing, we are revisiting the global symbols so do not
+ // need to repeat the pdbApplicatorMetrics.witnessGlobalSymbolType(symbol) call
+ if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here
+ procSymDeferred(iter);
+ }
+ monitor.incrementProgress(1);
+ }
+ }
+
/**
* Process global typdef symbols
* @throws CancelledException upon user cancellation
@@ -1755,7 +1857,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
AbstractMsSymbol symbol = iter.peek();
if (symbol instanceof AbstractUserDefinedTypeMsSymbol) { // Doing typedefs here
- procSym(iter);
+ procSymNew(iter);
}
monitor.incrementProgress(1);
}
@@ -1825,7 +1927,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
monitor.checkCancelled();
iter.initGetByOffset(offset);
AbstractMsSymbol symbol = iter.peek();
- procSym(iter);
+ procSymNew(iter);
monitor.incrementProgress(1);
}
}
@@ -1872,7 +1974,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
while (iter.hasNext()) {
monitor.checkCancelled();
pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek());
- procSym(iter);
+ procSymNew(iter);
monitor.incrementProgress(1);
}
return true;
@@ -1994,7 +2096,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
monitor.checkCancelled();
AbstractMsSymbol symbol = iter.peek();
if (symbol instanceof AbstractThunkMsSymbol) {
- procSym(iter);
+ procSymNew(iter);
}
else {
iter.next();
@@ -2013,11 +2115,32 @@ public class DefaultPdbApplicator implements PdbApplicator {
return symbolApplierParser.getSymbolApplier(iter);
}
+ MsSymbolApplier getSymbolApplier(AbstractMsSymbol symbol, MsSymbolIterator iter)
+ throws CancelledException {
+ return symbolApplierParser.getSymbolApplier(symbol, iter);
+ }
+
//==============================================================================================
- void procSym(MsSymbolIterator iter) throws CancelledException {
+// void procSym(MsSymbolIterator iter) throws CancelledException {
+// try {
+// MsSymbolApplier applier = getSymbolApplier(iter);
+// applier.apply();
+// }
+// catch (PdbException e) {
+// // skipping symbol
+// Msg.info(this, "Error applying symbol to program: " + e.toString());
+// }
+// }
+
+ void procSymNew(MsSymbolIterator iter) throws CancelledException {
try {
MsSymbolApplier applier = getSymbolApplier(iter);
- applier.apply();
+ if (applier instanceof DirectSymbolApplier directApplier) {
+ directApplier.apply(iter);
+ }
+ else {
+ iter.next();
+ }
}
catch (PdbException e) {
// skipping symbol
@@ -2025,6 +2148,23 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
}
+ void procSymDeferred(MsSymbolIterator iter) throws CancelledException {
+ try {
+ MsSymbolApplier applier = getSymbolApplier(iter);
+ if (applier instanceof DeferrableFunctionSymbolApplier deferrableApplier) {
+ deferrableApplier.deferredApply(iter);
+ }
+ else {
+ iter.next();
+ }
+ }
+ catch (PdbException e) {
+ // skipping symbol
+ Msg.info(this,
+ "Error during deferred processing of symbol to program: " + e.toString());
+ }
+ }
+
//==============================================================================================
//==============================================================================================
//==============================================================================================
@@ -2290,7 +2430,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
return newSymbol;
}
- private boolean addToPlateUnique(Address address, String comment) {
+ public boolean addToPlateUnique(Address address, String comment) {
if (StringUtils.isBlank(comment)) {
return false;
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DeferrableFunctionSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DeferrableFunctionSymbolApplier.java
index b73a172ae9..475773cb1d 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DeferrableFunctionSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DeferrableFunctionSymbolApplier.java
@@ -15,27 +15,36 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.program.model.address.Address;
+import ghidra.util.exception.CancelledException;
/**
* Interface class for MsSymbolApplier that has deferrable function work.
*/
-interface DeferrableFunctionSymbolApplier {
-
- /**
- * Returns entry address of code/function that needs disassembled; this is the original,
- * non-normalized address (e.g., odd if Thumb)
- * @return the address
- */
- Address getAddress();
+interface DeferrableFunctionSymbolApplier extends DirectSymbolApplier {
/**
* Deferred work for the MsSymbolApplier that can only be applied after all functions
* have been created and disassembled. Examples would be setting local variables and
* parameters
+ * @param iter the Iterator containing the symbol sequence being processed
+ * @throws PdbException if there was a problem processing the data
+ * @throws CancelledException upon user cancellation
*/
- default void doDeferredProcessing() {
- // do nothing
- }
+ public void deferredApply(MsSymbolIterator iter) throws PdbException, CancelledException;
+ /**
+ * Method to call to begin a block
+ * @param startAddress start address of block
+ * @param name name of the block
+ * @param length byte length of the block
+ */
+ public void beginBlock(Address startAddress, String name, long length);
+
+ /**
+ * Method to call to end a block
+ */
+ public void endBlock();
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefinedSingleAddressRangeSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefinedSingleAddressRangeSymbolApplier.java
index 41cd8637b6..cb4541750d 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefinedSingleAddressRangeSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefinedSingleAddressRangeSymbolApplier.java
@@ -24,38 +24,30 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractDefinedSingleAddressRangeMsSymbol} symbols.
*/
-public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier {
+public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier
+ implements NestableSymbolApplier {
private AbstractDefinedSingleAddressRangeMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
public DefinedSingleAddressRangeSymbolApplier(DefaultPdbApplicator applicator,
- MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractDefinedSingleAddressRangeMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractDefinedSingleAddressRangeMsSymbol) abstractSymbol;
+ AbstractDefinedSingleAddressRangeMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void apply() throws PdbException, CancelledException {
- pdbLogAndInfoMessage(this,
- "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
if (applyToApplier instanceof LocalOptimizedSymbolApplier) {
-// TODO: eventually apply.
-// LocalOptimizedSymbolApplier localSymbolApplier =
-// (LocalOptimizedSymbolApplier) applyToApplier;
+ // TODO: eventually apply.
+// LocalOptimizedSymbolApplier localSymbolApplier =
+// (LocalOptimizedSymbolApplier) applyToApplier;
symbol.getAddressRange();
symbol.getAddressGapList();
if (symbol instanceof EnregisteredSymbolDARMsSymbol) {
@@ -73,4 +65,14 @@ public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier {
}
}
+ private AbstractDefinedSingleAddressRangeMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractDefinedSingleAddressRangeMsSymbol rangeSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return rangeSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DirectSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DirectSymbolApplier.java
new file mode 100644
index 0000000000..1ae5cd0822
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DirectSymbolApplier.java
@@ -0,0 +1,37 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Interface class for MsSymbolApplier that has deferrable function work.
+ */
+interface DirectSymbolApplier {
+
+ /**
+ * Apply the next and any desired subsequent {@link AbstractMsSymbol AbstractMsSymbols} from
+ * the {@link SymbolGroup} to a program.
+ * @param iter the Iterator containing the symbol sequence being processed
+ * @throws PdbException if there was a problem processing the data.
+ * @throws CancelledException upon user cancellation
+ */
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException;
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/EndSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/EndSymbolApplier.java
index efd90d3f26..b232aed1a6 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/EndSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/EndSymbolApplier.java
@@ -17,60 +17,45 @@ package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
-import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.EndMsSymbol;
import ghidra.util.exception.AssertException;
+import ghidra.util.exception.CancelledException;
/**
* Applier for {@link EndMsSymbol} symbols.
*/
-public class EndSymbolApplier extends MsSymbolApplier {
+public class EndSymbolApplier extends MsSymbolApplier
+ implements BlockNestingSymbolApplier, NestableSymbolApplier {
+
+ private EndMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public EndSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof EndMsSymbol ||
- abstractSymbol instanceof ProcedureIdEndMsSymbol)) {
+ public EndSymbolApplier(DefaultPdbApplicator applicator, EndMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ applier.endBlock();
+ }
+ }
+
+ private EndMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof EndMsSymbol endSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
+ return endSymbol;
}
- @Override
- void apply() throws PdbException {
- pdbLogAndInfoMessage(this,
- String.format("Cannot apply %s directly to program (stream:0X%04X, offset:0X%08X)",
- this.getClass().getSimpleName(), iter.getStreamNumber(), iter.getCurrentOffset()));
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- if (!(applyToApplier instanceof FunctionSymbolApplier)) {
- return;
- }
-// FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
-// functionSymbolApplier.endBlock();
- }
-
- @Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- if (applierParam instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applierParam;
- functionSymbolApplier.endBlock();
- }
- else if (applierParam instanceof SeparatedCodeSymbolApplier) {
- SeparatedCodeSymbolApplier separatedCodeSymbolApplier =
- (SeparatedCodeSymbolApplier) applierParam;
- separatedCodeSymbolApplier.endBlock();
- }
- else if (applierParam instanceof ManagedProcedureSymbolApplier) {
- ManagedProcedureSymbolApplier procedureSymbolApplier =
- (ManagedProcedureSymbolApplier) applierParam;
- procedureSymbolApplier.endBlock();
- }
- }
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FrameAndProcedureInformationSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FrameAndProcedureInformationSymbolApplier.java
index c925e9e811..d97984b217 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FrameAndProcedureInformationSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FrameAndProcedureInformationSymbolApplier.java
@@ -25,36 +25,42 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link ExtraFrameAndProcedureInformationMsSymbol} symbols.
*/
-public class FrameAndProcedureInformationSymbolApplier extends MsSymbolApplier {
+public class FrameAndProcedureInformationSymbolApplier extends MsSymbolApplier
+ implements NestableSymbolApplier {
private ExtraFrameAndProcedureInformationMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
public FrameAndProcedureInformationSymbolApplier(DefaultPdbApplicator applicator,
- MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof ExtraFrameAndProcedureInformationMsSymbol)) {
+ ExtraFrameAndProcedureInformationMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ // TODO; depending on all children of AbstractBlockContextApplier, might need to change
+ // this to FunctionSymbolApplier and possibly Managed... (or remove Separated code
+ // from this parent)
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ applier.setSpecifiedFrameSize(symbol.getProcedureFrameTotalLength());
+ }
+ }
+
+ private ExtraFrameAndProcedureInformationMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof ExtraFrameAndProcedureInformationMsSymbol frameSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
- symbol = (ExtraFrameAndProcedureInformationMsSymbol) abstractSymbol;
+ return frameSymbol;
}
- @Override
- void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
- if (applyToApplier instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
- functionSymbolApplier.setSpecifiedFrameSize(symbol.getProcedureFrameTotalLength());
- }
- }
-
- @Override
- void apply() {
- // Quietly do nothing
- }
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
index a8d6911809..7f72e77a67 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
@@ -4,9 +4,9 @@
* 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.
@@ -15,8 +15,6 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
-import java.util.*;
-
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
import ghidra.app.cmd.function.CallDepthChangeInfo;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
@@ -36,278 +34,112 @@ import ghidra.util.task.TaskMonitor;
/**
* Applier for {@link AbstractProcedureStartMsSymbol} and {@link AbstractThunkMsSymbol} symbols.
*/
-public class FunctionSymbolApplier extends MsSymbolApplier
- implements DeferrableFunctionSymbolApplier {
+public class FunctionSymbolApplier extends AbstractBlockContextApplier
+ implements BlockNestingSymbolApplier {
- private static final String BLOCK_INDENT = " ";
+ // Do not trust any of these variables... this is work in progress (possibly getting
+ // torn up), but non-functioning code in other classes or this class still depend on these
+ private Address address_x;
+ private Function function_x = null;
+ private long specifiedFrameSize_x = 0;
+ private long currentFrameSize_x = 0;
- private AbstractProcedureMsSymbol procedureSymbol;
- private AbstractThunkMsSymbol thunkSymbol;
- private Address specifiedAddress;
- private Address address;
- private boolean isNonReturning;
- private Function function = null;
- private long specifiedFrameSize = 0;
- private long currentFrameSize = 0;
- private BlockCommentsManager comments;
-
- private int symbolBlockNestingLevel;
private Address currentBlockAddress;
// might not need this, but investigating whether it will help us. TODO remove?
private int baseParamOffset = 0;
-// private List stackVariableAppliers = new ArrayList<>();
-
- private List allAppliers = new ArrayList<>();
private RegisterChangeCalculator registerChangeCalculator;
+ private AbstractProcedureMsSymbol symbol;
+
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
- * @throws CancelledException upon user cancellation
+ * @param symbol the symbol for this applier
*/
- public FunctionSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter)
- throws CancelledException {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- symbolBlockNestingLevel = 0;
- comments = new BlockCommentsManager();
- currentBlockAddress = null;
-
- if (abstractSymbol instanceof AbstractProcedureMsSymbol) {
- procedureSymbol = (AbstractProcedureMsSymbol) abstractSymbol;
- specifiedAddress = applicator.getRawAddress(procedureSymbol);
- address = applicator.getAddress(procedureSymbol);
- isNonReturning =
- ((AbstractProcedureStartMsSymbol) procedureSymbol).getFlags().doesNotReturn();
- }
- else if (abstractSymbol instanceof AbstractProcedureStartIa64MsSymbol) {
- procedureSymbol = (AbstractProcedureStartIa64MsSymbol) abstractSymbol;
- specifiedAddress = applicator.getRawAddress(procedureSymbol);
- address = applicator.getAddress(procedureSymbol);
- isNonReturning =
- ((AbstractProcedureStartIa64MsSymbol) procedureSymbol).getFlags().doesNotReturn();
- }
- else if (abstractSymbol instanceof AbstractProcedureStartMipsMsSymbol) {
- procedureSymbol = (AbstractProcedureStartMipsMsSymbol) abstractSymbol;
- specifiedAddress = applicator.getRawAddress(procedureSymbol);
- address = applicator.getAddress(procedureSymbol);
- isNonReturning = false; // we do not have ProcedureFlags to check
- }
- else if (abstractSymbol instanceof AbstractThunkMsSymbol) {
- thunkSymbol = (AbstractThunkMsSymbol) abstractSymbol;
- specifiedAddress = applicator.getRawAddress(thunkSymbol);
- address = applicator.getAddress(thunkSymbol);
- // isNonReturning value is not used when thunk; is controlled by thunked function;
- }
- else {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- manageBlockNesting(this);
-
- while (notDone()) {
- applicator.checkCancelled();
- MsSymbolApplier applier = applicator.getSymbolApplier(iter);
- allAppliers.add(applier);
- applier.manageBlockNesting(this);
- }
+ public FunctionSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractProcedureMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
+ //==============================================================================================
@Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- if (applierParam instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applierParam;
- if (procedureSymbol != null) {
- long start = procedureSymbol.getDebugStartOffset();
- long end = procedureSymbol.getDebugEndOffset();
- Address blockAddress = address.add(start);
- long length = end - start;
- functionSymbolApplier.beginBlock(blockAddress, procedureSymbol.getName(), length);
- }
- else if (thunkSymbol != null) {
- functionSymbolApplier.beginBlock(address, thunkSymbol.getName(),
- thunkSymbol.getLength());
- }
- }
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+ processSymbol(iter);
}
- long getLength() {
- if (procedureSymbol != null) {
- return procedureSymbol.getProcedureLength();
- }
- else if (thunkSymbol != null) {
- return thunkSymbol.getLength();
- }
- throw new AssertException("Unexpected Symbol type");
- }
+ private void processSymbol(MsSymbolIterator iter)
+ throws CancelledException, PdbException {
- /**
- * Returns the {@link Function} for this applier.
- * @return the Function
- */
- Function getFunction() {
- return function;
- }
+ Address address = applicator.getAddress(symbol);
+ String name = symbol.getName();
- /**
- * Returns the current frame size.
- * @return the current frame size.
- */
- long getCurrentFrameSize() {
- return currentFrameSize;
- }
-
- /**
- * Returns the frame size as specified by the PDB
- * @return the frame size.
- */
- long getSpecifiedFrameSize() {
- return specifiedFrameSize;
- }
-
- /**
- * Set the specified frame size.
- * @param specifiedFrameSize the frame size.
- */
- void setSpecifiedFrameSize(long specifiedFrameSize) {
- this.specifiedFrameSize = specifiedFrameSize;
- currentFrameSize = specifiedFrameSize;
- }
-
- /**
- * Get the function name
- * @return the function name
- */
- String getName() {
- if (procedureSymbol != null) {
- return procedureSymbol.getName();
- }
- else if (thunkSymbol != null) {
- return thunkSymbol.getName();
- }
- return "";
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
-
- @Override
- void apply() throws PdbException, CancelledException {
- boolean result = applyTo(applicator.getCancelOnlyWrappingMonitor());
- if (result == false) {
- throw new PdbException(this.getClass().getSimpleName() + ": failure at " + address +
- " applying " + getName());
- }
- }
-
- boolean applyTo(TaskMonitor monitor) throws PdbException, CancelledException {
- if (applicator.isInvalidAddress(address, getName())) {
- return false;
+ // Regardless of ability to apply this symbol, we need to progress through symbols to the
+ // matching "end" symbol before we return
+ if (!processEndSymbol(symbol.getEndPointer(), iter)) {
+ applicator.appendLogMsg("PDB: Failed to process function at address " + address);
+ return;
}
- boolean functionSuccess = applyFunction(monitor);
- if (functionSuccess == false) {
- return false;
- }
- registerChangeCalculator = new RegisterChangeCalculator(procedureSymbol, function, monitor);
-
- baseParamOffset = VariableUtilities.getBaseStackParamOffset(function);
-
- for (MsSymbolApplier applier : allAppliers) {
- applier.applyTo(this);
+ if (applicator.isInvalidAddress(address, name)) {
+ applicator.appendLogMsg("PDB: Failed to process function at address: " + address);
+ return;
}
- // comments
- long addressDelta = address.subtract(specifiedAddress);
- comments.applyTo(applicator.getProgram(), addressDelta);
-
- // line numbers
- // TODO: not done yet
-// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
-// applyLineNumbers.applyTo(monitor, log);
-
- return true;
- }
-
- Integer getRegisterPrologChange(Register register) {
- return registerChangeCalculator.getRegChange(applicator, register);
- }
-
- int getBaseParamOffset() {
- return baseParamOffset;
- }
-
- /**
- * Sets a local variable (address, name, type)
- * @param varAddress Address of the variable.
- * @param varName varName of the variable.
- * @param dataType data type of the variable.
- */
- void setLocalVariable(Address varAddress, String varName, DataType dataType) {
- if (currentBlockAddress == null) {
- return; // silently return.
- }
- if (varName.isBlank()) {
- return; // silently return.
- }
-
- String plateAddition = "PDB: static local for function (" + address + "): " + getName();
- // TODO: 20220210... consider adding function name as namespace to varName
- applicator.createSymbol(varAddress, varName, true, plateAddition);
- }
-
- private boolean applyFunction(TaskMonitor monitor) throws CancelledException, PdbException {
- function = applicator.getExistingOrCreateOneByteFunction(address);
+ Function function = applicator.getExistingOrCreateOneByteFunction(address);
if (function == null) {
- return false;
+ return;
}
- applicator.scheduleDeferredFunctionWork(this);
- boolean succeededSetFunctionSignature = false;
- if (thunkSymbol == null) {
- if (function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) {
- function.setThunkedFunction(null);
- succeededSetFunctionSignature = setFunctionDefinition(monitor);
- function.setNoReturn(isNonReturning);
- }
- }
+ // Collecting all addresses from all functions to do one large bulk disassembly of the
+ // complete AddressSet of function addresses. We could consider removing this logic
+ // of collecting them all for bulk disassembly and do individual disassembly at the
+ // same deferred point in time.
+ applicator.scheduleDisassembly(address);
+
+ boolean succeededSetFunctionSignature = setFunctionDefinition(function, address);
+
// If signature was set, then override existing primary mangled symbol with
// the global symbol that provided this signature so that Demangler does not overwrite
// the richer data type we get with global symbols.
- applicator.createSymbol(address, getName(), succeededSetFunctionSignature);
-
- currentFrameSize = 0;
- return true;
+ applicator.createSymbol(address, name, succeededSetFunctionSignature);
}
/**
- * Sets function signature
- * @param monitor monitor
+ * returns true only if we set a function signature
* @return true if function signature was set
- * @throws CancelledException upon user cancellation
* @throws PdbException upon processing error
+ * @throws CancelledException upon user cancellation
*/
- private boolean setFunctionDefinition(TaskMonitor monitor)
+ private boolean setFunctionDefinition(Function function, Address address)
throws CancelledException, PdbException {
- if (procedureSymbol == null) {
- // TODO: is there anything we can do with thunkSymbol?
- // long x = thunkSymbol.getParentPointer();
+
+ RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
+ if (typeRecordNumber == RecordNumber.NO_TYPE) {
+ return false; // This will happen for thunks (we set to NO_TYPE specifically)
+ }
+ // Remaining are non-thunks
+
+ if (function.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
+ // return if IMPORTED or USER_DEFINED
return false;
}
- // Rest presumes procedureSymbol.
- RecordNumber typeRecordNumber = procedureSymbol.getTypeRecordNumber();
- MsTypeApplier applier = applicator.getTypeApplier(typeRecordNumber);
+
+ // Since the thunk detection algorithms are overly aggressive and make mistakes, we
+ // are specifically clearing the value to override these false positives
+ function.setThunkedFunction(null);
+
+ function.setNoReturn(isNonReturning());
+
AbstractMsType fType = applicator.getPdb().getTypeRecord(typeRecordNumber);
+ MsTypeApplier applier = applicator.getTypeApplier(fType);
if (!(applier instanceof AbstractFunctionTypeApplier)) {
- if (!((applier instanceof PrimitiveTypeApplier prim) && prim.isNoType(fType))) {
- applicator.appendLogMsg("Error: Failed to resolve datatype RecordNumber " +
- typeRecordNumber + " at " + address);
- }
+ applicator.appendLogMsg("Error: Failed to resolve datatype RecordNumber " +
+ typeRecordNumber + " at " + address_x);
return false;
}
@@ -330,6 +162,7 @@ public class FunctionSymbolApplier extends MsSymbolApplier
}
ApplyFunctionSignatureCmd sigCmd =
new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED);
+ TaskMonitor monitor = applicator.getCancelOnlyWrappingMonitor();
if (!sigCmd.applyTo(applicator.getProgram(), monitor)) {
applicator.appendLogMsg(
"PDB Warning: Failed to apply signature to function at address " + address +
@@ -339,58 +172,92 @@ public class FunctionSymbolApplier extends MsSymbolApplier
return true;
}
- private boolean notDone() {
- return (symbolBlockNestingLevel > 0) && iter.hasNext();
+ //==============================================================================================
+ @Override
+ public void deferredApply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+
+ String name = symbol.getName();
+ Address address = applicator.getAddress(symbol);
+
+ long start = getStartOffset();
+ long end = getEndOffset();
+ Address blockAddress = address.add(start);
+ long length = end - start;
+
+ deferredProcessing(iter, name, address, blockAddress, length);
}
- int endBlock() {
- if (--symbolBlockNestingLevel < 0) {
- applicator.appendLogMsg(
- "Block Nesting went negative for " + getName() + " at " + address);
- }
- if (symbolBlockNestingLevel == 0) {
- //currentFunctionSymbolApplier = null;
- }
- return symbolBlockNestingLevel;
+ /**
+ * Returns the {@link Function} for this applier.
+ * @return the Function
+ */
+ Function getFunction() {
+ return function_x;
}
- void beginBlock(Address startAddress, String name, long length) {
-
- int nestingLevel = beginBlock(startAddress);
- if (!applicator.getPdbApplicatorOptions().applyCodeScopeBlockComments()) {
- return;
- }
- if (applicator.isInvalidAddress(startAddress, name)) {
- return;
- }
-
- String indent = getIndent(nestingLevel);
-
- String baseComment = "level " + nestingLevel + ", length " + length;
-
- String preComment = indent + "PDB: Block Beg, " + baseComment;
- if (!name.isEmpty()) {
- preComment += " (" + name + ")";
- }
- comments.addPreComment(startAddress, preComment);
-
- String postComment = indent + "PDB: Block End, " + baseComment;
- Address endAddress = startAddress.add(((length <= 0) ? 0 : length - 1));
- comments.addPostComment(endAddress, postComment);
+ /**
+ * Returns the current frame size.
+ * @return the current frame size.
+ */
+ long getCurrentFrameSize() {
+ return currentFrameSize_x;
}
- private int beginBlock(Address startAddress) {
- currentBlockAddress = startAddress;
- ++symbolBlockNestingLevel;
- return symbolBlockNestingLevel;
+ /**
+ * Returns the frame size as specified by the PDB
+ * @return the frame size.
+ */
+ long getSpecifiedFrameSize() {
+ return specifiedFrameSize_x;
}
- private String getIndent(int indentLevel) {
- String indent = "";
- for (int i = 1; i < indentLevel; i++) {
- indent += BLOCK_INDENT;
+ /**
+ * Set the specified frame size.
+ * @param specifiedFrameSize the frame size.
+ */
+ @Override
+ void setSpecifiedFrameSize(long specifiedFrameSize) {
+ this.specifiedFrameSize_x = specifiedFrameSize;
+ currentFrameSize_x = specifiedFrameSize;
+ }
+
+ /**
+ * Get the function name
+ * @return the function name
+ */
+ String getName() {
+ return symbol.getName();
+ }
+
+ //==============================================================================================
+ //==============================================================================================
+ Integer getRegisterPrologChange(Register register) {
+ return registerChangeCalculator.getRegChange(applicator, register);
+ }
+
+ int getBaseParamOffset() {
+ return baseParamOffset;
+ }
+
+ /**
+ * Sets a local variable (address, name, type)
+ * @param varAddress Address of the variable.
+ * @param varName varName of the variable.
+ * @param dataType data type of the variable.
+ */
+ void setLocalVariable(Address varAddress, String varName, DataType dataType) {
+ if (currentBlockAddress == null) {
+ return; // silently return.
}
- return indent;
+ if (varName.isBlank()) {
+ return; // silently return.
+ }
+
+ String plateAddition = "PDB: static local for function (" + address_x + "): " + getName();
+ // TODO: 20220210... consider adding function name as namespace to varName
+ applicator.createSymbol(varAddress, varName, true, plateAddition);
}
// Method copied from ApplyStackVariables (ghidra.app.util.bin.format.pdb package)
@@ -403,26 +270,28 @@ public class FunctionSymbolApplier extends MsSymbolApplier
*/
private int getFrameBaseOffset(TaskMonitor monitor) throws CancelledException {
- int retAddrSize = function.getProgram().getDefaultPointerSize();
+ int retAddrSize = function_x.getProgram().getDefaultPointerSize();
if (retAddrSize != 8) {
// don't do this for 32 bit.
return -retAddrSize; // 32 bit has a -4 byte offset
}
- Register frameReg = function.getProgram().getCompilerSpec().getStackPointer();
- Address entryAddr = function.getEntryPoint();
+ Register frameReg = function_x.getProgram().getCompilerSpec().getStackPointer();
+ Address entryAddr = function_x.getEntryPoint();
AddressSet scopeSet = new AddressSet();
scopeSet.addRange(entryAddr, entryAddr.add(64));
CallDepthChangeInfo valueChange =
- new CallDepthChangeInfo(function, scopeSet, frameReg, monitor);
+ new CallDepthChangeInfo(function_x, scopeSet, frameReg, monitor);
InstructionIterator instructions =
- function.getProgram().getListing().getInstructions(scopeSet, true);
+ function_x.getProgram().getListing().getInstructions(scopeSet, true);
int max = 0;
while (instructions.hasNext()) {
monitor.checkCancelled();
Instruction next = instructions.next();
int newValue = valueChange.getDepth(next.getMinAddress());
+ // 20240131 review had comment about the these special values. TODO: When this
+ // code gets reworked, if these numbers stay, then document why "these" values, etc.
if (newValue < -(20 * 1024) || newValue > (20 * 1024)) {
continue;
}
@@ -433,55 +302,44 @@ public class FunctionSymbolApplier extends MsSymbolApplier
return max;
}
- private static class RegisterChangeCalculator {
-
- private Map registerChangeByRegisterName = new HashMap<>();
- private CallDepthChangeInfo callDepthChangeInfo;
- private Address debugStart;
-
- private RegisterChangeCalculator(AbstractProcedureMsSymbol procedureSymbol,
- Function function, TaskMonitor monitor) throws CancelledException {
- callDepthChangeInfo = createCallDepthChangInfo(procedureSymbol, function, monitor);
- }
-
- private CallDepthChangeInfo createCallDepthChangInfo(
- AbstractProcedureMsSymbol procedureSymbol, Function function, TaskMonitor monitor)
- throws CancelledException {
- if (procedureSymbol == null) {
- return null;
- }
- Register frameReg = function.getProgram().getCompilerSpec().getStackPointer();
- Address entryAddr = function.getEntryPoint();
- debugStart = entryAddr.add(procedureSymbol.getDebugStartOffset());
- AddressSet scopeSet = new AddressSet();
- scopeSet.addRange(entryAddr, debugStart);
- return new CallDepthChangeInfo(function, scopeSet, frameReg, monitor);
- }
-
- Integer getRegChange(DefaultPdbApplicator applicator, Register register) {
- if (callDepthChangeInfo == null || register == null) {
- return null;
- }
- Integer change = registerChangeByRegisterName.get(register);
- if (change != null) {
- return change;
- }
- change = callDepthChangeInfo.getRegDepth(debugStart, register);
- registerChangeByRegisterName.put(register, change);
- return change;
- }
+ //==============================================================================================
+ @Override
+ long getStartOffset() {
+ return symbol.getDebugStartOffset();
}
@Override
- public void doDeferredProcessing() {
- // TODO:
- // Try to processes parameters, locals, scopes if applicable.
+ long getEndOffset() {
+ return symbol.getDebugEndOffset();
}
- @Override
- public Address getAddress() {
- return address;
+ private boolean isNonReturning() {
+ if (symbol instanceof AbstractProcedureStartMsSymbol procMs) {
+ return procMs.getFlags().doesNotReturn();
+ }
+ else if (symbol instanceof AbstractProcedureStartIa64MsSymbol procIa64) {
+ return procIa64.getFlags().doesNotReturn();
+ }
+ else if (symbol instanceof AbstractProcedureStartMipsMsSymbol procMips) {
+ return false; // we do not have ProcedureFlags to check
+ }
+ else if (symbol instanceof AbstractThunkMsSymbol procThunk) {
+ // Value is not used when thunk; is controlled by thunked function;
+ // Thus, the return value is a fake value
+ return false;
+ }
+ throw new AssertException(
+ "PDB: getNonReturning: Invalid symbol type: " + symbol.getClass().getSimpleName());
+ }
+
+ private AbstractProcedureMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractProcedureMsSymbol procSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return procSymbol;
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LabelSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LabelSymbolApplier.java
index 479b03e3f7..4d9d3933c5 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LabelSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LabelSymbolApplier.java
@@ -32,28 +32,25 @@ import ghidra.util.task.TaskMonitor;
/**
* Applier for {@link AbstractLabelMsSymbol} symbols.
*/
-public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFunctionSymbolApplier {
+public class LabelSymbolApplier extends MsSymbolApplier
+ implements DirectSymbolApplier, NestableSymbolApplier {
private AbstractLabelMsSymbol symbol;
- private Function function = null;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public LabelSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractLabelMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractLabelMsSymbol) abstractSymbol;
+ public LabelSymbolApplier(DefaultPdbApplicator applicator, AbstractLabelMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void apply() throws PdbException, CancelledException {
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
// A naked label seems to imply an assembly procedure, unlike that applyTo(MsSymbolApplier),
// which is used for applying to something else (basically a block sequence of symbols,
// as is seen with GlobalProcedure symbols), in which case it is typically an instruction
@@ -85,7 +82,10 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
}
@Override
- void applyTo(MsSymbolApplier applyToApplier) {
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
String label = getLabel();
if (label == null) {
return;
@@ -159,11 +159,11 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
private boolean applyFunction(Address address, String name, TaskMonitor monitor) {
applicator.createSymbol(address, name, true);
- function = applicator.getExistingOrCreateOneByteFunction(address);
+ Function function = applicator.getExistingOrCreateOneByteFunction(address);
if (function == null) {
return false;
}
- applicator.scheduleDeferredFunctionWork(this);
+ applicator.scheduleDisassembly(address);
if (!function.isThunk() &&
function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) {
@@ -198,8 +198,13 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
return label;
}
- @Override
- public Address getAddress() {
- return applicator.getAddress(symbol);
+ private AbstractLabelMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractLabelMsSymbol labelSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return labelSymbol;
}
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LocalOptimizedSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LocalOptimizedSymbolApplier.java
index 958e100981..d0a98a1710 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LocalOptimizedSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/LocalOptimizedSymbolApplier.java
@@ -24,55 +24,61 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractLocalSymbolInOptimizedCodeMsSymbol} symbols.
*/
-public class LocalOptimizedSymbolApplier extends MsSymbolApplier {
+public class LocalOptimizedSymbolApplier extends MsSymbolApplier
+ implements NestingSymbolApplier, NestableSymbolApplier {
private AbstractLocalSymbolInOptimizedCodeMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public LocalOptimizedSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractLocalSymbolInOptimizedCodeMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractLocalSymbolInOptimizedCodeMsSymbol) abstractSymbol;
+ public LocalOptimizedSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractLocalSymbolInOptimizedCodeMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void apply() throws PdbException, CancelledException {
- pdbLogAndInfoMessage(this,
- "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
if (!applicator.getPdbApplicatorOptions().applyFunctionVariables()) {
return;
}
if (applyToApplier instanceof FunctionSymbolApplier) {
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
- doWork(functionSymbolApplier);
+ doWork(functionSymbolApplier, iter);
}
}
- private void doWork(FunctionSymbolApplier functionSymbolApplier)
+ private void doWork(FunctionSymbolApplier functionSymbolApplier, MsSymbolIterator iter)
throws CancelledException, PdbException {
+ getValidatedSymbol(iter, true);
// TODO: Not doing anything with the information yet.
symbol.getLocalVariableFlags();
symbol.getName();
symbol.getTypeRecordNumber();
while (iter.hasNext() &&
- (iter.peek() instanceof AbstractDefinedSingleAddressRangeMsSymbol)) {
+ (iter.peek() instanceof AbstractDefinedSingleAddressRangeMsSymbol subSymbol)) {
applicator.checkCancelled();
- DefinedSingleAddressRangeSymbolApplier rangeApplier =
- new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
- rangeApplier.applyTo(this);
+ MsSymbolApplier applier = applicator.getSymbolApplier(subSymbol, iter);
+ if (!(applier instanceof DefinedSingleAddressRangeSymbolApplier rangeApplier)) {
+ throw new PdbException("Expected Range Applier not encountered");
+ }
+ rangeApplier.applyTo(this, iter);
}
}
+ private AbstractLocalSymbolInOptimizedCodeMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractLocalSymbolInOptimizedCodeMsSymbol localSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return localSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java
index 036dd54d5d..31b756a585 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedProcedureSymbolApplier.java
@@ -15,8 +15,6 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
-import java.util.*;
-
import ghidra.app.cmd.function.CallDepthChangeInfo;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
@@ -48,20 +46,8 @@ import ghidra.util.task.TaskMonitor;
/**
* Applier for {@link AbstractManagedProcedureMsSymbol} symbols.
*/
-public class ManagedProcedureSymbolApplier extends MsSymbolApplier
- implements DeferrableFunctionSymbolApplier {
-
- private static final String BLOCK_INDENT = " ";
-
- private AbstractManagedProcedureMsSymbol procedureSymbol;
-
- private Address specifiedAddress;
- private Address address;
- private boolean isNonReturning;
- private Function function = null;
- private long specifiedFrameSize = 0;
- private long currentFrameSize = 0;
- private BlockCommentsManager comments;
+public class ManagedProcedureSymbolApplier extends AbstractBlockContextApplier
+ implements BlockNestingSymbolApplier {
private int symbolBlockNestingLevel;
private Address currentBlockAddress;
@@ -69,160 +55,200 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
// might not need this, but investigating whether it will help us. TODO remove?
private int baseParamOffset = 0;
-// private List stackVariableAppliers = new ArrayList<>();
+ private AbstractManagedProcedureMsSymbol symbol;
- private List allAppliers = new ArrayList<>();
- private RegisterChangeCalculator registerChangeCalculator;
+ // TODO: We are having difficulty figuring out how to process these... actually not getting
+ // correct addresses in some situations. This flag allows us to bypass this symbol and
+ // its nested symbols.
+ private boolean developerStillHavingProblemProcessingThese = true;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
- * @throws CancelledException upon user cancellation
+ * @param symbol the symbol for this applier
*/
- public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter)
- throws CancelledException {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- symbolBlockNestingLevel = 0;
- comments = new BlockCommentsManager();
- currentBlockAddress = null;
-
- if (!(abstractSymbol instanceof AbstractManagedProcedureMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- // TODO: Remove the witness call once we effectively process this class of symbols
- // See that the applyTo() method is much unimplemented.
- applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(abstractSymbol);
- procedureSymbol = (AbstractManagedProcedureMsSymbol) abstractSymbol;
- specifiedAddress = applicator.getRawAddress(procedureSymbol);
- address = applicator.getAddress(procedureSymbol);
- isNonReturning = procedureSymbol.getFlags().doesNotReturn();
-
- manageBlockNesting(this);
-
- while (notDone()) {
- applicator.checkCancelled();
- MsSymbolApplier applier = applicator.getSymbolApplier(iter);
- allAppliers.add(applier);
- applier.manageBlockNesting(this);
- }
+ public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractManagedProcedureMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- ManagedProcedureSymbolApplier procedureSymbolApplier =
- (ManagedProcedureSymbolApplier) applierParam;
- long start = procedureSymbol.getDebugStartOffset();
- long end = procedureSymbol.getDebugEndOffset();
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ processSymbol(iter);
+ }
+
+ // TODO. Investigate more. This is not working for at least one CLI dll in that we are
+ // not getting correct addresses. There is no omap and the one section is unnamed.
+ private void processSymbol(MsSymbolIterator iter)
+ throws CancelledException, PdbException {
+
+ Address address = applicator.getAddress(symbol);
+ String name = symbol.getName();
+
+ // Regardless of ability to apply this symbol, we need to progress through symbols to the
+ // matching "end" symbol before we return
+ if (!processEndSymbol(symbol.getEndPointer(), iter)) {
+ applicator.appendLogMsg("PDB: Failed to process function at address " + address);
+ return;
+ }
+
+ // Eventually will remove this when we know how to process
+ if (developerStillHavingProblemProcessingThese) {
+ applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol);
+ return;
+ }
+
+ if (applicator.isInvalidAddress(address, name)) {
+ applicator.appendLogMsg("PDB: Failed to process function at address: " + address);
+ return;
+ }
+
+ Function function = applicator.getExistingOrCreateOneByteFunction(address);
+ if (function == null) {
+ return;
+ }
+
+ // Collecting all addresses from all functions to do one large bulk disassembly of the
+ // complete AddressSet of function addresses. We could consider removing this logic
+ // of collecting them all for bulk diassembly and do individual disassembly at the
+ // same deferred point in time.
+ applicator.scheduleDisassembly(address);
+
+ boolean succeededSetFunctionSignature = setFunctionDefinition(function, address, symbol);
+
+ // If signature was set, then override existing primary mangled symbol with
+ // the global symbol that provided this signature so that Demangler does not overwrite
+ // the richer data type we get with global symbols.
+ applicator.createSymbol(address, name, succeededSetFunctionSignature);
+ }
+
+ @Override
+ public void deferredApply(MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+
+ // Eventually will remove this when we know how to process
+ if (developerStillHavingProblemProcessingThese) {
+ processEndSymbol(symbol.getEndPointer(), iter);
+ return;
+ }
+
+ String name = symbol.getName();
+ Address address = applicator.getAddress(symbol);
+
+ long start = getStartOffset();
+ long end = getEndOffset();
Address blockAddress = address.add(start);
long length = end - start;
- procedureSymbolApplier.beginBlock(blockAddress, procedureSymbol.getName(), length);
+
+ // Not sure if following procedure from parent class can be used or if should be
+ // specialized below
+ deferredProcessing(iter, name, address, blockAddress, length);
+
}
- /**
- * Returns the {@link Function} for this applier.
- * @return the Function
- */
- Function getFunction() {
- return function;
- }
-
- /**
- * Returns the current frame size.
- * @return the current frame size.
- */
- long getCurrentFrameSize() {
- return currentFrameSize;
- }
-
- /**
- * Returns the frame size as specified by the PDB
- * @return the frame size.
- */
- long getSpecifiedFrameSize() {
- return specifiedFrameSize;
- }
-
- /**
- * Set the specified frame size.
- * @param specifiedFrameSize the frame size.
- */
- void setSpecifiedFrameSize(long specifiedFrameSize) {
- this.specifiedFrameSize = specifiedFrameSize;
- currentFrameSize = specifiedFrameSize;
- }
-
- /**
- * Get the function name
- * @return the function name
- */
- String getName() {
- return procedureSymbol.getName();
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
-
- @Override
- void apply() throws PdbException, CancelledException {
- // TODO. Investigate more. This is not working for at least one CLI dll in that we are
- // not getting correct addresses. There is no omap and the one section is unnamed.
-// boolean result = applyTo(applicator.getCancelOnlyWrappingMonitor());
-// if (result == false) {
-// throw new PdbException(this.getClass().getSimpleName() + ": failure at " + address +
-// " applying " + getName());
+// private void deferredProcessing(MsSymbolIterator iter)
+// throws CancelledException, PdbException {
+//
+// long currentFrameSize = 0;
+//
+//// symbolBlockNestingLevel = 0;
+//// BlockCommentsManager comments = new BlockCommentsManager();
+//// currentBlockAddress = null;
+//
+// // TODO: Remove the witness call once we effectively process this class of symbols
+// // See that the applyTo() method is much unimplemented.
+// applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol);
+//
+// Address specifiedAddress = applicator.getRawAddress(symbol);
+// Address address = applicator.getAddress(symbol);
+// boolean isNonReturning = symbol.getFlags().doesNotReturn();
+//
+// initContext();
+// applyTo(this, context, iter);
+//
+//// TaskMonitor monitor = applicator.getCancelOnlyWrappingMonitor();
+//// RegisterChangeCalculator registerChangeCalculator =
+//// new RegisterChangeCalculator(symbol, function, monitor);
+////
+//// // TODO: need to decide how/where these get passed around... either we pass the function
+//// // around or pass things in the blockNestingContext or other
+//// int baseParamOffset = VariableUtilities.getBaseStackParamOffset(function_x);
+//// long currentFrameSize = 0;
+//
+// while (notDone(context, iter)) {
+// applicator.checkCancelled();
+// AbstractMsSymbol subSymbol = iter.peek();
+//
+// // TODO: msSymbol, subSymbol, comments, currentFrameSize, baseParmOffset
+//
+// MsSymbolApplier applier = applicator.getSymbolApplier(subSymbol, iter);
+//// if (applier instanceof BlockNestingSymbolApplier nestingApplier) {
+//// //nestingApplier.manageBlockNesting(iter, blockNestingContext);
+//// nestingApplier.applyTo(this, context, iter);
+//// }
+// if (applier instanceof NestableSymbolApplier nestingApplier) {
+// nestingApplier.applyTo(this, iter);
+// }
+// else {
+// applicator.getPdbApplicatorMetrics().witnessNonNestableSymbolType(subSymbol);
+// iter.next();
+// }
// }
- }
-
- boolean applyTo(TaskMonitor monitor) throws PdbException, CancelledException {
- if (applicator.isInvalidAddress(address, getName())) {
- return false;
- }
-
- // TODO: We do not know, yet, how/where to apply this. Need to wait for other .NET
- // work to get done for loading. Have commented-out code below, but have added some
- // functionality (laying down symbol). This file was somewhat copied from
- // FunctionSymbolApplier.
- // TODO: Also see the TODO in the constructor regarding the call to witness.
- for (MsSymbolApplier applier : allAppliers) {
- applier.applyTo(this);
- }
-
- boolean functionSuccess = applyFunction(monitor);
- if (functionSuccess == false) {
- return false;
- }
-// registerChangeCalculator = new RegisterChangeCalculator(procedureSymbol, function, monitor);
//
-// baseParamOffset = VariableUtilities.getBaseStackParamOffset(function);
+// // comments
+// //TODO: deal with specifiedAddress vs. address... do we still want to do any of this
+//// long addressDelta = address_x.subtract(specifiedAddress_x);
+//// blockNestingContext.getComments().applyTo(applicator.getProgram(), addressDelta);
+// context.getComments().applyTo(applicator.getProgram(), 0);
//
+//// // line numbers
+//// // TODO: not done yet
+////// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
+////// applyLineNumbers.applyTo(monitor, log);
+//
+// }
+
+// boolean applyTo(TaskMonitor monitor) throws PdbException, CancelledException {
+// if (applicator.isInvalidAddress(address, getName())) {
+// return false;
+// }
+//
+// // TODO: We do not know, yet, how/where to apply this. Need to wait for other .NET
+// // work to get done for loading. Have commented-out code below, but have added some
+// // functionality (laying down symbol). This file was somewhat copied from
+// // FunctionSymbolApplier.
+// // TODO: Also see the TODO in the constructor regarding the call to witness.
// for (MsSymbolApplier applier : allAppliers) {
// applier.applyTo(this);
// }
//
-// // comments
-// long addressDelta = address.subtract(specifiedAddress);
-// comments.applyTo(applicator.getProgram(), addressDelta);
-
- // line numbers
- // TODO: not done yet
-// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
-// applyLineNumbers.applyTo(monitor, log);
-
- return true;
- }
-
- Integer getRegisterPrologChange(Register register) {
- return registerChangeCalculator.getRegChange(applicator, register);
- }
-
- int getBaseParamOffset() {
- return baseParamOffset;
- }
+// boolean functionSuccess = applyFunction(procedureSymbol);
+// if (functionSuccess == false) {
+// return false;
+// }
+//// registerChangeCalculator = new RegisterChangeCalculator(procedureSymbol, function, monitor);
+////
+//// baseParamOffset = VariableUtilities.getBaseStackParamOffset(function);
+////
+//// for (MsSymbolApplier applier : allAppliers) {
+//// applier.applyTo(this);
+//// }
+////
+//// // comments
+//// long addressDelta = address.subtract(specifiedAddress);
+//// comments.applyTo(applicator.getProgram(), addressDelta);
+//
+// // line numbers
+// // TODO: not done yet
+//// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
+//// applyLineNumbers.applyTo(monitor, log);
+//
+// return true;
+// }
/**
* Sets a local variable (address, name, type)
@@ -235,38 +261,59 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return; // silently return.
}
// Currently just placing a comment.
- String comment = getIndent(symbolBlockNestingLevel + 1) + "static local (stored at " +
- address + ") " + dataType.getName() + " " + name;
- comments.addPreComment(currentBlockAddress, comment);
+ String comment =
+ context.getIndent(symbolBlockNestingLevel + 1) + "static local (stored at " +
+ address + ") " + dataType.getName() + " " + name;
+ context.getComments().addPreComment(currentBlockAddress, comment);
}
- private boolean applyFunction(TaskMonitor monitor) {
+// private boolean applyFunction(AbstractManagedProcedureMsSymbol procedureSymbol) {
+//
+// Address address = applicator.getAddress(procedureSymbol);
+// String name = procedureSymbol.getName();
+//
+// applicator.createSymbol(address, name, true);
+//
+// Function function = applicator.getExistingOrCreateOneByteFunction(address);
+// if (function == null) {
+// return false;
+// }
+//// applicator.scheduleDeferredFunctionWork(this);
+// applicator.scheduleDisassembly(address);
+//
+// boolean isNonReturning = procedureSymbol.getFlags().doesNotReturn();
+//
+// if (!function.isThunk() &&
+// function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) {
+// setFunctionDefinition(applicator.getCancelOnlyWrappingMonitor());
+// function.setNoReturn(isNonReturning);
+// }
+// //currentFrameSize = 0;
+// return true;
+// }
+//
+ /**
+ * returns true only if we set a function signature
+ * @return true if function signature was set
+ * @throws PdbException upon processing error
+ * @throws CancelledException upon user cancellation
+ */
+ private boolean setFunctionDefinition(Function function, Address address,
+ AbstractManagedProcedureMsSymbol symbol) throws CancelledException, PdbException {
- applicator.createSymbol(address, getName(), true);
-
- function = applicator.getExistingOrCreateOneByteFunction(address);
- if (function == null) {
+ if (function.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
+ // return if IMPORTED or USER_DEFINED
return false;
}
- applicator.scheduleDeferredFunctionWork(this);
- if (!function.isThunk() &&
- function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) {
- setFunctionDefinition(monitor);
- function.setNoReturn(isNonReturning);
- }
- currentFrameSize = 0;
- return true;
- }
+ // Since the thunk detection algorithms are overly aggressive and make mistakes, we
+ // are specifically clearing the value to override these false positives
+ function.setThunkedFunction(null);
+
+ function.setNoReturn(isNonReturning());
- private boolean setFunctionDefinition(TaskMonitor monitor) {
- if (procedureSymbol == null) {
- // TODO: is there anything we can do with thunkSymbol?
- // long x = thunkSymbol.getParentPointer();
- return true;
- }
// Rest presumes procedureSymbol.
- long token = procedureSymbol.getToken();
+ long token = symbol.getToken();
// TODO: once GP-328 is merged, use static methods to get table and row.
// CliIndexUtils.getTableIdUnencoded(token) and .getRowIdUnencoded(token).
int table = (int) (token >> 24) & 0xff;
@@ -338,60 +385,6 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return true;
}
- private boolean notDone() {
- return (symbolBlockNestingLevel > 0) && iter.hasNext();
- }
-
- int endBlock() {
- if (--symbolBlockNestingLevel < 0) {
- applicator.appendLogMsg(
- "Block Nesting went negative for " + getName() + " at " + address);
- }
- if (symbolBlockNestingLevel == 0) {
- //currentFunctionSymbolApplier = null;
- }
- return symbolBlockNestingLevel;
- }
-
- void beginBlock(Address startAddress, String name, long length) {
-
- int nestingLevel = beginBlock(startAddress);
- if (!applicator.getPdbApplicatorOptions().applyCodeScopeBlockComments()) {
- return;
- }
- if (applicator.isInvalidAddress(startAddress, name)) {
- return;
- }
-
- String indent = getIndent(nestingLevel);
-
- String baseComment = "level " + nestingLevel + ", length " + length;
-
- String preComment = indent + "PDB: Block Beg, " + baseComment;
- if (!name.isEmpty()) {
- preComment += " (" + name + ")";
- }
- comments.addPreComment(startAddress, preComment);
-
- String postComment = indent + "PDB: Block End, " + baseComment;
- Address endAddress = startAddress.add(((length <= 0) ? 0 : length - 1));
- comments.addPostComment(endAddress, postComment);
- }
-
- private int beginBlock(Address startAddress) {
- currentBlockAddress = startAddress;
- ++symbolBlockNestingLevel;
- return symbolBlockNestingLevel;
- }
-
- private String getIndent(int indentLevel) {
- String indent = "";
- for (int i = 1; i < indentLevel; i++) {
- indent += BLOCK_INDENT;
- }
- return indent;
- }
-
// Method copied from ApplyStackVariables (ghidra.app.util.bin.format.pdb package)
// on 20191119. TODO: Do we need something like this?
/**
@@ -400,7 +393,8 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
* @return stack offset that stack variables will be relative to.
* @throws CancelledException upon user cancellation.
*/
- private int getFrameBaseOffset(TaskMonitor monitor) throws CancelledException {
+ private int getFrameBaseOffset(Function function, TaskMonitor monitor)
+ throws CancelledException {
int retAddrSize = function.getProgram().getDefaultPointerSize();
@@ -432,54 +426,28 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return max;
}
- private static class RegisterChangeCalculator {
-
- private Map registerChangeByRegisterName = new HashMap<>();
- private CallDepthChangeInfo callDepthChangeInfo;
- private Address debugStart;
-
- private RegisterChangeCalculator(AbstractManagedProcedureMsSymbol procedureSymbol,
- Function function, TaskMonitor monitor) throws CancelledException {
- callDepthChangeInfo = createCallDepthChangInfo(procedureSymbol, function, monitor);
- }
-
- private CallDepthChangeInfo createCallDepthChangInfo(
- AbstractManagedProcedureMsSymbol procedureSymbol, Function function,
- TaskMonitor monitor) throws CancelledException {
- if (procedureSymbol == null) {
- return null;
- }
- Register frameReg = function.getProgram().getCompilerSpec().getStackPointer();
- Address entryAddr = function.getEntryPoint();
- debugStart = entryAddr.add(procedureSymbol.getDebugStartOffset());
- AddressSet scopeSet = new AddressSet();
- scopeSet.addRange(entryAddr, debugStart);
- return new CallDepthChangeInfo(function, scopeSet, frameReg, monitor);
- }
-
- Integer getRegChange(DefaultPdbApplicator applicator, Register register) {
- if (callDepthChangeInfo == null || register == null) {
- return null;
- }
- Integer change = registerChangeByRegisterName.get(register);
- if (change != null) {
- return change;
- }
- change = callDepthChangeInfo.getRegDepth(debugStart, register);
- registerChangeByRegisterName.put(register, change);
- return change;
- }
-
+ @Override
+ long getStartOffset() {
+ return symbol.getDebugStartOffset();
}
@Override
- public void doDeferredProcessing() {
- // TODO:
- // Try to processes parameters, locals, scopes if applicable.
+ long getEndOffset() {
+ return symbol.getDebugEndOffset();
}
- @Override
- public Address getAddress() {
- return address;
+ private boolean isNonReturning() {
+ return symbol.getFlags().doesNotReturn();
}
+
+ private AbstractManagedProcedureMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractManagedProcedureMsSymbol procSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return procSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedSymbolWithSlotSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedSymbolWithSlotSymbolApplier.java
new file mode 100644
index 0000000000..6c80df01ed
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ManagedSymbolWithSlotSymbolApplier.java
@@ -0,0 +1,65 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractManagedSymbolWithSlotIndexFieldMsSymbol;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
+import ghidra.util.exception.AssertException;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Applier for {@link AbstractManagedSymbolWithSlotIndexFieldMsSymbol} symbols.
+ */
+public class ManagedSymbolWithSlotSymbolApplier extends MsSymbolApplier
+ implements NestableSymbolApplier {
+
+ private AbstractManagedSymbolWithSlotIndexFieldMsSymbol symbol;
+
+ /**
+ * Constructor
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working.
+ * @param symbol the symbol for this applier
+ */
+ public ManagedSymbolWithSlotSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractManagedSymbolWithSlotIndexFieldMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ //==============================================================================================
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ // TODO: figure out what needs to be done.
+ }
+ }
+
+ private AbstractManagedSymbolWithSlotIndexFieldMsSymbol getValidatedSymbol(
+ MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractManagedSymbolWithSlotIndexFieldMsSymbol slotSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return slotSymbol;
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MsSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MsSymbolApplier.java
index aea5f34f7b..7d48a17702 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MsSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MsSymbolApplier.java
@@ -18,9 +18,8 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.Objects;
import ghidra.app.plugin.processors.sleigh.symbol.Symbol;
-import ghidra.app.util.bin.format.pdb2.pdbreader.*;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
-import ghidra.util.exception.CancelledException;
/**
* Abstract class representing the applier for a specific {@link AbstractMsSymbol}. The
@@ -31,20 +30,14 @@ import ghidra.util.exception.CancelledException;
*/
public abstract class MsSymbolApplier {
protected DefaultPdbApplicator applicator;
- protected MsSymbolIterator iter;
- protected long currentOffset;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
*/
- public MsSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
+ public MsSymbolApplier(DefaultPdbApplicator applicator) {
Objects.requireNonNull(applicator, "applicator cannot be null");
- Objects.requireNonNull(iter, "iter cannot be null");
this.applicator = applicator;
- this.iter = iter;
- currentOffset = iter.getCurrentOffset();
}
/**
@@ -56,40 +49,4 @@ public abstract class MsSymbolApplier {
applicator.pdbLogAndInfoMessage(originator, message);
}
- /**
- * Sets the offset of the {@link SymbolGroup} back to the state when this applicator was
- * created.
- */
- protected void resetOffset() {
- iter.initGetByOffset(currentOffset);
- }
-
- /**
- * Apply the next and any desired subsequent {@link AbstractMsSymbol AbstractMsSymbols} from
- * the {@link SymbolGroup} to a program.
- * @throws PdbException if there was a problem processing the data.
- * @throws CancelledException upon user cancellation
- */
- abstract void apply() throws PdbException, CancelledException;
-
- /**
- * Applies logic of this class to another {@link MsSymbolApplier} instead of to
- * the program.
- * @param applyToApplier the applier to which the logic of this class is applied.
- * @throws PdbException if there was a problem processing the data.
- * @throws CancelledException upon user cancellation.
- */
- abstract void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException;
-
- /**
- * Manages block nesting for symbols/appliers that represent the beginning or end of blocks.
- * The default is to do nothing. Otherwise the appliers should implement the appropriate
- * logic.
- * @param applierParam the applier which is managing blocks, which is typically
- * {@link FunctionSymbolApplier}.
- */
- void manageBlockNesting(MsSymbolApplier applierParam) {
- // Do nothing by default.
- }
-
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestableSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestableSymbolApplier.java
new file mode 100644
index 0000000000..098c6d06c1
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestableSymbolApplier.java
@@ -0,0 +1,38 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Interface class for MsSymbolApplier that can have its processing nested under another symbol
+ */
+interface NestableSymbolApplier {
+
+ /**
+ * Applies logic of this class to a {@link DeferrableFunctionSymbolApplier} instead of to
+ * the program.
+ * @param applyToApplier the applier to which the logic of this class is applied.
+ * @param iter the Iterator containing the symbol sequence being processed
+ * @throws PdbException if there was a problem processing the data.
+ * @throws CancelledException upon user cancellation.
+ */
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException;
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestingSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestingSymbolApplier.java
new file mode 100644
index 0000000000..61f41d19d9
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NestingSymbolApplier.java
@@ -0,0 +1,23 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+/**
+ * Interface class for MsSymbolApplier that is able to process nested symbols
+ */
+interface NestingSymbolApplier {
+ // Empty
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NoSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NoSymbolApplier.java
index a597cac46d..cb81c0012f 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NoSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/NoSymbolApplier.java
@@ -16,35 +16,33 @@
package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
+import ghidra.util.exception.CancelledException;
/**
* A dummy {@link MsSymbolApplier}, which, at a minimum, reads the symbol from the
* {@link SymbolGroup}, allowing proper sequencing of other symbols within the
* {@link SymbolGroup}.
*/
-public class NoSymbolApplier extends MsSymbolApplier {
+public class NoSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private AbstractMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public NoSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- symbol = iter.next();
+ public NoSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
-
- @Override
- void apply() {
- // Do nothing.
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ iter.next();
+ // Do nothing
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/OemDefinedSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/OemDefinedSymbolApplier.java
new file mode 100644
index 0000000000..6ae043402e
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/OemDefinedSymbolApplier.java
@@ -0,0 +1,71 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
+import ghidra.util.exception.AssertException;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Applier for {@link AbstractManagedSymbolWithSlotIndexFieldMsSymbol} symbols.
+ */
+public class OemDefinedSymbolApplier extends MsSymbolApplier
+ implements DirectSymbolApplier, NestableSymbolApplier {
+
+ private OemDefinedMsSymbol symbol;
+
+ /**
+ * Constructor
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working.
+ * @param symbol the symbol for this applier
+ */
+ public OemDefinedSymbolApplier(DefaultPdbApplicator applicator,
+ OemDefinedMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ //TODO: not sure that this can be directly applied (non-nested)... if not will need to also
+ // remove the DirectSymbolApplier interface
+ @Override
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ // TODO: figure out what needs to be done.
+ }
+ }
+
+ private OemDefinedMsSymbol getValidatedSymbol(
+ MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof OemDefinedMsSymbol oemSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return oemSymbol;
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicatorMetrics.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicatorMetrics.java
index 68666c78eb..b024db1169 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicatorMetrics.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicatorMetrics.java
@@ -108,6 +108,7 @@ public class PdbApplicatorMetrics {
private Set> unexpectedMemberFunctionContainerTypes =
new HashSet<>();
private Set> cannotApplySymbols = new HashSet<>();
+ private Set> nonNestableSymbols = new HashSet<>();
private Set> unexpectedGlobalSymbols = new HashSet<>();
private Set> unexpectedPublicSymbols = new HashSet<>();
private boolean witnessEnumerateNarrowing = false;
@@ -128,6 +129,14 @@ public class PdbApplicatorMetrics {
cannotApplySymbols.add(symbol.getClass());
}
+ /**
+ * Method to capture symbol type that we cannot currently process as a nested symbol
+ * @param symbol The symbol type witnessed
+ */
+ void witnessNonNestableSymbolType(AbstractMsSymbol symbol) {
+ nonNestableSymbols.add(symbol.getClass());
+ }
+
/**
* Method to capture symbol type that was unexpected as a Global symbol.
* @param symbol The symbol type witnessed.
@@ -220,6 +229,7 @@ public class PdbApplicatorMetrics {
builder.append(reportUnunsualThisPointerUnderlyingTypes());
builder.append(reportUnunsualMemberFunctionContainerTypes());
builder.append(reportNonappliableSymbols());
+ builder.append(reportNonNestableSymbols());
builder.append(reportUnexpectedPublicSymbols());
builder.append(reportUnexpectedGlobalSymbols());
builder.append(reportEnumerateNarrowing());
@@ -280,6 +290,15 @@ public class PdbApplicatorMetrics {
return builder.toString();
}
+ private String reportNonNestableSymbols() {
+ StringBuilder builder = new StringBuilder();
+ for (Class extends AbstractMsSymbol> clazz : nonNestableSymbols) {
+ builder.append("Could not nest one or more instances of a PDB symbol type: " +
+ clazz.getSimpleName() + "\n");
+ }
+ return builder.toString();
+ }
+
private String reportUnexpectedPublicSymbols() {
StringBuilder builder = new StringBuilder();
for (Class extends AbstractMsSymbol> clazz : unexpectedPublicSymbols) {
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java
index 059cf560eb..225ed75ea7 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java
@@ -4,9 +4,9 @@
* 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.
@@ -424,32 +424,29 @@ public class PdbResearch {
}
AbstractMsSymbol symbol = iter.peek(); //temporary during development
MsSymbolApplier applier = applicator.getSymbolApplier(iter);
- if (applier instanceof TypedefSymbolApplier) {
- TypedefSymbolApplier typedefApplier = (TypedefSymbolApplier) applier;
+ if (applier instanceof TypedefSymbolApplier typedefApplier) {
RecordNumber typeNumber = typedefApplier.getTypeRecordNumber();
AbstractMsType type = applicator.getPdb().getTypeRecord(typeNumber);
System.out
- .println("UDT " + typedefApplier.getName() + " depends on " + type.toString());
+ .println(
+ "UDT " + typedefApplier.getName() + " depends on " + type.toString());
// applier.apply();
// procSym(symbolGroup);
}
- else if (applier instanceof ReferenceSymbolApplier) {
- ReferenceSymbolApplier refSymbolApplier = (ReferenceSymbolApplier) applier;
+ else if (applier instanceof ReferenceSymbolApplier refSymbolApplier) {
MsSymbolIterator refIter =
- refSymbolApplier.getInitializedReferencedSymbolGroupIterator();
+ refSymbolApplier.getRefIterFromSymbol();
if (refIter == null) {
throw new PdbException("PDB: Referenced Symbol Error - not refIter");
}
// recursion
childWalkSym(applicator, refIter.getStreamNumber(), refIter);
}
- else if (applier instanceof DataSymbolApplier) {
- DataSymbolApplier dataSymbolApplier = (DataSymbolApplier) applier;
- MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier();
+ else if (applier instanceof DataSymbolApplier dataSymbolApplier) {
+ MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier(symbol);
childWalkType(streamNumber, typeApplier);
}
- else if (applier instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applier;
+ else if (applier instanceof FunctionSymbolApplier functionSymbolApplier) {
functionSymbolApplier.getFunction();
// AbstractMsTypeApplier typeApplier = functionSymbolApplier.getTypeApplier();
// childWalkType(symbolGroup.getModuleNumber(), typeApplier);
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffGroupSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffGroupSymbolApplier.java
index 80d715fa90..330279aeaf 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffGroupSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffGroupSymbolApplier.java
@@ -26,27 +26,23 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link PeCoffGroupMsSymbol} symbols.
*/
-public class PeCoffGroupSymbolApplier extends MsSymbolApplier {
+public class PeCoffGroupSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private PeCoffGroupMsSymbol symbol;
/**
* Constructor
- * @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working
+ * @param symbol the symbol for this applier
*/
- public PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof PeCoffGroupMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (PeCoffGroupMsSymbol) abstractSymbol;
+ public PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator, PeCoffGroupMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void apply() throws PdbException, CancelledException {
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
applicator.addMemoryGroupRefinement(symbol);
Address symbolAddress = applicator.getAddress(symbol);
if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
@@ -55,9 +51,13 @@ public class PeCoffGroupSymbolApplier extends MsSymbolApplier {
applicator.createSymbol(symbolAddress, symbol.getName(), false);
}
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing
+ private PeCoffGroupMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof PeCoffGroupMsSymbol peCoffGroupSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return peCoffGroupSymbol;
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffSectionSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffSectionSymbolApplier.java
index b8ab7dac28..5bb7ab69d6 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffSectionSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PeCoffSectionSymbolApplier.java
@@ -25,27 +25,24 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link PeCoffSectionMsSymbol} symbols.
*/
-public class PeCoffSectionSymbolApplier extends MsSymbolApplier {
+public class PeCoffSectionSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private PeCoffSectionMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public PeCoffSectionSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof PeCoffSectionMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (PeCoffSectionMsSymbol) abstractSymbol;
+ public PeCoffSectionSymbolApplier(DefaultPdbApplicator applicator,
+ PeCoffSectionMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void apply() throws PdbException, CancelledException {
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
int sectionNum = symbol.getSectionNumber();
long realAddress = symbol.getRva();
symbol.getLength();
@@ -59,8 +56,13 @@ public class PeCoffSectionSymbolApplier extends MsSymbolApplier {
// applicator.addMemorySectionRefinement(symbol);
}
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing
+ private PeCoffSectionMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof PeCoffSectionMsSymbol peCoffSectionSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return peCoffSectionSymbol;
}
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureIdEndSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureIdEndSymbolApplier.java
new file mode 100644
index 0000000000..b2572e46f7
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureIdEndSymbolApplier.java
@@ -0,0 +1,62 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.ProcedureIdEndMsSymbol;
+import ghidra.util.exception.AssertException;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Applier for {@link ProcedureIdEndMsSymbol} symbols.
+ */
+public class ProcedureIdEndSymbolApplier extends MsSymbolApplier
+ implements BlockNestingSymbolApplier, NestableSymbolApplier {
+
+ private ProcedureIdEndMsSymbol symbol;
+
+ /**
+ * Constructor
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working.
+ * @param symbol the symbol for this applier
+ */
+ public ProcedureIdEndSymbolApplier(DefaultPdbApplicator applicator,
+ ProcedureIdEndMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ applier.endBlock();
+ }
+ }
+
+ private ProcedureIdEndMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof ProcedureIdEndMsSymbol endSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return endSymbol;
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PublicSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PublicSymbolApplier.java
index 54338a00da..3521d93955 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PublicSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PublicSymbolApplier.java
@@ -32,43 +32,32 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractPublicMsSymbol} symbols.
*/
-public class PublicSymbolApplier extends MsSymbolApplier {
+public class PublicSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private AbstractPublicMsSymbol symbol;
- private Address symbolAddress = null;
- private Address existingSymbolAddress = null;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public PublicSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractPublicMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractPublicMsSymbol) abstractSymbol;
+ public PublicSymbolApplier(DefaultPdbApplicator applicator, AbstractPublicMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
-
- @Override
- void apply() throws CancelledException, PdbException {
-
- symbolAddress = applicator.getAddress(symbol);
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ Address symbolAddress = applicator.getAddress(symbol);
String name = symbol.getName();
if (applicator.isInvalidAddress(symbolAddress, name)) {
return;
}
- existingSymbolAddress = applicator.witnessSymbolNameAtAddress(getName(), symbolAddress);
+ Address existingSymbolAddress =
+ applicator.witnessSymbolNameAtAddress(name, symbolAddress);
// TODO: Consider... could add restriction of not putting down symbol if it is mangled,
// as this would violate the uniqueness of the symbol... but we would also want to
// know that this situation was being presented.
@@ -91,15 +80,13 @@ public class PublicSymbolApplier extends MsSymbolApplier {
}
}
- Address getAddress() {
- return symbolAddress;
+ private AbstractPublicMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractPublicMsSymbol pubSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return pubSymbol;
}
- Address getAddressRemappedThroughPublicSymbol() {
- return (existingSymbolAddress != null) ? existingSymbolAddress : symbolAddress;
- }
-
- String getName() {
- return symbol.getName();
- }
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ReferenceSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ReferenceSymbolApplier.java
index e472152820..673295872d 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ReferenceSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ReferenceSymbolApplier.java
@@ -32,50 +32,52 @@ public class ReferenceSymbolApplier extends MsSymbolApplier {
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public ReferenceSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractReferenceMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractReferenceMsSymbol) abstractSymbol;
+ public ReferenceSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractReferenceMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
+ //TODO: since we stopped taking the references from publics/globals to module-based symbols
+ // and processing them that way and are now just processing directly from the
+ // modules, we need to determine if there is any use for these reference symbols.
+ // We currently are not implementing the DirectSymbolApplier or the NestingSymbolApplier
+ // interfaces... so we are an applier just in form at this point.
+ // => Re-evaluate!!!
+// @Override
+// public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+// getValidatedSymbol(iter, true);
+// getValidatedSymbol(iter, true);
+// MsSymbolIterator refIter = getRefIterFromSymbol();
+// applicator.procSymNew(refIter);
+// }
- @Override
- void apply() throws CancelledException, PdbException {
- // Potential recursive call via applicator.procSym().
- MsSymbolIterator refIter = getInitializedReferencedSymbolGroupIterator();
- if (refIter == null) {
- throw new PdbException("PDB: Referenced Symbol Error - null refIter");
- }
- applicator.procSym(refIter);
- }
-
- MsSymbolIterator getInitializedReferencedSymbolGroupIterator() throws PdbException {
- SymbolGroup refSymbolGroup = getReferencedSymbolGroup();
- if (refSymbolGroup == null) {
- return null;
- }
- MsSymbolIterator refIter = refSymbolGroup.getSymbolIterator();
- refIter.initGetByOffset(getOffsetInReferencedSymbolGroup());
+ /**
+ * Checks check symbol from primary iterator for correct type and then retrieves the
+ * properly initialized reference iterator
+ * @return the initialized reference iterator
+ * @throws PdbException upon not enough data to parse
+ * @throws CancelledException upon user cancellation
+ */
+ MsSymbolIterator getRefIterFromSymbol()
+ throws CancelledException, PdbException {
+ int refModuleNumber = symbol.getModuleIndex();
+ MsSymbolIterator refIter =
+ applicator.getPdb().getDebugInfo().getSymbolIterator(refModuleNumber);
+ long refOffset = symbol.getOffsetActualSymbolInDollarDollarSymbols();
+ refIter.initGetByOffset(refOffset);
return refIter;
}
- SymbolGroup getReferencedSymbolGroup() {
- int refModuleNumber = symbol.getModuleIndex();
- return applicator.getSymbolGroupForModule(refModuleNumber);
- }
-
- long getOffsetInReferencedSymbolGroup() {
- return symbol.getOffsetActualSymbolInDollarDollarSymbols();
+ private AbstractReferenceMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractReferenceMsSymbol refSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return refSymbol;
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/RegisterRelativeSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/RegisterRelativeSymbolApplier.java
index abf402b79b..65dad129b9 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/RegisterRelativeSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/RegisterRelativeSymbolApplier.java
@@ -17,9 +17,7 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.Objects;
-import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
-import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
-import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
+import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractRegisterRelativeAddressMsSymbol;
import ghidra.program.model.data.DataType;
@@ -31,44 +29,24 @@ import ghidra.util.exception.*;
/**
* Applier for {@link AbstractRegisterRelativeAddressMsSymbol} symbols.
*/
-public class RegisterRelativeSymbolApplier extends MsSymbolApplier {
+public class RegisterRelativeSymbolApplier extends MsSymbolApplier
+ implements NestableSymbolApplier {
private AbstractRegisterRelativeAddressMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
public RegisterRelativeSymbolApplier(DefaultPdbApplicator applicator,
- MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractRegisterRelativeAddressMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (AbstractRegisterRelativeAddressMsSymbol) abstractSymbol;
+ AbstractRegisterRelativeAddressMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
- @Override
- void apply() throws PdbException, CancelledException {
- pdbLogAndInfoMessage(this,
- "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
- if (!applicator.getPdbApplicatorOptions().applyFunctionVariables()) {
- return;
- }
- if (applyToApplier instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
- createFunctionVariable(functionSymbolApplier);
- }
- }
-
- private boolean createFunctionVariable(FunctionSymbolApplier applier)
+ private boolean createFunctionVariable(FunctionSymbolApplier applier,
+ AbstractRegisterRelativeAddressMsSymbol symbol)
throws CancelledException, PdbException {
Objects.requireNonNull(applier, "FunctionSymbolApplier cannot be null");
Function function = applier.getFunction();
@@ -156,4 +134,26 @@ public class RegisterRelativeSymbolApplier extends MsSymbolApplier {
return true;
}
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (!applicator.getPdbApplicatorOptions().applyFunctionVariables()) {
+ return;
+ }
+ if (applyToApplier instanceof FunctionSymbolApplier functionSymbolApplier) {
+ createFunctionVariable(functionSymbolApplier, symbol);
+ }
+ }
+
+ private AbstractRegisterRelativeAddressMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractRegisterRelativeAddressMsSymbol regRelSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return regRelSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SeparatedCodeSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SeparatedCodeSymbolApplier.java
index 0dcc51f868..419e178a4b 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SeparatedCodeSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SeparatedCodeSymbolApplier.java
@@ -15,131 +15,130 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
-import java.util.ArrayList;
-import java.util.List;
-
-import ghidra.app.cmd.comments.SetCommentCmd;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.SeparatedCodeFromCompilerSupportMsSymbol;
import ghidra.program.model.address.Address;
-import ghidra.program.model.listing.CodeUnit;
-import ghidra.util.Msg;
+import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
/**
* Applier for {@link SeparatedCodeFromCompilerSupportMsSymbol} symbol.
*/
-// TODO: Need to evaluate relationship to function symbols.
-// TODO: Need to create anonymous name for this as a function?
-public class SeparatedCodeSymbolApplier extends MsSymbolApplier {
+public class SeparatedCodeSymbolApplier extends AbstractBlockContextApplier
+ implements BlockNestingSymbolApplier, NestableSymbolApplier {
private SeparatedCodeFromCompilerSupportMsSymbol symbol;
- private String craftedName;
-
- private Address specifiedAddress;
- private BlockCommentsManager comments;
-
- private int symbolBlockNestingLevel;
- private Address currentBlockAddress;
-
- private List allAppliers = new ArrayList<>();
-
- private static MsSymbolIterator validateSymbol(MsSymbolIterator iter) {
- if (!(iter.peek() instanceof SeparatedCodeFromCompilerSupportMsSymbol)) {
- throw new IllegalArgumentException("Not a SeparatedCodeFromCompilerSupportMsSymbol");
- }
- return iter;
- }
-
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
- * @throws CancelledException upon user cancellation
+ * @param symbol the symbol for this applier
*/
public SeparatedCodeSymbolApplier(DefaultPdbApplicator applicator,
- MsSymbolIterator iter) throws CancelledException {
- super(applicator, validateSymbol(iter));
-
- symbol = (SeparatedCodeFromCompilerSupportMsSymbol) iter.next();
-
- specifiedAddress = applicator.getAddress(symbol);
-
- // Make up name. TODO: decide if need better anonymous name
- craftedName = String.format("CompilerSeparatedCode%s", specifiedAddress);
-
- symbolBlockNestingLevel = 0;
-
- comments = new BlockCommentsManager();
- currentBlockAddress = null;
-
- manageBlockNesting(this);
-
- while (notDone()) {
- applicator.checkCancelled();
- MsSymbolApplier applier = applicator.getSymbolApplier(iter);
- if (!(applier instanceof EndSymbolApplier)) {
- Msg.info(this, "Unexpected applier in " + getClass().getSimpleName() + ": " +
- applier.getClass().getSimpleName());
- }
- allAppliers.add(applier);
- applier.manageBlockNesting(this);
- }
+ SeparatedCodeFromCompilerSupportMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- beginBlock(specifiedAddress);
- }
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ Address address = applicator.getAddress(symbol);
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
-
- @Override
- void apply() throws PdbException, CancelledException {
- if (applicator.isInvalidAddress(currentBlockAddress, craftedName)) {
+ // Regardless of ability to apply this symbol, we need to progress through symbols to the
+ // matching "end" symbol before we return
+ if (!processEndSymbol(symbol.getEndPointer(), iter)) {
+ applicator.appendLogMsg("PDB: Failed to process function at address " + address);
return;
}
- // DO NOTHING FOR NOW. TODO: should we have a configuration option?
- // Note: these comments can be noise in the decompiler an code browser
- setComments(false);
+
+ if (applicator.isInvalidAddress(address, craftBlockComment(address))) {
+ return;
+ }
+
+ // Although this is code, we do not create a function here or perform disassembly.
+ // The Decompiler should be able to track flow to this location from the parent.
+ // Just applying a plate comment here to identify this block in the code browser.
+ // Note, however, there are some flags that could be useful, such as "returns to parent."
+ applyPlateComment(address);
+// Function function = applicator.getExistingOrCreateOneByteFunction(address);
+// if (function == null) {
+// return;
+// }
+//
+// // Collecting all addresses from all functions to do one large bulk disassembly of the
+// // complete AddressSet of function addresses. We could consider removing this logic
+// // of collecting them all for bulk disassembly and do individual disassembly at the
+// // same deferred point in time.
+// applicator.scheduleDisassembly(address);
}
- private void setComments(boolean enabled) {
- if (enabled) {
- String existingComment = applicator.getProgram()
- .getListing()
- .getComment(
- CodeUnit.PRE_COMMENT, specifiedAddress);
- String p = "*************************************************************\n";
- String newComment =
- String.format(p + "* Separated code (from the compiler): %s - %s *\n" + p,
- specifiedAddress.toString(),
- specifiedAddress.add(symbol.getBlockLength() - 1).toString());
- String comment =
- (existingComment == null) ? newComment : existingComment + "\n" + newComment;
- SetCommentCmd.createComment(applicator.getProgram(), specifiedAddress, comment,
- CodeUnit.PRE_COMMENT);
+ @Override
+ public void deferredApply(MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+
+ Address address = applicator.getAddress(symbol);
+
+ long start = getStartOffset();
+ long end = getEndOffset();
+ Address blockAddress = address.add(start);
+ long length = end - start;
+
+ // Not sure if following procedure from parent class can be used or if should be
+ // specialized here
+ deferredProcessing(iter, craftBlockComment(blockAddress), address, blockAddress, length);
+ }
+
+ private String craftBlockComment(Address address) {
+ return String.format("CompilerSeparatedCode%s", address);
+ }
+
+ private void applyPlateComment(Address address) {
+ Address parentAddress =
+ applicator.getAddress(symbol.getSegmentParent(), symbol.getOffsetParent());
+ String comment = String.format(
+ "PDB: Separated code (from the compiler): %s - %s for parent address: %s",
+ address.toString(),
+ address.add(symbol.getBlockLength() - 1).toString(), parentAddress.toString());
+ applicator.addToPlateUnique(address, comment);
+ }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ Address address = applicator.getAddress(symbol);
+ applier.beginBlock(address, null, 0);
}
}
- private boolean notDone() {
- return (symbolBlockNestingLevel > 0) && iter.hasNext();
+ @Override
+ long getStartOffset() {
+ return symbol.getParentPointer(); // TODO: needs investigation as to what field to use!!!!!
}
- void endBlock() {
- if (--symbolBlockNestingLevel < 0) {
- applicator.appendLogMsg("Block Nesting went negative at " + specifiedAddress);
+ @Override
+ long getEndOffset() {
+ return symbol.getEndPointer(); // TODO: needs investigation as to what field to use!!!!!
+ }
+
+ boolean returnsToParent() {
+ return symbol.returnsToParent();
+ }
+
+ private SeparatedCodeFromCompilerSupportMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof SeparatedCodeFromCompilerSupportMsSymbol sepCodeSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
- }
-
- void beginBlock(Address startAddress) {
- currentBlockAddress = startAddress;
- ++symbolBlockNestingLevel;
+ return sepCodeSymbol;
}
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolApplierFactory.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolApplierFactory.java
index 65b97d4742..3e7c3b646e 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolApplierFactory.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolApplierFactory.java
@@ -17,11 +17,10 @@ package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
-import ghidra.util.exception.CancelledException;
/**
* Pseudo-factory for creating the {@link MsSymbolApplier} for the {@link AbstractMsSymbol}
- * indicated by the {@link AbstractMsSymbolIterator}.
+ * indicated by the {@link MsSymbolIterator}.
*/
public class SymbolApplierFactory {
@@ -31,21 +30,29 @@ public class SymbolApplierFactory {
this.applicator = applicator;
}
- // TODO: 20191120... Do we need a SymbolApplier cache for Symbols like we have the TypeApplier
- // cache (by index) for Types/Items? Would we use a record number (index) from within
- // the AbstractMsSymbol (do one for AbstractMsType as well)? Symbols are different in that
- // we are using SymbolGroup as a member instead of MsType.
-
- MsSymbolApplier getSymbolApplier(MsSymbolIterator iter) throws CancelledException {
-
+ MsSymbolApplier getSymbolApplier(MsSymbolIterator iter) {
AbstractMsSymbol symbol = iter.peek();
if (symbol == null) {
applicator.appendLogMsg("PDB Warning: No AbstractMsSymbol");
return null;
}
+ return getSymbolApplier(symbol, iter);
+ }
+
+ MsSymbolApplier getSymbolApplier(AbstractMsSymbol symbol, MsSymbolIterator iter) {
+ MsSymbolApplier applier = getSymbolApplierInternal(symbol, iter);
+ if (!(applier instanceof NoSymbolApplier)) {
+ applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol);
+ }
+ return applier;
+ }
+
+ private MsSymbolApplier getSymbolApplierInternal(AbstractMsSymbol symbol,
+ MsSymbolIterator iter) {
MsSymbolApplier applier = null;
- switch (symbol.getPdbId()) {
+ int pdbId = symbol.getPdbId();
+ switch (pdbId) {
// // 0x0000 block
// case CompileFlagsMsSymbol.PDB_ID:
// symbol = new CompileFlagsMsSymbol(pdb, reader);
@@ -57,13 +64,14 @@ public class SymbolApplierFactory {
// symbol = new Constant16MsSymbol(pdb, reader);
// break;
case UserDefinedType16MsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
// case StartSearchMsSymbol.PDB_ID:
// symbol = new StartSearchMsSymbol(pdb, reader);
// break;
case EndMsSymbol.PDB_ID:
- applier = new EndSymbolApplier(applicator, iter);
+ applier = new EndSymbolApplier(applicator, (EndMsSymbol) symbol);
break;
// case SkipMsSymbol.PDB_ID:
// symbol = new SkipMsSymbol(pdb, reader);
@@ -78,7 +86,8 @@ public class SymbolApplierFactory {
// symbol = new EndArgumentsListMsSymbol(pdb, reader);
// break;
case CobolUserDefinedType16MsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
// case ManyRegisterVariable16MsSymbol.PDB_ID:
// symbol = new ManyRegisterVariable16MsSymbol(pdb, reader);
@@ -95,31 +104,31 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative16MsSymbol(pdb, reader);
// break;
case LocalData16MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalData16MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case Public16MsSymbol.PDB_ID:
- applier = new PublicSymbolApplier(applicator, iter);
+ applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break;
case LocalProcedureStart16MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStart16MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case Thunk16MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case Block16MsSymbol.PDB_ID:
- applier = new BlockSymbolApplier(applicator, iter);
+ applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break;
case With16MsSymbol.PDB_ID:
- applier = new WithSymbolApplier(applicator, iter);
+ applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break;
case Label16MsSymbol.PDB_ID:
- applier = new LabelSymbolApplier(applicator, iter);
+ applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break;
// case ChangeExecutionModel16MsSymbol.PDB_ID:
// symbol = new ChangeExecutionModel16MsSymbol(pdb, reader);
@@ -128,7 +137,8 @@ public class SymbolApplierFactory {
// symbol = new VirtualFunctionTable16MsSymbol(pdb, reader);
// break;
case RegisterRelativeAddress16MsSymbol.PDB_ID:
- applier = new RegisterRelativeSymbolApplier(applicator, iter);
+ applier = new RegisterRelativeSymbolApplier(applicator,
+ (AbstractRegisterRelativeAddressMsSymbol) symbol);
break;
//
// // 0x0200 block
@@ -136,31 +146,31 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative3216MsSymbol(pdb, reader);
// break;
case LocalData3216MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalData3216MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case Public3216MsSymbol.PDB_ID:
- applier = new PublicSymbolApplier(applicator, iter);
+ applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break;
case LocalProcedureStart3216MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStart3216MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case Thunk32StMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case Block32StMsSymbol.PDB_ID:
- applier = new BlockSymbolApplier(applicator, iter);
+ applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break;
case With32StMsSymbol.PDB_ID:
- applier = new WithSymbolApplier(applicator, iter);
+ applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break;
case Label32StMsSymbol.PDB_ID:
- applier = new LabelSymbolApplier(applicator, iter);
+ applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break;
// case ChangeExecutionModel32MsSymbol.PDB_ID:
// symbol = new ChangeExecutionModel32MsSymbol(pdb, reader);
@@ -169,7 +179,8 @@ public class SymbolApplierFactory {
// symbol = new VirtualFunctionTable3216MsSymbol(pdb, reader);
// break;
case RegisterRelativeAddress3216MsSymbol.PDB_ID:
- applier = new RegisterRelativeSymbolApplier(applicator, iter);
+ applier = new RegisterRelativeSymbolApplier(applicator,
+ (AbstractRegisterRelativeAddressMsSymbol) symbol);
break;
// case LocalThreadStorage3216MsSymbol.PDB_ID:
// symbol = new LocalThreadStorage3216MsSymbol(pdb, reader);
@@ -183,28 +194,31 @@ public class SymbolApplierFactory {
// 0x0300 block
case LocalProcedureStartMips16MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStartMips16MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// 0x0400 block
case ProcedureReferenceStMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case DataReferenceStMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
// case AlignMsSymbol.PDB_ID:
// symbol = new AlignMsSymbol(pdb, reader);
// break;
case LocalProcedureReferenceStMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
+ break;
+ case OemDefinedMsSymbol.PDB_ID:
+ applier = new OemDefinedSymbolApplier(applicator, (OemDefinedMsSymbol) symbol);
break;
-// case OemDefinedMsSymbol.PDB_ID:
-// symbol = new OemDefinedMsSymbol(pdb, reader);
-// break;
//
// // 0x1000 block
// case RegisterStMsSymbol.PDB_ID:
@@ -214,10 +228,12 @@ public class SymbolApplierFactory {
// symbol = new ConstantStMsSymbol(pdb, reader);
// break;
case UserDefinedTypeStMsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
case CobolUserDefinedTypeStMsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
// case ManyRegisterVariableStMsSymbol.PDB_ID:
// symbol = new ManyRegisterVariableStMsSymbol(pdb, reader);
@@ -226,25 +242,26 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative32StMsSymbol(pdb, reader);
// break;
case LocalData32StMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalData32StMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case Public32StMsSymbol.PDB_ID:
- applier = new PublicSymbolApplier(applicator, iter);
+ applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break;
case LocalProcedureStart32StMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStart32StMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// case VirtualFunctionTable32MsSymbol.PDB_ID:
// symbol = new VirtualFunctionTable32MsSymbol(pdb, reader);
// break;
case RegisterRelativeAddress32StMsSymbol.PDB_ID:
- applier = new RegisterRelativeSymbolApplier(applicator, iter);
+ applier = new RegisterRelativeSymbolApplier(applicator,
+ (AbstractRegisterRelativeAddressMsSymbol) symbol);
break;
// case LocalThreadStorage32StMsSymbol.PDB_ID:
// symbol = new LocalThreadStorage32StMsSymbol(pdb, reader);
@@ -253,13 +270,14 @@ public class SymbolApplierFactory {
// symbol = new GlobalThreadStorage32StMsSymbol(pdb, reader);
// break;
case LocalProcedureStartMipsStMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStartMipsStMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case ExtraFrameAndProcedureInformationMsSymbol.PDB_ID:
- applier = new FrameAndProcedureInformationSymbolApplier(applicator, iter);
+ applier = new FrameAndProcedureInformationSymbolApplier(applicator,
+ (ExtraFrameAndProcedureInformationMsSymbol) symbol);
break;
// case Compile2StMsSymbol.PDB_ID:
// symbol = new Compile2StMsSymbol(pdb, reader);
@@ -268,10 +286,10 @@ public class SymbolApplierFactory {
// symbol = new ManyRegisterVariable2StMsSymbol(pdb, reader);
// break;
case LocalProcedureStartIa64StMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStartIa64StMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// case LocalSlotIndexFieldedLILStMsSymbol.PDB_ID:
// symbol = new LocalSlotIndexFieldedLILStMsSymbol(pdb, reader);
@@ -283,10 +301,12 @@ public class SymbolApplierFactory {
// symbol = new AnnotationMsSymbol(pdb, reader);
// break;
case GlobalManagedProcedureStMsSymbol.PDB_ID:
- applier = new ManagedProcedureSymbolApplier(applicator, iter);
+ applier = new ManagedProcedureSymbolApplier(applicator,
+ (AbstractManagedProcedureMsSymbol) symbol);
break;
case LocalManagedProcedureStMsSymbol.PDB_ID:
- applier = new ManagedProcedureSymbolApplier(applicator, iter);
+ applier = new ManagedProcedureSymbolApplier(applicator,
+ (AbstractManagedProcedureMsSymbol) symbol);
break;
// case Reserved1MsSymbol.PDB_ID:
// symbol = new Reserved1MsSymbol(pdb, reader);
@@ -301,10 +321,10 @@ public class SymbolApplierFactory {
// symbol = new Reserved4MsSymbol(pdb, reader);
// break;
case LocalManagedDataStMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalManagedDataStMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
// case ManLocOrParamReltoVFPStMsSymbol.PDB_ID:
// symbol = new ManLocOrParamReltoVFPStMsSymbol(pdb, reader);
@@ -312,9 +332,10 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIRStMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIRStMsSymbol(pdb, reader);
// break;
-// case ManagedSymbolWithSlotIndexFieldStMsSymbol.PDB_ID:
-// symbol = new ManagedSymbolWithSlotIndexFieldStMsSymbol(pdb, reader);
-// break;
+ case ManagedSymbolWithSlotIndexFieldStMsSymbol.PDB_ID:
+ applier = new ManagedSymbolWithSlotSymbolApplier(applicator,
+ (AbstractManagedSymbolWithSlotIndexFieldMsSymbol) symbol);
+ break;
// case ManagedLocalOrParameterSIMRStMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMRStMsSymbol(pdb, reader);
// break;
@@ -327,25 +348,26 @@ public class SymbolApplierFactory {
// case IndexForTypeReferencedByNameFromMetadataMsSymbol.PDB_ID:
// symbol = new IndexForTypeReferencedByNameFromMetadataMsSymbol(pdb, reader);
// break;
-// case UsingNamespaceStMsSymbol.PDB_ID:
-// symbol = new UsingNamespaceStMsSymbol(pdb, reader);
-// break;
+ case UsingNamespaceStMsSymbol.PDB_ID:
+ applier = new UsingNamespaceSymbolApplier(applicator,
+ (AbstractUsingNamespaceMsSymbol) symbol);
+ break;
//
// // 0x1100 block
// case ObjectNameMsSymbol.PDB_ID:
// symbol = new ObjectNameMsSymbol(pdb, reader);
// break;
case Thunk32MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case Block32MsSymbol.PDB_ID:
- applier = new BlockSymbolApplier(applicator, iter);
+ applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break;
case With32MsSymbol.PDB_ID:
- applier = new WithSymbolApplier(applicator, iter);
+ applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break;
case Label32MsSymbol.PDB_ID:
- applier = new LabelSymbolApplier(applicator, iter);
+ applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break;
// case RegisterMsSymbol.PDB_ID:
// symbol = new RegisterMsSymbol(pdb, reader);
@@ -354,10 +376,12 @@ public class SymbolApplierFactory {
// symbol = new ConstantMsSymbol(pdb, reader);
// break;
case UserDefinedTypeMsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
case CobolUserDefinedTypeMsSymbol.PDB_ID:
- applier = new TypedefSymbolApplier(applicator, iter);
+ applier =
+ new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break;
// case ManyRegisterVariableMsSymbol.PDB_ID:
// symbol = new ManyRegisterVariableMsSymbol(pdb, reader);
@@ -366,22 +390,23 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative32MsSymbol(pdb, reader);
// break;
case LocalData32MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalData32MsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case Public32MsSymbol.PDB_ID:
- applier = new PublicSymbolApplier(applicator, iter);
+ applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break;
case LocalProcedureStart32MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStart32MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case RegisterRelativeAddress32MsSymbol.PDB_ID:
- applier = new RegisterRelativeSymbolApplier(applicator, iter);
+ applier = new RegisterRelativeSymbolApplier(applicator,
+ (AbstractRegisterRelativeAddressMsSymbol) symbol);
break;
// case LocalThreadStorage32MsSymbol.PDB_ID:
// symbol = new LocalThreadStorage32MsSymbol(pdb, reader);
@@ -390,10 +415,10 @@ public class SymbolApplierFactory {
// symbol = new GlobalThreadStorage32MsSymbol(pdb, reader);
// break;
case LocalProcedureStartMipsMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStartMipsMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// case Compile2MsSymbol.PDB_ID:
// symbol = new Compile2MsSymbol(pdb, reader);
@@ -402,10 +427,10 @@ public class SymbolApplierFactory {
// symbol = new ManyRegisterVariable2MsSymbol(pdb, reader);
// break;
case LocalProcedureStartIa64MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureStartIa64MsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// case LocalSlotIndexFieldedLILMsSymbol.PDB_ID:
// symbol = new LocalSlotIndexFieldedLILMsSymbol(pdb, reader);
@@ -414,10 +439,10 @@ public class SymbolApplierFactory {
// symbol = new ParameterSlotIndexFieldedLILMsSymbol(pdb, reader);
// break;
case LocalManagedDataMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
case GlobalManagedDataMsSymbol.PDB_ID:
- applier = new DataSymbolApplier(applicator, iter);
+ applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break;
// case ManLocOrParamReltoVFPMsSymbol.PDB_ID:
// symbol = new ManLocOrParamReltoVFPMsSymbol(pdb, reader);
@@ -425,9 +450,10 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIRMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIRMsSymbol(pdb, reader);
// break;
-// case ManagedSymbolWithSlotIndexFieldMsSymbol.PDB_ID:
-// symbol = new ManagedSymbolWithSlotIndexFieldMsSymbol(pdb, reader);
-// break;
+ case ManagedSymbolWithSlotIndexFieldMsSymbol.PDB_ID:
+ applier = new ManagedSymbolWithSlotSymbolApplier(applicator,
+ (AbstractManagedSymbolWithSlotIndexFieldMsSymbol) symbol);
+ break;
// case ManagedLocalOrParameterSIMRMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMRMsSymbol(pdb, reader);
// break;
@@ -437,32 +463,40 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIMR2MsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMR2MsSymbol(pdb, reader);
// break;
-// case UsingNamespaceMsSymbol.PDB_ID:
-// symbol = new UsingNamespaceMsSymbol(pdb, reader);
-// break;
+ case UsingNamespaceMsSymbol.PDB_ID:
+ applier = new UsingNamespaceSymbolApplier(applicator,
+ (AbstractUsingNamespaceMsSymbol) symbol);
+ break;
case ProcedureReferenceMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case DataReferenceMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case LocalProcedureReferenceMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case AnnotationReferenceMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case TokenReferenceToManagedProcedureMsSymbol.PDB_ID:
- applier = new ReferenceSymbolApplier(applicator, iter);
+ applier =
+ new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break;
case GlobalManagedProcedureMsSymbol.PDB_ID:
- applier = new ManagedProcedureSymbolApplier(applicator, iter);
+ applier = new ManagedProcedureSymbolApplier(applicator,
+ (AbstractManagedProcedureMsSymbol) symbol);
break;
case LocalManagedProcedureMsSymbol.PDB_ID:
- applier = new ManagedProcedureSymbolApplier(applicator, iter);
+ applier = new ManagedProcedureSymbolApplier(applicator,
+ (AbstractManagedProcedureMsSymbol) symbol);
break;
case TrampolineMsSymbol.PDB_ID:
- applier = new TrampolineSymbolApplier(applicator, iter);
+ applier = new TrampolineSymbolApplier(applicator, (TrampolineMsSymbol) symbol);
break;
// case ManagedConstantMsSymbol.PDB_ID:
// symbol = new ManagedConstantMsSymbol(pdb, reader);
@@ -480,10 +514,12 @@ public class SymbolApplierFactory {
// symbol = new AttributedLocalOrParameterSIMRMsSymbol(pdb, reader);
// break;
case SeparatedCodeFromCompilerSupportMsSymbol.PDB_ID:
- applier = new SeparatedCodeSymbolApplier(applicator, iter);
+ applier = new SeparatedCodeSymbolApplier(applicator,
+ (SeparatedCodeFromCompilerSupportMsSymbol) symbol);
break;
case LocalSymbolInOptimizedCode2005MsSymbol.PDB_ID:
- applier = new LocalOptimizedSymbolApplier(applicator, iter);
+ applier = new LocalOptimizedSymbolApplier(applicator,
+ (AbstractLocalSymbolInOptimizedCodeMsSymbol) symbol);
break;
// case DefinedSingleAddressRange2005MsSymbol.PDB_ID:
// symbol = new DefinedSingleAddressRange2005MsSymbol(pdb, reader);
@@ -492,10 +528,11 @@ public class SymbolApplierFactory {
// symbol = new DefinedMultipleAddressRanges2005MsSymbol(pdb, reader);
// break;
case PeCoffSectionMsSymbol.PDB_ID:
- applier = new PeCoffSectionSymbolApplier(applicator, iter);
+ applier =
+ new PeCoffSectionSymbolApplier(applicator, (PeCoffSectionMsSymbol) symbol);
break;
case PeCoffGroupMsSymbol.PDB_ID:
- applier = new PeCoffGroupSymbolApplier(applicator, iter);
+ applier = new PeCoffGroupSymbolApplier(applicator, (PeCoffGroupMsSymbol) symbol);
break;
// case ExportMsSymbol.PDB_ID:
// symbol = new ExportMsSymbol(pdb, reader);
@@ -516,46 +553,54 @@ public class SymbolApplierFactory {
// symbol = new EnvironmentBlockMsSymbol(pdb, reader);
// break;
case LocalSymbolInOptimizedCodeMsSymbol.PDB_ID:
- applier = new LocalOptimizedSymbolApplier(applicator, iter);
+ applier = new LocalOptimizedSymbolApplier(applicator,
+ (AbstractLocalSymbolInOptimizedCodeMsSymbol) symbol);
break;
case DefinedSingleAddressRangeMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case SubfieldDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case EnregisteredSymbolDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case FramePointerRelativeDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case EnregisteredFieldOfSymbolDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case FramePointerRelativeFullScopeDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case EnregisteredSymbolRelativeDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
case LocalProcedure32IdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedure32IdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case LocalProcedureMipsIdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureMipsIdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case LocalProcedureIa64IdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case GlobalProcedureIa64IdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
// case BuildInformationMsSymbol.PDB_ID:
// symbol = new BuildInformationMsSymbol(pdb, reader);
@@ -567,10 +612,12 @@ public class SymbolApplierFactory {
// symbol = new InlinedFunctionEndMsSymbol(pdb, reader);
// break;
case ProcedureIdEndMsSymbol.PDB_ID:
- applier = new EndSymbolApplier(applicator, iter);
+ applier =
+ new ProcedureIdEndSymbolApplier(applicator, (ProcedureIdEndMsSymbol) symbol);
break;
case HighLevelShaderLanguageRegDimDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
// case GlobalDataHLSLMsSymbol.PDB_ID:
// symbol = new GlobalDataHLSLMsSymbol(pdb, reader);
@@ -585,13 +632,14 @@ public class SymbolApplierFactory {
// symbol = new LocalDeferredProcedureCallGroupSharedMsSymbol(pdb, reader);
// break;
case LocalProcedureStart32DeferredProcedureCallMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case LocalProcedure32DeferredProcedureCallIdMsSymbol.PDB_ID:
- applier = new FunctionSymbolApplier(applicator, iter);
+ applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break;
case DeferredProcedureCallPointerTagRegDimDARMsSymbol.PDB_ID:
- applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter);
+ applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
+ (AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break;
// case DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol.PDB_ID:
// symbol = new DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol(pdb, reader);
@@ -650,8 +698,7 @@ public class SymbolApplierFactory {
default:
// This should never happen (unless we missed something
// or MSFT has added new in a version we do not handle.
- applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol);
- applier = new NoSymbolApplier(applicator, iter);
+ applier = new NoSymbolApplier(applicator, symbol);
break;
}
return applier;
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolGroup.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolGroup.java
index cba0848141..a9f16eb667 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolGroup.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/SymbolGroup.java
@@ -21,7 +21,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
-import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
/**
@@ -174,12 +173,6 @@ public class SymbolGroup {
try {
startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber);
}
- catch (IOException e) {
- Msg.warn(this, "PDB issue reading stream when initializing iterator for stream " +
- streamNumber);
- startingOffset = 0;
- lengthSymbols = 0; // essentially null out iterator with zero length
- }
catch (CancelledException e) {
startingOffset = 0;
lengthSymbols = 0; // essentially null out iterator with zero length
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TrampolineSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TrampolineSymbolApplier.java
index cc6054a701..2cfb565a12 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TrampolineSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TrampolineSymbolApplier.java
@@ -27,38 +27,51 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link TrampolineMsSymbol} symbols.
*/
-public class TrampolineSymbolApplier extends MsSymbolApplier
- implements DeferrableFunctionSymbolApplier {
+public class TrampolineSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
+//public class TrampolineSymbolApplier extends MsSymbolApplier
+// implements DeferrableFunctionSymbolApplier { // Question of whether we need to do work later
private TrampolineMsSymbol symbol;
- private Address address;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public TrampolineSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof TrampolineMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- symbol = (TrampolineMsSymbol) abstractSymbol;
- address = applicator.getAddress(symbol);
+ public TrampolineSymbolApplier(DefaultPdbApplicator applicator, TrampolineMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing.
- }
+ // TODO? If we wanted to be able to apply this symbol to a different address, we should
+ // review code in FunctionSymbolApplier. Note, however, that there are two addresses
+ // that need to be dealt with here, and each could have a different address with a different
+ // delta from the specified address.
@Override
- void apply() throws CancelledException, PdbException {
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+
// We know the size of this trampoline, so use it to restrict the disassembly.
Address targetAddress =
applicator.getAddress(symbol.getSegmentTarget(), symbol.getOffsetTarget());
+ Address address = applicator.getAddress(symbol);
+// TrampolineMsSymbol.Type type = symbol.getType();
+// if (type == TrampolineMsSymbol.Type.INCREMENTAL) {
+// // Needed?
+// }
+// else if (type == TrampolineMsSymbol.Type.BRANCH_ISLAND) {
+// // Needed?
+// }
+// else {
+// Msg.info(this, "Unknown trampoline type for symbol: " + symbol);
+// }
+// int size = symbol.getSizeOfThunk();
+
+// int thunkModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionThunk(),
+// symbol.getOffsetThunk());
+//int targetModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionTarget(),
+// symbol.getOffsetTarget());
Function target = null;
Function thunk = null;
@@ -71,23 +84,17 @@ public class TrampolineSymbolApplier extends MsSymbolApplier
if (target != null && thunk != null) {
thunk.setThunkedFunction(target);
}
- applicator.scheduleDeferredFunctionWork(this);
-
-// int thunkModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionThunk(),
-// symbol.getOffsetThunk());
-// int targetModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionTarget(),
-// symbol.getOffsetTarget());
-
+ applicator.scheduleDisassembly(address);
+ // TODO: should we schedule at targetAddress too?
}
- @Override
- public Address getAddress() {
- return address;
+ private TrampolineMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof TrampolineMsSymbol trampolineSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return trampolineSymbol;
}
- // TODO? If we wanted to be able to apply this symbol to a different address, we should
- // review code in FunctionSymbolApplier. Note, however, that there are two addresses
- // that need to be dealt with here, and each could have a different address with a different
- // delta from the specified address.
-
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TypedefSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TypedefSymbolApplier.java
index 53ceae90e0..6bbb492fde 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TypedefSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/TypedefSymbolApplier.java
@@ -4,9 +4,9 @@
* 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.
@@ -28,42 +28,45 @@ import ghidra.util.exception.CancelledException;
/**
* Applier for {@link AbstractUserDefinedTypeMsSymbol} symbols.
*/
-public class TypedefSymbolApplier extends MsSymbolApplier {
+public class TypedefSymbolApplier extends MsSymbolApplier
+ implements DirectSymbolApplier /* , NestableSymbolApplier*/ {
private DataType resolvedDataType = null;
- private AbstractUserDefinedTypeMsSymbol udtSymbol;
+ private AbstractUserDefinedTypeMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public TypedefSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractUserDefinedTypeMsSymbol)) {
- throw new AssertException(
- "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
- }
- udtSymbol = (AbstractUserDefinedTypeMsSymbol) abstractSymbol;
+ public TypedefSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractUserDefinedTypeMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
}
@Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing
+ public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ resolvedDataType = applyUserDefinedTypeMsSymbol();
}
- @Override
- void apply() throws PdbException, CancelledException {
- resolvedDataType = applyUserDefinedTypeMsSymbol(udtSymbol);
- }
+ // TODO: employ something like this for when adding "Implements NestableSymbolApplier" to class
+// @Override
+// public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+// throws PdbException, CancelledException {
+// getValidatedSymbol(iter, true);
+// if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+// // TODO: some work: probably typedef in namespace of fn
+// }
+// }
/**
* Returns the name.
* @return Name.
*/
String getName() {
- return udtSymbol.getName();
+ return symbol.getName();
}
/**
@@ -71,7 +74,7 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
* @return Type record number.
*/
RecordNumber getTypeRecordNumber() {
- return udtSymbol.getTypeRecordNumber();
+ return symbol.getTypeRecordNumber();
}
DataType getResolvedDataType() throws PdbException {
@@ -82,18 +85,19 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
}
// Typedefs
- private DataType applyUserDefinedTypeMsSymbol(AbstractUserDefinedTypeMsSymbol symbol)
+ private DataType applyUserDefinedTypeMsSymbol()
throws CancelledException, PdbException {
String name = symbol.getName();
- AbstractMsType mType = applicator.getPdb().getTypeRecord(getTypeRecordNumber());
- MsTypeApplier applier = applicator.getTypeApplier(symbol.getTypeRecordNumber());
+ RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
+ AbstractMsType mType = applicator.getPdb().getTypeRecord(typeRecordNumber);
+ MsTypeApplier applier = applicator.getTypeApplier(typeRecordNumber);
// TODO:... NOT SURE IF WILL ALWAYS BE A DATATYPE OR WILL BE A VARIABLE OR ????
if (applier == null) {
return null;
}
- DataType dataType = applicator.getCompletedDataType(getTypeRecordNumber());
+ DataType dataType = applicator.getCompletedDataType(typeRecordNumber);
if (dataType == null) {
return null;
}
@@ -120,4 +124,14 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
return applicator.resolve(typedef);
}
+ private AbstractUserDefinedTypeMsSymbol getValidatedSymbol(MsSymbolIterator iter,
+ boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractUserDefinedTypeMsSymbol udtSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return udtSymbol;
+ }
+
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/UsingNamespaceSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/UsingNamespaceSymbolApplier.java
new file mode 100644
index 0000000000..3214499564
--- /dev/null
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/UsingNamespaceSymbolApplier.java
@@ -0,0 +1,73 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.util.pdb.pdbapplicator;
+
+import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
+import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
+import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
+import ghidra.util.exception.AssertException;
+import ghidra.util.exception.CancelledException;
+
+/**
+ * Applier for {@link AbstractManagedSymbolWithSlotIndexFieldMsSymbol} symbols.
+ */
+public class UsingNamespaceSymbolApplier extends MsSymbolApplier
+ implements NestableSymbolApplier {
+
+ private AbstractUsingNamespaceMsSymbol symbol;
+
+ /**
+ * Constructor
+ * @param applicator the {@link DefaultPdbApplicator} for which we are working.
+ * @param symbol the symbol for this applier
+ */
+ public UsingNamespaceSymbolApplier(DefaultPdbApplicator applicator,
+ AbstractUsingNamespaceMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ //==============================================================================================
+ //TODO: wondering if this can be seen in direct (non-nested use), like file-static. Need
+ // to study data. If so, make sure has DirectSymbolApplier interface above
+// @Override
+// void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+// // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+// getValidatedSymbol(iter, true);
+// }
+
+ //==============================================================================================
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ // TODO: figure out what needs to be done.
+ }
+ }
+
+ private AbstractUsingNamespaceMsSymbol getValidatedSymbol(
+ MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractUsingNamespaceMsSymbol usingNamespaceSymbol)) {
+ throw new AssertException(
+ "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
+ }
+ return usingNamespaceSymbol;
+ }
+
+}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/WithSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/WithSymbolApplier.java
index 298eb1115f..4b6d4b82b8 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/WithSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/WithSymbolApplier.java
@@ -28,44 +28,47 @@ import ghidra.util.exception.CancelledException;
* because we do not know its usage or have examples, but we have implemented
* the block management portion.
*/
-public class WithSymbolApplier extends MsSymbolApplier {
+public class WithSymbolApplier extends MsSymbolApplier
+ implements BlockNestingSymbolApplier, NestableSymbolApplier { // Not sure about nestable
private AbstractWithMsSymbol symbol;
/**
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
- * @param iter the Iterator containing the symbol sequence being processed
+ * @param symbol the symbol for this applier
*/
- public WithSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
- super(applicator, iter);
- AbstractMsSymbol abstractSymbol = iter.next();
- if (!(abstractSymbol instanceof AbstractWithMsSymbol)) {
+ public WithSymbolApplier(DefaultPdbApplicator applicator, AbstractWithMsSymbol symbol) {
+ super(applicator);
+ this.symbol = symbol;
+ }
+
+ // TODO: evaluate whether this can be applied directly to a program
+// @Override
+// public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
+// getValidatedSymbol(iter, true);
+// // TODO: We do not know if this can be applied to a program or not. We have no examples.
+// pdbLogAndInfoMessage(this,
+// "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
+// }
+
+ @Override
+ public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
+ throws PdbException, CancelledException {
+ getValidatedSymbol(iter, true);
+ if (applyToApplier instanceof AbstractBlockContextApplier applier) {
+ Address address = applicator.getAddress(symbol);
+ applier.beginBlock(address, symbol.getExpression(), symbol.getLength());
+ }
+ }
+
+ private AbstractWithMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
+ AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
+ if (!(abstractSymbol instanceof AbstractWithMsSymbol withSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
- symbol = (AbstractWithMsSymbol) abstractSymbol;
+ return withSymbol;
}
- @Override
- void apply() throws PdbException, CancelledException {
- // TODO: We do not know if this can be applied to a program or not. We have no examples.
- pdbLogAndInfoMessage(this,
- "Cannot apply " + this.getClass().getSimpleName() + " directly to program");
- }
-
- @Override
- void applyTo(MsSymbolApplier applyToApplier) {
- // Do nothing
- }
-
- @Override
- void manageBlockNesting(MsSymbolApplier applierParam) {
- if (applierParam instanceof FunctionSymbolApplier) {
- FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applierParam;
- Address address = applicator.getAddress(symbol);
- // TODO: not sure if getExpression() is correct, but there is no "name."
- functionSymbolApplier.beginBlock(address, symbol.getExpression(), symbol.getLength());
- }
- }
}