mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-3991 PDB progress on symbol appliers
This commit is contained in:
parent
e73d2088e4
commit
4bcabe6787
43 changed files with 2088 additions and 1353 deletions
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -29,27 +29,39 @@ import ghidra.util.exception.CancelledException;
|
||||||
/**
|
/**
|
||||||
* Applier for {@link AbstractDataMsSymbol} symbols.
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -424,32 +424,29 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
AbstractMsSymbol symbol = iter.peek(); //temporary during development
|
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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -28,42 +28,45 @@ import ghidra.util.exception.CancelledException;
|
||||||
/**
|
/**
|
||||||
* Applier for {@link AbstractUserDefinedTypeMsSymbol} symbols.
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue