klee
gen-bout.cpp
Go to the documentation of this file.
1//===-- gen-bout.cpp --------------------------------------------*- C++ -*-===//
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
10#include <assert.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <time.h>
17#include <unistd.h>
18
19#include "klee/ADT/KTest.h"
20
21#if defined(__FreeBSD__) || defined(__minix) || defined(__APPLE__)
22#define stat64 stat
23#endif
24
25
26#define MAX 64
27static void push_obj(KTest *b, const char *name, unsigned total_bytes,
28 unsigned char *bytes) {
29 KTestObject *o = &b->objects[b->numObjects++];
30 assert(b->numObjects < MAX);
31
32 o->name = strdup(name);
33 o->numBytes = total_bytes;
34 o->bytes = (unsigned char *)malloc(o->numBytes);
35
36 memcpy(o->bytes, bytes, total_bytes);
37}
38
39static void push_range(KTest *b, const char *name, unsigned value) {
40 KTestObject *o = &b->objects[b->numObjects++];
41 assert(b->numObjects < MAX);
42
43 o->name = strdup(name);
44 o->numBytes = 4;
45 o->bytes = (unsigned char *)malloc(o->numBytes);
46
47 *(unsigned *)o->bytes = value;
48}
49
50void print_usage_and_exit(char *program_name) {
51 fprintf(stderr,
52 "%s: Tool for generating a ktest file from concrete input, e.g., for using a concrete crashing input as a ktest seed.\n"
53 "Usage: %s <arguments>\n"
54 " <arguments> are the command-line arguments of the program, with the following treated as special:\n"
55 " --bout-file <filename> - Specifying the output file name for the ktest file (default: file.bout).\n"
56 " --sym-stdin <filename> - Specifying a file that is the content of stdin (only once).\n"
57 " --sym-stdout <filename> - Specifying a file that is the content of stdout (only once).\n"
58 " --sym-file <filename> - Specifying a file that is the content of a file named A provided for the program (only once).\n"
59 " Ex: %s -o -p -q file1 --sym-stdin file2 --sym-file file3 --sym-stdout file4\n",
60 program_name, program_name, program_name);
61 exit(1);
62}
63
64int main(int argc, char *argv[]) {
65 unsigned i, argv_copy_idx;
66 unsigned file_counter = 0;
67 char *stdout_content_filename = NULL;
68 char *stdin_content_filename = NULL;
69 char *content_filenames_list[1024];
70 char **argv_copy;
71 char *bout_file = NULL;
72
73 if (argc < 2)
74 print_usage_and_exit(argv[0]);
75
76 KTest b;
77 b.symArgvs = 0;
78 b.symArgvLen = 0;
79
80 b.numObjects = 0;
81 b.objects = (KTestObject *)malloc(MAX * sizeof *b.objects);
82
83 if ((argv_copy = (char **)malloc(sizeof(char *) * argc * 2)) == NULL) {
84 fprintf(stderr, "Could not allocate more memory\n");
85 return 1;
86 }
87
88 argv_copy[0] = (char *)malloc(strlen(argv[0]) + 1);
89 strcpy(argv_copy[0], argv[0]);
90 argv_copy_idx = 1;
91
92 for (i = 1; i < (unsigned)argc; i++) {
93 if (strcmp(argv[i], "--sym-stdout") == 0 ||
94 strcmp(argv[i], "-sym-stdout") == 0) {
95 if (++i == (unsigned)argc || argv[i][0] == '-')
96 print_usage_and_exit(argv[0]);
97
98 if (stdout_content_filename)
99 print_usage_and_exit(argv[0]);
100
101 stdout_content_filename = argv[i];
102
103 } else if (strcmp(argv[i], "--sym-stdin") == 0 ||
104 strcmp(argv[i], "-sym-stdin") == 0) {
105 if (++i == (unsigned)argc || argv[i][0] == '-')
106 print_usage_and_exit(argv[0]);
107
108 if (stdin_content_filename)
109 print_usage_and_exit(argv[0]);
110
111 stdin_content_filename = argv[i];
112 } else if (strcmp(argv[i], "--sym-file") == 0 ||
113 strcmp(argv[i], "-sym-file") == 0) {
114 if (++i == (unsigned)argc || argv[i][0] == '-')
115 print_usage_and_exit(argv[0]);
116
117 content_filenames_list[file_counter++] = argv[i];
118 } else if (strcmp(argv[i], "--bout-file") == 0 ||
119 strcmp(argv[i], "-bout-file") == 0) {
120 if (++i == (unsigned)argc)
121 print_usage_and_exit(argv[0]);
122
123 bout_file = argv[i];
124 } else {
125 long nbytes = strlen(argv[i]) + 1;
126 static int total_args = 0;
127
128 char arg[1024];
129 snprintf(arg, sizeof(arg), "arg%02d", total_args++);
130 push_obj(&b, (const char *)arg, nbytes, (unsigned char *)argv[i]);
131
132 char *buf1 = (char *)malloc(1024);
133 char *buf2 = (char *)malloc(1024);
134 strcpy(buf1, "-sym-arg");
135 snprintf(buf2, 1024, "%ld", nbytes - 1);
136 argv_copy[argv_copy_idx++] = buf1;
137 argv_copy[argv_copy_idx++] = buf2;
138 }
139 }
140
141 if (file_counter > 0) {
142 char filename[7] = "A-data";
143 char statname[12] = "A-data-stat";
144 char sym_file_name = 'A';
145 FILE *fp[file_counter];
146 unsigned char *file_content[file_counter];
147 struct stat64 file_stat[file_counter];
148 long max_file_size = 0;
149
150 for (unsigned current_file = 0; current_file < file_counter;
151 current_file++) {
152 char *content_filename = content_filenames_list[current_file];
153
154 if ((fp[current_file] = fopen(content_filename, "r")) == NULL ||
155 stat64(content_filename, file_stat + current_file) < 0) {
156 perror("Failed to open");
157 fprintf(stderr, "Failure opening %s %p\n", content_filename,
158 fp[current_file]);
159 print_usage_and_exit(argv[0]);
160 }
161
162 long nbytes = file_stat[current_file].st_size;
163 max_file_size = max_file_size > nbytes ? max_file_size : nbytes;
164
165 if ((file_content[current_file] = (unsigned char *)malloc(nbytes)) ==
166 NULL) {
167 fputs("Memory allocation failure\n", stderr);
168 exit(1);
169 }
170
171 int read_char;
172 unsigned char *fptr;
173 fptr = file_content[current_file];
174 while ((read_char = fgetc(fp[current_file])) != EOF) {
175 *fptr = (unsigned char)read_char;
176 fptr++;
177 }
178 }
179 // We opened all the files, read their content and got the max size of all
180 // files. Now we extend the smaller files to the max size and add them to
181 // ktest files.
182 for (unsigned current_file = 0; current_file < file_counter;
183 current_file++) {
184 long nbytes = file_stat[current_file].st_size;
185 if (nbytes < max_file_size) {
186 file_content[current_file] =
187 (unsigned char *)realloc(file_content[current_file], max_file_size);
188 // Rewrite the tail with EOF and all zeroes
189 file_content[current_file][nbytes] = EOF;
190 for (int i = nbytes; i < max_file_size; i++) {
191 file_content[current_file][i] = '\0';
192 }
193 }
194 // Push obj to ktest file
195 filename[0] = sym_file_name;
196 statname[0] = sym_file_name;
197 push_obj(&b, filename, max_file_size, file_content[current_file]);
198 push_obj(&b, statname, sizeof(struct stat64),
199 (unsigned char *)&file_stat[current_file]);
200 free(file_content[current_file]);
201 file_content[current_file] = NULL;
202 sym_file_name++;
203 }
204
205 char *buf1 = (char *)malloc(1024);
206 char *buf2 = (char *)malloc(1024);
207 char *buf3 = (char *)malloc(1024);
208 snprintf(buf1, 1024, "-sym-files");
209 snprintf(buf2, 1024, "%d", file_counter);
210 snprintf(buf3, 1024, "%ld", max_file_size);
211 argv_copy[argv_copy_idx++] = buf1;
212 argv_copy[argv_copy_idx++] = buf2;
213 argv_copy[argv_copy_idx++] = buf3;
214 }
215
216 if (stdin_content_filename) {
217 FILE *fp;
218 struct stat64 file_stat;
219 char filename[6] = "stdin";
220 char statname[11] = "stdin-stat";
221
222 if ((fp = fopen(stdin_content_filename, "r")) == NULL ||
223 stat64(stdin_content_filename, &file_stat) < 0) {
224 fprintf(stderr, "Failure opening %s\n", stdin_content_filename);
225 print_usage_and_exit(argv[0]);
226 }
227
228 unsigned char *file_content, *fptr;
229 if ((file_content = (unsigned char *)malloc(file_stat.st_size)) == NULL) {
230 fputs("Memory allocation failure\n", stderr);
231 exit(1);
232 }
233
234 int read_char;
235 fptr = file_content;
236 while ((read_char = fgetc(fp)) != EOF) {
237 *fptr = (unsigned char)read_char;
238 fptr++;
239 }
240
241 push_obj(&b, filename, file_stat.st_size, file_content);
242 push_obj(&b, statname, sizeof(struct stat64), (unsigned char *)&file_stat);
243
244 free(file_content);
245
246 char *buf1 = (char *)malloc(1024);
247 char *buf2 = (char *)malloc(1024);
248 snprintf(buf1, 1024, "-sym-stdin");
249 snprintf(buf2, 1024, "%lld", (long long int) file_stat.st_size);
250 argv_copy[argv_copy_idx++] = buf1;
251 argv_copy[argv_copy_idx++] = buf2;
252 }
253
254 if (stdout_content_filename) {
255 FILE *fp;
256 struct stat64 file_stat;
257 unsigned char file_content[1024];
258 char filename[7] = "stdout";
259 char statname[12] = "stdout-stat";
260
261 if ((fp = fopen(stdout_content_filename, "r")) == NULL ||
262 stat64(stdout_content_filename, &file_stat) < 0) {
263 fprintf(stderr, "Failure opening %s\n", stdout_content_filename);
264 print_usage_and_exit(argv[0]);
265 }
266
267 int read_char;
268 for (int i = 0; i < file_stat.st_size && i < 1024; ++i) {
269 read_char = fgetc(fp);
270 file_content[i] = (unsigned char)read_char;
271 }
272
273 for (int i = file_stat.st_size; i < 1024; ++i) {
274 file_content[i] = 0;
275 }
276
277 file_stat.st_size = 1024;
278
279 push_obj(&b, filename, 1024, file_content);
280 push_obj(&b, statname, sizeof(struct stat64), (unsigned char *)&file_stat);
281
282 char *buf = (char *)malloc(1024);
283 snprintf(buf, 1024, "-sym-stdout");
284 argv_copy[argv_copy_idx++] = buf;
285 }
286
287 argv_copy[argv_copy_idx] = 0;
288
289 b.numArgs = argv_copy_idx;
290 b.args = argv_copy;
291
292 push_range(&b, "model_version", 1);
293
294 if (!kTest_toFile(&b, bout_file ? bout_file : "file.bout"))
295 assert(0);
296
297 for (int i = 0; i < (int)b.numObjects; ++i) {
298 free(b.objects[i].name);
299 free(b.objects[i].bytes);
300 }
301 free(b.objects);
302
303 for (int i = 0; i < (int)argv_copy_idx; ++i) {
304 free(argv_copy[i]);
305 }
306 free(argv_copy);
307
308 return 0;
309}
int kTest_toFile(KTest *bo, const char *path)
Definition: KTest.cpp:178
int main(int argc, char *argv[])
Definition: gen-bout.cpp:64
void print_usage_and_exit(char *program_name)
Definition: gen-bout.cpp:50
#define MAX
Definition: gen-bout.cpp:26
static void push_obj(KTest *b, const char *name, unsigned total_bytes, unsigned char *bytes)
Definition: gen-bout.cpp:27
static void push_range(KTest *b, const char *name, unsigned value)
Definition: gen-bout.cpp:39
char * name
Definition: KTest.h:19
unsigned char * bytes
Definition: KTest.h:21
unsigned numBytes
Definition: KTest.h:20
Definition: KTest.h:25
unsigned symArgvLen
Definition: KTest.h:33
unsigned numObjects
Definition: KTest.h:35
KTestObject * objects
Definition: KTest.h:36
unsigned numArgs
Definition: KTest.h:29
unsigned symArgvs
Definition: KTest.h:32
char ** args
Definition: KTest.h:30