| Index: kernel_collector.cc
|
| diff --git a/kernel_collector.cc b/kernel_collector.cc
|
| index 652e7ff3a0d5875ca5e9d92f63161d03328d4000..56fa301f77872fa60b79c7c9fd8d53296ab14baa 100644
|
| --- a/kernel_collector.cc
|
| +++ b/kernel_collector.cc
|
| @@ -24,9 +24,31 @@ static const int kSignatureTimestampWindow = 2;
|
| // Kernel log timestamp regular expression.
|
| static const std::string kTimestampRegex("^<.*>\\[\\s*(\\d+\\.\\d+)\\]");
|
|
|
| +/*
|
| + * These regular expressions enable to us capture the PC in a backtrace.
|
| + * The backtrace is obtained through dmesg or the kernel's preserved/kcrashmem
|
| + * feature.
|
| + *
|
| + * For ARM we see:
|
| + * "<5>[ 39.458982] PC is at write_breakme+0xd0/0x1b4"
|
| + * For x86:
|
| + * "<0>[ 37.474699] EIP: [<790ed488>] write_breakme+0x80/0x108 \
|
| + * SS:ESP 0068:e9dd3efc
|
| + */
|
| +static const char *s_pc_regex[] = {
|
| + 0,
|
| + " PC is at ([^\\+ ]+).*",
|
| + " EIP: \\[<.*>\\] ([^\\+ ]+).*", // X86 uses EIP for the program counter
|
| +};
|
| +
|
| +COMPILE_ASSERT(arraysize(s_pc_regex) == KernelCollector::archCount,
|
| + missing_arch_pc_regexp);
|
| +
|
| KernelCollector::KernelCollector()
|
| : is_enabled_(false),
|
| preserved_dump_path_(kPreservedDumpPath) {
|
| + // We expect crash dumps in the format of the architecture we are built for.
|
| + arch_ = GetCompilerArch();
|
| }
|
|
|
| KernelCollector::~KernelCollector() {
|
| @@ -47,7 +69,12 @@ bool KernelCollector::LoadPreservedDump(std::string *contents) {
|
| }
|
|
|
| bool KernelCollector::Enable() {
|
| - if (!file_util::PathExists(preserved_dump_path_)) {
|
| + if (arch_ == archUnknown || arch_ >= archCount ||
|
| + s_pc_regex[arch_] == NULL) {
|
| + LOG(WARNING) << "KernelCollector does not understand this architecture";
|
| + return false;
|
| + }
|
| + else if (!file_util::PathExists(preserved_dump_path_)) {
|
| LOG(WARNING) << "Kernel does not support crash dumping";
|
| return false;
|
| }
|
| @@ -90,11 +117,21 @@ void KernelCollector::ProcessStackTrace(
|
| unsigned *hash,
|
| float *last_stack_timestamp) {
|
| pcrecpp::RE line_re("(.+)", pcrecpp::MULTILINE());
|
| - pcrecpp::RE stack_trace_start_re(kTimestampRegex + " Call Trace:$");
|
| + pcrecpp::RE stack_trace_start_re(kTimestampRegex +
|
| + " (Call Trace|Backtrace):$");
|
| +
|
| + // For ARM:
|
| + // <4>[ 3498.731164] [<c0057220>] (__bug+0x20/0x2c) from [<c018062c>]
|
| + // (write_breakme+0xdc/0x1bc)
|
| + //
|
| + // For X86:
|
| // Match lines such as the following and grab out "error_code".
|
| - // <4>[ 6066.849504] [<7937bcee>] error_code+0x66/0x6c
|
| + // <4>[ 6066.849504] [<7937bcee>] ? error_code+0x66/0x6c
|
| + // The ? may or may not be present
|
| pcrecpp::RE stack_entry_re(kTimestampRegex +
|
| - " \\[<.*>\\]([\\s\\?]+)([^\\+ ]+)");
|
| + "\\s+\\[<[[:xdigit:]]+>\\]" // Matches " [<7937bcee>]"
|
| + "([\\s\\?(]+)" // Matches " ? (" (ARM) or " ? " (X86)
|
| + "([^\\+ )]+)"); // Matches until delimiter reached
|
| std::string line;
|
| std::string hashable;
|
|
|
| @@ -137,14 +174,33 @@ void KernelCollector::ProcessStackTrace(
|
| }
|
| }
|
|
|
| +enum KernelCollector::ArchKind KernelCollector::GetCompilerArch(void)
|
| +{
|
| +#if defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
|
| + return archArm;
|
| +#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
|
| + return archX86;
|
| +#else
|
| + return archUnknown;
|
| +#endif
|
| +}
|
| +
|
| +void KernelCollector::SetArch(enum ArchKind arch)
|
| +{
|
| + arch_ = arch;
|
| +}
|
| +
|
| bool KernelCollector::FindCrashingFunction(
|
| - pcrecpp::StringPiece kernel_dump,
|
| - bool print_diagnostics,
|
| - float stack_trace_timestamp,
|
| - std::string *crashing_function) {
|
| - pcrecpp::RE eip_re(kTimestampRegex + " EIP: \\[<.*>\\] ([^\\+ ]+).*",
|
| - pcrecpp::MULTILINE());
|
| + pcrecpp::StringPiece kernel_dump,
|
| + bool print_diagnostics,
|
| + float stack_trace_timestamp,
|
| + std::string *crashing_function) {
|
| float timestamp = 0;
|
| +
|
| + // Use the correct regex for this architecture.
|
| + pcrecpp::RE eip_re(kTimestampRegex + s_pc_regex[arch_],
|
| + pcrecpp::MULTILINE());
|
| +
|
| while (eip_re.FindAndConsume(&kernel_dump, ×tamp, crashing_function)) {
|
| if (print_diagnostics) {
|
| printf("@%f: found crashing function %s\n",
|
|
|