mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
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:
parent
10702d0569
commit
b2eb2aaa65
11 changed files with 251 additions and 209 deletions
|
@ -15,16 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.datatype.microsoft;
|
package ghidra.app.util.datatype.microsoft;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
|
import ghidra.docking.settings.SettingsImpl;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.mem.DumbMemBufferImpl;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
public class GuidUtil {
|
public class GuidUtil {
|
||||||
|
|
||||||
public enum GuidType {
|
public enum GuidType {
|
||||||
|
@ -63,8 +65,8 @@ public class GuidUtil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
idTables = new Hashtable<GuidType, Hashtable<String, GuidInfo>>();
|
idTables = new Hashtable<GuidType, Hashtable<String, GuidInfo>>();
|
||||||
for (int i = 0; i < guidTypes.length; i++) {
|
for (GuidType guidType : guidTypes) {
|
||||||
idTables.put(guidTypes[i], new Hashtable<String, GuidInfo>());
|
idTables.put(guidType, new Hashtable<String, GuidInfo>());
|
||||||
}
|
}
|
||||||
buildGuidMap();
|
buildGuidMap();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
@ -81,11 +83,11 @@ public class GuidUtil {
|
||||||
}
|
}
|
||||||
initialize();
|
initialize();
|
||||||
guidString = guidString.toUpperCase();
|
guidString = guidString.toUpperCase();
|
||||||
for (int i = 0; i < guidTypes.length; i++) {
|
for (GuidType guidType : guidTypes) {
|
||||||
if (guidTypes[i].equals(GuidType.SYNTAX)) {
|
if (guidType.equals(GuidType.SYNTAX)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Hashtable<String, GuidInfo> table = idTables.get(guidTypes[i]);
|
Hashtable<String, GuidInfo> table = idTables.get(guidType);
|
||||||
GuidInfo guidInfo = table.get(guidString);
|
GuidInfo guidInfo = table.get(guidString);
|
||||||
if (guidInfo != null) {
|
if (guidInfo != null) {
|
||||||
return guidInfo;
|
return guidInfo;
|
||||||
|
@ -106,11 +108,11 @@ public class GuidUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildGuidMap() {
|
private static void buildGuidMap() {
|
||||||
for (int i = 0; i < guidTypes.length; i++) {
|
for (GuidType guidType : guidTypes) {
|
||||||
Hashtable<String, GuidInfo> table = idTables.get(guidTypes[i]);
|
Hashtable<String, GuidInfo> table = idTables.get(guidType);
|
||||||
|
|
||||||
String filename = guidTypes[i].getFilename();
|
String filename = guidType.getFilename();
|
||||||
readGuidFile(guidTypes[i], filename, table);
|
readGuidFile(guidType, filename, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,8 +197,8 @@ public class GuidUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOK(long[] data) {
|
private static boolean isOK(long[] data) {
|
||||||
for (int i = 0; i < data.length; i++) {
|
for (long element : data) {
|
||||||
if ((data[i] != 0) || (data[i] != 0xFFFFFFFFL)) {
|
if ((element != 0) || (element != 0xFFFFFFFFL)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,8 +231,9 @@ public class GuidUtil {
|
||||||
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
|
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
|
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
|
||||||
if (i == 1)
|
if (i == 1) {
|
||||||
guidString += delim;
|
guidString += delim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
|
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
|
||||||
|
@ -270,8 +273,9 @@ public class GuidUtil {
|
||||||
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
|
guidString += Conv.toHexString((short) (data[1] >> 16)) + delim;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
|
guidString += Conv.toHexString((byte) (data[2] >> i * 8));
|
||||||
if (i == 1)
|
if (i == 1) {
|
||||||
guidString += delim;
|
guidString += delim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
|
guidString += Conv.toHexString((byte) (data[3] >> i * 8));
|
||||||
|
@ -291,4 +295,32 @@ public class GuidUtil {
|
||||||
return guidString;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Finds and applies PDB debug information to the given Windows executable.
|
* Finds and applies PDB debug information to the given Windows executable.
|
||||||
*/
|
*/
|
||||||
public class PdbAnalyzer extends AbstractAnalyzer {
|
public class PdbAnalyzer extends AbstractAnalyzer {
|
||||||
static final String NAME = "PDB";
|
static final String NAME = "PDB MSDIA";
|
||||||
static final boolean DEFAULT_ENABLEMENT = !PdbUniversalAnalyzer.DEFAULT_ENABLEMENT;
|
static final boolean DEFAULT_ENABLEMENT = !PdbUniversalAnalyzer.DEFAULT_ENABLEMENT;
|
||||||
private static final String DESCRIPTION =
|
private static final String DESCRIPTION =
|
||||||
"PDB Analyzer.\n" + "Requires MS DIA-SDK for raw PDB processing (Windows only).\n" +
|
"PDB Analyzer.\n" + "Requires MS DIA-SDK for raw PDB processing (Windows only).\n" +
|
||||||
|
|
|
@ -61,9 +61,9 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
static final String NAME = "PDB Universal";
|
static final String NAME = "PDB Universal";
|
||||||
// TODO: decide which PDB Analyzer should be enabled by default for release
|
// 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 =
|
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.";
|
"NOTE: still undergoing development, so options may change.";
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -203,7 +203,7 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
public PdbUniversalAnalyzer() {
|
public PdbUniversalAnalyzer() {
|
||||||
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||||
setPrototype();
|
//setPrototype();
|
||||||
setDefaultEnablement(DEFAULT_ENABLEMENT);
|
setDefaultEnablement(DEFAULT_ENABLEMENT);
|
||||||
setPriority(AnalysisPriority.FORMAT_ANALYSIS.after());
|
setPriority(AnalysisPriority.FORMAT_ANALYSIS.after());
|
||||||
setSupportsOneTimeAnalysis();
|
setSupportsOneTimeAnalysis();
|
||||||
|
|
|
@ -20,14 +20,12 @@ import java.util.Set;
|
||||||
|
|
||||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.util.NamespaceUtils;
|
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.GuidDataType;
|
||||||
|
import ghidra.app.util.datatype.microsoft.GuidUtil;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.docking.settings.SettingsImpl;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.DumbMemBufferImpl;
|
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -37,11 +35,9 @@ import ghidra.xml.XmlElement;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
class ApplySymbols {
|
class ApplySymbols {
|
||||||
private static final String MS_VF_TABLE_PREFIX = "??_7";
|
// private static final String MS_VF_TABLE_PREFIX = "??_7";
|
||||||
private static final String MS_VB_TABLE_PREFIX = "??_8";
|
// private static final String MS_VB_TABLE_PREFIX = "??_8";
|
||||||
private static final String MS_STRING_PREFIX = "??_C@_";
|
// private static final String MS_STRING_PREFIX = "??_C@_";
|
||||||
|
|
||||||
private static final String MS_GUID_PREFIX = "_GUID_";
|
|
||||||
|
|
||||||
private ApplySymbols() {
|
private ApplySymbols() {
|
||||||
// static use only
|
// static use only
|
||||||
|
@ -146,11 +142,11 @@ class ApplySymbols {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
if (name.startsWith(MS_STRING_PREFIX)) {
|
// if (name.startsWith(MS_STRING_PREFIX)) {
|
||||||
// TODO: Should this be handled by the demangler instead of here?
|
// TODO: Should this be handled by the demangler instead of here?
|
||||||
boolean isUnicode = isUnicode(name);
|
// boolean isUnicode = isUnicode(name);
|
||||||
pdbParser.createString(isUnicode, address, log);
|
// pdbParser.createString(isUnicode, address, log);
|
||||||
}
|
// }
|
||||||
////////////
|
////////////
|
||||||
// Commented out the following for now, because it appears to be doing things it
|
// Commented out the following for now, because it appears to be doing things it
|
||||||
// shouldn't. Many of the things are very loosely speculative.
|
// shouldn't. Many of the things are very loosely speculative.
|
||||||
|
@ -170,7 +166,7 @@ class ApplySymbols {
|
||||||
// pdbParser.createData(address, DoubleDataType.dataType, log, monitor);
|
// 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);
|
pdbParser.createData(address, new GuidDataType(), log);
|
||||||
}
|
}
|
||||||
else if (tag.equals("Data")) {
|
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) {
|
private static boolean shouldForcePrimarySymbol(Program program, Address address) {
|
||||||
Symbol primarySymbol = program.getSymbolTable().getPrimarySymbol(address);
|
Symbol primarySymbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||||
if (primarySymbol != null) {
|
if (primarySymbol != null) {
|
||||||
|
@ -222,13 +201,13 @@ class ApplySymbols {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isUnicode(String name) {
|
// private static boolean isUnicode(String name) {
|
||||||
if (name.startsWith(MS_STRING_PREFIX)) {
|
// if (name.startsWith(MS_STRING_PREFIX)) {
|
||||||
if (name.charAt(MS_STRING_PREFIX.length()) == '1') {
|
// if (name.charAt(MS_STRING_PREFIX.length()) == '1') {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,10 @@ public class DebugData {
|
||||||
private List<Integer> debugStreams = new ArrayList<>();
|
private List<Integer> debugStreams = new ArrayList<>();
|
||||||
|
|
||||||
private List<FramePointerOmissionRecord> framePointerOmissionData;
|
private List<FramePointerOmissionRecord> framePointerOmissionData;
|
||||||
private Map<Long, Long> omapToSource;
|
// private SortedMap<Long, Long> omapToSource;
|
||||||
private Map<Long, Long> omapFromSource;
|
private SortedMap<Long, Long> omapFromSource;
|
||||||
private List<ImageSectionHeader> imageSectionHeaders;
|
private List<ImageSectionHeader> imageSectionHeaders;
|
||||||
|
private List<ImageSectionHeader> imageSectionHeadersOrig;
|
||||||
|
|
||||||
private List<ImageFunctionEntry> pData;
|
private List<ImageFunctionEntry> pData;
|
||||||
|
|
||||||
|
@ -96,19 +97,19 @@ public class DebugData {
|
||||||
return framePointerOmissionData;
|
return framePointerOmissionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns the OMAP_TO_SOURCE mapping of RVA to RVA
|
// * Returns the OMAP_TO_SOURCE mapping of RVA to RVA
|
||||||
* @return the omapToSource or null if does not exist.
|
// * @return the omapToSource or null if does not exist.
|
||||||
*/
|
// */
|
||||||
public Map<Long, Long> getOmapToSource() {
|
// public SortedMap<Long, Long> getOmapToSource() {
|
||||||
return omapToSource;
|
// return omapToSource;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
|
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
|
||||||
* @return the omapFromSource or null if does not exist.
|
* @return the omapFromSource or null if does not exist.
|
||||||
*/
|
*/
|
||||||
public Map<Long, Long> getOmapFromSource() {
|
public SortedMap<Long, Long> getOmapFromSource() {
|
||||||
return omapFromSource;
|
return omapFromSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +121,16 @@ public class DebugData {
|
||||||
return imageSectionHeaders;
|
return imageSectionHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link List}<{@link ImageSectionHeader}>.
|
||||||
|
* 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
|
* 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
|
* stream numbers for varying Debug Types--the order/location of the stream number is for
|
||||||
|
@ -178,13 +189,13 @@ public class DebugData {
|
||||||
// TODO: implement.
|
// TODO: implement.
|
||||||
break;
|
break;
|
||||||
case OMAP_TO_SOURCE:
|
case OMAP_TO_SOURCE:
|
||||||
deserializeOMapToSource(streamNum, monitor);
|
// omapToSource = deserializeOMap(streamNum, monitor);
|
||||||
break;
|
break;
|
||||||
case OMAP_FROM_SOURCE:
|
case OMAP_FROM_SOURCE:
|
||||||
deserializeOMapFromSource(streamNum, monitor);
|
omapFromSource = deserializeOMap(streamNum, monitor);
|
||||||
break;
|
break;
|
||||||
case SECTION_HEADER:
|
case SECTION_HEADER:
|
||||||
deserializeSectionHeader(streamNum, monitor);
|
imageSectionHeaders = deserializeSectionHeaders(streamNum, monitor);
|
||||||
break;
|
break;
|
||||||
case TOKEN_RID_MAP:
|
case TOKEN_RID_MAP:
|
||||||
// TODO: implement.
|
// TODO: implement.
|
||||||
|
@ -199,7 +210,7 @@ public class DebugData {
|
||||||
// TODO: implement.
|
// TODO: implement.
|
||||||
break;
|
break;
|
||||||
case SECTION_HEADER_ORIG:
|
case SECTION_HEADER_ORIG:
|
||||||
// TODO: implement.
|
imageSectionHeadersOrig = deserializeSectionHeaders(streamNum, monitor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,58 +230,30 @@ public class DebugData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deserializeOMapToSource(int streamNum, TaskMonitor monitor)
|
private SortedMap<Long, Long> deserializeOMap(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)
|
|
||||||
throws PdbException, CancelledException, IOException {
|
throws PdbException, CancelledException, IOException {
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor);
|
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()) {
|
while (reader.hasMore()) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
|
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
|
||||||
imageSectionHeader.parse(reader);
|
imageSectionHeader.parse(reader);
|
||||||
imageSectionHeaders.add(imageSectionHeader);
|
sectionHeaders.add(imageSectionHeader);
|
||||||
}
|
}
|
||||||
|
return sectionHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is incomplete.
|
// TODO: This is incomplete.
|
||||||
|
@ -372,15 +355,15 @@ public class DebugData {
|
||||||
}
|
}
|
||||||
writer.write("End FramePointerOmissionData--------------------------------\n");
|
writer.write("End FramePointerOmissionData--------------------------------\n");
|
||||||
|
|
||||||
writer.write("OmapToSource------------------------------------------------\n");
|
// writer.write("OmapToSource------------------------------------------------\n");
|
||||||
if (omapToSource != null) {
|
// if (omapToSource != null) {
|
||||||
int num = 0;
|
// int num = 0;
|
||||||
for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) {
|
// for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) {
|
||||||
writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
|
// writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
|
||||||
entry.getValue()));
|
// entry.getValue()));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
writer.write("End OmapToSource--------------------------------------------\n");
|
// writer.write("End OmapToSource--------------------------------------------\n");
|
||||||
|
|
||||||
writer.write("OmapFromSource----------------------------------------------\n");
|
writer.write("OmapFromSource----------------------------------------------\n");
|
||||||
if (omapFromSource != null) {
|
if (omapFromSource != null) {
|
||||||
|
@ -401,6 +384,15 @@ public class DebugData {
|
||||||
}
|
}
|
||||||
writer.write("End ImageSectionHeaders-------------------------------------\n");
|
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");
|
writer.write("PData-------------------------------------------------------\n");
|
||||||
if (pData != null) {
|
if (pData != null) {
|
||||||
for (ImageFunctionEntry entry : pData) {
|
for (ImageFunctionEntry entry : pData) {
|
||||||
|
|
|
@ -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
|
// 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
|
// 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.
|
// to test for it being an external address. These marker addresses should never be used
|
||||||
static final Address EXTERNAL_ADDRESS = AddressSpace.EXTERNAL_SPACE.getAddress(0);
|
// for symbol creation.
|
||||||
static final Address BAD_ADDRESS = Address.NO_ADDRESS; // using NO_ADDRESS as a marker
|
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 Map<Integer, Long> realAddressesBySection;
|
||||||
private List<SegmentMapDescription> segmentMapList;
|
private List<SegmentMapDescription> segmentMapList;
|
||||||
private List<ImageSectionHeader> imageSectionHeaders;
|
private List<ImageSectionHeader> imageSectionHeaders;
|
||||||
private Map<Long, Long> omapFromSource;
|
private SortedMap<Long, Long> omapFromSource;
|
||||||
private List<PeCoffGroupMsSymbol> memoryGroupRefinement;
|
private List<PeCoffGroupMsSymbol> memoryGroupRefinement;
|
||||||
private List<PeCoffSectionMsSymbol> memorySectionRefinement;
|
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
|
// 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
|
// 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<>();
|
memoryGroupRefinement = new ArrayList<>();
|
||||||
memorySectionRefinement = new ArrayList<>();
|
memorySectionRefinement = new ArrayList<>();
|
||||||
// TODO allSegmentInfo might go away if we use ImageSectionHeader. Under investigation.
|
// TODO allSegmentInfo might go away if we use ImageSectionHeader. Under investigation.
|
||||||
allSegmentsInfo = new ArrayList<>();
|
// allSegmentsInfo = new ArrayList<>();
|
||||||
addressByPreExistingSymbolName = new HashMap<>();
|
addressByPreExistingSymbolName = new HashMap<>();
|
||||||
primarySymbolByAddress = new HashMap<>();
|
primarySymbolByAddress = new HashMap<>();
|
||||||
determineMemoryBlocks();
|
determineMemoryBlocks();
|
||||||
determineMemoryBlocks_orig();
|
// determineMemoryBlocks_orig();
|
||||||
mapPreExistingSymbols();
|
mapPreExistingSymbols();
|
||||||
createAddressRemap();
|
createAddressRemap();
|
||||||
}
|
}
|
||||||
|
@ -144,16 +146,10 @@ public class PdbAddressManager {
|
||||||
* {@code Address.EXTERNAL_ADDRESS} if the address is external to the program.
|
* {@code Address.EXTERNAL_ADDRESS} if the address is external to the program.
|
||||||
*/
|
*/
|
||||||
Address getRawAddress(int segment, long offset) {
|
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) {
|
if (segment < 0) {
|
||||||
return BAD_ADDRESS;
|
return BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
Long relativeVirtualAddress;
|
Long relativeVirtualAddress = null;
|
||||||
if (imageSectionHeaders != null) {
|
if (imageSectionHeaders != null) {
|
||||||
if (segment > imageSectionHeaders.size() + 1) {
|
if (segment > imageSectionHeaders.size() + 1) {
|
||||||
return BAD_ADDRESS;
|
return BAD_ADDRESS;
|
||||||
|
@ -164,8 +160,16 @@ public class PdbAddressManager {
|
||||||
}
|
}
|
||||||
relativeVirtualAddress =
|
relativeVirtualAddress =
|
||||||
imageSectionHeaders.get(segment - 1).getVirtualAddress() + offset;
|
imageSectionHeaders.get(segment - 1).getVirtualAddress() + offset;
|
||||||
|
relativeVirtualAddress = applyOMap(relativeVirtualAddress);
|
||||||
|
if (relativeVirtualAddress == null) {
|
||||||
|
return BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
if (relativeVirtualAddress == 0) {
|
||||||
|
return ZERO_ADDRESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// TODO: need to verify use of segments here!
|
||||||
if (segment > segmentMapList.size() + 1) {
|
if (segment > segmentMapList.size() + 1) {
|
||||||
return BAD_ADDRESS;
|
return BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
|
@ -176,32 +180,25 @@ public class PdbAddressManager {
|
||||||
// TODO: Need to verify. Guessing at the moment
|
// TODO: Need to verify. Guessing at the moment
|
||||||
relativeVirtualAddress = segmentMapList.get(segment - 1).getSegmentOffset();
|
relativeVirtualAddress = segmentMapList.get(segment - 1).getSegmentOffset();
|
||||||
}
|
}
|
||||||
if (omapFromSource != null) {
|
|
||||||
relativeVirtualAddress = omapFromSource.get(relativeVirtualAddress);
|
|
||||||
if (relativeVirtualAddress == null) {
|
|
||||||
return BAD_ADDRESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imageBase.add(relativeVirtualAddress);
|
return imageBase.add(relativeVirtualAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getRawAddress_orig(int segment, long offset) {
|
private Long applyOMap(Long relativeVirtualAddress) {
|
||||||
if (segment < 0 || segment > allSegmentsInfo.size()) {
|
if (omapFromSource == null) {
|
||||||
return BAD_ADDRESS;
|
return relativeVirtualAddress;
|
||||||
}
|
}
|
||||||
// We are lumping 0 and size as EXTERNAL... one or other could be image base... but not
|
// NOTE: Original map entries are 32-bit values zero-extended to a java long (64-bits)
|
||||||
// necessarily consistent... but that's OK... it is still "EXTERNAL" from the program.
|
SortedMap<Long, Long> headMap = omapFromSource.headMap(relativeVirtualAddress + 1);
|
||||||
else if (segment == 0 || segment == allSegmentsInfo.size()) {
|
if (headMap.isEmpty()) {
|
||||||
// External address.
|
return null;
|
||||||
// Was getting issues of _IMAGE_DOSHEADER showing up with a segment index one
|
|
||||||
// beyond the end.
|
|
||||||
return EXTERNAL_ADDRESS;
|
|
||||||
}
|
}
|
||||||
SegmentInfo segmentInfo = allSegmentsInfo.get(segment);
|
long from = headMap.lastKey();
|
||||||
if (offset >= segmentInfo.getLength()) {
|
long to = headMap.get(from);
|
||||||
return BAD_ADDRESS;
|
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() {
|
// private void determineMemoryBlocks_orig() {
|
||||||
// Set section/segment 0 to image base. (should be what is header), but what is its size?
|
// // 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.
|
// // 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
|
// // For now, the method that reads this information might report EXTERNAL instead of
|
||||||
// trying to use this.
|
// // trying to use this.
|
||||||
long segmentZeroLength = 0x7fffffff;
|
// long segmentZeroLength = 0x7fffffff;
|
||||||
allSegmentsInfo.add(new SegmentInfo(imageBase, segmentZeroLength));
|
// allSegmentsInfo.add(new SegmentInfo(imageBase, segmentZeroLength));
|
||||||
PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
|
// PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
|
||||||
if (dbi instanceof PdbNewDebugInfo) {
|
// if (dbi instanceof PdbNewDebugInfo) {
|
||||||
DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
|
// DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
|
||||||
List<ImageSectionHeader> imageSectionHeaders = debugData.getImageSectionHeaders();
|
// List<ImageSectionHeader> imageSectionHeaders = debugData.getImageSectionHeaders();
|
||||||
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
|
// for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
|
||||||
long virtualAddress = imageSectionHeader.getVirtualAddress();
|
// long virtualAddress = imageSectionHeader.getVirtualAddress();
|
||||||
// TODO: not sure when unionPAVS is physical address vs. virtual size. Perhaps
|
// // TODO: not sure when unionPAVS is physical address vs. virtual size. Perhaps
|
||||||
// it keys off whether virtualAddress is not some special value such as
|
// // it keys off whether virtualAddress is not some special value such as
|
||||||
// 0x00000000 or 0xffffffff.
|
// // 0x00000000 or 0xffffffff.
|
||||||
long size = imageSectionHeader.getUnionPAVS();
|
// long size = imageSectionHeader.getUnionPAVS();
|
||||||
allSegmentsInfo.add(new SegmentInfo(imageBase.add(virtualAddress), size));
|
// allSegmentsInfo.add(new SegmentInfo(imageBase.add(virtualAddress), size));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// else instance of PdbDebugInfo; TODO: what can we do here?
|
// // else instance of PdbDebugInfo; TODO: what can we do here?
|
||||||
// Maybe get information from the program itself.
|
// // Maybe get information from the program itself.
|
||||||
|
//
|
||||||
// TODO: what should we do with these? Not doing anything at the moment
|
// // TODO: what should we do with these? Not doing anything at the moment
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
// AbstractPdb pdb = applicator.getPdb();
|
||||||
List<SegmentMapDescription> segmentMapList = pdb.getDebugInfo().getSegmentMapList();
|
// List<SegmentMapDescription> segmentMapList = pdb.getDebugInfo().getSegmentMapList();
|
||||||
for (SegmentMapDescription segmentMapDescription : segmentMapList) {
|
// for (SegmentMapDescription segmentMapDescription : segmentMapList) {
|
||||||
segmentMapDescription.getSegmentOffset();
|
// segmentMapDescription.getSegmentOffset();
|
||||||
segmentMapDescription.getLength();
|
// segmentMapDescription.getLength();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void determineMemoryBlocks() {
|
private void determineMemoryBlocks() {
|
||||||
PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
|
PdbDebugInfo dbi = applicator.getPdb().getDebugInfo();
|
||||||
segmentMapList = dbi.getSegmentMapList();
|
segmentMapList = dbi.getSegmentMapList();
|
||||||
if (dbi instanceof PdbNewDebugInfo) {
|
if (dbi instanceof PdbNewDebugInfo) {
|
||||||
DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
|
DebugData debugData = ((PdbNewDebugInfo) dbi).getDebugData();
|
||||||
omapFromSource = debugData.getOmapFromSource();
|
imageSectionHeaders = debugData.getImageSectionHeadersOrig();
|
||||||
imageSectionHeaders = debugData.getImageSectionHeaders();
|
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
|
// Put in two basic entries so we do not have to do conditional tests before looking
|
||||||
// up values in the table.
|
// up values in the table.
|
||||||
remapAddressByAddress.put(BAD_ADDRESS, BAD_ADDRESS);
|
remapAddressByAddress.put(BAD_ADDRESS, BAD_ADDRESS);
|
||||||
|
remapAddressByAddress.put(ZERO_ADDRESS, ZERO_ADDRESS);
|
||||||
remapAddressByAddress.put(EXTERNAL_ADDRESS, EXTERNAL_ADDRESS);
|
remapAddressByAddress.put(EXTERNAL_ADDRESS, EXTERNAL_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,9 +200,8 @@ public class PdbApplicator {
|
||||||
|
|
||||||
pdbAddressManager.logReport();
|
pdbAddressManager.logReport();
|
||||||
|
|
||||||
String applicatorMetrics = pdbApplicatorMetrics.getPostProcessingReport();
|
pdbApplicatorMetrics.logReport();
|
||||||
Msg.info(this, applicatorMetrics);
|
|
||||||
PdbLog.message(applicatorMetrics);
|
|
||||||
Msg.info(this, "PDB Terminated Normally");
|
Msg.info(this, "PDB Terminated Normally");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,6 +799,10 @@ public class PdbApplicator {
|
||||||
appendLogMsg("Invalid address encountered for: " + name);
|
appendLogMsg("Invalid address encountered for: " + name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (address == PdbAddressManager.ZERO_ADDRESS) {
|
||||||
|
// Symbol OMAP resulted in 0 RVA - Discard silently
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (address == PdbAddressManager.EXTERNAL_ADDRESS) {
|
if (address == PdbAddressManager.EXTERNAL_ADDRESS) {
|
||||||
//Msg.info(this, "External address not known for: " + name);
|
//Msg.info(this, "External address not known for: " + name);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -18,10 +18,12 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
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.symbol.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.listing.Program;
|
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
|
* 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
|
* Generate some post-processing metrics and write to log
|
||||||
* @return {@link String} of pretty output.
|
|
||||||
*/
|
*/
|
||||||
String getPostProcessingReport() {
|
void logReport() {
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("===Begin PdbApplicatorMetrics Report===\n");
|
|
||||||
builder.append(reportNonappliableTypes());
|
builder.append(reportNonappliableTypes());
|
||||||
builder.append(reportUnunsualThisPointerTypes());
|
builder.append(reportUnunsualThisPointerTypes());
|
||||||
builder.append(reportUnunsualThisPointerUnderlyingTypes());
|
builder.append(reportUnunsualThisPointerUnderlyingTypes());
|
||||||
|
@ -214,8 +216,17 @@ public class PdbApplicatorMetrics {
|
||||||
builder.append(reportUnexpectedPublicSymbols());
|
builder.append(reportUnexpectedPublicSymbols());
|
||||||
builder.append(reportUnexpectedGlobalSymbols());
|
builder.append(reportUnexpectedGlobalSymbols());
|
||||||
builder.append(reportEnumerateNarrowing());
|
builder.append(reportEnumerateNarrowing());
|
||||||
|
|
||||||
|
if (builder.length() == 0) {
|
||||||
|
return; // nothing reported
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.insert(0, "===Begin PdbApplicatorMetrics Report===\n");
|
||||||
builder.append("====End 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() {
|
private String reportNonappliableTypes() {
|
||||||
|
|
|
@ -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.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractPublicMsSymbol;
|
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.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
||||||
import ghidra.program.model.address.Address;
|
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.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -56,9 +62,12 @@ public class PublicSymbolApplier extends MsSymbolApplier {
|
||||||
void apply() throws CancelledException, PdbException {
|
void apply() throws CancelledException, PdbException {
|
||||||
|
|
||||||
symbolAddress = applicator.getAddress(symbol);
|
symbolAddress = applicator.getAddress(symbol);
|
||||||
if (applicator.isInvalidAddress(symbolAddress, symbol.getName())) {
|
|
||||||
|
String name = symbol.getName();
|
||||||
|
if (applicator.isInvalidAddress(symbolAddress, name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
existingSymbolAddress = applicator.witnessSymbolNameAtAddress(getName(), symbolAddress);
|
existingSymbolAddress = applicator.witnessSymbolNameAtAddress(getName(), symbolAddress);
|
||||||
// TODO: Consider... could add restriction of not putting down symbol if it is mangled,
|
// TODO: Consider... could add restriction of not putting down symbol if it is mangled,
|
||||||
// as this would violate the uniqueness of the symbol... but we would also want to
|
// as this would violate the uniqueness of the symbol... but we would also want to
|
||||||
|
@ -67,7 +76,18 @@ public class PublicSymbolApplier extends MsSymbolApplier {
|
||||||
// Note: there might be issues of thunk functions getting the same mangled name
|
// Note: there might be issues of thunk functions getting the same mangled name
|
||||||
// as thunked functions, which violates the thesis of their being unique.
|
// as thunked functions, which violates the thesis of their being unique.
|
||||||
// TODO: investigate this.
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package pdb;
|
package pdb;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private boolean isCanceled;
|
private boolean isCanceled;
|
||||||
|
|
||||||
private boolean useMsDiaParser = true;
|
private boolean useMsDiaParser;
|
||||||
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE;
|
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,9 +58,10 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
||||||
optionsPanel.add(new JLabel("PDB Parser:"));
|
optionsPanel.add(new JLabel("PDB Parser:"));
|
||||||
|
|
||||||
if (isPdbFile) {
|
if (isPdbFile) {
|
||||||
|
useMsDiaParser = false; // Use PDB Universal by default
|
||||||
if (PdbParser.onWindows) {
|
if (PdbParser.onWindows) {
|
||||||
final GComboBox<String> combo =
|
final GComboBox<String> combo =
|
||||||
new GComboBox<>(new String[] { "PDB MSDIA", "PDB Universal (Prototype)" });
|
new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" });
|
||||||
combo.setSelectedIndex(0);
|
combo.setSelectedIndex(0);
|
||||||
restrictionsCombo.setEnabled(!useMsDiaParser);
|
restrictionsCombo.setEnabled(!useMsDiaParser);
|
||||||
combo.addActionListener(e -> {
|
combo.addActionListener(e -> {
|
||||||
|
@ -73,8 +75,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
useMsDiaParser = false;
|
useMsDiaParser = false;
|
||||||
JLabel label = new JLabel("PDB Universal (Prototype)");
|
JLabel label = new JLabel("PDB Universal");
|
||||||
label.setForeground(Color.red); // set color to emphasize prototype status
|
//label.setForeground(Color.red); // set color to emphasize prototype status
|
||||||
optionsPanel.add(label);
|
optionsPanel.add(label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ class LoadPdbTask extends Task {
|
||||||
|
|
||||||
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser,
|
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser,
|
||||||
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) {
|
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) {
|
||||||
super("Loading PDB...", true, false, false);
|
super("Load PDB", true, false, false);
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.pdbFile = pdbFile;
|
this.pdbFile = pdbFile;
|
||||||
this.useMsDiaParser = useMsDiaParser;
|
this.useMsDiaParser = useMsDiaParser;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue