Skip to content

Commit c874601

Browse files
committed
v1.2.3
2 parents eaf1699 + 3ade67e commit c874601

24 files changed

+5524
-2874
lines changed

.github/workflows/test.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Build and test
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
runs-on: ${{ matrix.os }}
8+
9+
strategy:
10+
matrix:
11+
os: [macos-latest, ubuntu-latest, windows-latest]
12+
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- name: Set up Ninja
17+
uses: ashutoshvarma/[email protected]
18+
19+
- uses: ilammy/[email protected]
20+
21+
- name: CMake
22+
run: |
23+
cmake -GNinja .
24+
25+
- name: Build
26+
run: |
27+
ninja
28+
29+
- name: Test
30+
run: |
31+
python3 demumble_test.py

.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.*.sw?
2+
3+
# dist.py outputs:
4+
buildlinux/
5+
buildmac/
6+
buildwin/
7+
demumble-linux.zip
8+
demumble-mac.zip
9+
demumble-win.zip
10+
11+
# build outputs when building as described in README.md:
12+
.ninja_deps
13+
.ninja_log
14+
CMakeCache.txt
15+
CMakeFiles/
16+
build.ninja
17+
cmake_install.cmake
18+
demumble

CMakeLists.txt

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR)
1+
cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR)
22
project(demumble CXX)
33

44
if (UNIX)
@@ -19,9 +19,17 @@ if (UNIX)
1919
endif()
2020

2121
if (WIN32)
22+
# https://gitlab.kitware.com/cmake/cmake/-/issues/20610
23+
string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
24+
string(REGEX REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
25+
add_definitions(-D_HAS_EXCEPTIONS=0)
26+
2227
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:inline /EHs-c- /GR-")
2328
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # The LLVM build sets this.
2429

30+
# Disable cl.exe warnings that LLVM disables as well.
31+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4267")
32+
2533
# This is apparently the simplest way to statically link the CRT in CMake:
2634
string(TOUPPER "${CMAKE_BUILD_TYPE}" build)
2735
set(flag_var "CMAKE_CXX_FLAGS_${build}")
@@ -33,9 +41,12 @@ endif()
3341
include_directories(third_party/llvm/include)
3442
add_executable(demumble
3543
demumble.cc
44+
third_party/llvm/lib/Demangle/Demangle.cpp
3645
third_party/llvm/lib/Demangle/ItaniumDemangle.cpp
46+
third_party/llvm/lib/Demangle/DLangDemangle.cpp
3747
third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp
3848
third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
49+
third_party/llvm/lib/Demangle/RustDemangle.cpp
3950
)
40-
set_target_properties(demumble PROPERTIES CXX_STANDARD 11
51+
set_target_properties(demumble PROPERTIES CXX_STANDARD 17
4152
CXX_STANDARD_REQUIRED ON)

README.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# demumble
22

3-
`demumble` demangles both Itanium and Visual Studio symbols. It runs on both
4-
POSIX and Windows.
3+
`demumble` demangles both Itanium and Visual Studio symbols. It runs on
4+
both POSIX and Windows.
55

66
$ demumble _Z4funcPci
77
func(char*, int)
88
$ demumble '?Fx_i@@YAHP6AHH@Z@Z'
99
int __cdecl Fx_i(int (__cdecl *)(int))
10-
10+
11+
It can also demangle Rust and D symbols.
12+
1113
## Download
1214

1315
There are prebuilt x64 binaries for Linux, Mac (10.9+), and Windows on the
@@ -19,9 +21,9 @@ It has several nice features that c++filt lacks (and lacks many of c++filt's
1921
features I never use).
2022

2123
Smart about underscores: C++ symbols have an additional leading underscore on
22-
OS X. `operator new` is mangled as `_Znw` on Linux but `__Znw` on Mac. OS X's
24+
macOS. `operator new` is mangled as `_Znw` on Linux but `__Znw` on Mac. macOS's
2325
c++filt automatically strips one leading underscore, but Linux's c++filt
24-
doesn't. So if you want to demangle a Linux symbol on OS X, you need to pass
26+
doesn't. So if you want to demangle a Linux symbol on macOS, you need to pass
2527
`-n` to tell it to not strip the underscore, and if you want to demangle an OS
2628
X symbol on Linux you likewise need to pass `-_`. demumble just does the right
2729
thing:
@@ -75,7 +77,7 @@ Optionally print both mangled and demangled names:
7577

7678
## Build instructions
7779

78-
Use cmake to build: `cmake -G Ninja && ninja`
80+
Use cmake to build: `cmake -G Ninja . && ninja`
7981

8082
Run tests after building: `python demumble_test.py`
8183

RELEASING

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
Push new release branch:
2-
1. make sure branches 'master' and 'release' are synced up locally
3-
2. update demumble.cc with new version (with ".git"), then
2+
1. make sure branches 'main' and 'release' are synced up locally
3+
2. update kDemumbleVersion in demumble.cc with new version (with ".git"), then
44
git commit -am 'mark this 1.0.0.git'
5-
3. git checkout release; git merge master
6-
4. fix version number in src/version.cc (it will likely conflict in the above)
7-
5. commit, tag, push (don't forget to push --tags)
5+
3. git checkout release; git merge main
6+
4. fix version number in src/version.cc (it will conflict in the above)
7+
5. commit, tag, push (don't forget to push --tags), build binaries
88
git commit -am v1.0.0; git push origin release
99
git tag v1.0.0; git push --tags
10-
# Push the 1.0.0.git change on master too:
11-
git checkout master; git push origin master
12-
6. add binaries to https://github.com/nico/demumble/releases
13-
build them with `./dist.py` (on the release branch)
10+
./dist.py # on the 'release' branch
11+
# Push the 1.0.0.git change on main too:
12+
git checkout main; git push origin main
13+
6. add demumble-{linux,mac,win}.zip to https://github.com/nico/demumble/releases

demumble.cc

+34-15
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include "llvm/Demangle/Demangle.h"
88

9-
const char kDemumbleVersion[] = "1.2.2";
9+
const char kDemumbleVersion[] = "1.2.3";
1010

1111
static int print_help(FILE* out) {
1212
fprintf(out,
@@ -22,15 +22,19 @@ static int print_help(FILE* out) {
2222
return out == stdout ? 0 : 1;
2323
}
2424

25-
static void print_demangled(const char* format, const char* s) {
26-
if (char* itanium = llvm::itaniumDemangle(s, NULL, NULL, NULL)) {
27-
printf(format, itanium, s);
25+
static void print_demangled(const char* format, std::string_view s,
26+
size_t* n_used) {
27+
if (char* itanium = llvm::itaniumDemangle(s)) {
28+
printf(format, itanium, (int)s.size(), s.data());
2829
free(itanium);
29-
} else if (char* ms = llvm::microsoftDemangle(s, NULL, NULL, NULL)) {
30-
printf(format, ms, s);
30+
} else if (char* rust = llvm::rustDemangle(s)) {
31+
printf(format, rust, (int)s.size(), s.data());
32+
free(rust);
33+
} else if (char* ms = llvm::microsoftDemangle(s, n_used, NULL)) {
34+
printf(format, ms, (int)s.size(), s.data());
3135
free(ms);
3236
} else {
33-
printf("%s", s);
37+
printf("%.*s", (int)s.size(), s.data());
3438
}
3539
}
3640

@@ -39,6 +43,12 @@ static bool is_mangle_char_itanium(char c) {
3943
(c >= '0' && c <= '9') || c == '_' || c == '$';
4044
}
4145

46+
static bool is_mangle_char_rust(char c) {
47+
// See https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html.
48+
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
49+
(c >= '0' && c <= '9') || c == '_';
50+
}
51+
4252
static bool is_mangle_char_win(char c) {
4353
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
4454
(c >= '0' && c <= '9') || strchr("?_@$", c);
@@ -53,6 +63,11 @@ static bool is_plausible_itanium_prefix(char* s) {
5363
return strstr(prefix, "_Z");
5464
}
5565

66+
static bool is_plausible_rust_prefix(char* s) {
67+
// Rust symbols start with "_R".
68+
return s[0] == '_' && s[1] == 'R';
69+
}
70+
5671
static char buf[8192];
5772
int main(int argc, char* argv[]) {
5873
enum { kPrintAll, kPrintMatching } print_mode = kPrintAll;
@@ -68,9 +83,9 @@ int main(int argc, char* argv[]) {
6883
++argv;
6984
break;
7085
} else if (argv[1][0] == '-' && argv[1][1] != '-') {
71-
for (int i = 1; i < strlen(argv[1]); ++i)
86+
for (size_t i = 1; i < strlen(argv[1]); ++i)
7287
switch (argv[1][i]) {
73-
case 'b': print_format = "\"%s\" (%s)"; break;
88+
case 'b': print_format = "\"%s\" (%.*s)"; break;
7489
case 'h': return print_help(stdout);
7590
case 'm': print_mode = kPrintMatching; break;
7691
case 'u': setbuf(stdout, NULL); break;
@@ -87,8 +102,11 @@ int main(int argc, char* argv[]) {
87102
++argv;
88103
}
89104
for (int i = 1; i < argc; ++i) {
90-
print_demangled(print_format, argv[i]);
105+
size_t used = strlen(argv[i]);
106+
print_demangled(print_format, { argv[i], used }, &used);
91107
printf("\n");
108+
if (used < strlen(argv[i]))
109+
printf(" unused suffix: %s\n", argv[i] + used);
92110
}
93111
if (argc == 1) { // Read stdin instead.
94112
// By default, don't demangle types. Mangled function names are unlikely
@@ -118,20 +136,21 @@ int main(int argc, char* argv[]) {
118136
else if (is_plausible_itanium_prefix(cur))
119137
while (cur + n_sym != end && is_mangle_char_itanium(cur[n_sym]))
120138
++n_sym;
139+
else if (is_plausible_rust_prefix(cur))
140+
while (cur + n_sym != end && is_mangle_char_rust(cur[n_sym]))
141+
++n_sym;
121142
else {
122143
if (print_mode == kPrintAll)
123144
printf("_");
124145
++cur;
125146
continue;
126147
}
127148

128-
char tmp = cur[n_sym];
129-
cur[n_sym] = '\0';
130-
print_demangled(print_format, cur);
149+
size_t n_used = n_sym;
150+
print_demangled(print_format, { cur, n_sym }, &n_used);
131151
need_separator = true;
132-
cur[n_sym] = tmp;
133152

134-
cur += n_sym;
153+
cur += n_used;
135154
}
136155
}
137156
}

demumble_test.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
#!/usr/bin/env python
2-
from __future__ import print_function
1+
#!/usr/bin/env python3
32
import os, re, subprocess, sys
43

54
tests = [
65
('demumble hello', 'hello\n'),
76
('demumble _Z4funcPci _Z1fv', 'func(char*, int)\nf()\n'),
87
('demumble < _Z4funcPci _Z1fv', 'func(char*, int)\nf()\n'),
8+
('demumble _RINvNtC3std3mem8align_ofdE _RNvNvC5mylib3foo3bar',
9+
'std::mem::align_of::<f64>\nmylib::foo::bar\n'),
10+
('demumble < _RINvNtC3std3mem8align_ofdE _RNvNvC5mylib3foo3bar',
11+
'std::mem::align_of::<f64>\nmylib::foo::bar\n'),
912
('demumble ?Fxi@@YAHP6AHH@Z@Z', 'int __cdecl Fxi(int (__cdecl *)(int))\n'),
1013
('demumble ??0S@@QEAA@$$QEAU0@@Z', 'public: __cdecl S::S(struct S &&)\n'),
1114
('demumble ??_C@_02PCEFGMJL@hi?$AA@', '"hi"\n'),
12-
('demumble __Znwi', 'operator new(int)\n'), # Strip extra _ (for OS X)
15+
('demumble __Znwi', 'operator new(int)\n'), # Strip extra _ (for macOS)
1316
('demumble < __Znwi', 'operator new(int)\n'), # Also from stdin
1417
('demumble -m hi _Z1fv ho _Z1gv', 'hi\nf()\nho\ng()\n'),
1518
('demumble -m < hi_ho _Z1fv ho _Z1gv ?hm', 'f()\ng()\n?hm\n'),
@@ -40,6 +43,9 @@
4043
('demumble < _ZZ3fooiENK3$_0clEi',
4144
'foo(int)::$_0::operator()(int) const\n'),
4245
('demumble .?AVNet@@', "class Net `RTTI Type Descriptor Name'\n"),
46+
('demumble < asdf?x@@3HAjkl', 'asdfint xjkl\n'),
47+
('demumble < asdf?x@@3Hjkl', 'asdf?x@@3Hjkl\n'),
48+
('demumble ?x@@3HAjkl', 'int x\n unused suffix: jkl\n'),
4349
]
4450

4551
status = 0
@@ -50,12 +56,12 @@
5056
if '<' in cmd:
5157
p = subprocess.Popen(cmd[:cmd.index('<')], stdin=subprocess.PIPE,
5258
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
53-
universal_newlines=True)
59+
encoding='utf-8')
5460
out = p.communicate(input='\n'.join(cmd[cmd.index('<') + 1:]) + '\n')[0]
5561
else:
56-
out = subprocess.check_output(cmd, universal_newlines=True)
62+
out = subprocess.check_output(cmd, encoding='utf-8')
5763
if (out != t[1] if isinstance(t[1], str) else not t[1].match(out)):
58-
print("`%s`: Expected '%s', got '%s'" % (t[0], t[1], out))
64+
print(f"`{t[0]}`: Expected '{t[1]}', got '{out}'")
5965
status = 1
60-
print("passed" if status == 0 else "failed")
66+
print('passed' if status == 0 else 'failed')
6167
sys.exit(status)

0 commit comments

Comments
 (0)