PDB - Corrected symbol mapping using OMAP and enabled PDB Universal

Analyzer as default.  Renamed old PDB analyzer to PDB MSDIA.
This commit is contained in:
ghidra1 2020-10-06 17:38:55 -04:00
parent 10702d0569
commit b2eb2aaa65
11 changed files with 251 additions and 209 deletions

View File

@ -15,16 +15,18 @@
*/
package ghidra.app.util.datatype.microsoft;
import java.io.*;
import java.util.Hashtable;
import generic.jar.ResourceFile;
import ghidra.docking.settings.SettingsImpl;
import ghidra.framework.Application;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.DumbMemBufferImpl;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.*;
import java.io.*;
import java.util.Hashtable;
public class GuidUtil {
public enum GuidType {
@ -63,8 +65,8 @@ public class GuidUtil {
return;
}
idTables = new Hashtable<GuidType, Hashtable<String, GuidInfo>>();
for (int i = 0; i < guidTypes.length; i++) {
idTables.put(guidTypes[i], new Hashtable<String, GuidInfo>());
for (GuidType guidType : guidTypes) {
idTables.put(guidType, new Hashtable<String, GuidInfo>());
}
buildGuidMap();
initialized = true;
@ -81,11 +83,11 @@ public class GuidUtil {
}
initialize();
guidString = guidString.toUpperCase();
for (int i = 0; i < guidTypes.length; i++) {
if (guidTypes[i].equals(GuidType.SYNTAX)) {
for (GuidType guidType : guidTypes) {
if (guidType.equals(GuidType.SYNTAX)) {
continue;
}
Hashtable<String, GuidInfo> table = idTables.get(guidTypes[i]);
Hashtable<String, GuidInfo> table = idTables.get(guidType);
GuidInfo guidInfo = table.get(guidString);
if (guidInfo != null) {
return guidInfo;
@ -106,11 +108,11 @@ public class GuidUtil {
}
private static void buildGuidMap() {
for (int i = 0; i < guidTypes.length; i++) {
Hashtable<String, GuidInfo> table = idTables.get(guidTypes[i]);
for (GuidType guidType : guidTypes) {
Hashtable<String, GuidInfo> table = idTables.get(guidType);
String filename = guidTypes[i].getFilename();
readGuidFile(guidTypes[i], filename, table);
String filename = guidType.getFilename();
readGuidFile(guidType, filename, table);
}
}
@ -195,8 +197,8 @@ public class GuidUtil {
}
private static boolean isOK(long[] data) {
for (int i = 0; i < data.length; i++) {
if ((data[i] != 0) || (data[i] != 0xFFFFFFFFL)) {
for (long element : data) {
if ((element != 0) || (element != 0xFFFFFFFFL)) {
return true;
}
}
@ -229,8 +231,9 @@ public class GuidUtil {
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
for (int i = 0; i < 4; i++) {
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
if (i == 1)
if (i == 1) {
guidString += delim;
}
}
for (int i = 0; i < 4; i++) {
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
@ -270,8 +273,9 @@ public class GuidUtil {
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
for (int i = 0; i < 4; i++) {
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
if (i == 1)
if (i == 1) {
guidString += delim;
}
}
for (int i = 0; i < 4; i++) {
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
@ -291,4 +295,32 @@ public class GuidUtil {
return guidString;
}
private static final String MS_GUID_PREFIX = "_GUID_";
/**
* Verify that the specified label correpsonds to a Microsoft symbol name
* for the GUID stored at the specified address within program.
* @param program program
* @param address memory address
* @param label symbol name to be checked
* @return true if label is a valid GUID label which corresponds to the GUID
* stored at address within program
*/
public static boolean isGuidLabel(Program program, Address address, String label) {
if (!label.startsWith(MS_GUID_PREFIX)) {
return false;
}
String guidString = label.substring(MS_GUID_PREFIX.length()).replace("_", "-");
try {
new GUID(guidString);
}
catch (Exception e) {
return false;
}
GuidDataType dt = new GuidDataType();
String guidRep = dt.getRepresentation(new DumbMemBufferImpl(program.getMemory(), address),
new SettingsImpl(), -1);
return guidRep.endsWith(guidString);
}
}

View File

@ -37,7 +37,7 @@ import ghidra.util.task.TaskMonitor;
* Finds and applies PDB debug information to the given Windows executable.
*/
public class PdbAnalyzer extends AbstractAnalyzer {
static final String NAME = "PDB";
static final String NAME = "PDB MSDIA";
static final boolean DEFAULT_ENABLEMENT = !PdbUniversalAnalyzer.DEFAULT_ENABLEMENT;
private static final String DESCRIPTION =
"PDB Analyzer.\n" + "Requires MS DIA-SDK for raw PDB processing (Windows only).\n" +

View File

@ -61,9 +61,9 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
//==============================================================================================
static final String NAME = "PDB Universal";
// TODO: decide which PDB Analyzer should be enabled by default for release
static final boolean DEFAULT_ENABLEMENT = false;
static final boolean DEFAULT_ENABLEMENT = true;
private static final String DESCRIPTION =
"[Prototype V1] Platform-indepent PDB analyzer (No XML support).\n" +
"Platform-indepent PDB analyzer (No XML support).\n" +
"NOTE: still undergoing development, so options may change.";
//==============================================================================================
@ -203,7 +203,7 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
//==============================================================================================
public PdbUniversalAnalyzer() {
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
setPrototype();
//setPrototype();
setDefaultEnablement(DEFAULT_ENABLEMENT);
setPriority(AnalysisPriority.FORMAT_ANALYSIS.after());
setSupportsOneTimeAnalysis();

View File

@ -20,14 +20,12 @@ import java.util.Set;
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.util.NamespaceUtils;
import ghidra.app.util.datatype.microsoft.GUID;
import ghidra.app.util.datatype.microsoft.GuidDataType;
import ghidra.app.util.datatype.microsoft.GuidUtil;
import ghidra.app.util.importer.MessageLog;
import ghidra.docking.settings.SettingsImpl;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.DumbMemBufferImpl;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
@ -37,11 +35,9 @@ import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
class ApplySymbols {
private static final String MS_VF_TABLE_PREFIX = "??_7";
private static final String MS_VB_TABLE_PREFIX = "??_8";
private static final String MS_STRING_PREFIX = "??_C@_";
private static final String MS_GUID_PREFIX = "_GUID_";
// private static final String MS_VF_TABLE_PREFIX = "??_7";
// private static final String MS_VB_TABLE_PREFIX = "??_8";
// private static final String MS_STRING_PREFIX = "??_C@_";
private ApplySymbols() {
// static use only
@ -146,11 +142,11 @@ class ApplySymbols {
// }
// }
// else
if (name.startsWith(MS_STRING_PREFIX)) {
// if (name.startsWith(MS_STRING_PREFIX)) {
// TODO: Should this be handled by the demangler instead of here?
boolean isUnicode = isUnicode(name);
pdbParser.createString(isUnicode, address, log);
}
// boolean isUnicode = isUnicode(name);
// pdbParser.createString(isUnicode, address, log);
// }
////////////
// Commented out the following for now, because it appears to be doing things it
// shouldn't. Many of the things are very loosely speculative.
@ -170,7 +166,7 @@ class ApplySymbols {
// pdbParser.createData(address, DoubleDataType.dataType, log, monitor);
// }
// }
else if (isGuidLabel(name, address, program)) {
if (GuidUtil.isGuidLabel(program, address, name)) {
pdbParser.createData(address, new GuidDataType(), log);
}
else if (tag.equals("Data")) {
@ -193,23 +189,6 @@ class ApplySymbols {
}
private static boolean isGuidLabel(String name, Address address, Program program) {
if (!name.startsWith(MS_GUID_PREFIX)) {
return false;
}
String guidString = name.substring(MS_GUID_PREFIX.length()).replace("_", "-");
try {
new GUID(guidString);
}
catch (Exception e) {
return false;
}
GuidDataType dt = new GuidDataType();
String guidRep = dt.getRepresentation(new DumbMemBufferImpl(program.getMemory(), address),
new SettingsImpl(), -1);
return guidRep.endsWith(guidString);
}
private static boolean shouldForcePrimarySymbol(Program program, Address address) {
Symbol primarySymbol = program.getSymbolTable().getPrimarySymbol(address);
if (primarySymbol != null) {
@ -222,13 +201,13 @@ class ApplySymbols {
return false;
}
private static boolean isUnicode(String name) {
if (name.startsWith(MS_STRING_PREFIX)) {
if (name.charAt(MS_STRING_PREFIX.length()) == '1') {
return true;
}
}
return false;
}
// private static boolean isUnicode(String name) {
// if (name.startsWith(MS_STRING_PREFIX)) {
// if (name.charAt(MS_STRING_PREFIX.length()) == '1') {
// return true;
// }
// }
// return false;
// }
}

View File

@ -67,9 +67,10 @@ public class DebugData {
private List<Integer> debugStreams = new ArrayList<>();
private List<FramePointerOmissionRecord> framePointerOmissionData;
private Map<Long, Long> omapToSource;
private Map<Long, Long> omapFromSource;
// private SortedMap<Long, Long> omapToSource;
private SortedMap<Long, Long> omapFromSource;
private List<ImageSectionHeader> imageSectionHeaders;
private List<ImageSectionHeader> imageSectionHeadersOrig;
private List<ImageFunctionEntry> pData;
@ -96,19 +97,19 @@ public class DebugData {
return framePointerOmissionData;
}
/**
* Returns the OMAP_TO_SOURCE mapping of RVA to RVA
* @return the omapToSource or null if does not exist.
*/
public Map<Long, Long> getOmapToSource() {
return omapToSource;
}
// /**
// * Returns the OMAP_TO_SOURCE mapping of RVA to RVA
// * @return the omapToSource or null if does not exist.
// */
// public SortedMap<Long, Long> getOmapToSource() {
// return omapToSource;
// }
/**
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
* @return the omapFromSource or null if does not exist.
*/
public Map<Long, Long> getOmapFromSource() {
public SortedMap<Long, Long> getOmapFromSource() {
return omapFromSource;
}
@ -120,6 +121,16 @@ public class DebugData {
return imageSectionHeaders;
}
/**
* Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;.
* When this return a non-null list the OMAP_FROM_SRC should be
* used for remapping global symbols.
* @return the imageSectionHeadersOrig or null if does not exist.
*/
public List<ImageSectionHeader> getImageSectionHeadersOrig() {
return imageSectionHeadersOrig;
}
/**
* Deserialize {@link DebugData} header from the {@link PdbByteReader} input. This parses
* stream numbers for varying Debug Types--the order/location of the stream number is for
@ -178,13 +189,13 @@ public class DebugData {
// TODO: implement.
break;
case OMAP_TO_SOURCE:
deserializeOMapToSource(streamNum, monitor);
// omapToSource = deserializeOMap(streamNum, monitor);
break;
case OMAP_FROM_SOURCE:
deserializeOMapFromSource(streamNum, monitor);
omapFromSource = deserializeOMap(streamNum, monitor);
break;
case SECTION_HEADER:
deserializeSectionHeader(streamNum, monitor);
imageSectionHeaders = deserializeSectionHeaders(streamNum, monitor);
break;
case TOKEN_RID_MAP:
// TODO: implement.
@ -199,7 +210,7 @@ public class DebugData {
// TODO: implement.
break;
case SECTION_HEADER_ORIG:
// TODO: implement.
imageSectionHeadersOrig = deserializeSectionHeaders(streamNum, monitor);
break;
}
}
@ -219,58 +230,30 @@ public class DebugData {
}
}
private void deserializeOMapToSource(int streamNum, TaskMonitor monitor)
throws CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
// PdbLog.message("OMAP_TO_SOURCE DUMP");
// PdbLog.message(reader::dump);
omapToSource = new HashMap<>();
while (reader.hasMore()) {
monitor.checkCanceled();
try {
long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal();
omapToSource.put(v1, v2);
}
catch (PdbException e) {
// catching if we do not have a matching pair and then breaking from loop.
PdbLog.message("OmapToSource unmatched pair");
break;
}
}
}
private void deserializeOMapFromSource(int streamNum, TaskMonitor monitor)
throws CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
// PdbLog.message("OMAP_FROM_SOURCE DUMP");
// PdbLog.message(reader::dump);
omapFromSource = new HashMap<>();
while (reader.hasMore()) {
monitor.checkCanceled();
try {
long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal();
omapFromSource.put(v1, v2);
}
catch (PdbException e) {
// catching if we do not have a matching pair and then breaking from loop.
PdbLog.message("OmapFromSource unmatched pair");
break;
}
}
}
private void deserializeSectionHeader(int streamNum, TaskMonitor monitor)
private SortedMap<Long, Long> deserializeOMap(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
imageSectionHeaders = new ArrayList<>();
SortedMap<Long, Long> omap = new TreeMap<>();
while (reader.hasMore()) {
monitor.checkCanceled();
long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal();
omap.put(v1, v2);
}
return omap;
}
private List<ImageSectionHeader> deserializeSectionHeaders(int streamNum, TaskMonitor monitor)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
List<ImageSectionHeader> sectionHeaders = new ArrayList<>();
while (reader.hasMore()) {
monitor.checkCanceled();
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
imageSectionHeader.parse(reader);
imageSectionHeaders.add(imageSectionHeader);
sectionHeaders.add(imageSectionHeader);
}
return sectionHeaders;
}
// TODO: This is incomplete.
@ -372,15 +355,15 @@ public class DebugData {
}
writer.write("End FramePointerOmissionData--------------------------------\n");
writer.write("OmapToSource------------------------------------------------\n");
if (omapToSource != null) {
int num = 0;
for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) {
writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
entry.getValue()));
}
}
writer.write("End OmapToSource--------------------------------------------\n");
// writer.write("OmapToSource------------------------------------------------\n");
// if (omapToSource != null) {
// int num = 0;
// for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) {
// writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
// entry.getValue()));
// }
// }
// writer.write("End OmapToSource--------------------------------------------\n");
writer.write("OmapFromSource----------------------------------------------\n");
if (omapFromSource != null) {
@ -401,6 +384,15 @@ public class DebugData {
}
writer.write("End ImageSectionHeaders-------------------------------------\n");
writer.write("ImageSectionHeadersOrig-------------------------------------\n");
if (imageSectionHeadersOrig != null) {
int sectionNum = 0;
for (ImageSectionHeader imageSectionHeader : imageSectionHeadersOrig) {
imageSectionHeader.dump(writer, sectionNum++);
}
}
writer.write("End ImageSectionHeadersOrig---------------------------------\n");
writer.write("PData-------------------------------------------------------\n");
if (pData != null) {
for (ImageFunctionEntry entry : pData) {

View File

@ -36,18 +36,20 @@ public class PdbAddressManager {
// This could be a valid address for the program, but we are using it as a flag. We return
// it to designate that an address is an external address, and we use it outside of this class
// to test for it being an external address.
static final Address EXTERNAL_ADDRESS = AddressSpace.EXTERNAL_SPACE.getAddress(0);
static final Address BAD_ADDRESS = Address.NO_ADDRESS; // using NO_ADDRESS as a marker
// to test for it being an external address. These marker addresses should never be used
// for symbol creation.
static final Address EXTERNAL_ADDRESS = AddressSpace.EXTERNAL_SPACE.getAddress(1);
static final Address ZERO_ADDRESS = AddressSpace.EXTERNAL_SPACE.getAddress(0);
static final Address BAD_ADDRESS = Address.NO_ADDRESS;
//==============================================================================================
private Map<Integer, Long> realAddressesBySection;
private List<SegmentMapDescription> segmentMapList;
private List<ImageSectionHeader> imageSectionHeaders;
private Map<Long, Long> omapFromSource;
private SortedMap<Long, Long> omapFromSource;
private List<PeCoffGroupMsSymbol> memoryGroupRefinement;
private List<PeCoffSectionMsSymbol> memorySectionRefinement;
private List<SegmentInfo> allSegmentsInfo;
// private List<SegmentInfo> allSegmentsInfo;
// Map of Address by symbol name... if a name has appeared more than once, then the Address
// is written with Address.NO_ADDRESS to indicate that the name is found at more than one
@ -85,11 +87,11 @@ public class PdbAddressManager {
memoryGroupRefinement = new ArrayList<>();
memorySectionRefinement = new ArrayList<>();
// TODO allSegmentInfo might go away if we use ImageSectionHeader. Under investigation.
allSegmentsInfo = new ArrayList<>();
// allSegmentsInfo = new ArrayList<>();
addressByPreExistingSymbolName = new HashMap<>();
primarySymbolByAddress = new HashMap<>();
determineMemoryBlocks();
determineMemoryBlocks_orig();
// determineMemoryBlocks_orig();
mapPreExistingSymbols();
createAddressRemap();
}
@ -144,16 +146,10 @@ public class PdbAddressManager {
* {@code Address.EXTERNAL_ADDRESS} if the address is external to the program.
*/
Address getRawAddress(int segment, long offset) {
// Investigating
return getRawAddress_new(segment, offset);
//return getRawAddress_orig(segment, offset);
}
private Address getRawAddress_new(int segment, long offset) {
if (segment < 0) {
return BAD_ADDRESS;
}
Long relativeVirtualAddress;
Long relativeVirtualAddress = null;
if (imageSectionHeaders != null) {
if (segment > imageSectionHeaders.size() + 1) {
return BAD_ADDRESS;
@ -164,8 +160,16 @@ public class PdbAddressManager {
}
relativeVirtualAddress =
imageSectionHeaders.get(segment - 1).getVirtualAddress() + offset;
relativeVirtualAddress = applyOMap(relativeVirtualAddress);
if (relativeVirtualAddress == null) {
return BAD_ADDRESS;
}
if (relativeVirtualAddress == 0) {
return ZERO_ADDRESS;
}
}
else {
// TODO: need to verify use of segments here!
if (segment > segmentMapList.size() + 1) {
return BAD_ADDRESS;
}
@ -176,32 +180,25 @@ public class PdbAddressManager {
// TODO: Need to verify. Guessing at the moment
relativeVirtualAddress = segmentMapList.get(segment - 1).getSegmentOffset();
}
if (omapFromSource != null) {
relativeVirtualAddress = omapFromSource.get(relativeVirtualAddress);
if (relativeVirtualAddress == null) {
return BAD_ADDRESS;
}
}
return imageBase.add(relativeVirtualAddress);
}
private Address getRawAddress_orig(int segment, long offset) {
if (segment < 0 || segment > allSegmentsInfo.size()) {
return BAD_ADDRESS;
private Long applyOMap(Long relativeVirtualAddress) {
if (omapFromSource == null) {
return relativeVirtualAddress;
}
// We are lumping 0 and size as EXTERNAL... one or other could be image base... but not
// necessarily consistent... but that's OK... it is still "EXTERNAL" from the program.
else if (segment == 0 || segment == allSegmentsInfo.size()) {
// External address.
// Was getting issues of _IMAGE_DOSHEADER showing up with a segment index one
// beyond the end.
return EXTERNAL_ADDRESS;
// NOTE: Original map entries are 32-bit values zero-extended to a java long (64-bits)
SortedMap<Long, Long> headMap = omapFromSource.headMap(relativeVirtualAddress + 1);
if (headMap.isEmpty()) {
return null;
}
SegmentInfo segmentInfo = allSegmentsInfo.get(segment);
if (offset >= segmentInfo.getLength()) {
return BAD_ADDRESS;
long from = headMap.lastKey();
long to = headMap.get(from);
if (to == 0) {
return 0L;
}
return segmentInfo.getStartAddress().add(offset);
return to + (relativeVirtualAddress - from);
}
/**
@ -297,45 +294,50 @@ public class PdbAddressManager {
}
}
private void determineMemoryBlocks_orig() {
// Set section/segment 0 to image base. (should be what is header), but what is its size?
// TODO... made up size for now... is there something else? We could put null instead.
// For now, the method that reads this information might report EXTERNAL instead of
// trying to use this.
long segmentZeroLength = 0x7fffffff;
allSegmentsInfo.add(new SegmentInfo(imageBase, segmentZeroLength));
PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
if (dbi instanceof PdbNewDebugInfo) {
DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
List<ImageSectionHeader> imageSectionHeaders = debugData.getImageSectionHeaders();
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
long virtualAddress = imageSectionHeader.getVirtualAddress();
// TODO: not sure when unionPAVS is physical address vs. virtual size. Perhaps
// it keys off whether virtualAddress is not some special value such as
// 0x00000000 or 0xffffffff.
long size = imageSectionHeader.getUnionPAVS();
allSegmentsInfo.add(new SegmentInfo(imageBase.add(virtualAddress), size));
}
}
// else instance of PdbDebugInfo; TODO: what can we do here?
// Maybe get information from the program itself.
// TODO: what should we do with these? Not doing anything at the moment
AbstractPdb pdb = applicator.getPdb();
List<SegmentMapDescription> segmentMapList = pdb.getDebugInfo().getSegmentMapList();
for (SegmentMapDescription segmentMapDescription : segmentMapList) {
segmentMapDescription.getSegmentOffset();
segmentMapDescription.getLength();
}
}
// private void determineMemoryBlocks_orig() {
// // Set section/segment 0 to image base. (should be what is header), but what is its size?
// // TODO... made up size for now... is there something else? We could put null instead.
// // For now, the method that reads this information might report EXTERNAL instead of
// // trying to use this.
// long segmentZeroLength = 0x7fffffff;
// allSegmentsInfo.add(new SegmentInfo(imageBase, segmentZeroLength));
// PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
// if (dbi instanceof PdbNewDebugInfo) {
// DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
// List<ImageSectionHeader> imageSectionHeaders = debugData.getImageSectionHeaders();
// for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
// long virtualAddress = imageSectionHeader.getVirtualAddress();
// // TODO: not sure when unionPAVS is physical address vs. virtual size. Perhaps
// // it keys off whether virtualAddress is not some special value such as
// // 0x00000000 or 0xffffffff.
// long size = imageSectionHeader.getUnionPAVS();
// allSegmentsInfo.add(new SegmentInfo(imageBase.add(virtualAddress), size));
// }
// }
// // else instance of PdbDebugInfo; TODO: what can we do here?
// // Maybe get information from the program itself.
//
// // TODO: what should we do with these? Not doing anything at the moment
// AbstractPdb pdb = applicator.getPdb();
// List<SegmentMapDescription> segmentMapList = pdb.getDebugInfo().getSegmentMapList();
// for (SegmentMapDescription segmentMapDescription : segmentMapList) {
// segmentMapDescription.getSegmentOffset();
// segmentMapDescription.getLength();
// }
// }
private void determineMemoryBlocks() {
PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
segmentMapList = dbi.getSegmentMapList();
if (dbi instanceof PdbNewDebugInfo) {
DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
omapFromSource = debugData.getOmapFromSource();
imageSectionHeaders = debugData.getImageSectionHeaders();
imageSectionHeaders = debugData.getImageSectionHeadersOrig();
if (imageSectionHeaders != null) {
omapFromSource = debugData.getOmapFromSource();
}
else {
imageSectionHeaders = debugData.getImageSectionHeaders();
}
}
}
@ -399,6 +401,7 @@ public class PdbAddressManager {
// Put in two basic entries so we do not have to do conditional tests before looking
// up values in the table.
remapAddressByAddress.put(BAD_ADDRESS, BAD_ADDRESS);
remapAddressByAddress.put(ZERO_ADDRESS, ZERO_ADDRESS);
remapAddressByAddress.put(EXTERNAL_ADDRESS, EXTERNAL_ADDRESS);
}

View File

@ -200,9 +200,8 @@ public class PdbApplicator {
pdbAddressManager.logReport();
String applicatorMetrics = pdbApplicatorMetrics.getPostProcessingReport();
Msg.info(this, applicatorMetrics);
PdbLog.message(applicatorMetrics);
pdbApplicatorMetrics.logReport();
Msg.info(this, "PDB Terminated Normally");
}
@ -800,6 +799,10 @@ public class PdbApplicator {
appendLogMsg("Invalid address encountered for: " + name);
return true;
}
if (address == PdbAddressManager.ZERO_ADDRESS) {
// Symbol OMAP resulted in 0 RVA - Discard silently
return true;
}
if (address == PdbAddressManager.EXTERNAL_ADDRESS) {
//Msg.info(this, "External address not known for: " + name);
return true;

View File

@ -18,10 +18,12 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.HashSet;
import java.util.Set;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
/**
* Metrics captured during the application of a PDB. This is a Ghidra class separate from the
@ -200,12 +202,12 @@ public class PdbApplicatorMetrics {
//==============================================================================================
/**
* Return some post-processing metrics for applying the PDB
* @return {@link String} of pretty output.
* Generate some post-processing metrics and write to log
*/
String getPostProcessingReport() {
void logReport() {
StringBuilder builder = new StringBuilder();
builder.append("===Begin PdbApplicatorMetrics Report===\n");
builder.append(reportNonappliableTypes());
builder.append(reportUnunsualThisPointerTypes());
builder.append(reportUnunsualThisPointerUnderlyingTypes());
@ -214,8 +216,17 @@ public class PdbApplicatorMetrics {
builder.append(reportUnexpectedPublicSymbols());
builder.append(reportUnexpectedGlobalSymbols());
builder.append(reportEnumerateNarrowing());
if (builder.length() == 0) {
return; // nothing reported
}
builder.insert(0, "===Begin PdbApplicatorMetrics Report===\n");
builder.append("====End PdbApplicatorMetrics Report====\n");
return builder.toString();
String text = builder.toString();
Msg.info(this, text);
PdbLog.message(text);
}
private String reportNonappliableTypes() {

View File

@ -18,8 +18,14 @@ package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractPublicMsSymbol;
import ghidra.app.util.datatype.microsoft.GuidDataType;
import ghidra.app.util.datatype.microsoft.GuidUtil;
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataUtilities;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.listing.Program;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
@ -56,9 +62,12 @@ public class PublicSymbolApplier extends MsSymbolApplier {
void apply() throws CancelledException, PdbException {
symbolAddress = applicator.getAddress(symbol);
if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
String name = symbol.getName();
if (applicator.isInvalidAddress(symbolAddress, name)) {
return;
}
existingSymbolAddress = applicator.witnessSymbolNameAtAddress(getName(), symbolAddress);
// TODO: Consider... could add restriction of not putting down symbol if it is mangled,
// as this would violate the uniqueness of the symbol... but we would also want to
@ -67,7 +76,18 @@ public class PublicSymbolApplier extends MsSymbolApplier {
// Note: there might be issues of thunk functions getting the same mangled name
// as thunked functions, which violates the thesis of their being unique.
// TODO: investigate this.
applicator.createSymbol(symbolAddress, symbol.getName(), true);
applicator.createSymbol(symbolAddress, name, true);
Program program = applicator.getProgram();
if (GuidUtil.isGuidLabel(program, symbolAddress, name)) {
try {
DataUtilities.createData(program, symbolAddress, new GuidDataType(), -1, false,
ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA);
}
catch (CodeUnitInsertionException e) {
// ignore
}
}
}
}

View File

@ -15,7 +15,8 @@
*/
package pdb;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.*;
@ -30,7 +31,7 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
private boolean isCanceled;
private boolean useMsDiaParser = true;
private boolean useMsDiaParser;
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE;
/**
@ -57,9 +58,10 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
optionsPanel.add(new JLabel("PDB Parser:"));
if (isPdbFile) {
useMsDiaParser = false; // Use PDB Universal by default
if (PdbParser.onWindows) {
final GComboBox<String> combo =
new GComboBox<>(new String[] { "PDB MSDIA", "PDB Universal (Prototype)" });
new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" });
combo.setSelectedIndex(0);
restrictionsCombo.setEnabled(!useMsDiaParser);
combo.addActionListener(e -> {
@ -73,8 +75,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
}
else {
useMsDiaParser = false;
JLabel label = new JLabel("PDB Universal (Prototype)");
label.setForeground(Color.red); // set color to emphasize prototype status
JLabel label = new JLabel("PDB Universal");
//label.setForeground(Color.red); // set color to emphasize prototype status
optionsPanel.add(label);
}
}

View File

@ -47,7 +47,7 @@ class LoadPdbTask extends Task {
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser,
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) {
super("Loading PDB...", true, false, false);
super("Load PDB", true, false, false);
this.program = program;
this.pdbFile = pdbFile;
this.useMsDiaParser = useMsDiaParser;