CBMC
remove_internal_symbols.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Remove symbols that are internal only
4 
5 Author: Daniel Kroening
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <util/c_types.h>
15 #include <util/config.h>
16 #include <util/find_symbols.h>
17 #include <util/message.h>
18 #include <util/namespace.h>
19 #include <util/std_types.h>
20 #include <util/symbol_table.h>
21 
23 
24 #include "static_lifetime_init.h"
25 
26 static void get_symbols(
27  const namespacet &ns,
28  const symbolt &in_symbol,
29  find_symbols_sett &dest)
30 {
31  std::vector<const symbolt *> working_set;
32 
33  working_set.push_back(&in_symbol);
34 
35  while(!working_set.empty())
36  {
37  const symbolt *current_symbol_ptr = working_set.back();
38  working_set.pop_back();
39  const symbolt &symbol = *current_symbol_ptr;
40 
41  if(!dest.insert(symbol.name).second)
42  continue;
43 
44  find_symbols_sett new_symbols;
45 
46  find_type_and_expr_symbols(symbol.type, new_symbols);
47  find_type_and_expr_symbols(symbol.value, new_symbols);
48 
49  for(const auto &s : new_symbols)
50  working_set.push_back(&ns.lookup(s));
51 
52  if(symbol.type.id() == ID_code)
53  {
54  const code_typet &code_type = to_code_type(symbol.type);
55  const code_typet::parameterst &parameters = code_type.parameters();
56 
57  for(const auto &p : parameters)
58  {
59  const symbolt *s;
60  // identifiers for prototypes need not exist
61  if(!ns.lookup(p.get_identifier(), s))
62  working_set.push_back(s);
63  }
64 
65  // check for contract definitions
66  const code_with_contract_typet &maybe_contract =
67  to_code_with_contract_type(code_type);
68 
69  find_symbols_sett new_symbols;
70  for(const exprt &a : maybe_contract.assigns())
71  find_type_and_expr_symbols(a, new_symbols);
72  for(const exprt &e : maybe_contract.ensures())
73  find_type_and_expr_symbols(e, new_symbols);
74  for(const exprt &e : maybe_contract.ensures_contract())
75  find_type_and_expr_symbols(e, new_symbols);
76  for(const exprt &r : maybe_contract.requires())
77  find_type_and_expr_symbols(r, new_symbols);
78  for(const exprt &r : maybe_contract.requires_contract())
79  find_type_and_expr_symbols(r, new_symbols);
80 
81  for(const auto &s : new_symbols)
82  {
83  // keep functions called in contracts within scope.
84  // should we keep local variables from the contract as well?
85  const symbolt *new_symbol = nullptr;
86  if(!ns.lookup(s, new_symbol))
87  {
88  if(new_symbol->type.id() == ID_code)
89  {
90  working_set.push_back(new_symbol);
91  }
92  }
93  }
94  }
95  }
96 }
97 
112  symbol_tablet &symbol_table,
113  message_handlert &mh,
114  const bool keep_file_local)
115 {
116  remove_internal_symbols(symbol_table, mh, keep_file_local, {});
117 }
118 
135  symbol_tablet &symbol_table,
136  message_handlert &mh,
137  const bool keep_file_local,
138  const std::set<irep_idt> &keep)
139 {
140  namespacet ns(symbol_table);
141  find_symbols_sett exported;
142  messaget log(mh);
143 
144  // we retain certain special ones
145  find_symbols_sett special;
146  special.insert("argc'");
147  special.insert("argv'");
148  special.insert("envp'");
149  special.insert("envp_size'");
150  special.insert(CPROVER_PREFIX "memory");
151  special.insert(INITIALIZE_FUNCTION);
152  special.insert(CPROVER_PREFIX "deallocated");
153  special.insert(CPROVER_PREFIX "dead_object");
154  special.insert(CPROVER_PREFIX "assignable");
155  special.insert(CPROVER_PREFIX "object_upto");
156  special.insert(CPROVER_PREFIX "object_from");
157  special.insert(CPROVER_PREFIX "object_whole");
158  special.insert(rounding_mode_identifier());
159  special.insert("__new");
160  special.insert("__new_array");
161  special.insert("__placement_new");
162  special.insert("__placement_new_array");
163  special.insert("__delete");
164  special.insert("__delete_array");
165  // plus any extra symbols we wish to keep
166  special.insert(keep.begin(), keep.end());
167 
168  for(symbol_tablet::symbolst::const_iterator
169  it=symbol_table.symbols.begin();
170  it!=symbol_table.symbols.end();
171  it++)
172  {
173  // already marked?
174  if(exported.find(it->first)!=exported.end())
175  continue;
176 
177  // not marked yet
178  const symbolt &symbol=it->second;
179 
180  if(special.find(symbol.name)!=special.end())
181  {
182  get_symbols(ns, symbol, exported);
183  continue;
184  }
185 
186  bool is_function=symbol.type.id()==ID_code;
187  bool is_file_local=symbol.is_file_local;
188  bool is_type=symbol.is_type;
189  bool has_body=symbol.value.is_not_nil();
190  bool has_initializer = symbol.value.is_not_nil();
191  bool is_contract = is_function && symbol.is_property;
192 
193  // __attribute__((constructor)), __attribute__((destructor))
194  if(symbol.mode==ID_C && is_function && is_file_local)
195  {
196  const code_typet &code_type=to_code_type(symbol.type);
197  if(code_type.return_type().id()==ID_constructor ||
198  code_type.return_type().id()==ID_destructor)
199  is_file_local=false;
200  }
201 
202  if(is_type || symbol.is_macro)
203  {
204  // never EXPORTED by itself
205  }
206  else if(is_function)
207  {
208  // body? not local (i.e., "static")?
209  if(
210  has_body &&
211  (!is_file_local ||
212  (config.main.has_value() && symbol.base_name == config.main.value())))
213  {
214  get_symbols(ns, symbol, exported);
215  }
216  else if(has_body && is_file_local && keep_file_local)
217  {
218  get_symbols(ns, symbol, exported);
219  }
220  else if(is_contract)
221  get_symbols(ns, symbol, exported);
222  }
223  else
224  {
225  // 'extern' symbols are only exported if there
226  // is an initializer.
227  if((has_initializer || !symbol.is_extern) &&
228  !is_file_local)
229  {
230  get_symbols(ns, symbol, exported);
231  }
232  }
233  }
234 
235  // remove all that are _not_ exported!
236  for(symbol_tablet::symbolst::const_iterator
237  it=symbol_table.symbols.begin();
238  it!=symbol_table.symbols.end();
239  ) // no it++
240  {
241  if(exported.find(it->first)==exported.end())
242  {
243  symbol_tablet::symbolst::const_iterator next=std::next(it);
244  symbol_table.erase(it);
245  it=next;
246  }
247  else
248  {
249  it++;
250  }
251  }
252 }
messaget
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
to_code_with_contract_type
const code_with_contract_typet & to_code_with_contract_type(const typet &type)
Cast a typet to a code_with_contract_typet.
Definition: c_types.h:447
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
find_type_and_expr_symbols
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest)
Find identifiers of the sub expressions with id ID_symbol, considering both free and bound variables,...
Definition: find_symbols.cpp:283
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
configt::main
optionalt< std::string > main
Definition: config.h:341
exprt
Base class for all expressions.
Definition: expr.h:55
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
code_with_contract_typet::ensures_contract
const exprt::operandst & ensures_contract() const
Definition: c_types.h:407
code_with_contract_typet::assigns
const exprt::operandst & assigns() const
Definition: c_types.h:376
namespace.h
remove_internal_symbols
void remove_internal_symbols(symbol_tablet &symbol_table, message_handlert &mh, const bool keep_file_local)
Removes internal symbols from a symbol table A symbol is EXPORTED if it is a.
Definition: remove_internal_symbols.cpp:111
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
symbolt::mode
irep_idt mode
Language mode.
Definition: symbol.h:49
find_symbols.h
std_types.h
INITIALIZE_FUNCTION
#define INITIALIZE_FUNCTION
Definition: static_lifetime_init.h:22
code_typet
Base type of functions.
Definition: std_types.h:538
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
get_symbols
static void get_symbols(const namespacet &ns, const symbolt &in_symbol, find_symbols_sett &dest)
Definition: remove_internal_symbols.cpp:26
rounding_mode_identifier
irep_idt rounding_mode_identifier()
Return the identifier of the program symbol used to store the current rounding mode.
Definition: adjust_float_expressions.cpp:24
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
code_with_contract_typet::requires_contract
const exprt::operandst & requires_contract() const
Definition: c_types.h:386
config
configt config
Definition: config.cpp:25
code_with_contract_typet
Definition: c_types.h:357
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
symbolt::is_extern
bool is_extern
Definition: symbol.h:66
find_symbols_sett
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:21
symbolt
Symbol table entry.
Definition: symbol.h:27
code_with_contract_typet::ensures
const exprt::operandst & ensures() const
Definition: c_types.h:418
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
symbolt::is_type
bool is_type
Definition: symbol.h:61
remove_internal_symbols.h
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
config.h
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
symbol_tablet::erase
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
Definition: symbol_table.cpp:90
symbolt::is_file_local
bool is_file_local
Definition: symbol.h:66
r
static int8_t r
Definition: irep_hash.h:60
static_lifetime_init.h
symbol_table.h
Author: Diffblue Ltd.
message.h
adjust_float_expressions.h
c_types.h
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
code_with_contract_typet::requires
const exprt::operandst & requires() const
Definition: c_types.h:397
symbolt::is_property
bool is_property
Definition: symbol.h:62