diff --git a/src/libfibre/libfibre.so-gdb.py b/src/libfibre/libfibre.so-gdb.py index 8fa49c95a559983f6594e054f1059d990b150532..559539088a6f464bf17177b45a64831fb594593b 100644 --- a/src/libfibre/libfibre.so-gdb.py +++ b/src/libfibre/libfibre.so-gdb.py @@ -139,32 +139,124 @@ class FibreSupport(): class InfoFibres(gdb.Command): """Print list of fibres""" + header = " Idx \tTarget\tPtr \t\t Frame" + def __init__(self): super(InfoFibres, self).__init__("info fibres", gdb.COMMAND_USER) + def get_frame_string(self, frame): + # Print instruction pointer + result = str(gdb.parse_and_eval("$rip")).split(None, 1)[0] + result += " in " + frame.name() + sal = frame.find_sal() + if sal is not None and sal.symtab is not None: + result += " at " + sal.symtab.filename + ":" + str(sal.line) + return result + + def get_row_for(self, idx, curr, frame, print_frame_info=True): + result = "" + if (FibreSupport.list[idx] == curr): + result += "* " + else: + result += " " + result += str(idx) + "\tFibre\t" + str(FibreSupport.list[idx]) + + if frame is not None and print_frame_info == True: + result += '\t' + self.get_frame_string(frame) + return result + '\n' + + def print_all_fibres(self, curr): + print(self.header) + for i in range(len(FibreSupport.list)): + with FibreSupport.get_frame(FibreSupport.list[i]) as frame: + print(self.get_row_for(i, curr, frame)) + + def print_grouped_fibres(self, curr, n): + all_fibres = FibreSupport.list + frame_groups = {} + line_groups = {} + all_output = [] + for i in range(len(FibreSupport.list)): + with FibreSupport.get_frame(FibreSupport.list[i]) as frame: + all_output.append(( + self.get_row_for(i, curr, frame, False), + self.get_frame_string(frame), + )) + if frame is None: + continue + sal = frame.find_sal() + + if sal is not None and sal.symtab is not None: + # Find line similarities + source_str = "%s:%d" % (sal.symtab.filename, sal.line) + if source_str in line_groups: + line_groups[source_str].append(i) + else: + line_groups[source_str] = [i] + + # Find stack similarities (up to n frames) + newframe = frame + for j in range(n+1): + name = newframe.name() + if name is None: + continue + if name in frame_groups: + frame_groups[name].append(i) + else: + frame_groups[name] = [i] + # Step one frame up + try: + newframe = newframe.older() + if newframe == None: + break + except: + break + + grouped_indices = set() + # Finally print the groups + for line, indices in line_groups.items(): + if len(indices) <= 1: + continue + print("Fibres at line ", line, " :") + print(self.header) + for i in indices: + fibre_info, frame_info = all_output[i] + print(fibre_info) # Consider if we should print frame_info + grouped_indices.add(i) + print() + line_grouped_indices = set(grouped_indices) + for frame, indices in frame_groups.items(): + # Eliminate line grouped fibres + indices = set(indices) - line_grouped_indices + if len(indices) <= 1: + continue + print("Fibres called by ", frame, " :") + print(self.header) + for i in indices: + fibre_info, frame_info = all_output[i] + print(fibre_info, '\t', frame_info) + grouped_indices.add(i) + print() + + # Print anything not grouped + ungrouped = set(range(len(all_output))) - grouped_indices + print('All ungrouped fibres') + print(self.header) + for i in ungrouped: + fibre_info, frame_info = all_output[i] + print(fibre_info, '\t', frame_info) + def invoke(self, arg, from_tty): if (not FibreSupport.saved): return curr = gdb.parse_and_eval("Context::currStack") - print(" Idx \tTarget\tPtr \t\t Frame") - for i in range(len(FibreSupport.list)): - if (FibreSupport.list[i] == curr): - print("* ", end='') + try: + if (arg != None and int(arg) >= 0): + self.print_grouped_fibres(curr, int(arg)) else: - print(" ", end='') - print(str(i), "\tFibre\t", str(FibreSupport.list[i]), sep='', end='') - with FibreSupport.get_frame(FibreSupport.list[i]) as frame: - if frame is not None: - # Print instruction pointer - print("\t", str(gdb.parse_and_eval("$rip")).split(None, 1)[0], end='') - print(" in ", frame.name(), sep='', end='') - sal = frame.find_sal() - if sal is not None and sal.symtab is not None: - print(" at ", sal.symtab.filename, ":", sal.line, sep='') - else: - print() - else: - print() + self.print_all_fibres(curr) + except ValueError: + self.print_all_fibres(curr) class Fibre(gdb.Command): def __init__(self):