mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-25 16:45:02 +08:00
Merge remote-tracking branch 'origin/GP-6394-dragonmacher-gnu-demangler-function-qualifiers'
This commit is contained in:
@@ -41,7 +41,9 @@ Update January 2026
|
||||
|
||||
Fixed a bug seen in older mangled symbols that use an 'F' character for functions. We added a
|
||||
function to handle this case, isQualifiersAndFunc(). This function called from inside the
|
||||
demangle_signature() function.
|
||||
demangle_signature() function. The output also makes use of the added TYPE_QUAL_STATIC define.
|
||||
|
||||
|
||||
|
||||
|
||||
cp-demangle.c *
|
||||
|
||||
@@ -463,6 +463,7 @@ static int snarf_numeric_literal (const char **, string *);
|
||||
#define TYPE_QUAL_CONST 0x1
|
||||
#define TYPE_QUAL_VOLATILE 0x2
|
||||
#define TYPE_QUAL_RESTRICT 0x4
|
||||
#define TYPE_QUAL_STATIC 0x8
|
||||
|
||||
static int code_for_qualifier (int);
|
||||
|
||||
@@ -573,6 +574,9 @@ code_for_qualifier (int c)
|
||||
case 'C':
|
||||
return TYPE_QUAL_CONST;
|
||||
|
||||
case 'S':
|
||||
return TYPE_QUAL_STATIC;
|
||||
|
||||
case 'V':
|
||||
return TYPE_QUAL_VOLATILE;
|
||||
|
||||
@@ -601,22 +605,34 @@ qualifier_string (int type_quals)
|
||||
case TYPE_QUAL_CONST:
|
||||
return "const";
|
||||
|
||||
case TYPE_QUAL_STATIC:
|
||||
return "static";
|
||||
|
||||
case TYPE_QUAL_VOLATILE:
|
||||
return "volatile";
|
||||
|
||||
case TYPE_QUAL_RESTRICT:
|
||||
return "__restrict";
|
||||
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_STATIC:
|
||||
return "const static";
|
||||
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
|
||||
return "const volatile";
|
||||
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
|
||||
return "const __restrict";
|
||||
|
||||
case TYPE_QUAL_STATIC | TYPE_QUAL_VOLATILE:
|
||||
return "static volatile";
|
||||
|
||||
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
|
||||
return "volatile __restrict";
|
||||
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_STATIC | TYPE_QUAL_VOLATILE:
|
||||
return "static const volatile";
|
||||
|
||||
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
|
||||
return "const volatile __restrict";
|
||||
|
||||
default:
|
||||
@@ -819,33 +835,33 @@ cplus_demangle_name_to_style (const char *name)
|
||||
return unknown_demangling;
|
||||
}
|
||||
|
||||
|
||||
/* Scans to see if mangled is a set of optional qualifiers and a function. */
|
||||
|
||||
static int /* bool */
|
||||
isQualifiersAndFunc(const char *mangled)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
while (1)
|
||||
{
|
||||
|
||||
switch (mangled[i++])
|
||||
{
|
||||
case 'C':
|
||||
case 'V':
|
||||
case 'u':
|
||||
/*qualifier*/
|
||||
break;
|
||||
case 'F':
|
||||
/* function */
|
||||
return 1;
|
||||
default:
|
||||
/* anything else is not a qualifier or function */
|
||||
return 0;
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'V':
|
||||
case 'u':
|
||||
/* qualifier */
|
||||
break;
|
||||
case 'F':
|
||||
/* function */
|
||||
return 1;
|
||||
default:
|
||||
/* anything else is not a qualifier or function */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* char *cplus_demangle (const char *mangled, int options)
|
||||
|
||||
If MANGLED is a mangled function name produced by GNU C++, then
|
||||
|
||||
+40
@@ -198,6 +198,46 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertEquals("undefined Foo::foo(unsigned char,unsigned char)", object.getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLegacy_DemangedFunctionCharacter_Qualifiers() throws Exception {
|
||||
|
||||
// This is only supported in the older v24 demangler. The 'F' character was not being
|
||||
// correctly demangled along with some qualifier characters. The native demangler was
|
||||
// updated to fix this.
|
||||
process = GnuDemanglerNativeProcess
|
||||
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||
|
||||
//@formatter:off
|
||||
assertLegacyDemangled("foo__03FooCF",
|
||||
"Foo::foo(void) const",
|
||||
"undefined Foo::foo(void)");
|
||||
|
||||
assertLegacyDemangled("foo__03FooSF",
|
||||
"Foo::foo(void) static",
|
||||
"undefined Foo::foo(void)");
|
||||
|
||||
assertLegacyDemangled("foo__03FooSFUcT1",
|
||||
"Foo::foo(unsigned char, unsigned char) static",
|
||||
"undefined Foo::foo(unsigned char,unsigned char)");
|
||||
|
||||
assertLegacyDemangled("foo__03FooSCFUcT1",
|
||||
"Foo::foo(unsigned char, unsigned char) static const",
|
||||
"undefined Foo::foo(unsigned char,unsigned char)");
|
||||
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
private void assertLegacyDemangled(String mangled, String demangledExpected,
|
||||
String signatureExpected) throws Exception {
|
||||
|
||||
String demangledActual = process.demangle(mangled);
|
||||
assertEquals(demangledExpected, demangledActual);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangledExpected);
|
||||
assertType(object, DemangledFunction.class);
|
||||
assertEquals(signatureExpected, object.getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplates_TemplatedType() throws Exception {
|
||||
String mangled =
|
||||
|
||||
Reference in New Issue
Block a user