diff options
Diffstat (limited to 'src/processor')
-rw-r--r-- | src/processor/minidump_processor.cc | 123 | ||||
-rw-r--r-- | src/processor/synth_minidump.cc | 3 |
2 files changed, 126 insertions, 0 deletions
diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index afe15ca6..2d14cb37 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -305,6 +305,128 @@ static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, return minidump_system_info->system_info(); } +// Extract CPU info string from ARM-specific MDRawSystemInfo structure. +// raw_info: pointer to source MDRawSystemInfo. +// cpu_info: address of target string, cpu info text will be appended to it. +static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, + std::string* cpu_info) { + assert(raw_info != NULL && cpu_info != NULL); + + // Write ARM architecture version. + char cpu_string[32]; + snprintf(cpu_string, sizeof(cpu_string), "ARMv%d", + raw_info->processor_level); + cpu_info->append(cpu_string); + + // There is no good list of implementer id values, but the following + // pages provide some help: + // http://comments.gmane.org/gmane.linux.linaro.devel/6903 + // http://forum.xda-developers.com/archive/index.php/t-480226.html + const struct { + uint32_t id; + const char* name; + } vendors[] = { + { 0x41, "ARM" }, + { 0x51, "Qualcomm" }, + { 0x56, "Marvell" }, + { 0x69, "Intel/Marvell" }, + }; + const struct { + uint32_t id; + const char* name; + } parts[] = { + { 0x4100c050, "Cortex-A5" }, + { 0x4100c080, "Cortex-A8" }, + { 0x4100c090, "Cortex-A9" }, + { 0x4100c0f0, "Cortex-A15" }, + { 0x4100c140, "Cortex-R4" }, + { 0x4100c150, "Cortex-R5" }, + { 0x4100b360, "ARM1136" }, + { 0x4100b560, "ARM1156" }, + { 0x4100b760, "ARM1176" }, + { 0x4100b020, "ARM11-MPCore" }, + { 0x41009260, "ARM926" }, + { 0x41009460, "ARM946" }, + { 0x41009660, "ARM966" }, + { 0x510006f0, "Krait" }, + { 0x510000f0, "Scorpion" }, + }; + + const struct { + uint32_t hwcap; + const char* name; + } features[] = { + { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" }, + { MD_CPU_ARM_ELF_HWCAP_HALF, "half" }, + { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" }, + { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" }, + { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" }, + { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" }, + { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" }, + { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" }, + { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" }, + { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" }, + { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" }, + { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" }, + { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" }, + { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" }, + { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" }, + { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" }, + { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" }, + { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" }, + { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" }, + }; + + uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; + if (cpuid != 0) { + // Extract vendor name from CPUID + const char* vendor = NULL; + uint32_t vendor_id = (cpuid >> 24) & 0xff; + for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { + if (vendors[i].id == vendor_id) { + vendor = vendors[i].name; + break; + } + } + cpu_info->append(" "); + if (vendor) { + cpu_info->append(vendor); + } else { + snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id); + cpu_info->append(cpu_string); + } + + // Extract part name from CPUID + uint32_t part_id = (cpuid & 0xff00fff0); + const char* part = NULL; + for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { + if (parts[i].id == part_id) { + part = parts[i].name; + break; + } + } + cpu_info->append(" "); + if (part != NULL) { + cpu_info->append(part); + } else { + snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); + cpu_info->append(cpu_string); + } + } + uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps; + if (elf_hwcaps != 0) { + cpu_info->append(" features: "); + const char* comma = ""; + for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) { + if (elf_hwcaps & features[i].hwcap) { + cpu_info->append(comma); + cpu_info->append(features[i].name); + comma = ","; + } + } + } +} + // static bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { assert(dump); @@ -359,6 +481,7 @@ bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { case MD_CPU_ARCHITECTURE_ARM: { info->cpu = "arm"; + GetARMCpuInfo(raw_system_info, &info->cpu_info); break; } diff --git a/src/processor/synth_minidump.cc b/src/processor/synth_minidump.cc index 377368ac..0940a357 100644 --- a/src/processor/synth_minidump.cc +++ b/src/processor/synth_minidump.cc @@ -77,6 +77,9 @@ SystemInfo::SystemInfo(const Dump &dump, D32(system_info.cpu.x86_cpu_info.version_information); D32(system_info.cpu.x86_cpu_info.feature_information); D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features); + } else if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_ARM) { + D32(system_info.cpu.arm_cpu_info.cpuid); + D32(system_info.cpu.arm_cpu_info.elf_hwcaps); } else { D64(system_info.cpu.other_cpu_info.processor_features[0]); D64(system_info.cpu.other_cpu_info.processor_features[1]); |