OSDN Git Service

2007-04-20 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / gmem.c
index 48d1f62..508d18d 100644 (file)
@@ -4,10 +4,9 @@
  *                                                                          *
  *                                 G M E M                                  *
  *                                                                          *
- *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *         Copyright (C) 2000-2001 Free Software Foundation, Inc.           *
+ *         Copyright (C) 2000-2007, Free Software Foundation, Inc.          *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
@@ -17,8 +16,8 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
  * for  more details.  You should have  received  a copy of the GNU General *
  * Public License  distributed with GNAT;  see file COPYING.  If not, write *
- * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
- * MA 02111-1307, USA.                                                      *
+ * to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, *
+ * Boston, MA 02110-1301, USA.                                              *
  *                                                                          *
  * As a  special  exception,  if you  link  this file  with other  files to *
  * produce an executable,  this file does not by itself cause the resulting *
@@ -32,7 +31,7 @@
  ****************************************************************************/
 
 /*  This unit reads the allocation tracking log produced by augmented
-    __gnat_malloc and __gnat_free procedures (see file a-raise.c) and
+    __gnat_malloc and __gnat_free procedures (see file memtrack.adb) and
     provides GNATMEM tool with gdb-compliant output. The output is
     processed by GNATMEM to detect dynamic memory allocation errors.
 
     NOTE: This capability is currently supported on the following targets:
 
       DEC Unix
-      SGI Irix
       GNU/Linux x86
       Solaris (sparc and x86) (*)
       Windows 98/95/NT (x86)
+      Alpha OpenVMS
 
     (*) on these targets, the compilation must be done with -funwind-tables to
-    be able to build the stack backtrace.   */
-
-#ifdef __alpha_vxworks
-#include "vxWorks.h"
-#endif
+    be able to build the stack backtrace.
 
-#ifdef IN_RTS
-#include "tconfig.h"
-#include "tsystem.h"
-#else
-#include "config.h"
-#include "system.h"
-#endif
+*/
 
-#include "adaint.h"
+#include <stdio.h>
 
 static FILE *gmemfile;
 
 /* tb_len is the number of call level supported by this module */
-#define TB_LEN 200
-
-static char *tracebk[TB_LEN];
+#define tb_len 200
+static void * tracebk [tb_len];
 static int cur_tb_len, cur_tb_pos;
 
-extern void convert_addresses          PARAMS ((char *[], int, void *,
-                                                int *));
-static void gmem_read_backtrace        PARAMS ((void));
-static char *spc2nul                   PARAMS ((char *));
+#define LOG_EOF   '*'
+#define LOG_ALLOC 'A'
+#define LOG_DEALL 'D'
+
+struct struct_storage_elmt {
+  char   Elmt;
+  void * Address;
+  size_t Size;
+  long long Timestamp;
+};
+
+static void
+__gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len);
+/* Place in BUF a string representing the symbolic translation of N_ADDRS raw
+   addresses provided in ADDRS.  LEN is filled with the result length.
+
+   This is a GNAT specific interface to the libaddr2line convert_addresses
+   routine.  The latter examines debug info from a provided executable file
+   name to perform the translation into symbolic form of an input sequence of
+   raw binary addresses.  It attempts to open the file from the provided name
+   "as is", so an an absolute path must be provided to ensure the file is
+   always found.  We compute this name once, at initialization time.  */
+
+static const char * exename = 0;
+
+extern void convert_addresses (const char * , void *[], int, void *, int *);
+extern char  *__gnat_locate_exec_on_path (char *);
+/* ??? Both of these extern functions are prototyped in adaint.h, which
+   also refers to "time_t" hence needs complex extra header inclusions to
+   be satisfied on every target.  */
+
+static void
+__gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len)
+{
+  if (exename != 0)
+    convert_addresses (exename, addrs, n_addrs, buf, len);
+  else
+    *len = 0;
+}
 
-extern int __gnat_gmem_initialize      PARAMS ((char *));
-extern void __gnat_gmem_a2l_initialize PARAMS ((char *));
-extern void __gnat_gmem_read_next      PARAMS ((char *));
-extern void __gnat_gmem_read_bt_frame  PARAMS ((char *));
-\f
-/* Reads backtrace information from gmemfile placing them in tracebk
-   array. cur_tb_len is the size of this array.   */
+/* reads backtrace information from gmemfile placing them in tracebk
+   array. cur_tb_len is the size of this array
+*/
 
 static void
-gmem_read_backtrace ()
+gmem_read_backtrace (void)
 {
   fread (&cur_tb_len, sizeof (int), 1, gmemfile);
-  fread (tracebk, sizeof (char *), cur_tb_len, gmemfile);
+  fread (tracebk, sizeof (void *), cur_tb_len, gmemfile);
   cur_tb_pos = 0;
 }
 
-/* Initialize gmem feature from the dumpname file. Return 1 if the
-   dumpname has been generated by GMEM (instrumented malloc/free) and 0 if not
-   (i.e. probably a GDB generated file). */
+/* initialize gmem feature from the dumpname file. It returns t0 timestamp
+   if the dumpname has been generated by GMEM (instrumented malloc/free)
+   and 0 if not.
+*/
 
-int
-__gnat_gmem_initialize (dumpname)
-     char *dumpname;
+long long __gnat_gmem_initialize (char *dumpname)
 {
-  char header[10];
+  char header [10];
+  long long t0;
 
   gmemfile = fopen (dumpname, "rb");
   fread (header, 10, 1, gmemfile);
 
-  /* Check for GMEM magic-tag.  */
+  /* check for GMEM magic-tag */
   if (memcmp (header, "GMEM DUMP\n", 10))
     {
       fclose (gmemfile);
       return 0;
     }
 
-  return 1;
+  fread (&t0, sizeof (long long), 1, gmemfile);
+
+  return t0;
 }
 
-/* Initialize addr2line library */
+/* initialize addr2line library */
 
-void
-__gnat_gmem_a2l_initialize (exename)
-     char *exename;
+void __gnat_gmem_a2l_initialize (char *exearg)
 {
-  extern char **gnat_argv;
-  char s[100];
-  int l;
-
-  gnat_argv[0] = exename;
-  convert_addresses (tracebk, 1, s, &l);
+  /* Resolve the executable filename to use in later invocations of
+     the libaddr2line symbolization service.  */
+  exename = __gnat_locate_exec_on_path (exearg);
 }
 
 /* Read next allocation of deallocation information from the GMEM file and
-   write an alloc/free information in buf to be processed by GDB (see gnatmem
-   implementation). */
+   write an alloc/free information in buf to be processed by gnatmem */
 
 void
-__gnat_gmem_read_next (buf)
-     char *buf;
+__gnat_gmem_read_next (struct struct_storage_elmt *buf)
 {
   void *addr;
-  int size;
+  size_t size;
   int j;
 
   j = fgetc (gmemfile);
   if (j == EOF)
     {
       fclose (gmemfile);
-      sprintf (buf, "Program exited.");
+      buf->Elmt = LOG_EOF;
     }
   else
     {
       switch (j)
         {
           case 'A' :
-            fread (&addr, sizeof (char *), 1, gmemfile);
-            fread (&size, sizeof (int), 1, gmemfile);
-            sprintf (buf, "ALLOC^%d^0x%lx^", size, (long) addr);
+            buf->Elmt = LOG_ALLOC;
+            fread (&(buf->Address), sizeof (void *), 1, gmemfile);
+            fread (&(buf->Size), sizeof (size_t), 1, gmemfile);
+            fread (&(buf->Timestamp), sizeof (long long), 1, gmemfile);
             break;
           case 'D' :
-            fread (&addr, sizeof (char *), 1, gmemfile);
-            sprintf (buf, "DEALL^0x%lx^", (long) addr);
+            buf->Elmt = LOG_DEALL;
+            fread (&(buf->Address), sizeof (void *), 1, gmemfile);
+            fread (&(buf->Timestamp), sizeof (long long), 1, gmemfile);
             break;
           default:
-            puts ("GMEM dump file corrupt");
+            puts ("GNATMEM dump file corrupt");
             __gnat_os_exit (1);
         }
 
@@ -169,48 +185,25 @@ __gnat_gmem_read_next (buf)
     }
 }
 
-/* Scans the line until the space or new-line character is encountered;
-   this character is replaced by nul and its position is returned.  */
+/* Read the next frame from the current traceback, and move the cursor to the
+   next frame */
 
-static char *
-spc2nul (s)
-     char *s;
+void __gnat_gmem_read_next_frame (void** addr)
 {
-  while (*++s)
-    if (*s == ' ' || *s == '\n')
-      {
-       *s = 0;
-       return s;
-      }
-
-  abort ();
+  if (cur_tb_pos >= cur_tb_len) {
+    *addr = NULL;
+  } else {
+    *addr = (void*)*(tracebk + cur_tb_pos);
+    ++cur_tb_pos;
+  }
 }
 
-/* Convert backtrace address in tracebk at position cur_tb_pos to a symbolic
-   traceback information returned in buf and to be processed by GDB (see
-   gnatmem implementation).  */
+/* Converts addr into a symbolic traceback, and stores the result in buf
+   with a format suitable for gnatmem */
 
-void
-__gnat_gmem_read_bt_frame (buf)
-     char *buf;
+void __gnat_gmem_symbolic (void * addr, char* buf, int* length)
 {
-  int l = 0;
-  char s[1000];
-  char *name, *file;
-
-  if (cur_tb_pos >= cur_tb_len)
-    {
-      buf[0] = ' ';
-      buf[1] = '\0';
-      return;
-    }
-
-  convert_addresses (tracebk + cur_tb_pos, 1, s, &l);
-  s[l] = '\0';
-  name = spc2nul (s) + 4;
-  file = spc2nul (name) + 4;
-  spc2nul (file);
-  ++cur_tb_pos;
+  void * addresses [] = { addr };
 
-  sprintf (buf, "#  %s () at %s", name, file);
+  __gnat_convert_addresses (addresses, 1, buf, length);
 }