1 /***************************************************************************
2 $RCSfile$
3 -------------------
4 cvs : $Id$
5 begin : Sun Dec 04 2004
6 copyright : (C) 2004 by Martin Preuss
7 email : martin@libchipcard.de
8
9 ***************************************************************************
10 * *
11 * This library is free software; you can redistribute it and/or *
12 * modify it under the terms of the GNU Lesser General Public *
13 * License as published by the Free Software Foundation; either *
14 * version 2.1 of the License, or (at your option) any later version. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * Lesser General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU Lesser General Public *
22 * License along with this library; if not, write to the Free Software *
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24 * MA 02111-1307 USA *
25 * *
26 ***************************************************************************/
27
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include "debug_p.h"
34
35 #include <stdarg.h>
36 #include <assert.h>
37 #include <stdio.h>
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41 #include <gwenhywfar/misc.h>
42
43
44
45 static GWEN_MEMORY_DEBUG_OBJECT *gwen_debug__memobjects=0;
46
47
48
GWEN_Debug_PrintDec(char * buffer,uint32_t size,uint32_t num,int leadingZero,uint32_t length)49 uint32_t GWEN_Debug_PrintDec(char *buffer,
50 uint32_t size,
51 uint32_t num,
52 int leadingZero,
53 uint32_t length)
54 {
55 uint32_t i;
56 uint32_t j;
57 uint32_t k;
58 char numbuf[16];
59 int numOr;
60
61 /* first convert number */
62 numOr=0;
63 i=0;
64 j=1000000000;
65
66 while (j) {
67 k=num/j;
68 numOr|=k;
69 if (numOr || leadingZero || j==1) {
70 numbuf[i]=k+'0';
71 i++;
72 }
73 num-=(k*j);
74 j/=10;
75 } /* while j */
76
77 j=0;
78 if (length) {
79 if (i>length)
80 i=length;
81
82 /* fill left up to length-(sizeof number) */
83 k=length-i;
84 while (k) {
85 if (j<size) {
86 if (leadingZero)
87 buffer[j]='0';
88 else
89 buffer[j]=' ';
90 }
91 j++;
92 k--;
93 } /* while k */
94 } /* if length */
95
96 /* copy number */
97 for (k=0; k<i; k++) {
98 if (j<size)
99 buffer[j]=numbuf[k];
100 j++;
101 } /* while i */
102
103 /* append trailing 0 */
104 if (j<size)
105 buffer[j]=0;
106 j++;
107 /* return length (or possible length) */
108 return j;
109 }
110
111
112
GWEN_Debug_PrintHex(char * buffer,uint32_t size,uint32_t num,int leadingZero,int up,uint32_t length)113 uint32_t GWEN_Debug_PrintHex(char *buffer,
114 uint32_t size,
115 uint32_t num,
116 int leadingZero,
117 int up,
118 uint32_t length)
119 {
120 uint32_t i;
121 uint32_t j;
122 uint32_t k;
123 char numbuf[16];
124 int numOr;
125
126 /* first convert number */
127 numOr=0;
128 i=0;
129 j=8;
130
131 while (j) {
132 k=(num>>((j-1)*4))&0xf;
133 numOr|=k;
134 if (numOr || leadingZero || j==1) {
135 if (k>9) {
136 if (up)
137 numbuf[i]=k+'0'+7;
138 else
139 numbuf[i]=k+'0'+7+32;
140 }
141 else
142 numbuf[i]=k+'0';
143 i++;
144 }
145 j--;
146 } /* while j */
147
148 j=0;
149 if (length) {
150 if (i>length)
151 i=length;
152
153 /* fill left up to length-(sizeof number) */
154 k=length-i;
155 while (k) {
156 if (j<size) {
157 if (leadingZero)
158 buffer[j]='0';
159 else
160 buffer[j]=' ';
161 }
162 j++;
163 k--;
164 } /* while k */
165 } /* if length */
166
167 /* copy number */
168 for (k=0; k<i; k++) {
169 if (j<size)
170 buffer[j]=numbuf[k];
171 j++;
172 } /* while i */
173
174 /* append trailing 0 */
175 if (j<size)
176 buffer[j]=0;
177 j++;
178 /* return length (or possible length) */
179 return j;
180 }
181
182
183
184
185
GWEN_Debug_Snprintf(char * buffer,uint32_t size,const char * fmt,...)186 uint32_t GWEN_Debug_Snprintf(char *buffer,
187 uint32_t size,
188 const char *fmt, ...)
189 {
190 va_list arguments;
191 uint32_t i;
192
193 i=0;
194 va_start(arguments, fmt);
195 while (*fmt) {
196 if (*fmt=='%') {
197 fmt++;
198 if (*fmt=='%') {
199 /* write character '%' */
200 if (i<size)
201 buffer[i]='%';
202 i++;
203 }
204 else {
205 uint32_t length;
206 int leadingZero;
207
208 leadingZero=0;
209 length=0;
210
211 /* read length */
212 if ((*fmt)>='0' && (*fmt)<='9') {
213 /* read number */
214 if (*fmt=='0') {
215 leadingZero=1;
216 }
217 while ((*fmt)>='0' && (*fmt)<='9') {
218 length*=10;
219 length+=*fmt-'0';
220 fmt++;
221 } /* while */
222 }
223
224 /* read type */
225 switch (*fmt) {
226 /* decimal integer */
227 case 'c':
228 case 'd': {
229 int p;
230
231 p=va_arg(arguments, int);
232 if (p<0) {
233 if (i<size)
234 buffer[i]='-';
235 i++;
236 p=-p;
237 }
238 i+=GWEN_Debug_PrintDec(buffer+i,
239 size-i,
240 p,
241 leadingZero,
242 length)-1;
243 break;
244 }
245
246 /* hexadecimal integer */
247 case 'x': {
248 unsigned int p;
249
250 p=va_arg(arguments, unsigned int);
251 i+=GWEN_Debug_PrintHex(buffer+i,
252 size-i,
253 p,
254 leadingZero,
255 0,
256 length)-1;
257 break;
258 }
259
260 /* hexadecimal integer */
261 case 'X': {
262 unsigned int p;
263
264 p=va_arg(arguments, unsigned int);
265 i+=GWEN_Debug_PrintHex(buffer+i,
266 size-i,
267 p,
268 leadingZero,
269 1,
270 length)-1;
271 break;
272 }
273
274 case 's': {
275 const char *p;
276
277 p=va_arg(arguments, const char *);
278 if (!p)
279 p="(null)";
280 while (*p) {
281 if (i<size)
282 buffer[i]=*p;
283 i++;
284 p++;
285 } /* while */
286 break;
287 }
288
289 default:
290 break;
291 } /* switch */
292 }
293 }
294 else {
295 if (i<size)
296 buffer[i]=*fmt;
297 i++;
298 }
299 fmt++;
300 } /* while */
301
302 /* add trailing 0 */
303 if (i<size)
304 buffer[i]=0;
305 i++;
306 va_end(arguments);
307 return i;
308 }
309
310
311
312
313 #ifdef NO_VARIADIC_MACROS
DBG_ERROR(const char * dbg_logger,const char * format,...)314 void DBG_ERROR(const char *dbg_logger, const char *format, ...)
315 {
316 va_list args;
317 char dbg_buffer[256];
318 va_start(args, format);
319 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
320 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
321 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelError, dbg_buffer);
322 va_end(args);
323 }
324
DBG_WARN(const char * dbg_logger,const char * format,...)325 void DBG_WARN(const char *dbg_logger, const char *format, ...)
326 {
327 va_list args;
328 char dbg_buffer[256];
329 va_start(args, format);
330 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
331 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
332 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelWarning, dbg_buffer);
333 va_end(args);
334 }
335
DBG_NOTICE(const char * dbg_logger,const char * format,...)336 void DBG_NOTICE(const char *dbg_logger, const char *format, ...)
337 {
338 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelNotice) {
339 va_list args;
340 char dbg_buffer[256];
341 va_start(args, format);
342 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
343 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
344 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelNotice, dbg_buffer);
345 va_end(args);
346 }
347 }
348
DBG_INFO(const char * dbg_logger,const char * format,...)349 void DBG_INFO(const char *dbg_logger, const char *format, ...)
350 {
351 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelInfo) {
352 va_list args;
353 char dbg_buffer[256];
354 va_start(args, format);
355 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
356 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
357 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelInfo, dbg_buffer);
358 va_end(args);
359 }
360 }
361
DBG_DEBUG(const char * dbg_logger,const char * format,...)362 void DBG_DEBUG(const char *dbg_logger, const char *format, ...)
363 {
364 # ifndef DISABLE_DEBUGLOG
365 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelDebug) {
366 va_list args;
367 char dbg_buffer[256];
368 va_start(args, format);
369 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
370 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
371 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelDebug, dbg_buffer);
372 va_end(args);
373 }
374 # endif /* DISABLE_DEBUGLOG */
375 }
376
DBG_VERBOUS(const char * dbg_logger,const char * format,...)377 void DBG_VERBOUS(const char *dbg_logger, const char *format, ...)
378 {
379 # ifndef DISABLE_DEBUGLOG
380 if (GWEN_Logger_GetLevel(dbg_logger)>=GWEN_LoggerLevelVerbous) {
381 va_list args;
382 char dbg_buffer[256];
383 va_start(args, format);
384 vsnprintf(dbg_buffer, sizeof(dbg_buffer)-1, format, args);
385 dbg_buffer[sizeof(dbg_buffer)-1] = 0;
386 GWEN_Logger_Log(dbg_logger, GWEN_LoggerLevelVerbous, dbg_buffer);
387 va_end(args);
388 }
389 # endif /* DISABLE_DEBUGLOG */
390 }
391
392 #endif /* NO_VARIADIC_MACROS */
393
394
395
396
397
398
399
GWEN_MemoryDebugEntry_new(GWEN_MEMORY_DEBUG_ENTRY_TYPE t,const char * wFile,int wLine)400 GWEN_MEMORY_DEBUG_ENTRY *GWEN_MemoryDebugEntry_new(GWEN_MEMORY_DEBUG_ENTRY_TYPE t,
401 const char *wFile,
402 int wLine)
403 {
404 GWEN_MEMORY_DEBUG_ENTRY *e;
405
406 assert(wFile);
407 assert(wLine);
408 GWEN_NEW_OBJECT(GWEN_MEMORY_DEBUG_ENTRY, e);
409 e->file=strdup(wFile);
410 e->line=wLine;
411 e->type=t;
412 return e;
413 }
414
415
416
GWEN_MemoryDebugEntry_free(GWEN_MEMORY_DEBUG_ENTRY * e)417 void GWEN_MemoryDebugEntry_free(GWEN_MEMORY_DEBUG_ENTRY *e)
418 {
419 if (e) {
420 free(e->file);
421 GWEN_FREE_OBJECT(e);
422 }
423 }
424
425
426
427
GWEN_MemoryDebugObject_new(const char * name)428 GWEN_MEMORY_DEBUG_OBJECT *GWEN_MemoryDebugObject_new(const char *name)
429 {
430 GWEN_MEMORY_DEBUG_OBJECT *o;
431
432 assert(name);
433 GWEN_NEW_OBJECT(GWEN_MEMORY_DEBUG_OBJECT, o);
434 o->name=strdup(name);
435 return o;
436 }
437
438
439
GWEN_MemoryDebugObject_free(GWEN_MEMORY_DEBUG_OBJECT * o)440 void GWEN_MemoryDebugObject_free(GWEN_MEMORY_DEBUG_OBJECT *o)
441 {
442 if (o) {
443 GWEN_MEMORY_DEBUG_ENTRY *e;
444
445 e=o->entries;
446 while (e) {
447 GWEN_MEMORY_DEBUG_ENTRY *next;
448
449 next=e->next;
450 GWEN_MemoryDebugEntry_free(e);
451 e=next;
452 }
453 free(o->name);
454 GWEN_FREE_OBJECT(o);
455 }
456 }
457
458
459
GWEN_MemoryDebug__FindObject(const char * name)460 GWEN_MEMORY_DEBUG_OBJECT *GWEN_MemoryDebug__FindObject(const char *name)
461 {
462 GWEN_MEMORY_DEBUG_OBJECT *o;
463
464 o=gwen_debug__memobjects;
465 while (o) {
466 assert(o->name);
467 if (strcasecmp(o->name, name)==0)
468 break;
469 if (o->next==o) {
470 DBG_ERROR(GWEN_LOGDOMAIN, "What ?? Pointing to myself ??");
471 abort();
472 }
473 o=o->next;
474 }
475
476 return o;
477 }
478
479
480
GWEN_MemoryDebug_Increment(const char * name,const char * wFile,int wLine,int attach)481 void GWEN_MemoryDebug_Increment(const char *name,
482 const char *wFile,
483 int wLine,
484 int attach)
485 {
486 GWEN_MEMORY_DEBUG_OBJECT *o;
487 GWEN_MEMORY_DEBUG_ENTRY *e;
488
489 assert(name);
490 assert(wFile);
491 assert(wLine);
492 o=GWEN_MemoryDebug__FindObject(name);
493 if (!o) {
494 o=GWEN_MemoryDebugObject_new(name);
495 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_OBJECT, o, &gwen_debug__memobjects);
496 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
497 GWEN_MemoryDebugEntryTypeCreate,
498 wFile, wLine);
499 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
500 o->count++;
501 }
502 else {
503 e=GWEN_MemoryDebugEntry_new(attach?GWEN_MemoryDebugEntryTypeAttach:
504 GWEN_MemoryDebugEntryTypeCreate,
505 wFile, wLine);
506 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
507 o->count++;
508 }
509 }
510
511
512
GWEN_MemoryDebug_Decrement(const char * name,const char * wFile,int wLine)513 void GWEN_MemoryDebug_Decrement(const char *name,
514 const char *wFile,
515 int wLine)
516 {
517 GWEN_MEMORY_DEBUG_OBJECT *o;
518 GWEN_MEMORY_DEBUG_ENTRY *e;
519
520 assert(name);
521 assert(wFile);
522 assert(wLine);
523 o=GWEN_MemoryDebug__FindObject(name);
524 if (!o) {
525 DBG_ERROR(GWEN_LOGDOMAIN,
526 "Object to be freed not found (%s at %s:%d)",
527 name, wFile, wLine);
528 o=GWEN_MemoryDebugObject_new(name);
529 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_OBJECT, o, &gwen_debug__memobjects);
530 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
531 wFile, wLine);
532 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
533 o->count--;
534 }
535 else {
536 e=GWEN_MemoryDebugEntry_new(GWEN_MemoryDebugEntryTypeFree,
537 wFile, wLine);
538 GWEN_LIST_ADD(GWEN_MEMORY_DEBUG_ENTRY, e, &(o->entries));
539 o->count--;
540 }
541 }
542
543
544
GWEN_MemoryDebug__DumpObject(GWEN_MEMORY_DEBUG_OBJECT * o,uint32_t mode)545 void GWEN_MemoryDebug__DumpObject(GWEN_MEMORY_DEBUG_OBJECT *o,
546 uint32_t mode)
547 {
548
549 DBG_ERROR(0, "Object \"%s\" (count=%ld)",
550 o->name, o->count);
551 if (o->count!=0 || mode==GWEN_MEMORY_DEBUG_MODE_DETAILED) {
552 GWEN_MEMORY_DEBUG_ENTRY *e;
553
554 if (mode!=GWEN_MEMORY_DEBUG_MODE_SHORT) {
555 e=o->entries;
556 while (e) {
557 const char *s;
558
559 fprintf(stderr, " ");
560 switch (e->type) {
561 case GWEN_MemoryDebugEntryTypeCreate:
562 s="created";
563 break;
564 case GWEN_MemoryDebugEntryTypeAttach:
565 s="attached";
566 break;
567 case GWEN_MemoryDebugEntryTypeFree:
568 s="freed";
569 break;
570 case GWEN_MemoryDebugEntryTypeUnknown:
571 default:
572 s="<unknown action>";
573 break;
574 }
575 DBG_ERROR(0, " %s at %s:%d", s, e->file, e->line);
576 e=e->next;
577 } /* while e */
578 }
579 }
580 }
581
582
583
GWEN_MemoryDebug_DumpObject(const char * name,uint32_t mode)584 void GWEN_MemoryDebug_DumpObject(const char *name,
585 uint32_t mode)
586 {
587 GWEN_MEMORY_DEBUG_OBJECT *o;
588
589 assert(name);
590 o=GWEN_MemoryDebug__FindObject(name);
591 if (!o) {
592 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
593 }
594 else
595 GWEN_MemoryDebug__DumpObject(o, mode);
596 }
597
598
599
GWEN_MemoryDebug_GetObjectCount(const char * name)600 long int GWEN_MemoryDebug_GetObjectCount(const char *name)
601 {
602 GWEN_MEMORY_DEBUG_OBJECT *o;
603
604 assert(name);
605 o=GWEN_MemoryDebug__FindObject(name);
606 if (!o) {
607 DBG_ERROR(GWEN_LOGDOMAIN, "Object \"%s\" not found", name);
608 return 0;
609 }
610 else
611 return o->count;
612 }
613
614
615
GWEN_MemoryDebug_Dump(uint32_t mode)616 void GWEN_MemoryDebug_Dump(uint32_t mode)
617 {
618 GWEN_MEMORY_DEBUG_OBJECT *o;
619
620 DBG_ERROR(0, "Gwenhywfar Memory Debugger Statistics:");
621 DBG_ERROR(0, "====================================== begin\n");
622 o=gwen_debug__memobjects;
623 while (o) {
624 GWEN_MemoryDebug__DumpObject(o, mode);
625 o=o->next;
626 }
627 DBG_ERROR(0, "====================================== end\n");
628 }
629
630
631
GWEN_MemoryDebug_CleanUp(void)632 void GWEN_MemoryDebug_CleanUp(void)
633 {
634 GWEN_MEMORY_DEBUG_OBJECT *o;
635
636 o=gwen_debug__memobjects;
637 while (o) {
638 GWEN_MEMORY_DEBUG_OBJECT *next;
639
640 next=o->next;
641 GWEN_MemoryDebugObject_free(o);
642 o=next;
643 }
644 gwen_debug__memobjects=0;
645 }
646
647
648
649
650