mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-08-31 09:45:24 +02:00
The old one was reverse engineered from a handful of symbols and got the shape of the format wrong - it required a digit right after the kind character, which most real symbols don't have. Measured against a PSP executable that shipped with its symbol table intact, it decoded 238 of 4662 mangled symbols, most of those incorrectly. Worked out properly from that binary, the format turns out to be: __0 <kind> <name...> <params> [_ <return type>] [<qualifier>] where the kind character (member function, free function, operator, data) is the only thing that says how many name components follow, since nothing separates the last one from the first parameter. Lengths are letters (A = 0, a = 26); "5" marks an enclosing namespace; "7...._" is a template argument list, with "4" plus a compact integer for a non-type argument and "9<index>A" for a back-reference to one; "T<index>" and "N<count><index>" repeat an earlier parameter; a trailing "K" is const and a trailing "T" is a static member function. Also handles __TID_/__T_ (the two halves of a class's RTTI) and __sti__ (a translation unit's static initializers). That decodes 4661 of the 4662. The one holdout is an STL symbol whose template argument is a reference to a member of another template. Declarator wrapping is shared with the CodeWarrior demangler now, so pointers to arrays come out as "short (**)[64]" in both. docs/SNSystemsMangling.md describes the format, marking what's inferred rather than attested. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SF5eS5QDNexLksRDeDZvwY
63 lines
3.0 KiB
C++
63 lines
3.0 KiB
C++
// Copyright (c) 2026- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
// Demangler for Itanium C++ ABI symbol names ("_Z..."), which is what GCC and Clang
|
|
// produce - and thus what the PSP toolchain produces. Handy for homebrew built from C++,
|
|
// where the ELF symbol table is otherwise unreadable.
|
|
//
|
|
// Handles the constructs that show up in practice, and simply fails on the rest (complex
|
|
// template expressions, mostly) rather than emitting something wrong.
|
|
|
|
// Returns false and leaves *out alone if this isn't a mangled name, or we can't parse it.
|
|
bool DemangleItanium(std::string_view mangled, std::string *out);
|
|
|
|
// The other two manglings that show up in PSP binaries, both from compilers older than the
|
|
// PSP SDK's GCC: Metrowerks CodeWarrior (a descendant of the AT&T cfront scheme) and SN
|
|
// Systems' SNC/ProDG. Both are much rougher than the Itanium demangler above - they aim to
|
|
// recover a readable, correctly qualified *name* and make a best effort at the parameter
|
|
// list, rather than to reproduce any particular tool's output byte for byte.
|
|
|
|
// A demangled symbol, kept split up so callers can use the parts. The Itanium demangler
|
|
// doesn't fill this in (it prints straight to a string); the two below do.
|
|
struct DemangledSymbol {
|
|
std::string name; // Qualified, no parameters: "ANIMEData::operator=".
|
|
std::string parameters; // What goes between the parens. Empty means "()".
|
|
std::string returnType; // Usually empty - only templates encode one. Also carries the
|
|
// "static" of an SN Systems static member function.
|
|
std::string qualifiers; // "const" and friends, printed after the parameter list.
|
|
bool isFunction = false; // False for data symbols, where there are no parens at all.
|
|
|
|
std::string ToString() const;
|
|
};
|
|
|
|
// Metrowerks CodeWarrior: "getDistance__6KzUtilFP7st_unitP7st_unit".
|
|
// See docs/CodeWarriorMangling.md.
|
|
bool DemangleCodeWarrior(std::string_view mangled, DemangledSymbol *out);
|
|
|
|
// SN Systems (SNC/ProDG): "__0fLCHeapMemoryFAlloci".
|
|
// See docs/SNSystemsMangling.md.
|
|
bool DemangleSNSystems(std::string_view mangled, DemangledSymbol *out);
|
|
|
|
// Convenience wrapper: tries all three manglings and returns the demangled name, or a
|
|
// copy of the input if it isn't something we can demangle.
|
|
std::string DemangleSymbolName(std::string_view name);
|