source: zzuf/trunk/src/debug.c @ 4009

Last change on this file since 4009 was 4009, checked in by Sam Hocevar, 11 years ago

Add a second level of debugging for slightly less useful information.

  • Property svn:keywords set to Id
File size: 5.3 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: debug.c 4009 2009-11-23 00:26:53Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  debug.c: debugging support
17 */
18
19#include "config.h"
20
21#if defined HAVE_STDINT_H
22#   include <stdint.h>
23#elif defined HAVE_INTTYPES_H
24#   include <inttypes.h>
25#endif
26#include <stdio.h>
27#if defined HAVE_UNISTD_H
28#   include <unistd.h>
29#endif
30#if defined HAVE_IO_H
31#   include <io.h>
32#endif
33#include <errno.h>
34#include <stdarg.h>
35
36#include "debug.h"
37#include "libzzuf.h"
38
39static void mydebug(char const *format, va_list args);
40
41/**
42 * Helper macro to write an integer value to a given file descriptor,
43 * either in base 10 or in hexadecimal.
44 */
45#define WRITE_INT(fd, i, base) \
46    do \
47    { \
48        char buf[128], *b = buf + 127; \
49        if(i <= 0) \
50            write(fd, (i = -i) ? "-" : "0", 1); /* XXX: hack here */ \
51        while(i) \
52        { \
53            *b-- = hex2char[i % base]; \
54            i /= base; \
55        } \
56        write(fd, b + 1, (int)(buf + 127 - b)); \
57    } while(0)
58
59void _zz_debug(char const *format, ...)
60{
61    va_list args;
62    va_start(args, format);
63    if (_zz_debuglevel >= 1)
64        mydebug(format, args);
65    va_end(args);
66}
67
68void _zz_debug2(char const *format, ...)
69{
70    va_list args;
71    va_start(args, format);
72    if (_zz_debuglevel >= 2)
73        mydebug(format, args);
74    va_end(args);
75}
76
77/**
78 * Format a string, printf-like, and write the resulting data to zzuf's
79 * debug file descriptor _zz_debugfd. If the debug file descriptor is
80 * still -1, this function does nothing.
81 *
82 * This function's code is roughly equivalent to the following *printf
83 * calls, except it only uses signal-safe functions:
84 *  - fprintf(stderr, "** zzuf debug ** ");
85 *  - vfprintf(stderr, format, args);
86 *  - fprintf(stderr, "\n");
87 */
88static void mydebug(char const *format, va_list args)
89{
90    static char const *hex2char = "0123456789abcdef";
91    char const *f;
92    int saved_errno;
93
94    if(_zz_debugfd < 0)
95        return;
96
97    saved_errno = errno;
98
99    write(_zz_debugfd, "** zzuf debug ** ", 17);
100    for(f = format; *f; f++)
101    {
102        if(*f != '%')
103        {
104            write(_zz_debugfd, f, 1);
105            continue;
106        }
107
108        f++;
109        if(!*f)
110            break;
111
112        if(*f == 'c')
113        {
114            char i = (char)(unsigned char)va_arg(args, int);
115            if(i >= 0x20 && i < 0x7f)
116                write(_zz_debugfd, &i, 1);
117            else if(i == '\n')
118                write(_zz_debugfd, "\\n", 2);
119            else if(i == '\t')
120                write(_zz_debugfd, "\\t", 2);
121            else if(i == '\r')
122                write(_zz_debugfd, "\\r", 2);
123            else
124            {
125                write(_zz_debugfd, "\\x", 2);
126                write(_zz_debugfd, hex2char + ((i & 0xf0) >> 4), 1);
127                write(_zz_debugfd, hex2char + (i & 0x0f), 1);
128            }
129        }
130        else if(*f == 'i' || *f == 'd')
131        {
132            int i = va_arg(args, int);
133            WRITE_INT(_zz_debugfd, i, 10);
134        }
135        else if(*f == 'x')
136        {
137            int i = va_arg(args, int);
138            WRITE_INT(_zz_debugfd, i, 16);
139        }
140        else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
141        {
142            long int i = va_arg(args, long int);
143            WRITE_INT(_zz_debugfd, i, 10);
144            f++;
145        }
146        else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
147        {
148            long long int i = va_arg(args, long long int);
149            WRITE_INT(_zz_debugfd, i, 10);
150            f += 2;
151        }
152        else if(f[0] == 'g')
153        {
154            double g = va_arg(args, double), h = 0.0000001;
155            int i = g;
156            WRITE_INT(_zz_debugfd, i, 10);
157            for(i = 0; i < 7; i++)
158            {
159                g = (g - (int)g) * 10;
160                h *= 10;
161                if(g < h)
162                    break;
163                if(i == 0)
164                    write(_zz_debugfd, ".", 1);
165                write(_zz_debugfd, hex2char + (int)g, 1);
166            }
167        }
168        else if(f[0] == 'p')
169        {
170            uintptr_t i = va_arg(args, uintptr_t);
171            if(!i)
172                write(_zz_debugfd, "NULL", 5);
173            else
174            {
175                write(_zz_debugfd, "0x", 2);
176                WRITE_INT(_zz_debugfd, i, 16);
177            }
178        }
179        else if(f[0] == 's')
180        {
181            char *s = va_arg(args, char *);
182            if(!s)
183                write(_zz_debugfd, "(nil)", 5);
184            else
185            {
186                int l = 0;
187                while(s[l])
188                    l++;
189                write(_zz_debugfd, s, l);
190            }
191        }
192        else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
193        {
194            int i = va_arg(args, int);
195            write(_zz_debugfd, hex2char + ((i & 0xf0) >> 4), 1);
196            write(_zz_debugfd, hex2char + (i & 0x0f), 1);
197            f += 2;
198        }
199        else
200        {
201            write(_zz_debugfd, f - 1, 2);
202        }
203    }
204    write(_zz_debugfd, "\n", 1);
205    errno = saved_errno;
206}
Note: See TracBrowser for help on using the repository browser.