| 
 | 1 | +/*******************************************************************\  | 
 | 2 | +
  | 
 | 3 | +Module: Initialize command line arguments  | 
 | 4 | +
  | 
 | 5 | +Author: Michael Tautschnig  | 
 | 6 | +
  | 
 | 7 | +Date: April 2016  | 
 | 8 | +
  | 
 | 9 | +\*******************************************************************/  | 
 | 10 | + | 
 | 11 | +#include <sstream>  | 
 | 12 | + | 
 | 13 | +#include <util/cprover_prefix.h>  | 
 | 14 | +#include <util/message.h>  | 
 | 15 | +#include <util/namespace.h>  | 
 | 16 | +#include <util/config.h>  | 
 | 17 | +#include <util/replace_symbol.h>  | 
 | 18 | +#include <util/symbol_table.h>  | 
 | 19 | +#include <util/prefix.h>  | 
 | 20 | + | 
 | 21 | +#include <ansi-c/ansi_c_language.h>  | 
 | 22 | + | 
 | 23 | +#include <goto-programs/goto_convert.h>  | 
 | 24 | +#include <goto-programs/goto_functions.h>  | 
 | 25 | +#include <goto-programs/remove_skip.h>  | 
 | 26 | + | 
 | 27 | +#include "model_argc_argv.h"  | 
 | 28 | + | 
 | 29 | +/*******************************************************************\  | 
 | 30 | +
  | 
 | 31 | +Function: model_argc_argv  | 
 | 32 | +
  | 
 | 33 | +  Inputs:  | 
 | 34 | +
  | 
 | 35 | + Outputs:  | 
 | 36 | +
  | 
 | 37 | + Purpose:  | 
 | 38 | +
  | 
 | 39 | +\*******************************************************************/  | 
 | 40 | + | 
 | 41 | +bool model_argc_argv(  | 
 | 42 | +  symbol_tablet &symbol_table,  | 
 | 43 | +  goto_functionst &goto_functions,  | 
 | 44 | +  unsigned max_argc,  | 
 | 45 | +  message_handlert &message_handler)  | 
 | 46 | +{  | 
 | 47 | +  messaget message(message_handler);  | 
 | 48 | +  const namespacet ns(symbol_table);  | 
 | 49 | + | 
 | 50 | +  const symbolt *init_symbol=0;  | 
 | 51 | +  if(ns.lookup(CPROVER_PREFIX "initialize", init_symbol))  | 
 | 52 | +  {  | 
 | 53 | +    message.error() << "Linking not done, missing "  | 
 | 54 | +                    << CPROVER_PREFIX "initialize" << messaget::eom;  | 
 | 55 | +    return true;  | 
 | 56 | +  }  | 
 | 57 | + | 
 | 58 | +  if(init_symbol->mode!=ID_C)  | 
 | 59 | +  {  | 
 | 60 | +    message.error() << "argc/argv modelling is C specific"  | 
 | 61 | +                    << messaget::eom;  | 
 | 62 | +    return true;  | 
 | 63 | +  }  | 
 | 64 | + | 
 | 65 | +  goto_functionst::function_mapt::iterator init_entry=  | 
 | 66 | +    goto_functions.function_map.find(CPROVER_PREFIX "initialize");  | 
 | 67 | +  assert(  | 
 | 68 | +    init_entry!=goto_functions.function_map.end() &&  | 
 | 69 | +    init_entry->second.body_available());  | 
 | 70 | + | 
 | 71 | +  goto_programt &init=init_entry->second.body;  | 
 | 72 | +  goto_programt::targett init_end=init.instructions.end();  | 
 | 73 | +  --init_end;  | 
 | 74 | +  assert(init_end->is_end_function());  | 
 | 75 | +  assert(init_end!=init.instructions.begin());  | 
 | 76 | +  --init_end;  | 
 | 77 | + | 
 | 78 | +  const symbolt &main_symbol=  | 
 | 79 | +    ns.lookup(config.main.empty()?ID_main:config.main);  | 
 | 80 | + | 
 | 81 | +  const code_typet::parameterst ¶meters=  | 
 | 82 | +    to_code_type(main_symbol.type).parameters();  | 
 | 83 | +  if(parameters.size()!=2 &&  | 
 | 84 | +     parameters.size()!=3)  | 
 | 85 | +  {  | 
 | 86 | +    message.warning() << "main expected to take 2 or 3 arguments,"  | 
 | 87 | +                      << " argc/argv instrumentation skipped"  | 
 | 88 | +                      << messaget::eom;  | 
 | 89 | +    return false;  | 
 | 90 | +  }  | 
 | 91 | + | 
 | 92 | +  // set the size of ARGV storage to 4096, which matches the minimum  | 
 | 93 | +  // guaranteed by POSIX (_POSIX_ARG_MAX):  | 
 | 94 | +  // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html  | 
 | 95 | +  std::ostringstream oss;  | 
 | 96 | +  oss <<  | 
 | 97 | +    "int ARGC;\n\  | 
 | 98 | +     char *ARGV[1];\n\  | 
 | 99 | +     void " CPROVER_PREFIX "initialize()\n\  | 
 | 100 | +     {\n\  | 
 | 101 | +	     unsigned next=0u;\n\  | 
 | 102 | +       " CPROVER_PREFIX "assume(ARGC>=1);\n\  | 
 | 103 | +       " CPROVER_PREFIX "assume(ARGC<=" << max_argc << ");\n\  | 
 | 104 | +       " CPROVER_PREFIX "thread_local static char arg_string[4096];\n\  | 
 | 105 | +       for(unsigned i=0u; i<ARGC && i<" << max_argc << "; ++i)\n\  | 
 | 106 | +       {\n\  | 
 | 107 | +         unsigned len;\n\  | 
 | 108 | +         " CPROVER_PREFIX "assume(len<4096);\n\  | 
 | 109 | +         " CPROVER_PREFIX "assume(next+len<4096);\n\  | 
 | 110 | +         " CPROVER_PREFIX "assume(arg_string[next+len]==0);\n\  | 
 | 111 | +         ARGV[i]=&(arg_string[next]);\n\  | 
 | 112 | +         next+=len+1;\n\  | 
 | 113 | +       }\n\  | 
 | 114 | +     }";  | 
 | 115 | +  std::istringstream iss(oss.str());  | 
 | 116 | + | 
 | 117 | +  ansi_c_languaget ansi_c_language;  | 
 | 118 | +  ansi_c_language.set_message_handler(message_handler);  | 
 | 119 | +  configt::ansi_ct::preprocessort pp=config.ansi_c.preprocessor;  | 
 | 120 | +  config.ansi_c.preprocessor=configt::ansi_ct::preprocessort::NONE;  | 
 | 121 | +  ansi_c_language.parse(iss, "");  | 
 | 122 | +  config.ansi_c.preprocessor=pp;  | 
 | 123 | + | 
 | 124 | +  symbol_tablet tmp_symbol_table;  | 
 | 125 | +  ansi_c_language.typecheck(tmp_symbol_table, "<built-in-library>");  | 
 | 126 | + | 
 | 127 | +  goto_programt tmp;  | 
 | 128 | +  exprt value=nil_exprt();  | 
 | 129 | +  // locate the body of the newly built initialize function as well  | 
 | 130 | +  // as any additional declarations we might need; the body will then  | 
 | 131 | +  // be converted and appended to the existing initialize function  | 
 | 132 | +  forall_symbols(it, tmp_symbol_table.symbols)  | 
 | 133 | +  {  | 
 | 134 | +    // add __CPROVER_assume if necessary (it might exist already)  | 
 | 135 | +    if(it->first==CPROVER_PREFIX "assume")  | 
 | 136 | +      symbol_table.add(it->second);  | 
 | 137 | +    else if(it->first==CPROVER_PREFIX "initialize")  | 
 | 138 | +    {  | 
 | 139 | +      value=it->second.value;  | 
 | 140 | + | 
 | 141 | +      replace_symbolt replace;  | 
 | 142 | +      replace.insert("ARGC", ns.lookup("argc'").symbol_expr());  | 
 | 143 | +      replace.insert("ARGV", ns.lookup("argv'").symbol_expr());  | 
 | 144 | +      replace(value);  | 
 | 145 | +    }  | 
 | 146 | +    else if(has_prefix(id2string(it->first),  | 
 | 147 | +                       CPROVER_PREFIX "initialize::") &&  | 
 | 148 | +            symbol_table.add(it->second))  | 
 | 149 | +      assert(false);  | 
 | 150 | +  }  | 
 | 151 | + | 
 | 152 | +  assert(value.is_not_nil());  | 
 | 153 | +  goto_convert(  | 
 | 154 | +    to_code(value),  | 
 | 155 | +    symbol_table,  | 
 | 156 | +    tmp,  | 
 | 157 | +    message_handler);  | 
 | 158 | +  Forall_goto_program_instructions(it, tmp)  | 
 | 159 | +  {  | 
 | 160 | +    it->source_location.set_file("<built-in-library>");  | 
 | 161 | +    it->function=CPROVER_PREFIX "initialize";  | 
 | 162 | +  }  | 
 | 163 | +  init.insert_before_swap(init_end, tmp);  | 
 | 164 | + | 
 | 165 | +  // update counters etc.  | 
 | 166 | +  remove_skip(init);  | 
 | 167 | +  init.compute_loop_numbers();  | 
 | 168 | +  goto_functions.update();  | 
 | 169 | + | 
 | 170 | +  return false;  | 
 | 171 | +}  | 
 | 172 | + | 
0 commit comments