[padb-devel] [padb] r302 committed - Add support for stack traces on the solaris operating system, most...

padb at googlecode.com padb at googlecode.com
Tue Oct 27 21:00:44 GMT 2009


Revision: 302
Author: apittman
Date: Tue Oct 27 13:59:52 2009
Log: Add support for stack traces on the solaris operating system, most
changes revolve around using ps rather than /proc for discovering
proccess data and small changes to the way gdb attaches to processes.

http://code.google.com/p/padb/source/detail?r=302

Modified:
  /trunk/src/padb

=======================================
--- /trunk/src/padb	Sat Oct 24 04:51:05 2009
+++ /trunk/src/padb	Tue Oct 27 13:59:52 2009
@@ -291,6 +291,18 @@
  my %conf;

  my $secret;
+
+# Solaris support!  Tested for and works for stack traces, anything else
+# should be considered a bonus at this stage.  Reports are welcome, more so
+# if they contain good news.
+my $running_on_solaris = 0;
+
+# Test for solaris by checking for a file rather than running uname, it'll
+# be quicker.  Note that with this option enabled padb will still function
+# correctly on Linux.
+if ( -d '/proc/1/path' ) {
+    $running_on_solaris = 1;
+}

  # Config options the inner knows about, only forward options if they are in
  # this list.
@@ -774,6 +786,16 @@
  # Return an array of current processes for a given user.
  sub get_process_list {
      my ($user) = @_;
+    if ($running_on_solaris) {
+        my @procs = slurp_cmd("ps -o pid= -u $user");
+        chomp @procs;
+        my @clean_procs;
+        foreach my $proc (@procs) {
+            $proc =~ s{\s*}{}g;
+            push @clean_procs, $proc;
+        }
+        return @clean_procs;
+    }
      my $uid = getpwnam $user;
      return unless defined $uid;
      my @pids = slurp_dir('/proc');
@@ -796,6 +818,20 @@
  # and containing the parent pid for the given process.
  sub get_extended_process_list {
      my ($user) = @_;
+    if ($running_on_solaris) {
+        my @procs = slurp_cmd("ps -o pid= -o ppid= -u $user");
+        my %procs;
+        foreach my $proc (@procs) {
+
+            # A little bit of magic here, ps left pads its output with a
+            # space which the regexp matches so $pid is the second entry
+            # returned from the split command.  I need to verify that Linux
+            # ps and Solaris ps behave the same in this situation.
+            my ( undef, $pid, $ppid ) = split $SPACE, $proc;
+            $procs{$pid} = $ppid;
+        }
+        return %procs;
+    }
      my $uid = getpwnam $user;
      return unless defined $uid;
      my @pids = slurp_dir('/proc');
@@ -5079,6 +5115,15 @@
  sub gdb_attach {
      my ( $gdb, $pid ) = @_;

+    if ($running_on_solaris) {
+        my $exe = readlink("/proc/$pid/path/a.out");
+        my %cs = gdb_n_send( $gdb, "file $exe" );
+        if ( $cs{status} ne 'done' ) {
+            croak("Gdb command file $exe failed");
+            return;
+        }
+    }
+
      send_cont_signal($pid);
      my %p = gdb_n_send( $gdb, "attach $pid" );

@@ -6531,16 +6576,25 @@
          return;
      }
      if ( $data->{'number-of-threads'} == 0 ) {
-        my %t;
-        $t{id} = 0;
+        my %t = ( id => 0 );
          @{ $t{frames} } = gdb_dump_frames( $gdb, $detail );
          push @th, \%t;
          return @th;
      }
+    # Solaris has a extra "LWP" thread for every process which gdb reports
+    # as being a duplicate of the main thread for a process.  Skip loading
+    # this thread as it doesn't add anything to the output rather muddies
+    # the water somewhat.  What I don't know is if the LWP reports to be a
+    # duplicate of the first thread, I suspect it's the last one so drop
+    # the last thread from the list reported by gdb.  This needs verifying
+    # and possibly changing by somebody who has access to both solaris and
+    # multi threaded processes.
+    if ($running_on_solaris) {
+        pop @{ $data->{'thread-ids'} };
+    }
      foreach my $thread ( @{ $data->{'thread-ids'} } ) {
          my $id = $thread->{'thread-id'};
-        my %t;
-        $t{id} = $id;
+        my %t = ( id => $id );
          gdb_send( $gdb, "-thread-select $id" );
          @{ $t{frames} } = gdb_dump_frames( $gdb, $detail );
          push @th, \%t;
@@ -7611,6 +7665,21 @@
  sub find_from_status {
      my ( $pid, $key ) = @_;

+    if ($running_on_solaris) {
+        my %key_lookup = (
+            PPid  => 'ppid',
+            Name  => 'comm',
+            State => 's',
+        );
+        my $ps_key = $key_lookup{$key};
+        my @res    = slurp_cmd("ps -o $ps_key= -p $pid");
+        return if ( @res == 0 );
+        chomp @res;
+        my $proc = $res[0];
+        $proc =~ s{\s*}{}g;
+        return $proc;
+    }
+
      foreach my $l ( slurp_file("/proc/$pid/status") ) {
          if ( $l =~ m{\A(\w+):\s*(.+)}x ) {
              if ( $1 eq $key ) { return $2; }
@@ -7894,7 +7963,7 @@
          } else {
              my $ppid = $process_data{$pid};

-            while ( defined $ppid and $ppid != 1 ) {
+            while ( defined $ppid and $ppid != 1 and $ppid != 0 ) {
                  if ( defined $ipids->{$ppid} ) {
                      $rmpid = $ppid;
                      $ppid  = undef;
@@ -7982,8 +8051,8 @@
          my $pid = $proc->{pid};
          my $vp  = $proc->{vp};
          target_key_pair( $vp, 'FOUND', 'yes' );
-        target_key_pair( $vp, 'NAME',  $proc->{status}->{Name} );
-        target_key_pair( $vp, 'STATE', $proc->{status}->{State} );
+        target_key_pair( $vp, 'NAME',  find_from_status( $pid, 'Name' ) );
+        target_key_pair( $vp, 'STATE', find_from_status( $pid, 'State' ) );
      }
      return;
  }




More information about the padb-devel mailing list