mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-272 - Gnu Demangler - fixed demangler failure on variable name when
the parent namespace is an operator function
This commit is contained in:
@@ -25,6 +25,7 @@ import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utility.function.Dummy;
|
||||
|
||||
public class DemangledThunk extends DemangledObject {
|
||||
|
||||
@@ -176,8 +177,7 @@ public class DemangledThunk extends DemangledObject {
|
||||
}
|
||||
|
||||
Symbol s = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program,
|
||||
mangled, err -> Msg.warn(this, err));
|
||||
|
||||
mangled, Dummy.consumer());
|
||||
if (s == null) {
|
||||
Address thunkedAddr =
|
||||
CreateThunkFunctionCmd.getThunkedAddr(program, thunkAddress, false);
|
||||
@@ -185,11 +185,13 @@ public class DemangledThunk extends DemangledObject {
|
||||
s = program.getSymbolTable().getPrimarySymbol(thunkedAddr);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == null || !block.contains(s.getAddress())) {
|
||||
Msg.warn(this, "Unable to find or create thunk for " + mangled + " at " + thunkAddress);
|
||||
return null;
|
||||
}
|
||||
Address addr = s.getAddress();
|
||||
|
||||
Address addr = s.getAddress();
|
||||
DemanglerOptions subOptions = new DemanglerOptions(options);
|
||||
subOptions.setApplySignature(true);
|
||||
|
||||
|
||||
@@ -1004,6 +1004,81 @@ public class GnuDemanglerParser {
|
||||
return findBalancedStart(string, templateEnd, '<', '>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks backward from the given start position to find the next namespace separator. This
|
||||
* allows clients to determine if a given position is inside of a namespace.
|
||||
*
|
||||
* @param text the text to search
|
||||
* @param start the start position
|
||||
* @param stop the stop position
|
||||
* @return the start index of the namespace entry containing the current {@code start}
|
||||
* index; -1 if no namespace start is found
|
||||
*/
|
||||
private int findNamespaceStart(String text, int start, int stop) {
|
||||
|
||||
if (!text.contains(Namespace.DELIMITER)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nsCount = 0;
|
||||
int parenDepth = 0;
|
||||
int templateDepth = 0;
|
||||
int braceDepth = 0;
|
||||
boolean isNested = false;
|
||||
|
||||
for (int i = start; i >= stop; i--) {
|
||||
|
||||
char c = text.charAt(i);
|
||||
switch (c) {
|
||||
case ':': {
|
||||
nsCount++;
|
||||
if (nsCount == 2) {
|
||||
if (!isNested) {
|
||||
return i + 2;
|
||||
}
|
||||
nsCount = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ' ': {
|
||||
if (!isNested) {
|
||||
return -1; // a space implies a return type when not nested
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
isNested = --parenDepth > 0 || templateDepth > 0 || braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
case ')': {
|
||||
isNested = ++parenDepth > 0 || templateDepth > 0 || braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
case '<': {
|
||||
isNested = parenDepth > 0 || --templateDepth > 0 || braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
case '>': {
|
||||
isNested = parenDepth > 0 || ++templateDepth > 0 || braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
case '{': {
|
||||
isNested = parenDepth > 0 || templateDepth > 0 || --braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
case '}': {
|
||||
isNested = parenDepth > 0 || templateDepth > 0 || ++braceDepth > 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private DemangledDataType createTypeInNamespace(String name) {
|
||||
List<String> names = SymbolPathParser.parse(name, false);
|
||||
DemangledType namespace = null;
|
||||
@@ -1342,7 +1417,17 @@ public class GnuDemanglerParser {
|
||||
@Override
|
||||
boolean matches(String text) {
|
||||
matcher = OVERLOAD_OPERATOR_NAME_PATTERN.matcher(text);
|
||||
return matcher.matches();
|
||||
if (!matcher.matches()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int operatorStart = matcher.start(2);
|
||||
int leafStart = findNamespaceStart(demangled, text.length() - 1, operatorStart);
|
||||
if (leafStart > operatorStart) {
|
||||
return false; // operator is inside of a non-leaf namespace entry
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -842,6 +842,32 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertEquals("Magick::Coordinate const &", parameters.get(1).getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperatorAsNamespace() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: __ZN3WTF15__visitor_tableINS_7VisitorIZZN7WebCore12SubtleCrypto11generateKeyERN3JSC9ExecStateEONS_7VariantIJNS4_6StrongINS4_8JSObjectEEENS_6StringEEEEbONS_6VectorINS2_14CryptoKeyUsageELm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEEONS_3RefINS2_15DeferredPromiseENS_13DumbPtrTraitsISL_EEEEEN4$_10clEONS7_IJNS_6RefPtrINS2_9CryptoKeyENSM_ISS_EEEENS2_13CryptoKeyPairEEEEEUlRSU_E_JZZNS3_11generateKeyES6_SD_bSJ_SP_ENSQ_clESX_EUlRSV_E_EEEJSU_SV_EE12__trampolineE
|
||||
//
|
||||
// Demangled: WTF::__visitor_table<WTF::Visitor<WebCore::SubtleCrypto::generateKey(JSC::ExecState&, WTF::Variant<JSC::Strong<JSC::JSObject>, WTF::String>&&, bool, WTF::Vector<WebCore::CryptoKeyUsage, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&, WTF::Ref<WebCore::DeferredPromise, WTF::DumbPtrTraits<WebCore::DeferredPromise> >&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>&&)::{lambda(WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >&)#1}, WebCore::SubtleCrypto::generateKey(JSC::ExecState&, WTF::Variant<JSC::Strong<JSC::JSObject>, WTF::String>&&, bool, WTF::Vector<WebCore::CryptoKeyUsage, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&, WTF::Ref<WebCore::DeferredPromise, WTF::DumbPtrTraits<WebCore::DeferredPromise> >&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>&&)::{lambda(WebCore::CryptoKeyPair&)#1}>, WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>::__trampoline
|
||||
//
|
||||
|
||||
DemangledObject object = parser.parse(
|
||||
"__ZN3WTF15__visitor_tableINS_7VisitorIZZN7WebCore12SubtleCrypto11generateKeyERN3JSC9ExecStateEONS_7VariantIJNS4_6StrongINS4_8JSObjectEEENS_6StringEEEEbONS_6VectorINS2_14CryptoKeyUsageELm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEEONS_3RefINS2_15DeferredPromiseENS_13DumbPtrTraitsISL_EEEEEN4$_10clEONS7_IJNS_6RefPtrINS2_9CryptoKeyENSM_ISS_EEEENS2_13CryptoKeyPairEEEEEUlRSU_E_JZZNS3_11generateKeyES6_SD_bSJ_SP_ENSQ_clESX_EUlRSV_E_EEEJSU_SV_EE12__trampolineE",
|
||||
"WTF::__visitor_table<WTF::Visitor<WebCore::SubtleCrypto::generateKey(JSC::ExecState&, WTF::Variant<JSC::Strong<JSC::JSObject>, WTF::String>&&, bool, WTF::Vector<WebCore::CryptoKeyUsage, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&, WTF::Ref<WebCore::DeferredPromise, WTF::DumbPtrTraits<WebCore::DeferredPromise> >&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>&&)::{lambda(WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >&)#1}, WebCore::SubtleCrypto::generateKey(JSC::ExecState&, WTF::Variant<JSC::Strong<JSC::JSObject>, WTF::String>&&, bool, WTF::Vector<WebCore::CryptoKeyUsage, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&&, WTF::Ref<WebCore::DeferredPromise, WTF::DumbPtrTraits<WebCore::DeferredPromise> >&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>&&)::{lambda(WebCore::CryptoKeyPair&)#1}>, WTF::RefPtr<WebCore::CryptoKey, WTF::DumbPtrTraits<WebCore::CryptoKey> >, WebCore::CryptoKeyPair>::__trampoline");
|
||||
|
||||
assertNotNull(object);
|
||||
assertType(object, DemangledVariable.class);
|
||||
|
||||
String name = "__trampoline";
|
||||
assertName(object, name, "WTF",
|
||||
"__visitor_table<WTF::Visitor<WebCore::SubtleCrypto::generateKey(JSC::ExecState&,WTF::Variant<JSC::Strong<JSC::JSObject>,WTF::String>&&,bool,WTF::Vector<WebCore::CryptoKeyUsage,0ul,WTF::CrashOnOverflow,16ul,WTF::FastMalloc>&&,WTF::Ref<WebCore::DeferredPromise,WTF::DumbPtrTraits<WebCore::DeferredPromise>>&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>&&)::{lambda(WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>&)#1},WebCore::SubtleCrypto::generateKey(JSC::ExecState&,WTF::Variant<JSC::Strong<JSC::JSObject>,WTF::String>&&,bool,WTF::Vector<WebCore::CryptoKeyUsage,0ul,WTF::CrashOnOverflow,16ul,WTF::FastMalloc>&&,WTF::Ref<WebCore::DeferredPromise,WTF::DumbPtrTraits<WebCore::DeferredPromise>>&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>&&)::{lambda(WebCore::CryptoKeyPair&)#1}>,WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"WTF::__visitor_table<WTF::Visitor<WebCore::SubtleCrypto::generateKey(JSC::ExecState&,WTF::Variant<JSC::Strong<JSC::JSObject>,WTF::String>&&,bool,WTF::Vector<WebCore::CryptoKeyUsage,0ul,WTF::CrashOnOverflow,16ul,WTF::FastMalloc>&&,WTF::Ref<WebCore::DeferredPromise,WTF::DumbPtrTraits<WebCore::DeferredPromise>>&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>&&)::{lambda(WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>&)#1},WebCore::SubtleCrypto::generateKey(JSC::ExecState&,WTF::Variant<JSC::Strong<JSC::JSObject>,WTF::String>&&,bool,WTF::Vector<WebCore::CryptoKeyUsage,0ul,WTF::CrashOnOverflow,16ul,WTF::FastMalloc>&&,WTF::Ref<WebCore::DeferredPromise,WTF::DumbPtrTraits<WebCore::DeferredPromise>>&&)::$_10::operator()(WTF::Variant<WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>&&)::{lambda(WebCore::CryptoKeyPair&)#1}>,WTF::RefPtr<WebCore::CryptoKey,WTF::DumbPtrTraits<WebCore::CryptoKey>>,WebCore::CryptoKeyPair>::__trampoline",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverloadedShiftOperatorTemplated_RightShift() {
|
||||
parser = new GnuDemanglerParser();
|
||||
|
||||
Reference in New Issue
Block a user