demangle 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. demangle/__init__.py +103 -0
  2. demangle/_signature.py +623 -0
  3. demangle/api.py +749 -0
  4. demangle/cli.py +521 -0
  5. demangle/core/__init__.py +20 -0
  6. demangle/core/ast.py +899 -0
  7. demangle/core/builder.py +160 -0
  8. demangle/core/cache.py +70 -0
  9. demangle/core/decorations.py +73 -0
  10. demangle/core/errors.py +75 -0
  11. demangle/core/limits.py +50 -0
  12. demangle/core/plugin.py +98 -0
  13. demangle/core/reader.py +247 -0
  14. demangle/core/registry.py +221 -0
  15. demangle/core/spelling.py +470 -0
  16. demangle/core/style.py +192 -0
  17. demangle/filter.py +226 -0
  18. demangle/py.typed +0 -0
  19. demangle/schemes/__init__.py +7 -0
  20. demangle/schemes/ada/__init__.py +175 -0
  21. demangle/schemes/ada/_parser.py +313 -0
  22. demangle/schemes/ada/nodes.py +89 -0
  23. demangle/schemes/codewarrior/__init__.py +215 -0
  24. demangle/schemes/codewarrior/_parser.py +583 -0
  25. demangle/schemes/codewarrior/nodes.py +131 -0
  26. demangle/schemes/codewarrior/options.py +33 -0
  27. demangle/schemes/d/__init__.py +118 -0
  28. demangle/schemes/d/_parser.py +1616 -0
  29. demangle/schemes/d/nodes.py +93 -0
  30. demangle/schemes/delphi/__init__.py +79 -0
  31. demangle/schemes/delphi/_parser.py +897 -0
  32. demangle/schemes/delphi/nodes.py +128 -0
  33. demangle/schemes/gnuv2/__init__.py +325 -0
  34. demangle/schemes/gnuv2/_parser.py +2487 -0
  35. demangle/schemes/gnuv2/nodes.py +145 -0
  36. demangle/schemes/gnuv2/options.py +54 -0
  37. demangle/schemes/go/__init__.py +127 -0
  38. demangle/schemes/go/_parser.py +278 -0
  39. demangle/schemes/go/nodes.py +138 -0
  40. demangle/schemes/itanium/__init__.py +61 -0
  41. demangle/schemes/itanium/options.py +332 -0
  42. demangle/schemes/itanium/parser.py +5456 -0
  43. demangle/schemes/itanium/substitutions.py +362 -0
  44. demangle/schemes/itanium/tables.py +376 -0
  45. demangle/schemes/jni/__init__.py +96 -0
  46. demangle/schemes/jni/_parser.py +226 -0
  47. demangle/schemes/jni/nodes.py +91 -0
  48. demangle/schemes/msvc/__init__.py +291 -0
  49. demangle/schemes/msvc/_parser.py +2024 -0
  50. demangle/schemes/msvc/nodes.py +450 -0
  51. demangle/schemes/msvc/options.py +140 -0
  52. demangle/schemes/nim/__init__.py +81 -0
  53. demangle/schemes/nim/_parser.py +470 -0
  54. demangle/schemes/nim/nodes.py +81 -0
  55. demangle/schemes/objc/__init__.py +119 -0
  56. demangle/schemes/objc/_parser.py +823 -0
  57. demangle/schemes/objc/nodes.py +122 -0
  58. demangle/schemes/pascal/__init__.py +85 -0
  59. demangle/schemes/pascal/_parser.py +428 -0
  60. demangle/schemes/pascal/nodes.py +131 -0
  61. demangle/schemes/rust/__init__.py +244 -0
  62. demangle/schemes/rust/_dispatch.py +85 -0
  63. demangle/schemes/rust/_legacy.py +266 -0
  64. demangle/schemes/rust/_v0.py +1867 -0
  65. demangle/schemes/rust/nodes.py +194 -0
  66. demangle/schemes/rust/options.py +36 -0
  67. demangle/schemes/swift/__init__.py +247 -0
  68. demangle/schemes/swift/_demangler.py +3224 -0
  69. demangle/schemes/swift/_node.py +644 -0
  70. demangle/schemes/swift/_old_demangler.py +1525 -0
  71. demangle/schemes/swift/_printer.py +2737 -0
  72. demangle/schemes/swift/_punycode.py +116 -0
  73. demangle/schemes/swift/nodes.py +143 -0
  74. demangle/schemes/swift/options.py +155 -0
  75. demangle/schemes/swift/resolve.py +577 -0
  76. demangle/schemes/swift/symbolic.py +201 -0
  77. demangle-0.3.0.dist-info/METADATA +382 -0
  78. demangle-0.3.0.dist-info/RECORD +82 -0
  79. demangle-0.3.0.dist-info/WHEEL +4 -0
  80. demangle-0.3.0.dist-info/entry_points.txt +2 -0
  81. demangle-0.3.0.dist-info/licenses/LICENSE +21 -0
  82. demangle-0.3.0.dist-info/licenses/NOTICE +178 -0
@@ -0,0 +1,194 @@
1
+ """The Rust symbol tree.
2
+
3
+ Rust's spelling has no declarator syntax at all. A C++ type wraps the name it declares
4
+ -- `int (*)(char)` -- which is why `core/spelling.py` carries a left/right pair and why
5
+ MSVC needs a renderer of its own. Rust writes `&mut [u8; 4]` strictly left to right, and
6
+ a path is just its components joined by `::`. So the structure worth recovering here is
7
+ not a declarator shape: it is *which part of the name is which* -- the crate, the module
8
+ path, the generic arguments, the trait an impl is for, the closure disambiguator.
9
+
10
+ Every node holds `parts`: a tuple of plain strings and child nodes, in output order.
11
+ Rendering concatenates them. That is deliberate and is the whole correctness argument
12
+ for this module -- the printer in `_v0.py` emits one linear stream of fragments whether
13
+ it is building text or a tree, so a tree's rendering cannot drift from the text path.
14
+ It is not that the two are tested to agree; there is only one stream, and the tree is
15
+ that stream with the boundaries remembered.
16
+
17
+ Kinds are shared with the other schemes where they mean the same thing, so a tool can
18
+ ask any tree for its `name` or `template` nodes without knowing which language produced
19
+ it. `impl` and `namespace` are Rust's own: nothing in the C-family schemes means either.
20
+ """
21
+
22
+ from ...core.ast import Node, rendered
23
+
24
+ __all__ = [
25
+ "Generics",
26
+ "Impl",
27
+ "Namespace",
28
+ "Path",
29
+ "RustName",
30
+ "Symbol",
31
+ "Type",
32
+ "Value",
33
+ "render",
34
+ ]
35
+
36
+
37
+ def render(part):
38
+ """Text for a part, which is either a plain fragment or a subtree."""
39
+ return part if isinstance(part, str) else part.render()
40
+
41
+
42
+ class _Rust(Node):
43
+ """A node whose spelling is the fragments it was built from, in order.
44
+
45
+ `build()` hands a foreign builder finished text. Re-emitting the shape through the
46
+ shared builder would spell Rust's `&mut T` as C++'s `T&`, and a demangler that
47
+ answers two different things for one symbol is worse than one that answers text.
48
+ Inspecting the tree is unaffected -- that is what the structure is for.
49
+ """
50
+
51
+ __slots__ = ("parts",)
52
+
53
+ def __init__(self, parts):
54
+ self.parts = tuple(parts)
55
+ total = 0
56
+ for part in self.parts:
57
+ total += len(part) if isinstance(part, str) else part.size
58
+ self.size = total
59
+
60
+ def children(self):
61
+ return tuple(p for p in self.parts if isinstance(p, Node))
62
+
63
+ def render(self):
64
+ return "".join(render(p) for p in self.parts)
65
+
66
+ def spell(self, declarator="", style=None):
67
+ # `declarator` and `style` are accepted to match `Node.spell` and ignored. Rust
68
+ # has no declarator position to place one in, and the output styles exist only
69
+ # where llvm-cxxfilt and GNU c++filt disagree about C++.
70
+ return rendered(self.render)
71
+
72
+ def build(self, builder):
73
+ return builder.raw(self.render())
74
+
75
+ @property
76
+ def text(self):
77
+ """The rendered text, so a caller can read a node without spelling a whole tree."""
78
+ return self.render()
79
+
80
+
81
+ class RustName(_Rust):
82
+ """A single identifier: a crate name, a module, a function, a field.
83
+
84
+ Named `RustName` rather than `Name` because `core.ast.Name` already exists and means
85
+ the same thing to a consumer -- hence the shared `kind` -- but spells itself through
86
+ the shared builder, which is not this scheme's speller.
87
+ """
88
+
89
+ __slots__ = ()
90
+ kind = "name"
91
+
92
+
93
+ class Path(_Rust):
94
+ """A path: `std::collections::HashMap`, or a crate root on its own."""
95
+
96
+ __slots__ = ()
97
+ kind = "path"
98
+
99
+
100
+ class Namespace(_Rust):
101
+ """A compiler-generated path component: `{closure#0}`, `{shim:vtable#0}`.
102
+
103
+ `tag` is the namespace letter from the mangling -- `C` for a closure, `S` for a
104
+ shim, or a vendor's own -- and `disambiguator` separates several in one scope.
105
+ """
106
+
107
+ __slots__ = ("disambiguator", "tag")
108
+ kind = "namespace"
109
+
110
+ def __init__(self, parts, tag, disambiguator):
111
+ super().__init__(parts)
112
+ self.tag = tag
113
+ self.disambiguator = disambiguator
114
+
115
+
116
+ class Impl(_Rust):
117
+ """An inherent or trait impl: `<Foo>`, `<Foo as Bar>`.
118
+
119
+ `trait` is the trait's subtree for a trait impl and None for an inherent one, so a
120
+ caller can ask what a method implements without matching on rendered text.
121
+ """
122
+
123
+ __slots__ = ("self_type", "trait")
124
+ kind = "impl"
125
+
126
+ def __init__(self, parts, self_type, trait):
127
+ super().__init__(parts)
128
+ self.self_type = self_type
129
+ self.trait = trait
130
+
131
+
132
+ class Generics(_Rust):
133
+ """A generic argument application, `Vec<u8>` or `Foo::<T>`.
134
+
135
+ `base` is what is being applied to and `arguments` are the arguments themselves,
136
+ both also present in `parts` -- the fields name them, `parts` orders them.
137
+ """
138
+
139
+ __slots__ = ("arguments", "base")
140
+ kind = "template"
141
+
142
+ def __init__(self, parts, base, arguments):
143
+ super().__init__(parts)
144
+ self.base = base
145
+ self.arguments = tuple(arguments)
146
+
147
+
148
+ class Type(_Rust):
149
+ """A type. `form` says which shape: `reference`, `pointer`, `array`, `slice`,
150
+ `tuple`, `dyn`, `fn`, `basic`, `path`.
151
+
152
+ One class rather than nine because nothing walks these structurally -- a caller
153
+ asking "is this a reference" wants a field to test, and `kind` stays `type` so the
154
+ common query finds every one of them.
155
+ """
156
+
157
+ __slots__ = ("form",)
158
+ kind = "type"
159
+
160
+ def __init__(self, parts, form):
161
+ super().__init__(parts)
162
+ self.form = form
163
+
164
+
165
+ class Value(_Rust):
166
+ """A const generic argument: an integer, a `bool`, a `char`, a structural const."""
167
+
168
+ __slots__ = ("form",)
169
+ kind = "literal"
170
+
171
+ def __init__(self, parts, form):
172
+ super().__init__(parts)
173
+ self.form = form
174
+
175
+
176
+ class Symbol(_Rust):
177
+ """A whole Rust symbol.
178
+
179
+ `hash` is the value of the legacy scheme's trailing `17h<16 hex>` component -- the
180
+ sixteen digits, without the `h` marker or the length prefix. The mangling carries it
181
+ and the spelling drops it; it is recorded because it is the only thing telling two
182
+ monomorphisations of one generic function apart. `suffix` is whatever followed
183
+ the mangled name -- an LLVM `.llvm.<hash>` from the internaliser, a `.0` from a
184
+ promoted constant.
185
+ """
186
+
187
+ __slots__ = ("hash", "suffix", "vendor")
188
+ kind = "symbol"
189
+
190
+ def __init__(self, parts, hash=None, suffix="", vendor=""):
191
+ super().__init__(parts)
192
+ self.hash = hash
193
+ self.suffix = suffix
194
+ self.vendor = vendor
@@ -0,0 +1,36 @@
1
+ """Whether to spell the hash rustc writes into a symbol to keep it unique.
2
+
3
+ Both Rust manglings carry one and neither spells it by default, because it is noise to a
4
+ reader: `core::fmt::write` says what the function is and
5
+ `core::fmt::write::h05af221e174051e9` says the same thing with a machine's bookkeeping
6
+ after it. But it is the *only* thing telling two monomorphisations of one generic
7
+ function apart, so a caller symbolising a profile or diffing two builds needs it.
8
+
9
+ This is rustc-demangle's own choice, spelled as a formatting flag rather than an option:
10
+ `{}` on its `Demangle` prints the hash and `{:#}` suppresses it. `rustfilt` prints the
11
+ suppressed form, and so does this by default. What the flag reaches differs between the
12
+ two manglings, which is why it is one option and not two:
13
+
14
+ * legacy appends the path's trailing `17h<16 hex>` component -- `a::f::h05af221e174051e9`;
15
+ * v0 prints the crate's *disambiguator* wherever a crate root is spelled --
16
+ `features[9f05e0465351d495]::apply_hrtb`, at every occurrence rather than the first.
17
+ """
18
+
19
+ from dataclasses import dataclass
20
+
21
+ __all__ = ["DEFAULT_OPTIONS", "RustOptions"]
22
+
23
+
24
+ @dataclass(frozen=True, slots=True)
25
+ class RustOptions:
26
+ """How much of a Rust name to spell."""
27
+
28
+ keep_hash: bool = False
29
+ """Spell the disambiguating hash rather than dropping it.
30
+
31
+ Off by default, which is what `rustfilt` and every corpus here is scored against.
32
+ """
33
+
34
+
35
+ #: What the shipped styles use.
36
+ DEFAULT_OPTIONS = RustOptions()
@@ -0,0 +1,247 @@
1
+ """Swift mangled names.
2
+
3
+ A port of the Swift compiler's own demangler -- `lib/Demangling/Demangler.cpp` and
4
+ `lib/Demangling/NodePrinter.cpp` -- because nothing smaller is enough. Swift's mangling
5
+ is postfix and compresses aggressively against three tables that span a whole name, so a
6
+ symbol cannot be read a piece at a time, and how a piece is *spelled* depends on where it
7
+ sits in the tree. `_demangler.py` and `_printer.py` are those two files; `nodes.py`
8
+ records the structure of the printer's traversal.
9
+
10
+ Conformance is exact against `swift-demangle` from the 5.10.1 toolchain:
11
+
12
+ * every `$s` symbol in the shipped Swift runtime and Foundation -- 48,368 of them --
13
+ spelled identically, with nothing refused;
14
+ * all 376 cases in the compiler's own `test/Demangle/Inputs/manglings.txt`, which is a
15
+ much harder set: SIL function types, function-signature specialisations, key paths,
16
+ autodiff thunks, macro expansions, and the Swift 3 mangling.
17
+
18
+ The Swift 3 mangling -- `_T` followed by anything but `0` -- is a different grammar with
19
+ its own demangler in the compiler, and `_old_demangler.py` is a port of that one. It
20
+ still matters: the ObjC runtime holds a Swift class's name in that form, so it turns up
21
+ in any Apple binary with interop in it. It builds the same tree, so the printer spells it
22
+ with no idea which mangling it came from, and all 247 of the compiler's own Swift 3 test
23
+ cases come out exactly.
24
+ """
25
+
26
+ from ...core.ast import Node
27
+ from ...core.errors import LimitExceeded, NotMangledError, ParseError
28
+ from ...core.limits import DEFAULT_LIMITS
29
+ from ...core.plugin import LanguagePlugin
30
+ from ...core.registry import register
31
+ from . import nodes
32
+ from ._demangler import MANGLING_PREFIXES, async_main_entry_point_length, demangle_symbol, demangle_type
33
+ from ._old_demangler import demangle_old_symbol
34
+ from ._printer import print_root
35
+ from .options import DEFAULT_OPTIONS, SIMPLIFIED_OPTIONS, SwiftOptions
36
+ from .resolve import ContextResolver, Image, elf_image, macho_image
37
+ from .symbolic import SymbolicReference, end_of_name, scan
38
+
39
+ #: What each builder class answered to `_wants_structure`, asked once per class.
40
+ _STRUCTURED = {}
41
+
42
+
43
+ def detect(name):
44
+ """One of the prefixes either mangling uses.
45
+
46
+ `_T` covers Swift 3 as well as `_T0`; the two are different grammars and
47
+ `demangle_symbol` dispatches between them, but from the outside they are one scheme.
48
+ """
49
+ if not name:
50
+ return False
51
+ if name.startswith("__"):
52
+ # The Mach-O form: one underscore more than the compiler wrote, which
53
+ # `swift-demangle` takes off before reading. `__$s` is `_$s`, itself a prefix.
54
+ name = name[1:]
55
+ if async_main_entry_point_length(name):
56
+ # `async_Main`, the one Swift symbol with no prefix: the entry point of an
57
+ # `async` `@main`, which the reference's `isSwiftSymbol` claims by name.
58
+ return True
59
+ return name.startswith(MANGLING_PREFIXES) or name.startswith("_T")
60
+
61
+
62
+ def _wants_structure(builder):
63
+ cls = type(builder)
64
+ answer = _STRUCTURED.get(cls)
65
+ if answer is None:
66
+ answer = _STRUCTURED[cls] = isinstance(builder.raw(""), Node)
67
+ return answer
68
+
69
+
70
+ def parse(mangled, builder, limits=DEFAULT_LIMITS, options=DEFAULT_OPTIONS):
71
+ """Parse a Swift mangled name into `builder`."""
72
+ if not mangled:
73
+ raise NotMangledError(mangled, "empty name")
74
+ if not detect(mangled):
75
+ raise NotMangledError(mangled, "not a Swift mangled name")
76
+ if len(mangled) > limits.max_input:
77
+ raise LimitExceeded(mangled, "input length", limits.max_input)
78
+
79
+ # A Mach-O symbol table carries one more leading underscore than the compiler
80
+ # wrote, so `__T04demo5PointVMn`, `__$s...` and `__TtC...` are `_T0...`, `_$s...`
81
+ # and `_TtC...` -- and `swift-demangle` strips exactly one underscore from a name
82
+ # that opens with two before reading it. `_$s` needs no such help: the compiler's
83
+ # own prefix for a Mach-O symbol is listed as a prefix in its own right.
84
+ name = mangled[1:] if mangled.startswith("__") else mangled
85
+ try:
86
+ root = demangle_symbol(name)
87
+ except RecursionError as error:
88
+ raise LimitExceeded(mangled, "recursion depth", limits.max_depth) from error
89
+ return _finish(mangled, root, builder, limits, options)
90
+
91
+
92
+ def parse_type(mangled, builder, limits=DEFAULT_LIMITS, options=DEFAULT_OPTIONS):
93
+ """Parse a Swift *type* mangling -- `Si`, `SaySiG` -- rather than a whole symbol.
94
+
95
+ `Demangler::demangleType` rather than `demangleSymbol`, and what a metadata typeref
96
+ holds: a type mangling carries none of the `$s` a symbol opens with, so nothing about
97
+ it says it is Swift, and it is only readable because the caller said so.
98
+
99
+ A type mangling that reads as nothing is refused rather than spelled. The reference
100
+ hands back the whole input wrapped in a `Suffix` node when nothing at all parsed,
101
+ which prints as `with unmangled suffix "..."` -- true, but not a demangling of
102
+ anything, so it comes back here as the `ParseError` it is.
103
+ """
104
+ if not mangled:
105
+ raise NotMangledError(mangled, "empty type")
106
+ if len(mangled) > limits.max_input:
107
+ raise LimitExceeded(mangled, "input length", limits.max_input)
108
+ try:
109
+ root = demangle_type(mangled)
110
+ except RecursionError as error:
111
+ raise LimitExceeded(mangled, "recursion depth", limits.max_depth) from error
112
+ if root is not None and root.kind == "Suffix":
113
+ raise ParseError(mangled, None, "not a type this reads")
114
+ return _finish(mangled, root, builder, limits, options)
115
+
116
+
117
+ def _finish(mangled, root, builder, limits, options=DEFAULT_OPTIONS):
118
+ """Turn a reference-demangler root into what `builder` collects, or refuse it."""
119
+ if root is None:
120
+ raise ParseError(mangled, None, "not a name this reads")
121
+ options = options or DEFAULT_OPTIONS
122
+
123
+ if _wants_structure(builder):
124
+ tree = nodes.build(root, options)
125
+ if tree is None:
126
+ raise ParseError(mangled, None, "not a name this reads")
127
+ if tree.size > limits.max_output:
128
+ raise LimitExceeded(mangled, "output length", limits.max_output)
129
+ return tree
130
+
131
+ text = print_root(root, options)
132
+ if not text:
133
+ raise ParseError(mangled, None, "not a name this reads")
134
+ if len(text) > limits.max_output:
135
+ raise LimitExceeded(mangled, "output length", limits.max_output)
136
+ return builder.raw(text)
137
+
138
+
139
+ PLUGIN = LanguagePlugin(
140
+ name="swift",
141
+ node_kinds=(
142
+ "extension",
143
+ "function",
144
+ "generics",
145
+ "module",
146
+ "name",
147
+ "symbol",
148
+ "template",
149
+ "type",
150
+ "variable",
151
+ ),
152
+ detect=detect,
153
+ parse=parse,
154
+ parse_type=parse_type,
155
+ description="Swift symbol mangling",
156
+ options_type=SwiftOptions,
157
+ aliases=(),
158
+ # `priority` is ascending: *lower is offered first*. After D, before Rust. `$s` and
159
+ # `_T0` collide with nothing; `_$S` collides with Free Pascal, which is offered
160
+ # earlier and wins those.
161
+ # `$s`, `_$s`, `$S`, `_$S`, `_T0`, `_Tt` and `@__swiftmacro_` -- and `async_Main`,
162
+ # the entry point of an `async` `@main`, which is the one Swift symbol with no
163
+ # prefix at all.
164
+ first_characters="$_@a",
165
+ priority=45,
166
+ )
167
+
168
+ register(PLUGIN)
169
+
170
+
171
+ def demangle_symbolic(name, resolver=None, *, whole_symbol=None):
172
+ """Read a mangled name that may hold symbolic references, and spell it.
173
+
174
+ `name` is `bytes`, not `str`, because a name holding a symbolic reference is not
175
+ text: the reference's four-byte offset is arbitrary bytes. This is the entry a
176
+ metadata typeref takes, and the only one that can take it.
177
+
178
+ `resolver` is called with `(reference, offset-of-its-offset-field-within-name)` and
179
+ returns a *mangled fragment* naming what the reference points at, or None to decline.
180
+ `resolve.ContextResolver` is one, over an `Image`; a caller with a debugger or a
181
+ memory dump writes its own. With no resolver at all, a name holding a reference is
182
+ refused -- which is what the reference demangler does, and better than inventing a
183
+ name for something the bytes do not carry.
184
+
185
+ `whole_symbol` says whether to read the name as a whole symbol or as a type. Left
186
+ None it is decided by the mangling prefix, which is what tells the two apart: a
187
+ symbol carries `$s` or `_T`, a typeref carries nothing.
188
+
189
+ Returns the spelling, or None if the name could not be read.
190
+ """
191
+ if isinstance(name, str):
192
+ raise TypeError("demangle_symbolic reads bytes; a name holding a reference is not text")
193
+ # latin-1 maps every byte to the code point of the same value and back again, so the
194
+ # grammar can be read a character at a time without the bytes ever being interpreted
195
+ # as text. Swift spells a non-ASCII identifier in punycode, so nothing here is lost.
196
+ text = name.decode("latin-1")
197
+ if whole_symbol is None:
198
+ whole_symbol = detect(text)
199
+ try:
200
+ root = demangle_symbol(text, resolver) if whole_symbol else demangle_type(text, resolver)
201
+ except RecursionError:
202
+ return None
203
+ if root is None:
204
+ return None
205
+ if root.kind == "Suffix":
206
+ # `demangleType` hands back the whole input as a `Suffix` node when nothing at
207
+ # all parsed. That is the reference saying it could not read the name, and it
208
+ # comes back as None here rather than as the words `with unmangled suffix`
209
+ # wrapped around the bytes -- which is not a demangling of anything.
210
+ return None
211
+ spelled = print_root(root)
212
+ return spelled or None
213
+
214
+
215
+ def typerefs(blob):
216
+ """Split a metadata blob of NUL-terminated mangled names into those names.
217
+
218
+ Not `blob.split(b"\0")`: a symbolic reference's offset is arbitrary bytes and very
219
+ often holds a zero, so splitting cuts names in half. See `symbolic.end_of_name`.
220
+ """
221
+ from .symbolic import names
222
+
223
+ return names(blob)
224
+
225
+
226
+ __all__ = [
227
+ "DEFAULT_OPTIONS",
228
+ "PLUGIN",
229
+ "SIMPLIFIED_OPTIONS",
230
+ "ContextResolver",
231
+ "Image",
232
+ "SwiftOptions",
233
+ "SymbolicReference",
234
+ "demangle_old_symbol",
235
+ "demangle_symbol",
236
+ "demangle_symbolic",
237
+ "demangle_type",
238
+ "detect",
239
+ "elf_image",
240
+ "end_of_name",
241
+ "macho_image",
242
+ "parse",
243
+ "parse_type",
244
+ "print_root",
245
+ "scan",
246
+ "typerefs",
247
+ ]