stack_usage.tcl 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/tclsh
  2. #
  3. # Parse the output of
  4. #
  5. # objdump -d sqlite3.o
  6. #
  7. # for x64 and generate a report showing:
  8. #
  9. # (1) Stack used by each function
  10. # (2) Recursion paths and their aggregate stack depth
  11. #
  12. set getStack 0
  13. while {![eof stdin]} {
  14. set line [gets stdin]
  15. if {[regexp {^[0-9a-f]+ <([^>]+)>:\s*$} $line all procname]} {
  16. set curfunc $procname
  17. set root($curfunc) 1
  18. set calls($curfunc) {}
  19. set calledby($curfunc) {}
  20. set recursive($curfunc) {}
  21. set stkdepth($curfunc) 0
  22. set getStack 1
  23. continue
  24. }
  25. if {[regexp {callq? +[0-9a-z]+ <([^>]+)>} $line all other]} {
  26. set key [list $curfunc $other]
  27. set callpair($key) 1
  28. unset -nocomplain root($curfunc)
  29. continue
  30. }
  31. if {[regexp {sub +\$(0x[0-9a-z]+),%[er]sp} $line all xdepth]} {
  32. if {$getStack} {
  33. scan $xdepth %x depth
  34. set stkdepth($curfunc) $depth
  35. set getStack 0
  36. }
  37. continue
  38. }
  39. }
  40. puts "****************** Stack Usage By Function ********************"
  41. set sdlist {}
  42. foreach f [array names stkdepth] {
  43. lappend sdlist [list $stkdepth($f) $f]
  44. }
  45. foreach sd [lsort -integer -decr -index 0 $sdlist] {
  46. foreach {depth fname} $sd break
  47. puts [format {%6d %s} $depth $fname]
  48. }
  49. puts "****************** Stack Usage By Recursion *******************"
  50. foreach key [array names callpair] {
  51. foreach {from to} $key break
  52. lappend calls($from) $to
  53. # lappend calledby($to) $from
  54. }
  55. proc all_descendents {root} {
  56. global calls recursive
  57. set todo($root) $root
  58. set go 1
  59. while {$go} {
  60. set go 0
  61. foreach f [array names todo] {
  62. set path $todo($f)
  63. unset todo($f)
  64. if {![info exists calls($f)]} continue
  65. foreach x $calls($f) {
  66. if {$x==$root} {
  67. lappend recursive($root) [concat $path $root]
  68. } elseif {![info exists d($x)]} {
  69. set go 1
  70. set todo($x) [concat $path $x]
  71. set d($x) 1
  72. }
  73. }
  74. }
  75. }
  76. return [array names d]
  77. }
  78. set pathlist {}
  79. foreach f [array names recursive] {
  80. all_descendents $f
  81. foreach m $recursive($f) {
  82. set depth 0
  83. foreach b [lrange $m 0 end-1] {
  84. set depth [expr {$depth+$stkdepth($b)}]
  85. }
  86. lappend pathlist [list $depth $m]
  87. }
  88. }
  89. foreach path [lsort -integer -decr -index 0 $pathlist] {
  90. foreach {depth m} $path break
  91. set first [lindex $m 0]
  92. puts [format {%6d %s %d} $depth $first $stkdepth($first)]
  93. foreach b [lrange $m 1 end] {
  94. puts " $b $stkdepth($b)"
  95. }
  96. }