xref: /linux/tools/perf/util/demangle-rust-v0.h (revision 0939bd2fcf337243133b0271335a2838857c319f)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 // The contents of this file come from the Rust rustc-demangle library, hosted
4 // in the <https://github.com/rust-lang/rustc-demangle> repository, licensed
5 // under "Apache-2.0 OR MIT". For copyright details, see
6 // <https://github.com/rust-lang/rustc-demangle/blob/main/README.md>.
7 // Please note that the file should be kept as close as possible to upstream.
8 
9 #ifndef _H_DEMANGLE_V0_H
10 #define _H_DEMANGLE_V0_H
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 #include <stddef.h>
17 
18 #if defined(__GNUC__) || defined(__clang__)
19 #define DEMANGLE_NODISCARD __attribute__((warn_unused_result))
20 #else
21 #define DEMANGLE_NODISCARD
22 #endif
23 
24 typedef enum {
25     OverflowOk,
26     OverflowOverflow
27 } overflow_status;
28 
29 enum demangle_style {
30     DemangleStyleUnknown = 0,
31     DemangleStyleLegacy,
32     DemangleStyleV0,
33 };
34 
35 // Not using a union here to make the struct easier to copy-paste if needed.
36 struct demangle {
37     enum demangle_style style;
38     // points to the "mangled" part of the name,
39     // not including `ZN` or `R` prefixes.
40     const char *mangled;
41     size_t mangled_len;
42     // In DemangleStyleLegacy, is the number of path elements
43     size_t elements;
44     // while it's called "original", it will not contain `.llvm.9D1C9369@@16` suffixes
45     // that are to be ignored.
46     const char *original;
47     size_t original_len;
48     // Contains the part after the mangled name that is to be outputted,
49     // which can be `.exit.i.i` suffixes LLVM sometimes adds.
50     const char *suffix;
51     size_t suffix_len;
52 };
53 
54 // if the length of the output buffer is less than `output_len-OVERFLOW_MARGIN`,
55 // the demangler will return `OverflowOverflow` even if there is no overflow.
56 #define OVERFLOW_MARGIN 4
57 
58 /// Demangle a C string that refers to a Rust symbol and put the demangle intermediate result in `res`.
59 /// Beware that `res` contains references into `s`. If `s` is modified (or free'd) before calling
60 /// `rust_demangle_display_demangle` behavior is undefined.
61 ///
62 /// Use `rust_demangle_display_demangle` to convert it to an actual string.
63 void rust_demangle_demangle(const char *s, struct demangle *res);
64 
65 /// Write the string in a `struct demangle` into a buffer.
66 ///
67 /// Return `OverflowOk` if the output buffer was sufficiently big, `OverflowOverflow` if it wasn't.
68 /// This function is `O(n)` in the length of the input + *output* [$], but the demangled output of demangling a symbol can
69 /// be exponentially[$$] large, therefore it is recommended to have a sane bound (`rust-demangle`
70 /// uses 1,000,000 bytes) on `len`.
71 ///
72 /// `alternate`, if true, uses the less verbose alternate formatting (Rust `{:#}`) is used, which does not show
73 /// symbol hashes and types of constant ints.
74 ///
75 /// [$] It's `O(n * MAX_DEPTH)`, but `MAX_DEPTH` is a constant 300 and therefore it's `O(n)`
76 /// [$$] Technically, bounded by `O(n^MAX_DEPTH)`, but this is practically exponential.
77 DEMANGLE_NODISCARD overflow_status rust_demangle_display_demangle(struct demangle const *res, char *out, size_t len, bool alternate);
78 
79 /// Returns true if `res` refers to a known valid Rust demangling style, false if it's an unknown style.
80 bool rust_demangle_is_known(struct demangle *res);
81 
82 #undef DEMANGLE_NODISCARD
83 
84 #ifdef __cplusplus
85 }
86 #endif
87 
88 #endif
89