Rebuild of the OpenSSL memory allocation and deallocation routines.
[openssl.git] / crypto / mem_dbg.c
1 /* crypto/mem_dbg.c */
2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <time.h>       
62 #include <openssl/crypto.h>
63 #include <openssl/buffer.h>
64 #include <openssl/bio.h>
65 #include <openssl/lhash.h>
66 #include "cryptlib.h"
67
68 /* State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
69  * thinks that certain allocations should not be checked (e.g. the data
70  * structures used for memory checking).  It is not suitable as an initial
71  * state: the library will unexpectedly enable memory checking when it
72  * executes one of those sections that want to disable checking
73  * temporarily.
74  *
75  * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
76  */
77 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
78 static unsigned long disabling_thread = 0;
79
80
81 static unsigned long order=0;
82
83 static LHASH *amih=NULL;
84
85 typedef struct app_mem_info_st
86         {       
87         unsigned long thread;
88         const char *file;
89         int line;
90         const char *info;
91         struct app_mem_info_st *next;
92         int references;
93         } APP_INFO;
94
95 static LHASH *mh=NULL;
96
97 typedef struct mem_st
98         {
99         char *addr;
100         int num;
101         const char *file;
102         int line;
103         unsigned long thread;
104         unsigned long order;
105         time_t time;
106         APP_INFO *app_info;
107         } MEM;
108
109 static int options = V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD;
110
111
112 int CRYPTO_mem_ctrl(int mode)
113         {
114         int ret=mh_mode;
115
116         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
117         switch (mode)
118                 {
119         /* for applications: */
120         case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
121                 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
122                 disabling_thread = 0;
123                 break;
124         case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
125                 mh_mode = 0;
126                 disabling_thread = 0;
127                 break;
128
129         /* switch off temporarily (for library-internal use): */
130         case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
131                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
132                         {
133                         mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
134                         if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
135                                 {
136                                 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
137                                  * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
138                                  * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release it
139                                  * because we block entry to this function).
140                                  * Give them a chance, first, and then claim the locks in
141                                  * appropriate order (long-time lock first).
142                                  */
143                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
144                                 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
145                                  * and CRYPTO_LOCK_MALLOC, we'll still be in the right
146                                  * "case" and "if" branch because MemCheck_start and
147                                  * MemCheck_stop may never be used while there are multiple
148                                  * OpenSSL threads. */
149                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
150                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
151                                 disabling_thread=CRYPTO_thread_id();
152                                 }
153                         }
154                 break;
155         case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
156                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
157                         {
158                         mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
159                         if (disabling_thread != 0)
160                                 {
161                                 disabling_thread=0;
162                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
163                                 }
164                         }
165                 break;
166
167         default:
168                 break;
169                 }
170         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
171         return(ret);
172         }
173
174 int CRYPTO_mem_check_on(void)
175         {
176         int ret = 0;
177
178         if (mh_mode & CRYPTO_MEM_CHECK_ON)
179                 {
180                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
181
182                 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
183                         && disabling_thread != CRYPTO_thread_id();
184
185                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
186                 }
187         return(ret);
188         }       
189
190
191 void CRYPTO_dbg_set_options(int bits)
192         {
193         options = bits;
194         }
195
196 int CRYPTO_dbg_get_options()
197         {
198         return options;
199         }
200
201 static int mem_cmp(MEM *a, MEM *b)
202         {
203         return(a->addr - b->addr);
204         }
205
206 static unsigned long mem_hash(MEM *a)
207         {
208         unsigned long ret;
209
210         ret=(unsigned long)a->addr;
211
212         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
213         return(ret);
214         }
215
216 static int app_info_cmp(APP_INFO *a, APP_INFO *b)
217         {
218         return(a->thread - b->thread);
219         }
220
221 static unsigned long app_info_hash(APP_INFO *a)
222         {
223         unsigned long ret;
224
225         ret=(unsigned long)a->thread;
226
227         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
228         return(ret);
229         }
230
231 static APP_INFO *remove_info()
232         {
233         APP_INFO tmp;
234         APP_INFO *ret = NULL;
235
236         if (amih != NULL)
237                 {
238                 tmp.thread=CRYPTO_thread_id();
239                 if ((ret=(APP_INFO *)lh_delete(amih,(char *)&tmp)) != NULL)
240                         {
241                         APP_INFO *next=ret->next;
242
243                         if (next != NULL)
244                                 {
245                                 next->references++;
246                                 lh_insert(amih,(char *)next);
247                                 }
248 #ifdef LEVITTE_DEBUG
249                         if (ret->thread != tmp.thread)
250                                 {
251                                 fprintf(stderr, "remove_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
252                                         ret->thread, tmp.thread);
253                                 abort();
254                                 }
255 #endif
256                         if (--(ret->references) <= 0)
257                                 {
258                                 ret->next = NULL;
259                                 if (next != NULL)
260                                         next->references--;
261                                 Free(ret);
262                                 }
263                         }
264                 }
265         return(ret);
266         }
267
268 int CRYPTO_add_info(const char *file, int line, const char *info)
269         {
270         APP_INFO *ami, *amim;
271         int ret=0;
272
273         if (is_MemCheck_on())
274                 {
275                 MemCheck_off();
276
277                 if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL)
278                         {
279                         ret=0;
280                         goto err;
281                         }
282                 if (amih == NULL)
283                         {
284                         if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL)
285                                 {
286                                 Free(ami);
287                                 ret=0;
288                                 goto err;
289                                 }
290                         }
291
292                 ami->thread=CRYPTO_thread_id();
293                 ami->file=file;
294                 ami->line=line;
295                 ami->info=info;
296                 ami->references=1;
297                 ami->next=NULL;
298
299                 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
300                         {
301 #ifdef LEVITTE_DEBUG
302                         if (ami->thread != amim->thread)
303                                 {
304                                 fprintf(stderr, "CRYPTO_add_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
305                                         amim->thread, ami->thread);
306                                 abort();
307                                 }
308 #endif
309                         ami->next=amim;
310                         }
311  err:
312                 MemCheck_on();
313                 }
314
315         return(ret);
316         }
317
318 int CRYPTO_remove_info(void)
319         {
320         int ret=0;
321
322         if (is_MemCheck_on())
323                 {
324                 MemCheck_off();
325
326                 ret=(remove_info() != NULL);
327
328                 MemCheck_on();
329                 }
330         return(ret);
331         }
332
333 int CRYPTO_remove_all_info(void)
334         {
335         int ret=0;
336
337         if (is_MemCheck_on())
338                 {
339                 MemCheck_off();
340
341                 while(remove_info() != NULL)
342                         ret++;
343
344                 MemCheck_on();
345                 }
346         return(ret);
347         }
348
349
350 static unsigned long break_order_num=0;
351 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
352         int before_p)
353         {
354         MEM *m,*mm;
355         APP_INFO tmp,*amim;
356
357         switch(before_p & 127)
358                 {
359         case 0:
360                 break;
361         case 1:
362                 if (addr == NULL)
363                         break;
364
365                 if (is_MemCheck_on())
366                         {
367                         MemCheck_off();
368                         if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
369                                 {
370                                 Free(addr);
371                                 MemCheck_on();
372                                 return;
373                                 }
374                         if (mh == NULL)
375                                 {
376                                 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
377                                         {
378                                         Free(addr);
379                                         Free(m);
380                                         addr=NULL;
381                                         goto err;
382                                         }
383                                 }
384
385                         m->addr=addr;
386                         m->file=file;
387                         m->line=line;
388                         m->num=num;
389                         if (options & V_CRYPTO_MDEBUG_THREAD)
390                                 m->thread=CRYPTO_thread_id();
391                         else
392                                 m->thread=0;
393
394                         if (order == break_order_num)
395                                 {
396                                 /* BREAK HERE */
397                                 m->order=order;
398                                 }
399                         m->order=order++;
400 #ifdef LEVITTE_DEBUG
401                         fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n",
402                                 m->order,
403                                 (before_p & 128) ? '*' : '+',
404                                 m->addr, m->num);
405 #endif
406                         if (options & V_CRYPTO_MDEBUG_TIME)
407                                 m->time=time(NULL);
408                         else
409                                 m->time=0;
410
411                         tmp.thread=CRYPTO_thread_id();
412                         m->app_info=NULL;
413                         if (amih != NULL
414                                 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
415                                 {
416                                 m->app_info = amim;
417                                 amim->references++;
418                                 }
419
420                         if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
421                                 {
422                                 /* Not good, but don't sweat it */
423                                 if (mm->app_info != NULL)
424                                         {
425                                         mm->app_info->references--;
426                                         }
427                                 Free(mm);
428                                 }
429                 err:
430                         MemCheck_on();
431                         }
432                 break;
433                 }
434         return;
435         }
436
437 void CRYPTO_dbg_free(void *addr, int before_p)
438         {
439         MEM m,*mp;
440
441         switch(before_p)
442                 {
443         case 0:
444                 if (addr == NULL)
445                         break;
446
447                 if (is_MemCheck_on() && (mh != NULL))
448                         {
449                         MemCheck_off();
450
451                         m.addr=addr;
452                         mp=(MEM *)lh_delete(mh,(char *)&m);
453                         if (mp != NULL)
454                                 {
455 #ifdef LEVITTE_DEBUG
456                         fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n",
457                                 mp->order, mp->addr, mp->num);
458 #endif
459                                 if (mp->app_info != NULL)
460                                         {
461                                         mp->app_info->references--;
462                                         }
463                                 Free(mp);
464                                 }
465
466                         MemCheck_on();
467                         }
468                 break;
469         case 1:
470                 break;
471                 }
472         }
473
474 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
475         const char *file, int line, int before_p)
476         {
477         MEM m,*mp;
478
479 #ifdef LEVITTE_DEBUG
480         fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
481                 addr1, addr2, num, file, line, before_p);
482 #endif
483
484         switch(before_p)
485                 {
486         case 0:
487                 break;
488         case 1:
489                 if (addr2 == NULL)
490                         break;
491
492                 if (addr1 == NULL)
493                         {
494                         CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
495                         break;
496                         }
497
498                 if (is_MemCheck_on())
499                         {
500                         MemCheck_off();
501
502                         m.addr=addr1;
503                         mp=(MEM *)lh_delete(mh,(char *)&m);
504                         if (mp != NULL)
505                                 {
506 #ifdef LEVITTE_DEBUG
507                                 fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
508                                         mp->order,
509                                         mp->addr, mp->num,
510                                         addr2, num);
511 #endif
512                                 mp->addr=addr2;
513                                 mp->num=num;
514                                 lh_insert(mh,(char *)mp);
515                                 }
516
517                         MemCheck_on();
518                         }
519                 break;
520                 }
521         return;
522         }
523
524
525 typedef struct mem_leak_st
526         {
527         BIO *bio;
528         int chunks;
529         long bytes;
530         } MEM_LEAK;
531
532 static void print_leak(MEM *m, MEM_LEAK *l)
533         {
534         char buf[1024];
535         char *bufp = buf;
536         APP_INFO *amip;
537         int ami_cnt;
538         struct tm *lcl = NULL;
539         unsigned long ti;
540
541         if(m->addr == (char *)l->bio)
542             return;
543
544         if (options & V_CRYPTO_MDEBUG_TIME)
545                 {
546                 lcl = localtime(&m->time);
547         
548                 sprintf(bufp, "[%02d:%02d:%02d] ",
549                         lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
550                 bufp += strlen(bufp);
551                 }
552
553         sprintf(bufp, "%5lu file=%s, line=%d, ",
554                 m->order,m->file,m->line);
555         bufp += strlen(bufp);
556
557         if (options & V_CRYPTO_MDEBUG_THREAD)
558                 {
559                 sprintf(bufp, "thread=%lu, ", m->thread);
560                 bufp += strlen(bufp);
561                 }
562
563         sprintf(bufp, "number=%d, address=%08lX\n",
564                 m->num,(unsigned long)m->addr);
565         bufp += strlen(bufp);
566
567         BIO_puts(l->bio,buf);
568         
569         l->chunks++;
570         l->bytes+=m->num;
571
572         amip=m->app_info;
573         ami_cnt=0;
574         if (amip)
575                 ti=amip->thread;
576         while(amip && amip->thread == ti)
577                 {
578                 int buf_len;
579                 int info_len;
580
581                 ami_cnt++;
582                 memset(buf,'>',ami_cnt);
583                 sprintf(buf + ami_cnt,
584                         "thread=%lu, file=%s, line=%d, info=\"",
585                         amip->thread, amip->file, amip->line);
586                 buf_len=strlen(buf);
587                 info_len=strlen(amip->info);
588                 if (128 - buf_len - 3 < info_len)
589                         {
590                         memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
591                         buf_len = 128 - 3;
592                         }
593                 else
594                         {
595                         strcpy(buf + buf_len, amip->info);
596                         buf_len = strlen(buf);
597                         }
598                 sprintf(buf + buf_len, "\"\n");
599                 
600                 BIO_puts(l->bio,buf);
601
602                 amip = amip->next;
603                 }
604 #ifdef LEVITTE_DEBUG
605         if (amip)
606                 {
607                 fprintf(stderr, "Thread switch detected i backtrace!!!!\n");
608                 abort();
609                 }
610 #endif
611         }
612
613 void CRYPTO_mem_leaks(BIO *b)
614         {
615         MEM_LEAK ml;
616         char buf[80];
617
618         if (mh == NULL) return;
619         ml.bio=b;
620         ml.bytes=0;
621         ml.chunks=0;
622         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
623         lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
624         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
625         if (ml.chunks != 0)
626                 {
627                 sprintf(buf,"%ld bytes leaked in %d chunks\n",
628                         ml.bytes,ml.chunks);
629                 BIO_puts(b,buf);
630                 }
631
632 #if 0
633         lh_stats_bio(mh,b);
634         lh_node_stats_bio(mh,b);
635         lh_node_usage_stats_bio(mh,b);
636 #endif
637         }
638
639 static void (*mem_cb)()=NULL;
640
641 static void cb_leak(MEM *m, char *cb)
642         {
643         void (*mem_callback)()=(void (*)())cb;
644         mem_callback(m->order,m->file,m->line,m->num,m->addr);
645         }
646
647 void CRYPTO_mem_leaks_cb(void (*cb)())
648         {
649         if (mh == NULL) return;
650         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
651         mem_cb=cb;
652         lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
653         mem_cb=NULL;
654         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
655         }
656
657 #ifndef NO_FP_API
658 void CRYPTO_mem_leaks_fp(FILE *fp)
659         {
660         BIO *b;
661
662         if (mh == NULL) return;
663         if ((b=BIO_new(BIO_s_file())) == NULL)
664                 return;
665         BIO_set_fp(b,fp,BIO_NOCLOSE);
666         CRYPTO_mem_leaks(b);
667         BIO_free(b);
668         }
669 #endif
670