1 /**************************************************************************** 2 * * 3 * GNATMEM COMPONENTS * 4 * * 5 * G M E M * 6 * * 7 * C Implementation File * 8 * * 9 * Copyright (C) 2000-2003 Free Software Foundation, Inc. * 10 * * 11 * GNAT is free software; you can redistribute it and/or modify it under * 12 * terms of the GNU General Public License as published by the Free Soft- * 13 * ware Foundation; either version 2, or (at your option) any later ver- * 14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- * 15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * 17 * for more details. You should have received a copy of the GNU General * 18 * Public License distributed with GNAT; see file COPYING. If not, write * 19 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, * 20 * MA 02111-1307, USA. * 21 * * 22 * As a special exception, if you link this file with other files to * 23 * produce an executable, this file does not by itself cause the resulting * 24 * executable to be covered by the GNU General Public License. This except- * 25 * ion does not however invalidate any other reasons why the executable * 26 * file might be covered by the GNU Public License. * 27 * * 28 * GNAT was originally developed by the GNAT team at New York University. * 29 * Extensive contributions were provided by Ada Core Technologies Inc. * 30 * * 31 ****************************************************************************/ 32 33 /* This unit reads the allocation tracking log produced by augmented 34 __gnat_malloc and __gnat_free procedures (see file a-raise.c) and 35 provides GNATMEM tool with gdb-compliant output. The output is 36 processed by GNATMEM to detect dynamic memory allocation errors. 37 38 See GNATMEM section in GNAT User's Guide for more information. 39 40 NOTE: This capability is currently supported on the following targets: 41 42 DEC Unix 43 GNU/Linux x86 44 Solaris (sparc and x86) (*) 45 Windows 98/95/NT (x86) 46 47 (*) on these targets, the compilation must be done with -funwind-tables to 48 be able to build the stack backtrace. 49 */ 50 51 #include <stdio.h> 52 53 static FILE *gmemfile; 54 55 /* tb_len is the number of call level supported by this module */ 56 #define tb_len 200 57 static char * tracebk [tb_len]; 58 static int cur_tb_len, cur_tb_pos; 59 60 #define LOG_EOF '*' 61 #define LOG_ALLOC 'A' 62 #define LOG_DEALL 'D' 63 64 struct struct_storage_elmt { 65 char Elmt; 66 void * Address; 67 size_t Size; 68 }; 69 70 extern void 71 convert_addresses (char *addrs[], int n_addr, void *buf, int *len); 72 73 /* reads backtrace information from gmemfile placing them in tracebk 74 array. cur_tb_len is the size of this array 75 */ 76 77 static void 78 gmem_read_backtrace (void) 79 { 80 fread (&cur_tb_len, sizeof (int), 1, gmemfile); 81 fread (tracebk, sizeof (char *), cur_tb_len, gmemfile); 82 cur_tb_pos = 0; 83 } 84 85 /* initialize gmem feature from the dumpname file. It returns 1 if the 86 dumpname has beed generated by GMEM (instrumented malloc/free) and 0 if not 87 (i.e. probably a GDB generated file). 88 */ 89 90 int __gnat_gmem_initialize (char *dumpname) 91 { 92 char header [10]; 93 94 gmemfile = fopen (dumpname, "rb"); 95 fread (header, 10, 1, gmemfile); 96 97 /* check for GMEM magic-tag */ 98 if (memcmp (header, "GMEM DUMP\n", 10)) 99 { 100 fclose (gmemfile); 101 return 0; 102 } 103 104 return 1; 105 } 106 107 /* initialize addr2line library */ 108 109 void __gnat_gmem_a2l_initialize (char *exename) 110 { 111 extern char **gnat_argv; 112 char s [100]; 113 int l; 114 115 gnat_argv [0] = exename; 116 convert_addresses (tracebk, 1, s, &l); 117 } 118 119 /* Read next allocation of deallocation information from the GMEM file and 120 write an alloc/free information in buf to be processed by gnatmem */ 121 122 void 123 __gnat_gmem_read_next (struct struct_storage_elmt *buf) 124 { 125 void *addr; 126 size_t size; 127 int j; 128 129 j = fgetc (gmemfile); 130 if (j == EOF) 131 { 132 fclose (gmemfile); 133 buf->Elmt = LOG_EOF; 134 } 135 else 136 { 137 switch (j) 138 { 139 case 'A' : 140 buf->Elmt = LOG_ALLOC; 141 fread (&(buf->Address), sizeof (void *), 1, gmemfile); 142 fread (&(buf->Size), sizeof (size_t), 1, gmemfile); 143 break; 144 case 'D' : 145 buf->Elmt = LOG_DEALL; 146 fread (&(buf->Address), sizeof (void *), 1, gmemfile); 147 break; 148 default: 149 puts ("GNATMEM dump file corrupt"); 150 __gnat_os_exit (1); 151 } 152 153 gmem_read_backtrace (); 154 } 155 } 156 157 /* Read the next frame from the current traceback, and move the cursor to the 158 next frame */ 159 160 void __gnat_gmem_read_next_frame (void** addr) 161 { 162 if (cur_tb_pos >= cur_tb_len) { 163 *addr = NULL; 164 } else { 165 *addr = (void*)*(tracebk + cur_tb_pos); 166 ++cur_tb_pos; 167 } 168 } 169 170 /* Converts addr into a symbolic traceback, and stores the result in buf 171 with a format suitable for gnatmem */ 172 173 void __gnat_gmem_symbolic (void * addr, char* buf, int* length) 174 { 175 char* addresses [] = { (char*)addr }; 176 extern char** gnat_argv; 177 178 convert_addresses (addresses, 1, buf, length); 179 } 180