gdbmacros.txt 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #
  2. # This file contains a few gdb macros (user defined commands) to extract
  3. # useful information from kernel crashdump (kdump) like stack traces of
  4. # all the processes or a particular process and trapinfo.
  5. #
  6. # These macros can be used by copying this file in .gdbinit (put in home
  7. # directory or current directory) or by invoking gdb command with
  8. # --command=<command-file-name> option
  9. #
  10. # Credits:
  11. # Alexander Nyberg <alexn@telia.com>
  12. # V Srivatsa <vatsa@in.ibm.com>
  13. # Maneesh Soni <maneesh@in.ibm.com>
  14. #
  15. define bttnobp
  16. set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
  17. set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
  18. set $init_t=&init_task
  19. set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
  20. set var $stacksize = sizeof(union thread_union)
  21. while ($next_t != $init_t)
  22. set $next_t=(struct task_struct *)$next_t
  23. printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
  24. printf "===================\n"
  25. set var $stackp = $next_t.thread.sp
  26. set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
  27. while ($stackp < $stack_top)
  28. if (*($stackp) > _stext && *($stackp) < _sinittext)
  29. info symbol *($stackp)
  30. end
  31. set $stackp += 4
  32. end
  33. set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
  34. while ($next_th != $next_t)
  35. set $next_th=(struct task_struct *)$next_th
  36. printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
  37. printf "===================\n"
  38. set var $stackp = $next_t.thread.sp
  39. set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize
  40. while ($stackp < $stack_top)
  41. if (*($stackp) > _stext && *($stackp) < _sinittext)
  42. info symbol *($stackp)
  43. end
  44. set $stackp += 4
  45. end
  46. set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
  47. end
  48. set $next_t=(char *)($next_t->tasks.next) - $tasks_off
  49. end
  50. end
  51. document bttnobp
  52. dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
  53. end
  54. define btthreadstack
  55. set var $pid_task = $arg0
  56. printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
  57. printf "task struct: "
  58. print $pid_task
  59. printf "===================\n"
  60. set var $stackp = $pid_task.thread.sp
  61. set var $stacksize = sizeof(union thread_union)
  62. set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
  63. set var $stack_bot = ($stackp & ~($stacksize - 1))
  64. set $stackp = *((unsigned long *) $stackp)
  65. while (($stackp < $stack_top) && ($stackp > $stack_bot))
  66. set var $addr = *(((unsigned long *) $stackp) + 1)
  67. info symbol $addr
  68. set $stackp = *((unsigned long *) $stackp)
  69. end
  70. end
  71. document btthreadstack
  72. dump a thread stack using the given task structure pointer
  73. end
  74. define btt
  75. set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
  76. set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
  77. set $init_t=&init_task
  78. set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
  79. while ($next_t != $init_t)
  80. set $next_t=(struct task_struct *)$next_t
  81. btthreadstack $next_t
  82. set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
  83. while ($next_th != $next_t)
  84. set $next_th=(struct task_struct *)$next_th
  85. btthreadstack $next_th
  86. set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
  87. end
  88. set $next_t=(char *)($next_t->tasks.next) - $tasks_off
  89. end
  90. end
  91. document btt
  92. dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
  93. end
  94. define btpid
  95. set var $pid = $arg0
  96. set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
  97. set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
  98. set $init_t=&init_task
  99. set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
  100. set var $pid_task = 0
  101. while ($next_t != $init_t)
  102. set $next_t=(struct task_struct *)$next_t
  103. if ($next_t.pid == $pid)
  104. set $pid_task = $next_t
  105. end
  106. set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
  107. while ($next_th != $next_t)
  108. set $next_th=(struct task_struct *)$next_th
  109. if ($next_th.pid == $pid)
  110. set $pid_task = $next_th
  111. end
  112. set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
  113. end
  114. set $next_t=(char *)($next_t->tasks.next) - $tasks_off
  115. end
  116. btthreadstack $pid_task
  117. end
  118. document btpid
  119. backtrace of pid
  120. end
  121. define trapinfo
  122. set var $pid = $arg0
  123. set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
  124. set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
  125. set $init_t=&init_task
  126. set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
  127. set var $pid_task = 0
  128. while ($next_t != $init_t)
  129. set $next_t=(struct task_struct *)$next_t
  130. if ($next_t.pid == $pid)
  131. set $pid_task = $next_t
  132. end
  133. set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
  134. while ($next_th != $next_t)
  135. set $next_th=(struct task_struct *)$next_th
  136. if ($next_th.pid == $pid)
  137. set $pid_task = $next_th
  138. end
  139. set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
  140. end
  141. set $next_t=(char *)($next_t->tasks.next) - $tasks_off
  142. end
  143. printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
  144. $pid_task.thread.cr2, $pid_task.thread.error_code
  145. end
  146. document trapinfo
  147. Run info threads and lookup pid of thread #1
  148. 'trapinfo <pid>' will tell you by which trap & possibly
  149. address the kernel panicked.
  150. end
  151. define dump_log_idx
  152. set $idx = $arg0
  153. if ($argc > 1)
  154. set $prev_flags = $arg1
  155. else
  156. set $prev_flags = 0
  157. end
  158. set $msg = ((struct printk_log *) (log_buf + $idx))
  159. set $prefix = 1
  160. set $newline = 1
  161. set $log = log_buf + $idx + sizeof(*$msg)
  162. # prev & LOG_CONT && !(msg->flags & LOG_PREIX)
  163. if (($prev_flags & 8) && !($msg->flags & 4))
  164. set $prefix = 0
  165. end
  166. # msg->flags & LOG_CONT
  167. if ($msg->flags & 8)
  168. # (prev & LOG_CONT && !(prev & LOG_NEWLINE))
  169. if (($prev_flags & 8) && !($prev_flags & 2))
  170. set $prefix = 0
  171. end
  172. # (!(msg->flags & LOG_NEWLINE))
  173. if (!($msg->flags & 2))
  174. set $newline = 0
  175. end
  176. end
  177. if ($prefix)
  178. printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
  179. end
  180. if ($msg->text_len != 0)
  181. eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
  182. end
  183. if ($newline)
  184. printf "\n"
  185. end
  186. if ($msg->dict_len > 0)
  187. set $dict = $log + $msg->text_len
  188. set $idx = 0
  189. set $line = 1
  190. while ($idx < $msg->dict_len)
  191. if ($line)
  192. printf " "
  193. set $line = 0
  194. end
  195. set $c = $dict[$idx]
  196. if ($c == '\0')
  197. printf "\n"
  198. set $line = 1
  199. else
  200. if ($c < ' ' || $c >= 127 || $c == '\\')
  201. printf "\\x%02x", $c
  202. else
  203. printf "%c", $c
  204. end
  205. end
  206. set $idx = $idx + 1
  207. end
  208. printf "\n"
  209. end
  210. end
  211. document dump_log_idx
  212. Dump a single log given its index in the log buffer. The first
  213. parameter is the index into log_buf, the second is optional and
  214. specified the previous log buffer's flags, used for properly
  215. formatting continued lines.
  216. end
  217. define dmesg
  218. set $i = log_first_idx
  219. set $end_idx = log_first_idx
  220. set $prev_flags = 0
  221. while (1)
  222. set $msg = ((struct printk_log *) (log_buf + $i))
  223. if ($msg->len == 0)
  224. set $i = 0
  225. else
  226. dump_log_idx $i $prev_flags
  227. set $i = $i + $msg->len
  228. set $prev_flags = $msg->flags
  229. end
  230. if ($i == $end_idx)
  231. loop_break
  232. end
  233. end
  234. end
  235. document dmesg
  236. print the kernel ring buffer
  237. end