@@ -241,7 +241,7 @@ def bt_frames(
241241 return expand_frames (stack_trace )
242242
243243
244- def print_task_header (task : drgn .Object ) -> None :
244+ def print_task_header (task : drgn .Object , indent : int = 0 ) -> None :
245245 """
246246 Given a task struct, print the header line of the stack trace.
247247 """
@@ -253,8 +253,9 @@ def print_task_header(task: drgn.Object) -> None:
253253 cpu_note = ""
254254 if cpu_curr (task .prog_ , cpu ) == task :
255255 cpu_note = "!"
256+ pfx = " " * indent
256257 print (
257- f"PID: { pid :<7d} TASK: { taskp :x} [{ st } ] CPU: { cpu } { cpu_note } "
258+ f"{ pfx } PID: { pid :<7d} TASK: { taskp :x} [{ st } ] CPU: { cpu } { cpu_note } "
258259 f' COMMAND: "{ comm } "'
259260 )
260261
@@ -265,6 +266,7 @@ def print_frames(
265266 show_vars : bool = False ,
266267 show_absent : bool = False ,
267268 start_idx : int = 0 ,
269+ indent : int = 0 ,
268270) -> None :
269271 """
270272 Print stack frames using the drgn-tools (crash-like) format
@@ -274,8 +276,10 @@ def print_frames(
274276 :param trace: The stack trace or list of frames to print
275277 :param show_vars: True if you want to show variables
276278 :param show_absent: True if you further want to show absent variables
277- :start_idx: Where to start counting the frame indices from
279+ :param start_idx: Where to start counting the frame indices from
280+ :param indent: How many spaces to indent the output
278281 """
282+ pfx = " " * indent
279283 for i , frame in enumerate (trace ):
280284 sp = frame .sp # drgn 0.0.22
281285 intr = "!" if frame .interrupted else " "
@@ -285,7 +289,7 @@ def print_frames(
285289 pc = "???"
286290 name = frame_name (prog , frame )
287291 idx = start_idx + i
288- out_line = f"{ intr } #{ idx :2d} [{ sp :x} ] { name } at { pc } "
292+ out_line = f"{ pfx } { intr } #{ idx :2d} [{ sp :x} ] { name } at { pc } "
289293 try :
290294 file_ , line , col = frame .source ()
291295 out_line += f" { file_ } :{ line } :{ col } "
@@ -306,7 +310,8 @@ def print_frames(
306310 # This formats the registers in three columns.
307311 for j in range (0 , len (regnames ), 3 ):
308312 print (
309- " " * 5
313+ pfx
314+ + " " * 5
310315 + " " .join (
311316 f"{ reg .upper ():>3s} : { registers [reg ]:016x} "
312317 for reg in regnames [j : j + 3 ]
@@ -336,13 +341,14 @@ def print_frames(
336341 if val .absent_ and not show_absent :
337342 continue
338343 val_str = val .format_ (dereference = False ).replace ("\n " , "\n " )
339- print (" " * 5 + f"{ local } = { val_str } " )
344+ print (pfx + " " * 5 + f"{ local } = { val_str } " )
340345
341346
342347def print_traces (
343348 traces : t .List [drgn .StackTrace ],
344349 show_vars : bool = False ,
345350 show_absent : bool = False ,
351+ indent : int = 0 ,
346352) -> None :
347353 """
348354 Given a list of stack traces, print them in the crash-like format
@@ -357,13 +363,15 @@ def print_traces(
357363 idx = 0
358364 prog = traces [0 ].prog
359365 for trace_idx , trace in enumerate (traces ):
360- print_frames (prog , trace , show_vars = show_vars , start_idx = idx )
366+ print_frames (
367+ prog , trace , show_vars = show_vars , start_idx = idx , indent = indent
368+ )
361369 idx += len (trace )
362370
363371 # Ok, this is the end of the loop over each frame within the trace.
364372 if trace_idx < len (traces ) - 1 :
365373 # But there is still another segment
366- print (" -- continuing to previous stack -- " )
374+ print (" " * indent + " -- continuing to previous stack -- " )
367375
368376
369377def bt (
@@ -373,6 +381,7 @@ def bt(
373381 show_vars : bool = False ,
374382 show_absent : bool = False ,
375383 retframes : bool = False ,
384+ indent : int = 0 ,
376385) -> t .Optional [t .List [drgn .StackFrame ]]:
377386 """
378387 Format a crash-like stack trace.
@@ -418,6 +427,7 @@ def bt(
418427 to include absent variables. Normally there's no reason to see this, since
419428 absent variables have no information.
420429 :param retframes: When true, returns a list of stack frames.
430+ :param indent: Number of spaces to indent all output lines
421431 :returns: A list of the stack frames which were printed. This can be useful
422432 for accessing the variables out of the frames interactively. If you're
423433 writing a script that needs to access frames, you may want to consider the
@@ -431,13 +441,15 @@ def bt(
431441 "struct task_struct *" ,
432442 ):
433443 state = task_state_to_char (task )
434- print_task_header (task )
444+ print_task_header (task , indent = indent )
435445 if state in ("Z" , "X" ):
436446 print (f"Task is in state: { state } - cannot unwind" )
437447 return []
438448
439449 traces = expand_traces (task .prog_ .stack_trace (task ))
440- print_traces (traces , show_vars = show_vars , show_absent = show_absent )
450+ print_traces (
451+ traces , show_vars = show_vars , show_absent = show_absent , indent = indent
452+ )
441453 frames = None
442454 if retframes :
443455 frames = []
0 commit comments