Skip to content

Cherrypick upstream demangling commits #3902

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions lldb/include/lldb/Core/Mangled.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,9 @@ class Mangled {
/// Function signature for filtering mangled names.
using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);

/// Trigger explicit demangling to obtain rich mangling information. This is
/// optimized for batch processing while populating a name index. To get the
/// pure demangled name string for a single entity, use GetDemangledName()
/// instead.
/// Get rich mangling information. This is optimized for batch processing
/// while populating a name index. To get the pure demangled name string for
/// a single entity, use GetDemangledName() instead.
///
/// For names that match the Itanium mangling scheme, this uses LLVM's
/// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
Expand All @@ -258,8 +257,8 @@ class Mangled {
///
/// \return
/// True on success, false otherwise.
bool DemangleWithRichManglingInfo(RichManglingContext &context,
SkipMangledNameFn *skip_mangled_name);
bool GetRichManglingInfo(RichManglingContext &context,
SkipMangledNameFn *skip_mangled_name);

/// Try to identify the mangling scheme used.
/// \param[in] name
Expand Down
29 changes: 8 additions & 21 deletions lldb/include/lldb/Core/RichManglingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,22 @@ class RichManglingContext {
bool IsCtorOrDtor() const;

/// Get the base name of a function. This doesn't include trailing template
/// arguments, ie "a::b<int>" gives "b". The result will overwrite the
/// internal buffer. It can be obtained via GetBufferRef().
void ParseFunctionBaseName();
/// arguments, ie "a::b<int>" gives "b".
llvm::StringRef ParseFunctionBaseName();

/// Get the context name for a function. For "a::b::c", this function returns
/// "a::b". The result will overwrite the internal buffer. It can be obtained
/// via GetBufferRef().
void ParseFunctionDeclContextName();

/// Get the entire demangled name. The result will overwrite the internal
/// buffer. It can be obtained via GetBufferRef().
void ParseFullName();

/// Obtain a StringRef to the internal buffer that holds the result of the
/// most recent ParseXy() operation. The next ParseXy() call invalidates it.
llvm::StringRef GetBufferRef() const {
assert(m_provider != None && "Initialize a provider first");
return m_buffer;
}
/// "a::b".
llvm::StringRef ParseFunctionDeclContextName();

/// Get the entire demangled name.
llvm::StringRef ParseFullName();

private:
enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage };

/// Selects the rich mangling info provider.
InfoProvider m_provider = None;

/// Reference to the buffer used for results of ParseXy() operations.
llvm::StringRef m_buffer;

/// Members for ItaniumPartialDemangler
llvm::ItaniumPartialDemangler m_ipd;
/// Note: m_ipd_buf is a raw pointer due to being resized by realloc via
Expand All @@ -93,7 +80,7 @@ class RichManglingContext {
void ResetProvider(InfoProvider new_provider);

/// Uniform handling of string buffers for ItaniumPartialDemangler.
void processIPDStrResult(char *ipd_res, size_t res_len);
llvm::StringRef processIPDStrResult(char *ipd_res, size_t res_len);

/// Cast the given parser to the given type. Ideally we would have a type
/// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
Expand Down
21 changes: 6 additions & 15 deletions lldb/source/Core/Mangled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ static char *GetRustV0DemangledStr(const char *M) {

// Explicit demangling for scheduled requests during batch processing. This
// makes use of ItaniumPartialDemangler's rich demangle info
bool Mangled::DemangleWithRichManglingInfo(
RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) {
bool Mangled::GetRichManglingInfo(RichManglingContext &context,
SkipMangledNameFn *skip_mangled_name) {
// Others are not meant to arrive here. ObjC names or C's main() for example
// have their names stored in m_demangled, while m_mangled is empty.
assert(m_mangled);
Expand All @@ -240,25 +240,16 @@ bool Mangled::DemangleWithRichManglingInfo(
case eManglingSchemeItanium:
// We want the rich mangling info here, so we don't care whether or not
// there is a demangled string in the pool already.
if (context.FromItaniumName(m_mangled)) {
// If we got an info, we have a name. Copy to string pool and connect the
// counterparts to accelerate later access in GetDemangledName().
context.ParseFullName();
m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(),
m_mangled);
return true;
} else {
m_demangled.SetCString("");
return false;
}
return context.FromItaniumName(m_mangled);

case eManglingSchemeMSVC: {
// We have no rich mangling for MSVC-mangled names yet, so first try to
// demangle it if necessary.
if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) {
// If we got an info, we have a name. Copy to string pool and connect
// the counterparts to accelerate later access in GetDemangledName().
// Without the rich mangling info we have to demangle the full name.
// Copy it to string pool and connect the counterparts to accelerate
// later access in GetDemangledName().
m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
m_mangled);
::free(d);
Expand Down
46 changes: 20 additions & 26 deletions lldb/source/Core/RichManglingContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ bool RichManglingContext::IsCtorOrDtor() const {
llvm_unreachable("Fully covered switch above!");
}

void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
llvm::StringRef RichManglingContext::processIPDStrResult(char *ipd_res,
size_t res_size) {
// Error case: Clear the buffer.
if (LLVM_UNLIKELY(ipd_res == nullptr)) {
assert(res_size == m_ipd_buf_size &&
"Failed IPD queries keep the original size in the N parameter");

m_ipd_buf[0] = '\0';
m_buffer = llvm::StringRef(m_ipd_buf, 0);
return;
return llvm::StringRef(m_ipd_buf, 0);
}

// IPD's res_size includes null terminator.
Expand All @@ -109,60 +109,54 @@ void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
}

// 99% case: Just remember the string length.
m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
return llvm::StringRef(m_ipd_buf, res_size - 1);
}

void RichManglingContext::ParseFunctionBaseName() {
llvm::StringRef RichManglingContext::ParseFunctionBaseName() {
assert(m_provider != None && "Initialize a provider first");
switch (m_provider) {
case ItaniumPartialDemangler: {
auto n = m_ipd_buf_size;
auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
processIPDStrResult(buf, n);
return;
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
m_buffer =
get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
return;
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
->GetBasename();
case None:
return;
return {};
}
}

void RichManglingContext::ParseFunctionDeclContextName() {
llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {
assert(m_provider != None && "Initialize a provider first");
switch (m_provider) {
case ItaniumPartialDemangler: {
auto n = m_ipd_buf_size;
auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
processIPDStrResult(buf, n);
return;
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
m_buffer =
get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
return;
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
->GetContext();
case None:
return;
return {};
}
}

void RichManglingContext::ParseFullName() {
llvm::StringRef RichManglingContext::ParseFullName() {
assert(m_provider != None && "Initialize a provider first");
switch (m_provider) {
case ItaniumPartialDemangler: {
auto n = m_ipd_buf_size;
auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
processIPDStrResult(buf, n);
return;
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
->GetFullName()
.GetStringRef();
return;
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
->GetFullName()
.GetStringRef();
case None:
return;
return {};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ void InstrumentationRuntimeASan::Activate() {
if (!process_sp)
return;

ConstString symbol_name("__asan::AsanDie()");
ConstString symbol_name("_ZN6__asanL7AsanDieEv");
const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType(
symbol_name, eSymbolTypeCode);

Expand Down
15 changes: 8 additions & 7 deletions lldb/source/Symbol/Symtab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,13 @@ void Symtab::InitNameIndexes() {

const SymbolType type = symbol->GetType();
if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name))
if (mangled.GetRichManglingInfo(rmc, lldb_skip_name)) {
RegisterMangledNameEntry(value, class_contexts, backlog, rmc);
continue;
}
#ifdef LLDB_ENABLE_SWIFT
else if (SwiftLanguageRuntime::IsSwiftMangledName(name.GetStringRef())) {
else if (SwiftLanguageRuntime::IsSwiftMangledName(
name.GetStringRef())) {
lldb_private::ConstString basename;
bool is_method = false;
ConstString mangled_name = mangled.GetMangledName();
Expand All @@ -346,6 +349,7 @@ void Symtab::InitNameIndexes() {
else
basename_to_index.Append(basename, value);
}
continue;
}
}
#endif // LLDB_ENABLE_SWIFT
Expand Down Expand Up @@ -405,16 +409,13 @@ void Symtab::RegisterMangledNameEntry(
std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
RichManglingContext &rmc) {
// Only register functions that have a base name.
rmc.ParseFunctionBaseName();
llvm::StringRef base_name = rmc.GetBufferRef();
llvm::StringRef base_name = rmc.ParseFunctionBaseName();
if (base_name.empty())
return;

// The base name will be our entry's name.
NameToIndexMap::Entry entry(ConstString(base_name), value);

rmc.ParseFunctionDeclContextName();
llvm::StringRef decl_context = rmc.GetBufferRef();
llvm::StringRef decl_context = rmc.ParseFunctionDeclContextName();

// Register functions with no context.
if (decl_context.empty()) {
Expand Down
4 changes: 0 additions & 4 deletions lldb/test/API/macosx/dyld-trie-symbols/TestDyldTrieSymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ def test_dyld_trie_symbols(self):
self.assertEqual(unstripped_Z3pat_symbols.GetSize(), 1)
unstripped_pat_symbols = unstripped_target.FindSymbols("pat")
self.assertEqual(unstripped_pat_symbols.GetSize(), 1)
unstripped_patint_symbols = unstripped_target.FindSymbols("pat(int)")
self.assertEqual(unstripped_patint_symbols.GetSize(), 1)

unstripped_bar_symbols = unstripped_target.FindSymbols("bar")
self.assertEqual(unstripped_bar_symbols.GetSize(), 1)
Expand Down Expand Up @@ -77,8 +75,6 @@ def test_dyld_trie_symbols(self):
self.assertEqual(stripped_Z3pat_symbols.GetSize(), 1)
stripped_pat_symbols = stripped_target.FindSymbols("pat")
self.assertEqual(stripped_pat_symbols.GetSize(), 1)
stripped_patint_symbols = stripped_target.FindSymbols("pat(int)")
self.assertEqual(stripped_patint_symbols.GetSize(), 1)

# bar should have been strippped. We should not find it, or the
# stripping went wrong.
Expand Down
51 changes: 16 additions & 35 deletions lldb/unittests/Core/RichManglingContextTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,12 @@ using namespace lldb_private;
TEST(RichManglingContextTest, Basic) {
RichManglingContext RMC;
ConstString mangled("_ZN3foo3barEv");
EXPECT_TRUE(RMC.FromItaniumName(mangled));

EXPECT_TRUE(RMC.FromItaniumName(mangled));
EXPECT_FALSE(RMC.IsCtorOrDtor());

RMC.ParseFunctionDeclContextName();
EXPECT_EQ("foo", RMC.GetBufferRef());

RMC.ParseFunctionBaseName();
EXPECT_EQ("bar", RMC.GetBufferRef());

RMC.ParseFullName();
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
EXPECT_EQ("foo", RMC.ParseFunctionDeclContextName());
EXPECT_EQ("bar", RMC.ParseFunctionBaseName());
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
}

TEST(RichManglingContextTest, FromCxxMethodName) {
Expand All @@ -41,19 +35,12 @@ TEST(RichManglingContextTest, FromCxxMethodName) {
ConstString demangled("foo::bar()");
EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(demangled));

EXPECT_TRUE(ItaniumRMC.IsCtorOrDtor() == CxxMethodRMC.IsCtorOrDtor());

ItaniumRMC.ParseFunctionDeclContextName();
CxxMethodRMC.ParseFunctionDeclContextName();
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());

ItaniumRMC.ParseFunctionBaseName();
CxxMethodRMC.ParseFunctionBaseName();
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());

ItaniumRMC.ParseFullName();
CxxMethodRMC.ParseFullName();
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
EXPECT_EQ(ItaniumRMC.IsCtorOrDtor(), CxxMethodRMC.IsCtorOrDtor());
EXPECT_EQ(ItaniumRMC.ParseFunctionDeclContextName(),
CxxMethodRMC.ParseFunctionDeclContextName());
EXPECT_EQ(ItaniumRMC.ParseFunctionBaseName(),
CxxMethodRMC.ParseFunctionBaseName());
EXPECT_EQ(ItaniumRMC.ParseFullName(), CxxMethodRMC.ParseFullName());

// Construct with a random name.
{
Expand All @@ -68,8 +55,7 @@ TEST(RichManglingContextTest, FromCxxMethodName) {
ConstString("void * operator new(unsigned __int64)")));

// We expect its context is empty.
CxxMethodRMC.ParseFunctionDeclContextName();
EXPECT_TRUE(CxxMethodRMC.GetBufferRef().empty());
EXPECT_TRUE(CxxMethodRMC.ParseFunctionDeclContextName().empty());
}
}

Expand All @@ -79,16 +65,13 @@ TEST(RichManglingContextTest, SwitchProvider) {
llvm::StringRef demangled = "foo::bar()";

EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
RMC.ParseFullName();
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
EXPECT_EQ("foo::bar()", RMC.ParseFullName());

EXPECT_TRUE(RMC.FromCxxMethodName(ConstString(demangled)));
RMC.ParseFullName();
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
EXPECT_EQ("foo::bar()", RMC.ParseFullName());

EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
RMC.ParseFullName();
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
}

TEST(RichManglingContextTest, IPDRealloc) {
Expand Down Expand Up @@ -116,13 +99,11 @@ TEST(RichManglingContextTest, IPDRealloc) {

// Demangle the short one.
EXPECT_TRUE(RMC.FromItaniumName(ConstString(ShortMangled)));
RMC.ParseFullName();
const char *ShortDemangled = RMC.GetBufferRef().data();
const char *ShortDemangled = RMC.ParseFullName().data();

// Demangle the long one.
EXPECT_TRUE(RMC.FromItaniumName(ConstString(LongMangled)));
RMC.ParseFullName();
const char *LongDemangled = RMC.GetBufferRef().data();
const char *LongDemangled = RMC.ParseFullName().data();

// Make sure a new buffer was allocated or the default buffer was extended.
bool AllocatedNewBuffer = (ShortDemangled != LongDemangled);
Expand Down