cprover
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/config.h>
15 #include <util/find_symbols.h>
16 #include <util/namespace.h>
17 #include <util/std_types.h>
18 #include <util/symbol_table.h>
19 
20 #include "static_lifetime_init.h"
21 
22 static void get_symbols(
23  const namespacet &ns,
24  const symbolt &in_symbol,
25  find_symbols_sett &dest)
26 {
27  std::vector<const symbolt *> working_set;
28 
29  working_set.push_back(&in_symbol);
30 
31  while(!working_set.empty())
32  {
33  const symbolt *current_symbol_ptr = working_set.back();
34  working_set.pop_back();
35  const symbolt &symbol = *current_symbol_ptr;
36 
37  if(!dest.insert(symbol.name).second)
38  continue;
39 
40  find_symbols_sett new_symbols;
41 
42  find_type_and_expr_symbols(symbol.type, new_symbols);
43  find_type_and_expr_symbols(symbol.value, new_symbols);
44 
45  for(const auto &s : new_symbols)
46  working_set.push_back(&ns.lookup(s));
47 
48  if(symbol.type.id() == ID_code)
49  {
50  const code_typet &code_type = to_code_type(symbol.type);
51  const code_typet::parameterst &parameters = code_type.parameters();
52 
53  for(const auto &p : parameters)
54  {
55  const symbolt *s;
56  // identifiers for prototypes need not exist
57  if(!ns.lookup(p.get_identifier(), s))
58  working_set.push_back(s);
59  }
60  }
61  }
62 }
63 
78  symbol_tablet &symbol_table,
79  message_handlert &mh,
80  const bool keep_file_local)
81 {
82  namespacet ns(symbol_table);
83  find_symbols_sett exported;
84  messaget log(mh);
85 
86  // we retain certain special ones
87  find_symbols_sett special;
88  special.insert("argc'");
89  special.insert("argv'");
90  special.insert("envp'");
91  special.insert("envp_size'");
92  special.insert(CPROVER_PREFIX "memory");
93  special.insert(INITIALIZE_FUNCTION);
94  special.insert(CPROVER_PREFIX "malloc_size");
95  special.insert(CPROVER_PREFIX "deallocated");
96  special.insert(CPROVER_PREFIX "dead_object");
97  special.insert(CPROVER_PREFIX "rounding_mode");
98  special.insert("__new");
99  special.insert("__new_array");
100  special.insert("__placement_new");
101  special.insert("__placement_new_array");
102  special.insert("__delete");
103  special.insert("__delete_array");
104 
105  for(symbol_tablet::symbolst::const_iterator
106  it=symbol_table.symbols.begin();
107  it!=symbol_table.symbols.end();
108  it++)
109  {
110  // already marked?
111  if(exported.find(it->first)!=exported.end())
112  continue;
113 
114  // not marked yet
115  const symbolt &symbol=it->second;
116 
117  if(special.find(symbol.name)!=special.end())
118  {
119  get_symbols(ns, symbol, exported);
120  continue;
121  }
122 
123  bool is_function=symbol.type.id()==ID_code;
124  bool is_file_local=symbol.is_file_local;
125  bool is_type=symbol.is_type;
126  bool has_body=symbol.value.is_not_nil();
127  bool has_initializer = symbol.value.is_not_nil();
128 
129  // __attribute__((constructor)), __attribute__((destructor))
130  if(symbol.mode==ID_C && is_function && is_file_local)
131  {
132  const code_typet &code_type=to_code_type(symbol.type);
133  if(code_type.return_type().id()==ID_constructor ||
134  code_type.return_type().id()==ID_destructor)
135  is_file_local=false;
136  }
137 
138  if(is_type || symbol.is_macro)
139  {
140  // never EXPORTED by itself
141  }
142  else if(is_function)
143  {
144  // body? not local (i.e., "static")?
145  if(
146  has_body &&
147  (!is_file_local ||
148  (config.main.has_value() && symbol.base_name == config.main.value())))
149  {
150  get_symbols(ns, symbol, exported);
151  }
152  else if(has_body && is_file_local && keep_file_local)
153  {
154  get_symbols(ns, symbol, exported);
155  }
156  }
157  else
158  {
159  // 'extern' symbols are only exported if there
160  // is an initializer.
161  if((has_initializer || !symbol.is_extern) &&
162  !is_file_local)
163  {
164  get_symbols(ns, symbol, exported);
165  }
166  }
167  }
168 
169  // remove all that are _not_ exported!
170  for(symbol_tablet::symbolst::const_iterator
171  it=symbol_table.symbols.begin();
172  it!=symbol_table.symbols.end();
173  ) // no it++
174  {
175  if(exported.find(it->first)==exported.end())
176  {
177  symbol_tablet::symbolst::const_iterator next=std::next(it);
178  symbol_table.erase(it);
179  it=next;
180  }
181  else
182  {
183  it++;
184  }
185  }
186 }
Base type of functions.
Definition: std_types.h:744
std::vector< parametert > parameterst
Definition: std_types.h:746
const typet & return_type() const
Definition: std_types.h:850
const parameterst & parameters() const
Definition: std_types.h:860
optionalt< std::string > main
Definition: config.h:261
bool is_not_nil() const
Definition: irep.h:391
const irep_idt & id() const
Definition: irep.h:407
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:155
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:92
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:140
const symbolst & symbols
Read-only field, used to look up symbols given their names.
The symbol table.
Definition: symbol_table.h:20
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_extern
Definition: symbol.h:66
bool is_macro
Definition: symbol.h:61
bool is_file_local
Definition: symbol.h:66
bool is_type
Definition: symbol.h:61
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
exprt value
Initial value of symbol.
Definition: symbol.h:34
irep_idt mode
Language mode.
Definition: symbol.h:49
configt config
Definition: config.cpp:24
#define CPROVER_PREFIX
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest)
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:21
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.
static void get_symbols(const namespacet &ns, const symbolt &in_symbol, find_symbols_sett &dest)
Remove symbols that are internal only.
#define INITIALIZE_FUNCTION
Pre-defined types.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:949
Author: Diffblue Ltd.