Skip to content

Commit

Permalink
feat: add swift demangler (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
LouisBrunner committed Oct 25, 2024
1 parent 0504378 commit 9d2d4e3
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,7 @@ configure~
/memcheck/tests/deep_templates
/memcheck/tests/demangle
/memcheck/tests/demangle-rust
/memcheck/tests/demangle-swift
/memcheck/tests/describe-block
/memcheck/tests/descr_belowsp
/memcheck/tests/dir
Expand Down
4 changes: 3 additions & 1 deletion auxprogs/update-demangler
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -e
#---------------------------------------------------------------------
# This quick and dirty script assists in updating the C++ demangler
# machinery in coregrind/m_demangle.
# The script will check out
# The script will check out
# - old and new revisions of the C++ demangler related files from GCC's trunk
# - m_demangle from valgrind's trunk.
# It will assemble
Expand Down Expand Up @@ -63,6 +63,7 @@ cp ../gcc/libiberty/cplus-dem.c .
cp ../gcc/libiberty/dyn-string.c .
cp ../gcc/libiberty/d-demangle.c .
cp ../gcc/libiberty/rust-demangle.c .
cp ../gcc/libiberty/swift-demangle.c .
cp ../gcc/libiberty/safe-ctype.c .
cd ..

Expand All @@ -85,6 +86,7 @@ cp ../gcc/libiberty/cplus-dem.c .
cp ../gcc/libiberty/dyn-string.c .
cp ../gcc/libiberty/d-demangle.c .
cp ../gcc/libiberty/rust-demangle.c .
cp ../gcc/libiberty/swift-demangle.c .
cp ../gcc/libiberty/safe-ctype.c .
cd ..

Expand Down
1 change: 1 addition & 0 deletions coregrind/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ COREGRIND_SOURCES_COMMON = \
m_demangle/dyn-string.c \
m_demangle/d-demangle.c \
m_demangle/rust-demangle.c \
m_demangle/swift-demangle.c \
m_demangle/safe-ctype.c \
m_dispatch/dispatch-x86-linux.S \
m_dispatch/dispatch-amd64-linux.S \
Expand Down
15 changes: 11 additions & 4 deletions coregrind/m_demangle/cplus-dem.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const struct demangler_engine libiberty_demanglers[] =
enum demangling_styles
cplus_demangle_set_style (enum demangling_styles style)
{
const struct demangler_engine *demangler = libiberty_demanglers;
const struct demangler_engine *demangler = libiberty_demanglers;

for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (style == demangler->demangling_style)
Expand All @@ -145,7 +145,7 @@ cplus_demangle_set_style (enum demangling_styles style)
enum demangling_styles
cplus_demangle_name_to_style (const char *name)
{
const struct demangler_engine *demangler = libiberty_demanglers;
const struct demangler_engine *demangler = libiberty_demanglers;

for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (strcmp (name, demangler->demangling_style_name) == 0)
Expand Down Expand Up @@ -211,6 +211,13 @@ ML_(cplus_demangle) (const char *mangled, int options)
return ret;
}

if (SWIFT_DEMANGLING || AUTO_DEMANGLING)
{
ret = swift_demangle (mangled, options);
if (ret || SWIFT_DEMANGLING)
return ret;
}

return (ret);
}

Expand All @@ -223,7 +230,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
const char* p;
char *d;
char *demangled = NULL;

/* Discard leading _ada_, which is used for library level subprograms. */
if (strncmp (mangled, "_ada_", 5) == 0)
mangled += 5;
Expand All @@ -239,7 +246,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
they occur only once. */
len0 = strlen (mangled) + 7 + 1;
demangled = XNEWVEC (char, len0);

d = demangled;
p = mangled;
while (1)
Expand Down
30 changes: 22 additions & 8 deletions coregrind/m_demangle/demangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2000-2017 Julian Seward
Copyright (C) 2000-2017 Julian Seward
jseward@acm.org
Rust demangler components are
Expand Down Expand Up @@ -107,7 +107,7 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
/* OUT */ const HChar **result )
{
/* Possibly undo (2) */
/* Z-Demangling was requested.
/* Z-Demangling was requested.
The fastest way to see if it's a Z-mangled name is just to attempt
to Z-demangle it (with NULL for the soname buffer, since we're not
interested in that). */
Expand All @@ -125,11 +125,25 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
// - Rust "legacy" mangled symbols start with "_Z".
// - Rust "v0" mangled symbols start with "_R".
// - D programming language mangled symbols start with "_D".
// - Swift starts with many symbols:
// "_T": legacy
// "_T0": Swift v4
// "$S"/"_$S": Swift v4.x
// "$s"/"_$s": Swift v5
// XXX: the Java/Rust/Ada demangling here probably doesn't work. See
// https://bugs.kde.org/show_bug.cgi?id=445235 for details.
if (do_cxx_demangling && VG_(clo_demangle)
&& orig != NULL && orig[0] == '_'
&& (orig[1] == 'Z' || orig[1] == 'R' || orig[1] == 'D')) {
&& orig != NULL
&& (
VG_(strstr)(orig, "_Z") == orig
|| VG_(strstr)(orig, "_R") == orig
|| VG_(strstr)(orig, "_D") == orig
|| VG_(strstr)(orig, "_T") == orig
|| VG_(strstr)(orig, "$S") == orig
|| VG_(strstr)(orig, "$s") == orig
|| VG_(strstr)(orig, "_$S") == orig
|| VG_(strstr)(orig, "_$s") == orig
)) {
/* !!! vvv STATIC vvv !!! */
static HChar* demangled = NULL;
/* !!! ^^^ STATIC ^^^ !!! */
Expand Down Expand Up @@ -199,8 +213,8 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
/*--- DEMANGLE Z-ENCODED NAMES ---*/
/*------------------------------------------------------------*/

/* Demangle a Z-encoded name as described in pub_tool_redir.h.
Z-encoded names are used by Valgrind for doing function
/* Demangle a Z-encoded name as described in pub_tool_redir.h.
Z-encoded names are used by Valgrind for doing function
interception/wrapping.
Demangle 'sym' into its soname and fnname parts, putting them in
Expand All @@ -211,7 +225,7 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
'so' as NULL is acceptable if the caller is only interested in the
function name part. */

Bool VG_(maybe_Z_demangle) ( const HChar* sym,
Bool VG_(maybe_Z_demangle) ( const HChar* sym,
/*OUT*/const HChar** so,
/*OUT*/const HChar** fn,
/*OUT*/Bool* isWrap,
Expand All @@ -235,7 +249,7 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
}
sobuf[0] = fnbuf[0] = '\0';

if (so)
if (so)
*so = sobuf;
*fn = fnbuf;

Expand Down
17 changes: 12 additions & 5 deletions coregrind/m_demangle/demangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,22 @@ extern "C" {
#define DMGL_GNAT (1 << 15)
#define DMGL_DLANG (1 << 16)
#define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */
#define DMGL_SWIFT (1 << 18)

/* If none of these are set, use 'current_demangling_style' as the default. */
#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST|SWIFT_RUST)

/* Disable a limit on the depth of recursion in mangled strings.
Note if this limit is disabled then stack exhaustion is possible when
demangling pathologically complicated strings. Bug reports about stack
exhaustion when the option is enabled will be rejected. */
#define DMGL_NO_RECURSE_LIMIT (1 << 18)
exhaustion when the option is enabled will be rejected. */
#define DMGL_NO_RECURSE_LIMIT (1 << 18)

/* If DMGL_NO_RECURSE_LIMIT is not enabled, then this is the value used as
the maximum depth of recursion allowed. It should be enough for any
real-world mangled name. */
#define DEMANGLE_RECURSION_LIMIT 2048

/* Enumeration of possible demangling styles.
Lucid and ARM styles are still kept logically distinct, even though
Expand All @@ -91,7 +92,8 @@ extern enum demangling_styles
java_demangling = DMGL_JAVA,
gnat_demangling = DMGL_GNAT,
dlang_demangling = DMGL_DLANG,
rust_demangling = DMGL_RUST
rust_demangling = DMGL_RUST,
swift_demangling = DMGL_SWIFT
} current_demangling_style;

/* Define string names for the various demangling styles. */
Expand All @@ -103,6 +105,7 @@ extern enum demangling_styles
#define GNAT_DEMANGLING_STYLE_STRING "gnat"
#define DLANG_DEMANGLING_STYLE_STRING "dlang"
#define RUST_DEMANGLING_STYLE_STRING "rust"
#define SWIFT_DEMANGLING_STYLE_STRING "swift"

/* Some macros to test what demangling style is active. */

Expand All @@ -113,6 +116,7 @@ extern enum demangling_styles
#define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
#define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG)
#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST)
#define SWIFT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_SWIFT)

/* Provide information about the available demangle styles. This code is
pulled from gdb into libiberty because it is useful to binutils also. */
Expand Down Expand Up @@ -169,6 +173,9 @@ rust_demangle_callback (const char *mangled, int options,
extern char *
rust_demangle (const char *mangled, int options);

extern char *
swift_demangle (const char *mangled, int options);

enum gnu_v3_ctor_kinds {
gnu_v3_complete_object_ctor = 1,
gnu_v3_base_object_ctor,
Expand Down
56 changes: 56 additions & 0 deletions coregrind/m_demangle/swift-demangle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*--------------------------------------------------------------------*/
/*--- Swift demangler ---*/
/*--------------------------------------------------------------------*/

/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (c) 2024-2024 Louis Brunner <louis.brunner.fr@gmail.com>
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; either version 2 of the
License, or (at your option) any later version.
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 for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
The GNU General Public License is contained in the file COPYING.
*/

#include "vg_libciface.h"

#include "ansidecl.h"
#include "demangle.h"
#include "safe-ctype.h"

char* swift_demangle (const char *mangled, int options)
{
UInt prefix_length = 0;
Bool legacy = False;

if (VG_(strstr)(mangled, "_T0") == mangled || VG_(strstr)(mangled, "_$S") == mangled || VG_(strstr)(mangled, "_$s") == mangled) {
prefix_length = 3;
}
if (VG_(strstr)(mangled, "_T") == mangled) {
prefix_length = 2;
legacy = True;
}
if (VG_(strstr)(mangled, "$S") == mangled || VG_(strstr)(mangled, "$s") == mangled) {
prefix_length = 2;
}

if (prefix_length == 0) {
return NULL;
}

mangled += prefix_length;

return NULL;
}
4 changes: 4 additions & 0 deletions memcheck/tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ EXTRA_DIST = \
recursive-merge.stderr.exp recursive-merge.vgtest \
resvn_stack.stderr.exp resvn_stack.vgtest \
demangle-rust.vgtest demangle-rust.stderr.exp \
demangle-swift.vgtest demangle-swift.stderr.exp \
sbfragment.stdout.exp sbfragment.stderr.exp sbfragment.vgtest \
sem.stderr.exp sem.vgtest \
sendmsg.stderr.exp sendmsg.stderr.exp-solaris sendmsg.vgtest \
Expand Down Expand Up @@ -489,6 +490,7 @@ check_PROGRAMS = \
custom-overlap \
demangle \
demangle-rust \
demangle-swift \
big_debuginfo_symbol \
deep-backtrace \
describe-block \
Expand Down Expand Up @@ -698,6 +700,8 @@ endif
demangle_SOURCES = demangle.cpp
demangle_rust_SOURCES = demangle-rust.c
demangle_rust_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_USE_AFTER_FREE@
demangle_swift_SOURCES = demangle-swift.c
demangle_swift_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_USE_AFTER_FREE@
dw4_CFLAGS = $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section

descr_belowsp_LDADD = -lpthread
Expand Down
40 changes: 40 additions & 0 deletions memcheck/tests/demangle-swift.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Same principle as demangle-rust.c, but for Swift symbols.

#include <stdlib.h>

int $sSo13NSFileManagerC10FoundationE28withFileSystemRepresentation3for_xSS_xSPys4Int8VGSgKXEtKlFSDySo0A12AttributeKeyaypG_Tg5(int *p)
{
free(p);
free(p);
return 1;
}

int $ss26_SwiftDeferredNSDictionaryC12bridgeValuess20__BridgingHashBufferCSgyF(int* p)
{
return $sSo13NSFileManagerC10FoundationE28withFileSystemRepresentation3for_xSS_xSPys4Int8VGSgKXEtKlFSDySo0A12AttributeKeyaypG_Tg5(p);
}

int $sSS7cStringSSSPys4Int8VG_tcfC(int* p)
{
return $ss26_SwiftDeferredNSDictionaryC12bridgeValuess20__BridgingHashBufferCSgyF(p);
}

int $s10Foundation16_FileManagerImplV16attributesOfItem6atPathSDySo18NSFileAttributeKeyaypGSS_tKFAHSPys4Int8VGSgKXEfU_TA(size_t s)
{
return $sSS7cStringSSSPys4Int8VG_tcfC(malloc(s));
}

int _TtBv4Bf16_(void)
{
return $s10Foundation16_FileManagerImplV16attributesOfItem6atPathSDySo18NSFileAttributeKeyaypGSS_tKFAHSPys4Int8VGSgKXEfU_TA(sizeof(int));
}

int $ss6SimpleHr(void)
{
return _TtBv4Bf16_();
}

int main(void)
{
return $ss6SimpleHr();
}
16 changes: 16 additions & 0 deletions memcheck/tests/demangle-swift.stderr.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Invalid free() / delete / delete[] / realloc()
at 0x........: free (vg_replace_malloc.c:...)
by 0x........: <rustc_middle::ty::PredicateKind as rustc_middle::ty::fold::TypeFoldable>::fold_with::<rustc_infer::infer::resolve::OpportunisticVarResolver> (demangle-rust.c:13)
by 0x........: rustc_expand::mbe::macro_parser::parse_tt (demangle-rust.c:20)
by 0x........: core::str::lossy::Utf8Lossy::from_bytes (demangle-rust.c:26)
by 0x........: main (demangle-rust.c:31)
Address 0x........ is 0 bytes inside a block of size 4 free'd
at 0x........: free (vg_replace_malloc.c:...)
by 0x........: <rustc_middle::ty::PredicateKind as rustc_middle::ty::fold::TypeFoldable>::fold_with::<rustc_infer::infer::resolve::OpportunisticVarResolver> (demangle-rust.c:12)
by 0x........: rustc_expand::mbe::macro_parser::parse_tt (demangle-rust.c:20)
by 0x........: core::str::lossy::Utf8Lossy::from_bytes (demangle-rust.c:26)
by 0x........: main (demangle-rust.c:31)
Block was alloc'd at
at 0x........: malloc (vg_replace_malloc.c:...)
by 0x........: main (demangle-rust.c:31)

2 changes: 2 additions & 0 deletions memcheck/tests/demangle-swift.vgtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prog: demangle-swift
vgopts: -q

0 comments on commit 9d2d4e3

Please sign in to comment.