1========================
2Debugging C++ Coroutines
3========================
4
5.. contents::
6   :local:
7
8Introduction
9============
10
11For performance and other architectural reasons, the C++ Coroutines feature in
12the Clang compiler is implemented in two parts of the compiler.  Semantic
13analysis is performed in Clang, and Coroutine construction and optimization
14takes place in the LLVM middle-end.
15
16However, this design forces us to generate insufficient debugging information.
17Typically, the compiler generates debug information in the Clang frontend, as
18debug information is highly language specific. However, this is not possible
19for Coroutine frames because the frames are constructed in the LLVM middle-end.
20
21To mitigate this problem, the LLVM middle end attempts to generate some debug
22information, which is unfortunately incomplete, since much of the language
23specific information is missing in the middle end.
24
25This document describes how to use this debug information to better debug
26coroutines.
27
28Terminology
29===========
30
31Due to the recent nature of C++20 Coroutines, the terminology used to describe
32the concepts of Coroutines is not settled.  This section defines a common,
33understandable terminology to be used consistently throughout this document.
34
35coroutine type
36--------------
37
38A `coroutine function` is any function that contains any of the Coroutine
39Keywords `co_await`, `co_yield`, or `co_return`.  A `coroutine type` is a
40possible return type of one of these `coroutine functions`.  `Task` and
41`Generator` are commonly referred to coroutine types.
42
43coroutine
44---------
45
46By technical definition, a `coroutine` is a suspendable function. However,
47programmers typically use `coroutine` to refer to an individual instance.
48For example:
49
50.. code-block:: c++
51
52  std::vector<Task> Coros; // Task is a coroutine type.
53  for (int i = 0; i < 3; i++)
54    Coros.push_back(CoroTask()); // CoroTask is a coroutine function, which
55                                 // would return a coroutine type 'Task'.
56
57In practice, we typically say "`Coros` contains 3 coroutines" in the above
58example, though this is not strictly correct.  More technically, this should
59say "`Coros` contains 3 coroutine instances" or "Coros contains 3 coroutine
60objects."
61
62In this document, we follow the common practice of using `coroutine` to refer
63to an individual `coroutine instance`, since the terms `coroutine instance` and
64`coroutine object` aren't sufficiently defined in this case.
65
66coroutine frame
67---------------
68
69The C++ Standard uses `coroutine state` to describe the allocated storage. In
70the compiler, we use `coroutine frame` to describe the generated data structure
71that contains the necessary information.
72
73The structure of coroutine frames
74=================================
75
76The structure of coroutine frames is defined as:
77
78.. code-block:: c++
79
80  struct {
81    void (*__r)(); // function pointer to the `resume` function
82    void (*__d)(); // function pointer to the `destroy` function
83    promise_type; // the corresponding `promise_type`
84    ... // Any other needed information
85  }
86
87In the debugger, the function's name is obtainable from the address of the
88function. And the name of `resume` function is equal to the name of the
89coroutine function. So the name of the coroutine is obtainable once the
90address of the coroutine is known.
91
92Print promise_type
93==================
94
95Every coroutine has a `promise_type`, which defines the behavior
96for the corresponding coroutine. In other words, if two coroutines have the
97same `promise_type`, they should behave in the same way.
98To print a `promise_type` in a debugger when stopped at a breakpoint inside a
99coroutine, printing the `promise_type` can be done by:
100
101.. parsed-literal::
102
103  print __promise
104
105It is also possible to print the `promise_type` of a coroutine from the address
106of the coroutine frame. For example, if the address of a coroutine frame is
1070x416eb0, and the type of the `promise_type` is `task::promise_type`, printing
108the `promise_type` can be done by:
109
110.. parsed-literal::
111
112  print (task::promise_type)*(0x416eb0+0x10)
113
114This is possible because the `promise_type` is guaranteed by the ABI to be at a
11516 bit offset from the coroutine frame.
116
117Note that there is also an ABI independent method:
118
119.. parsed-literal::
120
121  print std::coroutine_handle<task::promise_type>::from_address((void*)0x416eb0).promise()
122
123The functions `from_address(void*)` and `promise()` are often small enough to
124be removed during optimization, so this method may not be possible.
125
126Print coroutine frames
127======================
128
129LLVM generates the debug information for the coroutine frame in the LLVM middle
130end, which permits printing of the coroutine frame in the debugger. Much like
131the `promise_type`, when stopped at a breakpoint inside a coroutine we can
132print the coroutine frame by:
133
134.. parsed-literal::
135
136  print __coro_frame
137
138
139Just as printing the `promise_type` is possible from the coroutine address,
140printing the details of the coroutine frame from an address is also possible:
141
142::
143
144  (gdb) # Get the address of coroutine frame
145  (gdb) print/x *0x418eb0
146  $1 = 0x4019e0
147  (gdb) # Get the linkage name for the coroutine
148  (gdb) x 0x4019e0
149  0x4019e0 <_ZL9coro_taski>:  0xe5894855
150  (gdb) # Turn off the demangler temporarily to avoid the debugger misunderstanding the name.
151  (gdb) set demangle-style none
152  (gdb) # The coroutine frame type is 'linkage_name.coro_frame_ty'
153  (gdb) print  ('_ZL9coro_taski.coro_frame_ty')*(0x418eb0)
154  $2 = {__resume_fn = 0x4019e0 <coro_task(int)>, __destroy_fn = 0x402000 <coro_task(int)>, __promise = {...}, ...}
155
156The above is possible because:
157
158(1) The name of the debug type of the coroutine frame is the `linkage_name`,
159plus the `.coro_frame_ty` suffix because each coroutine function shares the
160same coroutine type.
161
162(2) The coroutine function name is accessible from the address of the coroutine
163frame.
164
165The above commands can be simplified by placing them in debug scripts.
166
167Examples to print coroutine frames
168----------------------------------
169
170The print examples below use the following definition:
171
172.. code-block:: c++
173
174  #include <coroutine>
175  #include <iostream>
176
177  struct task{
178    struct promise_type {
179      task get_return_object() { return std::coroutine_handle<promise_type>::from_promise(*this); }
180      std::suspend_always initial_suspend() { return {}; }
181      std::suspend_always final_suspend() noexcept { return {}; }
182      void return_void() noexcept {}
183      void unhandled_exception() noexcept {}
184
185      int count = 0;
186    };
187
188    void resume() noexcept {
189      handle.resume();
190    }
191
192    task(std::coroutine_handle<promise_type> hdl) : handle(hdl) {}
193    ~task() {
194      if (handle)
195        handle.destroy();
196    }
197
198    std::coroutine_handle<> handle;
199  };
200
201  class await_counter : public std::suspend_always {
202    public:
203      template<class PromiseType>
204      void await_suspend(std::coroutine_handle<PromiseType> handle) noexcept {
205          handle.promise().count++;
206      }
207  };
208
209  static task coro_task(int v) {
210    int a = v;
211    co_await await_counter{};
212    a++;
213    std::cout << a << "\n";
214    a++;
215    std::cout << a << "\n";
216    a++;
217    std::cout << a << "\n";
218    co_await await_counter{};
219    a++;
220    std::cout << a << "\n";
221    a++;
222    std::cout << a << "\n";
223  }
224
225  int main() {
226    task t = coro_task(43);
227    t.resume();
228    t.resume();
229    t.resume();
230    return 0;
231  }
232
233In debug mode (`O0` + `g`), the printing result would be:
234
235.. parsed-literal::
236
237  {__resume_fn = 0x4019e0 <coro_task(int)>, __destroy_fn = 0x402000 <coro_task(int)>, __promise = {count = 1}, v = 43, a = 45, __coro_index = 1 '\001', struct_std__suspend_always_0 = {__int_8 = 0 '\000'},
238    class_await_counter_1 = {__int_8 = 0 '\000'}, class_await_counter_2 = {__int_8 = 0 '\000'}, struct_std__suspend_always_3 = {__int_8 = 0 '\000'}}
239
240In the above, the values of `v` and `a` are clearly expressed, as are the
241temporary values for `await_counter` (`class_await_counter_1` and
242`class_await_counter_2`) and `std::suspend_always` (
243`struct_std__suspend_always_0` and `struct_std__suspend_always_3`). The index
244of the current suspension point of the coroutine is emitted as `__coro_index`.
245In the above example, the `__coro_index` value of `1` means the coroutine
246stopped at the second suspend point (Note that `__coro_index` is zero indexed)
247which is the first `co_await await_counter{};` in `coro_task`. Note that the
248first initial suspend point is the compiler generated
249`co_await promise_type::initial_suspend()`.
250
251However, when optimizations are enabled, the printed result changes drastically:
252
253.. parsed-literal::
254
255  {__resume_fn = 0x401280 <coro_task(int)>, __destroy_fn = 0x401390 <coro_task(int)>, __promise = {count = 1}, __int_32_0 = 43, __coro_index = 1 '\001'}
256
257Unused values are optimized out, as well as the name of the local variable `a`.
258The only information remained is the value of a 32 bit integer. In this simple
259case, it seems to be pretty clear that `__int_32_0` represents `a`. However, it
260is not true.
261
262An important note with optimization is that the value of a variable may not
263properly express the intended value in the source code.  For example:
264
265.. code-block:: c++
266
267  static task coro_task(int v) {
268    int a = v;
269    co_await await_counter{};
270    a++; // __int_32_0 is 43 here
271    std::cout << a << "\n";
272    a++; // __int_32_0 is still 43 here
273    std::cout << a << "\n";
274    a++; // __int_32_0 is still 43 here!
275    std::cout << a << "\n";
276    co_await await_counter{};
277    a++; // __int_32_0 is still 43 here!!
278    std::cout << a << "\n";
279    a++; // Why is __int_32_0 still 43 here?
280    std::cout << a << "\n";
281  }
282
283When debugging step-by-step, the value of `__int_32_0` seemingly does not
284change, despite being frequently incremented, and instead is always `43`.
285While this might be surprising, this is a result of the optimizer recognizing
286that it can eliminate most of the load/store operations. The above code gets
287optimized to the equivalent of:
288
289.. code-block:: c++
290
291  static task coro_task(int v) {
292    store v to __int_32_0 in the frame
293    co_await await_counter{};
294    a = load __int_32_0
295    std::cout << a+1 << "\n";
296    std::cout << a+2 << "\n";
297    std::cout << a+3 << "\n";
298    co_await await_counter{};
299    a = load __int_32_0
300    std::cout << a+4 << "\n";
301    std::cout << a+5 << "\n";
302  }
303
304It should now be obvious why the value of `__int_32_0` remains unchanged
305throughout the function. It is important to recognize that `__int_32_0`
306does not directly correspond to `a`, but is instead a variable generated
307to assist the compiler in code generation. The variables in an optimized
308coroutine frame should not be thought of as directly representing the
309variables in the C++ source.
310
311Get the suspended points
312========================
313
314An important requirement for debugging coroutines is to understand suspended
315points, which are where the coroutine is currently suspended and awaiting.
316
317For simple cases like the above, inspecting the value of the `__coro_index`
318variable in the coroutine frame works well.
319
320However, it is not quite so simple in really complex situations. In these
321cases, it is necessary to use the coroutine libraries to insert the
322line-number.
323
324For example:
325
326.. code-block:: c++
327
328  // For all the promise_type we want:
329  class promise_type {
330    ...
331  +  unsigned line_number = 0xffffffff;
332  };
333
334  #include <source_location>
335
336  // For all the awaiter types we need:
337  class awaiter {
338    ...
339    template <typename Promise>
340    void await_suspend(std::coroutine_handle<Promise> handle,
341                       std::source_location sl = std::source_location::current()) {
342          ...
343          handle.promise().line_number = sl.line();
344    }
345  };
346
347In this case, we use `std::source_location` to store the line number of the
348await inside the `promise_type`.  Since we can locate the coroutine function
349from the address of the coroutine, we can identify suspended points this way
350as well.
351
352The downside here is that this comes at the price of additional runtime cost.
353This is consistent with the C++ philosophy of "Pay for what you use".
354
355Get the asynchronous stack
356==========================
357
358Another important requirement to debug a coroutine is to print the asynchronous
359stack to identify the asynchronous caller of the coroutine.  As many
360implementations of coroutine types store `std::coroutine_handle<> continuation`
361in the promise type, identifying the caller should be trivial.  The
362`continuation` is typically the awaiting coroutine for the current coroutine.
363That is, the asynchronous parent.
364
365Since the `promise_type` is obtainable from the address of a coroutine and
366contains the corresponding continuation (which itself is a coroutine with a
367`promise_type`), it should be trivial to print the entire asynchronous stack.
368
369This logic should be quite easily captured in a debugger script.
370
371Examples to print asynchronous stack
372------------------------------------
373
374Here is an example to print the asynchronous stack for the normal task implementation.
375
376.. code-block:: c++
377
378  // debugging-example.cpp
379  #include <coroutine>
380  #include <iostream>
381  #include <utility>
382
383  struct task {
384    struct promise_type {
385      task get_return_object();
386      std::suspend_always initial_suspend() { return {}; }
387
388      void unhandled_exception() noexcept {}
389
390      struct FinalSuspend {
391        std::coroutine_handle<> continuation;
392        auto await_ready() noexcept { return false; }
393        auto await_suspend(std::coroutine_handle<> handle) noexcept {
394          return continuation;
395        }
396        void await_resume() noexcept {}
397      };
398      FinalSuspend final_suspend() noexcept { return {continuation}; }
399
400      void return_value(int res) { result = res; }
401
402      std::coroutine_handle<> continuation = std::noop_coroutine();
403      int result = 0;
404    };
405
406    task(std::coroutine_handle<promise_type> handle) : handle(handle) {}
407    ~task() {
408      if (handle)
409        handle.destroy();
410    }
411
412    auto operator co_await() {
413      struct Awaiter {
414        std::coroutine_handle<promise_type> handle;
415        auto await_ready() { return false; }
416        auto await_suspend(std::coroutine_handle<> continuation) {
417          handle.promise().continuation = continuation;
418          return handle;
419        }
420        int await_resume() {
421          int ret = handle.promise().result;
422          handle.destroy();
423          return ret;
424        }
425      };
426      return Awaiter{std::exchange(handle, nullptr)};
427    }
428
429    int syncStart() {
430      handle.resume();
431      return handle.promise().result;
432    }
433
434  private:
435    std::coroutine_handle<promise_type> handle;
436  };
437
438  task task::promise_type::get_return_object() {
439    return std::coroutine_handle<promise_type>::from_promise(*this);
440  }
441
442  namespace detail {
443  template <int N>
444  task chain_fn() {
445    co_return N + co_await chain_fn<N - 1>();
446  }
447
448  template <>
449  task chain_fn<0>() {
450    // This is the default breakpoint.
451    __builtin_debugtrap();
452    co_return 0;
453  }
454  }  // namespace detail
455
456  task chain() {
457    co_return co_await detail::chain_fn<30>();
458  }
459
460  int main() {
461    std::cout << chain().syncStart() << "\n";
462    return 0;
463  }
464
465In the example, the ``task`` coroutine holds a ``continuation`` field,
466which would be resumed once the ``task`` completes.
467In another word, the ``continuation`` is the asynchronous caller for the ``task``.
468Just like the normal function returns to its caller when the function completes.
469
470So we can use the ``continuation`` field to construct the asynchronous stack:
471
472.. code-block:: python
473
474  # debugging-helper.py
475  import gdb
476  from gdb.FrameDecorator import FrameDecorator
477
478  class SymValueWrapper():
479      def __init__(self, symbol, value):
480          self.sym = symbol
481          self.val = value
482
483      def __str__(self):
484          return str(self.sym) + " = " + str(self.val)
485
486  def get_long_pointer_size():
487      return gdb.lookup_type('long').pointer().sizeof
488
489  def cast_addr2long_pointer(addr):
490      return gdb.Value(addr).cast(gdb.lookup_type('long').pointer())
491
492  def dereference(addr):
493      return long(cast_addr2long_pointer(addr).dereference())
494
495  class CoroutineFrame(object):
496      def __init__(self, task_addr):
497          self.frame_addr = task_addr
498          self.resume_addr = task_addr
499          self.destroy_addr = task_addr + get_long_pointer_size()
500          self.promise_addr = task_addr + get_long_pointer_size() * 2
501          # In the example, the continuation is the first field member of the promise_type.
502          # So they have the same addresses.
503          # If we want to generalize the scripts to other coroutine types, we need to be sure
504          # the continuation field is the first memeber of promise_type.
505          self.continuation_addr = self.promise_addr
506
507      def next_task_addr(self):
508          return dereference(self.continuation_addr)
509
510  class CoroutineFrameDecorator(FrameDecorator):
511      def __init__(self, coro_frame):
512          super(CoroutineFrameDecorator, self).__init__(None)
513          self.coro_frame = coro_frame
514          self.resume_func = dereference(self.coro_frame.resume_addr)
515          self.resume_func_block = gdb.block_for_pc(self.resume_func)
516          if self.resume_func_block == None:
517              raise Exception('Not stackless coroutine.')
518          self.line_info = gdb.find_pc_line(self.resume_func)
519
520      def address(self):
521          return self.resume_func
522
523      def filename(self):
524          return self.line_info.symtab.filename
525
526      def frame_args(self):
527          return [SymValueWrapper("frame_addr", cast_addr2long_pointer(self.coro_frame.frame_addr)),
528                  SymValueWrapper("promise_addr", cast_addr2long_pointer(self.coro_frame.promise_addr)),
529                  SymValueWrapper("continuation_addr", cast_addr2long_pointer(self.coro_frame.continuation_addr))
530                  ]
531
532      def function(self):
533          return self.resume_func_block.function.print_name
534
535      def line(self):
536          return self.line_info.line
537
538  class StripDecorator(FrameDecorator):
539      def __init__(self, frame):
540          super(StripDecorator, self).__init__(frame)
541          self.frame = frame
542          f = frame.function()
543          self.function_name = f
544
545      def __str__(self, shift = 2):
546          addr = "" if self.address() == None else '%#x' % self.address() + " in "
547          location = "" if self.filename() == None else " at " + self.filename() + ":" + str(self.line())
548          return addr + self.function() + " " + str([str(args) for args in self.frame_args()]) + location
549
550  class CoroutineFilter:
551      def create_coroutine_frames(self, task_addr):
552          frames = []
553          while task_addr != 0:
554              coro_frame = CoroutineFrame(task_addr)
555              frames.append(CoroutineFrameDecorator(coro_frame))
556              task_addr = coro_frame.next_task_addr()
557          return frames
558
559  class AsyncStack(gdb.Command):
560      def __init__(self):
561          super(AsyncStack, self).__init__("async-bt", gdb.COMMAND_USER)
562
563      def invoke(self, arg, from_tty):
564          coroutine_filter = CoroutineFilter()
565          argv = gdb.string_to_argv(arg)
566          if len(argv) == 0:
567              try:
568                  task = gdb.parse_and_eval('__coro_frame')
569                  task = int(str(task.address), 16)
570              except Exception:
571                  print ("Can't find __coro_frame in current context.\n" +
572                        "Please use `async-bt` in stackless coroutine context.")
573                  return
574          elif len(argv) != 1:
575              print("usage: async-bt <pointer to task>")
576              return
577          else:
578              task = int(argv[0], 16)
579
580          frames = coroutine_filter.create_coroutine_frames(task)
581          i = 0
582          for f in frames:
583              print '#'+ str(i), str(StripDecorator(f))
584              i += 1
585          return
586
587  AsyncStack()
588
589  class ShowCoroFrame(gdb.Command):
590      def __init__(self):
591          super(ShowCoroFrame, self).__init__("show-coro-frame", gdb.COMMAND_USER)
592
593      def invoke(self, arg, from_tty):
594          argv = gdb.string_to_argv(arg)
595          if len(argv) != 1:
596              print("usage: show-coro-frame <address of coroutine frame>")
597              return
598
599          addr = int(argv[0], 16)
600          block = gdb.block_for_pc(long(cast_addr2long_pointer(addr).dereference()))
601          if block == None:
602              print "block " + str(addr) + "  is none."
603              return
604
605          # Disable demangling since gdb will treat names starting with `_Z`(The marker for Itanium ABI) specially.
606          gdb.execute("set demangle-style none")
607
608          coro_frame_type = gdb.lookup_type(block.function.linkage_name + ".coro_frame_ty")
609          coro_frame_ptr_type = coro_frame_type.pointer()
610          coro_frame = gdb.Value(addr).cast(coro_frame_ptr_type).dereference()
611
612          gdb.execute("set demangle-style auto")
613          gdb.write(coro_frame.format_string(pretty_structs = True))
614
615  ShowCoroFrame()
616
617Then let's run:
618
619.. code-block:: text
620
621  $ clang++ -std=c++20 -g debugging-example.cpp -o debugging-example
622  $ gdb ./debugging-example
623  (gdb) # We've alreay set the breakpoint.
624  (gdb) r
625  Program received signal SIGTRAP, Trace/breakpoint trap.
626  detail::chain_fn<0> () at debugging-example2.cpp:73
627  73	  co_return 0;
628  (gdb) # Executes the debugging scripts
629  (gdb) source debugging-helper.py
630  (gdb) # Print the asynchronous stack
631  (gdb) async-bt
632  #0 0x401c40 in detail::chain_fn<0>() ['frame_addr = 0x441860', 'promise_addr = 0x441870', 'continuation_addr = 0x441870'] at debugging-example.cpp:71
633  #1 0x4022d0 in detail::chain_fn<1>() ['frame_addr = 0x441810', 'promise_addr = 0x441820', 'continuation_addr = 0x441820'] at debugging-example.cpp:66
634  #2 0x403060 in detail::chain_fn<2>() ['frame_addr = 0x4417c0', 'promise_addr = 0x4417d0', 'continuation_addr = 0x4417d0'] at debugging-example.cpp:66
635  #3 0x403df0 in detail::chain_fn<3>() ['frame_addr = 0x441770', 'promise_addr = 0x441780', 'continuation_addr = 0x441780'] at debugging-example.cpp:66
636  #4 0x404b80 in detail::chain_fn<4>() ['frame_addr = 0x441720', 'promise_addr = 0x441730', 'continuation_addr = 0x441730'] at debugging-example.cpp:66
637  #5 0x405910 in detail::chain_fn<5>() ['frame_addr = 0x4416d0', 'promise_addr = 0x4416e0', 'continuation_addr = 0x4416e0'] at debugging-example.cpp:66
638  #6 0x4066a0 in detail::chain_fn<6>() ['frame_addr = 0x441680', 'promise_addr = 0x441690', 'continuation_addr = 0x441690'] at debugging-example.cpp:66
639  #7 0x407430 in detail::chain_fn<7>() ['frame_addr = 0x441630', 'promise_addr = 0x441640', 'continuation_addr = 0x441640'] at debugging-example.cpp:66
640  #8 0x4081c0 in detail::chain_fn<8>() ['frame_addr = 0x4415e0', 'promise_addr = 0x4415f0', 'continuation_addr = 0x4415f0'] at debugging-example.cpp:66
641  #9 0x408f50 in detail::chain_fn<9>() ['frame_addr = 0x441590', 'promise_addr = 0x4415a0', 'continuation_addr = 0x4415a0'] at debugging-example.cpp:66
642  #10 0x409ce0 in detail::chain_fn<10>() ['frame_addr = 0x441540', 'promise_addr = 0x441550', 'continuation_addr = 0x441550'] at debugging-example.cpp:66
643  #11 0x40aa70 in detail::chain_fn<11>() ['frame_addr = 0x4414f0', 'promise_addr = 0x441500', 'continuation_addr = 0x441500'] at debugging-example.cpp:66
644  #12 0x40b800 in detail::chain_fn<12>() ['frame_addr = 0x4414a0', 'promise_addr = 0x4414b0', 'continuation_addr = 0x4414b0'] at debugging-example.cpp:66
645  #13 0x40c590 in detail::chain_fn<13>() ['frame_addr = 0x441450', 'promise_addr = 0x441460', 'continuation_addr = 0x441460'] at debugging-example.cpp:66
646  #14 0x40d320 in detail::chain_fn<14>() ['frame_addr = 0x441400', 'promise_addr = 0x441410', 'continuation_addr = 0x441410'] at debugging-example.cpp:66
647  #15 0x40e0b0 in detail::chain_fn<15>() ['frame_addr = 0x4413b0', 'promise_addr = 0x4413c0', 'continuation_addr = 0x4413c0'] at debugging-example.cpp:66
648  #16 0x40ee40 in detail::chain_fn<16>() ['frame_addr = 0x441360', 'promise_addr = 0x441370', 'continuation_addr = 0x441370'] at debugging-example.cpp:66
649  #17 0x40fbd0 in detail::chain_fn<17>() ['frame_addr = 0x441310', 'promise_addr = 0x441320', 'continuation_addr = 0x441320'] at debugging-example.cpp:66
650  #18 0x410960 in detail::chain_fn<18>() ['frame_addr = 0x4412c0', 'promise_addr = 0x4412d0', 'continuation_addr = 0x4412d0'] at debugging-example.cpp:66
651  #19 0x4116f0 in detail::chain_fn<19>() ['frame_addr = 0x441270', 'promise_addr = 0x441280', 'continuation_addr = 0x441280'] at debugging-example.cpp:66
652  #20 0x412480 in detail::chain_fn<20>() ['frame_addr = 0x441220', 'promise_addr = 0x441230', 'continuation_addr = 0x441230'] at debugging-example.cpp:66
653  #21 0x413210 in detail::chain_fn<21>() ['frame_addr = 0x4411d0', 'promise_addr = 0x4411e0', 'continuation_addr = 0x4411e0'] at debugging-example.cpp:66
654  #22 0x413fa0 in detail::chain_fn<22>() ['frame_addr = 0x441180', 'promise_addr = 0x441190', 'continuation_addr = 0x441190'] at debugging-example.cpp:66
655  #23 0x414d30 in detail::chain_fn<23>() ['frame_addr = 0x441130', 'promise_addr = 0x441140', 'continuation_addr = 0x441140'] at debugging-example.cpp:66
656  #24 0x415ac0 in detail::chain_fn<24>() ['frame_addr = 0x4410e0', 'promise_addr = 0x4410f0', 'continuation_addr = 0x4410f0'] at debugging-example.cpp:66
657  #25 0x416850 in detail::chain_fn<25>() ['frame_addr = 0x441090', 'promise_addr = 0x4410a0', 'continuation_addr = 0x4410a0'] at debugging-example.cpp:66
658  #26 0x4175e0 in detail::chain_fn<26>() ['frame_addr = 0x441040', 'promise_addr = 0x441050', 'continuation_addr = 0x441050'] at debugging-example.cpp:66
659  #27 0x418370 in detail::chain_fn<27>() ['frame_addr = 0x440ff0', 'promise_addr = 0x441000', 'continuation_addr = 0x441000'] at debugging-example.cpp:66
660  #28 0x419100 in detail::chain_fn<28>() ['frame_addr = 0x440fa0', 'promise_addr = 0x440fb0', 'continuation_addr = 0x440fb0'] at debugging-example.cpp:66
661  #29 0x419e90 in detail::chain_fn<29>() ['frame_addr = 0x440f50', 'promise_addr = 0x440f60', 'continuation_addr = 0x440f60'] at debugging-example.cpp:66
662  #30 0x41ac20 in detail::chain_fn<30>() ['frame_addr = 0x440f00', 'promise_addr = 0x440f10', 'continuation_addr = 0x440f10'] at debugging-example.cpp:66
663  #31 0x41b9b0 in chain() ['frame_addr = 0x440eb0', 'promise_addr = 0x440ec0', 'continuation_addr = 0x440ec0'] at debugging-example.cpp:77
664
665Now we get the complete asynchronous stack!
666It is also possible to print other asynchronous stack which doesn't live in the top of the stack.
667We can make it by passing the address of the corresponding coroutine frame to ``async-bt`` command.
668
669By the debugging scripts, we can print any coroutine frame too as long as we know the address.
670For example, we can print the coroutine frame for ``detail::chain_fn<18>()`` in the above example.
671From the log record, we know the address of the coroutine frame is ``0x4412c0`` in the run. Then we can:
672
673.. code-block:: text
674
675  (gdb) show-coro-frame 0x4412c0
676  {
677    __resume_fn = 0x410960 <detail::chain_fn<18>()>,
678    __destroy_fn = 0x410d60 <detail::chain_fn<18>()>,
679    __promise = {
680      continuation = {
681        _M_fr_ptr = 0x441270
682      },
683      result = 0
684    },
685    struct_Awaiter_0 = {
686      struct_std____n4861__coroutine_handle_0 = {
687        struct_std____n4861__coroutine_handle = {
688          PointerType = 0x441310
689        }
690      }
691    },
692    struct_task_1 = {
693      struct_std____n4861__coroutine_handle_0 = {
694        struct_std____n4861__coroutine_handle = {
695          PointerType = 0x0
696        }
697      }
698    },
699    struct_task__promise_type__FinalSuspend_2 = {
700      struct_std____n4861__coroutine_handle = {
701        PointerType = 0x0
702      }
703    },
704    __coro_index = 1 '\001',
705    struct_std____n4861__suspend_always_3 = {
706      __int_8 = 0 '\000'
707    }
708
709
710Get the living coroutines
711=========================
712
713Another useful task when debugging coroutines is to enumerate the list of
714living coroutines, which is often done with threads.  While technically
715possible, this task is not recommended in production code as it is costly at
716runtime. One such solution is to store the list of currently running coroutines
717in a collection:
718
719.. code-block:: c++
720
721  inline std::unordered_set<void*> lived_coroutines;
722  // For all promise_type we want to record
723  class promise_type {
724  public:
725      promise_type() {
726          // Note to avoid data races
727          lived_coroutines.insert(std::coroutine_handle<promise_type>::from_promise(*this).address());
728      }
729      ~promise_type() {
730          // Note to avoid data races
731          lived_coroutines.erase(std::coroutine_handle<promise_type>::from_promise(*this).address());
732      }
733  };
734
735In the above code snippet, we save the address of every lived coroutine in the
736`lived_coroutines` `unordered_set`. As before, once we know the address of the
737coroutine we can derive the function, `promise_type`, and other members of the
738frame. Thus, we could print the list of lived coroutines from that collection.
739
740Please note that the above is expensive from a storage perspective, and requires
741some level of locking (not pictured) on the collection to prevent data races.
742