1e5ad1662c9c2872639ba8e53ad866969ccb65ad
[c11tester.git] / main.cc
1 /** @file main.cc
2  *  @brief Entry point for the model checker.
3  */
4
5 #include <unistd.h>
6 #include <getopt.h>
7 #include <string.h>
8
9 #include "common.h"
10 #include "output.h"
11
12 #include "datarace.h"
13
14 /* global "model" object */
15 #include "model.h"
16 #include "params.h"
17 #include "snapshot-interface.h"
18 #include "plugins.h"
19
20 static void param_defaults(struct model_params *params)
21 {
22         params->verbose = !!DBG_ENABLED();
23         params->uninitvalue = 0;
24         params->maxexecutions = 10;
25 }
26
27 static void print_usage(const char *program_name, struct model_params *params)
28 {
29         ModelVector<TraceAnalysis *> * registeredanalysis=getRegisteredTraceAnalysis();
30         /* Reset defaults before printing */
31         param_defaults(params);
32
33         model_print(
34 "Copyright (c) 2013 Regents of the University of California. All rights reserved.\n"
35 "Distributed under the GPLv2\n"
36 "Written by Brian Norris and Brian Demsky\n"
37 "\n"
38 "Usage: %s [MODEL-CHECKER OPTIONS] -- [PROGRAM ARGS]\n"
39 "\n"
40 "MODEL-CHECKER OPTIONS can be any of the model-checker options listed below. Arguments\n"
41 "provided after the `--' (the PROGRAM ARGS) are passed to the user program.\n"
42 "\n"
43 "Model-checker options:\n"
44 "-h, --help                  Display this help message and exit\n"
45 "-v[NUM], --verbose[=NUM]    Print verbose execution information. NUM is optional:\n"
46 "                              0 is quiet; 1 shows valid executions; 2 is noisy;\n"
47 "                              3 is noisier.\n"
48 "                              Default: %d\n"
49 "-u, --uninitialized=VALUE   Return VALUE any load which may read from an\n"
50 "                              uninitialized atomic.\n"
51 "                              Default: %u\n"
52 "-t, --analysis=NAME         Use Analysis Plugin.\n"
53 "-o, --options=NAME          Option for previous analysis plugin.  \n"
54 "-x, --maxexec=NUM           Maximum number of executions.\n"
55 "                            Default: %u\n"
56 "                            -o help for a list of options\n"
57 " --                         Program arguments follow.\n\n",
58                 program_name,
59                 params->verbose,
60                 params->uninitvalue,
61                 params->maxexecutions);
62         model_print("Analysis plugins:\n");
63         for(unsigned int i=0;i<registeredanalysis->size();i++) {
64                 TraceAnalysis * analysis=(*registeredanalysis)[i];
65                 model_print("%s\n", analysis->name());
66         }
67         exit(EXIT_SUCCESS);
68 }
69
70 bool install_plugin(char * name) {
71         ModelVector<TraceAnalysis *> * registeredanalysis=getRegisteredTraceAnalysis();
72         ModelVector<TraceAnalysis *> * installedanalysis=getInstalledTraceAnalysis();
73
74         for(unsigned int i=0;i<registeredanalysis->size();i++) {
75                 TraceAnalysis * analysis=(*registeredanalysis)[i];
76                 if (strcmp(name, analysis->name())==0) {
77                         installedanalysis->push_back(analysis);
78                         return false;
79                 }
80         }
81         model_print("Analysis %s Not Found\n", name);
82         return true;
83 }
84
85 static void parse_options(struct model_params *params, int argc, char **argv)
86 {
87         const char *shortopts = "ht:o:u:x:v::";
88         const struct option longopts[] = {
89                 {"help", no_argument, NULL, 'h'},
90                 {"verbose", optional_argument, NULL, 'v'},
91                 {"uninitialized", required_argument, NULL, 'u'},
92                 {"analysis", required_argument, NULL, 't'},
93                 {"options", required_argument, NULL, 'o'},
94                 {"maxexecutions", required_argument, NULL, 'x'},
95                 {0, 0, 0, 0} /* Terminator */
96         };
97         int opt, longindex;
98         bool error = false;
99         while (!error && (opt = getopt_long(argc, argv, shortopts, longopts, &longindex)) != -1) {
100                 switch (opt) {
101                 case 'h':
102                         print_usage(argv[0], params);
103                         break;
104                 case 'x':
105                         params->maxexecutions = atoi(optarg);
106                         break;
107                 case 'v':
108                         params->verbose = optarg ? atoi(optarg) : 1;
109                         break;
110                 case 'u':
111                         params->uninitvalue = atoi(optarg);
112                         break;
113                 case 't':
114                         if (install_plugin(optarg))
115                                 error = true;
116                         break;
117                 case 'o':
118                         {
119                                 ModelVector<TraceAnalysis *> * analyses = getInstalledTraceAnalysis();
120                                 if ( analyses->size() == 0 || (*analyses)[analyses->size()-1]->option(optarg))
121                                         error = true;
122                         }
123                         break;
124                 default: /* '?' */
125                         error = true;
126                         break;
127                 }
128         }
129
130         /* Pass remaining arguments to user program */
131         params->argc = argc - (optind - 1);
132         params->argv = argv + (optind - 1);
133
134         /* Reset program name */
135         params->argv[0] = argv[0];
136
137         /* Reset (global) optind for potential use by user program */
138         optind = 1;
139
140         if (error)
141                 print_usage(argv[0], params);
142 }
143
144 int main_argc;
145 char **main_argv;
146
147 static void install_trace_analyses(ModelExecution *execution)
148 {
149         ModelVector<TraceAnalysis *> * installedanalysis=getInstalledTraceAnalysis();
150         for(unsigned int i=0;i<installedanalysis->size();i++) {
151                 TraceAnalysis * ta=(*installedanalysis)[i];
152                 ta->setExecution(execution);
153                 model->add_trace_analysis(ta);
154                 /** Call the installation event for each installed plugin */
155                 ta->actionAtInstallation();
156         }
157 }
158
159 /** The model_main function contains the main model checking loop. */
160 static void model_main()
161 {
162         struct model_params params;
163
164         param_defaults(&params);
165         register_plugins();
166
167         parse_options(&params, main_argc, main_argv);
168
169         //Initialize race detector
170         initRaceDetector();
171
172         snapshot_stack_init();
173
174         if (!model)
175           model = new ModelChecker();
176         model->setParams(params);
177         install_trace_analyses(model->get_execution());
178
179         snapshot_record(0);
180         model->run();
181         delete model;
182
183         DEBUG("Exiting\n");
184 }
185
186 /**
187  * Main function.  Just initializes snapshotting library and the
188  * snapshotting library calls the model_main function.
189  */
190 int main(int argc, char **argv)
191 {
192         main_argc = argc;
193         main_argv = argv;
194
195         /*
196          * If this printf statement is removed, CDSChecker will fail on an
197          * assert on some versions of glibc.  The first time printf is
198          * called, it allocated internal buffers.  We can't easily snapshot
199          * libc since we also use it.
200          */
201
202         printf("CDSChecker\n"
203                                  "Copyright (c) 2013 Regents of the University of California. All rights reserved.\n"
204                                  "Distributed under the GPLv2\n"
205                                  "Written by Brian Norris and Brian Demsky\n\n");
206
207         /* Configure output redirection for the model-checker */
208         redirect_output();
209
210         /* Let's jump in quickly and start running stuff */
211         snapshot_system_init(10000, 1024, 1024, 4000, &model_main);
212 }