(get_myaddress): Avoid loopback interfaces, return loopback address
[kopensolaris-gnu/glibc.git] / malloc / mtrace.c
1 /* More debugging hooks for `malloc'.
2    Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
3                  Written April 2, 1991 by John Gilmore of Cygnus Support.
4                  Based on mcheck.c by Mike Haertel.
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with this library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.
20
21    The author may be reached (Email) at the address mike@ai.mit.edu,
22    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
23
24 #ifndef _MALLOC_INTERNAL
25 #define _MALLOC_INTERNAL
26 #include <malloc.h>
27 #include <mcheck.h>
28 #include <bits/libc-lock.h>
29 #endif
30
31 #include <stdio.h>
32
33 #ifndef __GNU_LIBRARY__
34 extern char *getenv ();
35 #else
36 #include <stdlib.h>
37 #endif
38
39 static FILE *mallstream;
40 static char mallenv[]= "MALLOC_TRACE";
41 static char mallbuf[BUFSIZ];    /* Buffer for the output.  */
42
43 __libc_lock_define_initialized (static, lock);
44
45 /* Address to breakpoint on accesses to... */
46 __ptr_t mallwatch;
47
48 /* File name and line number information, for callers that had
49    the foresight to call through a macro.  */
50 char *_mtrace_file;
51 int _mtrace_line;
52
53 /* Old hook values.  */
54 static void (*tr_old_free_hook) __P ((__ptr_t ptr));
55 static __ptr_t (*tr_old_malloc_hook) __P ((__malloc_size_t size));
56 static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, __malloc_size_t size));
57
58 /* This function is called when the block being alloc'd, realloc'd, or
59    freed has an address matching the variable "mallwatch".  In a debugger,
60    set "mallwatch" to the address of interest, then put a breakpoint on
61    tr_break.  */
62
63 void tr_break __P ((void));
64 void
65 tr_break ()
66 {
67 }
68
69 static void tr_where __P ((void));
70 static void
71 tr_where ()
72 {
73   if (_mtrace_file)
74     {
75       fprintf (mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line);
76       _mtrace_file = NULL;
77     }
78 }
79
80 static void tr_freehook __P ((__ptr_t));
81 static void
82 tr_freehook (ptr)
83      __ptr_t ptr;
84 {
85   tr_where ();
86   fprintf (mallstream, "- %p\n", ptr);  /* Be sure to print it first.  */
87   if (ptr == mallwatch)
88     tr_break ();
89   __libc_lock_lock (lock);
90   __free_hook = tr_old_free_hook;
91   free (ptr);
92   __free_hook = tr_freehook;
93   __libc_lock_unlock (lock);
94 }
95
96 static __ptr_t tr_mallochook __P ((__malloc_size_t));
97 static __ptr_t
98 tr_mallochook (size)
99      __malloc_size_t size;
100 {
101   __ptr_t hdr;
102
103   __libc_lock_lock (lock);
104
105   __malloc_hook = tr_old_malloc_hook;
106   hdr = (__ptr_t) malloc (size);
107   __malloc_hook = tr_mallochook;
108
109   __libc_lock_unlock (lock);
110
111   tr_where ();
112   /* We could be printing a NULL here; that's OK.  */
113   fprintf (mallstream, "+ %p %lx\n", hdr, (unsigned long)size);
114
115   if (hdr == mallwatch)
116     tr_break ();
117
118   return hdr;
119 }
120
121 static __ptr_t tr_reallochook __P ((__ptr_t, __malloc_size_t));
122 static __ptr_t
123 tr_reallochook (ptr, size)
124      __ptr_t ptr;
125      __malloc_size_t size;
126 {
127   __ptr_t hdr;
128
129   if (ptr == mallwatch)
130     tr_break ();
131
132   __libc_lock_lock (lock);
133
134   __free_hook = tr_old_free_hook;
135   __malloc_hook = tr_old_malloc_hook;
136   __realloc_hook = tr_old_realloc_hook;
137   hdr = (__ptr_t) realloc (ptr, size);
138   __free_hook = tr_freehook;
139   __malloc_hook = tr_mallochook;
140   __realloc_hook = tr_reallochook;
141
142   __libc_lock_unlock (lock);
143
144   tr_where ();
145   if (hdr == NULL)
146     /* Failed realloc.  */
147     fprintf (mallstream, "! %p %lx\n", ptr, (unsigned long)size);
148   else if (ptr == NULL)
149     fprintf (mallstream, "+ %p %lx\n", hdr, (unsigned long)size);
150   else
151     fprintf (mallstream, "< %p\n> %p %lx\n", ptr, hdr, (unsigned long)size);
152
153   if (hdr == mallwatch)
154     tr_break ();
155
156   return hdr;
157 }
158
159 /* We enable tracing if either the environment variable MALLOC_TRACE
160    is set, or if the variable mallwatch has been patched to an address
161    that the debugging user wants us to stop on.  When patching mallwatch,
162    don't forget to set a breakpoint on tr_break!  */
163
164 void
165 mtrace ()
166 {
167   char *mallfile;
168
169   /* Don't panic if we're called more than once.  */
170   if (mallstream != NULL)
171     return;
172
173 #ifdef _LIBC
174   /* When compiling the GNU libc we use the secure getenv function
175      which prevents the misuse in case of SUID or SGID enabled
176      programs.  */
177   mallfile = __secure_getenv (mallenv);
178 #else
179   mallfile = getenv (mallenv);
180 #endif
181   if (mallfile != NULL || mallwatch != NULL)
182     {
183       mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
184       if (mallstream != NULL)
185         {
186           /* Be sure it doesn't malloc its buffer!  */
187           setbuf (mallstream, mallbuf);
188           fprintf (mallstream, "= Start\n");
189           tr_old_free_hook = __free_hook;
190           __free_hook = tr_freehook;
191           tr_old_malloc_hook = __malloc_hook;
192           __malloc_hook = tr_mallochook;
193           tr_old_realloc_hook = __realloc_hook;
194           __realloc_hook = tr_reallochook;
195         }
196     }
197 }
198
199 void
200 muntrace ()
201 {
202   if (mallstream == NULL)
203     return;
204
205   fprintf (mallstream, "= End\n");
206   fclose (mallstream);
207   mallstream = NULL;
208   __free_hook = tr_old_free_hook;
209   __malloc_hook = tr_old_malloc_hook;
210   __realloc_hook = tr_old_realloc_hook;
211 }