]>
Commit | Line | Data |
---|---|---|
38cbfe40 RK |
1 | /**************************************************************************** |
2 | * * | |
3 | * GNATMEM COMPONENTS * | |
4 | * * | |
5 | * G M E M * | |
6 | * * | |
38cbfe40 RK |
7 | * C Implementation File * |
8 | * * | |
df87f988 | 9 | * Copyright (C) 2000-2003 Free Software Foundation, Inc. * |
38cbfe40 RK |
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. * | |
71ff80dc | 29 | * Extensive contributions were provided by Ada Core Technologies Inc. * |
38cbfe40 RK |
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 | |
5d1a9698 | 43 | GNU/Linux x86 |
38cbfe40 RK |
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 | |
fbf5a39b AC |
48 | be able to build the stack backtrace. |
49 | */ | |
38cbfe40 | 50 | |
fbf5a39b | 51 | #include <stdio.h> |
38cbfe40 RK |
52 | |
53 | static FILE *gmemfile; | |
54 | ||
55 | /* tb_len is the number of call level supported by this module */ | |
fbf5a39b AC |
56 | #define tb_len 200 |
57 | static char * tracebk [tb_len]; | |
38cbfe40 RK |
58 | static int cur_tb_len, cur_tb_pos; |
59 | ||
fbf5a39b AC |
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); | |
38cbfe40 | 72 | |
fbf5a39b AC |
73 | /* reads backtrace information from gmemfile placing them in tracebk |
74 | array. cur_tb_len is the size of this array | |
75 | */ | |
38cbfe40 RK |
76 | |
77 | static void | |
78 | gmem_read_backtrace () | |
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 | ||
fbf5a39b AC |
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 | */ | |
38cbfe40 | 89 | |
fbf5a39b | 90 | int __gnat_gmem_initialize (char *dumpname) |
38cbfe40 | 91 | { |
fbf5a39b | 92 | char header [10]; |
38cbfe40 RK |
93 | |
94 | gmemfile = fopen (dumpname, "rb"); | |
95 | fread (header, 10, 1, gmemfile); | |
96 | ||
fbf5a39b | 97 | /* check for GMEM magic-tag */ |
38cbfe40 RK |
98 | if (memcmp (header, "GMEM DUMP\n", 10)) |
99 | { | |
100 | fclose (gmemfile); | |
101 | return 0; | |
102 | } | |
c0b1738d | 103 | |
38cbfe40 RK |
104 | return 1; |
105 | } | |
106 | ||
fbf5a39b | 107 | /* initialize addr2line library */ |
38cbfe40 | 108 | |
fbf5a39b | 109 | void __gnat_gmem_a2l_initialize (char *exename) |
38cbfe40 RK |
110 | { |
111 | extern char **gnat_argv; | |
fbf5a39b | 112 | char s [100]; |
38cbfe40 RK |
113 | int l; |
114 | ||
fbf5a39b | 115 | gnat_argv [0] = exename; |
38cbfe40 RK |
116 | convert_addresses (tracebk, 1, s, &l); |
117 | } | |
118 | ||
119 | /* Read next allocation of deallocation information from the GMEM file and | |
fbf5a39b | 120 | write an alloc/free information in buf to be processed by gnatmem */ |
38cbfe40 RK |
121 | |
122 | void | |
123 | __gnat_gmem_read_next (buf) | |
fbf5a39b | 124 | struct struct_storage_elmt *buf; |
38cbfe40 RK |
125 | { |
126 | void *addr; | |
fbf5a39b | 127 | size_t size; |
c0b1738d | 128 | int j; |
38cbfe40 | 129 | |
c0b1738d RK |
130 | j = fgetc (gmemfile); |
131 | if (j == EOF) | |
38cbfe40 RK |
132 | { |
133 | fclose (gmemfile); | |
fbf5a39b | 134 | buf->Elmt = LOG_EOF; |
38cbfe40 RK |
135 | } |
136 | else | |
137 | { | |
c0b1738d | 138 | switch (j) |
38cbfe40 RK |
139 | { |
140 | case 'A' : | |
fbf5a39b AC |
141 | buf->Elmt = LOG_ALLOC; |
142 | fread (&(buf->Address), sizeof (void *), 1, gmemfile); | |
143 | fread (&(buf->Size), sizeof (size_t), 1, gmemfile); | |
38cbfe40 RK |
144 | break; |
145 | case 'D' : | |
fbf5a39b AC |
146 | buf->Elmt = LOG_DEALL; |
147 | fread (&(buf->Address), sizeof (void *), 1, gmemfile); | |
38cbfe40 RK |
148 | break; |
149 | default: | |
fbf5a39b | 150 | puts ("GNATMEM dump file corrupt"); |
38cbfe40 RK |
151 | __gnat_os_exit (1); |
152 | } | |
153 | ||
154 | gmem_read_backtrace (); | |
155 | } | |
156 | } | |
157 | ||
fbf5a39b AC |
158 | /* Read the next frame from the current traceback, and move the cursor to the |
159 | next frame */ | |
38cbfe40 | 160 | |
fbf5a39b | 161 | void __gnat_gmem_read_next_frame (void** addr) |
38cbfe40 | 162 | { |
fbf5a39b AC |
163 | if (cur_tb_pos >= cur_tb_len) { |
164 | *addr = NULL; | |
165 | } else { | |
166 | *addr = (void*)*(tracebk + cur_tb_pos); | |
167 | ++cur_tb_pos; | |
168 | } | |
38cbfe40 RK |
169 | } |
170 | ||
fbf5a39b AC |
171 | /* Converts addr into a symbolic traceback, and stores the result in buf |
172 | with a format suitable for gnatmem */ | |
38cbfe40 | 173 | |
fbf5a39b | 174 | void __gnat_gmem_symbolic (void * addr, char* buf, int* length) |
38cbfe40 | 175 | { |
fbf5a39b AC |
176 | char* addresses [] = { (char*)addr }; |
177 | extern char** gnat_argv; | |
38cbfe40 | 178 | |
fbf5a39b | 179 | convert_addresses (addresses, 1, buf, length); |
38cbfe40 | 180 | } |