Skip to content

Commit

Permalink
GP-4773 - PDB - Standardize namespaces and improve class namespace de…
Browse files Browse the repository at this point in the history
…termination; involved MDMangUtils too; re-instates GP-4595 change
  • Loading branch information
ghizard committed Jul 18, 2024
1 parent cc2d53e commit c26a290
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down Expand Up @@ -162,8 +162,12 @@ else if (qual.isNameC()) {
// what it is
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 {
// This takes care of plain and local namespaces
demangled = new DemangledNamespaceNode(mangledSource, qual.toString(), qual.toString());
}
return demangled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,17 @@ else if (anon.startsWith("`")) {
return anon;
}
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
Expand Down Expand Up @@ -250,7 +260,7 @@ public static SymbolPath consolidateSymbolPath(MDParsableItem parsableItem,
* @param symbolPath the symbol path to standardize
* @return the standardized symbol path
*/
public static SymbolPath standarizeSymbolPath(SymbolPath symbolPath) {
public static SymbolPath standarizeSymbolPathTicks(SymbolPath symbolPath) {
List<String> parts = symbolPath.asList();
for (int i = 0; i < parts.size(); i++) {
String part = parts.get(i);
Expand Down Expand Up @@ -283,7 +293,7 @@ public static SymbolPath standarizeSymbolPath(SymbolPath symbolPath) {
* @param symbolPath the symbol path to standardize
* @return the standardized symbol path
*/
public static SymbolPath standarizeSymbolPathAlt(SymbolPath symbolPath) {
public static SymbolPath standarizeSymbolPathUnderscores(SymbolPath symbolPath) {
List<String> parts = symbolPath.asList();
for (int i = 0; i < parts.size(); i++) {
String part = parts.get(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,33 +108,33 @@ public void testTypeNamespaceSimpleConversionDoesNotApply2() throws Exception {
}

@Test
public void testStandarizeSymbolPath() throws Exception {
public void testStandarizeSymbolPathTicks() throws Exception {
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "__l1", "name2"));
SymbolPath result = MDMangUtils.standarizeSymbolPath(sp);
SymbolPath result = MDMangUtils.standarizeSymbolPathTicks(sp);
String expected = "name0::`1'::name2";
assertEquals(expected, result.toString());
}

@Test
public void testStandarizeSymbolPathWithEmbedded() throws Exception {
public void testStandarizeSymbolPathWithEmbeddedTicks() throws Exception {
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)";
assertEquals(expected, result.toString());
}

@Test
public void testStandarizeSymbolPathAlt() throws Exception {
public void testStandarizeSymbolPathUnderscores() throws Exception {
SymbolPath sp = new SymbolPath(Arrays.asList("name0", "`1'", "name2"));
SymbolPath result = MDMangUtils.standarizeSymbolPathAlt(sp);
SymbolPath result = MDMangUtils.standarizeSymbolPathUnderscores(sp);
String expected = "name0::__l1::name2";
assertEquals(expected, result.toString());
}

@Test
public void testStandarizeSymbolPathWithEmbeddedAlt() throws Exception {
public void testStandarizeSymbolPathWithEmbeddedUnderscores() throws Exception {
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)";
assertEquals(expected, result.toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -19,6 +19,7 @@
import ghidra.app.util.SymbolPathParser;
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.AbstractMsType;
import ghidra.app.util.pdb.PdbNamespaceUtils;
import ghidra.util.Msg;
import mdemangler.*;
Expand All @@ -45,22 +46,7 @@ public AbstractComplexTypeApplier(DefaultPdbApplicator applicator) {
* @see #getFixedSymbolPath(AbstractComplexMsType type)
*/
SymbolPath getSymbolPath(AbstractComplexMsType type) {
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.
// 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;
return getSymbolPath(type.getName(), type.getMangledName());
}

/**
Expand Down Expand Up @@ -92,7 +78,45 @@ SymbolPath getFixedSymbolPath(AbstractComplexMsType type) {
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();
try {
MDDataType mdDataType = demangler.demangleType(mangledString, true);
Expand All @@ -101,7 +125,7 @@ private SymbolPath getSymbolPathFromMangledTypeName(String mangledString) {
// 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
// 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
// return MDMangUtils.getSimpleSymbolPath(mdDataType);
}
Expand All @@ -110,7 +134,7 @@ private SymbolPath getSymbolPathFromMangledTypeName(String mangledString) {
// 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 is checked first).
Msg.info(this,
Msg.info(AbstractComplexTypeApplier.class,
"PDB issue dmangling type name: " + e.getMessage() + " for : " + mangledString);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down Expand Up @@ -82,19 +82,19 @@ private static ComboType createComposite(DefaultPdbApplicator myApplicator, Stri
myApplicator.predefineClass(fixedSymbolPath);
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
myClassType.setClass();
}
else if (compositeMsType instanceof AbstractStructureMsType) {
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), size,
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
myClassType.setStruct();
}
else if (compositeMsType instanceof AbstractUnionMsType) {
myComposite = new UnionDataType(categoryPath, fixedSymbolPath.getName(),
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType = new CppCompositeType(fixedSymbolPath, myComposite, mangledName);
myClassType.setUnion();
}
else { // InterfaceMsType
Expand Down Expand Up @@ -142,6 +142,16 @@ private void applyBasic(ComboType combo, AbstractCompositeMsType type,
boolean isClass = (type instanceof AbstractClassMsType);
int size = getSizeInt(type);
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<>();
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
addMembers(composite, classType, lists.nonstaticMembers(), type, myMembers);
Expand All @@ -159,6 +169,10 @@ private void applyCpp(ComboType combo, AbstractCompositeMsType type,
Composite composite = combo.dt();
CppCompositeType classType = combo.ct();
clearComponents(composite);
if (!lists.bases().isEmpty() || !lists.methods().isEmpty()) {
SymbolPath sp = classType.getSymbolPath();
applicator.predefineClass(sp);
}
List<DefaultPdbUniversalMember> myMembers = new ArrayList<>();
addClassTypeBaseClasses(composite, classType, lists.bases(), type);
addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.apache.commons.lang3.StringUtils;

import ghidra.app.util.SymbolPath;
import ghidra.app.util.bin.format.pdb.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
Expand Down Expand Up @@ -48,6 +49,7 @@ public class CppCompositeType {
private String className; // String for now.
private String mangledName;
private int size;
private SymbolPath symbolPath;
private Composite composite;
private CategoryPath categoryPath;

Expand Down Expand Up @@ -78,7 +80,8 @@ static CategoryPath createDirectCategoryPath(CppCompositeType cppType) {
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");
syntacticBaseClasses = new ArrayList<>();
layoutBaseClasses = new ArrayList<>();
Expand All @@ -90,46 +93,49 @@ public CppCompositeType(Composite composite, String mangledName) {

isFinal = false;
type = Type.UNKNOWN;
this.symbolPath = symbolPath;
this.composite = composite;
placeholderVirtualBaseTables = new HashMap<>();
categoryPath = new CategoryPath(composite.getCategoryPath(), composite.getName());
this.mangledName = mangledName;
}

public static CppClassType createCppClassType(Composite composite, String mangledName) {
return new CppClassType(composite, mangledName);
public static CppClassType createCppClassType(SymbolPath symbolPath, Composite composite,
String mangledName) {
return new CppClassType(symbolPath, composite, mangledName);
}

public static CppClassType createCppClassType(Composite composite, String name,
String mangledName, int size) {
CppClassType cppType = new CppClassType(composite, mangledName);
public static CppClassType createCppClassType(SymbolPath symbolPath, Composite composite,
String name, String mangledName, int size) {
CppClassType cppType = new CppClassType(symbolPath, composite, mangledName);
cppType.setName(name);
cppType.setSize(size);
return cppType;
}

public static CppStructType createCppStructType(Composite composite, String mangledName) {
return new CppStructType(composite, mangledName);
public static CppStructType createCppStructType(SymbolPath symbolPath, Composite composite,
String mangledName) {
return new CppStructType(symbolPath, composite, mangledName);
}

public static CppStructType createCppStructType(Composite composite, String name,
String mangledName, int size) {
CppStructType cppType = new CppStructType(composite, mangledName);
public static CppStructType createCppStructType(SymbolPath symbolPath, Composite composite,
String name, String mangledName, int size) {
CppStructType cppType = new CppStructType(symbolPath, composite, mangledName);
cppType.setName(name);
cppType.setSize(size);
return cppType;
}

private static class CppClassType extends CppCompositeType {
private CppClassType(Composite composite, String mangledName) {
super(composite, mangledName);
private CppClassType(SymbolPath symbolPath, Composite composite, String mangledName) {
super(symbolPath, composite, mangledName);
setClass();
}
}

private static class CppStructType extends CppCompositeType {
private CppStructType(Composite composite, String mangledName) {
super(composite, mangledName);
private CppStructType(SymbolPath symbolPath, Composite composite, String mangledName) {
super(symbolPath, composite, mangledName);
setStruct();
}
}
Expand Down Expand Up @@ -186,6 +192,10 @@ private List<LayoutBaseClass> getLayoutBaseClasses() {
return layoutBaseClasses;
}

SymbolPath getSymbolPath() {
return symbolPath;
}

Composite getComposite() {
return composite;
}
Expand Down
Loading

0 comments on commit c26a290

Please sign in to comment.