mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 13:11:47 +00:00
Merge remote-tracking branch 'origin/GP-4725_ghizard_PDBUniversal_source_line_investigations--SQUASHED'
This commit is contained in:
commit
22f95a5eba
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -669,7 +669,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||
writer.write("\nversionNumber: " + versionNumber);
|
||||
writer.write("\nsignature: " + Integer.toHexString(signature));
|
||||
writer.write("\nage: " + pdbAge);
|
||||
writer.write("End DirectoryHeader-----------------------------------------");
|
||||
writer.write("\nEnd DirectoryHeader-----------------------------------------");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -17,8 +17,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@ -30,6 +29,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class FileChecksumsC13Section extends C13Section {
|
||||
|
||||
private List<C13FileChecksum> fileChecksums = new ArrayList<>();
|
||||
private Map<Integer, C13FileChecksum> fileChecksumsByOffset = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Parse and return a {@link FileChecksumsC13Section}.
|
||||
@ -50,8 +50,10 @@ public class FileChecksumsC13Section extends C13Section {
|
||||
super(ignore);
|
||||
while (reader.numRemaining() >= C13FileChecksum.getBaseRecordSize()) {
|
||||
monitor.checkCancelled();
|
||||
int offset = reader.getIndex();
|
||||
C13FileChecksum fileChecksum = new C13FileChecksum(reader);
|
||||
fileChecksums.add(fileChecksum);
|
||||
fileChecksumsByOffset.put(offset, fileChecksum);
|
||||
}
|
||||
if (reader.hasMore()) {
|
||||
Msg.debug(FileChecksumsC13Section.class,
|
||||
@ -67,6 +69,15 @@ public class FileChecksumsC13Section extends C13Section {
|
||||
return fileChecksums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the C13 file checksum for the offset of the record in the checksum table
|
||||
* @param offset the offset of the record
|
||||
* @return the checksum or null if record not found
|
||||
*/
|
||||
public C13FileChecksum getFileChecksumByOffset(int offset) {
|
||||
return fileChecksumsByOffset.get(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: num checksums = %d", getClass().getSimpleName(),
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -336,7 +336,7 @@ public class Module {
|
||||
writer.append(String.format("Offset: 0X%08X\n", symbolIter.getCurrentOffset()));
|
||||
writer.append(symbol.toString());
|
||||
}
|
||||
writer.write("End Symbols-------------------------------------------------\n");
|
||||
writer.write("\nEnd Symbols-------------------------------------------------\n");
|
||||
}
|
||||
|
||||
private void dumpC11Lines(Writer writer) throws IOException, CancelledException, PdbException {
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -132,6 +132,14 @@ public abstract class ModuleInformation {
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the object file
|
||||
* @return name of the object file
|
||||
*/
|
||||
public String getObjectFileName() {
|
||||
return objectFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link SectionContribution} of the module
|
||||
* @return {@link SectionContribution} of the module
|
||||
@ -140,6 +148,15 @@ public abstract class ModuleInformation {
|
||||
return sectionContribution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename for the index
|
||||
* @param index the index for which the filename was stored
|
||||
* @return the filename
|
||||
*/
|
||||
public String getFilenameByIndex(int index) {
|
||||
return filenamesArray.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename for the offset
|
||||
* @param offset the offset for which the filename was stored
|
||||
@ -205,11 +222,12 @@ public abstract class ModuleInformation {
|
||||
// Package-Protected Internals
|
||||
//==============================================================================================
|
||||
/**
|
||||
* Stores the filename for the offset given
|
||||
* Stores the filename for the offset given. Also adds name to array, so order of call matters
|
||||
* @param offset the offset for which to store the filename
|
||||
* @param filename the filename to store
|
||||
*/
|
||||
protected void addFilenameByOffset(int offset, String filename) {
|
||||
filenamesArray.add(filename);
|
||||
filenameByOffset.put(offset, filename);
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -46,6 +46,22 @@ public class ModuleInformation600 extends ModuleInformation {
|
||||
reader.parseNullTerminatedString(pdb.getPdbReaderOptions().getOneByteCharset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Not yet sure what this field represents
|
||||
* @return the value
|
||||
*/
|
||||
public long getNameIndexSourceFile() {
|
||||
return nameIndexSourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not yet sure what this field represents
|
||||
* @return the value
|
||||
*/
|
||||
public long getNameCompilerPdbPath() {
|
||||
return nameIndexCompilerPdbPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dumpAdditionals(Writer writer) throws IOException {
|
||||
writer.write("\nnameIndexSourceFile: " + nameIndexSourceFile);
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -45,6 +45,19 @@ public class FunctionIdMsType extends AbstractMsType {
|
||||
reader.skipPadding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public RecordNumber getScopeIdRecordNumber() {
|
||||
return scopeIdRecordNumber;
|
||||
}
|
||||
|
||||
public RecordNumber getFunctionTypeRecordNumber() {
|
||||
return functionTypeRecordNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPdbId() {
|
||||
return PDB_ID;
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -45,6 +45,19 @@ public class MemberFunctionIdMsType extends AbstractMsType {
|
||||
reader.skipPadding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public RecordNumber getParentTypeRecordNumber() {
|
||||
return parentTypeRecordNumber;
|
||||
}
|
||||
|
||||
public RecordNumber getFunctionTypeRecordNumber() {
|
||||
return functionTypeRecordNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPdbId() {
|
||||
return PDB_ID;
|
||||
|
@ -176,6 +176,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
|
||||
private PdbApplicatorMetrics pdbApplicatorMetrics;
|
||||
|
||||
private boolean preWorkDone = false;
|
||||
|
||||
//==============================================================================================
|
||||
private Program program;
|
||||
|
||||
@ -197,6 +199,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
private AbstractMsSymbol compileSymbolForLinkerModule = null;
|
||||
private boolean processedLinkerModule = false;
|
||||
|
||||
//==============================================================================================
|
||||
private PdbSourceLinesApplicator linesApplicator;
|
||||
|
||||
//==============================================================================================
|
||||
// If we have symbols and memory with VBTs in them, then a better VbtManager is created.
|
||||
VbtManager vbtManager;
|
||||
@ -342,6 +347,14 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// For use by Function Symbol appliers, but might also get used during testing
|
||||
void setFunctionLength(Address address, int length) {
|
||||
if (linesApplicator != null) {
|
||||
linesApplicator.setFunctionLength(address, length);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
private void doPdbTypesAndMainSymbolsWork() throws PdbException, CancelledException {
|
||||
switch (applicatorOptions.getProcessingControl()) {
|
||||
@ -372,6 +385,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
private void doPdbFunctionInternalsWork() throws PdbException, CancelledException {
|
||||
if (program != null) {
|
||||
doDeferredFunctionProcessing();
|
||||
// Processing is done here because we want function bodies to be processed,
|
||||
// as that allows us to fetch the function start, given any address within
|
||||
// the function
|
||||
if (applicatorOptions.applySourceLineNumbers()) {
|
||||
linesApplicator.process();
|
||||
}
|
||||
// Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||
// options.setBoolean(PdbParserConstants.PDB_LOADED, true);
|
||||
}
|
||||
@ -582,6 +601,11 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
// Investigations into source/line info
|
||||
recordNumbersByFileName = new HashMap<>();
|
||||
recordNumbersByModuleNumber = new HashMap<>();
|
||||
|
||||
if (program != null && applicatorOptions.applySourceLineNumbers()) {
|
||||
linesApplicator = new PdbSourceLinesApplicator(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -591,7 +615,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
* @throws PdbException upon error in processing components
|
||||
*/
|
||||
private void doPdbPreWork() throws CancelledException, PdbException {
|
||||
|
||||
if (preWorkDone) {
|
||||
return;
|
||||
}
|
||||
pdbApplicatorMetrics = pdbAnalysisLookupState.getPdbApplicatorMetrics();
|
||||
pdbAddressManager = pdbAnalysisLookupState.getPdbAddressManager();
|
||||
complexTypeMapper = pdbAnalysisLookupState.getComplexTypeMapper();
|
||||
@ -613,6 +639,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
else {
|
||||
vbtManager = new VbtManager(getDataTypeManager());
|
||||
}
|
||||
preWorkDone = true;
|
||||
}
|
||||
|
||||
private void validateAndSetParameters(Program programParam,
|
||||
@ -1369,7 +1396,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
* @return the Address
|
||||
*/
|
||||
Address getAddress(int segment, long offset) {
|
||||
return pdbAddressManager.getRawAddress(segment, offset);
|
||||
return pdbAddressManager.getAddress(segment, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,6 +243,10 @@ public class FunctionSymbolApplier extends AbstractBlockContextApplier
|
||||
String name = symbol.getName();
|
||||
Address address = applicator.getAddress(symbol);
|
||||
|
||||
// Save off the function length for lines processing
|
||||
Long functionLength = symbol.getProcedureLength();
|
||||
applicator.setFunctionLength(address, functionLength.intValue());
|
||||
|
||||
function = applicator.getExistingFunction(address);
|
||||
if (function == null) {
|
||||
// Skip all interim symbols records
|
||||
|
@ -358,7 +358,7 @@ public class PdbAddressManager {
|
||||
private void determineMemoryBlocks() throws CancelledException {
|
||||
AbstractPdb pdb = applicator.getPdb();
|
||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||
if(debugInfo == null) {
|
||||
if (debugInfo == null) {
|
||||
return;
|
||||
}
|
||||
segmentMapList = debugInfo.getSegmentMapList();
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -112,6 +112,8 @@ public class PdbApplicatorMetrics {
|
||||
private Set<Class<? extends AbstractMsSymbol>> unexpectedGlobalSymbols = new HashSet<>();
|
||||
private Set<Class<? extends AbstractMsSymbol>> unexpectedPublicSymbols = new HashSet<>();
|
||||
private boolean witnessEnumerateNarrowing = false;
|
||||
private boolean witnessC11Lines = false;
|
||||
private boolean witnessC13InlineeLines = false;
|
||||
|
||||
/**
|
||||
* Method to capture data/item type that cannot be applied.
|
||||
@ -215,6 +217,22 @@ public class PdbApplicatorMetrics {
|
||||
unexpectedMemberFunctionContainerTypes.add(type.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to capture witnessing of C11Lines.
|
||||
*/
|
||||
void witnessC11Lines() {
|
||||
witnessC11Lines = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to capture witnessing of C13InlineeLines.
|
||||
*/
|
||||
void witnessC13InlineeLines() {
|
||||
// C13InlineeLines are prevalent, but we want to be able to inform the user that
|
||||
// we haven't processed them
|
||||
witnessC13InlineeLines = true;
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
|
||||
/**
|
||||
@ -233,6 +251,7 @@ public class PdbApplicatorMetrics {
|
||||
builder.append(reportUnexpectedPublicSymbols());
|
||||
builder.append(reportUnexpectedGlobalSymbols());
|
||||
builder.append(reportEnumerateNarrowing());
|
||||
builder.append(reportSourceLineProcessing()); // can be removed once we can process
|
||||
|
||||
if (builder.length() == 0) {
|
||||
return; // nothing reported
|
||||
@ -324,4 +343,17 @@ public class PdbApplicatorMetrics {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Routine can be modified to remove each as we can process each. Routine can be removed once
|
||||
// we can process both.
|
||||
private String reportSourceLineProcessing() {
|
||||
String result = "";
|
||||
if (witnessC11Lines) {
|
||||
result = "Could not process C11Lines\n";
|
||||
}
|
||||
if (witnessC13InlineeLines) {
|
||||
result += "Could not process C13InlineeLines\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -41,6 +41,15 @@ public class PdbApplicatorOptions {
|
||||
private static final PdbApplicatorControl DEFAULT_CONTROL = PdbApplicatorControl.ALL;
|
||||
private PdbApplicatorControl control;
|
||||
|
||||
// Apply Source Line Numbers.
|
||||
private static final String OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS =
|
||||
"Apply Source Line Numbers"; // DWARF says "Output Source Line Info", but we use "Apply"
|
||||
private static final String OPTION_DESCRIPTION_APPLY_SOURCE_LINE_NUMBERS =
|
||||
"Create source map entries containing the source code filename, line number, address, and" +
|
||||
" length at each location provided in the PDB data.";
|
||||
private static final boolean DEFAULT_APPLY_SOURCE_LINE_NUMBERS = false;
|
||||
private boolean applySourceLineNumbers;
|
||||
|
||||
// Apply Code Block Comments.
|
||||
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
|
||||
"Apply Code Scope Block Comments";
|
||||
@ -181,6 +190,11 @@ public class PdbApplicatorOptions {
|
||||
private void registerOptions(Options options, boolean enableControl) {
|
||||
HelpLocation help = null;
|
||||
|
||||
//TODO: Uncomment the following for GP-3883
|
||||
// options.registerOption(OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS,
|
||||
// applySourceLineNumbers, help,
|
||||
// OPTION_DESCRIPTION_APPLY_SOURCE_LINE_NUMBERS);
|
||||
|
||||
if (DEVELOPER_MODE || enableControl) {
|
||||
options.registerOption(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL, help,
|
||||
OPTION_DESCRIPTION_PROCESSING_CONTROL);
|
||||
@ -189,6 +203,11 @@ public class PdbApplicatorOptions {
|
||||
// PdbApplicatorOptions
|
||||
if (DEVELOPER_MODE) {
|
||||
|
||||
//TODO: Remove the following line for GP-3883
|
||||
options.registerOption(OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS,
|
||||
applySourceLineNumbers, help,
|
||||
OPTION_DESCRIPTION_APPLY_SOURCE_LINE_NUMBERS);
|
||||
|
||||
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
|
||||
applyCodeScopeBlockComments, help,
|
||||
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
|
||||
@ -232,6 +251,10 @@ public class PdbApplicatorOptions {
|
||||
|
||||
private void loadOptions(Options options, boolean enableControl) {
|
||||
|
||||
//TODO: Uncomment the following for GP-3883
|
||||
// applySourceLineNumbers = options.getBoolean(
|
||||
// OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS, applySourceLineNumbers);
|
||||
|
||||
if (DEVELOPER_MODE || enableControl) {
|
||||
control = options.getEnum(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL);
|
||||
}
|
||||
@ -239,6 +262,10 @@ public class PdbApplicatorOptions {
|
||||
// PdbApplicatorOptions
|
||||
if (DEVELOPER_MODE) {
|
||||
|
||||
//TODO: Remove the following line for GP-3883
|
||||
applySourceLineNumbers = options.getBoolean(
|
||||
OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS, applySourceLineNumbers);
|
||||
|
||||
applyCodeScopeBlockComments = options.getBoolean(
|
||||
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
|
||||
|
||||
@ -288,6 +315,7 @@ public class PdbApplicatorOptions {
|
||||
* Set the options to their default values
|
||||
*/
|
||||
public void setDefaults() {
|
||||
applySourceLineNumbers = DEFAULT_APPLY_SOURCE_LINE_NUMBERS;
|
||||
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
|
||||
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
|
||||
excludeInstructionLabels = DEFAULT_EXCLUDE_INSTRUCTION_LABELS;
|
||||
@ -300,6 +328,22 @@ public class PdbApplicatorOptions {
|
||||
compositeLayout = DEFAULT_CLASS_LAYOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable developmental debug of applying source line numbers.
|
||||
* @param applySourceLineNumbers {@code true} to turn on applySourceLineNumbers
|
||||
*/
|
||||
public void setApplySourceLineNumbers(boolean applySourceLineNumbers) {
|
||||
this.applySourceLineNumbers = applySourceLineNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if applySourceLineNumbers is "on."
|
||||
* @return {@code true} if applySourceLineNumbers is "on."
|
||||
*/
|
||||
public boolean applySourceLineNumbers() {
|
||||
return applySourceLineNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable developmental debug.
|
||||
* @param applyCodeScopeBlockComments {@code true} to turn applyCodeScopeBlockComments on
|
||||
|
@ -0,0 +1,378 @@
|
||||
/* ###
|
||||
* 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.*;
|
||||
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.Module;
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
||||
/**
|
||||
* Helper class to PdbApplicator for applying source line information
|
||||
*/
|
||||
public class PdbSourceLinesApplicator {
|
||||
|
||||
private DefaultPdbApplicator applicator;
|
||||
private AbstractPdb pdb;
|
||||
private Program program;
|
||||
private MessageLog log;
|
||||
|
||||
private Map<Address, Integer> functionLengthByAddress;
|
||||
|
||||
// private SourceFileManager manager;
|
||||
|
||||
//==============================================================================================
|
||||
/**
|
||||
* Constructor for PdbSourceLinesApplicator
|
||||
* @param applicator the PdbApplicator that we are helping
|
||||
*/
|
||||
public PdbSourceLinesApplicator(DefaultPdbApplicator applicator) {
|
||||
Objects.requireNonNull(applicator, "applicator cannot be null");
|
||||
this.applicator = applicator;
|
||||
this.program = applicator.getProgram();
|
||||
Objects.requireNonNull(program, "program cannot be null");
|
||||
this.pdb = applicator.getPdb();
|
||||
Objects.requireNonNull(pdb, "pdb cannot be null");
|
||||
this.log = applicator.getMessageLog();
|
||||
|
||||
functionLengthByAddress = new HashMap<>();
|
||||
|
||||
//manager = program.getSourceFileManager();
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
/**
|
||||
* When determined elsewhere, and before {@code process()} is called, this method should
|
||||
* be used to populate the lengths of functions in to this lines applier. If not done, then
|
||||
* some source line code lengths might not be correct
|
||||
* @param address the address
|
||||
* @param length the function length
|
||||
*/
|
||||
public void setFunctionLength(Address address, int length) {
|
||||
functionLengthByAddress.put(address, length);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
/**
|
||||
* Process all Module line information
|
||||
* @throws CancelledException upon user cancellation
|
||||
*/
|
||||
public void process() throws CancelledException {
|
||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||
if (debugInfo == null) {
|
||||
Msg.info(this, "PDB: Missing DebugInfo - cannot process line numbers.");
|
||||
return;
|
||||
}
|
||||
if (!program.hasExclusiveAccess()) {
|
||||
Msg.showWarn(this, null, "Cannot Apply SourceMap Information",
|
||||
"Exclusive access to the program is required to apply source map information");
|
||||
return;
|
||||
}
|
||||
|
||||
// Not processing user defined "Types" source information. TODO: ???
|
||||
|
||||
int numModules = debugInfo.getNumModules();
|
||||
for (int num = 1; num <= numModules; num++) {
|
||||
pdb.checkCancelled();
|
||||
Module module = debugInfo.getModule(num);
|
||||
processC11Lines(module);
|
||||
processC13Sections(module);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Suppress: for moduleInfo due to commented out call to processC11Line. Remove suppress when
|
||||
// no longer commented out.
|
||||
@SuppressWarnings("unused")
|
||||
private void processC11Lines(Module module)
|
||||
throws CancelledException {
|
||||
ModuleInformation moduleInfo = module.getModuleInformation();
|
||||
try {
|
||||
C11Lines c11Lines = module.getLineInformation();
|
||||
if (c11Lines != null) {
|
||||
// TODO: Figure out how to process and what to do with inline information. When
|
||||
// ready, uncomment the following code
|
||||
// processC11Line(moduleInfo, c11Lines);
|
||||
// TODO: remove this and underlying Metrics logic once we have a viable processing
|
||||
// technique for inlinee lines
|
||||
applicator.getPdbApplicatorMetrics().witnessC11Lines();
|
||||
}
|
||||
}
|
||||
catch (PdbException e) {
|
||||
log.appendMsg("PDB: Failed to process C11Lines due to " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress: for not being used and for unfinished implementation with unused variables
|
||||
@SuppressWarnings("unused")
|
||||
// TODO: Figure out how to process and what to do with inline information. When
|
||||
// ready, uncomment the following code
|
||||
private void processC11Line(ModuleInformation moduleInfo,
|
||||
C11Lines c11Lines) {
|
||||
Msg.info(this, "PDB: Unimplemented... unable to process C11 Lines");
|
||||
// TODO: See C11Lines dump method for indications of how we might process
|
||||
int cFile = c11Lines.getNumFiles();
|
||||
int cSet = c11Lines.getNumSegments();
|
||||
List<Integer> baseSrcFile = c11Lines.getBaseSrcFiles();
|
||||
List<C11LinesStartEnd> startEnd = c11Lines.getStartEnd();
|
||||
List<Integer> seg = c11Lines.getSegments();
|
||||
List<Integer> ccSegs = c11Lines.getPerFileNumSegments();
|
||||
List<List<Integer>> baseSrcLines = c11Lines.getPerFileBaseSrcLines();
|
||||
List<List<C11LinesStartEnd>> startEnds = c11Lines.getPerFileStartEndRecords();
|
||||
List<String> names = c11Lines.getFileNames();
|
||||
List<List<Integer>> segmentNumbers = c11Lines.getPerFileSegmentNumbers();
|
||||
List<List<List<Long>>> offsets = c11Lines.getPerFilePerSegmentOffsets();
|
||||
List<List<List<Integer>>> lineNumbers = c11Lines.getPerFilePerSegmentLineNumbers();
|
||||
// do something
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
private void processC13Sections(Module module)
|
||||
throws CancelledException {
|
||||
|
||||
ModuleInformation moduleInfo = module.getModuleInformation();
|
||||
|
||||
C13SectionIterator<FileChecksumsC13Section> c13FileChecksumIterator;
|
||||
C13SectionIterator<LinesC13Section> linesIterator;
|
||||
C13SectionIterator<IlLinesC13Section> ilLinesIterator;
|
||||
C13SectionIterator<InlineeLinesC13Section> inlineeLinesIterator;
|
||||
try {
|
||||
c13FileChecksumIterator =
|
||||
module.getC13SectionFilteredIterator(FileChecksumsC13Section.class);
|
||||
linesIterator = module.getC13SectionFilteredIterator(LinesC13Section.class);
|
||||
ilLinesIterator = module.getC13SectionFilteredIterator(IlLinesC13Section.class);
|
||||
inlineeLinesIterator =
|
||||
module.getC13SectionFilteredIterator(InlineeLinesC13Section.class);
|
||||
}
|
||||
catch (PdbException e) {
|
||||
log.appendMsg("PDB: Failed to process C13Sections due to " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// Must do file checksums first, as they have the file information for the source lines
|
||||
// Make sure there is one and only one
|
||||
FileChecksumsC13Section fileChecksumsSection = null;
|
||||
while (c13FileChecksumIterator.hasNext()) {
|
||||
pdb.checkCancelled();
|
||||
FileChecksumsC13Section section = c13FileChecksumIterator.next();
|
||||
if (fileChecksumsSection != null) {
|
||||
Msg.warn(this, "More than on FileChecksumC13Section found in module " +
|
||||
moduleInfo.getModuleName());
|
||||
break;
|
||||
}
|
||||
fileChecksumsSection = section;
|
||||
}
|
||||
if (fileChecksumsSection == null) {
|
||||
// No information for this module
|
||||
return;
|
||||
}
|
||||
|
||||
// Process lines, ilLines, and inlineeLines
|
||||
while (linesIterator.hasNext()) {
|
||||
pdb.checkCancelled();
|
||||
LinesC13Section linesSection = linesIterator.next();
|
||||
processC13FileRecords(moduleInfo, fileChecksumsSection, linesSection, false);
|
||||
}
|
||||
while (ilLinesIterator.hasNext()) {
|
||||
pdb.checkCancelled();
|
||||
IlLinesC13Section ilLinesSection = ilLinesIterator.next();
|
||||
processC13FileRecords(moduleInfo, fileChecksumsSection, ilLinesSection, true);
|
||||
}
|
||||
// TODO: Figure out how to process and what to do with inline information. When
|
||||
// ready, uncomment the following code
|
||||
// while (inlineeLinesIterator.hasNext()) {
|
||||
// monitor.checkCancelled();
|
||||
// InlineeLinesC13Section inlineeSection = inlineeLinesIterator.next();
|
||||
// processC13InlineeLines(moduleInfo, fileChecksumsSection, inlineeSection);
|
||||
// }
|
||||
// TODO: remove this and underlying Metrics logic once we have a viable processing
|
||||
// technique for inlinee lines
|
||||
if (inlineeLinesIterator.hasNext()) {
|
||||
applicator.getPdbApplicatorMetrics().witnessC13InlineeLines();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
private void processC13FileRecords(ModuleInformation moduleInfo,
|
||||
FileChecksumsC13Section fileChecksumsC13Section, AbstractLinesC13Section c13Lines,
|
||||
boolean isIlLines)
|
||||
throws CancelledException {
|
||||
|
||||
// Something else to look into: ModuleInformation600 version has more fields that we do
|
||||
// not know their usefulness at this time. These are:
|
||||
// String moduleName = moduleInfo.getModuleName();
|
||||
// String objectFileName = moduleInfo.getObjectFileName();
|
||||
List<C13FileRecord> fileRecords = c13Lines.getFileRecords();
|
||||
|
||||
long offCon = c13Lines.getOffCon();
|
||||
int segCon = c13Lines.getSegCon();
|
||||
// Currently not using getFlags() and getLenCon()
|
||||
for (C13FileRecord fileRecord : fileRecords) {
|
||||
pdb.checkCancelled();
|
||||
int fileId = fileRecord.getFileId();
|
||||
SourceFile sourceFile = getSourceFile(fileChecksumsC13Section, fileId);
|
||||
|
||||
// Everything we've see to this point shows that the address come in an increasing,
|
||||
// but non-strictly increasing order. Also, there is not a field to designate the
|
||||
// number of bytes of memory that pertain to each line record, but everything we've
|
||||
// seen seems to indicate that we can do the difference between the record addresses
|
||||
// to get the length needed. However, the last record doesn't have a "next" record
|
||||
// to do the difference with, but that is where function length comes into play.
|
||||
// And if we work in reverse order (we do not care if the records are created and
|
||||
// put into the DB in reverse order), then we can easily calculate the lengths.
|
||||
long lastValue = -1;
|
||||
Long numLines = fileRecord.getNLines();
|
||||
List<C13LineRecord> lineRecords = fileRecord.getLineRecords();
|
||||
for (int index = numLines.intValue() - 1; index >= 0; index--) {
|
||||
pdb.checkCancelled();
|
||||
C13LineRecord lineRecord = lineRecords.get(index);
|
||||
Long lineNumStart = lineRecord.getLineNumStart();
|
||||
// If we wanted the line end value, we could calculate it as:
|
||||
// Long lineNumEnd = lineNumStart + lineRecord.getDeltaLineEnd()
|
||||
long offset = lineRecord.getOffset();
|
||||
long actualOffset = offset + offCon;
|
||||
Address address = applicator.getAddress(segCon, actualOffset);
|
||||
if (lastValue == -1) {
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
Function function = functionManager.getFunctionContaining(address);
|
||||
if (function != null) {
|
||||
Address functionAddress = function.getEntryPoint();
|
||||
lastValue = functionLengthByAddress.getOrDefault(functionAddress, -1);
|
||||
}
|
||||
// If function was null, then lastValue stays -1 until overwritten
|
||||
}
|
||||
Long length = lastValue - offset;
|
||||
// TODO: remove next line once we initialize an appropriate lastValue
|
||||
length = Long.max(length, 0); // last record gets length zero if lastValue was -1
|
||||
lastValue = offset;
|
||||
|
||||
// Note: we are not currently using boolean isStatement = lineRecord.isStatement()
|
||||
|
||||
// Note: we are not using this call, but users might be interested in the fact of
|
||||
// 0xfeefee and 0xf00f00.
|
||||
// lineRecord.isSpecialLine();
|
||||
|
||||
// TODO: There might be something we can do with the boolean isIlLines
|
||||
// Seems that the pdb.xml is not necessarily doing anything different
|
||||
|
||||
applyRecord(sourceFile, address, lineNumStart.intValue(),
|
||||
length.intValue());
|
||||
|
||||
// Note: We are not processing column records, but they are available.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Suppress: for not being used and for unfinished implementation with unused variables
|
||||
@SuppressWarnings("unused")
|
||||
private void processC13InlineeLines(ModuleInformation moduleInfo,
|
||||
FileChecksumsC13Section fileChecksumsC13Section, InlineeLinesC13Section c13InlineeLines)
|
||||
throws CancelledException {
|
||||
|
||||
// Something else to look into: ModuleInformation600 version has more fields that we do
|
||||
// not know their usefulness at this time
|
||||
//String moduleName = moduleInfo.getModuleName();
|
||||
//String objectFileName = moduleInfo.getObjectFileName();
|
||||
List<C13InlineeSourceLine> inlineeLines = c13InlineeLines.getInlineeLines();
|
||||
|
||||
for (C13InlineeSourceLine inlineeLine : inlineeLines) {
|
||||
pdb.checkCancelled();
|
||||
|
||||
int fileId = inlineeLine.getFileId();
|
||||
SourceFile sourceFile = getSourceFile(fileChecksumsC13Section, fileId);
|
||||
|
||||
Long inlinee = inlineeLine.getInlinee();
|
||||
RecordNumber recordNumber = RecordNumber.itemRecordNumber(inlinee.intValue());
|
||||
AbstractMsType type = applicator.getTypeRecord(recordNumber);
|
||||
//TODO: might want to create TypeAppliers for MemberFunctionIdMsType and
|
||||
// FunctionIdMsType and any of their derivatives and use them to do logic for the
|
||||
// types.
|
||||
if (type instanceof FunctionIdMsType functionId) {
|
||||
String name = functionId.getName();
|
||||
RecordNumber scopeIdRecordNumber = functionId.getScopeIdRecordNumber();
|
||||
AbstractMsType scope = applicator.getTypeRecord(scopeIdRecordNumber);
|
||||
// TODO: DO MORE WORK
|
||||
}
|
||||
else if (type instanceof MemberFunctionIdMsType memberFunctionId) {
|
||||
String name = memberFunctionId.getName();
|
||||
RecordNumber parentTypeRecordNumber = memberFunctionId.getParentTypeRecordNumber();
|
||||
AbstractMsType parent = applicator.getTypeRecord(parentTypeRecordNumber);
|
||||
// TODO: DO MORE WORK
|
||||
}
|
||||
else {
|
||||
// TODO: DO MORE WORK
|
||||
}
|
||||
|
||||
long lineNum = inlineeLine.getSourceLineNum();
|
||||
|
||||
if (inlineeLine instanceof C13ExtendedInlineeSourceLine extendedInlineeLine) {
|
||||
int numIds = extendedInlineeLine.getNumExtraFileIds();
|
||||
List<Integer> ids = extendedInlineeLine.getExtraFileIds();
|
||||
for (int id : ids) {
|
||||
SourceFile inlineeSourceFile = getSourceFile(fileChecksumsC13Section, id);
|
||||
// TODO: DO MORE WORK
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Temporary mock class
|
||||
private static class SourceFile {
|
||||
// Empty
|
||||
}
|
||||
|
||||
private SourceFile getSourceFile(FileChecksumsC13Section fileChecksums, int fileId) {
|
||||
return new SourceFile();
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
private void applyRecord(SourceFile sourceFile, Address address, int start, int length) {
|
||||
// Need to use getCodeUnitContaining(address) instead of getCodeUnitAt(address) because
|
||||
// there is a situation where the PDB associates a line number with the base part of an
|
||||
// instructions instead of the prefix part, such as with MSFT tool-chain emits a
|
||||
// "REP RET" (f3 c3) sequence, where the "REP" is an instruction prefix, in order to
|
||||
// avoid a branch prediction penalty for AMD processors. However, Microsoft associates
|
||||
// the line number of the instruction with the address of the "RET" (c3) instead of with
|
||||
// the address of the "REP" (f3) portion (beginning) of the instruction.
|
||||
CodeUnit cu = program.getListing().getCodeUnitContaining(address);
|
||||
if (cu == null) {
|
||||
log.appendMsg("PDB",
|
||||
"Skipping source map info (no code unit found at " + address + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
// try {
|
||||
// manager.addSourceMapEntry(sourceFile, start, address, length);
|
||||
// }
|
||||
// catch (LockException e) {
|
||||
// throw new AssertException("LockException after exclusive access verified!");
|
||||
// }
|
||||
// catch (AddressOverflowException e) {
|
||||
// log.appendMsg("PDB", "AddressOverflow for source map info: %s, %d, %s, %d"
|
||||
// .formatted(sourceFile.getPath(), start, address.toString(), length));
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
/* ###
|
||||
* 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.framework.model.DomainFile;
|
||||
import ghidra.program.model.StubProgram;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
||||
/**
|
||||
* Stub Program for some PDB tests
|
||||
*/
|
||||
|
||||
public class PdbStubProgram extends StubProgram {
|
||||
|
||||
private DomainFile domainFile;
|
||||
|
||||
private AddressSpace space;
|
||||
private AddressFactory factory;
|
||||
private static long imageBaseVal = 0x400000L;
|
||||
private Address imageBase;
|
||||
private SymbolTable symbolTable;
|
||||
private Memory memory;
|
||||
private Listing listing;
|
||||
|
||||
public PdbStubProgram(DomainFile domainFile) {
|
||||
this.domainFile = domainFile;
|
||||
space = new GenericAddressSpace("xx", 64, AddressSpace.TYPE_RAM, 0);
|
||||
factory = new DefaultAddressFactory(new AddressSpace[] { space });
|
||||
imageBase = factory.getAddress(space.getSpaceID(), imageBaseVal);
|
||||
symbolTable = new PdbStubSymbolTable();
|
||||
memory = new PdbStubMemory(imageBase);
|
||||
listing = new PdbStubListing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainFile getDomainFile() {
|
||||
return domainFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getImageBase() {
|
||||
return imageBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolTable getSymbolTable() {
|
||||
return symbolTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Memory getMemory() {
|
||||
return memory;
|
||||
}
|
||||
// @Override
|
||||
// public ProgramDataTypeManager getDataTypeManager() {
|
||||
// return dataTypeManager;
|
||||
// }
|
||||
//
|
||||
|
||||
@Override
|
||||
public AddressFactory getAddressFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listing getListing() {
|
||||
return listing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExclusiveAccess() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private class PdbStubSymbolTable extends StubSymbolTable {
|
||||
@Override
|
||||
public SymbolIterator getAllSymbols(boolean includeDynamicSymbols) {
|
||||
return SymbolIterator.EMPTY_ITERATOR;
|
||||
}
|
||||
//
|
||||
// @Override
|
||||
// public SymbolIterator getPrimarySymbolIterator(AddressSetView asv, boolean forward) {
|
||||
// return SymbolIterator.EMPTY_ITERATOR;
|
||||
// }
|
||||
}
|
||||
|
||||
private class PdbStubMemory extends StubMemory {
|
||||
|
||||
private static final int NUM_BLOCKS = 1000;
|
||||
private static final long BLOCK_SIZE = 1000000;
|
||||
private static final MemoryBlock[] blocks = new MemoryBlock[NUM_BLOCKS];
|
||||
|
||||
PdbStubMemory(Address imageBase) {
|
||||
Address address = imageBase;
|
||||
for (int block = 0; block < NUM_BLOCKS; block++) {
|
||||
// We are pre-incrementing so that we do not get a "zero" address for our
|
||||
// processing
|
||||
address = address.add(BLOCK_SIZE);
|
||||
blocks[block] = new PdbMemoryBlock(address, BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock[] getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
}
|
||||
|
||||
private class PdbMemoryBlock extends MemoryBlockStub {
|
||||
|
||||
private Address address;
|
||||
private long size;
|
||||
|
||||
PdbMemoryBlock(Address address, long size) {
|
||||
this.address = address;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getStart() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
private class PdbStubListing extends StubListing {
|
||||
|
||||
@Override
|
||||
public CodeUnit getCodeUnitContaining(Address addr) {
|
||||
return new PdbInstructionStub(addr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class PdbInstructionStub extends InstructionStub {
|
||||
|
||||
Address address;
|
||||
|
||||
PdbInstructionStub(Address addr) {
|
||||
address = addr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class StubPdbApplicator implements PdbApplicator {
|
||||
|
||||
private AbstractPdb pdb = null;
|
||||
private long originalImageBase = 0L;
|
||||
private long originalImageBase = 0x400000L;
|
||||
|
||||
private Program program = null;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user