set mmap sizes to something more interesting
[trinity.git] / log.c
blob02d5d8c74964d2126ddf7959f82483ba0005039b
1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include "params.h" // logging, monochrome, quiet_level
9 #include "shm.h"
10 #include "pids.h"
11 #include "log.h"
12 #include "arch.h" //PAGE_MASK
13 #include "maps.h" //pages
14 #include "syscall.h" //syscalls
15 #include "tables.h"
17 #define BUFSIZE 1024
19 FILE *mainlogfile;
20 bool logfiles_opened = FALSE;
22 void open_logfiles(void)
24 unsigned int i;
25 char *logfilename;
27 logfilename = malloc(64);
28 sprintf(logfilename, "trinity.log");
29 unlink(logfilename);
30 mainlogfile = fopen(logfilename, "a");
31 if (!mainlogfile) {
32 outputerr("## couldn't open logfile %s\n", logfilename);
33 exit(EXIT_FAILURE);
36 for_each_pidslot(i) {
37 sprintf(logfilename, "trinity-child%d.log", i);
38 unlink(logfilename);
39 shm->logfiles[i] = fopen(logfilename, "a");
40 if (!shm->logfiles[i]) {
41 outputerr("## couldn't open logfile %s\n", logfilename);
42 exit(EXIT_FAILURE);
45 free(logfilename);
46 logfiles_opened = TRUE;
49 void close_logfiles(void)
51 unsigned int i;
53 for_each_pidslot(i)
54 if (shm->logfiles[i] != NULL)
55 fclose(shm->logfiles[i]);
58 static FILE * find_logfile_handle(void)
60 pid_t pid;
61 int i;
62 unsigned int j;
64 pid = getpid();
65 if (pid == initpid)
66 return mainlogfile;
68 if (pid == shm->mainpid)
69 return mainlogfile;
71 if (pid == watchdog_pid)
72 return mainlogfile;
74 i = find_pid_slot(pid);
75 if (i != PIDSLOT_NOT_FOUND)
76 return shm->logfiles[i];
77 else {
78 /* try one more time. FIXME: This is awful. */
79 sleep(1);
80 i = find_pid_slot(pid);
81 if (i != PIDSLOT_NOT_FOUND)
82 return shm->logfiles[i];
84 outputerr("## Couldn't find logfile for pid %d\n", pid);
85 dump_pid_slots();
86 outputerr("## Logfiles for pids: ");
87 for_each_pidslot(j)
88 outputerr("%p ", shm->logfiles[j]);
89 outputerr("\n");
91 return NULL;
94 unsigned int highest_logfile(void)
96 FILE *file;
97 int ret;
99 if (logging == FALSE)
100 return 0;
102 file = shm->logfiles[shm->max_children - 1];
103 ret = fileno(file);
105 return ret;
108 void synclogs(void)
110 unsigned int i;
111 int fd, ret;
113 if (logging == FALSE)
114 return;
116 for_each_pidslot(i) {
117 ret = fflush(shm->logfiles[i]);
118 if (ret == EOF) {
119 outputerr("## logfile flushing failed! %s\n", strerror(errno));
120 continue;
123 fd = fileno(shm->logfiles[i]);
124 if (fd != -1) {
125 ret = fsync(fd);
126 if (ret != 0)
127 outputerr("## fsyncing logfile %d failed. %s\n", i, strerror(errno));
131 (void)fflush(mainlogfile);
132 fsync(fileno(mainlogfile));
135 static void output_arg(unsigned int call, unsigned int argnum, const char *name, unsigned long reg, int type, FILE *fd, bool mono)
137 if (syscalls[call].entry->num_args >= argnum) {
138 if (!name)
139 return;
141 if (argnum != 1) {
142 CRESETFD
143 fprintf(fd, ", ");
145 if (name)
146 fprintf(fd, "%s=", name);
148 switch (type) {
149 case ARG_PATHNAME:
150 fprintf(fd, "\"%s\"", (char *) reg);
151 break;
152 case ARG_PID:
153 case ARG_FD:
154 CRESETFD
155 fprintf(fd, "%ld", reg);
156 break;
157 case ARG_MODE_T:
158 CRESETFD
159 fprintf(fd, "%o", (mode_t) reg);
160 break;
161 case ARG_UNDEFINED:
162 case ARG_LEN:
163 case ARG_ADDRESS:
164 case ARG_NON_NULL_ADDRESS:
165 case ARG_RANGE:
166 case ARG_OP:
167 case ARG_LIST:
168 case ARG_RANDPAGE:
169 case ARG_CPU:
170 case ARG_RANDOM_LONG:
171 case ARG_IOVEC:
172 case ARG_IOVECLEN:
173 case ARG_SOCKADDR:
174 case ARG_SOCKADDRLEN:
175 default:
176 if (reg > 8 * 1024)
177 fprintf(fd, "0x%lx", reg);
178 else
179 fprintf(fd, "%ld", reg);
180 CRESETFD
181 break;
183 if (reg == (((unsigned long)page_zeros) & PAGE_MASK))
184 fprintf(fd, "[page_zeros]");
185 if (reg == (((unsigned long)page_rand) & PAGE_MASK))
186 fprintf(fd, "[page_rand]");
187 if (reg == (((unsigned long)page_0xff) & PAGE_MASK))
188 fprintf(fd, "[page_0xff]");
189 if (reg == (((unsigned long)page_allocs) & PAGE_MASK))
190 fprintf(fd, "[page_allocs]");
194 static FILE *robust_find_logfile_handle(void)
196 unsigned int j;
197 FILE *handle = NULL;
199 if ((logging == TRUE) && (logfiles_opened)) {
200 handle = find_logfile_handle();
201 if (!handle) {
202 outputerr("## child logfile handle was null logging to main!\n");
203 (void)fflush(stdout);
204 for_each_pidslot(j)
205 shm->logfiles[j] = mainlogfile;
206 sleep(5);
207 handle = find_logfile_handle();
210 return handle;
214 * level defines whether it gets displayed to the screen with printf.
215 * (it always logs).
216 * 0 = everything, even all the registers
217 * 1 = Watchdog prints syscall count
218 * 2 = Just the reseed values
221 void output(unsigned char level, const char *fmt, ...)
223 va_list args;
224 int n;
225 FILE *handle;
226 unsigned int len, i, j;
227 pid_t pid;
228 char outputbuf[BUFSIZE];
229 char monobuf[BUFSIZE];
230 char *prefix = NULL;
231 char watchdog_prefix[]="[watchdog]";
232 char init_prefix[]="[init]";
233 char main_prefix[]="[main]";
234 char child_prefix[]="[childNN:1234567890]";
235 unsigned int slot;
237 if (logging == FALSE && level >= quiet_level)
238 return;
240 /* prefix preparation */
241 pid = getpid();
242 if (pid == watchdog_pid)
243 prefix = watchdog_prefix;
245 if (pid == initpid)
246 prefix = init_prefix;
248 if (pid == shm->mainpid)
249 prefix = main_prefix;
251 if (prefix == NULL) {
252 slot = find_pid_slot(pid);
253 sprintf(child_prefix, "[child%d:%d]", slot, pid);
254 prefix = child_prefix;
257 /* formatting output */
258 va_start(args, fmt);
259 n = vsnprintf(outputbuf, sizeof(outputbuf), fmt, args);
260 va_end(args);
261 if (n < 0) {
262 outputerr("## Something went wrong in output() [%d]\n", n);
263 exit(EXIT_FAILURE);
266 /* stdout output if needed */
267 if (quiet_level > level) {
268 printf("%s %s", prefix, outputbuf);
269 (void)fflush(stdout);
272 /* go on with file logs only if enabled */
273 if (logging == FALSE)
274 return;
276 handle = robust_find_logfile_handle();
277 if (!handle)
278 return;
280 /* If we've specified monochrome, we can just dump the buffer into
281 * the logfile as is, because there shouldn't be any ANSI codes
282 * in the buffer to be stripped out. */
283 if (monochrome == FALSE) {
284 /* copy buffer, sans ANSI codes */
285 len = strlen(outputbuf);
286 for (i = 0, j = 0; (i < len) && (i + 2 < BUFSIZE) && (j < BUFSIZE); i++) {
287 if (outputbuf[i] == '\e') {
288 if (outputbuf[i + 2] == '1')
289 i += 6; // ANSI_COLOUR
290 else
291 i += 3; // ANSI_RESET
292 } else {
293 monobuf[j] = outputbuf[i];
294 j++;
297 monobuf[j] = '\0';
298 fprintf(handle, "%s %s", prefix, monobuf);
299 } else {
300 fprintf(handle, "%s %s", prefix, outputbuf);
303 (void)fflush(handle);
307 * Used as a way to consolidated all printf calls if someones one to redirect it to somewhere else.
308 * note: this function ignores quiet_level since it main purpose is error output.
310 void outputerr(const char *fmt, ...)
312 va_list args;
314 va_start(args, fmt);
315 vfprintf(stderr, fmt, args);
316 va_end(args);
319 void outputstd(const char *fmt, ...)
321 va_list args;
323 va_start(args, fmt);
324 vfprintf(stdout, fmt, args);
325 va_end(args);
328 static void output_syscall_prefix_to_fd(const unsigned int childno, const pid_t pid, const unsigned int syscallno, FILE *fd, bool mono)
330 fprintf(fd, "[child%d:%d] [%ld] %s", childno, pid, shm->child_syscall_count[childno],
331 (shm->do32bit[childno] == TRUE) ? "[32BIT] " : "");
333 if (syscallno > max_nr_syscalls)
334 fprintf(fd, "%u", syscallno);
335 else
336 fprintf(fd, "%s", syscalls[syscallno].entry->name);
338 CRESETFD
339 fprintf(fd, "(");
340 output_arg(syscallno, 1, syscalls[syscallno].entry->arg1name, shm->a1[childno],
341 syscalls[syscallno].entry->arg1type, fd, mono);
342 output_arg(syscallno, 2, syscalls[syscallno].entry->arg2name, shm->a2[childno],
343 syscalls[syscallno].entry->arg2type, fd, mono);
344 output_arg(syscallno, 3, syscalls[syscallno].entry->arg3name, shm->a3[childno],
345 syscalls[syscallno].entry->arg3type, fd, mono);
346 output_arg(syscallno, 4, syscalls[syscallno].entry->arg4name, shm->a4[childno],
347 syscalls[syscallno].entry->arg4type, fd, mono);
348 output_arg(syscallno, 5, syscalls[syscallno].entry->arg5name, shm->a5[childno],
349 syscalls[syscallno].entry->arg5type, fd, mono);
350 output_arg(syscallno, 6, syscalls[syscallno].entry->arg6name, shm->a6[childno],
351 syscalls[syscallno].entry->arg6type, fd, mono);
352 CRESETFD
353 fprintf(fd, ") ");
356 /* This function is always called from a fuzzing child. */
357 void output_syscall_prefix(const unsigned int childno, const unsigned int syscallno)
359 FILE *log_handle;
360 pid_t pid;
362 /* Exit if should not continue at all. */
363 if (logging == FALSE && quiet_level < MAX_LOGLEVEL)
364 return;
365 pid = getpid();
367 /* Find the log file handle */
368 log_handle = robust_find_logfile_handle();
370 /* do not output any ascii control symbols to files */
371 if ((logging == TRUE) && (log_handle != NULL))
372 output_syscall_prefix_to_fd(childno, pid, syscallno, log_handle, TRUE);
374 /* Output to stdout only if -q param is not specified */
375 if (quiet_level == MAX_LOGLEVEL)
376 output_syscall_prefix_to_fd(childno, pid, syscallno, stdout, monochrome);
379 static void output_syscall_postfix_err(unsigned long ret, int errno_saved, FILE *fd, bool mono)
381 REDFD
382 fprintf(fd, "= %ld (%s)", ret, strerror(errno_saved));
383 CRESETFD
384 fprintf(fd, "\n");
387 static void output_syscall_postfix_success(unsigned long ret, FILE *fd, bool mono)
389 GREENFD
390 if ((unsigned long)ret > 10000)
391 fprintf(fd, "= 0x%lx", ret);
392 else
393 fprintf(fd, "= %ld", ret);
394 CRESETFD
395 fprintf(fd, "\n");
398 void output_syscall_postfix(unsigned long ret, int errno_saved, bool err)
400 FILE *log_handle;
402 /* Exit if should not continue at all. */
403 if (logging == FALSE && quiet_level < MAX_LOGLEVEL)
404 return;
406 /* Find the log file handle */
407 log_handle = robust_find_logfile_handle();
409 if (err) {
410 if ((logging == TRUE) && (log_handle != NULL))
411 output_syscall_postfix_err(ret, errno_saved, log_handle, TRUE);
412 if (quiet_level == MAX_LOGLEVEL)
413 output_syscall_postfix_err(ret, errno_saved, stdout, monochrome);
414 } else {
415 if ((logging == TRUE) && (log_handle != NULL))
416 output_syscall_postfix_success(ret, log_handle, TRUE);
417 if (quiet_level == MAX_LOGLEVEL)
418 output_syscall_postfix_success(ret, stdout, monochrome);
422 void debugf(const char *fmt, ...)
424 va_list args;
426 if (debug == TRUE) {
427 va_start(args, fmt);
428 vprintf(fmt, args);
429 va_end(args);