@@ -369,6 +369,12 @@ def aggregate_stacks(
369369 stack_aggr [stack_key ].append (task )
370370 return sorted (stack_aggr .items (), key = lambda x : len (x [1 ]), reverse = True )
371371
372+ @staticmethod
373+ def frame_string (frame_info : str , count : int ) -> str :
374+ if count > 1 :
375+ return f"{ frame_info } ({ str (count )} )\n "
376+ return f"{ frame_info } \n "
377+
372378 def print_stacks (self , objs : Iterable [drgn .Object ]) -> None :
373379 self .print_header ()
374380 for stack_key , tasks in KernelStacks .aggregate_stacks (objs ):
@@ -382,16 +388,47 @@ def print_stacks(self, objs: Iterable[drgn.Object]) -> None:
382388 task_ptr = hex (tasks [0 ].value_ ())
383389 stacktrace_info += f"{ task_ptr :<18s} { task_state :<16s} { len (tasks ):6d} \n "
384390
391+ #
392+ # List the frames for each task in the stack. Ignore frames
393+ # with a program counter of zero (sometimes the stack will be
394+ # padded out with zeros). Aggregate frames with the same program
395+ # counter and offset.
396+ #
385397 frame_pcs : Tuple [int , ...] = stack_key [1 ]
398+ last_frame_pc = 0x0
399+ last_offset = 0x0
400+ count = 0
386401 for frame_pc in frame_pcs :
387402 try :
403+ # ignore frames with a program counter of zero
404+ if frame_pc == 0x0 :
405+ continue
388406 sym = sdb .get_symbol (frame_pc )
389407 func = sym .name
390408 offset = frame_pc - sym .address
409+ if frame_pc == last_frame_pc and offset == last_offset :
410+ count += 1
411+ continue
412+ # emit the last frame we have accumulated
413+ if count > 0 :
414+ stacktrace_info += KernelStacks .frame_string (frame_info , count )
415+ frame_info = f"{ '' :18s} { func } +0x{ hex (offset )} "
416+ last_frame_pc = frame_pc
417+ last_offset = offset
418+ count = 1
391419 except LookupError :
392- func = hex (frame_pc )
393- offset = 0x0
394- stacktrace_info += f"{ '' :18s} { func } +{ hex (offset )} \n "
420+ if frame_pc == last_frame_pc :
421+ count += 1
422+ continue
423+ # emit any previous frame info we have accumulated
424+ if count > 0 :
425+ stacktrace_info += KernelStacks .frame_string (frame_info , count )
426+ frame_info = f"{ '' :18s} { hex (frame_pc )} +0x0"
427+ last_frame_pc = frame_pc
428+ count = 1
429+ # emit the final frame if we have one
430+ if count > 0 :
431+ stacktrace_info += KernelStacks .frame_string (frame_info , count )
395432 print (stacktrace_info )
396433
397434 def pretty_print (self , objs : Iterable [drgn .Object ]) -> None :
0 commit comments