Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "runtime_common.h"
     18 
     19 #include <signal.h>
     20 
     21 #include <cinttypes>
     22 #include <iostream>
     23 #include <sstream>
     24 #include <string>
     25 
     26 #include <android-base/logging.h>
     27 #include <android-base/stringprintf.h>
     28 
     29 #include "base/aborting.h"
     30 #include "base/file_utils.h"
     31 #include "base/logging.h"  // For LogHelper, GetCmdLine.
     32 #include "base/macros.h"
     33 #include "base/mutex.h"
     34 #include "native_stack_dump.h"
     35 #include "runtime.h"
     36 #include "thread-current-inl.h"
     37 #include "thread_list.h"
     38 
     39 namespace art {
     40 
     41 using android::base::StringPrintf;
     42 
     43 static constexpr bool kUseSigRTTimeout = true;
     44 static constexpr bool kDumpNativeStackOnTimeout = true;
     45 
     46 const char* GetSignalName(int signal_number) {
     47   switch (signal_number) {
     48     case SIGABRT: return "SIGABRT";
     49     case SIGBUS: return "SIGBUS";
     50     case SIGFPE: return "SIGFPE";
     51     case SIGILL: return "SIGILL";
     52     case SIGPIPE: return "SIGPIPE";
     53     case SIGSEGV: return "SIGSEGV";
     54 #if defined(SIGSTKFLT)
     55     case SIGSTKFLT: return "SIGSTKFLT";
     56 #endif
     57     case SIGTRAP: return "SIGTRAP";
     58   }
     59   return "??";
     60 }
     61 
     62 const char* GetSignalCodeName(int signal_number, int signal_code) {
     63   // Try the signal-specific codes...
     64   switch (signal_number) {
     65     case SIGILL:
     66       switch (signal_code) {
     67         case ILL_ILLOPC: return "ILL_ILLOPC";
     68         case ILL_ILLOPN: return "ILL_ILLOPN";
     69         case ILL_ILLADR: return "ILL_ILLADR";
     70         case ILL_ILLTRP: return "ILL_ILLTRP";
     71         case ILL_PRVOPC: return "ILL_PRVOPC";
     72         case ILL_PRVREG: return "ILL_PRVREG";
     73         case ILL_COPROC: return "ILL_COPROC";
     74         case ILL_BADSTK: return "ILL_BADSTK";
     75       }
     76       break;
     77     case SIGBUS:
     78       switch (signal_code) {
     79         case BUS_ADRALN: return "BUS_ADRALN";
     80         case BUS_ADRERR: return "BUS_ADRERR";
     81         case BUS_OBJERR: return "BUS_OBJERR";
     82       }
     83       break;
     84     case SIGFPE:
     85       switch (signal_code) {
     86         case FPE_INTDIV: return "FPE_INTDIV";
     87         case FPE_INTOVF: return "FPE_INTOVF";
     88         case FPE_FLTDIV: return "FPE_FLTDIV";
     89         case FPE_FLTOVF: return "FPE_FLTOVF";
     90         case FPE_FLTUND: return "FPE_FLTUND";
     91         case FPE_FLTRES: return "FPE_FLTRES";
     92         case FPE_FLTINV: return "FPE_FLTINV";
     93         case FPE_FLTSUB: return "FPE_FLTSUB";
     94       }
     95       break;
     96     case SIGSEGV:
     97       switch (signal_code) {
     98         case SEGV_MAPERR: return "SEGV_MAPERR";
     99         case SEGV_ACCERR: return "SEGV_ACCERR";
    100 #if defined(SEGV_BNDERR)
    101         case SEGV_BNDERR: return "SEGV_BNDERR";
    102 #endif
    103       }
    104       break;
    105     case SIGTRAP:
    106       switch (signal_code) {
    107         case TRAP_BRKPT: return "TRAP_BRKPT";
    108         case TRAP_TRACE: return "TRAP_TRACE";
    109       }
    110       break;
    111   }
    112   // Then the other codes...
    113   switch (signal_code) {
    114     case SI_USER:     return "SI_USER";
    115 #if defined(SI_KERNEL)
    116     case SI_KERNEL:   return "SI_KERNEL";
    117 #endif
    118     case SI_QUEUE:    return "SI_QUEUE";
    119     case SI_TIMER:    return "SI_TIMER";
    120     case SI_MESGQ:    return "SI_MESGQ";
    121     case SI_ASYNCIO:  return "SI_ASYNCIO";
    122 #if defined(SI_SIGIO)
    123     case SI_SIGIO:    return "SI_SIGIO";
    124 #endif
    125 #if defined(SI_TKILL)
    126     case SI_TKILL:    return "SI_TKILL";
    127 #endif
    128   }
    129   // Then give up...
    130   return "?";
    131 }
    132 
    133 struct UContext {
    134   explicit UContext(void* raw_context)
    135       : context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) {}
    136 
    137   void Dump(std::ostream& os) const;
    138 
    139   void DumpRegister32(std::ostream& os, const char* name, uint32_t value) const;
    140   void DumpRegister64(std::ostream& os, const char* name, uint64_t value) const;
    141 
    142   void DumpX86Flags(std::ostream& os, uint32_t flags) const;
    143   // Print some of the information from the status register (CPSR on ARMv7, PSTATE on ARMv8).
    144   template <typename RegisterType>
    145   void DumpArmStatusRegister(std::ostream& os, RegisterType status_register) const;
    146 
    147   mcontext_t& context;
    148 };
    149 
    150 void UContext::Dump(std::ostream& os) const {
    151 #if defined(__APPLE__) && defined(__i386__)
    152   DumpRegister32(os, "eax", context->__ss.__eax);
    153   DumpRegister32(os, "ebx", context->__ss.__ebx);
    154   DumpRegister32(os, "ecx", context->__ss.__ecx);
    155   DumpRegister32(os, "edx", context->__ss.__edx);
    156   os << '\n';
    157 
    158   DumpRegister32(os, "edi", context->__ss.__edi);
    159   DumpRegister32(os, "esi", context->__ss.__esi);
    160   DumpRegister32(os, "ebp", context->__ss.__ebp);
    161   DumpRegister32(os, "esp", context->__ss.__esp);
    162   os << '\n';
    163 
    164   DumpRegister32(os, "eip", context->__ss.__eip);
    165   os << "                   ";
    166   DumpRegister32(os, "eflags", context->__ss.__eflags);
    167   DumpX86Flags(os, context->__ss.__eflags);
    168   os << '\n';
    169 
    170   DumpRegister32(os, "cs",  context->__ss.__cs);
    171   DumpRegister32(os, "ds",  context->__ss.__ds);
    172   DumpRegister32(os, "es",  context->__ss.__es);
    173   DumpRegister32(os, "fs",  context->__ss.__fs);
    174   os << '\n';
    175   DumpRegister32(os, "gs",  context->__ss.__gs);
    176   DumpRegister32(os, "ss",  context->__ss.__ss);
    177 #elif defined(__linux__) && defined(__i386__)
    178   DumpRegister32(os, "eax", context.gregs[REG_EAX]);
    179   DumpRegister32(os, "ebx", context.gregs[REG_EBX]);
    180   DumpRegister32(os, "ecx", context.gregs[REG_ECX]);
    181   DumpRegister32(os, "edx", context.gregs[REG_EDX]);
    182   os << '\n';
    183 
    184   DumpRegister32(os, "edi", context.gregs[REG_EDI]);
    185   DumpRegister32(os, "esi", context.gregs[REG_ESI]);
    186   DumpRegister32(os, "ebp", context.gregs[REG_EBP]);
    187   DumpRegister32(os, "esp", context.gregs[REG_ESP]);
    188   os << '\n';
    189 
    190   DumpRegister32(os, "eip", context.gregs[REG_EIP]);
    191   os << "                   ";
    192   DumpRegister32(os, "eflags", context.gregs[REG_EFL]);
    193   DumpX86Flags(os, context.gregs[REG_EFL]);
    194   os << '\n';
    195 
    196   DumpRegister32(os, "cs",  context.gregs[REG_CS]);
    197   DumpRegister32(os, "ds",  context.gregs[REG_DS]);
    198   DumpRegister32(os, "es",  context.gregs[REG_ES]);
    199   DumpRegister32(os, "fs",  context.gregs[REG_FS]);
    200   os << '\n';
    201   DumpRegister32(os, "gs",  context.gregs[REG_GS]);
    202   DumpRegister32(os, "ss",  context.gregs[REG_SS]);
    203 #elif defined(__linux__) && defined(__x86_64__)
    204   DumpRegister64(os, "rax", context.gregs[REG_RAX]);
    205   DumpRegister64(os, "rbx", context.gregs[REG_RBX]);
    206   DumpRegister64(os, "rcx", context.gregs[REG_RCX]);
    207   DumpRegister64(os, "rdx", context.gregs[REG_RDX]);
    208   os << '\n';
    209 
    210   DumpRegister64(os, "rdi", context.gregs[REG_RDI]);
    211   DumpRegister64(os, "rsi", context.gregs[REG_RSI]);
    212   DumpRegister64(os, "rbp", context.gregs[REG_RBP]);
    213   DumpRegister64(os, "rsp", context.gregs[REG_RSP]);
    214   os << '\n';
    215 
    216   DumpRegister64(os, "r8 ", context.gregs[REG_R8]);
    217   DumpRegister64(os, "r9 ", context.gregs[REG_R9]);
    218   DumpRegister64(os, "r10", context.gregs[REG_R10]);
    219   DumpRegister64(os, "r11", context.gregs[REG_R11]);
    220   os << '\n';
    221 
    222   DumpRegister64(os, "r12", context.gregs[REG_R12]);
    223   DumpRegister64(os, "r13", context.gregs[REG_R13]);
    224   DumpRegister64(os, "r14", context.gregs[REG_R14]);
    225   DumpRegister64(os, "r15", context.gregs[REG_R15]);
    226   os << '\n';
    227 
    228   DumpRegister64(os, "rip", context.gregs[REG_RIP]);
    229   os << "   ";
    230   DumpRegister32(os, "eflags", context.gregs[REG_EFL]);
    231   DumpX86Flags(os, context.gregs[REG_EFL]);
    232   os << '\n';
    233 
    234   DumpRegister32(os, "cs",  (context.gregs[REG_CSGSFS]) & 0x0FFFF);
    235   DumpRegister32(os, "gs",  (context.gregs[REG_CSGSFS] >> 16) & 0x0FFFF);
    236   DumpRegister32(os, "fs",  (context.gregs[REG_CSGSFS] >> 32) & 0x0FFFF);
    237   os << '\n';
    238 #elif defined(__linux__) && defined(__arm__)
    239   DumpRegister32(os, "r0", context.arm_r0);
    240   DumpRegister32(os, "r1", context.arm_r1);
    241   DumpRegister32(os, "r2", context.arm_r2);
    242   DumpRegister32(os, "r3", context.arm_r3);
    243   os << '\n';
    244 
    245   DumpRegister32(os, "r4", context.arm_r4);
    246   DumpRegister32(os, "r5", context.arm_r5);
    247   DumpRegister32(os, "r6", context.arm_r6);
    248   DumpRegister32(os, "r7", context.arm_r7);
    249   os << '\n';
    250 
    251   DumpRegister32(os, "r8", context.arm_r8);
    252   DumpRegister32(os, "r9", context.arm_r9);
    253   DumpRegister32(os, "r10", context.arm_r10);
    254   DumpRegister32(os, "fp", context.arm_fp);
    255   os << '\n';
    256 
    257   DumpRegister32(os, "ip", context.arm_ip);
    258   DumpRegister32(os, "sp", context.arm_sp);
    259   DumpRegister32(os, "lr", context.arm_lr);
    260   DumpRegister32(os, "pc", context.arm_pc);
    261   os << '\n';
    262 
    263   DumpRegister32(os, "cpsr", context.arm_cpsr);
    264   DumpArmStatusRegister(os, context.arm_cpsr);
    265   os << '\n';
    266 #elif defined(__linux__) && defined(__aarch64__)
    267   for (size_t i = 0; i <= 30; ++i) {
    268     std::string reg_name = "x" + std::to_string(i);
    269     DumpRegister64(os, reg_name.c_str(), context.regs[i]);
    270     if (i % 4 == 3) {
    271       os << '\n';
    272     }
    273   }
    274   os << '\n';
    275 
    276   DumpRegister64(os, "sp", context.sp);
    277   DumpRegister64(os, "pc", context.pc);
    278   os << '\n';
    279 
    280   DumpRegister64(os, "pstate", context.pstate);
    281   DumpArmStatusRegister(os, context.pstate);
    282   os << '\n';
    283 #else
    284   // TODO: Add support for MIPS32 and MIPS64.
    285   os << "Unknown architecture/word size/OS in ucontext dump";
    286 #endif
    287 }
    288 
    289 void UContext::DumpRegister32(std::ostream& os, const char* name, uint32_t value) const {
    290   os << StringPrintf(" %6s: 0x%08x", name, value);
    291 }
    292 
    293 void UContext::DumpRegister64(std::ostream& os, const char* name, uint64_t value) const {
    294   os << StringPrintf(" %6s: 0x%016" PRIx64, name, value);
    295 }
    296 
    297 void UContext::DumpX86Flags(std::ostream& os, uint32_t flags) const {
    298   os << " [";
    299   if ((flags & (1 << 0)) != 0) {
    300     os << " CF";
    301   }
    302   if ((flags & (1 << 2)) != 0) {
    303     os << " PF";
    304   }
    305   if ((flags & (1 << 4)) != 0) {
    306     os << " AF";
    307   }
    308   if ((flags & (1 << 6)) != 0) {
    309     os << " ZF";
    310   }
    311   if ((flags & (1 << 7)) != 0) {
    312     os << " SF";
    313   }
    314   if ((flags & (1 << 8)) != 0) {
    315     os << " TF";
    316   }
    317   if ((flags & (1 << 9)) != 0) {
    318     os << " IF";
    319   }
    320   if ((flags & (1 << 10)) != 0) {
    321     os << " DF";
    322   }
    323   if ((flags & (1 << 11)) != 0) {
    324     os << " OF";
    325   }
    326   os << " ]";
    327 }
    328 
    329 template <typename RegisterType>
    330 void UContext::DumpArmStatusRegister(std::ostream& os, RegisterType status_register) const {
    331   // Condition flags.
    332   constexpr RegisterType kFlagV = 1U << 28;
    333   constexpr RegisterType kFlagC = 1U << 29;
    334   constexpr RegisterType kFlagZ = 1U << 30;
    335   constexpr RegisterType kFlagN = 1U << 31;
    336 
    337   os << " [";
    338   if ((status_register & kFlagN) != 0) {
    339     os << " N";
    340   }
    341   if ((status_register & kFlagZ) != 0) {
    342     os << " Z";
    343   }
    344   if ((status_register & kFlagC) != 0) {
    345     os << " C";
    346   }
    347   if ((status_register & kFlagV) != 0) {
    348     os << " V";
    349   }
    350   os << " ]";
    351 }
    352 
    353 int GetTimeoutSignal() {
    354 #if defined(__APPLE__)
    355   // Mac does not support realtime signals.
    356   UNUSED(kUseSigRTTimeout);
    357   return -1;
    358 #else
    359   return kUseSigRTTimeout ? (SIGRTMIN + 2) : -1;
    360 #endif
    361 }
    362 
    363 static bool IsTimeoutSignal(int signal_number) {
    364   return signal_number == GetTimeoutSignal();
    365 }
    366 
    367 #if defined(__APPLE__)
    368 // On macOS, clang complains about art::HandleUnexpectedSignalCommon's
    369 // stack frame size being too large; disable that warning locally.
    370 #pragma GCC diagnostic push
    371 #pragma GCC diagnostic ignored "-Wframe-larger-than="
    372 #endif
    373 
    374 void HandleUnexpectedSignalCommon(int signal_number,
    375                                   siginfo_t* info,
    376                                   void* raw_context,
    377                                   bool handle_timeout_signal,
    378                                   bool dump_on_stderr) {
    379   static bool handling_unexpected_signal = false;
    380   if (handling_unexpected_signal) {
    381     LogHelper::LogLineLowStack(__FILE__,
    382                                __LINE__,
    383                                ::android::base::FATAL_WITHOUT_ABORT,
    384                                "HandleUnexpectedSignal reentered\n");
    385     if (handle_timeout_signal) {
    386       if (IsTimeoutSignal(signal_number)) {
    387         // Ignore a recursive timeout.
    388         return;
    389       }
    390     }
    391     _exit(1);
    392   }
    393   handling_unexpected_signal = true;
    394 
    395   gAborting++;  // set before taking any locks
    396   MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_);
    397 
    398   auto logger = [&](auto& stream) {
    399     bool has_address = (signal_number == SIGILL || signal_number == SIGBUS ||
    400                         signal_number == SIGFPE || signal_number == SIGSEGV);
    401     OsInfo os_info;
    402     const char* cmd_line = GetCmdLine();
    403     if (cmd_line == nullptr) {
    404       cmd_line = "<unset>";  // Because no-one called InitLogging.
    405     }
    406     pid_t tid = GetTid();
    407     std::string thread_name(GetThreadName(tid));
    408     UContext thread_context(raw_context);
    409     Backtrace thread_backtrace(raw_context);
    410 
    411     stream << "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***" << std::endl
    412            << StringPrintf("Fatal signal %d (%s), code %d (%s)",
    413                              signal_number,
    414                              GetSignalName(signal_number),
    415                              info->si_code,
    416                              GetSignalCodeName(signal_number, info->si_code))
    417            << (has_address ? StringPrintf(" fault addr %p", info->si_addr) : "") << std::endl
    418            << "OS: " << Dumpable<OsInfo>(os_info) << std::endl
    419            << "Cmdline: " << cmd_line << std::endl
    420            << "Thread: " << tid << " \"" << thread_name << "\"" << std::endl
    421            << "Registers:\n" << Dumpable<UContext>(thread_context) << std::endl
    422            << "Backtrace:\n" << Dumpable<Backtrace>(thread_backtrace) << std::endl;
    423     stream << std::flush;
    424   };
    425 
    426   if (dump_on_stderr) {
    427     // Note: We are using cerr directly instead of LOG macros to ensure even just partial output
    428     //       makes it out. That means we lose the "dalvikvm..." prefix, but that is acceptable
    429     //       considering this is an abort situation.
    430     logger(std::cerr);
    431   } else {
    432     logger(LOG_STREAM(FATAL_WITHOUT_ABORT));
    433   }
    434   if (kIsDebugBuild && signal_number == SIGSEGV) {
    435     PrintFileToLog("/proc/self/maps", android::base::LogSeverity::FATAL_WITHOUT_ABORT);
    436   }
    437 
    438   Runtime* runtime = Runtime::Current();
    439   if (runtime != nullptr) {
    440     if (handle_timeout_signal && IsTimeoutSignal(signal_number)) {
    441       // Special timeout signal. Try to dump all threads.
    442       // Note: Do not use DumpForSigQuit, as that might disable native unwind, but the native parts
    443       //       are of value here.
    444       runtime->GetThreadList()->Dump(std::cerr, kDumpNativeStackOnTimeout);
    445       std::cerr << std::endl;
    446     }
    447 
    448     if (dump_on_stderr) {
    449       std::cerr << "Fault message: " << runtime->GetFaultMessage() << std::endl;
    450     } else {
    451       LOG(FATAL_WITHOUT_ABORT) << "Fault message: " << runtime->GetFaultMessage();
    452     }
    453   }
    454 }
    455 
    456 #if defined(__APPLE__)
    457 #pragma GCC diagnostic pop
    458 #endif
    459 
    460 void InitPlatformSignalHandlersCommon(void (*newact)(int, siginfo_t*, void*),
    461                                       struct sigaction* oldact,
    462                                       bool handle_timeout_signal) {
    463   struct sigaction action;
    464   memset(&action, 0, sizeof(action));
    465   sigemptyset(&action.sa_mask);
    466   action.sa_sigaction = newact;
    467   // Use the three-argument sa_sigaction handler.
    468   action.sa_flags |= SA_SIGINFO;
    469   // Use the alternate signal stack so we can catch stack overflows.
    470   action.sa_flags |= SA_ONSTACK;
    471 
    472   int rc = 0;
    473   rc += sigaction(SIGABRT, &action, oldact);
    474   rc += sigaction(SIGBUS, &action, oldact);
    475   rc += sigaction(SIGFPE, &action, oldact);
    476   rc += sigaction(SIGILL, &action, oldact);
    477   rc += sigaction(SIGPIPE, &action, oldact);
    478   rc += sigaction(SIGSEGV, &action, oldact);
    479 #if defined(SIGSTKFLT)
    480   rc += sigaction(SIGSTKFLT, &action, oldact);
    481 #endif
    482   rc += sigaction(SIGTRAP, &action, oldact);
    483   // Special dump-all timeout.
    484   if (handle_timeout_signal && GetTimeoutSignal() != -1) {
    485     rc += sigaction(GetTimeoutSignal(), &action, oldact);
    486   }
    487   CHECK_EQ(rc, 0);
    488 }
    489 
    490 }  // namespace art
    491