1 //===-- Mangled.h -----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_CORE_MANGLED_H
10 #define LLDB_CORE_MANGLED_H
11 #if defined(__cplusplus)
12 
13 #include "lldb/lldb-enumerations.h"
14 #include "lldb/lldb-forward.h"
15 #include "lldb/lldb-types.h"
16 #include "lldb/Utility/ConstString.h"
17 #include "llvm/ADT/StringRef.h"
18 
19 #include <cstddef>
20 #include <memory>
21 
22 namespace lldb_private {
23 
24 /// \class Mangled Mangled.h "lldb/Core/Mangled.h"
25 /// A class that handles mangled names.
26 ///
27 /// Designed to handle mangled names. The demangled version of any names will
28 /// be computed when the demangled name is accessed through the Demangled()
29 /// acccessor. This class can also tokenize the demangled version of the name
30 /// for powerful searches. Functions and symbols could make instances of this
31 /// class for their mangled names. Uniqued string pools are used for the
32 /// mangled, demangled, and token string values to allow for faster
33 /// comparisons and for efficient memory use.
34 class Mangled {
35 public:
36   enum NamePreference {
37     ePreferMangled,
38     ePreferDemangled,
39     ePreferDemangledWithoutArguments
40   };
41 
42   enum ManglingScheme {
43     eManglingSchemeNone = 0,
44     eManglingSchemeMSVC,
45     eManglingSchemeItanium,
46     eManglingSchemeRustV0,
47     eManglingSchemeD
48   };
49 
50   /// Default constructor.
51   ///
52   /// Initialize with both mangled and demangled names empty.
53   Mangled() = default;
54 
55   /// Construct with name.
56   ///
57   /// Constructor with an optional string and auto-detect if \a name is
58   /// mangled or not.
59   ///
60   /// \param[in] name
61   ///     The already const name to copy into this object.
62   explicit Mangled(ConstString name);
63 
64   explicit Mangled(llvm::StringRef name);
65 
66   bool operator==(const Mangled &rhs) const {
67     return m_mangled == rhs.m_mangled &&
68            GetDemangledName() == rhs.GetDemangledName();
69   }
70 
71   bool operator!=(const Mangled &rhs) const {
72     return !(*this == rhs);
73   }
74 
75   /// Convert to bool operator.
76   ///
77   /// This allows code to check any Mangled objects to see if they contain
78   /// anything valid using code such as:
79   ///
80   /// \code
81   /// Mangled mangled(...);
82   /// if (mangled)
83   /// { ...
84   /// \endcode
85   ///
86   /// \return
87   ///     Returns \b true if either the mangled or unmangled name is set,
88   ///     \b false if the object has an empty mangled and unmangled name.
89   explicit operator bool() const;
90 
91   /// Clear the mangled and demangled values.
92   void Clear();
93 
94   /// Compare the mangled string values
95   ///
96   /// Compares the Mangled::GetName() string in \a lhs and \a rhs.
97   ///
98   /// \param[in] lhs
99   ///     A const reference to the Left Hand Side object to compare.
100   ///
101   /// \param[in] rhs
102   ///     A const reference to the Right Hand Side object to compare.
103   ///
104   /// \return
105   ///     -1 if \a lhs is less than \a rhs
106   ///     0 if \a lhs is equal to \a rhs
107   ///     1 if \a lhs is greater than \a rhs
108   static int Compare(const Mangled &lhs, const Mangled &rhs);
109 
110   /// Dump a description of this object to a Stream \a s.
111   ///
112   /// Dump a Mangled object to stream \a s. We don't force our demangled name
113   /// to be computed currently (we don't use the accessor).
114   ///
115   /// \param[in] s
116   ///     The stream to which to dump the object description.
117   void Dump(Stream *s) const;
118 
119   /// Dump a debug description of this object to a Stream \a s.
120   ///
121   /// \param[in] s
122   ///     The stream to which to dump the object description.
123   void DumpDebug(Stream *s) const;
124 
125   /// Demangled name get accessor.
126   ///
127   /// \return
128   ///     A const reference to the demangled name string object.
129   ConstString GetDemangledName() const;
130 
131   /// Display demangled name get accessor.
132   ///
133   /// \return
134   ///     A const reference to the display demangled name string object.
135   ConstString GetDisplayDemangledName() const;
136 
137   void SetDemangledName(ConstString name) { m_demangled = name; }
138 
139   void SetMangledName(ConstString name) { m_mangled = name; }
140 
141   /// Mangled name get accessor.
142   ///
143   /// \return
144   ///     A reference to the mangled name string object.
145   ConstString &GetMangledName() { return m_mangled; }
146 
147   /// Mangled name get accessor.
148   ///
149   /// \return
150   ///     A const reference to the mangled name string object.
151   ConstString GetMangledName() const { return m_mangled; }
152 
153   /// Best name get accessor.
154   ///
155   /// \param[in] preference
156   ///     Which name would you prefer to get?
157   ///
158   /// \return
159   ///     A const reference to the preferred name string object if this
160   ///     object has a valid name of that kind, else a const reference to the
161   ///     other name is returned.
162   ConstString GetName(NamePreference preference = ePreferDemangled) const;
163 
164   /// Check if "name" matches either the mangled or demangled name.
165   ///
166   /// \param[in] name
167   ///     A name to match against both strings.
168   ///
169   /// \return
170   ///     \b True if \a name matches either name, \b false otherwise.
171   bool NameMatches(ConstString name) const {
172     if (m_mangled == name)
173       return true;
174     return GetDemangledName() == name;
175   }
176   bool NameMatches(const RegularExpression &regex) const;
177 
178   /// Get the memory cost of this object.
179   ///
180   /// Return the size in bytes that this object takes in memory. This returns
181   /// the size in bytes of this object, not any shared string values it may
182   /// refer to.
183   ///
184   /// \return
185   ///     The number of bytes that this object occupies in memory.
186   size_t MemorySize() const;
187 
188   /// Set the string value in this object.
189   ///
190   /// If \a is_mangled is \b true, then the mangled named is set to \a name,
191   /// else the demangled name is set to \a name.
192   ///
193   /// \param[in] name
194   ///     The already const version of the name for this object.
195   ///
196   /// \param[in] is_mangled
197   ///     If \b true then \a name is a mangled name, if \b false then
198   ///     \a name is demangled.
199   void SetValue(ConstString name, bool is_mangled);
200 
201   /// Set the string value in this object.
202   ///
203   /// This version auto detects if the string is mangled by inspecting the
204   /// string value and looking for common mangling prefixes.
205   ///
206   /// \param[in] name
207   ///     The already const version of the name for this object.
208   void SetValue(ConstString name);
209 
210   /// Try to guess the language from the mangling.
211   ///
212   /// For a mangled name to have a language it must have both a mangled and a
213   /// demangled name and it can be guessed from the mangling what the language
214   /// is.  Note: this will return C++ for any language that uses Itanium ABI
215   /// mangling.
216   ///
217   /// Standard C function names will return eLanguageTypeUnknown because they
218   /// aren't mangled and it isn't clear what language the name represents
219   /// (there will be no mangled name).
220   ///
221   /// \return
222   ///     The language for the mangled/demangled name, eLanguageTypeUnknown
223   ///     if there is no mangled or demangled counterpart.
224   lldb::LanguageType GuessLanguage() const;
225 
226   /// Function signature for filtering mangled names.
227   using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
228 
229   /// Get rich mangling information. This is optimized for batch processing
230   /// while populating a name index. To get the pure demangled name string for
231   /// a single entity, use GetDemangledName() instead.
232   ///
233   /// For names that match the Itanium mangling scheme, this uses LLVM's
234   /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
235   /// parser currently.
236   ///
237   /// This function is thread-safe when used with different \a context
238   /// instances in different threads.
239   ///
240   /// \param[in] context
241   ///     The context for this function. A single instance can be stack-
242   ///     allocated in the caller's frame and used for multiple calls.
243   ///
244   /// \param[in] skip_mangled_name
245   ///     A filtering function for skipping entities based on name and mangling
246   ///     scheme. This can be null if unused.
247   ///
248   /// \return
249   ///     True on success, false otherwise.
250   bool GetRichManglingInfo(RichManglingContext &context,
251                            SkipMangledNameFn *skip_mangled_name);
252 
253   /// Try to identify the mangling scheme used.
254   /// \param[in] name
255   ///     The name we are attempting to identify the mangling scheme for.
256   ///
257   /// \return
258   ///     eManglingSchemeNone if no known mangling scheme could be identified
259   ///     for s, otherwise the enumerator for the mangling scheme detected.
260   static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
261 
262   /// Decode a serialized version of this object from data.
263   ///
264   /// \param data
265   ///   The decoder object that references the serialized data.
266   ///
267   /// \param offset_ptr
268   ///   A pointer that contains the offset from which the data will be decoded
269   ///   from that gets updated as data gets decoded.
270   ///
271   /// \param strtab
272   ///   All strings in cache files are put into string tables for efficiency
273   ///   and cache file size reduction. Strings are stored as uint32_t string
274   ///   table offsets in the cache data.
275   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
276               const StringTableReader &strtab);
277 
278   /// Encode this object into a data encoder object.
279   ///
280   /// This allows this object to be serialized to disk.
281   ///
282   /// \param encoder
283   ///   A data encoder object that serialized bytes will be encoded into.
284   ///
285   /// \param strtab
286   ///   All strings in cache files are put into string tables for efficiency
287   ///   and cache file size reduction. Strings are stored as uint32_t string
288   ///   table offsets in the cache data.
289   void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;
290 
291 private:
292   /// Mangled member variables.
293   ConstString m_mangled;           ///< The mangled version of the name
294   mutable ConstString m_demangled; ///< Mutable so we can get it on demand with
295                                    ///a const version of this object
296 };
297 
298 Stream &operator<<(Stream &s, const Mangled &obj);
299 
300 } // namespace lldb_private
301 
302 #endif // #if defined(__cplusplus)
303 #endif // LLDB_CORE_MANGLED_H
304