Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions crash/arch/s390x.py
Original file line number Diff line number Diff line change
@@ -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)
50 changes: 29 additions & 21 deletions crash/arch/x86_64.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down
53 changes: 53 additions & 0 deletions crash/commands/mod.py
Original file line number Diff line number Diff line change
@@ -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()
5 changes: 3 additions & 2 deletions crash/kdump/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down