mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-4773 - PDB - Standardize namespaces and improve class namespace determination; involved MDMangUtils too; re-instates GP-4595 change
This commit is contained in:
parent
cc2d53e594
commit
c26a290c14
11 changed files with 244 additions and 129 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.
|
||||||
|
@ -162,8 +162,12 @@ public class MDMangGhidra extends MDMang {
|
||||||
// what it is
|
// what it is
|
||||||
demangled = new DemangledType(mangledSource, qual.toString(), qual.toString());
|
demangled = new DemangledType(mangledSource, qual.toString(), qual.toString());
|
||||||
}
|
}
|
||||||
|
else if (qual.isLocalNamespace()) {
|
||||||
|
String local =
|
||||||
|
MDMangUtils.createStandardLocalNamespaceNode(qual.getLocalNamespaceNumber());
|
||||||
|
demangled = new DemangledNamespaceNode(mangledSource, qual.toString(), local);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// This takes care of plain and local namespaces
|
|
||||||
demangled = new DemangledNamespaceNode(mangledSource, qual.toString(), qual.toString());
|
demangled = new DemangledNamespaceNode(mangledSource, qual.toString(), qual.toString());
|
||||||
}
|
}
|
||||||
return demangled;
|
return demangled;
|
||||||
|
|
|
@ -169,7 +169,17 @@ public class MDMangUtils {
|
||||||
return anon;
|
return anon;
|
||||||
}
|
}
|
||||||
Long num = Long.valueOf(str, 16);
|
Long num = Long.valueOf(str, 16);
|
||||||
return String.format("anon_%08X", num);
|
return String.format("_anon_%08X", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a number in string format as input, creates the standardized local namespace
|
||||||
|
* node string of the format {@code __l2} where {@code 2} is an an example number.
|
||||||
|
* @param localNumber the input string
|
||||||
|
* @return the standardized local namespace component
|
||||||
|
*/
|
||||||
|
public static String createStandardLocalNamespaceNode(String localNumber) {
|
||||||
|
return String.format("__l%s", localNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
@ -250,7 +260,7 @@ public class MDMangUtils {
|
||||||
* @param symbolPath the symbol path to standardize
|
* @param symbolPath the symbol path to standardize
|
||||||
* @return the standardized symbol path
|
* @return the standardized symbol path
|
||||||
*/
|
*/
|
||||||
public static SymbolPath standarizeSymbolPath(SymbolPath symbolPath) {
|
public static SymbolPath standarizeSymbolPathTicks(SymbolPath symbolPath) {
|
||||||
List<String> parts = symbolPath.asList();
|
List<String> parts = symbolPath.asList();
|
||||||
for (int i = 0; i < parts.size(); i++) {
|
for (int i = 0; i < parts.size(); i++) {
|
||||||
String part = parts.get(i);
|
String part = parts.get(i);
|
||||||
|
@ -283,7 +293,7 @@ public class MDMangUtils {
|
||||||
* @param symbolPath the symbol path to standardize
|
* @param symbolPath the symbol path to standardize
|
||||||
* @return the standardized symbol path
|
* @return the standardized symbol path
|
||||||
*/
|
*/
|
||||||
public static SymbolPath standarizeSymbolPathAlt(SymbolPath symbolPath) {
|
public static SymbolPath standarizeSymbolPathUnderscores(SymbolPath symbolPath) {
|
||||||
List<String> parts = symbolPath.asList();
|
List<String> parts = symbolPath.asList();
|
||||||
for (int i = 0; i < parts.size(); i++) {
|
for (int i = 0; i < parts.size(); i++) {
|
||||||
String part = parts.get(i);
|
String part = parts.get(i);
|
||||||
|
|
|
@ -108,33 +108,33 @@ public class MDMangUtilsTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandarizeSymbolPath() throws Exception {
|
public void testStandarizeSymbolPathTicks() throws Exception {
|
||||||
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "__l1", "name2"));
|
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "__l1", "name2"));
|
||||||
SymbolPath result = MDMangUtils.standarizeSymbolPath(sp);
|
SymbolPath result = MDMangUtils.standarizeSymbolPathTicks(sp);
|
||||||
String expected = "name0::`1'::name2";
|
String expected = "name0::`1'::name2";
|
||||||
assertEquals(expected, result.toString());
|
assertEquals(expected, result.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandarizeSymbolPathWithEmbedded() throws Exception {
|
public void testStandarizeSymbolPathWithEmbeddedTicks() throws Exception {
|
||||||
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "__l1", "name2(name3::__l4::name5)"));
|
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "__l1", "name2(name3::__l4::name5)"));
|
||||||
SymbolPath result = MDMangUtils.standarizeSymbolPath(sp);
|
SymbolPath result = MDMangUtils.standarizeSymbolPathTicks(sp);
|
||||||
String expected = "name0::`1'::name2(name3::`4'::name5)";
|
String expected = "name0::`1'::name2(name3::`4'::name5)";
|
||||||
assertEquals(expected, result.toString());
|
assertEquals(expected, result.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandarizeSymbolPathAlt() throws Exception {
|
public void testStandarizeSymbolPathUnderscores() throws Exception {
|
||||||
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "`1'", "name2"));
|
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "`1'", "name2"));
|
||||||
SymbolPath result = MDMangUtils.standarizeSymbolPathAlt(sp);
|
SymbolPath result = MDMangUtils.standarizeSymbolPathUnderscores(sp);
|
||||||
String expected = "name0::__l1::name2";
|
String expected = "name0::__l1::name2";
|
||||||
assertEquals(expected, result.toString());
|
assertEquals(expected, result.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandarizeSymbolPathWithEmbeddedAlt() throws Exception {
|
public void testStandarizeSymbolPathWithEmbeddedUnderscores() throws Exception {
|
||||||
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "`1'", "name2(name3::`4'::name5)"));
|
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "`1'", "name2(name3::`4'::name5)"));
|
||||||
SymbolPath result = MDMangUtils.standarizeSymbolPathAlt(sp);
|
SymbolPath result = MDMangUtils.standarizeSymbolPathUnderscores(sp);
|
||||||
String expected = "name0::__l1::name2(name3::__l4::name5)";
|
String expected = "name0::__l1::name2(name3::__l4::name5)";
|
||||||
assertEquals(expected, result.toString());
|
assertEquals(expected, result.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -19,6 +19,7 @@ import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.app.util.SymbolPathParser;
|
import ghidra.app.util.SymbolPathParser;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractComplexMsType;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractComplexMsType;
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
||||||
import ghidra.app.util.pdb.PdbNamespaceUtils;
|
import ghidra.app.util.pdb.PdbNamespaceUtils;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import mdemangler.*;
|
import mdemangler.*;
|
||||||
|
@ -45,22 +46,7 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
|
||||||
* @see #getFixedSymbolPath(AbstractComplexMsType type)
|
* @see #getFixedSymbolPath(AbstractComplexMsType type)
|
||||||
*/
|
*/
|
||||||
SymbolPath getSymbolPath(AbstractComplexMsType type) {
|
SymbolPath getSymbolPath(AbstractComplexMsType type) {
|
||||||
SymbolPath symbolPath = null;
|
return getSymbolPath(type.getName(), type.getMangledName());
|
||||||
// We added logic to check the mangled name first because we found some LLVM "lambda"
|
|
||||||
// symbols where the regular name was a generic "<lambda_0>" with a namespace, but this
|
|
||||||
// often had a member that also lambda that was marked with the exact same namespace/name
|
|
||||||
// as the containing structure. We found that the mangled names had more accurate and
|
|
||||||
// distinguished lambda numbers.
|
|
||||||
// Temporarily comment out main work of GP-4595 due to namespace/class issues (20240705) TODO: fix
|
|
||||||
// String mangledName = type.getMangledName();
|
|
||||||
// if (mangledName != null) {
|
|
||||||
// symbolPath = getSymbolPathFromMangledTypeName(mangledName);
|
|
||||||
// }
|
|
||||||
if (symbolPath == null) {
|
|
||||||
String fullPathName = type.getName();
|
|
||||||
symbolPath = new SymbolPath(SymbolPathParser.parse(fullPathName));
|
|
||||||
}
|
|
||||||
return symbolPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +78,45 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
|
||||||
return PdbNamespaceUtils.convertToGhidraPathName(path, num);
|
return PdbNamespaceUtils.convertToGhidraPathName(path, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SymbolPath getSymbolPathFromMangledTypeName(String mangledString) {
|
/**
|
||||||
|
* Returns the symbol path for the data type referenced by the type record number provided
|
||||||
|
* @param applicator the applicator
|
||||||
|
* @param recordNumber the record number
|
||||||
|
* @return the symbol path
|
||||||
|
*/
|
||||||
|
public static SymbolPath getSymbolPath(DefaultPdbApplicator applicator,
|
||||||
|
RecordNumber recordNumber) {
|
||||||
|
AbstractMsType t = applicator.getTypeRecord(recordNumber);
|
||||||
|
if (!(t instanceof AbstractComplexMsType ct)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CppCompositeType cpp = applicator.getClassType(ct);
|
||||||
|
if (cpp != null) {
|
||||||
|
return cpp.getSymbolPath();
|
||||||
|
}
|
||||||
|
return getSymbolPath(ct.getName(), ct.getMangledName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SymbolPath getSymbolPath(String name, String mangledName) {
|
||||||
|
SymbolPath symbolPath = null;
|
||||||
|
// We added logic to check the mangled name first because we found some LLVM "lambda"
|
||||||
|
// symbols where the regular name was a generic "<lambda_0>" with a namespace, but this
|
||||||
|
// often had a member that also lambda that was marked with the exact same namespace/name
|
||||||
|
// as the containing structure. We found that the mangled names had more accurate and
|
||||||
|
// distinguished lambda numbers.
|
||||||
|
if (mangledName != null) {
|
||||||
|
symbolPath = getSymbolPathFromMangledTypeName(mangledName, name);
|
||||||
|
}
|
||||||
|
if (symbolPath == null) {
|
||||||
|
symbolPath =
|
||||||
|
MDMangUtils.standarizeSymbolPathUnderscores(
|
||||||
|
new SymbolPath(SymbolPathParser.parse(name)));
|
||||||
|
}
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SymbolPath getSymbolPathFromMangledTypeName(String mangledString,
|
||||||
|
String fullPathName) {
|
||||||
MDMang demangler = new MDMangGhidra();
|
MDMang demangler = new MDMangGhidra();
|
||||||
try {
|
try {
|
||||||
MDDataType mdDataType = demangler.demangleType(mangledString, true);
|
MDDataType mdDataType = demangler.demangleType(mangledString, true);
|
||||||
|
@ -101,7 +125,7 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
|
||||||
// Namespace that are flagged as functions (not capable at this time) or types or
|
// Namespace that are flagged as functions (not capable at this time) or types or
|
||||||
// raw namespace nodes. Note, however, that the Demangler is still weak in this
|
// raw namespace nodes. Note, however, that the Demangler is still weak in this
|
||||||
// area as there are codes that we still not know how to interpret.
|
// area as there are codes that we still not know how to interpret.
|
||||||
return MDMangUtils.getSymbolPath(mdDataType);
|
return MDMangUtils.consolidateSymbolPath(mdDataType, fullPathName, true);
|
||||||
// Could consider the following simplification method instead
|
// Could consider the following simplification method instead
|
||||||
// return MDMangUtils.getSimpleSymbolPath(mdDataType);
|
// return MDMangUtils.getSimpleSymbolPath(mdDataType);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +134,7 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
|
||||||
// Message might cause too much noise (we have a fallback, above, to use the regular
|
// Message might cause too much noise (we have a fallback, above, to use the regular
|
||||||
// name, but this could cause an error... see the notes above about why a mangled
|
// name, but this could cause an error... see the notes above about why a mangled
|
||||||
// name is checked first).
|
// name is checked first).
|
||||||
Msg.info(this,
|
Msg.info(AbstractComplexTypeApplier.class,
|
||||||
"PDB issue dmangling type name: " + e.getMessage() + " for : " + mangledString);
|
"PDB issue dmangling type name: " + e.getMessage() + " for : " + mangledString);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -82,19 +82,19 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
|
||||||
myApplicator.predefineClass(fixedSymbolPath);
|
myApplicator.predefineClass(fixedSymbolPath);
|
||||||
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
|
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
|
||||||
myApplicator.getDataTypeManager());
|
myApplicator.getDataTypeManager());
|
||||||
myClassType = new CppCompositeType(myComposite, mangledName);
|
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
|
||||||
myClassType.setClass();
|
myClassType.setClass();
|
||||||
}
|
}
|
||||||
else if (compositeMsType instanceof AbstractStructureMsType) {
|
else if (compositeMsType instanceof AbstractStructureMsType) {
|
||||||
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
|
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
|
||||||
myApplicator.getDataTypeManager());
|
myApplicator.getDataTypeManager());
|
||||||
myClassType = new CppCompositeType(myComposite, mangledName);
|
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
|
||||||
myClassType.setStruct();
|
myClassType.setStruct();
|
||||||
}
|
}
|
||||||
else if (compositeMsType instanceof AbstractUnionMsType) {
|
else if (compositeMsType instanceof AbstractUnionMsType) {
|
||||||
myComposite = new UnionDataType(categoryPath, fixedSymbolPath.getName(),
|
myComposite = new UnionDataType(categoryPath, fixedSymbolPath.getName(),
|
||||||
myApplicator.getDataTypeManager());
|
myApplicator.getDataTypeManager());
|
||||||
myClassType = new CppCompositeType(myComposite, mangledName);
|
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
|
||||||
myClassType.setUnion();
|
myClassType.setUnion();
|
||||||
}
|
}
|
||||||
else { // InterfaceMsType
|
else { // InterfaceMsType
|
||||||
|
@ -142,6 +142,16 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
|
||||||
boolean isClass = (type instanceof AbstractClassMsType);
|
boolean isClass = (type instanceof AbstractClassMsType);
|
||||||
int size = getSizeInt(type);
|
int size = getSizeInt(type);
|
||||||
clearComponents(composite);
|
clearComponents(composite);
|
||||||
|
if (!lists.methods().isEmpty()) {
|
||||||
|
// See applyCpp where we store sp in CppCompositeType so we don't have to determine
|
||||||
|
// this again (including possible demangling)... need a place to store this or
|
||||||
|
// make sure our CppCompositeType (or its replacement) can be the union solution as
|
||||||
|
// well. Note that the namespace convention of making a Class namespace is what
|
||||||
|
// allows the "this" pointer to be a pointer to the appropriate container type (even
|
||||||
|
// though this is a "union").
|
||||||
|
SymbolPath sp = getFixedSymbolPath(type);
|
||||||
|
applicator.predefineClass(sp);
|
||||||
|
}
|
||||||
List<DefaultPdbUniversalMember> myMembers = new ArrayList<>();
|
List<DefaultPdbUniversalMember> myMembers = new ArrayList<>();
|
||||||
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
|
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
|
||||||
addMembers(composite, classType, lists.nonstaticMembers(), type, myMembers);
|
addMembers(composite, classType, lists.nonstaticMembers(), type, myMembers);
|
||||||
|
@ -159,6 +169,10 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
|
||||||
Composite composite = combo.dt();
|
Composite composite = combo.dt();
|
||||||
CppCompositeType classType = combo.ct();
|
CppCompositeType classType = combo.ct();
|
||||||
clearComponents(composite);
|
clearComponents(composite);
|
||||||
|
if (!lists.bases().isEmpty() || !lists.methods().isEmpty()) {
|
||||||
|
SymbolPath sp = classType.getSymbolPath();
|
||||||
|
applicator.predefineClass(sp);
|
||||||
|
}
|
||||||
List<DefaultPdbUniversalMember> myMembers = new ArrayList<>();
|
List<DefaultPdbUniversalMember> myMembers = new ArrayList<>();
|
||||||
addClassTypeBaseClasses(composite, classType, lists.bases(), type);
|
addClassTypeBaseClasses(composite, classType, lists.bases(), type);
|
||||||
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
|
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.app.util.bin.format.pdb.*;
|
import ghidra.app.util.bin.format.pdb.*;
|
||||||
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.PdbLog;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
|
||||||
|
@ -48,6 +49,7 @@ public class CppCompositeType {
|
||||||
private String className; // String for now.
|
private String className; // String for now.
|
||||||
private String mangledName;
|
private String mangledName;
|
||||||
private int size;
|
private int size;
|
||||||
|
private SymbolPath symbolPath;
|
||||||
private Composite composite;
|
private Composite composite;
|
||||||
private CategoryPath categoryPath;
|
private CategoryPath categoryPath;
|
||||||
|
|
||||||
|
@ -78,7 +80,8 @@ public class CppCompositeType {
|
||||||
private Map<Integer, PlaceholderVirtualBaseTable> placeholderVirtualBaseTables;
|
private Map<Integer, PlaceholderVirtualBaseTable> placeholderVirtualBaseTables;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
public CppCompositeType(Composite composite, String mangledName) {
|
public CppCompositeType(SymbolPath symbolPath, Composite composite, String mangledName) {
|
||||||
|
Objects.requireNonNull(symbolPath, "symbolPath may not be null");
|
||||||
Objects.requireNonNull(composite, "composite may not be null");
|
Objects.requireNonNull(composite, "composite may not be null");
|
||||||
syntacticBaseClasses = new ArrayList<>();
|
syntacticBaseClasses = new ArrayList<>();
|
||||||
layoutBaseClasses = new ArrayList<>();
|
layoutBaseClasses = new ArrayList<>();
|
||||||
|
@ -90,46 +93,49 @@ public class CppCompositeType {
|
||||||
|
|
||||||
isFinal = false;
|
isFinal = false;
|
||||||
type = Type.UNKNOWN;
|
type = Type.UNKNOWN;
|
||||||
|
this.symbolPath = symbolPath;
|
||||||
this.composite = composite;
|
this.composite = composite;
|
||||||
placeholderVirtualBaseTables = new HashMap<>();
|
placeholderVirtualBaseTables = new HashMap<>();
|
||||||
categoryPath = new CategoryPath(composite.getCategoryPath(), composite.getName());
|
categoryPath = new CategoryPath(composite.getCategoryPath(), composite.getName());
|
||||||
this.mangledName = mangledName;
|
this.mangledName = mangledName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CppClassType createCppClassType(Composite composite, String mangledName) {
|
public static CppClassType createCppClassType(SymbolPath symbolPath, Composite composite,
|
||||||
return new CppClassType(composite, mangledName);
|
String mangledName) {
|
||||||
|
return new CppClassType(symbolPath, composite, mangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CppClassType createCppClassType(Composite composite, String name,
|
public static CppClassType createCppClassType(SymbolPath symbolPath, Composite composite,
|
||||||
String mangledName, int size) {
|
String name, String mangledName, int size) {
|
||||||
CppClassType cppType = new CppClassType(composite, mangledName);
|
CppClassType cppType = new CppClassType(symbolPath, composite, mangledName);
|
||||||
cppType.setName(name);
|
cppType.setName(name);
|
||||||
cppType.setSize(size);
|
cppType.setSize(size);
|
||||||
return cppType;
|
return cppType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CppStructType createCppStructType(Composite composite, String mangledName) {
|
public static CppStructType createCppStructType(SymbolPath symbolPath, Composite composite,
|
||||||
return new CppStructType(composite, mangledName);
|
String mangledName) {
|
||||||
|
return new CppStructType(symbolPath, composite, mangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CppStructType createCppStructType(Composite composite, String name,
|
public static CppStructType createCppStructType(SymbolPath symbolPath, Composite composite,
|
||||||
String mangledName, int size) {
|
String name, String mangledName, int size) {
|
||||||
CppStructType cppType = new CppStructType(composite, mangledName);
|
CppStructType cppType = new CppStructType(symbolPath, composite, mangledName);
|
||||||
cppType.setName(name);
|
cppType.setName(name);
|
||||||
cppType.setSize(size);
|
cppType.setSize(size);
|
||||||
return cppType;
|
return cppType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CppClassType extends CppCompositeType {
|
private static class CppClassType extends CppCompositeType {
|
||||||
private CppClassType(Composite composite, String mangledName) {
|
private CppClassType(SymbolPath symbolPath, Composite composite, String mangledName) {
|
||||||
super(composite, mangledName);
|
super(symbolPath, composite, mangledName);
|
||||||
setClass();
|
setClass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CppStructType extends CppCompositeType {
|
private static class CppStructType extends CppCompositeType {
|
||||||
private CppStructType(Composite composite, String mangledName) {
|
private CppStructType(SymbolPath symbolPath, Composite composite, String mangledName) {
|
||||||
super(composite, mangledName);
|
super(symbolPath, composite, mangledName);
|
||||||
setStruct();
|
setStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,6 +192,10 @@ public class CppCompositeType {
|
||||||
return layoutBaseClasses;
|
return layoutBaseClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolPath getSymbolPath() {
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
|
||||||
Composite getComposite() {
|
Composite getComposite() {
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -49,6 +49,7 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.CancelOnlyWrappingTaskMonitor;
|
import ghidra.util.task.CancelOnlyWrappingTaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import mdemangler.MDMangUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main engine for applying an AbstractPdb to Ghidra, whether a Program or DataTypeManager.
|
* The main engine for applying an AbstractPdb to Ghidra, whether a Program or DataTypeManager.
|
||||||
|
@ -2249,42 +2250,23 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
@SuppressWarnings("unused") // For method not being called. In process of removing this version
|
boolean addToPlateUnique(Address address, String comment) {
|
||||||
boolean createSymbolOld(Address address, String symbolPathString, boolean forcePrimary) {
|
if (StringUtils.isBlank(comment)) {
|
||||||
|
return false;
|
||||||
// storeLabelByAddress(address, symbolPathString);
|
}
|
||||||
|
String plate = program.getListing().getComment(CodeUnit.PLATE_COMMENT, address);
|
||||||
try {
|
if (plate == null) {
|
||||||
Namespace namespace = program.getGlobalNamespace();
|
plate = "";
|
||||||
if (symbolPathString.startsWith(THUNK_NAME_PREFIX)) {
|
}
|
||||||
symbolPathString = symbolPathString.substring(THUNK_NAME_PREFIX.length(),
|
else if (plate.contains(comment)) {
|
||||||
symbolPathString.length());
|
|
||||||
}
|
|
||||||
SymbolPath symbolPath = new SymbolPath(symbolPathString);
|
|
||||||
symbolPath = symbolPath.replaceInvalidChars();
|
|
||||||
String name = symbolPath.getName();
|
|
||||||
String namespacePath = symbolPath.getParentPath();
|
|
||||||
if (namespacePath != null) {
|
|
||||||
namespace = NamespaceUtils.createNamespaceHierarchy(namespacePath, namespace,
|
|
||||||
program, address, SourceType.IMPORTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol s = SymbolUtilities.createPreferredLabelOrFunctionSymbol(program, address,
|
|
||||||
namespace, name, SourceType.IMPORTED);
|
|
||||||
if (s != null && forcePrimary) {
|
|
||||||
// PDB contains both mangled, namespace names, and global names
|
|
||||||
// If mangled name does not remain primary it will not get demamgled
|
|
||||||
// and we may not get signature information applied
|
|
||||||
SetLabelPrimaryCmd cmd =
|
|
||||||
new SetLabelPrimaryCmd(address, s.getName(), s.getParentNamespace());
|
|
||||||
cmd.applyTo(program);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
else if (!comment.endsWith("\n")) {
|
||||||
log.appendMsg("PDB Warning: Unable to create symbol: " + e.getMessage());
|
comment += '\n';
|
||||||
}
|
}
|
||||||
return false;
|
plate = comment + plate; // putting new comment at top of existing plate
|
||||||
|
SetCommentCmd.createComment(program, address, plate, CodeUnit.PLATE_COMMENT);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -2292,48 +2274,59 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
return createSymbol(address, symbolPathString, isNewFunctionSignature, null);
|
return createSymbol(address, symbolPathString, isNewFunctionSignature, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Symbol createSymbol(Address address, SymbolPath symbolPath, boolean isNewFunctionSignature) {
|
||||||
|
symbolPath = MDMangUtils.standarizeSymbolPathUnderscores(symbolPath);
|
||||||
|
symbolPath = symbolPath.replaceInvalidChars();
|
||||||
|
return createSymbolInternal(address, symbolPath, isNewFunctionSignature, null);
|
||||||
|
}
|
||||||
|
|
||||||
Symbol createSymbol(Address address, String symbolPathString, boolean isNewFunctionSignature,
|
Symbol createSymbol(Address address, String symbolPathString, boolean isNewFunctionSignature,
|
||||||
String plateAddition) {
|
String plateAddition) {
|
||||||
|
SymbolPath symbolPath = getCleanSymbolPath(symbolPathString);
|
||||||
|
return createSymbolInternal(address, symbolPath, isNewFunctionSignature, plateAddition);
|
||||||
|
}
|
||||||
|
|
||||||
SymbolPath newSymbolPath = getCleanSymbolPath(symbolPathString);
|
private Symbol createSymbolInternal(Address address, SymbolPath symbolPath,
|
||||||
|
boolean isNewFunctionSignature,
|
||||||
|
String plateAddition) {
|
||||||
|
|
||||||
Symbol existingSymbol = program.getSymbolTable().getPrimarySymbol(address);
|
Symbol existingSymbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||||
if (existingSymbol == null || isNewFunctionSignature) {
|
if (existingSymbol == null || isNewFunctionSignature) {
|
||||||
return createSymbol(address, newSymbolPath, true, plateAddition);
|
return doCreateSymbol(address, symbolPath, true, plateAddition);
|
||||||
}
|
}
|
||||||
if (existingSymbol.getSymbolType() == SymbolType.FUNCTION &&
|
if (existingSymbol.getSymbolType() == SymbolType.FUNCTION &&
|
||||||
existingSymbol.getSource() == SourceType.DEFAULT) {
|
existingSymbol.getSource() == SourceType.DEFAULT) {
|
||||||
return createSymbol(address, newSymbolPath, true, plateAddition);
|
return doCreateSymbol(address, symbolPath, true, plateAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function existingFunction = program.getListing().getFunctionAt(address);
|
Function existingFunction = program.getListing().getFunctionAt(address);
|
||||||
if (existingFunction != null) { // Maybe I should care if there is a data type there too.
|
if (existingFunction != null) { // Maybe I should care if there is a data type there too.
|
||||||
if (existingFunction.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
|
if (existingFunction.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
|
||||||
// Existing is USER or IMPORTED
|
// Existing is USER or IMPORTED
|
||||||
return createSymbol(address, newSymbolPath, false, plateAddition);
|
return doCreateSymbol(address, symbolPath, false, plateAddition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!existingSymbol.getParentNamespace().equals(program.getGlobalNamespace())) {
|
if (!existingSymbol.getParentNamespace().equals(program.getGlobalNamespace())) {
|
||||||
// existing symbol has a non-global namespace
|
// existing symbol has a non-global namespace
|
||||||
return createSymbol(address, newSymbolPath, false, plateAddition);
|
return doCreateSymbol(address, symbolPath, false, plateAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newSymbolPath.getParent() != null) {
|
if (symbolPath.getParent() != null) {
|
||||||
// new symbol has non-global namespace
|
// new symbol has non-global namespace
|
||||||
return createSymbol(address, newSymbolPath, true, plateAddition);
|
return doCreateSymbol(address, symbolPath, true, plateAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both existing and new symbols are in global namespace at this point
|
// Both existing and new symbols are in global namespace at this point
|
||||||
if (isMangled(symbolPathString) && !isMangled(existingSymbol.getName())) {
|
if (isMangled(symbolPath.getName()) && !isMangled(existingSymbol.getName())) {
|
||||||
// new symbol is mangled, but don't override existing one if it is mangled
|
// new symbol is mangled, but don't override existing one if it is mangled
|
||||||
return createSymbol(address, newSymbolPath, true, plateAddition);
|
return doCreateSymbol(address, symbolPath, true, plateAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
return createSymbol(address, newSymbolPath, false, plateAddition);
|
return doCreateSymbol(address, symbolPath, false, plateAddition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Symbol createSymbol(Address address, SymbolPath symbolPath, boolean makePrimary,
|
private Symbol doCreateSymbol(Address address, SymbolPath symbolPath, boolean makePrimary,
|
||||||
String plateAddition) {
|
String plateAddition) {
|
||||||
Symbol symbol = null;
|
Symbol symbol = null;
|
||||||
try {
|
try {
|
||||||
|
@ -2362,25 +2355,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addToPlateUnique(Address address, String comment) {
|
|
||||||
if (StringUtils.isBlank(comment)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String plate = program.getListing().getComment(CodeUnit.PLATE_COMMENT, address);
|
|
||||||
if (plate == null) {
|
|
||||||
plate = "";
|
|
||||||
}
|
|
||||||
else if (plate.contains(comment)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (!comment.endsWith("\n")) {
|
|
||||||
comment += '\n';
|
|
||||||
}
|
|
||||||
plate = comment + plate; // putting new comment at top of existing plate
|
|
||||||
SetCommentCmd.createComment(program, address, plate, CodeUnit.PLATE_COMMENT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isMangled(String name) {
|
private static boolean isMangled(String name) {
|
||||||
return name.startsWith("?");
|
return name.startsWith("?");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -123,6 +123,14 @@ public class EnumTypeApplier extends AbstractComplexTypeApplier {
|
||||||
FieldListTypeApplier.FieldLists lists =
|
FieldListTypeApplier.FieldLists lists =
|
||||||
fieldListApplier.getFieldLists(fieldListRecordNumber);
|
fieldListApplier.getFieldLists(fieldListRecordNumber);
|
||||||
|
|
||||||
|
if (!lists.methods().isEmpty()) {
|
||||||
|
// See applyCpp where we store sp in CppCompositeType so we don't have to determine
|
||||||
|
// this again (including possible demangling)... can we store this symbol path
|
||||||
|
// somewhere as well so we do not need to re-create it?
|
||||||
|
SymbolPath sp = getFixedSymbolPath(type);
|
||||||
|
applicator.predefineClass(sp);
|
||||||
|
}
|
||||||
|
|
||||||
// Note: not doing anything with getNamespaceList() or getMethodsList() at this time.
|
// Note: not doing anything with getNamespaceList() or getMethodsList() at this time.
|
||||||
List<AbstractEnumerateMsType> enumerates = lists.enumerates();
|
List<AbstractEnumerateMsType> enumerates = lists.enumerates();
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -15,11 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||||
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
||||||
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
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.*;
|
||||||
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.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
@ -28,6 +31,7 @@ import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
@ -103,7 +107,68 @@ public class FunctionSymbolApplier extends AbstractBlockContextApplier
|
||||||
// If signature was set, then override existing primary mangled symbol with
|
// If signature was set, then override existing primary mangled symbol with
|
||||||
// the global symbol that provided this signature so that Demangler does not overwrite
|
// the global symbol that provided this signature so that Demangler does not overwrite
|
||||||
// the richer data type we get with global symbols.
|
// the richer data type we get with global symbols.
|
||||||
applicator.createSymbol(address, name, succeededSetFunctionSignature);
|
applicator.createSymbol(address, getReconciledSymbolPath(), succeededSetFunctionSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SymbolPath getReconciledSymbolPath() {
|
||||||
|
|
||||||
|
String name = symbol.getName();
|
||||||
|
SymbolPath symbolPath = new SymbolPath(name);
|
||||||
|
RecordNumber typeRecordNumber = symbol.getTypeRecordNumber();
|
||||||
|
AbstractMsType fType = applicator.getTypeRecord(typeRecordNumber);
|
||||||
|
if (!(fType instanceof AbstractMemberFunctionMsType memberFunction)) {
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get containing type, and while we are at it, ensure that it is defined as a class
|
||||||
|
// namespace.
|
||||||
|
// This has likely already been done, but we want to be sure that it has.
|
||||||
|
RecordNumber rc = memberFunction.getContainingClassRecordNumber();
|
||||||
|
SymbolPath containerSymbolPath = AbstractComplexTypeApplier.getSymbolPath(applicator, rc);
|
||||||
|
applicator.predefineClass(containerSymbolPath);
|
||||||
|
|
||||||
|
// Make sure that the symbol path of the underlying type of the this pointer is also
|
||||||
|
// defined as a class namespace.
|
||||||
|
// Probably does not need to be done, as it likely was done for the underlying data type.
|
||||||
|
AbstractMsType p = memberFunction.getThisPointerType();
|
||||||
|
if (p instanceof AbstractPointerMsType ptr) {
|
||||||
|
RecordNumber rpt = ptr.getUnderlyingRecordNumber();
|
||||||
|
if (!rpt.equals(rc)) {
|
||||||
|
SymbolPath underlyingSymbolPath =
|
||||||
|
AbstractComplexTypeApplier.getSymbolPath(applicator, rc);
|
||||||
|
applicator.predefineClass(underlyingSymbolPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only trying to fix up anonymous namespaces
|
||||||
|
if (!name.startsWith("`anonymous namespace'") && !name.startsWith("anonymous-namespace")) {
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconcile path of function with path of container type.
|
||||||
|
// Logic is a little different from what is in MDMangUtils.
|
||||||
|
// Want all namespace nodes to match except possibly the first one, which should be
|
||||||
|
// the anonymous namespace one.
|
||||||
|
List<String> containerParts = containerSymbolPath.asList();
|
||||||
|
List<String> parts = symbolPath.asList();
|
||||||
|
if (containerParts.size() != parts.size() - 1) {
|
||||||
|
Msg.info(this, "Unmatched symbol path size during fn name reconcilation");
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < containerParts.size(); i++) {
|
||||||
|
String containerPart = containerParts.get(i);
|
||||||
|
String part = parts.get(i);
|
||||||
|
if (!containerPart.equals(part)) {
|
||||||
|
if (i == 0) {
|
||||||
|
parts.set(i, containerPart);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Msg.info(this, "Mismatch symbol path nodes during fn name reconcilation");
|
||||||
|
return symbolPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SymbolPath(parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -99,6 +99,9 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier {
|
||||||
if (!(applier instanceof CompositeTypeApplier compApplier)) {
|
if (!(applier instanceof CompositeTypeApplier compApplier)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 20240709: found example of "this" pointer of method that referenced a composite that
|
||||||
|
// did not have any base classes or methods. So we want to make sure we take the
|
||||||
|
// opportunity here to promote the namespace to a class.
|
||||||
SymbolPath sp = compApplier.getFixedSymbolPath(msComposite);
|
SymbolPath sp = compApplier.getFixedSymbolPath(msComposite);
|
||||||
applicator.predefineClass(sp);
|
applicator.predefineClass(sp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.app.plugin.core.checksums.MyTestMemory;
|
import ghidra.app.plugin.core.checksums.MyTestMemory;
|
||||||
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressIterator;
|
import ghidra.program.model.address.AddressIterator;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
@ -476,14 +477,16 @@ public class CppCompositeTypeTest extends AbstractGenericTest {
|
||||||
|
|
||||||
private static CppCompositeType createStruct32(String name, int size) {
|
private static CppCompositeType createStruct32(String name, int size) {
|
||||||
Composite composite = new StructureDataType(CategoryPath.ROOT, name, 0, dtm32);
|
Composite composite = new StructureDataType(CategoryPath.ROOT, name, 0, dtm32);
|
||||||
|
SymbolPath symbolPath = new SymbolPath(name);
|
||||||
String mangledName = createMangledName(name, CppCompositeType.Type.STRUCT);
|
String mangledName = createMangledName(name, CppCompositeType.Type.STRUCT);
|
||||||
return CppCompositeType.createCppStructType(composite, name, mangledName, size);
|
return CppCompositeType.createCppStructType(symbolPath, composite, name, mangledName, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CppCompositeType createStruct64(String name, int size) {
|
private static CppCompositeType createStruct64(String name, int size) {
|
||||||
Composite composite = new StructureDataType(CategoryPath.ROOT, name, 0, dtm64);
|
Composite composite = new StructureDataType(CategoryPath.ROOT, name, 0, dtm64);
|
||||||
|
SymbolPath symbolPath = new SymbolPath(name);
|
||||||
String mangledName = createMangledName(name, CppCompositeType.Type.STRUCT);
|
String mangledName = createMangledName(name, CppCompositeType.Type.STRUCT);
|
||||||
return CppCompositeType.createCppStructType(composite, name, mangledName, 0);
|
return CppCompositeType.createCppStructType(symbolPath, composite, name, mangledName, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createMangledName(String className, CppCompositeType.Type type) {
|
private static String createMangledName(String className, CppCompositeType.Type type) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue