diff --git a/src/libfibre/libfibre.so-gdb.py b/src/libfibre/libfibre.so-gdb.py index 4753db09baaccb08150fca0d77ef77e3914f511b..4b501524d05616608592fd4754d05fa021c5ea7a 100644 --- a/src/libfibre/libfibre.so-gdb.py +++ b/src/libfibre/libfibre.so-gdb.py @@ -7,6 +7,7 @@ from contextlib import contextmanager class FibreSupport(): def __init__(self): FibreSupport.list = [] + FibreSupport.active = {} FibreSupport.saved = False if (gdb.lookup_symbol("_globalStackList")[0] == None): print() @@ -28,9 +29,22 @@ class FibreSupport(): while (next != first): FibreSupport.list.append(next) next = next['link'][1]['next'] + orig_thread = gdb.selected_thread() + for thread in gdb.selected_inferior().threads(): + thread.switch() + currStack = str(gdb.parse_and_eval("Context::currStack")) + # Cache the registers for this thread, in case it represents + # a fibre + FibreSupport.active[currStack] = { + 'rsp': str(gdb.parse_and_eval("$rsp")).split(None, 1)[0], + 'rbp': str(gdb.parse_and_eval("$rbp")).split(None, 1)[0], + 'rip': str(gdb.parse_and_eval("$rip")).split(None, 1)[0] + } + orig_thread.switch() def cont_handler(event): FibreSupport.list = [] + FibreSupport.active = {} # ideally restore() would be hooked up with cont_handler, # but gdb currently fails with segmentation fault when trying @@ -56,19 +70,28 @@ class FibreSupport(): # if current pthread: use current register context if (arg == gdb.parse_and_eval("Context::currStack")): return True - # retrieve fibre's register context - ftype = gdb.lookup_type('Fibre').pointer() - ptr = gdb.Value(arg).cast(ftype) - rsp = ptr['stackPointer'] - if (rsp == 0): - if not silent: - print("cannot access stack pointer - active in different thread?") - return False - ptype = gdb.lookup_type('uintptr_t').pointer() - rsp = rsp + 40 # cf. STACK_PUSH in src/generic/regsave.h - rbp = gdb.Value(rsp).cast(ptype).dereference() - rsp = rsp + 8 - rip = gdb.Value(rsp).cast(ptype).dereference() + # Check active fibre cache in case this fibre is in it + # (FibreSupport.active is more up-to-date than + # StackContext for retrieving stack pointers) + argstr = str(arg) + if (argstr in FibreSupport.active): + rsp = FibreSupport.active[argstr]['rsp'] + rbp = FibreSupport.active[argstr]['rbp'] + rip = FibreSupport.active[argstr]['rip'] + else: + # retrieve fibre's register context + ftype = gdb.lookup_type('Fibre').pointer() + ptr = gdb.Value(arg).cast(ftype) + rsp = ptr['stackPointer'] + if (rsp == 0): + if not silent: + print("cannot access stack pointer - active in different thread?") + return False + ptype = gdb.lookup_type('uintptr_t').pointer() + rsp = rsp + 40 # cf. STACK_PUSH in src/generic/regsave.h + rbp = gdb.Value(rsp).cast(ptype).dereference() + rsp = rsp + 8 + rip = gdb.Value(rsp).cast(ptype).dereference() # enable fibre's register context gdb.execute("set $rsp = " + str(rsp)) gdb.execute("set $rbp = " + str(rbp))