#!/usr/bin/ruby -Ke # # backtrace.rb: resolve symbols in T-Monitor backtrace(btr) output # # Usage: # # 1. (Optional) Set environment variable LD_BACKTRACE_TKERNEL to # where you want to find *.so files from which to resolve symbols # e.g., export LD_BACKTRACE_TKERNEL=$QTDIR:$BD/lib/pcat.dl # # 2. Run "backtrace.rb " # # 3. (Optional), copy&paster "ref dyn " output to stdin as well # 4. Copy&paste "btr" command output to stdin # - 3. and 4. can be done at the same time, as garbage # lines (like [/SYS]% ...) are correctly ignored # # 5. Press Ctrl+D to close stdin # 6. See what happens :-) # $inputs = [] $output = "" $cnt = 0 $syms = [] $dirs = [] $regex_btrhead = /^TM\>\s*[bB][tT][rR]\s*/ $regex_btrbody = /^\s*(<--|EIP\s*=)\s*([0-9a-fA-F]{8})\s*$/ def searchSymbol(addr) sv = "" $syms.each do |elem| if elem[0] > addr then break end sv = elem[1] + " + " + (addr - elem[0]).to_s end return sv end def loadSymbols(file, offset) IO.popen("nm -Cn #{file}", "r") do |mapfile| mapfile.each do |line| line.chomp! if /^\s*([0-9a-fA-F]{8})\s+[TtWw]\s+(.+?)\s*$/ =~ line then $syms << [$1.hex + offset, $2] end end end $syms.sort! end def main() if ARGV.length != 1 then print "Usage: backtrace.rb \n" exit 1 end if ENV.has_key?('LD_BACKTRACE_TKERNEL') then $dirs = ENV['LD_BACKTRACE_TKERNEL'].split(':').delete_if {|x| x == ""} end # Symbols in executable itself maps as it is (offset = 0) loadSymbols(ARGV[0], 0) STDIN.each do |line| if $regex_btrhead =~ line || $regex_btrbody =~ line then $inputs << line elsif /^\s*0x([0-9a-fA-F]{8})\s+-\s+[0-9]+\+[0-9]+\s+(lib[a-zA-Z0-9_]+\.so[.0-9]*)\s*$/ =~ line then dir = $dirs.find {|x| File.exist?("#{x}/#{$2}")} if dir != nil then loadSymbols("#{dir}/#{$2}", $1.hex) else $stderr.print "Warning: #{$2} not found\n" end end end $inputs.each do |line| line.chomp! if $regex_btrhead =~ line then $output += "<>\n" $cnt = 0 elsif $regex_btrbody =~ line addr = $2.hex $output += sprintf("[%02d] : %08x : %s\n", $cnt, addr, searchSymbol(addr)) $cnt = $cnt+1 end end print "#{$output}" end main()