diff --git a/demumble.cc b/demumble.cc index bea3163..21e2902 100644 --- a/demumble.cc +++ b/demumble.cc @@ -5,6 +5,7 @@ #include #include "llvm/Demangle/Demangle.h" +#include "swift/Demangling/Demangle.h" const char kDemumbleVersion[] = "1.2.3.git"; @@ -33,6 +34,14 @@ static void print_demangled(const char* format, std::string_view s, } else if (char* ms = llvm::microsoftDemangle(s, n_used, NULL)) { printf(format, ms, (int)s.size(), s.data()); free(ms); + } else if (swift::Demangle::isSwiftSymbol(s)) { + swift::Demangle::DemangleOptions options; + options.SynthesizeSugarOnTypes = true; + std::string swift = swift::Demangle::demangleSymbolAsString(s, options); + if (swift == s) + printf("%.*s", (int)s.size(), s.data()); // Not a mangled name + else + printf(format, swift.c_str(), (int)s.size(), s.data()); } else { printf("%.*s", (int)s.size(), s.data()); } @@ -49,6 +58,12 @@ static bool is_mangle_char_rust(char c) { (c >= '0' && c <= '9') || c == '_'; } +static bool is_mangle_char_swift(char c) { + // https://github.com/swiftlang/swift/blob/main/docs/ABI/Mangling.rst + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '_' || c == '$'; +} + static bool is_mangle_char_win(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || strchr("?_@$", c); @@ -68,6 +83,18 @@ static bool is_plausible_rust_prefix(char* s) { return s[0] == '_' && s[1] == 'R'; } +static bool is_plausible_swift_prefix(char* s) { + // https://github.com/swiftlang/swift/blob/main/docs/ABI/Mangling.rst + // But also swift/test/Demangle/Inputs/manglings.txt, which has + // _Tt, _TF etc as prefix. + + // FIXME: This is missing prefix `@__swiftmacro_`. + return + (s[0] == '$' && s[1] == 's') || + (s[0] == '_' && s[1] == 'T') || + (s[0] == '$' && s[1] == 'S'); +} + static char buf[8192]; int main(int argc, char* argv[]) { enum { kPrintAll, kPrintMatching } print_mode = kPrintAll; @@ -119,7 +146,7 @@ int main(int argc, char* argv[]) { char* end = cur + strlen(cur); while (cur != end) { - size_t offset_to_possible_symbol = strcspn(cur, "_?"); + size_t offset_to_possible_symbol = strcspn(cur, "_?$"); if (print_mode == kPrintAll) printf("%.*s", static_cast(offset_to_possible_symbol), cur); else if (need_separator) @@ -139,6 +166,9 @@ int main(int argc, char* argv[]) { else if (is_plausible_rust_prefix(cur)) while (cur + n_sym != end && is_mangle_char_rust(cur[n_sym])) ++n_sym; + else if (is_plausible_swift_prefix(cur)) + while (cur + n_sym != end && is_mangle_char_swift(cur[n_sym])) + ++n_sym; else { if (print_mode == kPrintAll) printf("_"); diff --git a/demumble_test.py b/demumble_test.py index c7d6242..6ed3533 100755 --- a/demumble_test.py +++ b/demumble_test.py @@ -9,6 +9,10 @@ 'std::mem::align_of::\nmylib::foo::bar\n'), ('demumble < _RINvNtC3std3mem8align_ofdE _RNvNvC5mylib3foo3bar', 'std::mem::align_of::\nmylib::foo::bar\n'), + ('demumble _TtP3foo3bar_', 'foo.bar\n'), + ('demumble < _TtP3foo3bar_', 'foo.bar\n'), + ('demumble $sSS5countSivg', 'Swift.String.count.getter : Swift.Int\n'), + ('demumble < $sSS5countSivg', 'Swift.String.count.getter : Swift.Int\n'), ('demumble ?Fxi@@YAHP6AHH@Z@Z', 'int __cdecl Fxi(int (__cdecl *)(int))\n'), ('demumble ??0S@@QEAA@$$QEAU0@@Z', 'public: __cdecl S::S(struct S &&)\n'), ('demumble ??_C@_02PCEFGMJL@hi?$AA@', '"hi"\n'),