15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/stack_trace.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <android/log.h> 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <unwind.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/debug/proc_maps_linux.h" 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringprintf.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/threading/thread_restrictions.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#ifdef __LP64__ 1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#define FMT_ADDR "0x%016lx" 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#define FMT_ADDR "0x%08x" 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif 1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstruct StackCrawlState { 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StackCrawlState(uintptr_t* frames, size_t max_depth) 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch : frames(frames), 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_count(0), 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch max_depth(max_depth), 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch have_skipped_self(false) {} 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uintptr_t* frames; 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t frame_count; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t max_depth; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool have_skipped_self; 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch_Unwind_Reason_Code TraceStackFrame(_Unwind_Context* context, void* arg) { 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StackCrawlState* state = static_cast<StackCrawlState*>(arg); 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uintptr_t ip = _Unwind_GetIP(context); 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The first stack frame is this function itself. Skip it. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ip != 0 && !state->have_skipped_self) { 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state->have_skipped_self = true; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return _URC_NO_REASON; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state->frames[state->frame_count++] = ip; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (state->frame_count >= state->max_depth) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return _URC_END_OF_STACK; 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return _URC_NO_REASON; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace debug { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnableInProcessStackDumping() { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When running in an application, our code typically expects SIGPIPE 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be ignored. Therefore, when testing that same code, it should run 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with SIGPIPE ignored as well. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(phajdan.jr): De-duplicate this SIGPIPE code. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction action; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&action, 0, sizeof(action)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action.sa_handler = SIG_IGN; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sigemptyset(&action.sa_mask); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (sigaction(SIGPIPE, &action, NULL) == 0); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StackTrace::StackTrace() { 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StackCrawlState state(reinterpret_cast<uintptr_t*>(trace_), kMaxTraces); 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch _Unwind_Backtrace(&TraceStackFrame, &state); 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) count_ = state.frame_count; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void StackTrace::Print() const { 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string backtrace = ToString(); 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch __android_log_write(ANDROID_LOG_ERROR, "chromium", backtrace.c_str()); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// NOTE: Native libraries in APKs are stripped before installing. Print out the 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// relocatable address and library names so host computers can use tools to 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// symbolize and demangle (e.g., addr2line, c++filt). 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StackTrace::OutputToStream(std::ostream* os) const { 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string proc_maps; 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<MappedMemoryRegion> regions; 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Allow IO to read /proc/self/maps. Reading this file doesn't hit the disk 867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // since it lives in procfs, and this is currently used to print a stack trace 877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // on fatal log messages in debug builds only. If the restriction is enabled 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // then it will recursively trigger fatal failures when this enters on the 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // UI thread. 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::ThreadRestrictions::ScopedAllowIO allow_io; 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ReadProcMaps(&proc_maps)) { 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch __android_log_write( 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ANDROID_LOG_ERROR, "chromium", "Failed to read /proc/self/maps"); 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (!ParseProcMaps(proc_maps, ®ions)) { 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch __android_log_write( 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ANDROID_LOG_ERROR, "chromium", "Failed to parse /proc/self/maps"); 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (size_t i = 0; i < count_; ++i) { 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Subtract one as return address of function may be in the next 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // function when a function is annotated as noreturn. 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uintptr_t address = reinterpret_cast<uintptr_t>(trace_[i]) - 1; 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<MappedMemoryRegion>::iterator iter = regions.begin(); 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch while (iter != regions.end()) { 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (address >= iter->start && address < iter->end && 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !iter->path.empty()) { 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ++iter; 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *os << base::StringPrintf("#%02zd " FMT_ADDR " ", i, address); 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (iter != regions.end()) { 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uintptr_t rel_pc = address - iter->start + iter->offset; 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* path = iter->path.c_str(); 11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *os << base::StringPrintf("%s+" FMT_ADDR, path, rel_pc); 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *os << "<unknown>"; 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *os << "\n"; 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace debug 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 129