forked from OSchip/llvm-project
Straight forward FastDemangle replacement in SubsPrimitiveParmItanium
Summary: Removing FastDemangle will greatly reduce maintenance efforts. This patch replaces the last point of use in LLDB. Semantics should be kept intact. Once this is agreed upon, we can: * Remove the FastDemangle sources * Add more features e.g. substitutions in template parameters, considering all variations, etc. Depends on LLVM patch https://reviews.llvm.org/D50586 Reviewers: erik.pilkington, friss, jingham, JDevlieghere Subscribers: kristof.beyls, chrib, lldb-commits Differential Revision: https://reviews.llvm.org/D50587 llvm-svn: 339583
This commit is contained in:
parent
4e34c65ffd
commit
5e6bd2f8a9
|
@ -21,6 +21,7 @@
|
|||
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
|
||||
// Project includes
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
|
@ -30,7 +31,6 @@
|
|||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
#include "lldb/DataFormatters/VectorType.h"
|
||||
#include "lldb/Utility/ConstString.h"
|
||||
#include "lldb/Utility/FastDemangle.h"
|
||||
#include "lldb/Utility/Log.h"
|
||||
#include "lldb/Utility/RegularExpression.h"
|
||||
|
||||
|
@ -278,48 +278,67 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
|
|||
static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
|
||||
llvm::StringRef search,
|
||||
llvm::StringRef replace) {
|
||||
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
|
||||
class PrimitiveParmSubs {
|
||||
llvm::StringRef mangled;
|
||||
llvm::StringRef search;
|
||||
llvm::StringRef replace;
|
||||
ptrdiff_t read_pos;
|
||||
std::string output;
|
||||
std::back_insert_iterator<std::string> writer;
|
||||
|
||||
const size_t max_len =
|
||||
mangled.size() + mangled.count(search) * replace.size() + 1;
|
||||
public:
|
||||
PrimitiveParmSubs(llvm::StringRef m, llvm::StringRef s, llvm::StringRef r)
|
||||
: mangled(m), search(s), replace(r), read_pos(0),
|
||||
writer(std::back_inserter(output)) {}
|
||||
|
||||
// Make a temporary buffer to fix up the mangled parameter types and copy the
|
||||
// original there
|
||||
std::string output_buf;
|
||||
output_buf.reserve(max_len);
|
||||
output_buf.insert(0, mangled.str());
|
||||
ptrdiff_t replaced_offset = 0;
|
||||
void Substitute(llvm::StringRef tail) {
|
||||
assert(tail.data() >= mangled.data() &&
|
||||
tail.data() < mangled.data() + mangled.size() &&
|
||||
"tail must point into range of mangled");
|
||||
|
||||
auto swap_parms_hook = [&](const char *parsee) {
|
||||
if (!parsee || !*parsee)
|
||||
return;
|
||||
if (tail.startswith(search)) {
|
||||
auto reader = mangled.begin() + read_pos;
|
||||
ptrdiff_t read_len = tail.data() - (mangled.data() + read_pos);
|
||||
|
||||
// Check whether we've found a substitutee
|
||||
llvm::StringRef s(parsee);
|
||||
if (s.startswith(search)) {
|
||||
// account for the case where a replacement is of a different length to
|
||||
// the original
|
||||
replaced_offset += replace.size() - search.size();
|
||||
// First write the unmatched part of the original. Then write the
|
||||
// replacement string. Finally skip the search string in the original.
|
||||
writer = std::copy(reader, reader + read_len, writer);
|
||||
writer = std::copy(replace.begin(), replace.end(), writer);
|
||||
read_pos += read_len + search.size();
|
||||
}
|
||||
}
|
||||
|
||||
ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
|
||||
output_buf.erase(replace_idx, search.size());
|
||||
output_buf.insert(replace_idx, replace.str());
|
||||
ConstString Finalize() {
|
||||
// If we did a substitution, write the remaining part of the original.
|
||||
if (read_pos > 0) {
|
||||
writer = std::copy(mangled.begin() + read_pos, mangled.end(), writer);
|
||||
read_pos = mangled.size();
|
||||
}
|
||||
|
||||
return ConstString(output);
|
||||
}
|
||||
|
||||
static void Callback(void *context, const char *match) {
|
||||
((PrimitiveParmSubs *)context)->Substitute(llvm::StringRef(match));
|
||||
}
|
||||
};
|
||||
|
||||
// FastDemangle will call our hook for each instance of a primitive type,
|
||||
// FastDemangle will call back for each instance of a primitive type,
|
||||
// allowing us to perform substitution
|
||||
char *const demangled =
|
||||
FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
|
||||
PrimitiveParmSubs parmSubs(mangled, search, replace);
|
||||
assert(mangled.data()[mangled.size()] == '\0' && "Expect C-String");
|
||||
bool err = llvm::itaniumFindTypesInMangledName(mangled.data(), &parmSubs,
|
||||
PrimitiveParmSubs::Callback);
|
||||
ConstString result = parmSubs.Finalize();
|
||||
|
||||
if (log)
|
||||
log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
|
||||
mangled.str().c_str(), demangled, output_buf.c_str(),
|
||||
FastDemangle(output_buf.c_str()));
|
||||
// FastDemangle malloc'd this string.
|
||||
free(demangled);
|
||||
if (Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)) {
|
||||
if (err)
|
||||
LLDB_LOG(log, "Failed to substitute mangling in {0}", mangled);
|
||||
else if (result)
|
||||
LLDB_LOG(log, "Substituted mangling {0} -> {1}", mangled, result);
|
||||
}
|
||||
|
||||
return output_buf == mangled ? ConstString() : ConstString(output_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
|
||||
|
|
|
@ -183,4 +183,5 @@ TEST(CPlusPlusLanguage, FindAlternateFunctionManglings) {
|
|||
EXPECT_THAT(FindAlternate("_ZN1A1fEa"), Contains("_ZN1A1fEc"));
|
||||
EXPECT_THAT(FindAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl"));
|
||||
EXPECT_THAT(FindAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm"));
|
||||
EXPECT_THAT(FindAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue