GP-3991 PDB progress on symbol appliers

This commit is contained in:
ghizard 2024-02-06 10:49:27 -05:00
parent e73d2088e4
commit 4bcabe6787
43 changed files with 2088 additions and 1353 deletions

View file

@ -200,7 +200,7 @@ public class PdbQuery {
TaskMonitor monitor = script.getMonitor(); TaskMonitor monitor = script.getMonitor();
monitor.initialize(numModules); 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++) { for (int module = 0; module <= numModules; module++) {
monitor.checkCancelled(); monitor.checkCancelled();
SymbolGroup symbolGroup = new SymbolGroup(pdb, module); SymbolGroup symbolGroup = new SymbolGroup(pdb, module);

View file

@ -125,10 +125,9 @@ public class Module {
* Returns an MsSymbolIterator for the symbols of this module * Returns an MsSymbolIterator for the symbols of this module
* @return the iterator * @return the iterator
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws IOException upon error reading stream
* @throws PdbException upon invalid cvSignature * @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 startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber);
int lengthSymbols = moduleInformation.getSizeLocalSymbolsDebugInformation(); int lengthSymbols = moduleInformation.getSizeLocalSymbolsDebugInformation();
return new MsSymbolIterator(pdb, streamNumber, startingOffset, lengthSymbols); return new MsSymbolIterator(pdb, streamNumber, startingOffset, lengthSymbols);
@ -329,7 +328,7 @@ public class Module {
private void dumpSymbols(Writer writer) throws IOException, CancelledException, PdbException { private void dumpSymbols(Writer writer) throws IOException, CancelledException, PdbException {
writer.write("Symbols-----------------------------------------------------"); writer.write("Symbols-----------------------------------------------------");
MsSymbolIterator symbolIter = iterator(); MsSymbolIterator symbolIter = getSymbolIterator();
while (symbolIter.hasNext()) { while (symbolIter.hasNext()) {
pdb.checkCancelled(); pdb.checkCancelled();
AbstractMsSymbol symbol = symbolIter.next(); AbstractMsSymbol symbol = symbolIter.next();

View file

@ -560,6 +560,7 @@ public abstract class PdbDebugInfo {
for (ModuleInformation moduleInformation : moduleInformationList) { for (ModuleInformation moduleInformation : moduleInformationList) {
pdb.checkCancelled(); pdb.checkCancelled();
Module module = new Module(pdb, moduleInformation); Module module = new Module(pdb, moduleInformation);
// Indices: module #1 goes into index 0 and so on.
modules.add(module); modules.add(module);
} }
} }
@ -574,7 +575,8 @@ public abstract class PdbDebugInfo {
* @return the module * @return the module
*/ */
public Module getModule(int moduleNum) { 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 CancelledException upon user cancellation
* @throws PdbException upon not enough data left to parse * @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); 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 * @return an iterator over all symbols of the module
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon not enough data left to parse * @throws PdbException upon not enough data left to parse
* @throws IOException upon issue reading the stream
*/ */
MsSymbolIterator getSymbolIterator(int moduleNum) public MsSymbolIterator getSymbolIterator(int moduleNum)
throws CancelledException, PdbException, IOException { throws CancelledException, PdbException {
Module module = modules.get(moduleNum); Module module = getModule(moduleNum);
return module.iterator(); return module.getSymbolIterator();
} }
private void dumpSymbols(Writer writer) throws CancelledException, IOException, PdbException { private void dumpSymbols(Writer writer) throws CancelledException, IOException, PdbException {

View file

@ -175,15 +175,20 @@ public class SymbolRecords {
* @param streamNumber the stream number * @param streamNumber the stream number
* @return the space * @return the space
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws IOException upon error reading from file
* @throws PdbException upon processing error * @throws PdbException upon processing error
*/ */
public int getCvSigLength(int streamNumber) public int getCvSigLength(int streamNumber)
throws CancelledException, IOException, PdbException { throws CancelledException, PdbException {
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) { if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
return 0; // returning inconsequential value; fact of NIL will be dealt with elsewhere 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) { if (getSig) {
cvSignature = reader.parseInt(); cvSignature = reader.parseInt();
} }

View file

@ -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 * Note: we do not necessarily understand each of these symbol type classes. Refer to the
* base class for more information. * base class for more information.
*/ */
public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol public abstract class AbstractThunkMsSymbol extends AbstractProcedureMsSymbol {
implements AddressMsSymbol, NameMsSymbol {
public enum Ordinal { public enum Ordinal {
NOTYPE("", 0), NOTYPE("", 0),
@ -115,6 +113,7 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the parent pointer. * Returns the parent pointer.
* @return Parent pointer. * @return Parent pointer.
*/ */
@Override
public long getParentPointer() { public long getParentPointer() {
return parentPointer; return parentPointer;
} }
@ -123,6 +122,7 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the end pointer. * Returns the end pointer.
* @return End pointer. * @return End pointer.
*/ */
@Override
public long getEndPointer() { public long getEndPointer() {
return endPointer; return endPointer;
} }
@ -131,10 +131,47 @@ public abstract class AbstractThunkMsSymbol extends AbstractMsSymbol
* Returns the next pointer * Returns the next pointer
* @return Next pointer. * @return Next pointer.
*/ */
@Override
public long getNextPointer() { public long getNextPointer() {
return nextPointer; 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. * Returns the offset.
* @return Offset. * @return Offset.

View file

@ -141,7 +141,7 @@ public class SeparatedCodeFromCompilerSupportMsSymbol extends AbstractMsSymbol
* Returns the parent segment. * Returns the parent segment.
* @return Parent segment. * @return Parent segment.
*/ */
public long getSegmentParent() { public int getSegmentParent() {
return sectionParent; return sectionParent;
} }

View file

@ -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.
* <p>
* 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<Register, Integer> 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;
}
}
}

View file

@ -22,6 +22,7 @@ import ghidra.app.cmd.comments.SetCommentCmd;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
/** /**
* Manages the nesting of scoping blocks for functions and scoped variables. * Manages the nesting of scoping blocks for functions and scoped variables.
@ -120,10 +121,17 @@ public class BlockCommentsManager {
CodeUnit.PRE_COMMENT); CodeUnit.PRE_COMMENT);
} }
for (Map.Entry<Address, String> entry : blockPostComments.entrySet()) { for (Map.Entry<Address, String> entry : blockPostComments.entrySet()) {
Address endCodeUnitAddress = program.getListing().getCodeUnitContaining( CodeUnit codeUnit = program.getListing()
entry.getKey().add(addressDelta)).getAddress(); .getCodeUnitContaining(
appendBlockComment(program, endCodeUnitAddress, entry.getValue(), entry.getKey().add(addressDelta));
CodeUnit.POST_COMMENT); if (codeUnit == null) {
Msg.warn(this, "PDB error: null Code unit");
}
else {
Address endCodeUnitAddress = codeUnit.getAddress();
appendBlockComment(program, endCodeUnitAddress, entry.getValue(),
CodeUnit.POST_COMMENT);
}
} }
} }

View file

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

View file

@ -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
}

View file

@ -26,52 +26,38 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractBlockMsSymbol} symbols. * Applier for {@link AbstractBlockMsSymbol} symbols.
*/ */
public class BlockSymbolApplier extends MsSymbolApplier { public class BlockSymbolApplier extends MsSymbolApplier
implements BlockNestingSymbolApplier, NestableSymbolApplier {
private AbstractBlockMsSymbol symbol; private AbstractBlockMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public BlockSymbolApplier(DefaultPdbApplicator applicator, AbstractBlockMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractBlockMsSymbol)) { }
@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( throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName()); "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());
}
}
} }

View file

@ -29,27 +29,39 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractDataMsSymbol} symbols. * Applier for {@link AbstractDataMsSymbol} symbols.
*/ */
public class DataSymbolApplier extends MsSymbolApplier { public class DataSymbolApplier extends MsSymbolApplier
implements DirectSymbolApplier, NestableSymbolApplier {
private AbstractDataMsSymbol symbol; private AbstractDataMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public DataSymbolApplier(DefaultPdbApplicator applicator, AbstractDataMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractDataMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractDataMsSymbol) abstractSymbol;
} }
@Override @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) { if (applyToApplier instanceof FunctionSymbolApplier) {
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier; FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
DataType dataType = applicator.getCompletedDataType(symbol.getTypeRecordNumber()); DataType dataType = applicator.getCompletedDataType(symbol.getTypeRecordNumber());
@ -57,37 +69,28 @@ public class DataSymbolApplier extends MsSymbolApplier {
return; // silently return. return; // silently return.
} }
Address address = applicator.getAddress(symbol); Address address = applicator.getAddress(symbol);
if (!createData(address, dataType)) { if (!createData(symbol, address, dataType)) {
return; return;
} }
functionSymbolApplier.setLocalVariable(address, symbol.getName(), dataType); functionSymbolApplier.setLocalVariable(address, symbol.getName(), dataType);
} }
} }
@Override MsTypeApplier getTypeApplier(AbstractMsSymbol abstractSymbol) {
void apply() throws CancelledException, PdbException { if (!(abstractSymbol instanceof AbstractDataMsSymbol symbol)) {
Address symbolAddress = applicator.getAddress(symbol); throw new AssertException(
if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) { "Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
return;
} }
RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
if (!createData(symbolAddress, typeRecordNumber)) {
return;
}
applicator.createSymbol(symbolAddress, symbol.getName(), true);
}
MsTypeApplier getTypeApplier() {
return applicator.getTypeApplier(symbol.getTypeRecordNumber()); return applicator.getTypeApplier(symbol.getTypeRecordNumber());
} }
boolean createData(Address address, RecordNumber typeRecordNumber) boolean createData(AbstractDataMsSymbol symbol, Address address, RecordNumber typeRecordNumber)
throws CancelledException, PdbException { throws CancelledException, PdbException {
DataType dataType = applicator.getCompletedDataType(symbol.getTypeRecordNumber()); DataType dataType = applicator.getCompletedDataType(typeRecordNumber);
return createData(address, dataType); 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())) { if (applicator.isInvalidAddress(address, symbol.getName())) {
return false; return false;
} }
@ -266,4 +269,13 @@ public class DataSymbolApplier extends MsSymbolApplier {
return datatype1.isEquivalent(datatype2); 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;
}
} }

View file

@ -141,6 +141,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
private PdbCategories categoryUtils; private PdbCategories categoryUtils;
private PdbPrimitiveTypeApplicator pdbPrimitiveTypeApplicator; private PdbPrimitiveTypeApplicator pdbPrimitiveTypeApplicator;
private TypeApplierFactory typeApplierParser; 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<Integer, Long> dataTypeIdByMsTypeNum; private Map<Integer, Long> dataTypeIdByMsTypeNum;
private Map<Integer, DataTypeImpl> dataTypeImplByMsTypeNum; private Map<Integer, DataTypeImpl> dataTypeImplByMsTypeNum;
private Map<Integer, CppCompositeType> classTypeByMsTypeNum; private Map<Integer, CppCompositeType> classTypeByMsTypeNum;
@ -223,6 +226,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
if (program != null) { if (program != null) {
// TODO: if I'm PDB Universal Analyzer #1, schedule PDD Universal Analyzer #2; for now,
// just calling doDeferred here.
doDeferredProgramProcessing(); doDeferredProgramProcessing();
// Mark PDB analysis as complete. // Mark PDB analysis as complete.
Options options = program.getOptions(Program.PROGRAM_INFO); 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(); disassembleFunctions();
doDeferredFunctionProcessing(); doDeferredFunctionProcessing();
} }
@ -288,12 +293,19 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Do work, such as create parameters or local variables and scopes * Do work, such as create parameters or local variables and scopes
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon not enough data left to parse
*/ */
private void doDeferredFunctionProcessing() throws CancelledException { private void doDeferredFunctionProcessing() throws CancelledException, PdbException {
for (DeferrableFunctionSymbolApplier applier : deferredFunctionWorkAppliers) { if (applicatorOptions.getProcessingControl() == PdbApplicatorControl.DATA_TYPES_ONLY) {
cancelOnlyWrappingMonitor.checkCancelled(); return;
applier.doDeferredProcessing();
} }
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 // 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 // used the normalized address when creating the one-byte function
disassembleAddresses.add(applier.getAddress()); disassembleAddresses.add(address);
//deferredFunctionWorkAppliers.add(applier);
} }
//============================================================================================== //==============================================================================================
@ -1536,6 +1554,61 @@ public class DefaultPdbApplicator implements PdbApplicator {
currentModuleNumber = moduleNumber; 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 { private void processModuleSymbols() throws CancelledException, PdbException {
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo == null) { if (debugInfo == null) {
@ -1596,7 +1669,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
TaskMonitor monitor = getMonitor(); TaskMonitor monitor = getMonitor();
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
procSym(iter); procSymNew(iter);
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
} }
@ -1635,7 +1708,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
break; break;
} }
pdbApplicatorMetrics.witnessPublicSymbolType(iter.peek()); pdbApplicatorMetrics.witnessPublicSymbolType(iter.peek());
procSym(iter); procSymNew(iter);
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
@ -1674,15 +1747,16 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
SymbolGroup symbolGroup = getSymbolGroup(); // SymbolGroup symbolGroup = getSymbolGroup();
if (symbolGroup == null) { // if (symbolGroup == null) {
return; // return;
} // }
//
TaskMonitor monitor = getMonitor(); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying global symbols..."); monitor.setMessage("PDB: Applying global symbols...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
MsSymbolIterator iter = symbolGroup.getSymbolIterator(); // MsSymbolIterator iter = symbolGroup.getSymbolIterator();
MsSymbolIterator iter = debugInfo.getSymbolIterator();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
@ -1695,7 +1769,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
pdbApplicatorMetrics.witnessGlobalSymbolType(symbol); pdbApplicatorMetrics.witnessGlobalSymbolType(symbol);
if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here
procSym(iter); // procSym(iter);
procSymNew(iter);
} }
monitor.incrementProgress(1); 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<Long> 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 * Process global typdef symbols
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
@ -1755,7 +1857,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
if (symbol instanceof AbstractUserDefinedTypeMsSymbol) { // Doing typedefs here if (symbol instanceof AbstractUserDefinedTypeMsSymbol) { // Doing typedefs here
procSym(iter); procSymNew(iter);
} }
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
@ -1825,7 +1927,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
monitor.checkCancelled(); monitor.checkCancelled();
iter.initGetByOffset(offset); iter.initGetByOffset(offset);
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
procSym(iter); procSymNew(iter);
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
} }
@ -1872,7 +1974,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek()); pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek());
procSym(iter); procSymNew(iter);
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
return true; return true;
@ -1994,7 +2096,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
monitor.checkCancelled(); monitor.checkCancelled();
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
if (symbol instanceof AbstractThunkMsSymbol) { if (symbol instanceof AbstractThunkMsSymbol) {
procSym(iter); procSymNew(iter);
} }
else { else {
iter.next(); iter.next();
@ -2013,11 +2115,32 @@ public class DefaultPdbApplicator implements PdbApplicator {
return symbolApplierParser.getSymbolApplier(iter); 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 { try {
MsSymbolApplier applier = getSymbolApplier(iter); MsSymbolApplier applier = getSymbolApplier(iter);
applier.apply(); if (applier instanceof DirectSymbolApplier directApplier) {
directApplier.apply(iter);
}
else {
iter.next();
}
} }
catch (PdbException e) { catch (PdbException e) {
// skipping symbol // 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; return newSymbol;
} }
private boolean addToPlateUnique(Address address, String comment) { public boolean addToPlateUnique(Address address, String comment) {
if (StringUtils.isBlank(comment)) { if (StringUtils.isBlank(comment)) {
return false; return false;
} }

View file

@ -15,27 +15,36 @@
*/ */
package ghidra.app.util.pdb.pdbapplicator; 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.program.model.address.Address;
import ghidra.util.exception.CancelledException;
/** /**
* Interface class for MsSymbolApplier that has deferrable function work. * Interface class for MsSymbolApplier that has deferrable function work.
*/ */
interface DeferrableFunctionSymbolApplier { interface DeferrableFunctionSymbolApplier extends DirectSymbolApplier {
/**
* 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();
/** /**
* Deferred work for the MsSymbolApplier that can only be applied after all functions * 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 * have been created and disassembled. Examples would be setting local variables and
* parameters * 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() { public void deferredApply(MsSymbolIterator iter) throws PdbException, CancelledException;
// do nothing
}
/**
* 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();
} }

View file

@ -24,38 +24,30 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractDefinedSingleAddressRangeMsSymbol} symbols. * Applier for {@link AbstractDefinedSingleAddressRangeMsSymbol} symbols.
*/ */
public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier { public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier
implements NestableSymbolApplier {
private AbstractDefinedSingleAddressRangeMsSymbol symbol; private AbstractDefinedSingleAddressRangeMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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, public DefinedSingleAddressRangeSymbolApplier(DefaultPdbApplicator applicator,
MsSymbolIterator iter) { AbstractDefinedSingleAddressRangeMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractDefinedSingleAddressRangeMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractDefinedSingleAddressRangeMsSymbol) abstractSymbol;
} }
@Override @Override
void apply() throws PdbException, CancelledException { public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
pdbLogAndInfoMessage(this, throws PdbException, CancelledException {
"Cannot apply " + this.getClass().getSimpleName() + " directly to program"); getValidatedSymbol(iter, true);
}
@Override
void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
if (applyToApplier instanceof LocalOptimizedSymbolApplier) { if (applyToApplier instanceof LocalOptimizedSymbolApplier) {
// TODO: eventually apply. // TODO: eventually apply.
// LocalOptimizedSymbolApplier localSymbolApplier = // LocalOptimizedSymbolApplier localSymbolApplier =
// (LocalOptimizedSymbolApplier) applyToApplier; // (LocalOptimizedSymbolApplier) applyToApplier;
symbol.getAddressRange(); symbol.getAddressRange();
symbol.getAddressGapList(); symbol.getAddressGapList();
if (symbol instanceof EnregisteredSymbolDARMsSymbol) { 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;
}
} }

View file

@ -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;
}

View file

@ -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.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; 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.AssertException;
import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link EndMsSymbol} symbols. * Applier for {@link EndMsSymbol} symbols.
*/ */
public class EndSymbolApplier extends MsSymbolApplier { public class EndSymbolApplier extends MsSymbolApplier
implements BlockNestingSymbolApplier, NestableSymbolApplier {
private EndMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public EndSymbolApplier(DefaultPdbApplicator applicator, EndMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof EndMsSymbol || }
abstractSymbol instanceof ProcedureIdEndMsSymbol)) {
@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( throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName()); "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();
}
}
} }

View file

@ -25,36 +25,42 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link ExtraFrameAndProcedureInformationMsSymbol} symbols. * Applier for {@link ExtraFrameAndProcedureInformationMsSymbol} symbols.
*/ */
public class FrameAndProcedureInformationSymbolApplier extends MsSymbolApplier { public class FrameAndProcedureInformationSymbolApplier extends MsSymbolApplier
implements NestableSymbolApplier {
private ExtraFrameAndProcedureInformationMsSymbol symbol; private ExtraFrameAndProcedureInformationMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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, public FrameAndProcedureInformationSymbolApplier(DefaultPdbApplicator applicator,
MsSymbolIterator iter) { ExtraFrameAndProcedureInformationMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof ExtraFrameAndProcedureInformationMsSymbol)) { }
@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( throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName()); "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
}
} }

View file

@ -15,8 +15,6 @@
*/ */
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
import java.util.*;
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd; import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
import ghidra.app.cmd.function.CallDepthChangeInfo; import ghidra.app.cmd.function.CallDepthChangeInfo;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; 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. * Applier for {@link AbstractProcedureStartMsSymbol} and {@link AbstractThunkMsSymbol} symbols.
*/ */
public class FunctionSymbolApplier extends MsSymbolApplier public class FunctionSymbolApplier extends AbstractBlockContextApplier
implements DeferrableFunctionSymbolApplier { 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; private Address currentBlockAddress;
// might not need this, but investigating whether it will help us. TODO remove? // might not need this, but investigating whether it will help us. TODO remove?
private int baseParamOffset = 0; private int baseParamOffset = 0;
// private List<RegisterRelativeSymbolApplier> stackVariableAppliers = new ArrayList<>();
private List<MsSymbolApplier> allAppliers = new ArrayList<>();
private RegisterChangeCalculator registerChangeCalculator; private RegisterChangeCalculator registerChangeCalculator;
private AbstractProcedureMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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
* @throws CancelledException upon user cancellation
*/ */
public FunctionSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) public FunctionSymbolApplier(DefaultPdbApplicator applicator,
throws CancelledException { AbstractProcedureMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
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);
}
} }
//==============================================================================================
@Override @Override
void manageBlockNesting(MsSymbolApplier applierParam) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
if (applierParam instanceof FunctionSymbolApplier) { // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applierParam; getValidatedSymbol(iter, true);
if (procedureSymbol != null) { processSymbol(iter);
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());
}
}
} }
long getLength() { private void processSymbol(MsSymbolIterator iter)
if (procedureSymbol != null) { throws CancelledException, PdbException {
return procedureSymbol.getProcedureLength();
}
else if (thunkSymbol != null) {
return thunkSymbol.getLength();
}
throw new AssertException("Unexpected Symbol type");
}
/** Address address = applicator.getAddress(symbol);
* Returns the {@link Function} for this applier. String name = symbol.getName();
* @return the Function
*/
Function getFunction() {
return function;
}
/** // Regardless of ability to apply this symbol, we need to progress through symbols to the
* Returns the current frame size. // matching "end" symbol before we return
* @return the current frame size. if (!processEndSymbol(symbol.getEndPointer(), iter)) {
*/ applicator.appendLogMsg("PDB: Failed to process function at address " + address);
long getCurrentFrameSize() { return;
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;
} }
boolean functionSuccess = applyFunction(monitor); if (applicator.isInvalidAddress(address, name)) {
if (functionSuccess == false) { applicator.appendLogMsg("PDB: Failed to process function at address: " + address);
return false; return;
}
registerChangeCalculator = new RegisterChangeCalculator(procedureSymbol, function, monitor);
baseParamOffset = VariableUtilities.getBaseStackParamOffset(function);
for (MsSymbolApplier applier : allAppliers) {
applier.applyTo(this);
} }
// comments Function function = applicator.getExistingOrCreateOneByteFunction(address);
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);
if (function == null) { if (function == null) {
return false; return;
} }
applicator.scheduleDeferredFunctionWork(this);
boolean succeededSetFunctionSignature = false; // Collecting all addresses from all functions to do one large bulk disassembly of the
if (thunkSymbol == null) { // complete AddressSet of function addresses. We could consider removing this logic
if (function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) { // of collecting them all for bulk disassembly and do individual disassembly at the
function.setThunkedFunction(null); // same deferred point in time.
succeededSetFunctionSignature = setFunctionDefinition(monitor); applicator.scheduleDisassembly(address);
function.setNoReturn(isNonReturning);
} boolean succeededSetFunctionSignature = setFunctionDefinition(function, address);
}
// If signature was set, then override existing primary mangled symbol with // 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 global symbol that provided this signature so that Demangler does not overwrite
// the richer data type we get with global symbols. // the richer data type we get with global symbols.
applicator.createSymbol(address, getName(), succeededSetFunctionSignature); applicator.createSymbol(address, name, succeededSetFunctionSignature);
currentFrameSize = 0;
return true;
} }
/** /**
* Sets function signature * returns true only if we set a function signature
* @param monitor monitor
* @return true if function signature was set * @return true if function signature was set
* @throws CancelledException upon user cancellation
* @throws PdbException upon processing error * @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 { throws CancelledException, PdbException {
if (procedureSymbol == null) {
// TODO: is there anything we can do with thunkSymbol? RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
// long x = thunkSymbol.getParentPointer(); 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; return false;
} }
// Rest presumes procedureSymbol.
RecordNumber typeRecordNumber = procedureSymbol.getTypeRecordNumber(); // Since the thunk detection algorithms are overly aggressive and make mistakes, we
MsTypeApplier applier = applicator.getTypeApplier(typeRecordNumber); // are specifically clearing the value to override these false positives
function.setThunkedFunction(null);
function.setNoReturn(isNonReturning());
AbstractMsType fType = applicator.getPdb().getTypeRecord(typeRecordNumber); AbstractMsType fType = applicator.getPdb().getTypeRecord(typeRecordNumber);
MsTypeApplier applier = applicator.getTypeApplier(fType);
if (!(applier instanceof AbstractFunctionTypeApplier)) { if (!(applier instanceof AbstractFunctionTypeApplier)) {
if (!((applier instanceof PrimitiveTypeApplier prim) && prim.isNoType(fType))) { applicator.appendLogMsg("Error: Failed to resolve datatype RecordNumber " +
applicator.appendLogMsg("Error: Failed to resolve datatype RecordNumber " + typeRecordNumber + " at " + address_x);
typeRecordNumber + " at " + address);
}
return false; return false;
} }
@ -330,6 +162,7 @@ public class FunctionSymbolApplier extends MsSymbolApplier
} }
ApplyFunctionSignatureCmd sigCmd = ApplyFunctionSignatureCmd sigCmd =
new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED); new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED);
TaskMonitor monitor = applicator.getCancelOnlyWrappingMonitor();
if (!sigCmd.applyTo(applicator.getProgram(), monitor)) { if (!sigCmd.applyTo(applicator.getProgram(), monitor)) {
applicator.appendLogMsg( applicator.appendLogMsg(
"PDB Warning: Failed to apply signature to function at address " + address + "PDB Warning: Failed to apply signature to function at address " + address +
@ -339,58 +172,92 @@ public class FunctionSymbolApplier extends MsSymbolApplier
return true; 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) { * Returns the {@link Function} for this applier.
applicator.appendLogMsg( * @return the Function
"Block Nesting went negative for " + getName() + " at " + address); */
} Function getFunction() {
if (symbolBlockNestingLevel == 0) { return function_x;
//currentFunctionSymbolApplier = null;
}
return symbolBlockNestingLevel;
} }
void beginBlock(Address startAddress, String name, long length) { /**
* Returns the current frame size.
int nestingLevel = beginBlock(startAddress); * @return the current frame size.
if (!applicator.getPdbApplicatorOptions().applyCodeScopeBlockComments()) { */
return; long getCurrentFrameSize() {
} return currentFrameSize_x;
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; * Returns the frame size as specified by the PDB
++symbolBlockNestingLevel; * @return the frame size.
return symbolBlockNestingLevel; */
long getSpecifiedFrameSize() {
return specifiedFrameSize_x;
} }
private String getIndent(int indentLevel) { /**
String indent = ""; * Set the specified frame size.
for (int i = 1; i < indentLevel; i++) { * @param specifiedFrameSize the frame size.
indent += BLOCK_INDENT; */
@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) // 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 { private int getFrameBaseOffset(TaskMonitor monitor) throws CancelledException {
int retAddrSize = function.getProgram().getDefaultPointerSize(); int retAddrSize = function_x.getProgram().getDefaultPointerSize();
if (retAddrSize != 8) { if (retAddrSize != 8) {
// don't do this for 32 bit. // don't do this for 32 bit.
return -retAddrSize; // 32 bit has a -4 byte offset return -retAddrSize; // 32 bit has a -4 byte offset
} }
Register frameReg = function.getProgram().getCompilerSpec().getStackPointer(); Register frameReg = function_x.getProgram().getCompilerSpec().getStackPointer();
Address entryAddr = function.getEntryPoint(); Address entryAddr = function_x.getEntryPoint();
AddressSet scopeSet = new AddressSet(); AddressSet scopeSet = new AddressSet();
scopeSet.addRange(entryAddr, entryAddr.add(64)); scopeSet.addRange(entryAddr, entryAddr.add(64));
CallDepthChangeInfo valueChange = CallDepthChangeInfo valueChange =
new CallDepthChangeInfo(function, scopeSet, frameReg, monitor); new CallDepthChangeInfo(function_x, scopeSet, frameReg, monitor);
InstructionIterator instructions = InstructionIterator instructions =
function.getProgram().getListing().getInstructions(scopeSet, true); function_x.getProgram().getListing().getInstructions(scopeSet, true);
int max = 0; int max = 0;
while (instructions.hasNext()) { while (instructions.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
Instruction next = instructions.next(); Instruction next = instructions.next();
int newValue = valueChange.getDepth(next.getMinAddress()); 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)) { if (newValue < -(20 * 1024) || newValue > (20 * 1024)) {
continue; continue;
} }
@ -433,55 +302,44 @@ public class FunctionSymbolApplier extends MsSymbolApplier
return max; return max;
} }
private static class RegisterChangeCalculator { //==============================================================================================
private Map<Register, Integer> 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 @Override
public void doDeferredProcessing() { long getEndOffset() {
// TODO: return symbol.getDebugEndOffset();
// Try to processes parameters, locals, scopes if applicable.
} }
@Override private boolean isNonReturning() {
public Address getAddress() { if (symbol instanceof AbstractProcedureStartMsSymbol procMs) {
return address; 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;
} }
} }

View file

@ -32,28 +32,25 @@ import ghidra.util.task.TaskMonitor;
/** /**
* Applier for {@link AbstractLabelMsSymbol} symbols. * Applier for {@link AbstractLabelMsSymbol} symbols.
*/ */
public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFunctionSymbolApplier { public class LabelSymbolApplier extends MsSymbolApplier
implements DirectSymbolApplier, NestableSymbolApplier {
private AbstractLabelMsSymbol symbol; private AbstractLabelMsSymbol symbol;
private Function function = null;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public LabelSymbolApplier(DefaultPdbApplicator applicator, AbstractLabelMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractLabelMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractLabelMsSymbol) abstractSymbol;
} }
@Override @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), // 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, // 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 // 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 @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(); String label = getLabel();
if (label == null) { if (label == null) {
return; return;
@ -159,11 +159,11 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
private boolean applyFunction(Address address, String name, TaskMonitor monitor) { private boolean applyFunction(Address address, String name, TaskMonitor monitor) {
applicator.createSymbol(address, name, true); applicator.createSymbol(address, name, true);
function = applicator.getExistingOrCreateOneByteFunction(address); Function function = applicator.getExistingOrCreateOneByteFunction(address);
if (function == null) { if (function == null) {
return false; return false;
} }
applicator.scheduleDeferredFunctionWork(this); applicator.scheduleDisassembly(address);
if (!function.isThunk() && if (!function.isThunk() &&
function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) { function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) {
@ -198,8 +198,13 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
return label; return label;
} }
@Override private AbstractLabelMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
public Address getAddress() { AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
return applicator.getAddress(symbol); if (!(abstractSymbol instanceof AbstractLabelMsSymbol labelSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
return labelSymbol;
} }
} }

View file

@ -24,55 +24,61 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractLocalSymbolInOptimizedCodeMsSymbol} symbols. * Applier for {@link AbstractLocalSymbolInOptimizedCodeMsSymbol} symbols.
*/ */
public class LocalOptimizedSymbolApplier extends MsSymbolApplier { public class LocalOptimizedSymbolApplier extends MsSymbolApplier
implements NestingSymbolApplier, NestableSymbolApplier {
private AbstractLocalSymbolInOptimizedCodeMsSymbol symbol; private AbstractLocalSymbolInOptimizedCodeMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public LocalOptimizedSymbolApplier(DefaultPdbApplicator applicator,
super(applicator, iter); AbstractLocalSymbolInOptimizedCodeMsSymbol symbol) {
AbstractMsSymbol abstractSymbol = iter.next(); super(applicator);
if (!(abstractSymbol instanceof AbstractLocalSymbolInOptimizedCodeMsSymbol)) { this.symbol = symbol;
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractLocalSymbolInOptimizedCodeMsSymbol) abstractSymbol;
} }
@Override @Override
void apply() throws PdbException, CancelledException { public void applyTo(NestingSymbolApplier applyToApplier, MsSymbolIterator iter)
pdbLogAndInfoMessage(this, throws PdbException, CancelledException {
"Cannot apply " + this.getClass().getSimpleName() + " directly to program"); getValidatedSymbol(iter, true);
}
@Override
void applyTo(MsSymbolApplier applyToApplier) throws PdbException, CancelledException {
if (!applicator.getPdbApplicatorOptions().applyFunctionVariables()) { if (!applicator.getPdbApplicatorOptions().applyFunctionVariables()) {
return; return;
} }
if (applyToApplier instanceof FunctionSymbolApplier) { if (applyToApplier instanceof FunctionSymbolApplier) {
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier; FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applyToApplier;
doWork(functionSymbolApplier); doWork(functionSymbolApplier, iter);
} }
} }
private void doWork(FunctionSymbolApplier functionSymbolApplier) private void doWork(FunctionSymbolApplier functionSymbolApplier, MsSymbolIterator iter)
throws CancelledException, PdbException { throws CancelledException, PdbException {
getValidatedSymbol(iter, true);
// TODO: Not doing anything with the information yet. // TODO: Not doing anything with the information yet.
symbol.getLocalVariableFlags(); symbol.getLocalVariableFlags();
symbol.getName(); symbol.getName();
symbol.getTypeRecordNumber(); symbol.getTypeRecordNumber();
while (iter.hasNext() && while (iter.hasNext() &&
(iter.peek() instanceof AbstractDefinedSingleAddressRangeMsSymbol)) { (iter.peek() instanceof AbstractDefinedSingleAddressRangeMsSymbol subSymbol)) {
applicator.checkCancelled(); applicator.checkCancelled();
DefinedSingleAddressRangeSymbolApplier rangeApplier = MsSymbolApplier applier = applicator.getSymbolApplier(subSymbol, iter);
new DefinedSingleAddressRangeSymbolApplier(applicator, iter); if (!(applier instanceof DefinedSingleAddressRangeSymbolApplier rangeApplier)) {
rangeApplier.applyTo(this); 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;
}
} }

View file

@ -15,8 +15,6 @@
*/ */
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
import java.util.*;
import ghidra.app.cmd.function.CallDepthChangeInfo; import ghidra.app.cmd.function.CallDepthChangeInfo;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator; 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.PdbException;
@ -48,20 +46,8 @@ import ghidra.util.task.TaskMonitor;
/** /**
* Applier for {@link AbstractManagedProcedureMsSymbol} symbols. * Applier for {@link AbstractManagedProcedureMsSymbol} symbols.
*/ */
public class ManagedProcedureSymbolApplier extends MsSymbolApplier public class ManagedProcedureSymbolApplier extends AbstractBlockContextApplier
implements DeferrableFunctionSymbolApplier { implements BlockNestingSymbolApplier {
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;
private int symbolBlockNestingLevel; private int symbolBlockNestingLevel;
private Address currentBlockAddress; 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? // might not need this, but investigating whether it will help us. TODO remove?
private int baseParamOffset = 0; private int baseParamOffset = 0;
// private List<RegisterRelativeSymbolApplier> stackVariableAppliers = new ArrayList<>(); private AbstractManagedProcedureMsSymbol symbol;
private List<MsSymbolApplier> allAppliers = new ArrayList<>(); // TODO: We are having difficulty figuring out how to process these... actually not getting
private RegisterChangeCalculator registerChangeCalculator; // correct addresses in some situations. This flag allows us to bypass this symbol and
// its nested symbols.
private boolean developerStillHavingProblemProcessingThese = true;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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
* @throws CancelledException upon user cancellation
*/ */
public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator,
throws CancelledException { AbstractManagedProcedureMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
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);
}
} }
@Override @Override
void manageBlockNesting(MsSymbolApplier applierParam) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
ManagedProcedureSymbolApplier procedureSymbolApplier = getValidatedSymbol(iter, true);
(ManagedProcedureSymbolApplier) applierParam; processSymbol(iter);
long start = procedureSymbol.getDebugStartOffset(); }
long end = procedureSymbol.getDebugEndOffset();
// 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); Address blockAddress = address.add(start);
long length = end - 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);
} }
/** // private void deferredProcessing(MsSymbolIterator iter)
* Returns the {@link Function} for this applier. // throws CancelledException, PdbException {
* @return the Function //
*/ // long currentFrameSize = 0;
Function getFunction() { //
return function; //// symbolBlockNestingLevel = 0;
} //// BlockCommentsManager comments = new BlockCommentsManager();
//// currentBlockAddress = null;
/** //
* Returns the current frame size. // // TODO: Remove the witness call once we effectively process this class of symbols
* @return the current frame size. // // See that the applyTo() method is much unimplemented.
*/ // applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol);
long getCurrentFrameSize() { //
return currentFrameSize; // Address specifiedAddress = applicator.getRawAddress(symbol);
} // Address address = applicator.getAddress(symbol);
// boolean isNonReturning = symbol.getFlags().doesNotReturn();
/** //
* Returns the frame size as specified by the PDB // initContext();
* @return the frame size. // applyTo(this, context, iter);
*/ //
long getSpecifiedFrameSize() { //// TaskMonitor monitor = applicator.getCancelOnlyWrappingMonitor();
return specifiedFrameSize; //// RegisterChangeCalculator registerChangeCalculator =
} //// new RegisterChangeCalculator(symbol, function, monitor);
////
/** //// // TODO: need to decide how/where these get passed around... either we pass the function
* Set the specified frame size. //// // around or pass things in the blockNestingContext or other
* @param specifiedFrameSize the frame size. //// int baseParamOffset = VariableUtilities.getBaseStackParamOffset(function_x);
*/ //// long currentFrameSize = 0;
void setSpecifiedFrameSize(long specifiedFrameSize) { //
this.specifiedFrameSize = specifiedFrameSize; // while (notDone(context, iter)) {
currentFrameSize = specifiedFrameSize; // applicator.checkCancelled();
} // AbstractMsSymbol subSymbol = iter.peek();
//
/** // // TODO: msSymbol, subSymbol, comments, currentFrameSize, baseParmOffset
* Get the function name //
* @return the function name // MsSymbolApplier applier = applicator.getSymbolApplier(subSymbol, iter);
*/ //// if (applier instanceof BlockNestingSymbolApplier nestingApplier) {
String getName() { //// //nestingApplier.manageBlockNesting(iter, blockNestingContext);
return procedureSymbol.getName(); //// nestingApplier.applyTo(this, context, iter);
} //// }
// if (applier instanceof NestableSymbolApplier nestingApplier) {
@Override // nestingApplier.applyTo(this, iter);
void applyTo(MsSymbolApplier applyToApplier) { // }
// Do nothing. // else {
} // applicator.getPdbApplicatorMetrics().witnessNonNestableSymbolType(subSymbol);
// iter.next();
@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());
// } // }
}
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) { // for (MsSymbolApplier applier : allAppliers) {
// applier.applyTo(this); // applier.applyTo(this);
// } // }
// //
// // comments // boolean functionSuccess = applyFunction(procedureSymbol);
// long addressDelta = address.subtract(specifiedAddress); // if (functionSuccess == false) {
// comments.applyTo(applicator.getProgram(), addressDelta); // return false;
// }
// line numbers //// registerChangeCalculator = new RegisterChangeCalculator(procedureSymbol, function, monitor);
// TODO: not done yet ////
// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program); //// baseParamOffset = VariableUtilities.getBaseStackParamOffset(function);
// applyLineNumbers.applyTo(monitor, log); ////
//// for (MsSymbolApplier applier : allAppliers) {
return true; //// applier.applyTo(this);
} //// }
////
Integer getRegisterPrologChange(Register register) { //// // comments
return registerChangeCalculator.getRegChange(applicator, register); //// long addressDelta = address.subtract(specifiedAddress);
} //// comments.applyTo(applicator.getProgram(), addressDelta);
//
int getBaseParamOffset() { // // line numbers
return baseParamOffset; // // TODO: not done yet
} //// ApplyLineNumbers applyLineNumbers = new ApplyLineNumbers(pdbParser, xmlParser, program);
//// applyLineNumbers.applyTo(monitor, log);
//
// return true;
// }
/** /**
* Sets a local variable (address, name, type) * Sets a local variable (address, name, type)
@ -235,38 +261,59 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return; // silently return. return; // silently return.
} }
// Currently just placing a comment. // Currently just placing a comment.
String comment = getIndent(symbolBlockNestingLevel + 1) + "static local (stored at " + String comment =
address + ") " + dataType.getName() + " " + name; context.getIndent(symbolBlockNestingLevel + 1) + "static local (stored at " +
comments.addPreComment(currentBlockAddress, comment); 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); if (function.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
// return if IMPORTED or USER_DEFINED
function = applicator.getExistingOrCreateOneByteFunction(address);
if (function == null) {
return false; return false;
} }
applicator.scheduleDeferredFunctionWork(this);
if (!function.isThunk() && // Since the thunk detection algorithms are overly aggressive and make mistakes, we
function.getSignatureSource().isLowerPriorityThan(SourceType.IMPORTED)) { // are specifically clearing the value to override these false positives
setFunctionDefinition(monitor); function.setThunkedFunction(null);
function.setNoReturn(isNonReturning);
} function.setNoReturn(isNonReturning());
currentFrameSize = 0;
return true;
}
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. // 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. // TODO: once GP-328 is merged, use static methods to get table and row.
// CliIndexUtils.getTableIdUnencoded(token) and .getRowIdUnencoded(token). // CliIndexUtils.getTableIdUnencoded(token) and .getRowIdUnencoded(token).
int table = (int) (token >> 24) & 0xff; int table = (int) (token >> 24) & 0xff;
@ -338,60 +385,6 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return true; 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) // Method copied from ApplyStackVariables (ghidra.app.util.bin.format.pdb package)
// on 20191119. TODO: Do we need something like this? // 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. * @return stack offset that stack variables will be relative to.
* @throws CancelledException upon user cancellation. * @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(); int retAddrSize = function.getProgram().getDefaultPointerSize();
@ -432,54 +426,28 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
return max; return max;
} }
private static class RegisterChangeCalculator { @Override
long getStartOffset() {
private Map<Register, Integer> registerChangeByRegisterName = new HashMap<>(); return symbol.getDebugStartOffset();
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 @Override
public void doDeferredProcessing() { long getEndOffset() {
// TODO: return symbol.getDebugEndOffset();
// Try to processes parameters, locals, scopes if applicable.
} }
@Override private boolean isNonReturning() {
public Address getAddress() { return symbol.getFlags().doesNotReturn();
return address;
} }
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;
}
} }

View file

@ -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;
}
}

View file

@ -18,9 +18,8 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.Objects; import java.util.Objects;
import ghidra.app.plugin.processors.sleigh.symbol.Symbol; 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.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.exception.CancelledException;
/** /**
* Abstract class representing the applier for a specific {@link AbstractMsSymbol}. The * Abstract class representing the applier for a specific {@link AbstractMsSymbol}. The
@ -31,20 +30,14 @@ import ghidra.util.exception.CancelledException;
*/ */
public abstract class MsSymbolApplier { public abstract class MsSymbolApplier {
protected DefaultPdbApplicator applicator; protected DefaultPdbApplicator applicator;
protected MsSymbolIterator iter;
protected long currentOffset;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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(applicator, "applicator cannot be null");
Objects.requireNonNull(iter, "iter cannot be null");
this.applicator = applicator; this.applicator = applicator;
this.iter = iter;
currentOffset = iter.getCurrentOffset();
} }
/** /**
@ -56,40 +49,4 @@ public abstract class MsSymbolApplier {
applicator.pdbLogAndInfoMessage(originator, message); 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.
}
} }

View file

@ -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;
}

View file

@ -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
}

View file

@ -16,35 +16,33 @@
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator; 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.AbstractMsSymbol;
import ghidra.util.exception.CancelledException;
/** /**
* A dummy {@link MsSymbolApplier}, which, at a minimum, reads the symbol from the * 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}, allowing proper sequencing of other symbols within the
* {@link SymbolGroup}. * {@link SymbolGroup}.
*/ */
public class NoSymbolApplier extends MsSymbolApplier { public class NoSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private AbstractMsSymbol symbol; private AbstractMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public NoSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbol symbol) {
super(applicator, iter); super(applicator);
symbol = iter.next(); this.symbol = symbol;
} }
@Override @Override
void applyTo(MsSymbolApplier applyToApplier) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
// Do nothing. iter.next();
} // Do nothing
@Override
void apply() {
// Do nothing.
} }
} }

View file

@ -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;
}
}

View file

@ -108,6 +108,7 @@ public class PdbApplicatorMetrics {
private Set<Class<? extends AbstractMsType>> unexpectedMemberFunctionContainerTypes = private Set<Class<? extends AbstractMsType>> unexpectedMemberFunctionContainerTypes =
new HashSet<>(); new HashSet<>();
private Set<Class<? extends AbstractMsSymbol>> cannotApplySymbols = new HashSet<>(); private Set<Class<? extends AbstractMsSymbol>> cannotApplySymbols = new HashSet<>();
private Set<Class<? extends AbstractMsSymbol>> nonNestableSymbols = new HashSet<>();
private Set<Class<? extends AbstractMsSymbol>> unexpectedGlobalSymbols = new HashSet<>(); private Set<Class<? extends AbstractMsSymbol>> unexpectedGlobalSymbols = new HashSet<>();
private Set<Class<? extends AbstractMsSymbol>> unexpectedPublicSymbols = new HashSet<>(); private Set<Class<? extends AbstractMsSymbol>> unexpectedPublicSymbols = new HashSet<>();
private boolean witnessEnumerateNarrowing = false; private boolean witnessEnumerateNarrowing = false;
@ -128,6 +129,14 @@ public class PdbApplicatorMetrics {
cannotApplySymbols.add(symbol.getClass()); 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. * Method to capture symbol type that was unexpected as a Global symbol.
* @param symbol The symbol type witnessed. * @param symbol The symbol type witnessed.
@ -220,6 +229,7 @@ public class PdbApplicatorMetrics {
builder.append(reportUnunsualThisPointerUnderlyingTypes()); builder.append(reportUnunsualThisPointerUnderlyingTypes());
builder.append(reportUnunsualMemberFunctionContainerTypes()); builder.append(reportUnunsualMemberFunctionContainerTypes());
builder.append(reportNonappliableSymbols()); builder.append(reportNonappliableSymbols());
builder.append(reportNonNestableSymbols());
builder.append(reportUnexpectedPublicSymbols()); builder.append(reportUnexpectedPublicSymbols());
builder.append(reportUnexpectedGlobalSymbols()); builder.append(reportUnexpectedGlobalSymbols());
builder.append(reportEnumerateNarrowing()); builder.append(reportEnumerateNarrowing());
@ -280,6 +290,15 @@ public class PdbApplicatorMetrics {
return builder.toString(); return builder.toString();
} }
private String reportNonNestableSymbols() {
StringBuilder builder = new StringBuilder();
for (Class<? extends AbstractMsSymbol> clazz : nonNestableSymbols) {
builder.append("Could not nest one or more instances of a PDB symbol type: " +
clazz.getSimpleName() + "\n");
}
return builder.toString();
}
private String reportUnexpectedPublicSymbols() { private String reportUnexpectedPublicSymbols() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Class<? extends AbstractMsSymbol> clazz : unexpectedPublicSymbols) { for (Class<? extends AbstractMsSymbol> clazz : unexpectedPublicSymbols) {

View file

@ -424,32 +424,29 @@ public class PdbResearch {
} }
AbstractMsSymbol symbol = iter.peek(); //temporary during development AbstractMsSymbol symbol = iter.peek(); //temporary during development
MsSymbolApplier applier = applicator.getSymbolApplier(iter); MsSymbolApplier applier = applicator.getSymbolApplier(iter);
if (applier instanceof TypedefSymbolApplier) { if (applier instanceof TypedefSymbolApplier typedefApplier) {
TypedefSymbolApplier typedefApplier = (TypedefSymbolApplier) applier;
RecordNumber typeNumber = typedefApplier.getTypeRecordNumber(); RecordNumber typeNumber = typedefApplier.getTypeRecordNumber();
AbstractMsType type = applicator.getPdb().getTypeRecord(typeNumber); AbstractMsType type = applicator.getPdb().getTypeRecord(typeNumber);
System.out System.out
.println("UDT " + typedefApplier.getName() + " depends on " + type.toString()); .println(
"UDT " + typedefApplier.getName() + " depends on " + type.toString());
// applier.apply(); // applier.apply();
// procSym(symbolGroup); // procSym(symbolGroup);
} }
else if (applier instanceof ReferenceSymbolApplier) { else if (applier instanceof ReferenceSymbolApplier refSymbolApplier) {
ReferenceSymbolApplier refSymbolApplier = (ReferenceSymbolApplier) applier;
MsSymbolIterator refIter = MsSymbolIterator refIter =
refSymbolApplier.getInitializedReferencedSymbolGroupIterator(); refSymbolApplier.getRefIterFromSymbol();
if (refIter == null) { if (refIter == null) {
throw new PdbException("PDB: Referenced Symbol Error - not refIter"); throw new PdbException("PDB: Referenced Symbol Error - not refIter");
} }
// recursion // recursion
childWalkSym(applicator, refIter.getStreamNumber(), refIter); childWalkSym(applicator, refIter.getStreamNumber(), refIter);
} }
else if (applier instanceof DataSymbolApplier) { else if (applier instanceof DataSymbolApplier dataSymbolApplier) {
DataSymbolApplier dataSymbolApplier = (DataSymbolApplier) applier; MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier(symbol);
MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier();
childWalkType(streamNumber, typeApplier); childWalkType(streamNumber, typeApplier);
} }
else if (applier instanceof FunctionSymbolApplier) { else if (applier instanceof FunctionSymbolApplier functionSymbolApplier) {
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applier;
functionSymbolApplier.getFunction(); functionSymbolApplier.getFunction();
// AbstractMsTypeApplier typeApplier = functionSymbolApplier.getTypeApplier(); // AbstractMsTypeApplier typeApplier = functionSymbolApplier.getTypeApplier();
// childWalkType(symbolGroup.getModuleNumber(), typeApplier); // childWalkType(symbolGroup.getModuleNumber(), typeApplier);

View file

@ -26,27 +26,23 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link PeCoffGroupMsSymbol} symbols. * Applier for {@link PeCoffGroupMsSymbol} symbols.
*/ */
public class PeCoffGroupSymbolApplier extends MsSymbolApplier { public class PeCoffGroupSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private PeCoffGroupMsSymbol symbol; private PeCoffGroupMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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 PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) { public PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator, PeCoffGroupMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof PeCoffGroupMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (PeCoffGroupMsSymbol) abstractSymbol;
} }
@Override @Override
void apply() throws PdbException, CancelledException { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
getValidatedSymbol(iter, true);
applicator.addMemoryGroupRefinement(symbol); applicator.addMemoryGroupRefinement(symbol);
Address symbolAddress = applicator.getAddress(symbol); Address symbolAddress = applicator.getAddress(symbol);
if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) { if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
@ -55,9 +51,13 @@ public class PeCoffGroupSymbolApplier extends MsSymbolApplier {
applicator.createSymbol(symbolAddress, symbol.getName(), false); applicator.createSymbol(symbolAddress, symbol.getName(), false);
} }
@Override private PeCoffGroupMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
void applyTo(MsSymbolApplier applyToApplier) { AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
// Do nothing if (!(abstractSymbol instanceof PeCoffGroupMsSymbol peCoffGroupSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
return peCoffGroupSymbol;
} }
} }

View file

@ -25,27 +25,24 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link PeCoffSectionMsSymbol} symbols. * Applier for {@link PeCoffSectionMsSymbol} symbols.
*/ */
public class PeCoffSectionSymbolApplier extends MsSymbolApplier { public class PeCoffSectionSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private PeCoffSectionMsSymbol symbol; private PeCoffSectionMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public PeCoffSectionSymbolApplier(DefaultPdbApplicator applicator,
super(applicator, iter); PeCoffSectionMsSymbol symbol) {
AbstractMsSymbol abstractSymbol = iter.next(); super(applicator);
if (!(abstractSymbol instanceof PeCoffSectionMsSymbol)) { this.symbol = symbol;
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (PeCoffSectionMsSymbol) abstractSymbol;
} }
@Override @Override
void apply() throws PdbException, CancelledException { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
getValidatedSymbol(iter, true);
int sectionNum = symbol.getSectionNumber(); int sectionNum = symbol.getSectionNumber();
long realAddress = symbol.getRva(); long realAddress = symbol.getRva();
symbol.getLength(); symbol.getLength();
@ -59,8 +56,13 @@ public class PeCoffSectionSymbolApplier extends MsSymbolApplier {
// applicator.addMemorySectionRefinement(symbol); // applicator.addMemorySectionRefinement(symbol);
} }
@Override private PeCoffSectionMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
void applyTo(MsSymbolApplier applyToApplier) { AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
// Do nothing if (!(abstractSymbol instanceof PeCoffSectionMsSymbol peCoffSectionSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
return peCoffSectionSymbol;
} }
} }

View file

@ -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;
}
}

View file

@ -32,43 +32,32 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractPublicMsSymbol} symbols. * Applier for {@link AbstractPublicMsSymbol} symbols.
*/ */
public class PublicSymbolApplier extends MsSymbolApplier { public class PublicSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
private AbstractPublicMsSymbol symbol; private AbstractPublicMsSymbol symbol;
private Address symbolAddress = null;
private Address existingSymbolAddress = null;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public PublicSymbolApplier(DefaultPdbApplicator applicator, AbstractPublicMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractPublicMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractPublicMsSymbol) abstractSymbol;
} }
@Override @Override
void applyTo(MsSymbolApplier applyToApplier) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
// Do nothing. getValidatedSymbol(iter, true);
} Address symbolAddress = applicator.getAddress(symbol);
@Override
void apply() throws CancelledException, PdbException {
symbolAddress = applicator.getAddress(symbol);
String name = symbol.getName(); String name = symbol.getName();
if (applicator.isInvalidAddress(symbolAddress, name)) { if (applicator.isInvalidAddress(symbolAddress, name)) {
return; 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, // 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 // as this would violate the uniqueness of the symbol... but we would also want to
// know that this situation was being presented. // know that this situation was being presented.
@ -91,15 +80,13 @@ public class PublicSymbolApplier extends MsSymbolApplier {
} }
} }
Address getAddress() { private AbstractPublicMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
return symbolAddress; 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();
}
} }

View file

@ -32,50 +32,52 @@ public class ReferenceSymbolApplier extends MsSymbolApplier {
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public ReferenceSymbolApplier(DefaultPdbApplicator applicator,
super(applicator, iter); AbstractReferenceMsSymbol symbol) {
AbstractMsSymbol abstractSymbol = iter.next(); super(applicator);
if (!(abstractSymbol instanceof AbstractReferenceMsSymbol)) { this.symbol = symbol;
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractReferenceMsSymbol) abstractSymbol;
} }
@Override //TODO: since we stopped taking the references from publics/globals to module-based symbols
void applyTo(MsSymbolApplier applyToApplier) { // and processing them that way and are now just processing directly from the
// Do nothing. // 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 { * Checks check symbol from primary iterator for correct type and then retrieves the
// Potential recursive call via applicator.procSym(). * properly initialized reference iterator
MsSymbolIterator refIter = getInitializedReferencedSymbolGroupIterator(); * @return the initialized reference iterator
if (refIter == null) { * @throws PdbException upon not enough data to parse
throw new PdbException("PDB: Referenced Symbol Error - null refIter"); * @throws CancelledException upon user cancellation
} */
applicator.procSym(refIter); MsSymbolIterator getRefIterFromSymbol()
} throws CancelledException, PdbException {
int refModuleNumber = symbol.getModuleIndex();
MsSymbolIterator getInitializedReferencedSymbolGroupIterator() throws PdbException { MsSymbolIterator refIter =
SymbolGroup refSymbolGroup = getReferencedSymbolGroup(); applicator.getPdb().getDebugInfo().getSymbolIterator(refModuleNumber);
if (refSymbolGroup == null) { long refOffset = symbol.getOffsetActualSymbolInDollarDollarSymbols();
return null; refIter.initGetByOffset(refOffset);
}
MsSymbolIterator refIter = refSymbolGroup.getSymbolIterator();
refIter.initGetByOffset(getOffsetInReferencedSymbolGroup());
return refIter; return refIter;
} }
SymbolGroup getReferencedSymbolGroup() { private AbstractReferenceMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
int refModuleNumber = symbol.getModuleIndex(); AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
return applicator.getSymbolGroupForModule(refModuleNumber); if (!(abstractSymbol instanceof AbstractReferenceMsSymbol refSymbol)) {
} throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
long getOffsetInReferencedSymbolGroup() { }
return symbol.getOffsetActualSymbolInDollarDollarSymbols(); return refSymbol;
} }
} }

View file

@ -17,9 +17,7 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.Objects; import java.util.Objects;
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator; import ghidra.app.util.bin.format.pdb2.pdbreader.*;
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.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractRegisterRelativeAddressMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractRegisterRelativeAddressMsSymbol;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
@ -31,44 +29,24 @@ import ghidra.util.exception.*;
/** /**
* Applier for {@link AbstractRegisterRelativeAddressMsSymbol} symbols. * Applier for {@link AbstractRegisterRelativeAddressMsSymbol} symbols.
*/ */
public class RegisterRelativeSymbolApplier extends MsSymbolApplier { public class RegisterRelativeSymbolApplier extends MsSymbolApplier
implements NestableSymbolApplier {
private AbstractRegisterRelativeAddressMsSymbol symbol; private AbstractRegisterRelativeAddressMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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, public RegisterRelativeSymbolApplier(DefaultPdbApplicator applicator,
MsSymbolIterator iter) { AbstractRegisterRelativeAddressMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractRegisterRelativeAddressMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (AbstractRegisterRelativeAddressMsSymbol) abstractSymbol;
} }
@Override private boolean createFunctionVariable(FunctionSymbolApplier applier,
void apply() throws PdbException, CancelledException { AbstractRegisterRelativeAddressMsSymbol symbol)
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)
throws CancelledException, PdbException { throws CancelledException, PdbException {
Objects.requireNonNull(applier, "FunctionSymbolApplier cannot be null"); Objects.requireNonNull(applier, "FunctionSymbolApplier cannot be null");
Function function = applier.getFunction(); Function function = applier.getFunction();
@ -156,4 +134,26 @@ public class RegisterRelativeSymbolApplier extends MsSymbolApplier {
return true; 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;
}
} }

View file

@ -15,131 +15,130 @@
*/ */
package ghidra.app.util.pdb.pdbapplicator; 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.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; 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.app.util.bin.format.pdb2.pdbreader.symbol.SeparatedCodeFromCompilerSupportMsSymbol;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit; import ghidra.util.exception.AssertException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link SeparatedCodeFromCompilerSupportMsSymbol} symbol. * Applier for {@link SeparatedCodeFromCompilerSupportMsSymbol} symbol.
*/ */
// TODO: Need to evaluate relationship to function symbols. public class SeparatedCodeSymbolApplier extends AbstractBlockContextApplier
// TODO: Need to create anonymous name for this as a function? implements BlockNestingSymbolApplier, NestableSymbolApplier {
public class SeparatedCodeSymbolApplier extends MsSymbolApplier {
private SeparatedCodeFromCompilerSupportMsSymbol symbol; private SeparatedCodeFromCompilerSupportMsSymbol symbol;
private String craftedName;
private Address specifiedAddress;
private BlockCommentsManager comments;
private int symbolBlockNestingLevel;
private Address currentBlockAddress;
private List<MsSymbolApplier> allAppliers = new ArrayList<>();
private static MsSymbolIterator validateSymbol(MsSymbolIterator iter) {
if (!(iter.peek() instanceof SeparatedCodeFromCompilerSupportMsSymbol)) {
throw new IllegalArgumentException("Not a SeparatedCodeFromCompilerSupportMsSymbol");
}
return iter;
}
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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
* @throws CancelledException upon user cancellation
*/ */
public SeparatedCodeSymbolApplier(DefaultPdbApplicator applicator, public SeparatedCodeSymbolApplier(DefaultPdbApplicator applicator,
MsSymbolIterator iter) throws CancelledException { SeparatedCodeFromCompilerSupportMsSymbol symbol) {
super(applicator, validateSymbol(iter)); super(applicator);
this.symbol = symbol;
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);
}
} }
@Override @Override
void manageBlockNesting(MsSymbolApplier applierParam) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
beginBlock(specifiedAddress); getValidatedSymbol(iter, true);
} Address address = applicator.getAddress(symbol);
@Override // Regardless of ability to apply this symbol, we need to progress through symbols to the
void applyTo(MsSymbolApplier applyToApplier) { // matching "end" symbol before we return
// Do nothing. if (!processEndSymbol(symbol.getEndPointer(), iter)) {
} applicator.appendLogMsg("PDB: Failed to process function at address " + address);
@Override
void apply() throws PdbException, CancelledException {
if (applicator.isInvalidAddress(currentBlockAddress, craftedName)) {
return; return;
} }
// DO NOTHING FOR NOW. TODO: should we have a configuration option?
// Note: these comments can be noise in the decompiler an code browser if (applicator.isInvalidAddress(address, craftBlockComment(address))) {
setComments(false); 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) { @Override
if (enabled) { public void deferredApply(MsSymbolIterator iter)
String existingComment = applicator.getProgram() throws PdbException, CancelledException {
.getListing() // Pealing the symbol off again, as the iterator is coming in fresh, and we need the symbol
.getComment( getValidatedSymbol(iter, true);
CodeUnit.PRE_COMMENT, specifiedAddress);
String p = "*************************************************************\n"; Address address = applicator.getAddress(symbol);
String newComment =
String.format(p + "* Separated code (from the compiler): %s - %s *\n" + p, long start = getStartOffset();
specifiedAddress.toString(), long end = getEndOffset();
specifiedAddress.add(symbol.getBlockLength() - 1).toString()); Address blockAddress = address.add(start);
String comment = long length = end - start;
(existingComment == null) ? newComment : existingComment + "\n" + newComment;
SetCommentCmd.createComment(applicator.getProgram(), specifiedAddress, comment, // Not sure if following procedure from parent class can be used or if should be
CodeUnit.PRE_COMMENT); // 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() { @Override
return (symbolBlockNestingLevel > 0) && iter.hasNext(); long getStartOffset() {
return symbol.getParentPointer(); // TODO: needs investigation as to what field to use!!!!!
} }
void endBlock() { @Override
if (--symbolBlockNestingLevel < 0) { long getEndOffset() {
applicator.appendLogMsg("Block Nesting went negative at " + specifiedAddress); 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());
} }
} return sepCodeSymbol;
void beginBlock(Address startAddress) {
currentBlockAddress = startAddress;
++symbolBlockNestingLevel;
} }
} }

View file

@ -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.MsSymbolIterator;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*; 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} * Pseudo-factory for creating the {@link MsSymbolApplier} for the {@link AbstractMsSymbol}
* indicated by the {@link AbstractMsSymbolIterator}. * indicated by the {@link MsSymbolIterator}.
*/ */
public class SymbolApplierFactory { public class SymbolApplierFactory {
@ -31,21 +30,29 @@ public class SymbolApplierFactory {
this.applicator = applicator; this.applicator = applicator;
} }
// TODO: 20191120... Do we need a SymbolApplier cache for Symbols like we have the TypeApplier MsSymbolApplier getSymbolApplier(MsSymbolIterator iter) {
// 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 {
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
if (symbol == null) { if (symbol == null) {
applicator.appendLogMsg("PDB Warning: No AbstractMsSymbol"); applicator.appendLogMsg("PDB Warning: No AbstractMsSymbol");
return null; 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; MsSymbolApplier applier = null;
switch (symbol.getPdbId()) { int pdbId = symbol.getPdbId();
switch (pdbId) {
// // 0x0000 block // // 0x0000 block
// case CompileFlagsMsSymbol.PDB_ID: // case CompileFlagsMsSymbol.PDB_ID:
// symbol = new CompileFlagsMsSymbol(pdb, reader); // symbol = new CompileFlagsMsSymbol(pdb, reader);
@ -57,13 +64,14 @@ public class SymbolApplierFactory {
// symbol = new Constant16MsSymbol(pdb, reader); // symbol = new Constant16MsSymbol(pdb, reader);
// break; // break;
case UserDefinedType16MsSymbol.PDB_ID: case UserDefinedType16MsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
// case StartSearchMsSymbol.PDB_ID: // case StartSearchMsSymbol.PDB_ID:
// symbol = new StartSearchMsSymbol(pdb, reader); // symbol = new StartSearchMsSymbol(pdb, reader);
// break; // break;
case EndMsSymbol.PDB_ID: case EndMsSymbol.PDB_ID:
applier = new EndSymbolApplier(applicator, iter); applier = new EndSymbolApplier(applicator, (EndMsSymbol) symbol);
break; break;
// case SkipMsSymbol.PDB_ID: // case SkipMsSymbol.PDB_ID:
// symbol = new SkipMsSymbol(pdb, reader); // symbol = new SkipMsSymbol(pdb, reader);
@ -78,7 +86,8 @@ public class SymbolApplierFactory {
// symbol = new EndArgumentsListMsSymbol(pdb, reader); // symbol = new EndArgumentsListMsSymbol(pdb, reader);
// break; // break;
case CobolUserDefinedType16MsSymbol.PDB_ID: case CobolUserDefinedType16MsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
// case ManyRegisterVariable16MsSymbol.PDB_ID: // case ManyRegisterVariable16MsSymbol.PDB_ID:
// symbol = new ManyRegisterVariable16MsSymbol(pdb, reader); // symbol = new ManyRegisterVariable16MsSymbol(pdb, reader);
@ -95,31 +104,31 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative16MsSymbol(pdb, reader); // symbol = new BasePointerRelative16MsSymbol(pdb, reader);
// break; // break;
case LocalData16MsSymbol.PDB_ID: case LocalData16MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalData16MsSymbol.PDB_ID: case GlobalData16MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case Public16MsSymbol.PDB_ID: case Public16MsSymbol.PDB_ID:
applier = new PublicSymbolApplier(applicator, iter); applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break; break;
case LocalProcedureStart16MsSymbol.PDB_ID: case LocalProcedureStart16MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStart16MsSymbol.PDB_ID: case GlobalProcedureStart16MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case Thunk16MsSymbol.PDB_ID: case Thunk16MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case Block16MsSymbol.PDB_ID: case Block16MsSymbol.PDB_ID:
applier = new BlockSymbolApplier(applicator, iter); applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break; break;
case With16MsSymbol.PDB_ID: case With16MsSymbol.PDB_ID:
applier = new WithSymbolApplier(applicator, iter); applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break; break;
case Label16MsSymbol.PDB_ID: case Label16MsSymbol.PDB_ID:
applier = new LabelSymbolApplier(applicator, iter); applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break; break;
// case ChangeExecutionModel16MsSymbol.PDB_ID: // case ChangeExecutionModel16MsSymbol.PDB_ID:
// symbol = new ChangeExecutionModel16MsSymbol(pdb, reader); // symbol = new ChangeExecutionModel16MsSymbol(pdb, reader);
@ -128,7 +137,8 @@ public class SymbolApplierFactory {
// symbol = new VirtualFunctionTable16MsSymbol(pdb, reader); // symbol = new VirtualFunctionTable16MsSymbol(pdb, reader);
// break; // break;
case RegisterRelativeAddress16MsSymbol.PDB_ID: case RegisterRelativeAddress16MsSymbol.PDB_ID:
applier = new RegisterRelativeSymbolApplier(applicator, iter); applier = new RegisterRelativeSymbolApplier(applicator,
(AbstractRegisterRelativeAddressMsSymbol) symbol);
break; break;
// //
// // 0x0200 block // // 0x0200 block
@ -136,31 +146,31 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative3216MsSymbol(pdb, reader); // symbol = new BasePointerRelative3216MsSymbol(pdb, reader);
// break; // break;
case LocalData3216MsSymbol.PDB_ID: case LocalData3216MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalData3216MsSymbol.PDB_ID: case GlobalData3216MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case Public3216MsSymbol.PDB_ID: case Public3216MsSymbol.PDB_ID:
applier = new PublicSymbolApplier(applicator, iter); applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break; break;
case LocalProcedureStart3216MsSymbol.PDB_ID: case LocalProcedureStart3216MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStart3216MsSymbol.PDB_ID: case GlobalProcedureStart3216MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case Thunk32StMsSymbol.PDB_ID: case Thunk32StMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case Block32StMsSymbol.PDB_ID: case Block32StMsSymbol.PDB_ID:
applier = new BlockSymbolApplier(applicator, iter); applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break; break;
case With32StMsSymbol.PDB_ID: case With32StMsSymbol.PDB_ID:
applier = new WithSymbolApplier(applicator, iter); applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break; break;
case Label32StMsSymbol.PDB_ID: case Label32StMsSymbol.PDB_ID:
applier = new LabelSymbolApplier(applicator, iter); applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break; break;
// case ChangeExecutionModel32MsSymbol.PDB_ID: // case ChangeExecutionModel32MsSymbol.PDB_ID:
// symbol = new ChangeExecutionModel32MsSymbol(pdb, reader); // symbol = new ChangeExecutionModel32MsSymbol(pdb, reader);
@ -169,7 +179,8 @@ public class SymbolApplierFactory {
// symbol = new VirtualFunctionTable3216MsSymbol(pdb, reader); // symbol = new VirtualFunctionTable3216MsSymbol(pdb, reader);
// break; // break;
case RegisterRelativeAddress3216MsSymbol.PDB_ID: case RegisterRelativeAddress3216MsSymbol.PDB_ID:
applier = new RegisterRelativeSymbolApplier(applicator, iter); applier = new RegisterRelativeSymbolApplier(applicator,
(AbstractRegisterRelativeAddressMsSymbol) symbol);
break; break;
// case LocalThreadStorage3216MsSymbol.PDB_ID: // case LocalThreadStorage3216MsSymbol.PDB_ID:
// symbol = new LocalThreadStorage3216MsSymbol(pdb, reader); // symbol = new LocalThreadStorage3216MsSymbol(pdb, reader);
@ -183,28 +194,31 @@ public class SymbolApplierFactory {
// 0x0300 block // 0x0300 block
case LocalProcedureStartMips16MsSymbol.PDB_ID: case LocalProcedureStartMips16MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStartMips16MsSymbol.PDB_ID: case GlobalProcedureStartMips16MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// 0x0400 block // 0x0400 block
case ProcedureReferenceStMsSymbol.PDB_ID: case ProcedureReferenceStMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case DataReferenceStMsSymbol.PDB_ID: case DataReferenceStMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
// case AlignMsSymbol.PDB_ID: // case AlignMsSymbol.PDB_ID:
// symbol = new AlignMsSymbol(pdb, reader); // symbol = new AlignMsSymbol(pdb, reader);
// break; // break;
case LocalProcedureReferenceStMsSymbol.PDB_ID: 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; break;
// case OemDefinedMsSymbol.PDB_ID:
// symbol = new OemDefinedMsSymbol(pdb, reader);
// break;
// //
// // 0x1000 block // // 0x1000 block
// case RegisterStMsSymbol.PDB_ID: // case RegisterStMsSymbol.PDB_ID:
@ -214,10 +228,12 @@ public class SymbolApplierFactory {
// symbol = new ConstantStMsSymbol(pdb, reader); // symbol = new ConstantStMsSymbol(pdb, reader);
// break; // break;
case UserDefinedTypeStMsSymbol.PDB_ID: case UserDefinedTypeStMsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
case CobolUserDefinedTypeStMsSymbol.PDB_ID: case CobolUserDefinedTypeStMsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
// case ManyRegisterVariableStMsSymbol.PDB_ID: // case ManyRegisterVariableStMsSymbol.PDB_ID:
// symbol = new ManyRegisterVariableStMsSymbol(pdb, reader); // symbol = new ManyRegisterVariableStMsSymbol(pdb, reader);
@ -226,25 +242,26 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative32StMsSymbol(pdb, reader); // symbol = new BasePointerRelative32StMsSymbol(pdb, reader);
// break; // break;
case LocalData32StMsSymbol.PDB_ID: case LocalData32StMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalData32StMsSymbol.PDB_ID: case GlobalData32StMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case Public32StMsSymbol.PDB_ID: case Public32StMsSymbol.PDB_ID:
applier = new PublicSymbolApplier(applicator, iter); applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break; break;
case LocalProcedureStart32StMsSymbol.PDB_ID: case LocalProcedureStart32StMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStart32StMsSymbol.PDB_ID: case GlobalProcedureStart32StMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// case VirtualFunctionTable32MsSymbol.PDB_ID: // case VirtualFunctionTable32MsSymbol.PDB_ID:
// symbol = new VirtualFunctionTable32MsSymbol(pdb, reader); // symbol = new VirtualFunctionTable32MsSymbol(pdb, reader);
// break; // break;
case RegisterRelativeAddress32StMsSymbol.PDB_ID: case RegisterRelativeAddress32StMsSymbol.PDB_ID:
applier = new RegisterRelativeSymbolApplier(applicator, iter); applier = new RegisterRelativeSymbolApplier(applicator,
(AbstractRegisterRelativeAddressMsSymbol) symbol);
break; break;
// case LocalThreadStorage32StMsSymbol.PDB_ID: // case LocalThreadStorage32StMsSymbol.PDB_ID:
// symbol = new LocalThreadStorage32StMsSymbol(pdb, reader); // symbol = new LocalThreadStorage32StMsSymbol(pdb, reader);
@ -253,13 +270,14 @@ public class SymbolApplierFactory {
// symbol = new GlobalThreadStorage32StMsSymbol(pdb, reader); // symbol = new GlobalThreadStorage32StMsSymbol(pdb, reader);
// break; // break;
case LocalProcedureStartMipsStMsSymbol.PDB_ID: case LocalProcedureStartMipsStMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStartMipsStMsSymbol.PDB_ID: case GlobalProcedureStartMipsStMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case ExtraFrameAndProcedureInformationMsSymbol.PDB_ID: case ExtraFrameAndProcedureInformationMsSymbol.PDB_ID:
applier = new FrameAndProcedureInformationSymbolApplier(applicator, iter); applier = new FrameAndProcedureInformationSymbolApplier(applicator,
(ExtraFrameAndProcedureInformationMsSymbol) symbol);
break; break;
// case Compile2StMsSymbol.PDB_ID: // case Compile2StMsSymbol.PDB_ID:
// symbol = new Compile2StMsSymbol(pdb, reader); // symbol = new Compile2StMsSymbol(pdb, reader);
@ -268,10 +286,10 @@ public class SymbolApplierFactory {
// symbol = new ManyRegisterVariable2StMsSymbol(pdb, reader); // symbol = new ManyRegisterVariable2StMsSymbol(pdb, reader);
// break; // break;
case LocalProcedureStartIa64StMsSymbol.PDB_ID: case LocalProcedureStartIa64StMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStartIa64StMsSymbol.PDB_ID: case GlobalProcedureStartIa64StMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// case LocalSlotIndexFieldedLILStMsSymbol.PDB_ID: // case LocalSlotIndexFieldedLILStMsSymbol.PDB_ID:
// symbol = new LocalSlotIndexFieldedLILStMsSymbol(pdb, reader); // symbol = new LocalSlotIndexFieldedLILStMsSymbol(pdb, reader);
@ -283,10 +301,12 @@ public class SymbolApplierFactory {
// symbol = new AnnotationMsSymbol(pdb, reader); // symbol = new AnnotationMsSymbol(pdb, reader);
// break; // break;
case GlobalManagedProcedureStMsSymbol.PDB_ID: case GlobalManagedProcedureStMsSymbol.PDB_ID:
applier = new ManagedProcedureSymbolApplier(applicator, iter); applier = new ManagedProcedureSymbolApplier(applicator,
(AbstractManagedProcedureMsSymbol) symbol);
break; break;
case LocalManagedProcedureStMsSymbol.PDB_ID: case LocalManagedProcedureStMsSymbol.PDB_ID:
applier = new ManagedProcedureSymbolApplier(applicator, iter); applier = new ManagedProcedureSymbolApplier(applicator,
(AbstractManagedProcedureMsSymbol) symbol);
break; break;
// case Reserved1MsSymbol.PDB_ID: // case Reserved1MsSymbol.PDB_ID:
// symbol = new Reserved1MsSymbol(pdb, reader); // symbol = new Reserved1MsSymbol(pdb, reader);
@ -301,10 +321,10 @@ public class SymbolApplierFactory {
// symbol = new Reserved4MsSymbol(pdb, reader); // symbol = new Reserved4MsSymbol(pdb, reader);
// break; // break;
case LocalManagedDataStMsSymbol.PDB_ID: case LocalManagedDataStMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalManagedDataStMsSymbol.PDB_ID: case GlobalManagedDataStMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
// case ManLocOrParamReltoVFPStMsSymbol.PDB_ID: // case ManLocOrParamReltoVFPStMsSymbol.PDB_ID:
// symbol = new ManLocOrParamReltoVFPStMsSymbol(pdb, reader); // symbol = new ManLocOrParamReltoVFPStMsSymbol(pdb, reader);
@ -312,9 +332,10 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIRStMsSymbol.PDB_ID: // case ManagedLocalOrParameterSIRStMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIRStMsSymbol(pdb, reader); // symbol = new ManagedLocalOrParameterSIRStMsSymbol(pdb, reader);
// break; // break;
// case ManagedSymbolWithSlotIndexFieldStMsSymbol.PDB_ID: case ManagedSymbolWithSlotIndexFieldStMsSymbol.PDB_ID:
// symbol = new ManagedSymbolWithSlotIndexFieldStMsSymbol(pdb, reader); applier = new ManagedSymbolWithSlotSymbolApplier(applicator,
// break; (AbstractManagedSymbolWithSlotIndexFieldMsSymbol) symbol);
break;
// case ManagedLocalOrParameterSIMRStMsSymbol.PDB_ID: // case ManagedLocalOrParameterSIMRStMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMRStMsSymbol(pdb, reader); // symbol = new ManagedLocalOrParameterSIMRStMsSymbol(pdb, reader);
// break; // break;
@ -327,25 +348,26 @@ public class SymbolApplierFactory {
// case IndexForTypeReferencedByNameFromMetadataMsSymbol.PDB_ID: // case IndexForTypeReferencedByNameFromMetadataMsSymbol.PDB_ID:
// symbol = new IndexForTypeReferencedByNameFromMetadataMsSymbol(pdb, reader); // symbol = new IndexForTypeReferencedByNameFromMetadataMsSymbol(pdb, reader);
// break; // break;
// case UsingNamespaceStMsSymbol.PDB_ID: case UsingNamespaceStMsSymbol.PDB_ID:
// symbol = new UsingNamespaceStMsSymbol(pdb, reader); applier = new UsingNamespaceSymbolApplier(applicator,
// break; (AbstractUsingNamespaceMsSymbol) symbol);
break;
// //
// // 0x1100 block // // 0x1100 block
// case ObjectNameMsSymbol.PDB_ID: // case ObjectNameMsSymbol.PDB_ID:
// symbol = new ObjectNameMsSymbol(pdb, reader); // symbol = new ObjectNameMsSymbol(pdb, reader);
// break; // break;
case Thunk32MsSymbol.PDB_ID: case Thunk32MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case Block32MsSymbol.PDB_ID: case Block32MsSymbol.PDB_ID:
applier = new BlockSymbolApplier(applicator, iter); applier = new BlockSymbolApplier(applicator, (AbstractBlockMsSymbol) symbol);
break; break;
case With32MsSymbol.PDB_ID: case With32MsSymbol.PDB_ID:
applier = new WithSymbolApplier(applicator, iter); applier = new WithSymbolApplier(applicator, (AbstractWithMsSymbol) symbol);
break; break;
case Label32MsSymbol.PDB_ID: case Label32MsSymbol.PDB_ID:
applier = new LabelSymbolApplier(applicator, iter); applier = new LabelSymbolApplier(applicator, (AbstractLabelMsSymbol) symbol);
break; break;
// case RegisterMsSymbol.PDB_ID: // case RegisterMsSymbol.PDB_ID:
// symbol = new RegisterMsSymbol(pdb, reader); // symbol = new RegisterMsSymbol(pdb, reader);
@ -354,10 +376,12 @@ public class SymbolApplierFactory {
// symbol = new ConstantMsSymbol(pdb, reader); // symbol = new ConstantMsSymbol(pdb, reader);
// break; // break;
case UserDefinedTypeMsSymbol.PDB_ID: case UserDefinedTypeMsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
case CobolUserDefinedTypeMsSymbol.PDB_ID: case CobolUserDefinedTypeMsSymbol.PDB_ID:
applier = new TypedefSymbolApplier(applicator, iter); applier =
new TypedefSymbolApplier(applicator, (AbstractUserDefinedTypeMsSymbol) symbol);
break; break;
// case ManyRegisterVariableMsSymbol.PDB_ID: // case ManyRegisterVariableMsSymbol.PDB_ID:
// symbol = new ManyRegisterVariableMsSymbol(pdb, reader); // symbol = new ManyRegisterVariableMsSymbol(pdb, reader);
@ -366,22 +390,23 @@ public class SymbolApplierFactory {
// symbol = new BasePointerRelative32MsSymbol(pdb, reader); // symbol = new BasePointerRelative32MsSymbol(pdb, reader);
// break; // break;
case LocalData32MsSymbol.PDB_ID: case LocalData32MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalData32MsSymbol.PDB_ID: case GlobalData32MsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case Public32MsSymbol.PDB_ID: case Public32MsSymbol.PDB_ID:
applier = new PublicSymbolApplier(applicator, iter); applier = new PublicSymbolApplier(applicator, (AbstractPublicMsSymbol) symbol);
break; break;
case LocalProcedureStart32MsSymbol.PDB_ID: case LocalProcedureStart32MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStart32MsSymbol.PDB_ID: case GlobalProcedureStart32MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case RegisterRelativeAddress32MsSymbol.PDB_ID: case RegisterRelativeAddress32MsSymbol.PDB_ID:
applier = new RegisterRelativeSymbolApplier(applicator, iter); applier = new RegisterRelativeSymbolApplier(applicator,
(AbstractRegisterRelativeAddressMsSymbol) symbol);
break; break;
// case LocalThreadStorage32MsSymbol.PDB_ID: // case LocalThreadStorage32MsSymbol.PDB_ID:
// symbol = new LocalThreadStorage32MsSymbol(pdb, reader); // symbol = new LocalThreadStorage32MsSymbol(pdb, reader);
@ -390,10 +415,10 @@ public class SymbolApplierFactory {
// symbol = new GlobalThreadStorage32MsSymbol(pdb, reader); // symbol = new GlobalThreadStorage32MsSymbol(pdb, reader);
// break; // break;
case LocalProcedureStartMipsMsSymbol.PDB_ID: case LocalProcedureStartMipsMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStartMipsMsSymbol.PDB_ID: case GlobalProcedureStartMipsMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// case Compile2MsSymbol.PDB_ID: // case Compile2MsSymbol.PDB_ID:
// symbol = new Compile2MsSymbol(pdb, reader); // symbol = new Compile2MsSymbol(pdb, reader);
@ -402,10 +427,10 @@ public class SymbolApplierFactory {
// symbol = new ManyRegisterVariable2MsSymbol(pdb, reader); // symbol = new ManyRegisterVariable2MsSymbol(pdb, reader);
// break; // break;
case LocalProcedureStartIa64MsSymbol.PDB_ID: case LocalProcedureStartIa64MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureStartIa64MsSymbol.PDB_ID: case GlobalProcedureStartIa64MsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// case LocalSlotIndexFieldedLILMsSymbol.PDB_ID: // case LocalSlotIndexFieldedLILMsSymbol.PDB_ID:
// symbol = new LocalSlotIndexFieldedLILMsSymbol(pdb, reader); // symbol = new LocalSlotIndexFieldedLILMsSymbol(pdb, reader);
@ -414,10 +439,10 @@ public class SymbolApplierFactory {
// symbol = new ParameterSlotIndexFieldedLILMsSymbol(pdb, reader); // symbol = new ParameterSlotIndexFieldedLILMsSymbol(pdb, reader);
// break; // break;
case LocalManagedDataMsSymbol.PDB_ID: case LocalManagedDataMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
case GlobalManagedDataMsSymbol.PDB_ID: case GlobalManagedDataMsSymbol.PDB_ID:
applier = new DataSymbolApplier(applicator, iter); applier = new DataSymbolApplier(applicator, (AbstractDataMsSymbol) symbol);
break; break;
// case ManLocOrParamReltoVFPMsSymbol.PDB_ID: // case ManLocOrParamReltoVFPMsSymbol.PDB_ID:
// symbol = new ManLocOrParamReltoVFPMsSymbol(pdb, reader); // symbol = new ManLocOrParamReltoVFPMsSymbol(pdb, reader);
@ -425,9 +450,10 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIRMsSymbol.PDB_ID: // case ManagedLocalOrParameterSIRMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIRMsSymbol(pdb, reader); // symbol = new ManagedLocalOrParameterSIRMsSymbol(pdb, reader);
// break; // break;
// case ManagedSymbolWithSlotIndexFieldMsSymbol.PDB_ID: case ManagedSymbolWithSlotIndexFieldMsSymbol.PDB_ID:
// symbol = new ManagedSymbolWithSlotIndexFieldMsSymbol(pdb, reader); applier = new ManagedSymbolWithSlotSymbolApplier(applicator,
// break; (AbstractManagedSymbolWithSlotIndexFieldMsSymbol) symbol);
break;
// case ManagedLocalOrParameterSIMRMsSymbol.PDB_ID: // case ManagedLocalOrParameterSIMRMsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMRMsSymbol(pdb, reader); // symbol = new ManagedLocalOrParameterSIMRMsSymbol(pdb, reader);
// break; // break;
@ -437,32 +463,40 @@ public class SymbolApplierFactory {
// case ManagedLocalOrParameterSIMR2MsSymbol.PDB_ID: // case ManagedLocalOrParameterSIMR2MsSymbol.PDB_ID:
// symbol = new ManagedLocalOrParameterSIMR2MsSymbol(pdb, reader); // symbol = new ManagedLocalOrParameterSIMR2MsSymbol(pdb, reader);
// break; // break;
// case UsingNamespaceMsSymbol.PDB_ID: case UsingNamespaceMsSymbol.PDB_ID:
// symbol = new UsingNamespaceMsSymbol(pdb, reader); applier = new UsingNamespaceSymbolApplier(applicator,
// break; (AbstractUsingNamespaceMsSymbol) symbol);
break;
case ProcedureReferenceMsSymbol.PDB_ID: case ProcedureReferenceMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case DataReferenceMsSymbol.PDB_ID: case DataReferenceMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case LocalProcedureReferenceMsSymbol.PDB_ID: case LocalProcedureReferenceMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case AnnotationReferenceMsSymbol.PDB_ID: case AnnotationReferenceMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case TokenReferenceToManagedProcedureMsSymbol.PDB_ID: case TokenReferenceToManagedProcedureMsSymbol.PDB_ID:
applier = new ReferenceSymbolApplier(applicator, iter); applier =
new ReferenceSymbolApplier(applicator, (AbstractReferenceMsSymbol) symbol);
break; break;
case GlobalManagedProcedureMsSymbol.PDB_ID: case GlobalManagedProcedureMsSymbol.PDB_ID:
applier = new ManagedProcedureSymbolApplier(applicator, iter); applier = new ManagedProcedureSymbolApplier(applicator,
(AbstractManagedProcedureMsSymbol) symbol);
break; break;
case LocalManagedProcedureMsSymbol.PDB_ID: case LocalManagedProcedureMsSymbol.PDB_ID:
applier = new ManagedProcedureSymbolApplier(applicator, iter); applier = new ManagedProcedureSymbolApplier(applicator,
(AbstractManagedProcedureMsSymbol) symbol);
break; break;
case TrampolineMsSymbol.PDB_ID: case TrampolineMsSymbol.PDB_ID:
applier = new TrampolineSymbolApplier(applicator, iter); applier = new TrampolineSymbolApplier(applicator, (TrampolineMsSymbol) symbol);
break; break;
// case ManagedConstantMsSymbol.PDB_ID: // case ManagedConstantMsSymbol.PDB_ID:
// symbol = new ManagedConstantMsSymbol(pdb, reader); // symbol = new ManagedConstantMsSymbol(pdb, reader);
@ -480,10 +514,12 @@ public class SymbolApplierFactory {
// symbol = new AttributedLocalOrParameterSIMRMsSymbol(pdb, reader); // symbol = new AttributedLocalOrParameterSIMRMsSymbol(pdb, reader);
// break; // break;
case SeparatedCodeFromCompilerSupportMsSymbol.PDB_ID: case SeparatedCodeFromCompilerSupportMsSymbol.PDB_ID:
applier = new SeparatedCodeSymbolApplier(applicator, iter); applier = new SeparatedCodeSymbolApplier(applicator,
(SeparatedCodeFromCompilerSupportMsSymbol) symbol);
break; break;
case LocalSymbolInOptimizedCode2005MsSymbol.PDB_ID: case LocalSymbolInOptimizedCode2005MsSymbol.PDB_ID:
applier = new LocalOptimizedSymbolApplier(applicator, iter); applier = new LocalOptimizedSymbolApplier(applicator,
(AbstractLocalSymbolInOptimizedCodeMsSymbol) symbol);
break; break;
// case DefinedSingleAddressRange2005MsSymbol.PDB_ID: // case DefinedSingleAddressRange2005MsSymbol.PDB_ID:
// symbol = new DefinedSingleAddressRange2005MsSymbol(pdb, reader); // symbol = new DefinedSingleAddressRange2005MsSymbol(pdb, reader);
@ -492,10 +528,11 @@ public class SymbolApplierFactory {
// symbol = new DefinedMultipleAddressRanges2005MsSymbol(pdb, reader); // symbol = new DefinedMultipleAddressRanges2005MsSymbol(pdb, reader);
// break; // break;
case PeCoffSectionMsSymbol.PDB_ID: case PeCoffSectionMsSymbol.PDB_ID:
applier = new PeCoffSectionSymbolApplier(applicator, iter); applier =
new PeCoffSectionSymbolApplier(applicator, (PeCoffSectionMsSymbol) symbol);
break; break;
case PeCoffGroupMsSymbol.PDB_ID: case PeCoffGroupMsSymbol.PDB_ID:
applier = new PeCoffGroupSymbolApplier(applicator, iter); applier = new PeCoffGroupSymbolApplier(applicator, (PeCoffGroupMsSymbol) symbol);
break; break;
// case ExportMsSymbol.PDB_ID: // case ExportMsSymbol.PDB_ID:
// symbol = new ExportMsSymbol(pdb, reader); // symbol = new ExportMsSymbol(pdb, reader);
@ -516,46 +553,54 @@ public class SymbolApplierFactory {
// symbol = new EnvironmentBlockMsSymbol(pdb, reader); // symbol = new EnvironmentBlockMsSymbol(pdb, reader);
// break; // break;
case LocalSymbolInOptimizedCodeMsSymbol.PDB_ID: case LocalSymbolInOptimizedCodeMsSymbol.PDB_ID:
applier = new LocalOptimizedSymbolApplier(applicator, iter); applier = new LocalOptimizedSymbolApplier(applicator,
(AbstractLocalSymbolInOptimizedCodeMsSymbol) symbol);
break; break;
case DefinedSingleAddressRangeMsSymbol.PDB_ID: case DefinedSingleAddressRangeMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case SubfieldDARMsSymbol.PDB_ID: case SubfieldDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case EnregisteredSymbolDARMsSymbol.PDB_ID: case EnregisteredSymbolDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case FramePointerRelativeDARMsSymbol.PDB_ID: case FramePointerRelativeDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case EnregisteredFieldOfSymbolDARMsSymbol.PDB_ID: case EnregisteredFieldOfSymbolDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case FramePointerRelativeFullScopeDARMsSymbol.PDB_ID: case FramePointerRelativeFullScopeDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case EnregisteredSymbolRelativeDARMsSymbol.PDB_ID: case EnregisteredSymbolRelativeDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
case LocalProcedure32IdMsSymbol.PDB_ID: case LocalProcedure32IdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedure32IdMsSymbol.PDB_ID: case GlobalProcedure32IdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case LocalProcedureMipsIdMsSymbol.PDB_ID: case LocalProcedureMipsIdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureMipsIdMsSymbol.PDB_ID: case GlobalProcedureMipsIdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case LocalProcedureIa64IdMsSymbol.PDB_ID: case LocalProcedureIa64IdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case GlobalProcedureIa64IdMsSymbol.PDB_ID: case GlobalProcedureIa64IdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
// case BuildInformationMsSymbol.PDB_ID: // case BuildInformationMsSymbol.PDB_ID:
// symbol = new BuildInformationMsSymbol(pdb, reader); // symbol = new BuildInformationMsSymbol(pdb, reader);
@ -567,10 +612,12 @@ public class SymbolApplierFactory {
// symbol = new InlinedFunctionEndMsSymbol(pdb, reader); // symbol = new InlinedFunctionEndMsSymbol(pdb, reader);
// break; // break;
case ProcedureIdEndMsSymbol.PDB_ID: case ProcedureIdEndMsSymbol.PDB_ID:
applier = new EndSymbolApplier(applicator, iter); applier =
new ProcedureIdEndSymbolApplier(applicator, (ProcedureIdEndMsSymbol) symbol);
break; break;
case HighLevelShaderLanguageRegDimDARMsSymbol.PDB_ID: case HighLevelShaderLanguageRegDimDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
// case GlobalDataHLSLMsSymbol.PDB_ID: // case GlobalDataHLSLMsSymbol.PDB_ID:
// symbol = new GlobalDataHLSLMsSymbol(pdb, reader); // symbol = new GlobalDataHLSLMsSymbol(pdb, reader);
@ -585,13 +632,14 @@ public class SymbolApplierFactory {
// symbol = new LocalDeferredProcedureCallGroupSharedMsSymbol(pdb, reader); // symbol = new LocalDeferredProcedureCallGroupSharedMsSymbol(pdb, reader);
// break; // break;
case LocalProcedureStart32DeferredProcedureCallMsSymbol.PDB_ID: case LocalProcedureStart32DeferredProcedureCallMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case LocalProcedure32DeferredProcedureCallIdMsSymbol.PDB_ID: case LocalProcedure32DeferredProcedureCallIdMsSymbol.PDB_ID:
applier = new FunctionSymbolApplier(applicator, iter); applier = new FunctionSymbolApplier(applicator, (AbstractProcedureMsSymbol) symbol);
break; break;
case DeferredProcedureCallPointerTagRegDimDARMsSymbol.PDB_ID: case DeferredProcedureCallPointerTagRegDimDARMsSymbol.PDB_ID:
applier = new DefinedSingleAddressRangeSymbolApplier(applicator, iter); applier = new DefinedSingleAddressRangeSymbolApplier(applicator,
(AbstractDefinedSingleAddressRangeMsSymbol) symbol);
break; break;
// case DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol.PDB_ID: // case DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol.PDB_ID:
// symbol = new DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol(pdb, reader); // symbol = new DeferredProcedureCallPointerTagToSymbolRecordMapMsSymbol(pdb, reader);
@ -650,8 +698,7 @@ public class SymbolApplierFactory {
default: default:
// This should never happen (unless we missed something // This should never happen (unless we missed something
// or MSFT has added new in a version we do not handle. // or MSFT has added new in a version we do not handle.
applicator.getPdbApplicatorMetrics().witnessCannotApplySymbolType(symbol); applier = new NoSymbolApplier(applicator, symbol);
applier = new NoSymbolApplier(applicator, iter);
break; break;
} }
return applier; return applier;

View file

@ -21,7 +21,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; 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.AbstractMsSymbol;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
/** /**
@ -174,12 +173,6 @@ public class SymbolGroup {
try { try {
startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber); 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) { catch (CancelledException e) {
startingOffset = 0; startingOffset = 0;
lengthSymbols = 0; // essentially null out iterator with zero length lengthSymbols = 0; // essentially null out iterator with zero length

View file

@ -27,38 +27,51 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link TrampolineMsSymbol} symbols. * Applier for {@link TrampolineMsSymbol} symbols.
*/ */
public class TrampolineSymbolApplier extends MsSymbolApplier public class TrampolineSymbolApplier extends MsSymbolApplier implements DirectSymbolApplier {
implements DeferrableFunctionSymbolApplier { //public class TrampolineSymbolApplier extends MsSymbolApplier
// implements DeferrableFunctionSymbolApplier { // Question of whether we need to do work later
private TrampolineMsSymbol symbol; private TrampolineMsSymbol symbol;
private Address address;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public TrampolineSymbolApplier(DefaultPdbApplicator applicator, TrampolineMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof TrampolineMsSymbol)) {
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
symbol = (TrampolineMsSymbol) abstractSymbol;
address = applicator.getAddress(symbol);
} }
@Override // TODO? If we wanted to be able to apply this symbol to a different address, we should
void applyTo(MsSymbolApplier applyToApplier) { // review code in FunctionSymbolApplier. Note, however, that there are two addresses
// Do nothing. // that need to be dealt with here, and each could have a different address with a different
} // delta from the specified address.
@Override @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. // We know the size of this trampoline, so use it to restrict the disassembly.
Address targetAddress = Address targetAddress =
applicator.getAddress(symbol.getSegmentTarget(), symbol.getOffsetTarget()); 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 target = null;
Function thunk = null; Function thunk = null;
@ -71,23 +84,17 @@ public class TrampolineSymbolApplier extends MsSymbolApplier
if (target != null && thunk != null) { if (target != null && thunk != null) {
thunk.setThunkedFunction(target); thunk.setThunkedFunction(target);
} }
applicator.scheduleDeferredFunctionWork(this); applicator.scheduleDisassembly(address);
// TODO: should we schedule at targetAddress too?
// int thunkModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionThunk(),
// symbol.getOffsetThunk());
// int targetModule = findModuleNumberBySectionOffsetContribution(symbol.getSectionTarget(),
// symbol.getOffsetTarget());
} }
@Override private TrampolineMsSymbol getValidatedSymbol(MsSymbolIterator iter, boolean iterate) {
public Address getAddress() { AbstractMsSymbol abstractSymbol = iterate ? iter.next() : iter.peek();
return address; 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.
} }

View file

@ -28,42 +28,45 @@ import ghidra.util.exception.CancelledException;
/** /**
* Applier for {@link AbstractUserDefinedTypeMsSymbol} symbols. * Applier for {@link AbstractUserDefinedTypeMsSymbol} symbols.
*/ */
public class TypedefSymbolApplier extends MsSymbolApplier { public class TypedefSymbolApplier extends MsSymbolApplier
implements DirectSymbolApplier /* , NestableSymbolApplier*/ {
private DataType resolvedDataType = null; private DataType resolvedDataType = null;
private AbstractUserDefinedTypeMsSymbol udtSymbol; private AbstractUserDefinedTypeMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public TypedefSymbolApplier(DefaultPdbApplicator applicator,
super(applicator, iter); AbstractUserDefinedTypeMsSymbol symbol) {
AbstractMsSymbol abstractSymbol = iter.next(); super(applicator);
if (!(abstractSymbol instanceof AbstractUserDefinedTypeMsSymbol)) { this.symbol = symbol;
throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName());
}
udtSymbol = (AbstractUserDefinedTypeMsSymbol) abstractSymbol;
} }
@Override @Override
void applyTo(MsSymbolApplier applyToApplier) { public void apply(MsSymbolIterator iter) throws PdbException, CancelledException {
// Do nothing getValidatedSymbol(iter, true);
resolvedDataType = applyUserDefinedTypeMsSymbol();
} }
@Override // TODO: employ something like this for when adding "Implements NestableSymbolApplier" to class
void apply() throws PdbException, CancelledException { // @Override
resolvedDataType = applyUserDefinedTypeMsSymbol(udtSymbol); // 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. * Returns the name.
* @return Name. * @return Name.
*/ */
String getName() { String getName() {
return udtSymbol.getName(); return symbol.getName();
} }
/** /**
@ -71,7 +74,7 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
* @return Type record number. * @return Type record number.
*/ */
RecordNumber getTypeRecordNumber() { RecordNumber getTypeRecordNumber() {
return udtSymbol.getTypeRecordNumber(); return symbol.getTypeRecordNumber();
} }
DataType getResolvedDataType() throws PdbException { DataType getResolvedDataType() throws PdbException {
@ -82,18 +85,19 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
} }
// Typedefs // Typedefs
private DataType applyUserDefinedTypeMsSymbol(AbstractUserDefinedTypeMsSymbol symbol) private DataType applyUserDefinedTypeMsSymbol()
throws CancelledException, PdbException { throws CancelledException, PdbException {
String name = symbol.getName(); String name = symbol.getName();
AbstractMsType mType = applicator.getPdb().getTypeRecord(getTypeRecordNumber()); RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
MsTypeApplier applier = applicator.getTypeApplier(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 ???? // TODO:... NOT SURE IF WILL ALWAYS BE A DATATYPE OR WILL BE A VARIABLE OR ????
if (applier == null) { if (applier == null) {
return null; return null;
} }
DataType dataType = applicator.getCompletedDataType(getTypeRecordNumber()); DataType dataType = applicator.getCompletedDataType(typeRecordNumber);
if (dataType == null) { if (dataType == null) {
return null; return null;
} }
@ -120,4 +124,14 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
return applicator.resolve(typedef); 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;
}
} }

View file

@ -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;
}
}

View file

@ -28,44 +28,47 @@ import ghidra.util.exception.CancelledException;
* because we do not know its usage or have examples, but we have implemented * because we do not know its usage or have examples, but we have implemented
* the block management portion. * the block management portion.
*/ */
public class WithSymbolApplier extends MsSymbolApplier { public class WithSymbolApplier extends MsSymbolApplier
implements BlockNestingSymbolApplier, NestableSymbolApplier { // Not sure about nestable
private AbstractWithMsSymbol symbol; private AbstractWithMsSymbol symbol;
/** /**
* Constructor * Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working. * @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) { public WithSymbolApplier(DefaultPdbApplicator applicator, AbstractWithMsSymbol symbol) {
super(applicator, iter); super(applicator);
AbstractMsSymbol abstractSymbol = iter.next(); this.symbol = symbol;
if (!(abstractSymbol instanceof AbstractWithMsSymbol)) { }
// 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( throw new AssertException(
"Invalid symbol type: " + abstractSymbol.getClass().getSimpleName()); "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());
}
}
} }