On Thu, 24 Jan 2008, Nick Rout wrote:

I often find strace gives more info than I can comprehend. Very often the
problems I am looking at solving are to do with libraries (missing,
outdated, updated etc)

For missing libraries sometimes
  ldd -v /path/to/program
can be more explicit.

To handle the info flood I have my nifty "grace" script...

strace -o tlog ls
a.txt0  Makefile  Makefile~  tlog  uniqId  #uniqId.cpp#  uniqId.cpp  
uniqId.cpp~  uniqId.o
$ grace < tlog
Unhandled set_robust_list(0xb7d35700, 0xc)        = 0
Unhandled statfs64("/selinux", 84, 0xbfdad380)    = -1 ENOENT (No such file or 
directory)
. close fcntl64 fstat64 getdents64(2) open /bin/ls execve /etc/ld.so.cache close fstat64 open /etc/ld.so.nohwcap access(9) /etc/ld.so.preload access /lib/libacl.so.1 close fstat64 open read /lib/libattr.so.1 close fstat64 open read /lib/libselinux.so.1 close fstat64 open read /lib/libsepol.so.1 close fstat64 open read /lib/tls/i686/cmov/libc.so.6 close fstat64 open read /lib/tls/i686/cmov/libdl.so.2 close fstat64 open read /lib/tls/i686/cmov/libpthread.so.0 close fstat64 open read /lib/tls/i686/cmov/librt.so.1 close fstat64 open read /proc/meminfo close fstat64 open read /proc/mounts close fstat64 open read(3) /usr/lib/gconv/gconv-modules.cache close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_ADDRESS close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_COLLATE close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_CTYPE close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_IDENTIFICATION close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_MEASUREMENT close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_MESSAGES close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_MESSAGES/SYS_LC_MESSAGES close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_MONETARY close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_NAME close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_NUMERIC close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_PAPER close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_TELEPHONE close fstat64 open /usr/lib/locale/en_NZ.utf8/LC_TIME close fstat64 open /usr/share/locale/locale.alias close fstat64 open read(2) __NO FILE NAME NEEDED__ brk(3) exit_group futex getrlimit mmap2(41) mprotect munmap(5) rt_sigaction(2) rt_sigprocmask set_thread_area set_tid_address uname


John Carter                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : [EMAIL PROTECTED]
New Zealand

==~/bin/grace=========================================================
#!/usr/bin/ruby -w
require 'pp'

def printHelp(plaint = 'Usage:-')
  print <<EOHELP;
#{plaint}

  grace [-e] < tlog

  An aid to grokking strace files, first create strace file like so...

    strace -o tlog myprog


  Will print out a list of all the files it
  \(open|access|stat|unlink|exec|...\)ed.

 -e Include files that couldn\'t be opened.
 -f If you use \"strace -f\", then this option strip\'s the pid
    off the front of the line.
EOHELP

  exit(0);
end

enoent = false
strip_pid = false
while !ARGV.empty?
  arg = ARGV.shift
  if arg == '-e'
    enoent = true
  elsif arg == '-f'
    strip_pid = true
  else
    printHelp("Invalid option #{arg}")
  end
end

class Fog < Hash
  def []=(k,v)
    raise if k.nil?
    super(k,v)
  end
end

o = Fog.new {|hash,key|hash[key] = Hash.new(0)}

fd_to_file_name = {}
STDIN.each do |line|
  line.chomp!;
  if strip_pid
    line.sub!( %r{^\s* \d+ \s+}x, '')
  end

  # Facilities of the form ^name("fileName",....) = fd
  if line =~ %r{ ^(?:\d+ \s)? (open) \( \"([^\"]+ )\" .* \s+ = \s+ (\S+) }x
    facility, fileName, fd = $1, $2, $3
    next if !enoent && line =~ /ENOENT/;
    o[fileName][facility] += 1
    fd_to_file_name[fd] = fileName
  elsif line =~ %r{ ^ (?:\d+ \s)? (connect|bind|getsockname) \( (\d+) .* 
path="([^\"]+)" }x
    facility, fd, fileName = $1, $2, $3
    o[fileName][facility] += 1
    fd_to_file_name[fd] = fileName
  elsif line =~ %r{ ^ (?:\d+ \s)? (connect) \( (\d+) .* 
sin_port=htons\((\d+)\),\s*sin_addr=inet_addr\("([^\"]+)"\) }x
    facility, fd, port, inet_addr = $1, $2, $3, $4
    fileName = "__IP_#{inet_addr}:#{port}"
    o[fileName][facility] += 1
    fd_to_file_name[fd] = fileName
  elsif line =~ %r{ ^ (?:\d+ \s)? 
(readv?|writev?|fchmod|fchown(?:32)?|send|recvfrom|close|
                                   
fstat\d*|ioctl|flock|ftruncate|fsync|fcntl\d*|getdents\d*|
                                   
(?:_ll|l)?seek|listen|[gs]etsockopt|accept|shutdown|getpeername) \( (\d+) }x
    facility,  fd = $1, $2
    if fd_to_file_name.has_key? fd
      fileName = fd_to_file_name[fd]
      raise "I'm confused about #{fd}, #{fileName}, #{facility} '#{line}' \n" 
unless o.has_key?( fileName)
      o[fileName][facility] += 1
      fd_to_file_name.delete( fd) if facility == 'close'
    end
  elsif line =~ %r{ ^ (?:\d+ \s)? (poll)\(.*fd=(\d+)  }x
    facility, fd = $1, $2
    if fd_to_file_name.has_key? fd
      fileName = fd_to_file_name[fd]
      raise "I'm confused about #{fd}, #{fileName}, #{facility} '#{line}' \n" 
unless o.has_key?( fileName)
      o[fileName][facility] += 1
    end
  elsif line =~ %r{ ^ (?:\d+ \s)? (select)\(.*\[(\d+(?:\ \d+)*)\]  }x
    facility, fd_list = $1, $2
    fd_list.split.each do |fd|
      if fd_to_file_name.has_key? fd
        fileName = fd_to_file_name[fd]
        raise "I'm confused about #{fd}, #{fileName}, #{facility} '#{line}' \n" 
unless o.has_key?( fileName)
        o[fileName][facility] += 1
      end
    end
  elsif line =~ %r{ ^ (?:\d+ \s)? 
(exec[a-z]*|utime|getcwd|mkdir|unlink|readlink|l?stat\d*|access|chmod) \( 
"([^\"]+)" }x
    facility, fileName = $1, $2
    o[fileName][facility] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? (rename|(?:sym)?link) \( "([^\"]+)", \s* 
"([^\"]+)" }x
    facility, left, right = $1, $2,$3
    p line
    o[left][facility] += 1
    o[right][facility] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? 
(uname|brk|(?:old_)?mmap2?|set_thread_area|munmap|times|
                                   
set_tid_address|sched_setscheduler|rt_sig(?:action|procmask)|
                                   
get(?:rlimit|pid|(?:res)?[ug]id)\d*|getppid|nanosleep|_exit|setitimer|
                                   
futex|(?:sched_)?get_?priority(?:_min|_max)?|fork|clock_gettime|
                                   
socket|exit_group|gettimeofday|time|shm(?:at|get|ctl)|alarm|
                                   
umask|mprotect|clone|gete[ug]id\d*|getgroups32|sigreturn|waitpid|sigprocmask) 
\( }x
    facility = $1
    o["__NO FILE NAME NEEDED__"][facility] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? ( select \( 0),  }x
    facility = $1
    o["__NO FILE NAME NEEDED__"][facility] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? ( sigaction ) \( (SIG[A-Z]+),  }x
    facility = $1
    alarm = $2
    o[alarm][facility] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? (pipe) \(\[(\d+), \s* (\d+) \] \)  }x
    facility, left, right = $1, $2, $3
    left = "__pipe_#{left}"
    right = "__pipe_#{right}"
    o[left][facility] += 1
    fd_to_file_name[fd] = left
    o[right][facility] += 1
    fd_to_file_name[fd] = right
  elsif line =~ %r{ ^ (?:\d+ \s)? ---\ (SIG(?:ALRM|INT|IO))  }x
    sig = $1
    o["__NO FILE NAME NEEDED__"][sig] += 1
  elsif line =~ %r{ ^ (?:\d+ \s)? <\.\.\.\ 
((?:read|write|select|futex|brk|gettimeofday|clock_gettime)\ resumed)>   }x
    sig = $1.sub(/\s+/, '_')
    o["__NO FILE NAME NEEDED__"][sig] += 1
  else
    puts "Unhandled #{line}"
  end
end

o.keys.sort.each do |file|
  printf "%-40s\t", file
  o[file].keys.sort.each do |facility|
    count = o[file][facility]
    print facility
    print "(#{count})" if count > 1
    print ' '
  end
  puts
end

Reply via email to