diff options
Diffstat (limited to 'runtime/utils.cc')
-rw-r--r-- | runtime/utils.cc | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/runtime/utils.cc b/runtime/utils.cc index 3f779df15a..515ba9f9e3 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -46,20 +46,12 @@ #include <sys/syscall.h> #endif -// For DumpNativeStack. -#include <backtrace/Backtrace.h> -#include <backtrace/BacktraceMap.h> - #if defined(__linux__) #include <linux/unistd.h> #endif namespace art { -#if defined(__linux__) -static constexpr bool kUseAddr2line = !kIsTargetBuild; -#endif - pid_t GetTid() { #if defined(__APPLE__) uint64_t owner; @@ -1026,210 +1018,6 @@ std::string GetSchedulerGroupName(pid_t tid) { return ""; } -#if defined(__linux__) - -ALWAYS_INLINE -static inline void WritePrefix(std::ostream* os, const char* prefix, bool odd) { - if (prefix != nullptr) { - *os << prefix; - } - *os << " "; - if (!odd) { - *os << " "; - } -} - -static bool RunCommand(std::string cmd, std::ostream* os, const char* prefix) { - FILE* stream = popen(cmd.c_str(), "r"); - if (stream) { - if (os != nullptr) { - bool odd_line = true; // We indent them differently. - bool wrote_prefix = false; // Have we already written a prefix? - constexpr size_t kMaxBuffer = 128; // Relatively small buffer. Should be OK as we're on an - // alt stack, but just to be sure... - char buffer[kMaxBuffer]; - while (!feof(stream)) { - if (fgets(buffer, kMaxBuffer, stream) != nullptr) { - // Split on newlines. - char* tmp = buffer; - for (;;) { - char* new_line = strchr(tmp, '\n'); - if (new_line == nullptr) { - // Print the rest. - if (*tmp != 0) { - if (!wrote_prefix) { - WritePrefix(os, prefix, odd_line); - } - wrote_prefix = true; - *os << tmp; - } - break; - } - if (!wrote_prefix) { - WritePrefix(os, prefix, odd_line); - } - char saved = *(new_line + 1); - *(new_line + 1) = 0; - *os << tmp; - *(new_line + 1) = saved; - tmp = new_line + 1; - odd_line = !odd_line; - wrote_prefix = false; - } - } - } - } - pclose(stream); - return true; - } else { - return false; - } -} - -static void Addr2line(const std::string& map_src, uintptr_t offset, std::ostream& os, - const char* prefix) { - std::string cmdline(StringPrintf("addr2line --functions --inlines --demangle -e %s %zx", - map_src.c_str(), offset)); - RunCommand(cmdline.c_str(), &os, prefix); -} - -static bool PcIsWithinQuickCode(ArtMethod* method, uintptr_t pc) NO_THREAD_SAFETY_ANALYSIS { - uintptr_t code = reinterpret_cast<uintptr_t>(EntryPointToCodePointer( - method->GetEntryPointFromQuickCompiledCode())); - if (code == 0) { - return pc == 0; - } - uintptr_t code_size = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; - return code <= pc && pc <= (code + code_size); -} -#endif - -void DumpNativeStack(std::ostream& os, pid_t tid, BacktraceMap* existing_map, const char* prefix, - ArtMethod* current_method, void* ucontext_ptr) { -#if __linux__ - // b/18119146 - if (RUNNING_ON_MEMORY_TOOL != 0) { - return; - } - - BacktraceMap* map = existing_map; - std::unique_ptr<BacktraceMap> tmp_map; - if (map == nullptr) { - tmp_map.reset(BacktraceMap::Create(getpid())); - map = tmp_map.get(); - } - std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid, map)); - if (!backtrace->Unwind(0, reinterpret_cast<ucontext*>(ucontext_ptr))) { - os << prefix << "(backtrace::Unwind failed for thread " << tid - << ": " << backtrace->GetErrorString(backtrace->GetError()) << ")\n"; - return; - } else if (backtrace->NumFrames() == 0) { - os << prefix << "(no native stack frames for thread " << tid << ")\n"; - return; - } - - // Check whether we have and should use addr2line. - bool use_addr2line; - if (kUseAddr2line) { - // Try to run it to see whether we have it. Push an argument so that it doesn't assume a.out - // and print to stderr. - use_addr2line = (gAborting > 0) && RunCommand("addr2line -h", nullptr, nullptr); - } else { - use_addr2line = false; - } - - for (Backtrace::const_iterator it = backtrace->begin(); - it != backtrace->end(); ++it) { - // We produce output like this: - // ] #00 pc 000075bb8 /system/lib/libc.so (unwind_backtrace_thread+536) - // In order for parsing tools to continue to function, the stack dump - // format must at least adhere to this format: - // #XX pc <RELATIVE_ADDR> <FULL_PATH_TO_SHARED_LIBRARY> ... - // The parsers require a single space before and after pc, and two spaces - // after the <RELATIVE_ADDR>. There can be any prefix data before the - // #XX. <RELATIVE_ADDR> has to be a hex number but with no 0x prefix. - os << prefix << StringPrintf("#%02zu pc ", it->num); - bool try_addr2line = false; - if (!BacktraceMap::IsValid(it->map)) { - os << StringPrintf(Is64BitInstructionSet(kRuntimeISA) ? "%016" PRIxPTR " ???" - : "%08" PRIxPTR " ???", - it->pc); - } else { - os << StringPrintf(Is64BitInstructionSet(kRuntimeISA) ? "%016" PRIxPTR " " - : "%08" PRIxPTR " ", - BacktraceMap::GetRelativePc(it->map, it->pc)); - os << it->map.name; - os << " ("; - if (!it->func_name.empty()) { - os << it->func_name; - if (it->func_offset != 0) { - os << "+" << it->func_offset; - } - try_addr2line = true; - } else if (current_method != nullptr && - Locks::mutator_lock_->IsSharedHeld(Thread::Current()) && - PcIsWithinQuickCode(current_method, it->pc)) { - const void* start_of_code = current_method->GetEntryPointFromQuickCompiledCode(); - os << JniLongName(current_method) << "+" - << (it->pc - reinterpret_cast<uintptr_t>(start_of_code)); - } else { - os << "???"; - } - os << ")"; - } - os << "\n"; - if (try_addr2line && use_addr2line) { - Addr2line(it->map.name, it->pc - it->map.start, os, prefix); - } - } -#else - UNUSED(os, tid, existing_map, prefix, current_method, ucontext_ptr); -#endif -} - -#if defined(__APPLE__) - -// TODO: is there any way to get the kernel stack on Mac OS? -void DumpKernelStack(std::ostream&, pid_t, const char*, bool) {} - -#else - -void DumpKernelStack(std::ostream& os, pid_t tid, const char* prefix, bool include_count) { - if (tid == GetTid()) { - // There's no point showing that we're reading our stack out of /proc! - return; - } - - std::string kernel_stack_filename(StringPrintf("/proc/self/task/%d/stack", tid)); - std::string kernel_stack; - if (!ReadFileToString(kernel_stack_filename, &kernel_stack)) { - os << prefix << "(couldn't read " << kernel_stack_filename << ")\n"; - return; - } - - std::vector<std::string> kernel_stack_frames; - Split(kernel_stack, '\n', &kernel_stack_frames); - // We skip the last stack frame because it's always equivalent to "[<ffffffff>] 0xffffffff", - // which looking at the source appears to be the kernel's way of saying "that's all, folks!". - kernel_stack_frames.pop_back(); - for (size_t i = 0; i < kernel_stack_frames.size(); ++i) { - // Turn "[<ffffffff8109156d>] futex_wait_queue_me+0xcd/0x110" - // into "futex_wait_queue_me+0xcd/0x110". - const char* text = kernel_stack_frames[i].c_str(); - const char* close_bracket = strchr(text, ']'); - if (close_bracket != nullptr) { - text = close_bracket + 2; - } - os << prefix; - if (include_count) { - os << StringPrintf("#%02zd ", i); - } - os << text << "\n"; - } -} - -#endif - const char* GetAndroidRoot() { const char* android_root = getenv("ANDROID_ROOT"); if (android_root == nullptr) { |