source: zzuf/trunk/src/libzzuf/debug.c @ 4885

Last change on this file since 4885 was 4885, checked in by Sam Hocevar, 5 years ago

build: fix a few compilation warnings.

  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
11 */
12
13/*
14 *  debug.c: debugging support
15 */
16
17#include "config.h"
18
19#if defined HAVE_STDINT_H
20#   include <stdint.h>
21#elif defined HAVE_INTTYPES_H
22#   include <inttypes.h>
23#endif
24#include <stdio.h>
25#include <string.h>
26#if defined HAVE_UNISTD_H
27#   include <unistd.h>
28#endif
29#if defined HAVE_IO_H
30#   include <io.h>
31#endif
32#include <errno.h>
33#include <stdarg.h>
34
35#include "debug.h"
36#include "libzzuf.h"
37
38static void mydebug(char const *format, va_list args);
39
40/**
41 * Helper macro to write an integer value to a given file descriptor,
42 * either in base 10 or in hexadecimal.
43 */
44#define WRITE_INT(i, base) \
45    do \
46    { \
47        char buf[128], *b = buf + 127; \
48        if (i <= 0) \
49            append((i = 1 + ~i) ? "-" : "0", 1); /* XXX: hack here */ \
50        if (i + 1 <= 0) \
51        { \
52            i = 1 + ~(i + base); /* XXX: special case for INT_MIN */ \
53            *b-- = hex2char[i % base]; \
54            i = i / base + 1; \
55        } \
56        while (i) \
57        { \
58            *b-- = hex2char[i % base]; \
59            i /= base; \
60        } \
61        append(b + 1, (int)(buf + 127 - b)); \
62    } while (0)
63
64/* Temporary buffer for deferred output */
65char debugbuffer[BUFSIZ];
66size_t debugcount = 1;
67
68#ifdef _WIN32
69
70CRITICAL_SECTION _zz_pipe_cs; /* Initialized in DllMain */
71
72void _zz_debug(char const *format, ...)
73{
74    va_list args;
75    char buf[0x100];
76    DWORD written;
77    va_start(args, format);
78    //if (_zz_debuglevel >= 1) // LATER:
79    {
80        HANDLE dbg_hdl = (HANDLE)_get_osfhandle(_zz_debugfd);
81        int ret = _vsnprintf(buf, sizeof(buf), format, args);
82
83        if (ret <= 0)       return;  /* if _snprintf failed, we send nothing                    */
84        if (buf[0] == '\0') return; /* if the buf is empty, we don't bother to send it to zzuf */
85
86        /* FIXME: if len >= count, no null-terminator is appended, so we may erased the last character */
87        if (ret >= sizeof(buf)) buf[ret - 1] = '\n';
88        else                    buf[ret++]   = '\n';
89
90        EnterCriticalSection(&_zz_pipe_cs);
91        WriteFile(dbg_hdl, buf, ret, &written, NULL);
92        LeaveCriticalSection(&_zz_pipe_cs);
93    }
94    va_end(args);
95    fflush(NULL); /* flush all streams to make sure zzuf gotta catch 'em all */
96}
97
98void _zz_debug2(char const *format, ...)
99{
100    va_list args;
101    char buf[0x100];
102    DWORD written;
103    va_start(args, format);
104    //if (_zz_debuglevel >= 1) // LATER:
105    {
106        HANDLE dbg_hdl = (HANDLE)_get_osfhandle(_zz_debugfd);
107        int ret = _vsnprintf(buf, sizeof(buf), format, args);
108
109        if (ret <= 0)       return;  /* if _snprintf failed, we send nothing                    */
110        if (buf[0] == '\0') return; /* if the buf is empty, we don't bother to send it to zzuf */
111
112        /* FIXME: if len >= count, no null-terminator is appended, so we may erased the last character */
113        if (ret >= sizeof(buf)) buf[ret - 1] = '\n';
114        else                    buf[ret++]   = '\n';
115
116        EnterCriticalSection(&_zz_pipe_cs);
117        WriteFile(dbg_hdl, buf, ret, &written, NULL);
118        LeaveCriticalSection(&_zz_pipe_cs);
119    }
120    va_end(args);
121    fflush(NULL); /* flush all streams to make sure zzuf gotta catch 'em all */
122}
123#else
124void _zz_debug(char const *format, ...)
125{
126    va_list args;
127    va_start(args, format);
128    if (_zz_debuglevel >= 1)
129        mydebug(format, args);
130    va_end(args);
131}
132
133void _zz_debug2(char const *format, ...)
134{
135    va_list args;
136    va_start(args, format);
137    if (_zz_debuglevel >= 2)
138        mydebug(format, args);
139    va_end(args);
140}
141#endif
142
143/**
144 * Format a string, printf-like, and write the resulting data to zzuf's
145 * debug file descriptor _zz_debugfd. If the debug file descriptor is
146 * still -1, this function does nothing.
147 *
148 * This function's code is roughly equivalent to the following *printf
149 * calls, except it only uses signal-safe functions:
150 *  - fprintf(stderr, "** zzuf debug ** ");
151 *  - vfprintf(stderr, format, args);
152 *  - fprintf(stderr, "\n");
153 */
154static inline void append(void const *data, size_t count)
155{
156    if (debugcount + count <= sizeof(debugbuffer))
157    {
158        memcpy(debugbuffer + debugcount, data, count);
159        debugcount += count;
160    }
161}
162
163static void mydebug(char const *format, va_list args)
164{
165    static char const *hex2char = "0123456789abcdef";
166    char const *f;
167    int saved_errno;
168
169    saved_errno = errno;
170
171    /* If there is spare data and the debug fd is open, we send the data */
172    if (debugcount && _zz_debugfd >= 0)
173    {
174        write(_zz_debugfd, debugbuffer, debugcount);
175        debugcount = 0;
176    }
177
178    append("** zzuf debug ** ", 17);
179    for(f = format; *f; f++)
180    {
181        if(*f != '%')
182        {
183            append(f, 1);
184            continue;
185        }
186
187        f++;
188        if(!*f)
189            break;
190
191        if(*f == 'c')
192        {
193            char i = (char)(unsigned char)va_arg(args, int);
194            if(i >= 0x20 && i < 0x7f)
195                append(&i, 1);
196            else if(i == '\n')
197                append("\\n", 2);
198            else if(i == '\t')
199                append("\\t", 2);
200            else if(i == '\r')
201                append("\\r", 2);
202            else
203            {
204                append("\\x", 2);
205                append(hex2char + ((i & 0xf0) >> 4), 1);
206                append(hex2char + (i & 0x0f), 1);
207            }
208        }
209        else if(*f == 'i' || *f == 'd')
210        {
211            int i = va_arg(args, int);
212            WRITE_INT(i, 10);
213        }
214        else if(*f == 'x')
215        {
216            unsigned int i = va_arg(args, unsigned int);
217            WRITE_INT(i, 16);
218        }
219        else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
220        {
221            long int i = va_arg(args, long int);
222            WRITE_INT(i, 10);
223            f++;
224        }
225        else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
226        {
227            long long int i = va_arg(args, long long int);
228            WRITE_INT(i, 10);
229            f += 2;
230        }
231        else if(f[0] == 'g')
232        {
233            double g = va_arg(args, double), h = 0.0000001;
234            int i = (int)g;
235            WRITE_INT(i, 10);
236            for(i = 0; i < 7; i++)
237            {
238                g = (g - (int)g) * 10;
239                h *= 10;
240                if(g < h)
241                    break;
242                if(i == 0)
243                    append(".", 1);
244                append(hex2char + (int)g, 1);
245            }
246        }
247        else if(f[0] == 'p')
248        {
249            uintptr_t i = va_arg(args, uintptr_t);
250            if(!i)
251                append("NULL", 4);
252            else
253            {
254                append("0x", 2);
255                WRITE_INT(i, 16);
256            }
257        }
258        else if(f[0] == 's')
259        {
260            char *s = va_arg(args, char *);
261            if(!s)
262                append("(nil)", 5);
263            else
264            {
265                int l = 0;
266                while(s[l])
267                    l++;
268                append(s, l);
269            }
270        }
271        else if(f[0] == 'S')
272        {
273            uint16_t *s = va_arg(args, uint16_t *);
274            if(!s)
275                append("(nil)", 5);
276            else
277            {
278                int l = 0;
279                while(s[l])
280                {
281                    if (s[l] < 128)
282                    {
283                        char tmp = (char)s[l];
284                        append(&tmp, 1);
285                    }
286                    else
287                    {
288                        append("\\u", 2);
289                        append(hex2char + ((s[l] & 0xf000) >> 12), 1);
290                        append(hex2char + ((s[l] & 0xf00) >> 8), 1);
291                        append(hex2char + ((s[l] & 0xf0) >> 4), 1);
292                        append(hex2char + (s[l] & 0xf), 1);
293                    }
294                    l++;
295                }
296            }
297        }
298        else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
299        {
300            int i = va_arg(args, int);
301            append(hex2char + ((i & 0xf0) >> 4), 1);
302            append(hex2char + (i & 0x0f), 1);
303            f += 2;
304        }
305        else
306        {
307            append(f - 1, 2);
308        }
309    }
310    append("\n", 1);
311
312    /* If the debug fd is open, we send the data */
313    if (_zz_debugfd >= 0)
314    {
315        write(_zz_debugfd, debugbuffer, debugcount);
316        debugcount = 0;
317    }
318
319    errno = saved_errno;
320}
321
Note: See TracBrowser for help on using the repository browser.