public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* gcore support for AIX
@ 2017-10-13 10:58 Sangamesh Mallayya
  2017-10-17 10:11 ` Ulrich Weigand
  0 siblings, 1 reply; 4+ messages in thread
From: Sangamesh Mallayya @ 2017-10-13 10:58 UTC (permalink / raw)
  To: gdb-patches, Ulrich Weigand; +Cc: David Edelsohn

[-- Attachment #1: Type: text/plain, Size: 1250 bytes --]

Hi All,

I have came across a way to add gencore support for the AIX.
Need to your input and suggestions on current implementation or is their 
any other way this can be done ?

Some background on the gencore command/API on AIX.

AIX provides a gencore command and gencore api for generating a 
core of a running program. If debugging a process through gdb,
gdb uses ptrace to control the prcoess execution.

In this case all threads of process must have stopped by
gdb and gencore will hang if gencore command or API is used on the
process which gdb is debugging. 

In order to keep it from hanging, gdb would need to continue one thread
in the process for as little as one instruction.
If a thread is continued, then when it runs it will be resumed such that
the core signal will be handled by that thread of the process and the
core file will be written.

In this implementation gencore api will be called through a separate gdb 
thread
which will be scheduled and gencore will be executed after a call to 
"step_1_ext (0, 1, "1")" which will call step_1 to execute single 
instruction.

I am yet to try this patch on other linux system to check if the change 
won't cause any issues their.



Thanks,
Sangamesh

[-- Attachment #2: aix-gcore.patch --]
[-- Type: application/octet-stream, Size: 5307 bytes --]

--- ./gdb/configure_orig	2017-10-10 03:49:09 -0500
+++ ./gdb/configure	2017-10-10 03:52:30 -0500
@@ -14672,6 +14672,7 @@
 _ACEOF
 
       fi
+      LIBS="$LIBS -lpthread"
       ;;
    esac
 
--- ./gdb/configure.ac_orig	2017-10-10 03:50:03 -0500
+++ ./gdb/configure.ac	2017-10-10 03:50:40 -0500
@@ -1782,6 +1782,7 @@
          # with AIX 6.x).
          AC_CHECK_DECLS(getthrds, [], [], [[#include <procinfo.h>]])
       fi
+      LIBS="$LIBS -lpthread"
       ;;
    esac
    AC_SUBST(CONFIG_LDFLAGS)
--- ./gdb/gcore.h_orig	2017-10-10 04:00:25 -0500
+++ ./gdb/gcore.h	2017-10-10 06:25:58 -0500
@@ -22,6 +22,18 @@
 
 #include "gdb_bfd.h"
 
+#if (GDB_OSABI_DEFAULT == GDB_OSABI_AIX)
+#include <core.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <libgen.h>
+struct aix_gencore_args {
+    char *name;
+    pid_t pid; 
+};
+extern void step_1_ext (int, int, char *);
+#endif
+
 extern gdb_bfd_ref_ptr create_gcore_bfd (const char *filename);
 extern void write_gcore_file (bfd *obfd);
 extern bfd *load_corefile (char *filename, int from_tty);
--- ./gdb/gcore.c_orig	2017-10-10 04:27:47 -0500
+++ ./gdb/gcore.c	2017-10-12 08:01:45 -0500
@@ -137,6 +137,22 @@
     throw_exception (except);
 }
 
+/* AIX gcore helper function */
+void * issue_gencore_aix (void *args)
+{
+    struct coredumpinfo dumpinfo;
+    int rc = 0;
+
+    dumpinfo.length = strlen(((struct aix_gencore_args *)args)->name);
+    dumpinfo.name = ((struct aix_gencore_args *)args)->name;
+    dumpinfo.flags = GENCORE_VERSION_1;
+    dumpinfo.pid = ((struct aix_gencore_args *)args)->pid;
+    rc = gencore(&dumpinfo);
+    if (rc != 0)
+       fprintf_filtered (gdb_stdout, "gencore failed\n");
+    return NULL;
+}
+
 /* gcore_command -- implements the 'gcore' command.
    Generate a core file from the inferior process.  */
 
@@ -145,6 +161,15 @@
 {
   gdb::unique_xmalloc_ptr<char> corefilename;
 
+  #if (GDB_OSABI_DEFAULT == GDB_OSABI_AIX)
+  pthread_t gcore_t;
+  struct aix_gencore_args g_args;
+  int rc = 0;
+  time64_t last_mod = 0;
+  char *dir, *aix_core;
+  struct stat64 st;
+  #endif
+
   /* No use generating a corefile without a target process.  */
   if (!target_has_execution)
     noprocess ();
@@ -162,6 +187,49 @@
 		      "Opening corefile '%s' for output.\n",
 		      corefilename.get ());
 
+   #if (GDB_OSABI_DEFAULT == GDB_OSABI_AIX)
+   aix_core = corefilename.get ();
+   g_args.name = aix_core;
+   g_args.pid = ptid_get_pid (inferior_ptid);
+
+   memset (&st, 0, sizeof(st)); 
+   if (!access (aix_core, W_OK)) {
+       if (!stat (aix_core, &st))
+           last_mod = st.st_mtime;
+   }
+   dir = dirname (aix_core);
+   /* Check if directory has the write permission. */
+   if (dir && !access (dir, W_OK) && !S_ISDIR(st.st_mode)) {
+       rc = pthread_create(&gcore_t, NULL, issue_gencore_aix, &g_args);
+       if (!rc) {
+           step_1_ext (0, 1, "1");
+           if (!access (aix_core, R_OK) && !last_mod)
+               fprintf_filtered (gdb_stdout,
+                           "Saved corefile '%s' \n", aix_core);
+           else if (!access (aix_core, R_OK) && last_mod)  {
+               stat(aix_core, &st);
+               if (st.st_mtime >= last_mod)
+                   fprintf_filtered (gdb_stdout,
+                              "Saved corefile '%s' \n", aix_core);
+               else
+                   fprintf_filtered (gdb_stdout,
+                              "Unable to generate core\n");
+           }
+           else
+           /* Their can be a slight delay in scheduling gencore call after gdb's
+              single step for an multi-threaded programs, and above checks might
+              fail. But eventually we will be having a core file generated from
+              the gencore. So display informative message that core will be 
+              created. */
+           fprintf_filtered (gdb_stdout,
+                          "corefile might be saved as '%s' \n", aix_core); 
+       }
+   }
+   else
+       fprintf_filtered (gdb_stdout,
+                       "Can't open :%s for writing \n", aix_core);
+  #else
+
   /* Open the output file.  */
   gdb_bfd_ref_ptr obfd (create_gcore_bfd (corefilename.get ()));
 
@@ -175,6 +243,7 @@
   unlink_file.keep ();
 
   fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename.get ());
+  #endif
 }
 
 static unsigned long
--- ./gdb/infcmd.c_orig	2017-10-10 04:06:30 -0500
+++ ./gdb/infcmd.c	2017-10-10 04:07:02 -0500
@@ -136,6 +136,11 @@
 
 int startup_with_shell = 1;
 
+void step_1_ext (int skip, int inst, char *string)
+{
+    step_1 (skip, inst, string);
+}
+
 \f
 /* Accessor routines.  */
 
--- ./include/libiberty.h_orig	2017-10-10 06:15:51 -0500
+++ ./include/libiberty.h	2017-10-10 06:49:24 -0500
@@ -105,6 +105,7 @@
    to find the declaration so provide a fully prototyped one.  If it
    is 1, we found it so don't provide any declaration at all.  */
 #if !HAVE_DECL_BASENAME
+#ifndef _AIX
 #if defined (__GNU_LIBRARY__ ) || defined (__linux__) \
  || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \
  || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) \
@@ -117,6 +118,7 @@
 #define basename basename_cannot_be_used_without_a_prototype
 #endif
 #endif
+#endif
 
 /* A well-defined basename () that is always compiled in.  */
 

[-- Attachment #3: testings --]
[-- Type: application/octet-stream, Size: 3924 bytes --]

Testing with sample program
---------------------------

Reading symbols from /tmp/test...done.
(gdb) br main
Breakpoint 1 at 0x1000040c: file test.c, line 4.
(gdb) gcore
You can't do that without a process to debug.
(gdb) r
Starting program: /tmp/test 

Breakpoint 1, main () at test.c:4
4          int i = 2;
(gdb) disassemble 
Dump of assembler code for function main:
......
   0x10000408 <+16>:    mr      r31,r1
=> 0x1000040c <+20>:    li      r9,2
   0x10000410 <+24>:    stw     r9,56(r31)
......
End of assembler dump.
(gdb) gcore
Saved corefile 'core.14680238' 
0x10000410      4          int i = 2;
(gdb) disassemble 
Dump of assembler code for function main:
......
   0x1000040c <+20>:    li      r9,2
=> 0x10000410 <+24>:    stw     r9,56(r31)
   0x10000414 <+28>:    li      r9,97
......
End of assembler dump.
(gdb) gcore /tmp/core_test
Saved corefile '/tmp/core_test' 
5          char j = 'a';
(gdb) disassemble 
Dump of assembler code for function main:
......
   0x10000410 <+24>:    stw     r9,56(r31)
=> 0x10000414 <+28>:    li      r9,97
   0x10000418 <+32>:    stb     r9,60(r31)
......
End of assembler dump.
(gdb) gcore /tmp/test_gcore/t
Can't open :/tmp/test_gcore/t for writing 
(gdb) gcore /tmp/test_gcore/ 
Can't open :/tmp/test_gcore/ for writing 
(gdb) gcore /tmp/test_gcore/t             <= After creating the directory /tmp/test_gcore
Saved corefile '/tmp/test_gcore/t' 
0x10000418      5          char j = 'a';
(gdb) disassemble 
Dump of assembler code for function main:
......
   0x10000414 <+28>:    li      r9,97
=> 0x10000418 <+32>:    stb     r9,60(r31)
   0x1000041c <+36>:    li      r3,60
......
End of assembler dump.
(gdb) gcore ~/test_gcore
Saved corefile '//test_gcore' 
6          printf("Value of j:%d j:%c\n", i, j);
(gdb) disassemble 
Dump of assembler code for function main:
......
   0x10000418 <+32>:    stb     r9,60(r31)
=> 0x1000041c <+36>:    li      r3,60
   0x10000420 <+40>:    bl      0x1000049c <sleep>
......
End of assembler dump.
(gdb) 


running process
---------------
Reading symbols from /tmp/test...done.
Attaching to program: /tmp/test, process 14811202
0xd0120a54 in nsleep () from /usr/lib/libc.a(shr.o)
(gdb) disassemble 
Dump of assembler code for function nsleep:
......
   0xd0120a50 <+592>:   bl      0xd0121100 <_nsleep>
=> 0xd0120a54 <+596>:   l       r2,20(r1)
   0xd0120a58 <+600>:   mr.     r28,r3
......
End of assembler dump.
(gdb) gcore
Saved corefile 'core.14811202' 
0xd0120a58 in nsleep () from /usr/lib/libc.a(shr.o)
(gdb) disassemble 
Dump of assembler code for function nsleep:
......
   0xd0120a54 <+596>:   l       r2,20(r1)
=> 0xd0120a58 <+600>:   mr.     r28,r3
   0xd0120a5c <+604>:   beq     0xd0120a10 <nsleep+528>


Multi-threded application
-------------------------
Reading symbols from /tmp/th...done.
(gdb) br main
Breakpoint 1 at 0x1000048c: file th.c, line 31.
(gdb) r
Starting program: /tmp/th 
[New Thread 1]
[Switching to Thread 1]

Thread 2 hit Breakpoint 1, main () at th.c:31
31          int rc = 0;
(gdb) s
33          rc = pthread_create(&tid1, NULL, thread_func1, NULL);
(gdb) 
value of i in thread1 is :1
[New Thread 258]
34          if (rc)
(gdb) gcore
corefile might be saved as 'core.14811204' 
0x100004b4      34          if (rc)
(gdb) s
37          rc = pthread_create(&tid2, NULL, thread_func2, NULL);
(gdb) 
value of i in thread2 is :2
[New Thread 515]
38          if (rc)
(gdb) 
40          pthread_join(tid1, NULL);
(gdb) gcore
Saved corefile 'core.14811204' 
0x10000500      40          pthread_join(tid1, NULL);


Multi-threded running process
-----------------------------
Attaching to program: /tmp/th, process 15204524
[New Thread 1]
[New Thread 258]
[New Thread 515]
[Switching to Thread 258]
0xd0544070 in _p_nsleep () from /usr/lib/libpthreads.a(shr_xpg5.o)
(gdb) gcore
corefile might be saved as 'core.15204524' 
0xd0544074 in _p_nsleep () from /usr/lib/libpthreads.a(shr_xpg5.o)
(gdb) 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-10-18 10:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-13 10:58 gcore support for AIX Sangamesh Mallayya
2017-10-17 10:11 ` Ulrich Weigand
2017-10-18  9:41   ` Sangamesh Mallayya
2017-10-18 10:14     ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).