mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-08-08 07:40:39 -09:00
GP-6394 - Gnu Demangler - Added legacy support for the static qualifier
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
|
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
|
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 *
|
cp-demangle.c *
|
||||||
|
|||||||
@@ -463,6 +463,7 @@ static int snarf_numeric_literal (const char **, string *);
|
|||||||
#define TYPE_QUAL_CONST 0x1
|
#define TYPE_QUAL_CONST 0x1
|
||||||
#define TYPE_QUAL_VOLATILE 0x2
|
#define TYPE_QUAL_VOLATILE 0x2
|
||||||
#define TYPE_QUAL_RESTRICT 0x4
|
#define TYPE_QUAL_RESTRICT 0x4
|
||||||
|
#define TYPE_QUAL_STATIC 0x8
|
||||||
|
|
||||||
static int code_for_qualifier (int);
|
static int code_for_qualifier (int);
|
||||||
|
|
||||||
@@ -573,6 +574,9 @@ code_for_qualifier (int c)
|
|||||||
case 'C':
|
case 'C':
|
||||||
return TYPE_QUAL_CONST;
|
return TYPE_QUAL_CONST;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
return TYPE_QUAL_STATIC;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
return TYPE_QUAL_VOLATILE;
|
return TYPE_QUAL_VOLATILE;
|
||||||
|
|
||||||
@@ -601,22 +605,34 @@ qualifier_string (int type_quals)
|
|||||||
case TYPE_QUAL_CONST:
|
case TYPE_QUAL_CONST:
|
||||||
return "const";
|
return "const";
|
||||||
|
|
||||||
|
case TYPE_QUAL_STATIC:
|
||||||
|
return "static";
|
||||||
|
|
||||||
case TYPE_QUAL_VOLATILE:
|
case TYPE_QUAL_VOLATILE:
|
||||||
return "volatile";
|
return "volatile";
|
||||||
|
|
||||||
case TYPE_QUAL_RESTRICT:
|
case TYPE_QUAL_RESTRICT:
|
||||||
return "__restrict";
|
return "__restrict";
|
||||||
|
|
||||||
|
case TYPE_QUAL_CONST | TYPE_QUAL_STATIC:
|
||||||
|
return "const static";
|
||||||
|
|
||||||
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
|
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
|
||||||
return "const volatile";
|
return "const volatile";
|
||||||
|
|
||||||
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
|
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
|
||||||
return "const __restrict";
|
return "const __restrict";
|
||||||
|
|
||||||
|
case TYPE_QUAL_STATIC | TYPE_QUAL_VOLATILE:
|
||||||
|
return "static volatile";
|
||||||
|
|
||||||
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
|
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
|
||||||
return "volatile __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";
|
return "const volatile __restrict";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -819,33 +835,33 @@ cplus_demangle_name_to_style (const char *name)
|
|||||||
return unknown_demangling;
|
return unknown_demangling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Scans to see if mangled is a set of optional qualifiers and a function. */
|
/* Scans to see if mangled is a set of optional qualifiers and a function. */
|
||||||
|
|
||||||
static int /* bool */
|
static int /* bool */
|
||||||
isQualifiersAndFunc(const char *mangled)
|
isQualifiersAndFunc(const char *mangled)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (mangled[i++])
|
switch (mangled[i++])
|
||||||
{
|
{
|
||||||
case 'C':
|
case 'C':
|
||||||
case 'V':
|
case 'S':
|
||||||
case 'u':
|
case 'V':
|
||||||
/*qualifier*/
|
case 'u':
|
||||||
break;
|
/* qualifier */
|
||||||
case 'F':
|
break;
|
||||||
/* function */
|
case 'F':
|
||||||
return 1;
|
/* function */
|
||||||
default:
|
return 1;
|
||||||
/* anything else is not a qualifier or function */
|
default:
|
||||||
return 0;
|
/* anything else is not a qualifier or function */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* char *cplus_demangle (const char *mangled, int options)
|
/* char *cplus_demangle (const char *mangled, int options)
|
||||||
|
|
||||||
If MANGLED is a mangled function name produced by GNU C++, then
|
If MANGLED is a mangled function name produced by GNU C++, then
|
||||||
|
|||||||
@@ -198,6 +198,46 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||||||
assertEquals("undefined Foo::foo(unsigned char,unsigned char)", object.getSignature());
|
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
|
@Test
|
||||||
public void testTemplates_TemplatedType() throws Exception {
|
public void testTemplates_TemplatedType() throws Exception {
|
||||||
String mangled =
|
String mangled =
|
||||||
|
|||||||
Reference in New Issue
Block a user