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/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/commands/mod.py b/crash/commands/mod.py new file mode 100644 index 00000000000..3e3ebe58209 --- /dev/null +++ b/crash/commands/mod.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: + +import gdb +import argparse +from crash.commands import CrashCommand +from crash.types.task import LinuxTask +from crash.types.list import list_for_each_entry + +import os +import os.path +import fnmatch + +class MODCommand(CrashCommand): + """display modules information + + """ + def __init__(self): + parser = argparse.ArgumentParser(prog="mod") + + group = parser.add_mutually_exclusive_group() + parser.add_argument('-S', help='directory with debuginfo') + parser.add_argument('args', nargs=argparse.REMAINDER) + + parser.format_usage = lambda : \ + "mod [-S path]\n" + + CrashCommand.__init__(self, "mod", parser) + + def execute(self, argv): + + if not argv.S: + gdb.write("Give me -S path/to/debuginfo\n") + return + + mods = {} + for root, dirnames, filenames in os.walk(argv.S): + for filename in fnmatch.filter(filenames, '*.ko.debug'): + modname = os.path.basename(filename)[:-9] # strip that .ko.debug + mods [modname] = os.path.join(root, filename) + + modules = gdb.lookup_symbol("modules", None)[0].value() + t_module = gdb.lookup_type("struct module") + + for mod in list_for_each_entry(modules, t_module, 'list'): + modname = mod["name"].string() + module_core = long(mod["module_core"]) + if not mods.has_key(modname): + gdb.write("Debuginfo for %s not found (to be loaded at %lx)!\n" % (modname, module_core)) + else: + gdb.execute("add-symbol-file %s 0x%lx" % (mods[modname], module_core)) + +MODCommand() diff --git a/crash/kdump/target.py b/crash/kdump/target.py index 1a3a75357e8..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) @@ -106,7 +107,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):