1 #include "links.h"
2
3 char dummy_val;
4 volatile char *dummy_ptr = &dummy_val;
5
do_not_optimize_here(void * p)6 void do_not_optimize_here(void *p)
7 {
8 *dummy_ptr = 0;
9 /* break ANSI aliasing */
10 }
11
12 #ifdef LEAK_DEBUG
13 my_uintptr_t mem_amount = 0;
14 #ifdef LEAK_DEBUG_LIST
15 struct list_head memory_list = { &memory_list, &memory_list };
16 #endif
17 #endif
18
force_dump()19 static inline void force_dump()
20 {
21 int rs;
22 fprintf(stderr, "\n"ANSI_SET_BOLD"Forcing core dump"ANSI_CLEAR_BOLD"\n");
23 fflush(stdout);
24 fflush(stderr);
25 fatal_tty_exit();
26 EINTRLOOP(rs, raise(SIGSEGV));
27 }
28
check_memory_leaks()29 void check_memory_leaks()
30 {
31 #ifdef LEAK_DEBUG
32 if (mem_amount) {
33 fprintf(stderr, "\n"ANSI_SET_BOLD"Memory leak by %lu bytes"ANSI_CLEAR_BOLD"\n", (unsigned long)mem_amount);
34 #ifdef LEAK_DEBUG_LIST
35 fprintf(stderr, "\nList of blocks: ");
36 {
37 int r = 0;
38 struct alloc_header *ah;
39 foreach (ah, memory_list) {
40 fprintf(stderr, "%s%p:%lu @ %s:%d", r ? ", ": "", (char *)ah + L_D_S, (unsigned long)ah->size, ah->file, ah->line), r = 1;
41 if (ah->comment) fprintf(stderr, ":\"%s\"", ah->comment);
42 }
43 fprintf(stderr, "\n");
44 }
45 #endif
46 force_dump();
47 }
48 #endif
49 }
50
er(int b,char * m,va_list l)51 void er(int b, char *m, va_list l)
52 {
53 #ifdef HAVE_VPRINTF
54 vfprintf(stderr, m, l);
55 #else
56 fprintf(stderr, "%s", m);
57 #endif
58 if (b) fprintf(stderr, ANSI_BELL);
59 fprintf(stderr, "\n");
60 fflush(stderr);
61 sleep(1);
62 }
63
error(char * m,...)64 void error(char *m, ...)
65 {
66 va_list l;
67 va_start(l, m);
68 er(1, m, l);
69 va_end(l);
70 }
71
72 int errline;
73 unsigned char *errfile;
74
75 unsigned char errbuf[4096];
76
int_error(char * m,...)77 void int_error(char *m, ...)
78 {
79 va_list l;
80 va_start(l, m);
81 sprintf(errbuf, ANSI_SET_BOLD"INTERNAL ERROR"ANSI_CLEAR_BOLD" at %s:%d: ", errfile, errline);
82 strcat(errbuf, m);
83 er(1, errbuf, l);
84 force_dump();
85 va_end(l);
86 }
87
debug_msg(char * m,...)88 void debug_msg(char *m, ...)
89 {
90 va_list l;
91 va_start(l, m);
92 sprintf(errbuf, "DEBUG MESSAGE at %s:%d: ", errfile, errline);
93 strcat(errbuf, m);
94 er(0, errbuf, l);
95 va_end(l);
96 }
97
98 #ifdef LEAK_DEBUG
99
debug_mem_alloc(unsigned char * file,int line,size_t size)100 void *debug_mem_alloc(unsigned char *file, int line, size_t size)
101 {
102 void *p;
103 #ifdef LEAK_DEBUG
104 struct alloc_header *ah;
105 #endif
106 if (!size) return DUMMY;
107 if (size > MAXINT) overalloc();
108 #ifdef LEAK_DEBUG
109 mem_amount += size;
110 size += L_D_S;
111 #endif
112 if (!(p = malloc(size))) {
113 error("ERROR: out of memory (malloc returned NULL)");
114 fatal_tty_exit();
115 exit(RET_FATAL);
116 return NULL;
117 }
118 #ifdef LEAK_DEBUG
119 ah = p;
120 p = (char *)p + L_D_S;
121 ah->size = size - L_D_S;
122 #ifdef LEAK_DEBUG_LIST
123 ah->file = file;
124 ah->line = line;
125 ah->comment = NULL;
126 add_to_list(memory_list, ah);
127 #endif
128 #endif
129 return p;
130 }
131
debug_mem_free(unsigned char * file,int line,void * p)132 void debug_mem_free(unsigned char *file, int line, void *p)
133 {
134 #ifdef LEAK_DEBUG
135 struct alloc_header *ah;
136 #endif
137 if (p == DUMMY) return;
138 if (!p) {
139 errfile = file, errline = line, int_error("mem_free(NULL)");
140 return;
141 }
142 #ifdef LEAK_DEBUG
143 p = (char *)p - L_D_S;
144 ah = p;
145 #ifdef LEAK_DEBUG_LIST
146 del_from_list(ah);
147 if (ah->comment) free(ah->comment);
148 #endif
149 mem_amount -= ah->size;
150 #endif
151 free(p);
152 }
153
debug_mem_realloc(unsigned char * file,int line,void * p,size_t size)154 void *debug_mem_realloc(unsigned char *file, int line, void *p, size_t size)
155 {
156 #ifdef LEAK_DEBUG
157 struct alloc_header *ah;
158 #endif
159 if (p == DUMMY) return debug_mem_alloc(file, line, size);
160 if (!p) {
161 errfile = file, errline = line, int_error("mem_realloc(NULL, %lu)", (unsigned long)size);
162 return NULL;
163 }
164 if (!size) {
165 debug_mem_free(file, line, p);
166 return DUMMY;
167 }
168 if (size > MAXINT) overalloc();
169 if (!(p = realloc((char *)p - L_D_S, size + L_D_S))) {
170 error("ERROR: out of memory (realloc returned NULL)");
171 fatal_tty_exit();
172 exit(RET_FATAL);
173 return NULL;
174 }
175 #ifdef LEAK_DEBUG
176 ah = p;
177 mem_amount += size - ah->size;
178 ah->size = size;
179 #ifdef LEAK_DEBUG_LIST
180 ah->prev->next = ah;
181 ah->next->prev = ah;
182 #endif
183 #endif
184 return (char *)p + L_D_S;
185 }
186
set_mem_comment(void * p,unsigned char * c,int l)187 void set_mem_comment(void *p, unsigned char *c, int l)
188 {
189 #ifdef LEAK_DEBUG_LIST
190 struct alloc_header *ah = (struct alloc_header *)((char *)p - L_D_S);
191 if (ah->comment) free(ah->comment);
192 if ((ah->comment = malloc(l + 1))) memcpy(ah->comment, c, l), ah->comment[l] = 0;
193 #endif
194 }
195
196 #endif
197
198