diff options
Diffstat (limited to 'src/client/linux')
-rw-r--r-- | src/client/linux/minidump_writer/minidump_writer.cc | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index ce8503d2..43c1ef2c 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -378,12 +378,34 @@ typedef MDRawContextARM64 RawContextCPU; void CPUFillFromThreadInfo(MDRawContextARM64* out, const google_breakpad::ThreadInfo& info) { - // TODO(rmcilroy): Implement for arm64. + out->context_flags = MD_CONTEXT_ARM64_FULL; + + out->cpsr = static_cast<uint32_t>(info.regs.pstate); + for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i) + out->iregs[i] = info.regs.regs[i]; + out->iregs[MD_CONTEXT_ARM64_REG_SP] = info.regs.sp; + out->iregs[MD_CONTEXT_ARM64_REG_PC] = info.regs.pc; + + out->float_save.fpsr = info.fpregs.fpsr; + out->float_save.fpcr = info.fpregs.fpcr; + my_memcpy(&out->float_save.regs, &info.fpregs.vregs, + MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16); } void CPUFillFromUContext(MDRawContextARM64* out, const ucontext* uc, const struct fpsimd_context* fpregs) { - // TODO(rmcilroy): Implement for arm64. + out->context_flags = MD_CONTEXT_ARM64_FULL; + + out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate); + for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i) + out->iregs[i] = uc->uc_mcontext.regs[i]; + out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp; + out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc; + + out->float_save.fpsr = fpregs->fpsr; + out->float_save.fpcr = fpregs->fpcr; + my_memcpy(&out->float_save.regs, &fpregs->vregs, + MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16); } #elif defined(__mips__) @@ -1328,7 +1350,7 @@ class MinidumpWriter { bool found; } cpu_info_table[] = { { "processor", -1, false }, -#if !defined(__mips__) +#if defined(__i386__) || defined(__x86_64__) { "model", 0, false }, { "stepping", 0, false }, { "cpu family", 0, false }, @@ -1402,7 +1424,7 @@ class MinidumpWriter { cpu_info_table[0].value++; sys_info->number_of_processors = cpu_info_table[0].value; -#if !defined(__mips__) +#if defined(__i386__) || defined(__x86_64__) sys_info->processor_level = cpu_info_table[3].value; sys_info->processor_revision = cpu_info_table[1].value << 8 | cpu_info_table[2].value; @@ -1414,7 +1436,7 @@ class MinidumpWriter { } return true; } -#elif defined(__arm__) +#elif defined(__arm__) || defined(__aarch64__) bool WriteCPUInformation(MDRawSystemInfo* sys_info) { // The CPUID value is broken up in several entries in /proc/cpuinfo. // This table is used to rebuild it from the entries. @@ -1436,6 +1458,7 @@ class MinidumpWriter { const char* tag; uint32_t hwcaps; } cpu_features_entries[] = { +#if defined(__arm__) { "swp", MD_CPU_ARM_ELF_HWCAP_SWP }, { "half", MD_CPU_ARM_ELF_HWCAP_HALF }, { "thumb", MD_CPU_ARM_ELF_HWCAP_THUMB }, @@ -1456,10 +1479,18 @@ class MinidumpWriter { { "idiva", MD_CPU_ARM_ELF_HWCAP_IDIVA }, { "idivt", MD_CPU_ARM_ELF_HWCAP_IDIVT }, { "idiv", MD_CPU_ARM_ELF_HWCAP_IDIVA | MD_CPU_ARM_ELF_HWCAP_IDIVT }, +#elif defined(__aarch64__) + // No hwcaps on aarch64. +#endif }; // processor_architecture should always be set, do this first - sys_info->processor_architecture = MD_CPU_ARCHITECTURE_ARM; + sys_info->processor_architecture = +#if defined(__aarch64__) + MD_CPU_ARCHITECTURE_ARM64; +#else + MD_CPU_ARCHITECTURE_ARM; +#endif // /proc/cpuinfo is not readable under various sandboxed environments // (e.g. Android services with the android:isolatedProcess attribute) @@ -1543,13 +1574,14 @@ class MinidumpWriter { sys_info->cpu.arm_cpu_info.cpuid |= static_cast<uint32_t>(result); } +#if defined(__arm__) // Get the architecture version from the "Processor" field. // Note that it is also available in the "CPU architecture" field, // however, some existing kernels are misconfigured and will report // invalid values here (e.g. 6, while the CPU is ARMv7-A based). // The "Processor" field doesn't have this issue. if (!my_strcmp(field, "Processor")) { - unsigned value_len; + size_t value_len; const char* value = reader->GetValueAndLen(&value_len); // Expected format: <text> (v<level><endian>) // Where <text> is some text like "ARMv7 Processor rev 2" @@ -1568,9 +1600,23 @@ class MinidumpWriter { sys_info->processor_level = static_cast<uint16_t>(arch_level); } } +#elif defined(__aarch64__) + // The aarch64 architecture does not provide the architecture level + // in the Processor field, so we instead check the "CPU architecture" + // field. + if (!my_strcmp(field, "CPU architecture")) { + uintptr_t arch_level = 0; + const char* value = reader->GetValue(); + const char* p = value; + p = my_read_decimal_ptr(&arch_level, value); + if (p == value) + continue; + sys_info->processor_level = static_cast<uint16_t>(arch_level); + } +#endif // Rebuild the ELF hwcaps from the 'Features' field. if (!my_strcmp(field, "Features")) { - unsigned value_len; + size_t value_len; const char* value = reader->GetValueAndLen(&value_len); // Parse each space-separated tag. @@ -1605,11 +1651,6 @@ class MinidumpWriter { return true; } -#elif defined(__aarch64__) - bool WriteCPUInformation(MDRawSystemInfo* sys_info) { - // TODO(rmcilroy): Implement for arm64. - return false; - } #else # error "Unsupported CPU" #endif |