Skip to content
Snippets Groups Projects
Commit 3071ceb1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "linux-ramdump-parser-v2: Add initial version of DDRCompare"

parents ca8e2a31 3409cb2b
No related branches found
No related tags found
No related merge requests found
# Copyright (c) 2014, The Linux Foundation. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import os
import struct
import re
import sys
import subprocess
from print_out import print_out_str
from parser_util import register_parser, RamParser
@register_parser('--ddr-compare', 'Sanity check the DDR data to find possible corruptions')
class DDRCompare(RamParser) :
def compare_magic(self):
self.output_file.write("----------------------------------------------------------------------------------------\n")
self.output_file.write("Comparing statically initialized lock values from vmlinux and ramdumps\n")
self.output_file.write("----------------------------------------------------------------------------------------\n")
if not self.ramdump.is_config_defined('CONFIG_DEBUG_SPINLOCK'):
self.output_file.write('Kernel Configuration for debug spinlocks is not enabled, cannot comapre the magic values!!\n\n')
return
elif self.ramdump.objdump_path is None:
self.output_file.write("!!! Objdump path is not set, please use --objdump-path option to specify the path\n\n")
return
cmd = self.ramdump.objdump_path + " -D -j.data " + self.ramdump.vmlinux
cmdarr = cmd.split(' ')
output = subprocess.Popen(cmdarr, stdout=subprocess.PIPE).communicate()[0]
foundcorruption = 0;
for line in output.split('\n'):
m = re.search("^(.*?):\s+(dead4ead|deaf1eed?)\s+\.word\s+(0x\\2?)", line)
if m:
virtual = m.group(1)
virtual = int(m.group(1), 16)
bitcheck = virtual & 0x3
if bitcheck:
virtual = virtual - bitcheck
physical = self.ramdump.virt_to_phys(virtual)
magic = hex(self.ramdump.read_u32(physical, False)).rstrip("L").lstrip("0x").zfill(8)
if (m.group(2) != magic):
foundcorruption = 1;
self.output_file.write("Magic didn't match for virtual address {0}\n".format("0x"+m.group(1)))
for i in range(2):
physical = physical - 4
dumpvalue = hex(self.ramdump.read_u32(physical, False)).rstrip("L").lstrip("0x").zfill(8)
self.output_file.write("{0}\n".format(dumpvalue))
physical = physical + 8
self.output_file.write("{0}\n".format(magic))
for i in range(2):
physical = physical + 4
dumpvalue = hex(self.ramdump.read_u32(physical, False)).rstrip("L").lstrip("0x").zfill(8)
self.output_file.write("{0}\n".format(dumpvalue))
if (foundcorruption == 0):
self.output_file.write("No Corruption found in the lock values\n\n")
def validate_sched_class(self, address):
sc_stop = self.ramdump.addr_lookup('stop_sched_class')
sc_rt = self.ramdump.addr_lookup('rt_sched_class')
sc_idle = self.ramdump.addr_lookup('idle_sched_class')
sc_fair = self.ramdump.addr_lookup('fair_sched_class')
sched_class_offset = address + self.ramdump.field_offset('struct task_struct', 'sched_class');
sched_class_pointer = self.ramdump.read_word(sched_class_offset, True)
if not ((sched_class_pointer == sc_stop) or (sched_class_pointer == sc_rt) or (sched_class_pointer == sc_idle) or (sched_class_pointer == sc_fair)):
self.output_file.write(hex(address) + " seems to be corrupted! sched_class doesn't match with the defined ones\n")
return -1;
def validate_task_struct(self, address):
thread_info_address = address + self.ramdump.field_offset('struct task_struct', 'stack');
thread_info_pointer = self.ramdump.read_word(thread_info_address, True)
task_address = thread_info_pointer + self.ramdump.field_offset('struct thread_info', 'task');
task_struct = self.ramdump.read_word(task_address, True)
cpu_address = thread_info_pointer + self.ramdump.field_offset('struct thread_info', 'cpu');
cpu_number = self.ramdump.read_u32(cpu_address, True)
if((address != task_struct) or (thread_info_pointer == 0x0)):
self.output_file.write(hex(address) + " seems to be corrupted! Please check task_struct and thread_info to find corruptions\n")
return -1
if((cpu_number < 0) or (cpu_number >= self.ramdump.get_num_cpus())):
self.output_file.write(hex(address) + " seems to be corrupted! CPU number " + str(int(cpu_number)) + " seems to be corrupted\n")
return -1
def check_thread_group(self, address, comm_offset_index):
thread_group_offset_index = self.ramdump.field_offset('struct task_struct', 'thread_group')
thread_group_offset = address + thread_group_offset_index;
thread_group_pointer = self.ramdump.read_word(thread_group_offset, True)
thread_group_pointer = thread_group_pointer - thread_group_offset_index
next = thread_group_pointer;
if(thread_group_pointer != address):
self.output_file.write("-----------------------------------\n")
self.output_file.write("Threads of 0x{0:x}\n".format(address))
self.output_file.write("-----------------------------------\n")
while 1:
tasks_offset = next + thread_group_offset_index;
task_pointer = self.ramdump.read_word(tasks_offset, True)
if(task_pointer <= 0x0):
self.output_file.write("task_pointer " + hex(task_pointer) + " calculcated from thread_group is corrupted\n")
return -1
task_struct = task_pointer - thread_group_offset_index;
if(task_struct <= 0x0):
self.output_file.write("task_struct " + hex(task_pointer) + " calculcated from thread_group is corrupted\n")
return -1
comm_offset = task_struct + comm_offset_index
comm = self.ramdump.read_cstring(comm_offset, 16, True)
self.output_file.write("Next = {0} ({1})\n".format(hex(task_struct).rstrip("L"), comm))
if (self.validate_task_struct(task_struct) == -1):
return -1
if (self.validate_sched_class(task_struct) == -1):
return -1
next = task_struct;
if (next == thread_group_pointer):
break
self.output_file.write("\n")
def corruptionchecker(self):
self.output_file.write("----------------------------------------------------------------------------------------\n")
self.output_file.write("Checking for task list corruption.\n")
self.output_file.write("----------------------------------------------------------------------------------------\n")
init_task = self.ramdump.addr_lookup('init_task')
self.output_file.write("Init Task Address = {0}\n".format(hex(init_task)))
tasks_offset = self.ramdump.field_offset('struct task_struct', 'tasks')
self.output_file.write("Task Offset {0}\n".format(hex(tasks_offset).rstrip("L")))
comm_offset = self.ramdump.field_offset('struct task_struct', 'comm')
self.output_file.write("Comm Offset {0}\n\n".format(hex(comm_offset).rstrip("L")))
next = init_task;
found_corruption = 0
while 1:
tasks_pointer = self.ramdump.read_word(next + tasks_offset, True)
if(tasks_pointer == 0x0):
found_corruption = 1
break
task_struct = tasks_pointer - tasks_offset
comm = self.ramdump.read_cstring(task_struct + comm_offset, 16, True)
self.output_file.write("Next = {0} ({1})\n".format(hex(task_struct).rstrip("L"), comm))
if (self.validate_task_struct(task_struct) == -1):
found_corruption = 1
break
if (self.validate_sched_class(task_struct) == -1):
found_corruption = 1
break
if (self.check_thread_group(task_struct, comm_offset) == -1):
found_corruption = 1
break
next = task_struct;
if (next == init_task):
break
if(found_corruption):
self.output_file.write("----------------------------------------\n")
self.output_file.write("RESULT: Corruption found in the task list\n")
self.output_file.write("----------------------------------------\n")
else:
self.output_file.write("----------------------------------------\n")
self.output_file.write("RESULT: No issues found in the task list\n")
self.output_file.write("----------------------------------------\n")
def parse(self):
self.output_file = self.ramdump.open_file('DDRCacheCompare.txt')
self.compare_magic()
self.corruptionchecker()
self.output_file.close()
print_out_str("--- Wrote the output to DDRCacheCompare.txt")
...@@ -436,8 +436,7 @@ class RamDump(): ...@@ -436,8 +436,7 @@ class RamDump():
if urc < 0: if urc < 0:
break break
def __init__(self, vmlinux_path, nm_path, gdb_path, ebi, file_path, phys_offset, outdir, hw_id=None, hw_version=None, arm64=False, def __init__(self, vmlinux_path, nm_path, gdb_path, objdump_path, ebi, file_path, phys_offset, outdir, hw_id=None, hw_version=None, arm64=False, page_offset=None):
page_offset=None):
self.ebi_files = [] self.ebi_files = []
self.phys_offset = None self.phys_offset = None
self.tz_start = 0 self.tz_start = 0
...@@ -449,6 +448,7 @@ class RamDump(): ...@@ -449,6 +448,7 @@ class RamDump():
self.vmlinux = vmlinux_path self.vmlinux = vmlinux_path
self.nm_path = nm_path self.nm_path = nm_path
self.gdb_path = gdb_path self.gdb_path = gdb_path
self.objdump_path = objdump_path
self.outdir = outdir self.outdir = outdir
self.imem_fname = None self.imem_fname = None
self.gdbmi = gdbmi.GdbMI(self.gdb_path, self.vmlinux) self.gdbmi = gdbmi.GdbMI(self.gdb_path, self.vmlinux)
......
...@@ -93,6 +93,7 @@ if __name__ == '__main__': ...@@ -93,6 +93,7 @@ if __name__ == '__main__':
parser.add_option('-v', '--vmlinux', dest='vmlinux', help='vmlinux path') parser.add_option('-v', '--vmlinux', dest='vmlinux', help='vmlinux path')
parser.add_option('-n', '--nm-path', dest='nm', help='nm path') parser.add_option('-n', '--nm-path', dest='nm', help='nm path')
parser.add_option('-g', '--gdb-path', dest='gdb', help='gdb path') parser.add_option('-g', '--gdb-path', dest='gdb', help='gdb path')
parser.add_option('-j', '--objdump-path', dest='objdump', help='objdump path')
parser.add_option('-a', '--auto-dump', dest='autodump', parser.add_option('-a', '--auto-dump', dest='autodump',
help='Auto find ram dumps from the path') help='Auto find ram dumps from the path')
parser.add_option('-o', '--outdir', dest='outdir', help='Output directory') parser.add_option('-o', '--outdir', dest='outdir', help='Output directory')
...@@ -209,6 +210,7 @@ if __name__ == '__main__': ...@@ -209,6 +210,7 @@ if __name__ == '__main__':
gdb_path = options.gdb gdb_path = options.gdb
nm_path = options.nm nm_path = options.nm
objdump_path = options.objdump
try: try:
import local_settings import local_settings
...@@ -216,9 +218,11 @@ if __name__ == '__main__': ...@@ -216,9 +218,11 @@ if __name__ == '__main__':
if options.arm64: if options.arm64:
gdb_path = gdb_path or local_settings.gdb64_path gdb_path = gdb_path or local_settings.gdb64_path
nm_path = nm_path or local_settings.nm64_path nm_path = nm_path or local_settings.nm64_path
objdump_path = objdump_path or local_settings.objdump64_path
else: else:
gdb_path = gdb_path or local_settings.gdb_path gdb_path = gdb_path or local_settings.gdb_path
nm_path = nm_path or local_settings.nm_path nm_path = nm_path or local_settings.nm_path
objdump_path = objdump_path or local_settings.objdump_path
except AttributeError as e: except AttributeError as e:
print_out_str("local_settings.py looks bogus. Please see README.txt") print_out_str("local_settings.py looks bogus. Please see README.txt")
missing_attr = re.sub(".*has no attribute '(.*)'", '\\1', e.message) missing_attr = re.sub(".*has no attribute '(.*)'", '\\1', e.message)
...@@ -259,7 +263,7 @@ if __name__ == '__main__': ...@@ -259,7 +263,7 @@ if __name__ == '__main__':
print_out_str("!!! If this tool is being run from a shared location, contact the maintainer") print_out_str("!!! If this tool is being run from a shared location, contact the maintainer")
sys.exit(1) sys.exit(1)
dump = RamDump(options.vmlinux, nm_path, gdb_path, options.ram_addr, dump = RamDump(options.vmlinux, nm_path, gdb_path, objdump_path, options.ram_addr,
options.autodump, options.phys_offset, options.outdir, options.autodump, options.phys_offset, options.outdir,
options.force_hardware, options.force_hardware_version, options.force_hardware, options.force_hardware_version,
arm64=options.arm64, arm64=options.arm64,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment