mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 15:40:14 +00:00
Gnu Demangler - Added support for demangler simplifications
This commit is contained in:
parent
2760eebc92
commit
9018ece7c0
@ -428,6 +428,19 @@
|
||||
Only demangle symbols that follow known compiler mangling patterns.
|
||||
Leaving this option off may cause non-mangled symbols to get demangled.
|
||||
</TD>
|
||||
</TR><TR>
|
||||
<TD>Use Standard Text Replacements
|
||||
</TD>
|
||||
<TD>
|
||||
Use text simplifications in demangled output, for example to use standard c++
|
||||
typedefs. Using this option will produce shorter demangled output in some cases.
|
||||
<P>
|
||||
The simplifications are defined in
|
||||
<CODE>Ghidra/Features/GnuDemangler/data/default.gnu.demangler.replacements.txt</CODE>
|
||||
This file can be edited. Also new files can be added with more simplifications.
|
||||
Each new file must end with <CODE>.gnu.demangler.replacements.txt</CODE> and must
|
||||
reside inside of a module's <CODE>data</CODE> directory.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</P>
|
||||
|
@ -1,3 +1,4 @@
|
||||
##VERSION: 2.0
|
||||
Module.manifest||GHIDRA||||END|
|
||||
data/default.gnu.demangler.replacements.txt||GHIDRA||||END|
|
||||
src/test/resources/ghidra/app/util/demangler/gnu_mangled_names.txt||GHIDRA||reviewed||END|
|
||||
|
@ -0,0 +1,205 @@
|
||||
//
|
||||
// This file contains a list of search and replace text pairs.
|
||||
// Each line is one specialaization name to full library definition.
|
||||
//
|
||||
// This list is based on content found in:
|
||||
// https://en.cppreference.com/w/cpp/string
|
||||
// https://en.cppreference.com/w/cpp/io
|
||||
// https://en.cppreference.com/w/cpp/regex/basic_regex
|
||||
//
|
||||
// The list has been tested against a small selection of known samples, but since not all of these entries have been tested, they have been built based on observed patterns and are quite speculative.
|
||||
|
||||
//
|
||||
// Users can edit this file or add content to new files in an installation.
|
||||
// New files must end with '.gnu.demangler.replacements.txt' and must be placed inside of a module's 'data' directory.
|
||||
// When each replacement file is loaded, the will be sorted by name.
|
||||
// All replacements will be processed in the order the files are loaded, in the order listed in each file.
|
||||
//
|
||||
// The replacements will be executed in the order they are listed in this file.
|
||||
//
|
||||
// Each line must be of the format: replacement text | whitespace | search text
|
||||
// The replacement text may be two literal double quote characters (""), which signals to replace the match with the empty string.
|
||||
// Any line can be disabled by deleting or prepending a double forward slash.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// General removal statements
|
||||
//
|
||||
|
||||
// current tests show this is a non-leading mangled namespace placeholder
|
||||
"" ::__1
|
||||
|
||||
// current tests show this is a non-leading mangled namespace placeholder
|
||||
"" ::__cxx11
|
||||
|
||||
// current tests show this is only in the leading mangled namespace position
|
||||
"" __gnu_cxx::
|
||||
|
||||
|
||||
// speculative: pool_allocator has been spotted in some binaries; replace first so the cases below will match
|
||||
std::allocator<char> pool_allocator<char>
|
||||
|
||||
|
||||
//
|
||||
// Standard c++ library typedefs
|
||||
//
|
||||
std::string std::basic_string<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wstring std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
std::u8string std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t> >
|
||||
std::u16string std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t> >
|
||||
std::u32string std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t> >
|
||||
|
||||
std::string_view std::basic_string_view<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wstring_view std::basic_string_view<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
std::u8string_view std::basic_string<char8_t_view, std::char_traits<char8_t_view>, std::allocator<char8_t_view> >
|
||||
std::u16string_view std::basic_string<char16_t_view, std::char_traits<char16_t_view>, std::allocator<char16_t_view> >
|
||||
std::u32string_view std::basic_string<char32_t_view, std::char_traits<char32_t_view>, std::allocator<char32_t_view> >
|
||||
|
||||
std::stringstream std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wstringstream std::basic_stringstream<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
std::istringstream std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wistringstream std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
std::ostringstream std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wostringstream std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
|
||||
std::spanbuf std::basic_spanbuf<char, std::char_traits<char> >
|
||||
std::wspanbuf std::basic_spanbuf<wchar_t, std::char_traits<wchar_t> >
|
||||
std::ispanstream std::basic_ispanstream<char, std::char_traits<char> >
|
||||
std::wispanstream std::basic_ispanstream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::spanstream std::basic_spanstream<char, std::char_traits<char> >
|
||||
std::wspanstream std::basic_spanstream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::syncbuf std::basic_syncbuf<char, std::char_traits<char> >
|
||||
std::wsyncbuf std::basic_syncbuf<wchar_t, std::char_traits<wchar_t> >
|
||||
std::osyncstream std::basic_osyncstream<char, std::char_traits<char> >
|
||||
std::wosyncstream std::basic_osyncstream<wchar_t, std::char_traits<wchar_t> >
|
||||
|
||||
std::stringbuf std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >
|
||||
std::wstringbuf std::basic_stringbuf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
|
||||
std::ios std::basic_ios<char, std::char_traits<char> >
|
||||
std::wios std::basic_ios<wchar_t, std::char_traits<wchar_t> >
|
||||
std::istream std::basic_istream<char, std::char_traits<char> >
|
||||
std::wistream std::basic_istream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::ostream std::basic_ostream<char, std::char_traits<char> >
|
||||
std::wostream std::basic_ostream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::iostream std::basic_iostream<char, std::char_traits<char> >
|
||||
std::wiostream std::basic_iostream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::fstream std::basic_fstream<char, std::char_traits<char> >
|
||||
std::wfstream std::basic_fstream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::ifstream std::basic_ifstream<char, std::char_traits<char> >
|
||||
std::wifstream std::basic_ifstream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::ofstream std::basic_ofstream<char, std::char_traits<char> >
|
||||
std::wofstream std::basic_ofstream<wchar_t, std::char_traits<wchar_t> >
|
||||
std::streambuf std::basic_streambuf<char, std::char_traits<char> >
|
||||
std::wstreambuf std::basic_streambuf<wchar_t, std::char_traits<wchar_t> >
|
||||
std::filebuf std::basic_filebuf<char, std::char_traits<char> >
|
||||
std::wfilebuf std::basic_filebuf<wchar_t, std::char_traits<wchar_t> >
|
||||
|
||||
std::regex std::basic_regex<char, std::regex_traits<char> >
|
||||
std::wregex std::basic_regex<wchar_t, std::regex_traits<wchar_t> >
|
||||
|
||||
|
||||
//
|
||||
// Secondary pass conversions
|
||||
//
|
||||
// These run after previous conversions so that we can perform further replacements
|
||||
//
|
||||
|
||||
std::string::string std::string::basic_string
|
||||
std::string::~string std::string::~basic_string
|
||||
std::wstring::wstring std::wstring::basic_string
|
||||
std::wstring::~wstring std::wstring::~basic_string
|
||||
std::u8string::u8string std::u8string::basic_string
|
||||
std::u8string::~u8string std::u8string::~basic_string
|
||||
std::u16string::u16string std::u16string::basic_string
|
||||
std::u16string::~u16string std::u16string::~basic_string
|
||||
std::u32string::u32string std::u32string::basic_string
|
||||
std::u32string::~u32string std::u32string::~basic_string
|
||||
std::string_view::string_view std::string_view::basic_string_view
|
||||
std::string_view::~string_view std::string_view::~basic_string_view
|
||||
std::wstring_view::wstring_view std::wstring_view::basic_string_view
|
||||
std::wstring_view::~wstring_view std::wstring_view::~basic_string_view
|
||||
std::u8string_view::u8string_view std::u8string_view::basic_string
|
||||
std::u8string_view::~u8string_view std::u8string_view::~basic_string
|
||||
std::u16string_view::u16string_view std::u16string_view::basic_string
|
||||
std::u16string_view::~u16string_view std::u16string_view::~basic_string
|
||||
std::u32string_view::u32string_view std::u32string_view::basic_string
|
||||
std::u32string_view::~u32string_view std::u32string_view::~basic_string
|
||||
std::stringstream::stringstream std::stringstream::basic_stringstream
|
||||
std::stringstream::~stringstream std::stringstream::~basic_stringstream
|
||||
std::wstringstream::wstringstream std::wstringstream::basic_stringstream
|
||||
std::wstringstream::~wstringstream std::wstringstream::~basic_stringstream
|
||||
std::istringstream::istringstream std::istringstream::basic_istringstream
|
||||
std::istringstream::~istringstream std::istringstream::~basic_istringstream
|
||||
td::wistringstream::wistringstream std::wistringstream::basic_istringstream
|
||||
std::wistringstream::~wistringstream std::wistringstream::~basic_istringstream
|
||||
std::ostringstream::ostringstream std::ostringstream::basic_ostringstream
|
||||
std::ostringstream::~ostringstream std::ostringstream::~basic_ostringstream
|
||||
std::wostringstream::wostringstream std::wostringstream::basic_ostringstream
|
||||
std::wostringstream::~wostringstream std::wostringstream::~basic_ostringstream
|
||||
std::stringbuf::stringbuf std::stringbuf::basic_stringbuf
|
||||
std::stringbuf::~stringbuf std::stringbuf::~basic_stringbuf
|
||||
std::wstringbuf::wstringbuf std::wstringbuf::basic_stringbuf
|
||||
std::wstringbuf::~wstringbuf std::wstringbuf::~basic_stringbuf
|
||||
std::ios::ios std::ios::basic_ios
|
||||
std::ios::~ios std::ios::~basic_ios
|
||||
std::wios::wios std::wios::basic_ios
|
||||
std::wios::~wios std::wios::~basic_ios
|
||||
std::istream::istream std::istream::basic_istream
|
||||
std::istream::~istream std::istream::~basic_istream
|
||||
std::wistream::wistream std::wistream::basic_istream
|
||||
std::wistream::~wistream std::wistream::~basic_istream
|
||||
std::ostream::ostream std::ostream::basic_ostream
|
||||
std::ostream::~ostream std::ostream::~basic_ostream
|
||||
std::wostream::wostream std::wostream::basic_ostream
|
||||
std::wostream::~wostream std::wostream::~basic_ostream
|
||||
std::iostream::iostream std::iostream::basic_iostream
|
||||
std::iostream::~iostream std::iostream::~basic_iostream
|
||||
std::wiostream::wiostream std::wiostream::basic_iostream
|
||||
std::wiostream::~wiostream std::wiostream::~basic_iostream
|
||||
std::fstream::fstream std::fstream::basic_fstream
|
||||
std::fstream::~fstream std::fstream::~basic_fstream
|
||||
std::wfstream::wfstream std::wfstream::basic_fstream
|
||||
std::wfstream::~wfstream std::wfstream::~basic_fstream
|
||||
std::ifstream::ifstream std::ifstream::basic_ifstream
|
||||
std::ifstream::~ifstream std::ifstream::~basic_ifstream
|
||||
std::wifstream::wifstream std::wifstream::basic_ifstream
|
||||
std::wifstream::~wifstream std::wifstream::~basic_ifstream
|
||||
std::ofstream::ofstream std::ofstream::basic_ofstream
|
||||
std::ofstream::~ofstream std::ofstream::~basic_ofstream
|
||||
std::wofstream::wofstream std::wofstream::basic_ofstream
|
||||
std::wofstream::~wofstream std::wofstream::~basic_ofstream
|
||||
std::streambuf::streambuf std::streambuf::basic_streambuf
|
||||
std::streambuf::~streambuf std::streambuf::~basic_streambuf
|
||||
std::wstreambuf::wstreambuf std::wstreambuf::basic_streambuf
|
||||
std::wstreambuf::~wstreambuf std::wstreambuf::~basic_streambuf
|
||||
std::filebuf::filebuf std::filebuf::basic_filebuf
|
||||
std::filebuf::~filebuf std::filebuf::~basic_filebuf
|
||||
std::wfilebuf::wfilebuf std::wfilebuf::basic_filebuf
|
||||
std::wfilebuf::~wfilebuf std::wfilebuf::~basic_filebuf
|
||||
std::spanbuf::spanbuf std::spanbuf::basic_spanbuf
|
||||
std::spanbuf::~spanbuf std::spanbuf::~basic_spanbuf
|
||||
std::wspanbuf::wspanbuf std::wspanbuf::basic_spanbuf
|
||||
std::wspanbuf::~wspanbuf std::wspanbuf::~basic_spanbuf
|
||||
std::ispanstream::ispanstream std::ispanstream::basic_ispanstream
|
||||
std::ispanstream::~ispanstream std::ispanstream::~basic_ispanstream
|
||||
std::wispanstream::wispanstream std::wispanstream::basic_ispanstream
|
||||
std::wispanstream::~wispanstream std::wispanstream::~basic_ispanstream
|
||||
std::spanstream::spanstream std::spanstream::basic_spanstream
|
||||
std::spanstream::~spanstream std::spanstream::~basic_spanstream
|
||||
std::wspanstream::wspanstream std::wspanstream::basic_spanstream
|
||||
std::wspanstream::~wspanstream std::wspanstream::~basic_spanstream
|
||||
std::syncbuf::syncbuf std::syncbuf::basic_syncbuf
|
||||
std::syncbuf::~syncbuf std::syncbuf::~basic_syncbuf
|
||||
std::wsyncbuf::wsyncbuf std::wsyncbuf::basic_syncbuf
|
||||
std::wsyncbuf::~wsyncbuf std::wsyncbuf::~basic_syncbuf
|
||||
std::osyncstream::osyncstream std::osyncstream::basic_osyncstream
|
||||
std::osyncstream::~osyncstream std::osyncstream::~basic_osyncstream
|
||||
std::wosyncstream::wosyncstream std::wosyncstream::basic_osyncstream
|
||||
std::wosyncstream::~wosyncstream std::wosyncstream::~basic_osyncstream
|
||||
|
||||
|
||||
// speculative:
|
||||
std::string std::basic_string<std::remove_const<char const>::type, std::char_traits<std::remove_const<char const>::type>, std::allocator<std::remove_const<char const>::type> >
|
||||
|
||||
|
@ -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.
|
||||
@ -43,6 +43,11 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
"Only demangle symbols that follow known compiler mangling patterns. " +
|
||||
"Leaving this option off may cause non-mangled symbols to get demangled.";
|
||||
|
||||
private static final String OPTION_NAME_DEMANGLE_USE_STANDARD_REPLACEMENTS =
|
||||
"Use Standard Text Replacements";
|
||||
private static final String OPTION_DESCRIPTION_STANDARD_REPLACEMENTS =
|
||||
"Use text simplifications in demangled output, for example to use standard c++ typedefs.";
|
||||
|
||||
private static final String OPTION_NAME_APPLY_SIGNATURE = "Apply Function Signatures";
|
||||
private static final String OPTION_DESCRIPTION_APPLY_SIGNATURE =
|
||||
"Apply any recovered function signature, in addition to the function name";
|
||||
@ -64,6 +69,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
private boolean applyFunctionSignature = true;
|
||||
private boolean applyCallingConvention = true;
|
||||
private boolean demangleOnlyKnownPatterns = false;
|
||||
private boolean useStandardReplacements = true;
|
||||
private GnuDemanglerFormat demanglerFormat = GnuDemanglerFormat.AUTO;
|
||||
private boolean useDeprecatedDemangler = false;
|
||||
|
||||
@ -92,6 +98,9 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns,
|
||||
help, OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
|
||||
|
||||
options.registerOption(OPTION_NAME_DEMANGLE_USE_STANDARD_REPLACEMENTS,
|
||||
useStandardReplacements, help, OPTION_DESCRIPTION_STANDARD_REPLACEMENTS);
|
||||
|
||||
GnuOptionsEditor optionsEditor = new GnuOptionsEditor();
|
||||
|
||||
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
|
||||
@ -112,6 +121,8 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
options.getBoolean(OPTION_NAME_APPLY_CALLING_CONVENTION, applyCallingConvention);
|
||||
demangleOnlyKnownPatterns =
|
||||
options.getBoolean(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns);
|
||||
useStandardReplacements =
|
||||
options.getBoolean(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useStandardReplacements);
|
||||
demanglerFormat = options.getEnum(OPTION_NAME_DEMANGLER_FORMAT, GnuDemanglerFormat.AUTO);
|
||||
useDeprecatedDemangler =
|
||||
options.getBoolean(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler);
|
||||
@ -125,6 +136,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
options.setApplySignature(applyFunctionSignature);
|
||||
options.setApplyCallingConvention(applyCallingConvention);
|
||||
options.setDemangleOnlyKnownPatterns(demangleOnlyKnownPatterns);
|
||||
options.setUseStandardReplacements(useStandardReplacements);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -115,9 +115,8 @@ public class GnuDemangler implements Demangler {
|
||||
throw new DemangledException(true);
|
||||
}
|
||||
|
||||
boolean onlyKnownPatterns = options.demangleOnlyKnownPatterns();
|
||||
DemangledObject demangledObject =
|
||||
parse(originalMangled, process, demangled, onlyKnownPatterns);
|
||||
parse(originalMangled, process, demangled, options);
|
||||
if (demangledObject == null) {
|
||||
return demangledObject;
|
||||
}
|
||||
@ -226,14 +225,16 @@ public class GnuDemangler implements Demangler {
|
||||
}
|
||||
|
||||
private DemangledObject parse(String mangled, GnuDemanglerNativeProcess process,
|
||||
String demangled, boolean demangleOnlyKnownPatterns) {
|
||||
String demangled, GnuDemanglerOptions options) {
|
||||
|
||||
if (demangleOnlyKnownPatterns && !isKnownMangledString(mangled, demangled)) {
|
||||
boolean onlyKnownPatterns = options.demangleOnlyKnownPatterns();
|
||||
if (onlyKnownPatterns && !isKnownMangledString(mangled, demangled)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean replaceStdTypedefs = options.shouldUseStandardReplacements();
|
||||
GnuDemanglerParser parser = new GnuDemanglerParser();
|
||||
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
||||
DemangledObject demangledObject = parser.parse(mangled, demangled, replaceStdTypedefs);
|
||||
return demangledObject;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
@ -46,6 +46,7 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||
|
||||
private final GnuDemanglerFormat format;
|
||||
private final boolean isDeprecated;
|
||||
private boolean useStandardReplacements;
|
||||
|
||||
/**
|
||||
* Default constructor to use the modern demangler with auto-detect for the format. This
|
||||
@ -76,6 +77,7 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||
public GnuDemanglerOptions(GnuDemanglerFormat format, boolean isDeprecated) {
|
||||
this.format = format;
|
||||
this.isDeprecated = isDeprecated;
|
||||
this.useStandardReplacements = true;
|
||||
if (!format.isAvailable(isDeprecated)) {
|
||||
throw new IllegalArgumentException(
|
||||
format.name() + " is not available in the " + getDemanglerName());
|
||||
@ -98,13 +100,29 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||
format = GnuDemanglerFormat.AUTO;
|
||||
isDeprecated = false;
|
||||
}
|
||||
|
||||
this.useStandardReplacements = true;
|
||||
}
|
||||
|
||||
private GnuDemanglerOptions(GnuDemanglerOptions copy, GnuDemanglerFormat format,
|
||||
boolean deprecated) {
|
||||
this(copy, format, deprecated, true);
|
||||
}
|
||||
|
||||
private GnuDemanglerOptions(GnuDemanglerOptions copy, GnuDemanglerFormat format,
|
||||
boolean deprecated, boolean useStandardReplacements) {
|
||||
super(copy);
|
||||
this.format = format;
|
||||
this.isDeprecated = deprecated;
|
||||
this.useStandardReplacements = useStandardReplacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes this options value of {@link #shouldUseStandardReplacements()}
|
||||
* @param replace true to replace
|
||||
*/
|
||||
public void setUseStandardReplacements(boolean replace) {
|
||||
this.useStandardReplacements = replace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,12 +176,23 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the gnu demangler parser should replace demangler output with standard text
|
||||
* replacements defined in {@code GnuDemangler/data/default.gnu.demangler.replacements.txt}.
|
||||
*
|
||||
* @return true to use replacements; false to not replace text
|
||||
*/
|
||||
public boolean shouldUseStandardReplacements() {
|
||||
return useStandardReplacements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//@formatter:off
|
||||
return "{\n" +
|
||||
"\tdoDisassembly: " + doDisassembly() + ",\n" +
|
||||
"\tapplySignature: " + applySignature() + ",\n" +
|
||||
"\tuseStandardReplacements: " + useStandardReplacements + ",\n" +
|
||||
"\tdemangleOnlyKnownPatterns: " + demangleOnlyKnownPatterns() + ",\n" +
|
||||
"\tdemanglerName: " + getDemanglerName() + ",\n" +
|
||||
"\tdemanglerApplicationArguments: " + getDemanglerApplicationArguments() + ",\n" +
|
||||
|
@ -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.
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.demangler.gnu;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -25,16 +26,33 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.json.Json;
|
||||
import ghidra.app.util.SymbolPathParser;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.StringUtilities;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
/**
|
||||
* Parses output generated by the gnu demangler. This class will create a {@link DemangledObject}
|
||||
* if it can successfully parse the given input. By default, this class will apply simplifications
|
||||
* to the input, for example, to use simplified typedefs provided by the c++ language. To avoid
|
||||
* simplifications, use {@link #parse(String, String, boolean)}.
|
||||
* <p>
|
||||
* The simplification process is based upon predefined text patterns that this class will search for
|
||||
* and replace with alternate text. New simplifications can be added by providing a module data file
|
||||
* that ends with {@value #REPLACEMENT_FILE_EXTENSION}. The file is parsed expected each line to
|
||||
* contain a replacement string consisting of the replacement and the search value, separated by
|
||||
* whitespace.
|
||||
*/
|
||||
public class GnuDemanglerParser {
|
||||
|
||||
private static final String REPLACEMENT_FILE_EXTENSION = ".gnu.demangler.replacements.txt";
|
||||
|
||||
private static final String CONSTRUCTION_VTABLE_FOR = "construction vtable for ";
|
||||
private static final String VTT_FOR = "VTT for ";
|
||||
private static final String VTABLE_FOR = "vtable for ";
|
||||
@ -347,6 +365,8 @@ public class GnuDemanglerParser {
|
||||
private static final Pattern RUST_LEGACY_SUFFIX_PATTERN =
|
||||
Pattern.compile("(.*)::h[0-9a-f]{16}");
|
||||
|
||||
private static final List<GnuDemanglerReplacement> REPLACEMENTS = loadStandardReplacements();
|
||||
|
||||
private String mangledSource;
|
||||
private String demangledSource;
|
||||
|
||||
@ -357,11 +377,32 @@ public class GnuDemanglerParser {
|
||||
* @param demangled the demangled text
|
||||
* @return the demangled object
|
||||
* @throws DemanglerParseException if there is an unexpected error parsing
|
||||
* @see #parse(String, String, boolean)
|
||||
*/
|
||||
public DemangledObject parse(String mangled, String demangled) throws DemanglerParseException {
|
||||
return parse(mangled, demangled, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given demangled string and creates a {@link DemangledObject}
|
||||
*
|
||||
* @param mangled the original mangled text
|
||||
* @param demangled the demangled text
|
||||
* @param simplify true signals to simplify types where possible, such as using simple c++
|
||||
* typedefs where possible.
|
||||
* @return the demangled object
|
||||
* @throws DemanglerParseException if there is an unexpected error parsing
|
||||
* @see #parse(String, String, boolean)
|
||||
*/
|
||||
public DemangledObject parse(String mangled, String demangled, boolean simplify)
|
||||
throws DemanglerParseException {
|
||||
|
||||
demangled = cleanupRustLegacySymbol(demangled);
|
||||
|
||||
if (simplify) {
|
||||
demangled = replaceStdLibraryTypes(demangled);
|
||||
}
|
||||
|
||||
this.mangledSource = mangled;
|
||||
this.demangledSource = demangled;
|
||||
|
||||
@ -507,6 +548,14 @@ public class GnuDemanglerParser {
|
||||
return demangled;
|
||||
}
|
||||
|
||||
private String replaceStdLibraryTypes(String demangled) {
|
||||
String d = demangled;
|
||||
for (GnuDemanglerReplacement replacement : REPLACEMENTS) {
|
||||
d = StringUtils.replace(d, replacement.find(), replacement.replace());
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
private void setReturnType(String demangled, DemangledFunction function, String returnType) {
|
||||
|
||||
String updatedReturnType = returnType;
|
||||
@ -1462,6 +1511,66 @@ public class GnuDemanglerParser {
|
||||
return myNamespace;
|
||||
}
|
||||
|
||||
private static List<GnuDemanglerReplacement> loadStandardReplacements() {
|
||||
|
||||
List<GnuDemanglerReplacement> results = new ArrayList<>();
|
||||
List<ResourceFile> files =
|
||||
Application.findFilesByExtensionInApplication(REPLACEMENT_FILE_EXTENSION);
|
||||
|
||||
// sort files by name to provide a consistent way for prioritizing replacements
|
||||
files.sort((r1, r2) -> r1.getName().compareTo(r2.getName()));
|
||||
|
||||
for (ResourceFile file : files) {
|
||||
List<String> lines = getReplacementLines(file);
|
||||
for (String line : lines) {
|
||||
GnuDemanglerReplacement replacement = parseReplacement(line, file);
|
||||
if (replacement != null) {
|
||||
results.add(replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static GnuDemanglerReplacement parseReplacement(String line, ResourceFile file) {
|
||||
for (int i = 0; i < line.length(); i++) {
|
||||
char c = line.charAt(i);
|
||||
if (Character.isWhitespace(c)) {
|
||||
String replace = line.substring(0, i).trim();
|
||||
|
||||
// special case
|
||||
if (replace.equals("\"\"")) {
|
||||
replace = StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
String find = line.substring(i).trim();
|
||||
return new GnuDemanglerReplacement(find, replace, file);
|
||||
}
|
||||
}
|
||||
|
||||
Msg.warn(GnuDemanglerParser.class,
|
||||
"Malformed replacement line. No spaces found: " + line + ". In file: " + file);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<String> getReplacementLines(ResourceFile file) {
|
||||
try {
|
||||
List<String> lines = FileUtilities.getLines(file);
|
||||
return lines.stream()
|
||||
.filter(l -> !l.startsWith("//"))
|
||||
.filter(l -> !l.isBlank())
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(GnuDemanglerParser.class,
|
||||
"Unable to load gnu demangler replacement file: " + file, e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
@ -0,0 +1,39 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler.gnu;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
|
||||
/**
|
||||
* A simple object that is used to find and replace content within Gnu demangled strings.
|
||||
* @param find the string to search for; cannot be null
|
||||
* @param replace the replacement string; cannot be null
|
||||
* @param source the file from whence the replacement came; may be null
|
||||
*/
|
||||
public record GnuDemanglerReplacement(String find, String replace, ResourceFile source) {
|
||||
|
||||
public GnuDemanglerReplacement {
|
||||
Objects.requireNonNull(find, "'find' cannot be null");
|
||||
Objects.requireNonNull(replace, "'replace' cannot be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return replace + "\t\t" + find;
|
||||
}
|
||||
}
|
@ -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.
|
||||
@ -197,15 +197,15 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
|
||||
assertEquals(
|
||||
"__insertion_sort<__gnu_cxx::__normal_iterator<std::pair<unsigned_long,PcodeOp*>*,std::vector<std::pair<unsigned_long,PcodeOp*>,std::allocator<std::pair<unsigned_long,PcodeOp*>>>>,bool(*)(std::pair<unsigned_long,PcodeOp*>const&,std::pair<unsigned_long,PcodeOp*>const&)>",
|
||||
"__insertion_sort<__normal_iterator<std::pair<unsigned_long,PcodeOp*>*,std::vector<std::pair<unsigned_long,PcodeOp*>,std::allocator<std::pair<unsigned_long,PcodeOp*>>>>,bool(*)(std::pair<unsigned_long,PcodeOp*>const&,std::pair<unsigned_long,PcodeOp*>const&)>",
|
||||
function.getName());
|
||||
assertEquals("std", function.getNamespace().getName());
|
||||
|
||||
assertEquals(
|
||||
"__gnu_cxx::__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
||||
"__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
||||
parameters.get(0).toString());
|
||||
assertEquals(
|
||||
"__gnu_cxx::__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
||||
"__normal_iterator<std::pair<unsigned long,PcodeOp *> *,std::vector<std::pair<unsigned long,PcodeOp *>,std::allocator<std::pair<unsigned long,PcodeOp *>>>>",
|
||||
parameters.get(1).toString());
|
||||
assertEquals(
|
||||
"bool (*)(std::pair<unsigned long,PcodeOp *> const &,std::pair<unsigned long,PcodeOp *> const &)",
|
||||
@ -283,11 +283,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertType(object, DemangledThunk.class);
|
||||
assertName(object, "~basic_ostringstream", "std",
|
||||
"basic_ostringstream<char,std::char_traits<char>,pool_allocator<char>>");
|
||||
assertName(object, "~ostringstream", "std", "ostringstream");
|
||||
|
||||
assertEquals(
|
||||
"virtual thunk to undefined __thiscall std::basic_ostringstream<char,std::char_traits<char>,pool_allocator<char>>::~basic_ostringstream(void)",
|
||||
"virtual thunk to undefined __thiscall std::ostringstream::~ostringstream(void)",
|
||||
object.getSignature(false));
|
||||
}
|
||||
|
||||
@ -915,8 +914,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertName(object, "Image", "Magick", "Image");
|
||||
|
||||
assertEquals(
|
||||
"undefined Magick::Image::Image(" +
|
||||
"std::basic_string<char,std::char_traits<char>,std::allocator<char>> const &)",
|
||||
"undefined Magick::Image::Image(std::string const &)",
|
||||
object.getSignature(false));
|
||||
}
|
||||
|
||||
@ -977,9 +975,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
String name = object.getName();
|
||||
assertEquals("operator>>", name);
|
||||
assertEquals(
|
||||
"std::basic_istream<char,std::char_traits<char>> & " +
|
||||
"std::operator>><char,std::char_traits<char>>" +
|
||||
"(std::basic_istream<char,std::char_traits<char>> &,char &)",
|
||||
"std::istream & std::operator>><char,std::char_traits<char>>(std::istream &,char &)",
|
||||
object.getSignature());
|
||||
}
|
||||
|
||||
@ -989,9 +985,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
String raw = "std::basic_ostream<char, std::char_traits<char> >& " +
|
||||
"std::operator<< <std::char_traits<char> >" +
|
||||
"(std::basic_ostream<char, std::char_traits<char> >&, char const*)";
|
||||
String formatted = "std::basic_ostream<char,std::char_traits<char>> & " +
|
||||
"std::operator<<<std::char_traits<char>>" +
|
||||
"(std::basic_ostream<char,std::char_traits<char>> &,char const *)";
|
||||
String formatted =
|
||||
"std::ostream & std::operator<<<std::char_traits<char>>(std::ostream &,char const *)";
|
||||
DemangledObject object =
|
||||
parser.parse("_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc", raw);
|
||||
String name = object.getName();
|
||||
@ -1010,9 +1005,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
"(*)(std::basic_ostream<char, std::char_traits<char> >&))");
|
||||
String name = object.getName();
|
||||
assertEquals("operator<<", name);
|
||||
assertName(object, "operator<<", "std", "basic_ostream<char,std::char_traits<char>>");
|
||||
assertEquals("undefined std::basic_ostream<char,std::char_traits<char>>" + "::operator<<(" +
|
||||
"std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))",
|
||||
assertName(object, "operator<<", "std", "ostream");
|
||||
assertEquals("undefined std::ostream::operator<<(std::ostream & (*)(std::ostream &))",
|
||||
object.getSignature());
|
||||
}
|
||||
|
||||
@ -1118,7 +1112,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>> std::_Bind<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>(EduAppConfigs::*(EduAppConfigs_const*))()const>::operator()<missing_argument,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>(void)",
|
||||
"std::string std::_Bind<std::string(EduAppConfigs::*(EduAppConfigs_const*))()const>::operator()<missing_argument,std::string>(void)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@ -1151,7 +1145,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"std::__cxx11::basic_string<std::remove_const<char_const>::type,std::char_traits<std::remove_const<char_const>::type>,std::allocator<std::remove_const<char_const>::type>> gsl::to_string<char_const,-1l>(gsl::basic_string_span<char const,long>)",
|
||||
"std::string gsl::to_string<char_const,-1l>(gsl::basic_string_span<char const,long>)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@ -1289,10 +1283,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertType(object, DemangledFunction.class);
|
||||
assertName(object, "operator.cast.to.basic_string", "Magick", "Color");
|
||||
assertName(object, "operator.cast.to.string", "Magick", "Color");
|
||||
|
||||
assertEquals("std::basic_string<char,std::char_traits<char>,std::allocator<char>> " +
|
||||
"Magick::Color::operator.cast.to.basic_string(void)", object.getSignature(false));
|
||||
assertEquals("std::string Magick::Color::operator.cast.to.string(void)",
|
||||
object.getSignature(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1636,7 +1630,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
"vector<boost::function<void()>,std::allocator<boost::function<void()>>>");
|
||||
|
||||
assertEquals(
|
||||
"undefined std::vector<boost::function<void()>,std::allocator<boost::function<void()>>>::_M_insert_aux(__gnu_cxx::__normal_iterator<boost::function<void ()> *,std::vector<boost::function<void ()>,std::allocator<boost::function<void ()>>>>,boost::function<void ()> const &)",
|
||||
"undefined std::vector<boost::function<void()>,std::allocator<boost::function<void()>>>::_M_insert_aux(__normal_iterator<boost::function<void ()> *,std::vector<boost::function<void ()>,std::allocator<boost::function<void ()>>>>,boost::function<void ()> const &)",
|
||||
object.getSignature(false));
|
||||
}
|
||||
|
||||
@ -1665,7 +1659,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"undefined WebCore::ContentFilterUnblockHandler::ContentFilterUnblockHandler(WTF::String,std::__1::function<void (std::__1::function<void (bool)>)>)",
|
||||
"undefined WebCore::ContentFilterUnblockHandler::ContentFilterUnblockHandler(WTF::String,std::function<void (std::function<void (bool)>)>)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@ -1775,9 +1769,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals("undefined __gnu_cxx" + "::" +
|
||||
assertEquals("undefined " +
|
||||
"__stoa<long,int,char,int>(long(*)(char_const*,char**,int),char_const*,char_const*,unsigned_long*,int)" +
|
||||
"::" + "_Save_errno::_Save_errno(void)", signature);
|
||||
"::_Save_errno::_Save_errno(void)", signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1814,12 +1808,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
String name =
|
||||
"for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>>>";
|
||||
"for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,2l>>>";
|
||||
assertName(object, name, "brigand");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>>>(WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,long>> &&)",
|
||||
"WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,2l>>>(WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::integral_constant<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,long>> &&,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std<long,long>> &&)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@ -1928,7 +1922,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
String signature = object.getSignature(false);
|
||||
|
||||
assertEquals(
|
||||
"undefined WebCore::TextCodecICU::registerCodecs(void (*)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
||||
"undefined WebCore::TextCodecICU::registerCodecs(void (*)(char const *,WTF::Function<std::unique_ptr<WebCore::TextCodec,std::default_delete<WebCore::TextCodec>> ()> &&))",
|
||||
signature);
|
||||
}
|
||||
|
||||
@ -2215,13 +2209,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
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>>>>",
|
||||
"std",
|
||||
"__1");
|
||||
"__allocate_at_least[abi:v160006]<std::allocator<std::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>",
|
||||
"std");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"std::__1::__allocation_result<std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>::pointer> std::__1::__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>(std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void *,&VPTimeFreqConverter_Dispose>>> &,unsigned long)",
|
||||
"std::__allocation_result<std::allocator_traits<std::allocator<std::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>::pointer> std::__allocate_at_least[abi:v160006]<std::allocator<std::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>(std::allocator<std::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void *,&VPTimeFreqConverter_Dispose>>> &,unsigned long)",
|
||||
signature);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
@ -86,6 +86,45 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseStandardReplacements() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev
|
||||
//
|
||||
// Demangled: virtual thunk to std::basic_ostringstream<char, std::char_traits<char>, pool_allocator<char> >::~basic_ostringstream()
|
||||
//
|
||||
// Replaced: virtual thunk to undefined __thiscall std::ostringstream::~ostringstream(void)
|
||||
//
|
||||
String mangled =
|
||||
"_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||
options.setUseStandardReplacements(true);
|
||||
DemangledObject dobj = demangler.demangle(mangled, options);
|
||||
assertNotNull(dobj);
|
||||
|
||||
String signature = dobj.getSignature();
|
||||
assertEquals(
|
||||
"virtual thunk to undefined __thiscall std::ostringstream::~ostringstream(void)",
|
||||
signature);
|
||||
|
||||
//
|
||||
// Now disable demangled string replacement
|
||||
//
|
||||
options.setUseStandardReplacements(false);
|
||||
dobj = demangler.demangle(mangled, options);
|
||||
assertNotNull(dobj);
|
||||
|
||||
String fullSignature = dobj.getSignature();
|
||||
assertEquals(
|
||||
"virtual thunk to undefined __thiscall std::basic_ostringstream<char,std::char_traits<char>,pool_allocator<char>>::~basic_ostringstream(void)",
|
||||
fullSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleOnlyKnownPatterns_True() throws Exception {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user