summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2023-02-01 21:24:07 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-02-01 21:24:07 +0000
commit2ec58fe4b40aaa58252c796d39dff4e5b0b424d7 (patch)
tree3d739922811bd9e6b67b8e4ab41b763ecfe71287
parentc16d1dc8292d57527a8d93d31c5e6ff7dd6af5b0 (diff)
parent5dd10e676eac53eec28a37879ca5054de8a538d1 (diff)
downloadunwinding-2ec58fe4b40aaa58252c796d39dff4e5b0b424d7.tar.gz
Merge "Revert^2 "Add rust demangling."" am: 63369c7750 am: 5dd10e676e
Original change: https://android-review.googlesource.com/c/platform/system/unwinding/+/2403073 Change-Id: I3e2b75e346db038ac1fc13554788b3e93ee90199 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libunwindstack/Android.bp6
-rw-r--r--libunwindstack/AndroidUnwinder.cpp10
-rw-r--r--libunwindstack/Demangle.cpp51
-rw-r--r--libunwindstack/Unwinder.cpp15
-rw-r--r--libunwindstack/include/unwindstack/Demangle.h25
-rw-r--r--libunwindstack/tests/DemangleTest.cpp46
6 files changed, 133 insertions, 20 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 84619ee..7a63a22 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -54,6 +54,7 @@ cc_defaults {
libunwindstack_common_src_files = [
"AndroidUnwinder.cpp",
"ArmExidx.cpp",
+ "Demangle.cpp",
"DexFiles.cpp",
"DwarfCfa.cpp",
"DwarfEhFrameWithHdr.cpp",
@@ -123,6 +124,10 @@ cc_defaults {
"libprocinfo",
],
+ whole_static_libs: [
+ "librustc_demangle_static",
+ ],
+
shared_libs: [
"libbase",
"liblog",
@@ -273,6 +278,7 @@ cc_defaults {
"tests/AndroidUnwinderTest.cpp",
"tests/ArmExidxDecodeTest.cpp",
"tests/ArmExidxExtractTest.cpp",
+ "tests/DemangleTest.cpp",
"tests/DexFileTest.cpp",
"tests/DexFilesTest.cpp",
"tests/DwarfCfaLogTest.cpp",
diff --git a/libunwindstack/AndroidUnwinder.cpp b/libunwindstack/AndroidUnwinder.cpp
index d228aea..3b25604 100644
--- a/libunwindstack/AndroidUnwinder.cpp
+++ b/libunwindstack/AndroidUnwinder.cpp
@@ -28,6 +28,7 @@
#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Arch.h>
+#include <unwindstack/Demangle.h>
#include <unwindstack/DexFiles.h>
#include <unwindstack/Error.h>
#include <unwindstack/JitDebug.h>
@@ -45,18 +46,11 @@ static constexpr int kThreadUnwindSignal = BIONIC_SIGNAL_BACKTRACE;
static int kThreadUnwindSignal = SIGRTMIN;
#endif
-// Use the demangler from libc++.
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
-
namespace unwindstack {
void AndroidUnwinderData::DemangleFunctionNames() {
for (auto& frame : frames) {
- char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
- if (demangled_name != nullptr) {
- frame.function_name = demangled_name;
- free(demangled_name);
- }
+ frame.function_name = DemangleNameIfNeeded(frame.function_name);
}
}
diff --git a/libunwindstack/Demangle.cpp b/libunwindstack/Demangle.cpp
new file mode 100644
index 0000000..8d0bfd6
--- /dev/null
+++ b/libunwindstack/Demangle.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cxxabi.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include <rustc_demangle.h>
+
+#include <unwindstack/Demangle.h>
+
+namespace unwindstack {
+
+std::string DemangleNameIfNeeded(const std::string& name) {
+ if (name.length() < 2 || name[0] != '_') {
+ return name;
+ }
+
+ char* demangled_str = nullptr;
+ if (name[1] == 'Z') {
+ // Try to demangle C++ name.
+ demangled_str = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr);
+ } else if (name[1] == 'R') {
+ // Try to demangle rust name.
+ demangled_str = rustc_demangle(name.c_str(), nullptr, nullptr, nullptr);
+ }
+
+ if (demangled_str == nullptr) {
+ return name;
+ }
+
+ std::string demangled_name(demangled_str);
+ free(demangled_str);
+ return demangled_name;
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index facff86..7304000 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -25,10 +25,12 @@
#include <algorithm>
#include <memory>
+#include <string>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
+#include <unwindstack/Demangle.h>
#include <unwindstack/DexFiles.h>
#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
@@ -39,9 +41,6 @@
#include "Check.h"
-// Use the demangler from libc++.
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
-
namespace unwindstack {
// Inject extra 'virtual' frame that represents the dex pc data.
@@ -326,15 +325,7 @@ std::string Unwinder::FormatFrame(ArchEnum arch, const FrameData& frame, bool di
}
if (!frame.function_name.empty()) {
- char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
- if (demangled_name == nullptr) {
- data += " (";
- data += frame.function_name;
- } else {
- data += " (";
- data += demangled_name;
- free(demangled_name);
- }
+ data += " (" + DemangleNameIfNeeded(frame.function_name);
if (frame.function_offset != 0) {
data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
}
diff --git a/libunwindstack/include/unwindstack/Demangle.h b/libunwindstack/include/unwindstack/Demangle.h
new file mode 100644
index 0000000..8ea51bc
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Demangle.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace unwindstack {
+
+std::string DemangleNameIfNeeded(const std::string& name);
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/DemangleTest.cpp b/libunwindstack/tests/DemangleTest.cpp
new file mode 100644
index 0000000..3047b6e
--- /dev/null
+++ b/libunwindstack/tests/DemangleTest.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Demangle.h>
+
+namespace unwindstack {
+
+TEST(DemangleTest, none) {
+ EXPECT_EQ("", DemangleNameIfNeeded(""));
+ EXPECT_EQ("a", DemangleNameIfNeeded("a"));
+ EXPECT_EQ("_", DemangleNameIfNeeded("_"));
+ EXPECT_EQ("ab", DemangleNameIfNeeded("ab"));
+ EXPECT_EQ("abc", DemangleNameIfNeeded("abc"));
+ EXPECT_EQ("_R", DemangleNameIfNeeded("_R"));
+ EXPECT_EQ("_Z", DemangleNameIfNeeded("_Z"));
+}
+
+TEST(DemangleTest, cxx_names) {
+ EXPECT_EQ("fake(bool)", DemangleNameIfNeeded("_Z4fakeb"));
+ EXPECT_EQ("demangle(int)", DemangleNameIfNeeded("_Z8demanglei"));
+}
+
+TEST(DemangleTest, rust_names) {
+ EXPECT_EQ("std::rt::lang_start_internal",
+ DemangleNameIfNeeded("_RNvNtCs2WRBrrl1bb1_3std2rt19lang_start_internal"));
+ EXPECT_EQ("profcollectd::main", DemangleNameIfNeeded("_RNvCs4VPobU5SDH_12profcollectd4main"));
+}
+
+} // namespace unwindstack