1 /* 2 * Copyright (c) 2014 Alex Crichton 3 * 4 * Permission is hereby granted, free of charge, to any 5 * person obtaining a copy of this software and associated 6 * documentation files (the "Software"), to deal in the 7 * Software without restriction, including without 8 * limitation the rights to use, copy, modify, merge, 9 * publish, distribute, sublicense, and/or sell copies of 10 * the Software, and to permit persons to whom the Software 11 * is furnished to do so, subject to the following 12 * conditions: 13 * 14 * The above copyright notice and this permission notice 15 * shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 /* 29 * Copyright 2019, Joyent, Inc. 30 * Copyright 2021 Jason King 31 */ 32 33 /* 34 * Test cases taken from rustc-demangle 0.1.9 35 */ 36 #include <errno.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <sys/sysmacros.h> 41 #include <demangle-sys.h> 42 43 typedef struct rust_test_case { 44 const char *mangled; 45 const char *demangled; 46 } rust_test_case_t; 47 #define T(_m, _d) { .mangled = _m, .demangled = _d } 48 #define T_ERR(_m) { .mangled = _m } 49 50 typedef struct rust_test_grp { 51 const char *name; 52 rust_test_case_t tests[]; 53 } rust_test_grp_t; 54 #define GROUP(_n, ...) \ 55 static rust_test_grp_t _n = { \ 56 .name = #_n, \ 57 .tests = { \ 58 __VA_ARGS__, \ 59 { NULL, NULL } \ 60 } \ 61 } 62 63 GROUP(demangle, 64 T_ERR("test"), 65 T("_ZN4testE", "test"), 66 T_ERR("_ZN4test"), 67 T("_ZN4test1a2bcE", "test::a::bc")); 68 69 GROUP(demangle_dollars, 70 T("_ZN4$RP$E", ")"), 71 T("_ZN8$RF$testE", "&test"), 72 T("_ZN8$BP$test4foobE", "*test::foob"), 73 T("_ZN9$u20$test4foobE", " test::foob"), 74 T("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>")); 75 76 GROUP(demangle_many_dollars, 77 T("_ZN13test$u20$test4foobE", "test test::foob"), 78 T("_ZN12test$BP$test4foobE", "test*test::foob")); 79 80 /* BEGIN CSTYLED */ 81 GROUP(demangle_osx, 82 T("__ZN5alloc9allocator6Layout9for_value17h02a996811f781011E", 83 "alloc::allocator::Layout::for_value::h02a996811f781011"), 84 T("__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap18_MSG_FILE_LINE_COL17haf7cb8d5824ee659E", 85 "<core::option::Option<T>>::unwrap::_MSG_FILE_LINE_COL::haf7cb8d5824ee659"), 86 T("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E", 87 "core::slice::<impl core::iter::traits::IntoIterator for &'a [T]>::into_iter::h450e234d27262170")); 88 89 GROUP(demangle_elements_beginning_with_underscore, 90 T("_ZN13_$LT$test$GT$E", "<test>"), 91 T("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"), 92 T("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR")); 93 94 GROUP(demangle_trait_impls, 95 T("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", 96 "<Test + 'static as foo::Bar<Test>>::bar")); 97 98 GROUP(invalid_no_chop, T_ERR("_ZNfooE")); 99 100 GROUP(handle_assoc_types, 101 T("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE", 102 "<alloc::boxed::Box<alloc::boxed::FnBox<A, Output=R> + 'a> as core::ops::function::FnOnce<A>>::call_once::h69e8f44b3723e1ca")); 103 104 /* C++ mangled names that aren't valid rust names */ 105 GROUP(cplusplus_as_rust, T_ERR("_ZN7mozilla3dom13BrowserParent22RecvUpdateContentCacheERKNS_12ContentCacheE")); 106 107 /* END CSTYLED */ 108 109 static rust_test_grp_t *rust_tests[] = { 110 &demangle, 111 &demangle_dollars, 112 &demangle_many_dollars, 113 &demangle_osx, 114 &demangle_elements_beginning_with_underscore, 115 &demangle_trait_impls, 116 &invalid_no_chop, 117 &handle_assoc_types, 118 &cplusplus_as_rust, 119 }; 120 121 static const size_t n_rust_tests = ARRAY_SIZE(rust_tests); 122 123 static boolean_t 124 check_failure(size_t i, rust_test_case_t *tc, const char *dem, boolean_t res) 125 { 126 int savederr = errno; 127 128 if (dem == NULL && savederr == EINVAL) 129 return (B_TRUE); 130 131 if (res) 132 (void) printf("FAILURE\n"); 133 134 if (dem != NULL) { 135 (void) printf(" [%zu] Successfully demanged an invalid " 136 "name\n", i); 137 (void) printf(" Name: '%s'\n", tc->mangled); 138 (void) printf(" Demangled: '%s'\n", dem); 139 return (B_FALSE); 140 } 141 142 (void) printf(" [%zu] demangle() returned an unexpected error\n", i); 143 (void) printf(" Errno: %d\n", savederr); 144 return (B_FALSE); 145 } 146 147 static boolean_t 148 check_success(size_t i, rust_test_case_t *tc, const char *dem, boolean_t res) 149 { 150 if (dem != NULL && strcmp(tc->demangled, dem) == 0) 151 return (B_TRUE); 152 153 if (res) 154 (void) printf("FAILURE\n"); 155 156 if (dem == NULL) { 157 (void) printf(" [%zu] Failed to demangle '%s'\n", i, 158 tc->mangled); 159 return (B_FALSE); 160 } 161 162 (void) printf(" [%zu] Demangled results do not match.\n", i); 163 (void) printf(" Mangled: %s\n", tc->mangled); 164 (void) printf(" Expected: %s\n", tc->demangled); 165 (void) printf(" Actual: %s\n", dem); 166 return (B_FALSE); 167 } 168 169 static boolean_t 170 run_test(rust_test_grp_t *test) 171 { 172 boolean_t res = B_TRUE; 173 174 (void) printf("Test %s: ", test->name); 175 176 for (size_t i = 0; test->tests[i].mangled != NULL; i++) { 177 char *dem; 178 179 dem = sysdemangle(test->tests[i].mangled, SYSDEM_LANG_RUST, 180 NULL); 181 if (test->tests[i].demangled == NULL) 182 res &= check_failure(i, &test->tests[i], dem, res); 183 else 184 res &= check_success(i, &test->tests[i], dem, res); 185 186 free(dem); 187 } 188 189 if (res) 190 (void) printf("SUCCESS\n"); 191 192 return (res); 193 } 194 195 int 196 main(int argc, char **argv) 197 { 198 boolean_t ok = B_TRUE; 199 200 for (size_t i = 0; i < n_rust_tests; i++) 201 ok &= run_test(rust_tests[i]); 202 203 return (ok ? 0 : 1); 204 } 205 206 const char * 207 _umem_debug_init(void) 208 { 209 return ("default,verbose"); 210 } 211 212 const char * 213 _umem_logging_init(void) 214 { 215 return ("fail,contents"); 216 } 217