CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
goto_harness_parse_options.cpp
Go to the documentation of this file.
1/******************************************************************\
2
3Module: goto_harness_parse_options
4
5Author: Diffblue Ltd.
6
7\******************************************************************/
8
10
11#include <util/config.h>
13#include <util/exit_codes.h>
14#include <util/help_formatter.h>
15#include <util/invariant.h>
16#include <util/suffix.h>
17#include <util/version.h>
18
22
24
28
29#include <algorithm>
30#include <fstream>
31#include <iostream>
32#include <set>
33#include <string>
34#include <unordered_set>
35#include <utility>
36
37std::unordered_set<irep_idt>
39{
40 auto symbols = std::unordered_set<irep_idt>{};
41 std::transform(
42 goto_model.get_symbol_table().begin(),
43 goto_model.get_symbol_table().end(),
44 std::inserter(symbols, symbols.end()),
45 [](const std::pair<const irep_idt, symbolt> &key_value_pair) {
46 return key_value_pair.first;
47 });
48 return symbols;
49}
50
53 const std::unordered_set<irep_idt> &goto_model_without_harness_symbols)
54{
56 {
57 auto &symbol =
58 goto_model_with_harness.symbol_table.get_writeable_ref(symbol_id);
59 if(symbol.is_function())
60 {
61 // We don’t want bodies of functions that already existed in the
62 // symbol table (i.e. not generated by us)
64 if(symbol.is_file_local)
65 {
66 goto_model_with_harness.symbol_table.remove(symbol_id);
67 }
68 }
69 else if(!symbol.is_type && symbol.is_file_local)
70 {
71 // We don’t want file local symbols from an existing goto model
72 // except types / typedefs, which also apparently get marked
73 // file local sometimes.
74 goto_model_with_harness.symbol_table.remove(symbol_id);
75 }
76 else if(!symbol.is_type && symbol.is_static_lifetime)
77 {
78 // if it has static lifetime and is *not* a type it is a global variable
79 // We keep around other global variables in case we want to initialise
80 // them, but mark them as extern so we don't duplicate their definitions
81 symbol.value = nil_exprt{};
82 symbol.is_extern = true;
83 }
84 }
85}
86
87// The basic idea is that this module is handling the following
88// sequence of events:
89// 1. Initialise a goto-model by parsing an input (goto) binary
90// 2. Initialise the harness generator (with some config) that will handle
91// the mutation of the goto-model. The generator should create a new
92// function that can be called by `cbmc --function`. The generated function
93// should implement the behaviour of the harness (What exactly this means
94// depends on the configuration)
95// 3. Write the end result of that process to the output binary
96
98{
99 if(cmdline.isset("version"))
100 {
101 std::cout << CBMC_VERSION << '\n';
103 }
104
106 auto factory = make_factory();
107
109
110 // This just sets up the defaults (and would interpret options such as --32).
112
113 // Normally we would register language front-ends here but as goto-harness
114 // only works on goto binaries, we don't need to
115
116 // Read goto binary into goto-model
119 if(!read_goto_binary_result.has_value())
120 {
121 throw deserialization_exceptiont{"failed to read goto program from file '" +
122 got_harness_config.in_file + "'"};
123 }
124 auto goto_model = std::move(read_goto_binary_result.value());
127
128 // This has to be called after the defaults are set up (as per the
129 // config.set(cmdline) above) otherwise, e.g. the architecture specification
130 // will be unknown.
131 config.set_from_symbol_table(goto_model.symbol_table);
132
133 if(goto_model.symbol_table.has_symbol(
134 got_harness_config.harness_function_name))
135 {
137 "harness function `" +
138 id2string(got_harness_config.harness_function_name) +
139 "` already in "
140 "the symbol table",
142 }
143
144 // Initialise harness generator
145 auto harness_generator = factory.factory(
146 got_harness_config.harness_type, factory_options, goto_model);
148
149 harness_generator->generate(
150 goto_model, got_harness_config.harness_function_name);
151
152 if(has_suffix(got_harness_config.out_file, ".c"))
153 {
155 auto harness_out = std::ofstream{got_harness_config.out_file};
156 dump_c(
157 goto_model.goto_functions,
158 true,
159 true,
160 false,
161 namespacet{goto_model.get_symbol_table()},
163 }
164 else
165 {
167 got_harness_config.out_file, goto_model, log.get_message_handler());
168 }
169
171}
172
174{
175 std::cout << '\n'
176 << banner_string("Goto-Harness", CBMC_VERSION) << '\n'
177 << align_center_with_border("Copyright (C) 2019") << '\n'
178 << align_center_with_border("Diffblue Ltd.") << '\n'
179 << align_center_with_border("info@diffblue.com") << '\n';
180
181 // clang-format off
182 std::cout << help_formatter(
183 "\n"
184 "Usage: \tPurpose:\n"
185 "\n"
186 " {bgoto-harness} [{y-?}] [{y-h}] [{y--help}] \t show this help\n"
187 " {bgoto-harness} {y--version} \t show version and exit\n"
188 " {bgoto-harness} {uin} {uout} {y--harness-function-name} {uname}"
189 " {y--harness-type} {uharness-type} [harness options]\n"
190 "\n"
191 " {uin} \t goto binary to read from\n"
192 " {uout} \t file to write the harness to; the harness is printed as C"
193 " code, if {uout} has a .c suffix, else a goto binary including the harness"
194 " is generated\n"
195 " {y--harness-function-name} {uname} \t the name of the harness function to"
196 " generate\n"
197 " {y--harness-type} {utype} \t one of the harness types listed below\n"
198 "\n"
200 "\n"
202 "\n");
203 // clang-format on
204}
205
207 int argc,
208 const char *argv[])
210 argc,
211 argv,
212 std::string("GOTO-HARNESS ") + CBMC_VERSION}
213{
214}
215
218{
220
221 // This just checks the positional arguments to be 2.
222 // Options are not in .args
223 if(cmdline.args.size() != 2)
224 {
225 help();
227 "need to specify both input and output file names (may be "
228 "the same)",
229 "<in goto binary> <output C file or goto binary>"};
230 }
231
232 goto_harness_config.in_file = cmdline.args[0];
233 goto_harness_config.out_file = cmdline.args[1];
234
236 {
238 "required option not set", "--" GOTO_HARNESS_GENERATOR_TYPE_OPT};
239 }
240 goto_harness_config.harness_type =
242
243 // Read the name of the harness function to generate
245 {
247 "required option not set",
249 }
250 goto_harness_config.harness_function_name = {
252
253 return goto_harness_config;
254}
255
257{
258 auto factory = goto_harness_generator_factoryt{};
259 factory.register_generator("call-function", [this]() {
260 return std::make_unique<function_call_harness_generatort>(
262 });
263
264 factory.register_generator("initialize-with-memory-snapshot", [this]() {
265 return std::make_unique<memory_snapshot_harness_generatort>(
267 });
268
269 return factory;
270}
271
274{
275 auto const common_options =
276 std::set<std::string>{"version",
279
281
282 for(auto const &option : cmdline.option_names())
283 {
284 if(common_options.find(option) == common_options.end())
285 {
286 factory_options.insert({option, cmdline.get_values(option.c_str())});
287 }
288 }
289
290 return factory_options;
291}
configt config
Definition config.cpp:25
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
std::string get_value(char option) const
Definition cmdline.cpp:48
virtual bool isset(char option) const
Definition cmdline.cpp:30
argst args
Definition cmdline.h:154
option_namest option_names() const
Pseudo-object that can be used to iterate over options in this cmdlinet (should not outlive this)
Definition cmdline.cpp:171
const std::list< std::string > & get_values(const std::string &option) const
Definition cmdline.cpp:119
bool set(const cmdlinet &cmdline)
Definition config.cpp:863
void set_from_symbol_table(const symbol_table_baset &)
Definition config.cpp:1357
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
helper to select harness type by name.
std::map< std::string, std::list< std::string > > generator_optionst
void register_generator(std::string generator_name, build_generatort build_generator)
register a new goto-harness generator with the given name.
goto_harness_configt handle_common_options()
Handle command line arguments that are common to all harness generators.
goto_harness_parse_optionst(int argc, const char *argv[])
goto_harness_generator_factoryt make_factory()
Setup the generator factory.
goto_harness_generator_factoryt::generator_optionst collect_generate_factory_options()
Gather all the options that are not handled by handle_common_options().
const symbol_tablet & get_symbol_table() const override
Accessor to get the symbol table.
Definition goto_model.h:84
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
message_handlert & get_message_handler()
Definition message.h:183
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
The NIL expression.
Definition std_expr.h:3208
ui_message_handlert ui_message_handler
void dump_c(const goto_functionst &src, const bool use_system_headers, const bool use_all_headers, const bool include_harness, const namespacet &ns, std::ostream &out)
Definition dump_c.cpp:1668
Dump C from Goto Program.
Document and give macros for the exit codes of CPROVER binaries.
#define CPROVER_EXIT_SUCCESS
Success indicates the required analysis has been performed without error.
Definition exit_codes.h:16
#define FUNCTION_HARNESS_GENERATOR_HELP
#define GOTO_HARNESS_GENERATOR_TYPE_OPT
#define GOTO_HARNESS_GENERATOR_HARNESS_FUNCTION_NAME_OPT
std::unordered_set< irep_idt > get_symbol_names_from_goto_model(const goto_modelt &goto_model)
static void filter_goto_model(goto_modelt &goto_model_with_harness, const std::unordered_set< irep_idt > &goto_model_without_harness_symbols)
#define GOTO_HARNESS_OPTIONS
Symbol Table + CFG.
Help Formatter.
static help_formattert help_formatter(const std::string &s)
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
#define MEMORY_SNAPSHOT_HARNESS_GENERATOR_HELP
STL namespace.
std::string align_center_with_border(const std::string &text)
Utility for displaying help centered messages borderered by "* *".
std::string banner_string(const std::string &front_end, const std::string &version)
static bool read_goto_binary(const std::string &filename, symbol_tablet &, goto_functionst &, message_handlert &)
Read a goto binary from a file, but do not update config.
Read Goto Programs.
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
bool has_suffix(const std::string &s, const std::string &suffix)
Definition suffix.h:17
const char * CBMC_VERSION
static void write_goto_binary(std::ostream &out, const symbol_table_baset &symbol_table, const goto_functionst &goto_functions, irep_serializationt &irepconverter)
Writes a goto program to disc, using goto binary format.
Write GOTO binaries.