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 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 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()); - } - } }