1 
2 /***************************************************************************
3  *                    __            __ _ ___________                       *
4  *                    \ \          / /| |____   ____|                      *
5  *                     \ \        / / | |    | |                           *
6  *                      \ \  /\  / /  | |    | |                           *
7  *                       \ \/  \/ /   | |    | |                           *
8  *                        \  /\  /    | |    | |                           *
9  *                         \/  \/     |_|    |_|                           *
10  *                                                                         *
11  *                           Wiimms ISO Tools                              *
12  *                         http://wit.wiimm.de/                            *
13  *                                                                         *
14  ***************************************************************************
15  *                                                                         *
16  *   This file is part of the WIT project.                                 *
17  *   Visit http://wit.wiimm.de/ for project details and sources.           *
18  *                                                                         *
19  *   Copyright (c) 2009-2013 by Dirk Clemens <wiimm@wiimm.de>              *
20  *                                                                         *
21  ***************************************************************************
22  *                                                                         *
23  *   This program is free software; you can redistribute it and/or modify  *
24  *   it under the terms of the GNU General Public License as published by  *
25  *   the Free Software Foundation; either version 2 of the License, or     *
26  *   (at your option) any later version.                                   *
27  *                                                                         *
28  *   This program is distributed in the hope that it will be useful,       *
29  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
30  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
31  *   GNU General Public License for more details.                          *
32  *                                                                         *
33  *   See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt       *
34  *                                                                         *
35  ***************************************************************************/
36 
37 #define WIIMM_DEBUG_C 1
38 #include "debug.h"
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stdarg.h>
43 
44 #include "lib-std.h"
45 
46 //
47 ///////////////////////////////////////////////////////////////////////////////
48 ///////////////			 trace functions		///////////////
49 ///////////////////////////////////////////////////////////////////////////////
50 
51 FILE * TRACE_FILE = 0;
52 
53 unsigned GetTimerMSec();
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 
trace_helper(int print_stderr,ccp format,va_list arg)57 static void trace_helper ( int print_stderr, ccp  format, va_list arg )
58 {
59     if (!TRACE_FILE)
60     {
61 	TRACE_FILE = fopen("_trace.tmp","wb");
62 	if (!TRACE_FILE)
63 	    TRACE_FILE = stderr;
64     }
65 
66     unsigned msec = GetTimerMSec();
67 
68     if ( print_stderr || TRACE_FILE == stderr )
69     {
70 	fflush(stdout);
71 	fprintf(stderr,"%4d.%03d  ",msec/1000,msec%1000);
72 	va_list arg2;
73 	va_copy(arg2,arg);
74 	vfprintf(stderr,format,arg2);
75 	va_end(arg2);
76 	fflush(stderr);
77     }
78 
79     if ( TRACE_FILE != stderr )
80     {
81 	fprintf(TRACE_FILE,"%4d.%03d  ",msec/1000,msec%1000);
82 	vfprintf(TRACE_FILE,format,arg);
83 	fflush(TRACE_FILE);
84     }
85 }
86 
87 ///////////////////////////////////////////////////////////////////////////////
88 
89 #undef TRACE_ARG_FUNC
90 
TRACE_ARG_FUNC(ccp format,va_list arg)91 void TRACE_ARG_FUNC ( ccp format, va_list arg )
92 {
93     trace_helper(0,format,arg);
94 }
95 
96 ///////////////////////////////////////////////////////////////////////////////
97 
98 #undef TRACE_FUNC
99 
TRACE_FUNC(ccp format,...)100 void TRACE_FUNC ( ccp format, ... )
101 {
102     va_list arg;
103     va_start(arg,format);
104     trace_helper(0,format,arg);
105     va_end(arg);
106 }
107 
108 ///////////////////////////////////////////////////////////////////////////////
109 
110 #undef PRINT_ARG_FUNC
111 
PRINT_ARG_FUNC(ccp format,va_list arg)112 void PRINT_ARG_FUNC ( ccp format, va_list arg )
113 {
114     trace_helper(1,format,arg);
115 }
116 
117 ///////////////////////////////////////////////////////////////////////////////
118 
119 #undef PRINT_FUNC
120 
PRINT_FUNC(ccp format,...)121 void PRINT_FUNC ( ccp format, ... )
122 {
123     va_list arg;
124     va_start(arg,format);
125     trace_helper(1,format,arg);
126     va_end(arg);
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 
131 #undef WAIT_ARG_FUNC
132 
WAIT_ARG_FUNC(ccp format,va_list arg)133 void WAIT_ARG_FUNC ( ccp format, va_list arg )
134 {
135     if ( format && *format )
136 	trace_helper(1,format,arg);
137     PRINT_FUNC(">>>>>> PRESS RETURN: ");
138     getchar();
139 }
140 
141 ///////////////////////////////////////////////////////////////////////////////
142 
143 #undef WAIT_FUNC
144 
WAIT_FUNC(ccp format,...)145 void WAIT_FUNC ( ccp format, ... )
146 {
147     va_list arg;
148     va_start(arg,format);
149     WAIT_ARG_FUNC(format,arg);
150     va_end(arg);
151 }
152 
153 //
154 ///////////////////////////////////////////////////////////////////////////////
155 ///////////////			alloc/free system		///////////////
156 ///////////////////////////////////////////////////////////////////////////////
157 
158 #if TRACE_ALLOC_MODE > 2
159     #define MEM_FILLER_SIZE 8
160     static u8 mem_filler[MEM_FILLER_SIZE];
161 #else
162     #define MEM_FILLER_SIZE 0
163 #endif
164 
165 #if TRACE_ALLOC_MODE > 1
166     #define MPARAM ccp func, ccp file, uint line,
167     #define MCALL  func,file,line,
168     #define PRINT_OOM(...) \
169 	PrintError(func,file,line,0,ERR_OUT_OF_MEMORY,__VA_ARGS__)
170 #else
171     #define MPARAM
172     #define MCALL
173     #define PRINT_OOM(...) \
174 	PrintError(__FUNCTION__,__FILE__,__LINE__,0,ERR_OUT_OF_MEMORY,__VA_ARGS__)
175 #endif
176 
177 ///////////////////////////////////////////////////////////////////////////////
178 
my_free(void * ptr)179 void my_free ( void * ptr )
180 {
181     free(ptr);
182 }
183 
184 ///////////////////////////////////////////////////////////////////////////////
185 ///////////////////////////////////////////////////////////////////////////////
186 
my_calloc(MPARAM size_t nmemb,size_t size)187 void * my_calloc ( MPARAM size_t nmemb, size_t size )
188 {
189     void * res = calloc(nmemb,size);
190     if (!res)
191 	PRINT_OOM("Out of memory while calloc() %zu bytes (%zu*%zu=0x%zx)\n",
192 		nmemb*size, nmemb, size, nmemb*size );
193     return res;
194 }
195 
196 ///////////////////////////////////////////////////////////////////////////////
197 
my_malloc(MPARAM size_t size)198 void * my_malloc ( MPARAM size_t size )
199 {
200     void * res = malloc(size);
201     if (!res)
202 	PRINT_OOM("Out of memory while malloc() %zu bytes (0x%zx)\n",
203 		size, size );
204     return res;
205 }
206 
207 ///////////////////////////////////////////////////////////////////////////////
208 
my_realloc(MPARAM void * ptr,size_t size)209 void * my_realloc ( MPARAM void * ptr, size_t size )
210 {
211     void * res = realloc(ptr,size);
212     if (!res)
213 	PRINT_OOM("Out of memory while realloc() %zu bytes (0x%zx)\n",
214 		size, size );
215     return res;
216 }
217 
218 ///////////////////////////////////////////////////////////////////////////////
219 ///////////////////////////////////////////////////////////////////////////////
220 
my_strdup(MPARAM ccp src)221 char * my_strdup  ( MPARAM ccp src )
222 {
223     char * res = strdup(src);
224     if (!res)
225     {
226 	const uint size = src ? strlen(src)+1 : 0;
227 	PRINT_OOM("Out of memory while strdup() %u bytes (0x%x)\n",
228 		size, size );
229     }
230     return res;
231 }
232 
233 ///////////////////////////////////////////////////////////////////////////////
234 
my_strdup2(MPARAM ccp src1,ccp src2)235 char * my_strdup2 ( MPARAM ccp src1, ccp src2 )
236 {
237     const uint len1 = src1 ? strlen(src1) : 0;
238     const uint len2 = src2 ? strlen(src2) : 0;
239     char * res = my_malloc( MCALL len1+len2+1 );
240     if (len1)
241 	memcpy(res,src1,len1);
242     if (len2)
243 	memcpy(res+len1,src2,len2);
244     res[len1+len2] = 0;
245     return res;
246 }
247 
248 ///////////////////////////////////////////////////////////////////////////////
249 
my_strdup3(MPARAM ccp src1,ccp src2,ccp src3)250 char * my_strdup3 ( MPARAM ccp src1, ccp src2, ccp src3 )
251 {
252     const uint len1 = src1 ? strlen(src1) : 0;
253     const uint len2 = src2 ? strlen(src2) : 0;
254     const uint len3 = src3 ? strlen(src3) : 0;
255     char * res = my_malloc( MCALL len1+len2+len3+1 );
256     char * dest = res;
257     if (len1)
258     {
259 	memcpy(dest,src1,len1);
260 	dest += len1;
261     }
262     if (len2)
263     {
264 	memcpy(dest,src2,len2);
265 	dest += len2;
266     }
267     if (len3)
268     {
269 	memcpy(dest,src3,len3);
270 	dest += len3;
271     }
272     *dest = 0;
273     return res;
274 }
275 
276 ///////////////////////////////////////////////////////////////////////////////
277 
my_memdup(MPARAM const void * src,size_t copylen)278 void * my_memdup ( MPARAM const void * src, size_t copylen )
279 {
280     char * dest = my_malloc( MCALL copylen+1);
281     memcpy(dest,src,copylen);
282     dest[copylen] = 0;
283     return dest;
284 }
285 
286 //
287 ///////////////////////////////////////////////////////////////////////////////
288 ///////////////////////////////////////////////////////////////////////////////
289 #if TRACE_ALLOC_MODE > 2
290 ///////////////////////////////////////////////////////////////////////////////
291 
292 typedef struct mem_info_t
293 {
294     ccp		func;
295     ccp		file;
296     uint	line;
297     u8		* data;
298     uint	size;
299     uint	seqnum;
300 
301 } mem_info_t;
302 
303 //-----------------------------------------------------------------------------
304 
305 static mem_info_t * mem_list = 0;
306 static uint  mem_used	= 0;
307 static uint  mem_size	= 0;
308 static FILE *mem_log	= 0;
309 static uint  mem_seqnum	= 0;
310 
311 ///////////////////////////////////////////////////////////////////////////////
312 
OpenMemLog()313 static FILE * OpenMemLog()
314 {
315     static bool done = false;
316     if (!done)
317     {
318 	done = true;
319 	mem_log = fopen("_alloc-err-log.tmp","wb");
320     }
321     return mem_log;
322 }
323 
324 ///////////////////////////////////////////////////////////////////////////////
325 
MemLog(ccp func,ccp file,uint line,ccp info,u8 * ptr,bool no_stderr)326 static void MemLog
327     ( ccp func, ccp file, uint line, ccp info, u8 * ptr, bool no_stderr )
328 {
329     if (!no_stderr)
330     {
331 	fprintf(stderr,"MEM-ERR[%s,%p] %s() @ %s#%u\n",
332 		info, ptr, func, file, line );
333 	fflush(stderr);
334     }
335 
336     if (OpenMemLog())
337     {
338 	fprintf(mem_log,"[%s,%p] %s() @ %s#%u\n",
339 		info, ptr, func, file, line );
340 	fflush(mem_log);
341     }
342 }
343 
344 ///////////////////////////////////////////////////////////////////////////////
345 
MemLogItem(ccp func,ccp file,uint line,ccp info,const mem_info_t * mi)346 static void MemLogItem ( ccp func, ccp file, uint line, ccp info, const mem_info_t * mi )
347 {
348     if (func)
349 	fprintf(stderr,"MEM-ERR[%s] %s() @ %s#%u\n",
350 		info, func, file, line );
351     fprintf(stderr,"MEM-ERR[%s,%u] %s() @ %s#%u\n",
352 		info, mi->seqnum, mi->func, mi->file, mi->line );
353     fflush(stderr);
354 
355     if (OpenMemLog())
356     {
357 	if (func)
358 	    fprintf(mem_log,"[%s] %s() @ %s#%u\n",
359 		    info, func, file, line );
360 	fprintf(mem_log,"[%s,%u] %s() @ %s#%u\n",
361 		    info, mi->seqnum, mi->func, mi->file, mi->line );
362 	HexDump16( mem_log, 10, 0, mi->data - MEM_FILLER_SIZE, 2*MEM_FILLER_SIZE );
363 	HexDump16( mem_log, 10, mi->size + MEM_FILLER_SIZE,
364 			mi->data + mi->size - MEM_FILLER_SIZE, 2 * MEM_FILLER_SIZE );
365 	fputc('\n',mem_log);
366 	fflush(mem_log);
367     }
368 }
369 
370 ///////////////////////////////////////////////////////////////////////////////
371 
FindMemInfoHelper(u8 * data,uint size)372 uint FindMemInfoHelper ( u8 * data, uint size )
373 {
374     int beg = 0;
375     int end = mem_used - 1;
376     while ( beg <= end )
377     {
378 	uint idx = (beg+end)/2;
379 	mem_info_t * mi = mem_list + idx;
380 	if ( data < mi->data )
381 	    end = idx - 1 ;
382 	else if ( data > mi->data )
383 	    beg = idx + 1;
384 	else if ( size < mi->size )
385 	    end = idx - 1 ;
386 	else if ( size > mi->size )
387 	    beg = idx + 1;
388 	else
389 	{
390 	    noTRACE("FindMemMapHelper(%llx,%llx) FOUND=%d/%d/%d\n",
391 		    (u64)off, (u64)size, idx, mem_used, mem_size );
392 	    return idx;
393 	}
394     }
395 
396     noTRACE("FindStringFieldHelper(%llx,%llx) failed=%d/%d/%d\n",
397 		(u64)off, (u64)size, beg, mem_used, mem_size );
398     return beg;
399 }
400 
401 ///////////////////////////////////////////////////////////////////////////////
402 ///////////////////////////////////////////////////////////////////////////////
403 
InitializeTraceAlloc()404 void InitializeTraceAlloc()
405 {
406     static bool done = false;
407     if (done)
408 	return;
409     done = true;
410 
411     OpenMemLog();
412 
413     memset(mem_filler,0xdc,sizeof(mem_filler));
414     mem_filler[MEM_FILLER_SIZE/2] = 0xcd;
415     mem_filler[MEM_FILLER_SIZE/3] = 0xcd;
416 }
417 
418 ///////////////////////////////////////////////////////////////////////////////
419 
CheckTraceAlloc(ccp func,ccp file,uint line)420 int CheckTraceAlloc ( ccp func, ccp file, uint line )
421 {
422     int count = 0;
423 
424     mem_info_t *ptr, *end = mem_list + mem_used;
425     for ( ptr = mem_list; ptr < end; ptr++ )
426     {
427 	if (memcmp(ptr->data-MEM_FILLER_SIZE,mem_filler,sizeof(mem_filler)))
428 	{
429 	    MemLogItem(0,0,0,"BEG",ptr);
430 	    memcpy(ptr->data-MEM_FILLER_SIZE,mem_filler,sizeof(mem_filler));
431 	    count++;
432 	}
433 
434 	if (memcmp(ptr->data+ptr->size,mem_filler,sizeof(mem_filler)))
435 	{
436 	    MemLogItem(0,0,0,"END",ptr);
437 	    memcpy(ptr->data+ptr->size,mem_filler,sizeof(mem_filler));
438 	    count++;
439 	}
440     }
441 
442     if (count)
443     {
444 	fprintf(stderr,"MEM-ERR: %u errors found -> %s() @ %s#%u\n",
445 		count, func, file, line );
446 	fflush(stderr);
447 
448 	if (OpenMemLog())
449 	{
450 	    fprintf(mem_log,"--- %u errors found -> %s() @ %s#%u\n\n",
451 		count, func, file, line );
452 	    fflush(mem_log);
453 	}
454     }
455     return count;
456 }
457 
458 ///////////////////////////////////////////////////////////////////////////////
459 
DumpTraceAlloc(ccp func,ccp file,uint line,FILE * f)460 void DumpTraceAlloc ( ccp func, ccp file, uint line, FILE * f )
461 {
462     CheckTraceAlloc(func,file,line);
463 
464     if (!f)
465 	return;
466 
467     fprintf(f,"---- MEM-DUMP [N=%u] -----\n",mem_used);
468     mem_info_t *ptr, *end = mem_list + mem_used;
469     for ( ptr = mem_list; ptr < end; ptr++ )
470     {
471 	ccp file = strrchr(ptr->file,'/');
472 	file = file ? file+1 : ptr->file;
473 	fprintf(f,"%5u %p %5u %-20.20s %5u %-.25s\n",
474 		ptr->seqnum, ptr->data, ptr->size,
475 		ptr->func, ptr->line, file );
476     }
477     fflush(stderr);
478 }
479 
480 ///////////////////////////////////////////////////////////////////////////////
481 
RegisterAlloc(ccp func,ccp file,uint line,u8 * data,uint size)482 static mem_info_t * RegisterAlloc
483 	( ccp func, ccp file, uint line, u8 * data, uint size )
484 {
485     if (!mem_seqnum)
486 	InitializeTraceAlloc();
487 
488     memcpy(data-MEM_FILLER_SIZE,mem_filler,MEM_FILLER_SIZE);
489     memcpy(data+size,mem_filler,MEM_FILLER_SIZE);
490 
491     uint idx = FindMemInfoHelper(data,size);
492 
493     ASSERT( mem_used <= mem_size );
494     if ( mem_used == mem_size )
495     {
496 	mem_size += 1000 + mem_size/2;
497 	const uint alloc_size = mem_size * sizeof(*mem_list);
498 	mem_list = realloc(mem_list,alloc_size);
499 	if (!mem_list)
500 	    PRINT_OOM("Out of memory while RegisterAlloc() %u bytes (0x%x)\n",
501 		alloc_size, alloc_size );
502     }
503 
504     DASSERT( idx <= mem_used );
505     mem_info_t * mi = mem_list + idx;
506     memmove(mi+1,mi,(mem_used-idx)*sizeof(*mi));
507     mem_used++;
508 
509     mi->func	= func;
510     mi->file	= file;
511     mi->line	= line;
512     mi->data	= data;
513     mi->size	= size;
514     mi->seqnum	= mem_seqnum++;
515 
516  #if TRACE_ALLOC_MODE > 3
517     MemLog(func,file,line,"ALLOCED",data,true);
518  #endif
519     return mi;
520 }
521 
522 //
523 ///////////////////////////////////////////////////////////////////////////////
524 #endif // TRACE_ALLOC_MODE > 2
525 ///////////////////////////////////////////////////////////////////////////////
526 ///////////////////////////////////////////////////////////////////////////////
527 
UnregisterAlloc(ccp func,ccp file,uint line,u8 * data)528 static void * UnregisterAlloc ( ccp func, ccp file, uint line, u8 * data )
529 {
530  #if TRACE_ALLOC_MODE > 2
531     if (!data)
532 	return 0;
533 
534     int beg = 0;
535     int end = mem_used - 1;
536     while ( beg <= end )
537     {
538 	uint idx = (beg+end)/2;
539 	mem_info_t * mi = mem_list + idx;
540 	if ( data < mi->data )
541 	    end = idx - 1 ;
542 	else if ( data > mi->data )
543 	    beg = idx + 1;
544 	else
545 	{
546 	 #if TRACE_ALLOC_MODE > 3
547 	    MemLog(func,file,line,"FREE",data,true);
548 	 #endif
549 
550 	    if (memcmp(data-MEM_FILLER_SIZE,mem_filler,sizeof(mem_filler)))
551 		MemLogItem(func,file,line,"BEG",mi);
552 
553 	    if (memcmp(data+mi->size,mem_filler,sizeof(mem_filler)))
554 		MemLogItem(func,file,line,"END",mi);
555 
556 	    memmove(mi,mi+1,(--mem_used-idx)*sizeof(*mi));
557 	    return data - MEM_FILLER_SIZE;
558 	}
559     }
560     MemLog(func,file,line,"NOT FOUND",data,false);
561  #endif
562     return data;
563 }
564 
565 ///////////////////////////////////////////////////////////////////////////////
566 
trace_free(ccp func,ccp file,uint line,void * ptr)567 void trace_free ( ccp func, ccp file, uint line, void * ptr )
568 {
569     free(UnregisterAlloc(func,file,line,ptr));
570 }
571 
572 ///////////////////////////////////////////////////////////////////////////////
573 
trace_malloc(ccp func,ccp file,uint line,size_t size)574 void * trace_malloc  ( ccp func, ccp file, uint line, size_t size )
575 {
576     u8 * res = malloc( size + 2 * MEM_FILLER_SIZE );
577     if (!res)
578 	PRINT_OOM("Out of memory while allocate %zu+%u bytes (0x%zx)\n",
579 		size, 2 * MEM_FILLER_SIZE, size + 2 * MEM_FILLER_SIZE );
580 
581     res += MEM_FILLER_SIZE;
582  #if TRACE_ALLOC_MODE > 2
583     RegisterAlloc(func,file,line,res,size);
584  #endif
585     return res;
586 }
587 
588 ///////////////////////////////////////////////////////////////////////////////
589 
trace_calloc(ccp func,ccp file,uint line,size_t nmemb,size_t size)590 void * trace_calloc  ( ccp func, ccp file, uint line, size_t nmemb, size_t size )
591 {
592     uint total_size = nmemb * size;
593     void * res = trace_malloc(func,file,line,total_size);
594     memset(res,0,total_size);
595     return res;
596 }
597 
598 ///////////////////////////////////////////////////////////////////////////////
599 
trace_realloc(ccp func,ccp file,uint line,void * ptr,size_t size)600 void * trace_realloc ( ccp func, ccp file, uint line, void *ptr, size_t size )
601 {
602     ptr = UnregisterAlloc(func,file,line,ptr);
603     u8 * res = realloc( ptr, size + 2 * MEM_FILLER_SIZE );
604     if (!res)
605 	PRINT_OOM("Out of memory while re allocate %zu+%u bytes (0x%zx)\n",
606 		size, 2 * MEM_FILLER_SIZE, size + 2 * MEM_FILLER_SIZE );
607 
608     res += MEM_FILLER_SIZE;
609  #if TRACE_ALLOC_MODE > 2
610     RegisterAlloc(func,file,line,res,size);
611  #endif
612     return res;
613 }
614 
615 ///////////////////////////////////////////////////////////////////////////////
616 
trace_strdup(ccp func,ccp file,uint line,ccp src)617 char * trace_strdup ( ccp func, ccp file, uint line, ccp src )
618 {
619     const uint len = src ? strlen(src)+1 : 0;
620     char * res = trace_malloc(func,file,line,len);
621     memcpy(res,src,len);
622     return res;
623 }
624 
625 ///////////////////////////////////////////////////////////////////////////////
626 
trace_strdup2(ccp func,ccp file,uint line,ccp src1,ccp src2)627 char * trace_strdup2 ( ccp func, ccp file, uint line, ccp src1, ccp src2 )
628 {
629     const uint len1 = src1 ? strlen(src1) : 0;
630     const uint len2 = src2 ? strlen(src2) : 0;
631     char * res = trace_malloc(func,file,line,len1+len2+1);
632     if (len1)
633 	memcpy(res,src1,len1);
634     if (len2)
635 	memcpy(res+len1,src2,len2);
636     res[len1+len2] = 0;
637     return res;
638 }
639 
640 ///////////////////////////////////////////////////////////////////////////////
641 
trace_strdup3(ccp func,ccp file,uint line,ccp src1,ccp src2,ccp src3)642 char * trace_strdup3 ( ccp func, ccp file, uint line, ccp src1, ccp src2, ccp src3 )
643 {
644     const uint len1 = src1 ? strlen(src1) : 0;
645     const uint len2 = src2 ? strlen(src2) : 0;
646     const uint len3 = src3 ? strlen(src3) : 0;
647     char * res = trace_malloc(func,file,line,len1+len2+len3+1);
648     char * dest = res;
649     if (len1)
650     {
651 	memcpy(dest,src1,len1);
652 	dest += len1;
653     }
654     if (len2)
655     {
656 	memcpy(dest,src2,len2);
657 	dest += len2;
658     }
659     if (len3)
660     {
661 	memcpy(dest,src3,len3);
662 	dest += len3;
663     }
664     *dest = 0;
665     return res;
666 }
667 
668 ///////////////////////////////////////////////////////////////////////////////
669 
trace_memdup(ccp func,ccp file,uint line,const void * src,size_t copylen)670 void * trace_memdup ( ccp func, ccp file, uint line, const void * src, size_t copylen )
671 {
672     char * dest = trace_malloc(func,file,line,copylen+1);
673     memcpy(dest,src,copylen);
674     dest[copylen] = 0;
675     return dest;
676 }
677 
678 //
679 ///////////////////////////////////////////////////////////////////////////////
680 ///////////////			 mem check			///////////////
681 ///////////////////////////////////////////////////////////////////////////////
682 
683 static u8	    mem_check_buf[0x100];
684 static const void * mem_check_ptr = 0;
685 static uint	    mem_check_size = 0;
686 
687 ///////////////////////////////////////////////////////////////////////////////
688 
MemCheckSetup(const void * ptr,uint size)689 void MemCheckSetup ( const void * ptr, uint size )
690 {
691     if ( ptr && size > 0 )
692     {
693 	mem_check_ptr = ptr;
694 	if ( size > sizeof(mem_check_buf) )
695 	{
696 	    ERROR0(ERR_WARNING,
697 		"MemCheckSetup(), max watch size = %zx (<%x)",
698 		sizeof(mem_check_buf), size );
699 	    size = sizeof(mem_check_buf);
700 	}
701 	mem_check_size = size;
702 	memcpy(mem_check_buf,ptr,size);
703     }
704     else
705 	mem_check_size = 0;
706 }
707 
708 ///////////////////////////////////////////////////////////////////////////////
709 
MemCheck(ccp func,ccp file,uint line)710 void MemCheck ( ccp func, ccp file, uint line )
711 {
712     if (!mem_check_size)
713 	return;
714 
715     if ( memcmp(mem_check_buf,mem_check_ptr,mem_check_size) )
716     {
717 	fprintf(stderr,"--- MemCheck: %p should be:\n",mem_check_ptr);
718 	HexDump16(stderr,0,0,mem_check_buf,mem_check_size);
719 	fprintf(stderr,"--- MemCheck: ... but is:\n");
720 	HexDump16(stderr,0,0,mem_check_ptr,mem_check_size);
721 
722 	TRACE("--- MemCheck: %p should be:\n",mem_check_ptr);
723 	TRACE_HEXDUMP16(0,0,mem_check_buf,mem_check_size);
724 	TRACE("--- MemCheck: ... but is:\n");
725 	TRACE_HEXDUMP16(0,0,mem_check_ptr,mem_check_size);
726 
727 	PrintError(func,file,line,0,ERR_FATAL,"MemCheck() failed!\n");
728     }
729     else
730 	TRACE("MemCheck OK: %s @ %s#%u\n",func,file,line);
731 }
732 
733 //
734 ///////////////////////////////////////////////////////////////////////////////
735 ///////////////				END			///////////////
736 ///////////////////////////////////////////////////////////////////////////////
737