[Demangle] Add support for D types back referencing
This patch adds support for type back referencing, allowing demangling of compressed mangled symbols with repetitive types. Signed-off-by: Luís Ferreira <contact@lsferreira.net> Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D111419
This commit is contained in:
parent
bec08795db
commit
b21ea1c270
|
@ -105,6 +105,17 @@ private:
|
||||||
/// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
|
/// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
|
||||||
const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
|
const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
|
||||||
|
|
||||||
|
/// Extract and demangle backreferenced type from a given mangled symbol
|
||||||
|
/// and append it to the output string.
|
||||||
|
///
|
||||||
|
/// \param Mangled mangled symbol to be demangled.
|
||||||
|
///
|
||||||
|
/// \return the remaining string on success or nullptr on failure.
|
||||||
|
///
|
||||||
|
/// \see https://dlang.org/spec/abi.html#back_ref .
|
||||||
|
/// \see https://dlang.org/spec/abi.html#TypeBackRef .
|
||||||
|
const char *parseTypeBackref(const char *Mangled);
|
||||||
|
|
||||||
/// Check whether it is the beginning of a symbol name.
|
/// Check whether it is the beginning of a symbol name.
|
||||||
///
|
///
|
||||||
/// \param Mangled string to extract the symbol name.
|
/// \param Mangled string to extract the symbol name.
|
||||||
|
@ -162,6 +173,8 @@ private:
|
||||||
|
|
||||||
/// The string we are demangling.
|
/// The string we are demangling.
|
||||||
const char *Str;
|
const char *Str;
|
||||||
|
/// The index of the last back reference.
|
||||||
|
int LastBackref;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -276,6 +289,39 @@ const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
|
||||||
return Mangled;
|
return Mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *Demangler::parseTypeBackref(const char *Mangled) {
|
||||||
|
// A type back reference always points to a letter.
|
||||||
|
// TypeBackRef:
|
||||||
|
// Q NumberBackRef
|
||||||
|
// ^
|
||||||
|
const char *Backref;
|
||||||
|
|
||||||
|
// If we appear to be moving backwards through the mangle string, then
|
||||||
|
// bail as this may be a recursive back reference.
|
||||||
|
if (Mangled - Str >= LastBackref)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int SaveRefPos = LastBackref;
|
||||||
|
LastBackref = Mangled - Str;
|
||||||
|
|
||||||
|
// Get position of the back reference.
|
||||||
|
Mangled = decodeBackref(Mangled, Backref);
|
||||||
|
|
||||||
|
// Can't decode back reference.
|
||||||
|
if (Backref == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// TODO: Add support for function type back references.
|
||||||
|
Backref = parseType(Backref);
|
||||||
|
|
||||||
|
LastBackref = SaveRefPos;
|
||||||
|
|
||||||
|
if (Backref == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return Mangled;
|
||||||
|
}
|
||||||
|
|
||||||
bool Demangler::isSymbolName(const char *Mangled) {
|
bool Demangler::isSymbolName(const char *Mangled) {
|
||||||
long Ret;
|
long Ret;
|
||||||
const char *Qref = Mangled;
|
const char *Qref = Mangled;
|
||||||
|
@ -423,7 +469,10 @@ const char *Demangler::parseType(const char *Mangled) {
|
||||||
return Mangled;
|
return Mangled;
|
||||||
|
|
||||||
// TODO: Add support for the rest of the basic types.
|
// TODO: Add support for the rest of the basic types.
|
||||||
// TODO: Parse back referenced types.
|
|
||||||
|
// Back referenced type.
|
||||||
|
case 'Q':
|
||||||
|
return parseTypeBackref(Mangled);
|
||||||
|
|
||||||
default: // unhandled.
|
default: // unhandled.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -487,7 +536,8 @@ const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
|
||||||
return Mangled;
|
return Mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Demangler::Demangler(const char *Mangled) : Str(Mangled) {}
|
Demangler::Demangler(const char *Mangled)
|
||||||
|
: Str(Mangled), LastBackref(strlen(Mangled)) {}
|
||||||
|
|
||||||
const char *Demangler::parseMangle(OutputBuffer *Demangled) {
|
const char *Demangler::parseMangle(OutputBuffer *Demangled) {
|
||||||
return parseMangle(Demangled, this->Str);
|
return parseMangle(Demangled, this->Str);
|
||||||
|
|
|
@ -63,4 +63,13 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
std::make_pair("_D8demangle3ABCQa1ai",
|
std::make_pair("_D8demangle3ABCQa1ai",
|
||||||
nullptr), // invalid symbol back reference (recursive).
|
nullptr), // invalid symbol back reference (recursive).
|
||||||
std::make_pair("_D8demangleQDXXXXXXXXXXXXx",
|
std::make_pair("_D8demangleQDXXXXXXXXXXXXx",
|
||||||
nullptr))); // overflow back reference position.
|
nullptr), // overflow back reference position.
|
||||||
|
std::make_pair(
|
||||||
|
"_D8demangle4ABCi1aQd",
|
||||||
|
"demangle.ABCi.a"), // type back reference: `Qd` is a back reference
|
||||||
|
// for position 4, counting from `d` char, so
|
||||||
|
// decoding it points to `i`.
|
||||||
|
std::make_pair("_D8demangle3fooQXXXx",
|
||||||
|
nullptr), // invalid type back reference position.
|
||||||
|
std::make_pair("_D8demangle5recurQa",
|
||||||
|
nullptr))); // invalid type back reference (recursive).
|
||||||
|
|
Loading…
Reference in New Issue