klee
ErrorHandling.cpp
Go to the documentation of this file.
1//===-- ErrorHandling.cpp -------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
11#include "llvm/ADT/StringRef.h"
12#include "llvm/Support/raw_ostream.h"
13#include "llvm/Support/CommandLine.h"
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <stdarg.h>
18#include <assert.h>
19#include <string.h>
20
21#include <set>
22
23using namespace klee;
24using namespace llvm;
25
28
29static const char *warningPrefix = "WARNING";
30static const char *warningOncePrefix = "WARNING ONCE";
31static const char *errorPrefix = "ERROR";
32static const char *notePrefix = "NOTE";
33
34namespace klee {
35cl::OptionCategory MiscCat("Miscellaneous options", "");
36}
37
38namespace {
39cl::opt<bool> WarningsOnlyToFile(
40 "warnings-only-to-file", cl::init(false),
41 cl::desc("All warnings will be written to warnings.txt only. If disabled, "
42 "they are also written on screen."),
43 cl::cat(MiscCat));
44} // namespace
45
46static bool shouldSetColor(const char *pfx, const char *msg,
47 const char *prefixToSearchFor) {
48 if (pfx && strcmp(pfx, prefixToSearchFor) == 0)
49 return true;
50
51 if (llvm::StringRef(msg).startswith(prefixToSearchFor))
52 return true;
53
54 return false;
55}
56
57static void klee_vfmessage(FILE *fp, const char *pfx, const char *msg,
58 va_list ap) {
59 if (!fp)
60 return;
61
62 llvm::raw_fd_ostream fdos(fileno(fp), /*shouldClose=*/false,
63 /*unbuffered=*/true);
64 bool modifyConsoleColor = fdos.is_displayed() && (fp == stderr);
65
66 if (modifyConsoleColor) {
67
68 // Warnings
69 if (shouldSetColor(pfx, msg, warningPrefix))
70 fdos.changeColor(llvm::raw_ostream::MAGENTA,
71 /*bold=*/false,
72 /*bg=*/false);
73
74 // Once warning
75 if (shouldSetColor(pfx, msg, warningOncePrefix))
76 fdos.changeColor(llvm::raw_ostream::MAGENTA,
77 /*bold=*/true,
78 /*bg=*/false);
79
80 // Errors
81 if (shouldSetColor(pfx, msg, errorPrefix))
82 fdos.changeColor(llvm::raw_ostream::RED,
83 /*bold=*/true,
84 /*bg=*/false);
85
86 // Notes
87 if (shouldSetColor(pfx, msg, notePrefix))
88 fdos.changeColor(llvm::raw_ostream::WHITE,
89 /*bold=*/true,
90 /*bg=*/false);
91 }
92
93 fdos << "KLEE: ";
94 if (pfx)
95 fdos << pfx << ": ";
96
97 // FIXME: Can't use fdos here because we need to print
98 // a variable number of arguments and do substitution
99 vfprintf(fp, msg, ap);
100 fflush(fp);
101
102 fdos << "\n";
103
104 if (modifyConsoleColor)
105 fdos.resetColor();
106
107 fdos.flush();
108}
109
110/* Prints a message/warning.
111
112 If pfx is NULL, this is a regular message, and it's sent to
113 klee_message_file (messages.txt). Otherwise, it is sent to
114 klee_warning_file (warnings.txt).
115
116 Iff onlyToFile is false, the message is also printed on stderr.
117*/
118static void klee_vmessage(const char *pfx, bool onlyToFile, const char *msg,
119 va_list ap) {
120 if (!onlyToFile) {
121 va_list ap2;
122 va_copy(ap2, ap);
123 klee_vfmessage(stderr, pfx, msg, ap2);
124 va_end(ap2);
125 }
126
128}
129
130void klee::klee_message(const char *msg, ...) {
131 va_list ap;
132 va_start(ap, msg);
133 klee_vmessage(NULL, false, msg, ap);
134 va_end(ap);
135}
136
137/* Message to be written only to file */
138void klee::klee_message_to_file(const char *msg, ...) {
139 va_list ap;
140 va_start(ap, msg);
141 klee_vmessage(NULL, true, msg, ap);
142 va_end(ap);
143}
144
145void klee::klee_error(const char *msg, ...) {
146 va_list ap;
147 va_start(ap, msg);
148 klee_vmessage(errorPrefix, false, msg, ap);
149 va_end(ap);
150 exit(1);
151}
152
153void klee::klee_warning(const char *msg, ...) {
154 va_list ap;
155 va_start(ap, msg);
156 klee_vmessage(warningPrefix, WarningsOnlyToFile, msg, ap);
157 va_end(ap);
158}
159
160/* Prints a warning once per message. */
161void klee::klee_warning_once(const void *id, const char *msg, ...) {
162 static std::set<std::pair<const void *, const char *> > keys;
163 std::pair<const void *, const char *> key;
164
165 /* "calling external" messages contain the actual arguments with
166 which we called the external function, so we need to ignore them
167 when computing the key. */
168 if (strncmp(msg, "calling external", strlen("calling external")) != 0)
169 key = std::make_pair(id, msg);
170 else
171 key = std::make_pair(id, "calling external");
172
173 if (!keys.count(key)) {
174 keys.insert(key);
175 va_list ap;
176 va_start(ap, msg);
177 klee_vmessage(warningOncePrefix, WarningsOnlyToFile, msg, ap);
178 va_end(ap);
179 }
180}
static void klee_vfmessage(FILE *fp, const char *pfx, const char *msg, va_list ap)
static const char * errorPrefix
static const char * warningPrefix
static const char * warningOncePrefix
static bool shouldSetColor(const char *pfx, const char *msg, const char *prefixToSearchFor)
static const char * notePrefix
static void klee_vmessage(const char *pfx, bool onlyToFile, const char *msg, va_list ap)
Definition: main.cpp:291
FILE * klee_warning_file
void klee_message(const char *msg,...) __attribute__((format(printf
llvm::cl::OptionCategory MiscCat
void void klee_message_to_file(const char *msg,...) __attribute__((format(printf
void klee_error(const char *msg,...) __attribute__((format(printf
void void void void klee_warning_once(const void *id, const char *msg,...) __attribute__((format(printf
void void void klee_warning(const char *msg,...) __attribute__((format(printf
FILE * klee_message_file
cl::OptionCategory MiscCat("Miscellaneous options", "")