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

Last change on this file since 4253 was 4253, checked in by sam, 4 years ago

Fix copyright information and remove Id tag everywhere.

  • Property svn:keywords set to Id
File size: 5.6 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 = -i) ? "-" : "0", 1); /* XXX: hack here */ \
50        while(i) \
51        { \
52            *b-- = hex2char[i % base]; \
53            i /= base; \
54        } \
55        append(b + 1, (int)(buf + 127 - b)); \
56    } while(0)
57
58/* Temporary buffer for deferred output */
59char debugbuffer[BUFSIZ];
60size_t debugcount = 1;
61
62void _zz_debug(char const *format, ...)
63{
64    va_list args;
65    va_start(args, format);
66    if (_zz_debuglevel >= 1)
67        mydebug(format, args);
68    va_end(args);
69}
70
71void _zz_debug2(char const *format, ...)
72{
73    va_list args;
74    va_start(args, format);
75    if (_zz_debuglevel >= 2)
76        mydebug(format, args);
77    va_end(args);
78}
79
80/**
81 * Format a string, printf-like, and write the resulting data to zzuf's
82 * debug file descriptor _zz_debugfd. If the debug file descriptor is
83 * still -1, this function does nothing.
84 *
85 * This function's code is roughly equivalent to the following *printf
86 * calls, except it only uses signal-safe functions:
87 *  - fprintf(stderr, "** zzuf debug ** ");
88 *  - vfprintf(stderr, format, args);
89 *  - fprintf(stderr, "\n");
90 */
91static inline void append(void const *data, size_t count)
92{
93    if (debugcount + count <= sizeof(debugbuffer))
94    {
95        memcpy(debugbuffer + debugcount, data, count);
96        debugcount += count;
97    }
98}
99
100static void mydebug(char const *format, va_list args)
101{
102    static char const *hex2char = "0123456789abcdef";
103    char const *f;
104    int saved_errno;
105
106    saved_errno = errno;
107
108    /* If there is spare data and the debug fd is open, we send the data */
109    if (debugcount && _zz_debugfd >= 0)
110    {
111        write(_zz_debugfd, debugbuffer, debugcount);
112        debugcount = 0;
113    }
114
115    append("** zzuf debug ** ", 17);
116    for(f = format; *f; f++)
117    {
118        if(*f != '%')
119        {
120            append(f, 1);
121            continue;
122        }
123
124        f++;
125        if(!*f)
126            break;
127
128        if(*f == 'c')
129        {
130            char i = (char)(unsigned char)va_arg(args, int);
131            if(i >= 0x20 && i < 0x7f)
132                append(&i, 1);
133            else if(i == '\n')
134                append("\\n", 2);
135            else if(i == '\t')
136                append("\\t", 2);
137            else if(i == '\r')
138                append("\\r", 2);
139            else
140            {
141                append("\\x", 2);
142                append(hex2char + ((i & 0xf0) >> 4), 1);
143                append(hex2char + (i & 0x0f), 1);
144            }
145        }
146        else if(*f == 'i' || *f == 'd')
147        {
148            int i = va_arg(args, int);
149            WRITE_INT(i, 10);
150        }
151        else if(*f == 'x')
152        {
153            int i = va_arg(args, int);
154            WRITE_INT(i, 16);
155        }
156        else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
157        {
158            long int i = va_arg(args, long int);
159            WRITE_INT(i, 10);
160            f++;
161        }
162        else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
163        {
164            long long int i = va_arg(args, long long int);
165            WRITE_INT(i, 10);
166            f += 2;
167        }
168        else if(f[0] == 'g')
169        {
170            double g = va_arg(args, double), h = 0.0000001;
171            int i = (int)g;
172            WRITE_INT(i, 10);
173            for(i = 0; i < 7; i++)
174            {
175                g = (g - (int)g) * 10;
176                h *= 10;
177                if(g < h)
178                    break;
179                if(i == 0)
180                    append(".", 1);
181                append(hex2char + (int)g, 1);
182            }
183        }
184        else if(f[0] == 'p')
185        {
186            uintptr_t i = va_arg(args, uintptr_t);
187            if(!i)
188                append("NULL", 4);
189            else
190            {
191                append("0x", 2);
192                WRITE_INT(i, 16);
193            }
194        }
195        else if(f[0] == 's')
196        {
197            char *s = va_arg(args, char *);
198            if(!s)
199                append("(nil)", 5);
200            else
201            {
202                int l = 0;
203                while(s[l])
204                    l++;
205                append(s, l);
206            }
207        }
208        else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
209        {
210            int i = va_arg(args, int);
211            append(hex2char + ((i & 0xf0) >> 4), 1);
212            append(hex2char + (i & 0x0f), 1);
213            f += 2;
214        }
215        else
216        {
217            append(f - 1, 2);
218        }
219    }
220    append("\n", 1);
221
222    /* If the debug fd is open, we send the data */
223    if (_zz_debugfd >= 0)
224    {
225        write(_zz_debugfd, debugbuffer, debugcount);
226        debugcount = 0;
227    }
228
229    errno = saved_errno;
230}
231
Note: See TracBrowser for help on using the repository browser.