#endif
}
-void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc,
- const struct _libc_fpstate* fpregs) {
+void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc) {
out->context_flags = MD_CONTEXT_ARM_FULL;
out->iregs[0] = uc->uc_mcontext.arm_r0;
my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
}
+#elif defined(__aarch64__)
+typedef MDRawContextARM64 RawContextCPU;
+
+void CPUFillFromThreadInfo(MDRawContextARM64* out,
+ const google_breakpad::ThreadInfo& info) {
+ 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) {
+ 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__)
typedef MDRawContextMIPS RawContextCPU;
out->float_save.fir = info.fpregs.fir;
}
-static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc,
- const struct _libc_fpstate* fpregs) {
+static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc) {
out->context_flags = MD_CONTEXT_MIPS_FULL;
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
ucontext_(context ? &context->context : NULL),
#if !defined(__ARM_EABI__) && !defined(__mips__)
float_state_(context ? &context->float_state : NULL),
-#else
- // TODO: fix this after fixing ExceptionHandler
- float_state_(NULL),
#endif
dumper_(dumper),
minidump_size_limit_(-1),
if (!cpu.Allocate())
return false;
my_memset(cpu.get(), 0, sizeof(RawContextCPU));
+#if !defined(__ARM_EABI__) && !defined(__mips__)
CPUFillFromUContext(cpu.get(), ucontext_, float_state_);
+#else
+ CPUFillFromUContext(cpu.get(), ucontext_);
+#endif
if (stack_copy)
PopSeccompStackFrame(cpu.get(), thread, stack_copy);
thread.thread_context = cpu.location();
uintptr_t GetInstructionPointer(const ThreadInfo& info) {
return info.regs.uregs[15];
}
+#elif defined(__aarch64__)
+ uintptr_t GetStackPointer() {
+ return ucontext_->uc_mcontext.sp;
+ }
+
+ uintptr_t GetInstructionPointer() {
+ return ucontext_->uc_mcontext.pc;
+ }
+
+ uintptr_t GetInstructionPointer(const ThreadInfo& info) {
+ return info.regs.pc;
+ }
#elif defined(__mips__)
uintptr_t GetStackPointer() {
return ucontext_->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
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 },
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;
}
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.
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 },
{ "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)
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"
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.
const char* path_; // Path to the file where the minidum should be written.
const struct ucontext* const ucontext_; // also from the signal handler
- const struct _libc_fpstate* const float_state_; // ditto
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ const google_breakpad::fpstate_t* const float_state_; // ditto
+#endif
LinuxDumper* dumper_;
MinidumpFileWriter minidump_writer_;
off_t minidump_size_limit_;