mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-4725 - PDB work toward applying source lines information
This commit is contained in:
parent
c08736bf19
commit
91f82f9f90
15 changed files with 753 additions and 27 deletions
|
@ -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.
|
||||||
|
@ -669,7 +669,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
writer.write("\nversionNumber: " + versionNumber);
|
writer.write("\nversionNumber: " + versionNumber);
|
||||||
writer.write("\nsignature: " + Integer.toHexString(signature));
|
writer.write("\nsignature: " + Integer.toHexString(signature));
|
||||||
writer.write("\nage: " + pdbAge);
|
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");
|
* 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.
|
||||||
|
@ -17,8 +17,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -30,6 +29,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
public class FileChecksumsC13Section extends C13Section {
|
public class FileChecksumsC13Section extends C13Section {
|
||||||
|
|
||||||
private List<C13FileChecksum> fileChecksums = new ArrayList<>();
|
private List<C13FileChecksum> fileChecksums = new ArrayList<>();
|
||||||
|
private Map<Integer, C13FileChecksum> fileChecksumsByOffset = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse and return a {@link FileChecksumsC13Section}.
|
* Parse and return a {@link FileChecksumsC13Section}.
|
||||||
|
@ -50,8 +50,10 @@ public class FileChecksumsC13Section extends C13Section {
|
||||||
super(ignore);
|
super(ignore);
|
||||||
while (reader.numRemaining() >= C13FileChecksum.getBaseRecordSize()) {
|
while (reader.numRemaining() >= C13FileChecksum.getBaseRecordSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
int offset = reader.getIndex();
|
||||||
C13FileChecksum fileChecksum = new C13FileChecksum(reader);
|
C13FileChecksum fileChecksum = new C13FileChecksum(reader);
|
||||||
fileChecksums.add(fileChecksum);
|
fileChecksums.add(fileChecksum);
|
||||||
|
fileChecksumsByOffset.put(offset, fileChecksum);
|
||||||
}
|
}
|
||||||
if (reader.hasMore()) {
|
if (reader.hasMore()) {
|
||||||
Msg.debug(FileChecksumsC13Section.class,
|
Msg.debug(FileChecksumsC13Section.class,
|
||||||
|
@ -67,6 +69,15 @@ public class FileChecksumsC13Section extends C13Section {
|
||||||
return fileChecksums;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s: num checksums = %d", getClass().getSimpleName(),
|
return String.format("%s: num checksums = %d", getClass().getSimpleName(),
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -336,7 +336,7 @@ public class Module {
|
||||||
writer.append(String.format("Offset: 0X%08X\n", symbolIter.getCurrentOffset()));
|
writer.append(String.format("Offset: 0X%08X\n", symbolIter.getCurrentOffset()));
|
||||||
writer.append(symbol.toString());
|
writer.append(symbol.toString());
|
||||||
}
|
}
|
||||||
writer.write("End Symbols-------------------------------------------------\n");
|
writer.write("\nEnd Symbols-------------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpC11Lines(Writer writer) throws IOException, CancelledException, PdbException {
|
private void dumpC11Lines(Writer writer) throws IOException, CancelledException, 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.
|
||||||
|
@ -132,6 +132,14 @@ public abstract class ModuleInformation {
|
||||||
return moduleName;
|
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
|
* Returns {@link SectionContribution} of the module
|
||||||
* @return {@link SectionContribution} of the module
|
* @return {@link SectionContribution} of the module
|
||||||
|
@ -140,6 +148,15 @@ public abstract class ModuleInformation {
|
||||||
return sectionContribution;
|
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
|
* Returns the filename for the offset
|
||||||
* @param offset the offset for which the filename was stored
|
* @param offset the offset for which the filename was stored
|
||||||
|
@ -205,11 +222,12 @@ public abstract class ModuleInformation {
|
||||||
// Package-Protected Internals
|
// 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 offset the offset for which to store the filename
|
||||||
* @param filename the filename to store
|
* @param filename the filename to store
|
||||||
*/
|
*/
|
||||||
protected void addFilenameByOffset(int offset, String filename) {
|
protected void addFilenameByOffset(int offset, String filename) {
|
||||||
|
filenamesArray.add(filename);
|
||||||
filenameByOffset.put(offset, filename);
|
filenameByOffset.put(offset, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -46,6 +46,22 @@ public class ModuleInformation600 extends ModuleInformation {
|
||||||
reader.parseNullTerminatedString(pdb.getPdbReaderOptions().getOneByteCharset());
|
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
|
@Override
|
||||||
protected void dumpAdditionals(Writer writer) throws IOException {
|
protected void dumpAdditionals(Writer writer) throws IOException {
|
||||||
writer.write("\nnameIndexSourceFile: " + nameIndexSourceFile);
|
writer.write("\nnameIndexSourceFile: " + nameIndexSourceFile);
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -45,6 +45,19 @@ public class FunctionIdMsType extends AbstractMsType {
|
||||||
reader.skipPadding();
|
reader.skipPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordNumber getScopeIdRecordNumber() {
|
||||||
|
return scopeIdRecordNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordNumber getFunctionTypeRecordNumber() {
|
||||||
|
return functionTypeRecordNumber;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPdbId() {
|
public int getPdbId() {
|
||||||
return PDB_ID;
|
return PDB_ID;
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -45,6 +45,19 @@ public class MemberFunctionIdMsType extends AbstractMsType {
|
||||||
reader.skipPadding();
|
reader.skipPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordNumber getParentTypeRecordNumber() {
|
||||||
|
return parentTypeRecordNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordNumber getFunctionTypeRecordNumber() {
|
||||||
|
return functionTypeRecordNumber;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPdbId() {
|
public int getPdbId() {
|
||||||
return PDB_ID;
|
return PDB_ID;
|
||||||
|
|
|
@ -176,6 +176,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
private PdbApplicatorMetrics pdbApplicatorMetrics;
|
private PdbApplicatorMetrics pdbApplicatorMetrics;
|
||||||
|
|
||||||
|
private boolean preWorkDone = false;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private Program program;
|
private Program program;
|
||||||
|
|
||||||
|
@ -197,6 +199,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
private AbstractMsSymbol compileSymbolForLinkerModule = null;
|
private AbstractMsSymbol compileSymbolForLinkerModule = null;
|
||||||
private boolean processedLinkerModule = false;
|
private boolean processedLinkerModule = false;
|
||||||
|
|
||||||
|
//==============================================================================================
|
||||||
|
private PdbSourceLinesApplicator linesApplicator;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// If we have symbols and memory with VBTs in them, then a better VbtManager is created.
|
// If we have symbols and memory with VBTs in them, then a better VbtManager is created.
|
||||||
VbtManager vbtManager;
|
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 {
|
private void doPdbTypesAndMainSymbolsWork() throws PdbException, CancelledException {
|
||||||
switch (applicatorOptions.getProcessingControl()) {
|
switch (applicatorOptions.getProcessingControl()) {
|
||||||
|
@ -372,6 +385,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
private void doPdbFunctionInternalsWork() throws PdbException, CancelledException {
|
private void doPdbFunctionInternalsWork() throws PdbException, CancelledException {
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
doDeferredFunctionProcessing();
|
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 options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
// options.setBoolean(PdbParserConstants.PDB_LOADED, true);
|
// options.setBoolean(PdbParserConstants.PDB_LOADED, true);
|
||||||
}
|
}
|
||||||
|
@ -582,6 +601,11 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
// Investigations into source/line info
|
// Investigations into source/line info
|
||||||
recordNumbersByFileName = new HashMap<>();
|
recordNumbersByFileName = new HashMap<>();
|
||||||
recordNumbersByModuleNumber = 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
|
* @throws PdbException upon error in processing components
|
||||||
*/
|
*/
|
||||||
private void doPdbPreWork() throws CancelledException, PdbException {
|
private void doPdbPreWork() throws CancelledException, PdbException {
|
||||||
|
if (preWorkDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
pdbApplicatorMetrics = pdbAnalysisLookupState.getPdbApplicatorMetrics();
|
pdbApplicatorMetrics = pdbAnalysisLookupState.getPdbApplicatorMetrics();
|
||||||
pdbAddressManager = pdbAnalysisLookupState.getPdbAddressManager();
|
pdbAddressManager = pdbAnalysisLookupState.getPdbAddressManager();
|
||||||
complexTypeMapper = pdbAnalysisLookupState.getComplexTypeMapper();
|
complexTypeMapper = pdbAnalysisLookupState.getComplexTypeMapper();
|
||||||
|
@ -613,6 +639,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
else {
|
else {
|
||||||
vbtManager = new VbtManager(getDataTypeManager());
|
vbtManager = new VbtManager(getDataTypeManager());
|
||||||
}
|
}
|
||||||
|
preWorkDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateAndSetParameters(Program programParam,
|
private void validateAndSetParameters(Program programParam,
|
||||||
|
@ -1369,7 +1396,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
* @return the Address
|
* @return the Address
|
||||||
*/
|
*/
|
||||||
Address getAddress(int segment, long offset) {
|
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();
|
String name = symbol.getName();
|
||||||
Address address = applicator.getAddress(symbol);
|
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);
|
function = applicator.getExistingFunction(address);
|
||||||
if (function == null) {
|
if (function == null) {
|
||||||
// Skip all interim symbols records
|
// Skip all interim symbols records
|
||||||
|
|
|
@ -358,7 +358,7 @@ public class PdbAddressManager {
|
||||||
private void determineMemoryBlocks() throws CancelledException {
|
private void determineMemoryBlocks() throws CancelledException {
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if(debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
segmentMapList = debugInfo.getSegmentMapList();
|
segmentMapList = debugInfo.getSegmentMapList();
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -112,6 +112,8 @@ public class PdbApplicatorMetrics {
|
||||||
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;
|
||||||
|
private boolean witnessC11Lines = false;
|
||||||
|
private boolean witnessC13InlineeLines = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to capture data/item type that cannot be applied.
|
* Method to capture data/item type that cannot be applied.
|
||||||
|
@ -215,6 +217,22 @@ public class PdbApplicatorMetrics {
|
||||||
unexpectedMemberFunctionContainerTypes.add(type.getClass());
|
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(reportUnexpectedPublicSymbols());
|
||||||
builder.append(reportUnexpectedGlobalSymbols());
|
builder.append(reportUnexpectedGlobalSymbols());
|
||||||
builder.append(reportEnumerateNarrowing());
|
builder.append(reportEnumerateNarrowing());
|
||||||
|
builder.append(reportSourceLineProcessing()); // can be removed once we can process
|
||||||
|
|
||||||
if (builder.length() == 0) {
|
if (builder.length() == 0) {
|
||||||
return; // nothing reported
|
return; // nothing reported
|
||||||
|
@ -324,4 +343,17 @@ public class PdbApplicatorMetrics {
|
||||||
return "";
|
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");
|
* 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.
|
||||||
|
@ -41,6 +41,15 @@ public class PdbApplicatorOptions {
|
||||||
private static final PdbApplicatorControl DEFAULT_CONTROL = PdbApplicatorControl.ALL;
|
private static final PdbApplicatorControl DEFAULT_CONTROL = PdbApplicatorControl.ALL;
|
||||||
private PdbApplicatorControl control;
|
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.
|
// Apply Code Block Comments.
|
||||||
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
|
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
|
||||||
"Apply Code Scope Block Comments";
|
"Apply Code Scope Block Comments";
|
||||||
|
@ -181,6 +190,11 @@ public class PdbApplicatorOptions {
|
||||||
private void registerOptions(Options options, boolean enableControl) {
|
private void registerOptions(Options options, boolean enableControl) {
|
||||||
HelpLocation help = null;
|
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) {
|
if (DEVELOPER_MODE || enableControl) {
|
||||||
options.registerOption(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL, help,
|
options.registerOption(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL, help,
|
||||||
OPTION_DESCRIPTION_PROCESSING_CONTROL);
|
OPTION_DESCRIPTION_PROCESSING_CONTROL);
|
||||||
|
@ -189,6 +203,11 @@ public class PdbApplicatorOptions {
|
||||||
// PdbApplicatorOptions
|
// PdbApplicatorOptions
|
||||||
if (DEVELOPER_MODE) {
|
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,
|
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
|
||||||
applyCodeScopeBlockComments, help,
|
applyCodeScopeBlockComments, help,
|
||||||
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
|
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
|
||||||
|
@ -232,6 +251,10 @@ public class PdbApplicatorOptions {
|
||||||
|
|
||||||
private void loadOptions(Options options, boolean enableControl) {
|
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) {
|
if (DEVELOPER_MODE || enableControl) {
|
||||||
control = options.getEnum(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL);
|
control = options.getEnum(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL);
|
||||||
}
|
}
|
||||||
|
@ -239,6 +262,10 @@ public class PdbApplicatorOptions {
|
||||||
// PdbApplicatorOptions
|
// PdbApplicatorOptions
|
||||||
if (DEVELOPER_MODE) {
|
if (DEVELOPER_MODE) {
|
||||||
|
|
||||||
|
//TODO: Remove the following line for GP-3883
|
||||||
|
applySourceLineNumbers = options.getBoolean(
|
||||||
|
OPTION_NAME_APPLY_SOURCE_LINE_NUMBERS, applySourceLineNumbers);
|
||||||
|
|
||||||
applyCodeScopeBlockComments = options.getBoolean(
|
applyCodeScopeBlockComments = options.getBoolean(
|
||||||
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
|
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
|
||||||
|
|
||||||
|
@ -288,6 +315,7 @@ public class PdbApplicatorOptions {
|
||||||
* Set the options to their default values
|
* Set the options to their default values
|
||||||
*/
|
*/
|
||||||
public void setDefaults() {
|
public void setDefaults() {
|
||||||
|
applySourceLineNumbers = DEFAULT_APPLY_SOURCE_LINE_NUMBERS;
|
||||||
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
|
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
|
||||||
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
|
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
|
||||||
excludeInstructionLabels = DEFAULT_EXCLUDE_INSTRUCTION_LABELS;
|
excludeInstructionLabels = DEFAULT_EXCLUDE_INSTRUCTION_LABELS;
|
||||||
|
@ -300,6 +328,22 @@ public class PdbApplicatorOptions {
|
||||||
compositeLayout = DEFAULT_CLASS_LAYOUT;
|
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.
|
* Enable/disable developmental debug.
|
||||||
* @param applyCodeScopeBlockComments {@code true} to turn applyCodeScopeBlockComments on
|
* @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 {
|
public class StubPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
private AbstractPdb pdb = null;
|
private AbstractPdb pdb = null;
|
||||||
private long originalImageBase = 0L;
|
private long originalImageBase = 0x400000L;
|
||||||
|
|
||||||
private Program program = null;
|
private Program program = null;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue