]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/BackTrace: extract demangle() out
authorKefu Chai <kchai@redhat.com>
Tue, 8 Sep 2020 11:52:46 +0000 (19:52 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 17 Sep 2020 07:24:37 +0000 (15:24 +0800)
so it can be reused by crimson

Signed-off-by: Kefu Chai <kchai@redhat.com>
src/common/BackTrace.cc
src/common/BackTrace.h

index 5e014946982db6d21f34ac5156eb468fbed2d7e9..453ba02dbb9d7fccb3e9e488411cdb72b9dbb404 100644 (file)
@@ -15,59 +15,7 @@ void BackTrace::print(std::ostream& out) const
 {
   out << " " << pretty_version_to_str() << std::endl;
   for (size_t i = skip; i < size; i++) {
-    //      out << " " << (i-skip+1) << ": " << strings[i] << std::endl;
-
-    size_t sz = 1024; // just a guess, template names will go much wider
-    char *function = (char *)malloc(sz);
-    if (!function)
-      return;
-    char *begin = 0, *end = 0;
-    
-    // find the parentheses and address offset surrounding the mangled name
-#ifdef __FreeBSD__
-    static constexpr char OPEN = '<';
-#else
-    static constexpr char OPEN = '(';
-#endif
-    for (char *j = strings[i]; *j; ++j) {
-      if (*j == OPEN)
-       begin = j+1;
-      else if (*j == '+')
-       end = j;
-    }
-    if (begin && end) {
-      int len = end - begin;
-      char *foo = (char *)malloc(len+1);
-      if (!foo) {
-       free(function);
-       return;
-      }
-      memcpy(foo, begin, len);
-      foo[len] = 0;
-
-      int status;
-      char *ret = nullptr;
-      // only demangle a C++ mangled name
-      if (foo[0] == '_' && foo[1] == 'Z')
-       ret = abi::__cxa_demangle(foo, function, &sz, &status);
-      if (ret) {
-       // return value may be a realloc() of the input
-       function = ret;
-      }
-      else {
-       // demangling failed, just pretend it's a C function with no args
-       strncpy(function, foo, sz);
-       strncat(function, "()", sz);
-       function[sz-1] = 0;
-      }
-      out << " " << (i-skip+1) << ": " << OPEN << function << end << std::endl;
-      //fprintf(out, "    %s:%s\n", stack.strings[i], function);
-      free(foo);
-    } else {
-      // didn't find the mangled name, just print the whole line
-      out << " " << (i-skip+1) << ": " << strings[i] << std::endl;
-    }
-    free(function);
+    out << " " << (i-skip+1) << ": " << demangle(strings[i]) << std::endl;
   }
 }
 
@@ -76,61 +24,57 @@ void BackTrace::dump(Formatter *f) const
   f->open_array_section("backtrace");
   for (size_t i = skip; i < size; i++) {
     //      out << " " << (i-skip+1) << ": " << strings[i] << std::endl;
+    f->dump_string("frame", demangle(strings[i]));
+  }
+  f->close_section();
+}
 
-    size_t sz = 1024; // just a guess, template names will go much wider
-    char *function = (char *)malloc(sz);
-    if (!function)
-      return;
-    char *begin = 0, *end = 0;
-
-    // find the parentheses and address offset surrounding the mangled name
+std::string BackTrace::demangle(const char* name)
+{
+  // find the parentheses and address offset surrounding the mangled name
 #ifdef __FreeBSD__
-    static constexpr char OPEN = '<';
+  static constexpr char OPEN = '<';
 #else
-    static constexpr char OPEN = '(';
+  static constexpr char OPEN = '(';
 #endif
-    for (char *j = strings[i]; *j; ++j) {
-      if (*j == OPEN)
-       begin = j+1;
-      else if (*j == '+')
-       end = j;
+  const char* begin = nullptr;
+  const char* end = nullptr;
+  for (const char *j = name; *j; ++j) {
+    if (*j == OPEN) {
+      begin = j + 1;
+    } else if (*j == '+') {
+      end = j;
     }
-    if (begin && end) {
-      int len = end - begin;
-      char *foo = (char *)malloc(len+1);
-      if (!foo) {
-       free(function);
-       return;
-      }
-      memcpy(foo, begin, len);
-      foo[len] = 0;
-
-      int status;
-      char *ret = nullptr;
-      // only demangle a C++ mangled name
-      if (foo[0] == '_' && foo[1] == 'Z')
-       ret = abi::__cxa_demangle(foo, function, &sz, &status);
-      if (ret) {
-       // return value may be a realloc() of the input
-       function = ret;
+  }
+  if (begin && end) {
+    std::string mangled(begin, end);
+    int status;
+    // only demangle a C++ mangled name
+    if (mangled.compare(0, 2, "_Z") == 0) {
+      // just a guess, template names will go much wider
+      size_t len = 1024;
+      char* buf = (char*)malloc(len);
+      if (!buf) {
+        return {};
       }
-      else {
-       // demangling failed, just pretend it's a C function with no args
-       strncpy(function, foo, sz);
-       strncat(function, "()", sz);
-       function[sz-1] = 0;
+      if (char* demangled = abi::__cxa_demangle(mangled.c_str(), buf, &len, &status)) {
+        std::string full_name{OPEN};
+        full_name += demangled;
+        full_name += end;
+        // buf could be reallocated, so free(demangled) instead
+        free(demangled);
+        return full_name;
+      } else {
+        // demangle failed, just pretend it's a C function with no args
+        free(buf);
       }
-      f->dump_stream("frame") << OPEN << function << end;
-      //fprintf(out, "    %s:%s\n", stack.strings[i], function);
-      free(foo);
-    } else {
-      // didn't find the mangled name, just print the whole line
-      //out << " " << (i-skip+1) << ": " << strings[i] << std::endl;
-      f->dump_string("frame", strings[i]);
     }
-    free(function);
+    // C function
+    return mangled + "()";
+  } else {
+    // didn't find the mangled name, just print the whole line
+    return name;
   }
-  f->close_section();
 }
 
 }
index 5cb73d47bd6c4cce893b2d90d09486c3e6658f81..0132fa5da8776708e8c2576e76833d931b61b2dc 100644 (file)
@@ -42,6 +42,7 @@ struct BackTrace {
 
   void print(std::ostream& out) const;
   void dump(Formatter *f) const;
+  static std::string demangle(const char* name);
 };
 
 inline std::ostream& operator<<(std::ostream& out, const BackTrace& bt) {