mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4825 - Gnu Demangler - Update parser for some special global constructor/destructor symbols
This commit is contained in:
parent
95573ed834
commit
518860f0d6
3 changed files with 143 additions and 28 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.
|
||||||
|
@ -45,38 +45,38 @@ public abstract class DemangledObject implements Demangled {
|
||||||
The following names probably need to be refactored. Until then, this is how the following
|
The following names probably need to be refactored. Until then, this is how the following
|
||||||
fields are used.
|
fields are used.
|
||||||
|
|
||||||
mangled -
|
mangled -
|
||||||
Source: The original mangled string as seen in the program
|
Source: The original mangled string as seen in the program
|
||||||
Usage: Can be used to see if a program symbol has already been demangled
|
Usage: Can be used to see if a program symbol has already been demangled
|
||||||
|
|
||||||
originalDemangled -
|
originalDemangled -
|
||||||
Source: The raw demangled string returned from the demangler
|
Source: The raw demangled string returned from the demangler
|
||||||
Usage: for display
|
Usage: for display
|
||||||
|
|
||||||
demangledName -
|
demangledName -
|
||||||
Source: The name as created by the parser which may transform or even replace the
|
Source: The name as created by the parser which may transform or even replace the
|
||||||
string returned from the demangler
|
string returned from the demangler
|
||||||
Usage: for display
|
Usage: for display
|
||||||
|
|
||||||
name -
|
name -
|
||||||
Source: This is derived from the 'demangledName' This is updated to be suitable
|
Source: This is derived from the 'demangledName' This is updated to be suitable
|
||||||
for use as a symbol name. This may be null while building, but is
|
for use as a symbol name. This may be null while building, but is
|
||||||
expected to be non-null when applyTo() is called
|
expected to be non-null when applyTo() is called
|
||||||
Usage: The name that will be applied when applyTo() is called.
|
Usage: The name that will be applied when applyTo() is called.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Future: These variables should be refactored and renamed to be clearer and more cohesive,
|
Future: These variables should be refactored and renamed to be clearer and more cohesive,
|
||||||
something like:
|
something like:
|
||||||
|
|
||||||
mangled
|
mangled
|
||||||
rawDemangled
|
rawDemangled
|
||||||
escapedDemangled
|
escapedDemangled
|
||||||
symbolName
|
symbolName
|
||||||
|
|
||||||
*/
|
*/
|
||||||
protected final String mangled; // original mangled string
|
protected final String mangled; // original mangled string
|
||||||
protected final String originalDemangled; // raw demangled string
|
protected String originalDemangled; // raw demangled string
|
||||||
private String demangledName; // updated demangled string
|
private String demangledName; // updated demangled string
|
||||||
private String name; // version of demangled name suitable for symbols
|
private String name; // version of demangled name suitable for symbols
|
||||||
|
|
||||||
|
@ -240,6 +240,17 @@ public abstract class DemangledObject implements Demangled {
|
||||||
return originalDemangled;
|
return originalDemangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the original demangled string. This is useful for clients that reuse constructed
|
||||||
|
* demangled objects for special case constructs.
|
||||||
|
* <p>
|
||||||
|
* Note: this method is not on the interface
|
||||||
|
* @param originalDemangled the new original demangled string
|
||||||
|
*/
|
||||||
|
public void setOriginalDemangled(String originalDemangled) {
|
||||||
|
this.originalDemangled = originalDemangled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Demangled getNamespace() {
|
public Demangled getNamespace() {
|
||||||
return namespace;
|
return namespace;
|
||||||
|
@ -364,7 +375,7 @@ public abstract class DemangledObject implements Demangled {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply this demangled object detail to the specified program.
|
* Apply this demangled object detail to the specified program.
|
||||||
* <br>
|
* <br>
|
||||||
* NOTE: An open Program transaction must be established prior to invoking this method.
|
* NOTE: An open Program transaction must be established prior to invoking this method.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -271,6 +271,19 @@ public class GnuDemanglerParser {
|
||||||
private static final Pattern DESCRIPTIVE_PREFIX_PATTERN =
|
private static final Pattern DESCRIPTIVE_PREFIX_PATTERN =
|
||||||
Pattern.compile("((.+ )(for|to) )(.+)");
|
Pattern.compile("((.+ )(for|to) )(.+)");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sample: global constructors keyed to cyg_libc_stdio_altout
|
||||||
|
*
|
||||||
|
* Pattern: global (constructors|destructors) keyed to text
|
||||||
|
*
|
||||||
|
* Parts:
|
||||||
|
* -global (constructors|destructors) keyed to (group 1)
|
||||||
|
* -text (group 3)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final Pattern GLOBAL_CTOR_DTOR_FOR_PATTERN =
|
||||||
|
Pattern.compile("(global (constructors|destructors) keyed to )(.+)");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The c 'decltype' keyword pattern
|
* The c 'decltype' keyword pattern
|
||||||
*/
|
*/
|
||||||
|
@ -446,6 +459,13 @@ public class GnuDemanglerParser {
|
||||||
return new ArrayHandler(demangled, prefix, type);
|
return new ArrayHandler(demangled, prefix, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matcher globalCtorMatcher = GLOBAL_CTOR_DTOR_FOR_PATTERN.matcher(demangled);
|
||||||
|
if (globalCtorMatcher.matches()) {
|
||||||
|
prefix = globalCtorMatcher.group(1);
|
||||||
|
type = globalCtorMatcher.group(3);
|
||||||
|
return new GlobalCtorDtorHandler(demangled, prefix, type);
|
||||||
|
}
|
||||||
|
|
||||||
return new ItemInNamespaceHandler(demangled, prefix, type);
|
return new ItemInNamespaceHandler(demangled, prefix, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1524,13 +1544,11 @@ public class GnuDemanglerParser {
|
||||||
|
|
||||||
ItemInNamespaceHandler(String demangled) {
|
ItemInNamespaceHandler(String demangled) {
|
||||||
super(demangled);
|
super(demangled);
|
||||||
this.demangled = demangled;
|
|
||||||
this.type = demangled;
|
this.type = demangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemInNamespaceHandler(String demangled, String prefix, String item) {
|
ItemInNamespaceHandler(String demangled, String prefix, String item) {
|
||||||
super(demangled);
|
super(demangled);
|
||||||
this.demangled = demangled;
|
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.type = item;
|
this.type = item;
|
||||||
}
|
}
|
||||||
|
@ -1542,6 +1560,40 @@ public class GnuDemanglerParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GlobalCtorDtorHandler extends SpecialPrefixHandler {
|
||||||
|
|
||||||
|
GlobalCtorDtorHandler(String demangled, String prefix, String item) {
|
||||||
|
super(demangled);
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.type = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
DemangledObject doBuild(Demangled namespace) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Since we are for constructors/destructors, assume each item is function
|
||||||
|
//
|
||||||
|
String functionName = type;
|
||||||
|
if (!functionName.contains("(")) {
|
||||||
|
// add parens so the type will be parsed as a function
|
||||||
|
functionName += "()";
|
||||||
|
}
|
||||||
|
|
||||||
|
DemangledObject demangledFunction = parseFunctionOrVariable(functionName);
|
||||||
|
demangledFunction.setOriginalDemangled(demangled);
|
||||||
|
|
||||||
|
// e.g., global.constructors.keyed.to.functionName
|
||||||
|
String parsedFunctionName = demangledFunction.getName();
|
||||||
|
String prefixNoSpaces = prefix.replaceAll("\s", "\\.");
|
||||||
|
String fullName = prefixNoSpaces + parsedFunctionName;
|
||||||
|
|
||||||
|
demangledFunction.setName(fullName);
|
||||||
|
demangledFunction.setBackupPlateComment(demangled);
|
||||||
|
return demangledFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ArrayHandler extends SpecialPrefixHandler {
|
private class ArrayHandler extends SpecialPrefixHandler {
|
||||||
|
|
||||||
private String arrayType;
|
private String arrayType;
|
||||||
|
@ -1576,9 +1628,8 @@ public class GnuDemanglerParser {
|
||||||
//
|
//
|
||||||
if ("char".equals(arrayType) && type.contains("StringLiteral")) {
|
if ("char".equals(arrayType) && type.contains("StringLiteral")) {
|
||||||
// treat a char[] as a string
|
// treat a char[] as a string
|
||||||
DemangledString ds =
|
DemangledString ds = new DemangledString(variable.getMangledString(), demangled,
|
||||||
new DemangledString(variable.getMangledString(), demangled, type, type,
|
type, type, -1 /*unknown length*/, false);
|
||||||
-1 /*unknown length*/, false);
|
|
||||||
ds.setSpecialPrefix(prefix);
|
ds.setSpecialPrefix(prefix);
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -1025,7 +1025,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typeinfo for
|
typeinfo for
|
||||||
std::__ndk1::__function::__func<
|
std::__ndk1::__function::__func<
|
||||||
dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1},
|
dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1},
|
||||||
std::__ndk1::allocator<dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1}>,
|
std::__ndk1::allocator<dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1}>,
|
||||||
|
@ -2216,8 +2216,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
assertName(object,
|
assertName(object,
|
||||||
"__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>",
|
"__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>",
|
||||||
"std",
|
"std", "__1");
|
||||||
"__1");
|
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
@ -2225,6 +2224,60 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGlobalConstructor() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// mangled: _GLOBAL__I_cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
// demangled: global constructors keyed to cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
// updated name: global.constructors.keyed.to.cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
|
||||||
|
String mangled = "_GLOBAL__I_cyg_libc_stdio_altout";
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
assertEquals("global constructors keyed to cyg_libc_stdio_altout",
|
||||||
|
object.getOriginalDemangled());
|
||||||
|
assertName(object, "global.constructors.keyed.to.cyg_libc_stdio_altout");
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals("undefined global.constructors.keyed.to.cyg_libc_stdio_altout(void)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGlobalDestructor() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// mangled: _GLOBAL__D_cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
// demangled: global destructors keyed to cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
// updated name: global.destructors.keyed.to.cyg_libc_stdio_altout
|
||||||
|
//
|
||||||
|
|
||||||
|
String mangled = "_GLOBAL__D_cyg_libc_stdio_altout";
|
||||||
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
DemangledObject object = parser.parse(mangled, demangled);
|
||||||
|
assertNotNull(object);
|
||||||
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
|
assertEquals("global destructors keyed to cyg_libc_stdio_altout",
|
||||||
|
object.getOriginalDemangled());
|
||||||
|
assertName(object, "global.destructors.keyed.to.cyg_libc_stdio_altout");
|
||||||
|
|
||||||
|
String signature = object.getSignature(false);
|
||||||
|
assertEquals("undefined global.destructors.keyed.to.cyg_libc_stdio_altout(void)",
|
||||||
|
signature);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertType(Demangled o, Class<?> c) {
|
private void assertType(Demangled o, Class<?> c) {
|
||||||
assertTrue("Wrong demangled type. \nExpected " + c + "; \nfound " + o.getClass(),
|
assertTrue("Wrong demangled type. \nExpected " + c + "; \nfound " + o.getClass(),
|
||||||
c.isInstance(o));
|
c.isInstance(o));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue