From 8d0b66fe581b18b0a7b042aa0e4ae5fe1b7881d2 Mon Sep 17 00:00:00 2001 From: Ales Novak Date: Thu, 30 Jun 2016 11:19:58 +0200 Subject: [PATCH 1/2] target: pass whole register object x86_64: fix active task %rip retrieval, clear up scheduled task's registers retrieval. --- crash/arch/x86_64.py | 50 +++++++++++++++++++++++++------------------ crash/kdump/target.py | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/crash/arch/x86_64.py b/crash/arch/x86_64.py index ce616396153..0573e837b95 100644 --- a/crash/arch/x86_64.py +++ b/crash/arch/x86_64.py @@ -7,6 +7,13 @@ class x86_64Architecture(CrashArchitecture): ident = "i386:x86-64" aliases = [ "x86_64" ] + # register position on stack (in the future, this should be generated + # dynamically) + stackregs = {"rbx": 1, + "r12": 2, + "r13": 3, + "r14": 4, + "r15": 5} def __init__(self): # PC for blocked threads @@ -23,7 +30,7 @@ def setup_thread_info(self, thread): def fetch_register_active(self, thread, register): task = thread.info for reg in task.regs: - if reg == "rip" and (register != 16 and register != -1): + if reg == "rip" and (register.name != "rip"): continue if reg in ["gs_base", "orig_ax", "rflags", "fs_base"]: continue @@ -32,40 +39,41 @@ def fetch_register_active(self, thread, register): def fetch_register_scheduled(self, thread, register): ulong_type = self.ulong_type task = thread.info.task_struct + r = register.name # Only write rip when requested; It resets the frame cache - if register == 16 or register == -1: + if r == 'rip': thread.registers['rip'].value = self.rip - if register == 16: - return True + return True rsp = task['thread']['sp'].cast(ulong_type.pointer()) rbp = rsp.dereference().cast(ulong_type.pointer()) - rbx = (rbp - 1).dereference() - r12 = (rbp - 2).dereference() - r13 = (rbp - 3).dereference() - r14 = (rbp - 4).dereference() - r15 = (rbp - 5).dereference() - # The two pushes that don't have CFI info + if r in self.stackregs: + thread.registers[r].value = (rbp - self.stackregs[r]).dereference() + elif r == 'rsp': + thread.registers[r].value = rsp + thread.info.stack_pointer = rsp + thread.info.valid_stack = True + elif r == 'rbp': + thread.registers[r].value = rbp + + # The two pushes that don't have CFI info # rsp += 2 # ex = in_exception_stack(rsp) # if ex: # print "EXCEPTION STACK: pid %d" % task['pid'] - thread.registers['rsp'].value = rsp - thread.registers['rbp'].value = rbp - thread.registers['rbx'].value = rbx - thread.registers['r12'].value = r12 - thread.registers['r13'].value = r13 - thread.registers['r14'].value = r14 - thread.registers['r15'].value = r15 - thread.registers['cs'].value = 2*8 - thread.registers['ss'].value = 3*8 + elif r == 'cs': + thread.registers['cs'].value = 2*8 + elif r == 'ss': + thread.registers['ss'].value = 3*8 + else: + gdb.write("wanted register %s\n" % r) + return False - thread.info.stack_pointer = rsp - thread.info.valid_stack = True + return True def get_stack_pointer(self, thread): return long(thread.registers['rsp'].value) diff --git a/crash/kdump/target.py b/crash/kdump/target.py index 1a3a75357e8..011e2d8ac17 100644 --- a/crash/kdump/target.py +++ b/crash/kdump/target.py @@ -106,7 +106,7 @@ def to_pid_to_str(self, ptid): def to_fetch_registers(self, register): thread = gdb.selected_thread() - self.arch.fetch_register(thread, register.regnum) + self.arch.fetch_register(thread, register) return True def to_prepare_to_store(self, thread): From 7c9465393d58ff05b8fbaf8058e662f5e875b623 Mon Sep 17 00:00:00 2001 From: Ales Novak Date: Thu, 30 Jun 2016 14:49:53 +0200 Subject: [PATCH 2/2] Add s390x architecture. --- crash/arch/s390x.py | 72 +++++++++++++++++++++++++++++++++++++++++++ crash/kdump/target.py | 3 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 crash/arch/s390x.py diff --git a/crash/arch/s390x.py b/crash/arch/s390x.py new file mode 100644 index 00000000000..00f3021342d --- /dev/null +++ b/crash/arch/s390x.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: + +import gdb +from crash.arch import CrashArchitecture, register + +class s390xArchitecture(CrashArchitecture): + ident = "s390:64-bit" + aliases = [ "s390x" ] + ulong_type = gdb.lookup_type('unsigned long') + + def __init__(self): + self.archident = "s390:64-bit" + self.lowcore_loaded = False + self.cpu_to_lowcore = {} + self.task_to_cpu = {} + thread_info_type = gdb.lookup_type('struct thread_info') + self.thread_info_p_type = thread_info_type.pointer() + + def setup_thread_info(self, thread): + task = thread.info.task_struct + thread_info = task['stack'].cast(self.thread_info_p_type) + thread.info.set_thread_info(thread_info) + + def ensure_lowcore(self): + if self.lowcore_loaded: return + lcs = gdb.lookup_global_symbol("lowcore_ptr").value() + for i in range(0, lcs.type.range()[1]+2): + lc = lcs[i] + if long(lc) == 0L: break + cpu = long(lc["cpu_nr"]) + self.cpu_to_lowcore[cpu] = lc + self.task_to_cpu[long(lc["current_task"])] = cpu + + self.lowcore_loaded = True + + + def fetch_register_active(self, thread, register): + self.ensure_lowcore() + taskp = long(thread.info.task_struct.address) + if not taskp in self.task_to_cpu: + gdb.write("task %lx not found in lowcore!" % taskp) + + lc = self.cpu_to_lowcore[self.task_to_cpu[taskp]] + regs = { "r%d"%x:x for x in range(0,16)} + + if register.name in regs: + thread.registers[register.name].value = lc["gpregs_save_area"][regs[register.name]] + elif register.name == 'pswa': + thread.registers["pswa"].value = lc["psw_save_area"]["addr"] + + def fetch_register_scheduled(self, thread, register): + ulong_type = self.ulong_type + task = thread.info.task_struct + + ksp = task['thread']['ksp'].cast(ulong_type.pointer()) + rip = (ksp+17).dereference().cast(ulong_type.pointer()) + if register.name == 'pswa': + thread.registers["pswa"].value = rip + return True + ksp = (ksp+18).dereference().cast(ulong_type.pointer()) + regmap = {"r%d"%i: i+3 for i in range(1,16)} + if register.name in regmap: + thread.registers[register.name].value = (ksp + regmap[register.name]).dereference() + + def get_stack_pointer(self, thread): + task = thread.info.task_struct + ksp = task['thread']['ksp'].cast(ulong_type.pointer()) + ksp = (ksp+18).dereference().cast(ulong_type.pointer()) + return long(ksp) + +register(s390xArchitecture) diff --git a/crash/kdump/target.py b/crash/kdump/target.py index 011e2d8ac17..74ad1e715b9 100644 --- a/crash/kdump/target.py +++ b/crash/kdump/target.py @@ -70,7 +70,8 @@ def setup_tasks(self): active = long(task.address) in rqscurrs if active: cpu = rqscurrs[long(task.address)] - regs = self.kdump.attr.cpu[cpu].reg + if 'cpu' in dir(self.kdump.attr): + regs = self.kdump.attr.cpu[cpu].reg ltask = LinuxTask(task, active, cpu, regs) ptid = (LINUX_KERNEL_PID, task['pid'], 0)