summaryrefslogtreecommitdiff
path: root/src/runtime_linux.cc
blob: b614a635e42462ab7e57f61945613728d0c4587f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2011 Google Inc. All Rights Reserved.

#include "runtime.h"

#include <cxxabi.h>
#include <execinfo.h>

#include "logging.h"
#include "stringprintf.h"

namespace art {

std::string Demangle(const std::string& mangled_name) {
  if (mangled_name.empty()) {
    return "??";
  }

  // http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
  int status;
  char* name(abi::__cxa_demangle(mangled_name.c_str(), NULL, NULL, &status));
  if (name != NULL) {
    std::string result(name);
    free(name);
    return result;
  }

  return mangled_name + "()";
}

void Runtime::PlatformAbort(const char* file, int line) {
  // On the host, we don't have debuggerd to dump a stack for us.

  // Get the raw stack frames.
  size_t MAX_STACK_FRAMES = 64;
  void* frames[MAX_STACK_FRAMES];
  size_t frame_count = backtrace(frames, MAX_STACK_FRAMES);

  // Turn them into something human-readable with symbols.
  char** symbols = backtrace_symbols(frames, frame_count);
  if (symbols == NULL) {
    PLOG(ERROR) << "backtrace_symbols failed";
    return;
  }

  // backtrace_symbols(3) gives us lines like this:
  // "/usr/local/google/home/enh/a1/out/host/linux-x86/bin/../lib/libartd.so(_ZN3art7Runtime13PlatformAbortEPKci+0x15b) [0xf76c5af3]"
  // "[0xf7b62057]"

  // We extract the pieces and demangle, so we can produce output like this:
  // libartd.so:-1]    #00 art::Runtime::PlatformAbort(char const*, int) +0x15b [0xf770dd51]

  for (size_t i = 0; i < frame_count; ++i) {
    std::string text(symbols[i]);
    std::string filename("??");
    std::string function_name;

    size_t index = text.find('(');
    if (index != std::string::npos) {
      filename = text.substr(0, index);
      text.erase(0, index + 1);

      index = text.find_first_of("+)");
      function_name = Demangle(text.substr(0, index));
      text.erase(0, index);
      index = text.find(')');
      text.erase(index, 1);
    }
    std::string log_line(StringPrintf("\t#%02zd ", i) + function_name + text);
    LogMessage(filename.c_str(), -1, ERROR, -1).stream() << log_line;
  }

  free(symbols);
}

}  // namespace art