CBMC
system_library_symbols.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Goto Programs
4 
5 Author: Thomas Kiley
6 
7 \*******************************************************************/
8 
11 
12 #include "system_library_symbols.h"
13 #include <util/cprover_prefix.h>
14 #include <util/prefix.h>
15 #include <util/suffix.h>
16 #include <util/symbol.h>
17 #include <sstream>
18 
20  use_all_headers(false)
21 {
22  if(init)
24 }
25 
30 {
31  // ctype.h
32  std::list<irep_idt> ctype_syms=
33  {
34  "isalnum", "isalpha", "isblank", "iscntrl", "isdigit", "isgraph",
35  "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit",
36  "tolower", "toupper"
37  };
38  add_to_system_library("ctype.h", ctype_syms);
39 
40  // fcntl.h
41  std::list<irep_idt> fcntl_syms=
42  {
43  "creat", "fcntl", "open"
44  };
45  add_to_system_library("fcntl.h", fcntl_syms);
46 
47  // locale.h
48  std::list<irep_idt> locale_syms=
49  {
50  "setlocale"
51  };
52  add_to_system_library("locale.h", locale_syms);
53 
54  // math.h
55  std::list<irep_idt> math_syms=
56  {
57  "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh",
58  "cbrt", "ceil", "copysign", "cos", "cosh", "erf", "erfc", "exp",
59  "exp2", "expm1", "fabs", "fdim", "floor", "fma", "fmax", "fmin",
60  "fmod", "fpclassify", "fpclassifyl", "fpclassifyf", "frexp",
61  "hypot", "ilogb", "isfinite", "isinf", "isnan", "isnormal",
62  "j0", "j1", "jn", "ldexp", "lgamma", "llrint", "llround", "log",
63  "log10", "log1p", "log2", "logb", "lrint", "lround", "modf", "nan",
64  "nearbyint", "nextafter", "pow", "remainder", "remquo", "rint",
65  "round", "scalbln", "scalbn", "signbit", "sin", "sinh", "sqrt",
66  "tan", "tanh", "tgamma", "trunc", "y0", "y1", "yn", "isinff",
67  "isinfl", "isnanf", "isnanl"
68  };
69  add_to_system_library("math.h", math_syms);
70 
71  // for some reason the math functions can sometimes be prefixed with
72  // a double underscore
73  std::list<irep_idt> underscore_math_syms;
74  for(const irep_idt &math_sym : math_syms)
75  {
76  std::ostringstream underscore_id;
77  underscore_id << "__" << math_sym;
78  underscore_math_syms.push_back(irep_idt(underscore_id.str()));
79  }
80  add_to_system_library("math.h", underscore_math_syms);
81 
82  // pthread.h
83  std::list<irep_idt> pthread_syms=
84  {
85  "pthread_cleanup_pop", "pthread_cleanup_push",
86  "pthread_cond_broadcast", "pthread_cond_destroy",
87  "pthread_cond_init", "pthread_cond_signal",
88  "pthread_cond_timedwait", "pthread_cond_wait", "pthread_create",
89  "pthread_detach", "pthread_equal", "pthread_exit",
90  "pthread_getspecific", "pthread_join", "pthread_key_delete",
91  "pthread_mutex_destroy", "pthread_mutex_init",
92  "pthread_mutex_lock", "pthread_mutex_trylock",
93  "pthread_mutex_unlock", "pthread_once", "pthread_rwlock_destroy",
94  "pthread_rwlock_init", "pthread_rwlock_rdlock",
95  "pthread_rwlock_unlock", "pthread_rwlock_wrlock",
96  "pthread_rwlockattr_destroy", "pthread_rwlockattr_getpshared",
97  "pthread_rwlockattr_init", "pthread_rwlockattr_setpshared",
98  "pthread_self", "pthread_setspecific",
99  /* non-public struct types */
100  "tag-__pthread_internal_list", "tag-__pthread_mutex_s",
101  "pthread_mutex_t"
102  };
103  add_to_system_library("pthread.h", pthread_syms);
104 
105  // setjmp.h
106  std::list<irep_idt> setjmp_syms=
107  {
108  "_longjmp", "_setjmp", "jmp_buf", "longjmp", "longjmperror", "setjmp",
109  "siglongjmp", "sigsetjmp"
110  };
111  add_to_system_library("setjmp.h", setjmp_syms);
112 
113  // stdio.h
114  std::list<irep_idt> stdio_syms=
115  {
116  "asprintf", "clearerr", "fclose", "fdopen", "feof", "ferror",
117  "fflush", "fgetc", "fgetln", "fgetpos", "fgets", "fgetwc",
118  "fgetws", "fileno", "fopen", "fprintf", "fpurge", "fputc",
119  "fputs", "fputwc", "fputws", "fread", "freopen", "fropen",
120  "fscanf", "fseek", "fsetpos", "ftell", "funopen", "fwide",
121  "fwopen", "fwprintf", "fwrite", "getc", "getchar", "getdelim",
122  "getline", "gets", "getw", "getwc", "getwchar", "mkdtemp",
123  "mkstemp", "mktemp", "perror", "printf", "putc", "putchar",
124  "puts", "putw", "putwc", "putwchar", "remove", "rewind", "scanf",
125  "setbuf", "setbuffer", "setlinebuf", "setvbuf", "snprintf",
126  "sprintf", "sscanf", "swprintf", "sys_errlist",
127  "sys_nerr", "tempnam", "tmpfile", "tmpnam", "ungetc", "ungetwc",
128  "vasprintf", "vfprintf", "vfscanf", "vfwprintf", "vprintf",
129  "vscanf", "vsnprintf", "vsprintf", "vsscanf", "vswprintf",
130  "vwprintf", "wprintf",
131  /* non-public struct types */
132  "tag-__sFILE", "tag-__sbuf", // OS X
133  "tag-_IO_FILE", "tag-_IO_marker", // Linux
134  };
135  add_to_system_library("stdio.h", stdio_syms);
136 
137  // stdlib.h
138  std::list<irep_idt> stdlib_syms=
139  {
140  "abort", "abs", "atexit", "atof", "atoi", "atol", "atoll",
141  "bsearch", "calloc", "div", "exit", "free", "getenv", "labs",
142  "ldiv", "llabs", "lldiv", "malloc", "mblen", "mbstowcs", "mbtowc",
143  "qsort", "rand", "realloc", "srand", "strtod", "strtof", "strtol",
144  "strtold", "strtoll", "strtoul", "strtoull", "system", "wcstombs",
145  "wctomb"
146  };
147  add_to_system_library("stdlib.h", stdlib_syms);
148 
149  // string.h
150  std::list<irep_idt> string_syms=
151  {
152  "strcat", "strncat", "strchr", "strrchr", "strcmp", "strncmp",
153  "strcpy", "strncpy", "strerror", "strlen", "strpbrk", "strspn",
154  "strcspn", "strstr", "strtok", "strcasecmp", "strncasecmp", "strdup",
155  "memset"
156  };
157  add_to_system_library("string.h", string_syms);
158 
159  // time.h
160  std::list<irep_idt> time_syms=
161  {
162  "asctime", "asctime_r", "ctime", "ctime_r", "difftime", "gmtime",
163  "gmtime_r", "localtime", "localtime_r", "mktime", "strftime",
164  /* non-public struct types */
165  "tag-timespec", "tag-timeval", "tag-tm"
166  };
167  add_to_system_library("time.h", time_syms);
168 
169  // unistd.h
170  std::list<irep_idt> unistd_syms=
171  {
172  "_exit", "access", "alarm", "chdir", "chown", "close", "dup",
173  "dup2", "execl", "execle", "execlp", "execv", "execve", "execvp",
174  "fork", "fpathconf", "getcwd", "getegid", "geteuid", "getgid",
175  "getgroups", "getlogin", "getpgrp", "getpid", "getppid", "getuid",
176  "isatty", "link", "lseek", "pathconf", "pause", "pipe", "read",
177  "rmdir", "setgid", "setpgid", "setsid", "setuid", "sleep",
178  "sysconf", "tcgetpgrp", "tcsetpgrp", "ttyname", "ttyname_r",
179  "unlink", "write"
180  };
181  add_to_system_library("unistd.h", unistd_syms);
182 
183  // sys/select.h
184  std::list<irep_idt> sys_select_syms=
185  {
186  "select",
187  /* non-public struct types */
188  "fd_set"
189  };
190  add_to_system_library("sys/select.h", sys_select_syms);
191 
192  // sys/socket.h
193  std::list<irep_idt> sys_socket_syms=
194  {
195  "accept", "bind", "connect",
196  /* non-public struct types */
197  "tag-sockaddr"
198  };
199  add_to_system_library("sys/socket.h", sys_socket_syms);
200 
201  // sys/stat.h
202  std::list<irep_idt> sys_stat_syms=
203  {
204  "fstat", "lstat", "stat",
205  /* non-public struct types */
206  "tag-stat"
207  };
208  add_to_system_library("sys/stat.h", sys_stat_syms);
209 
210  std::list<irep_idt> fenv_syms=
211  {
212  "fenv_t", "fexcept_t", "feclearexcept", "fegetexceptflag",
213  "feraiseexcept", "fesetexceptflag", "fetestexcept",
214  "fegetround", "fesetround", "fegetenv", "feholdexcept",
215  "fesetenv", "feupdateenv"
216  };
217  add_to_system_library("fenv.h", fenv_syms);
218 
219  std::list<irep_idt> errno_syms=
220  {
221  "__error", "__errno_location", "__errno"
222  };
223  add_to_system_library("errno.h", errno_syms);
224 
225 #if 0
226  // sys/types.h
227  std::list<irep_idt> sys_types_syms=
228  {
229  };
230  add_to_system_library("sys/types.h", sys_types_syms);
231 #endif
232 
233  // sys/wait.h
234  std::list<irep_idt> sys_wait_syms=
235  {
236  "wait", "waitpid"
237  };
238  add_to_system_library("sys/wait.h", sys_wait_syms);
239 }
240 
246  irep_idt header_file,
247  std::list<irep_idt> symbols)
248 {
249  for(const irep_idt &symbol : symbols)
250  {
251  system_library_map[symbol]=header_file;
252  }
253 }
254 
261  const symbolt &symbol,
262  std::set<std::string> &out_system_headers) const
263 {
264  const std::string &name_str=id2string(symbol.name);
265 
266  if(has_prefix(name_str, CPROVER_PREFIX) ||
267  name_str=="__func__" ||
268  name_str=="__FUNCTION__" ||
269  name_str=="__PRETTY_FUNCTION__" ||
270  name_str=="argc'" ||
271  name_str=="argv'" ||
272  name_str=="envp'" ||
273  name_str=="envp_size'")
274  return true;
275 
276  if(has_suffix(name_str, "$object"))
277  return true;
278 
279  // exclude nondet instructions
280  if(has_prefix(name_str, "nondet_"))
281  {
282  return true;
283  }
284 
285  if(has_prefix(name_str, "__VERIFIER"))
286  {
287  return true;
288  }
289 
290  const std::string &file_str=id2string(symbol.location.get_file());
291 
292  // don't dump internal GCC builtins
293  if(has_prefix(file_str, "gcc_builtin_headers_") &&
294  has_prefix(name_str, "__builtin_"))
295  return true;
296 
297  if(name_str=="__builtin_va_start" ||
298  name_str=="__builtin_va_end" ||
299  symbol.name==ID_gcc_builtin_va_arg)
300  {
301  out_system_headers.insert("stdarg.h");
302  return true;
303  }
304 
305  // don't dump asserts
306  else if(name_str=="__assert_fail" ||
307  name_str=="_assert" ||
308  name_str=="__assert_c99" ||
309  name_str=="_wassert")
310  {
311  return true;
312  }
313 
314  const auto &it=system_library_map.find(symbol.name);
315 
316  if(it!=system_library_map.end())
317  {
318  out_system_headers.insert(id2string(it->second));
319  return true;
320  }
321 
322  if(use_all_headers)
323  {
324  if(
325  has_prefix(file_str, "/usr/include/") ||
326  ((has_prefix(file_str, "/Library/Developer/") ||
327  has_prefix(file_str, "/Applications/Xcode")) &&
328  file_str.find("/usr/include/") != std::string::npos))
329  {
330  if(file_str.find("/bits/") == std::string::npos)
331  {
332  // Do not include transitive includes of system headers!
333  const std::string::size_type prefix_len =
334  file_str.find("/usr/include/") + std::string("/usr/include/").size();
335  out_system_headers.insert(file_str.substr(prefix_len));
336  }
337 
338  return true;
339  }
340  else if(
341  (has_prefix(
342  file_str, "C:\\Program Files (x86)\\Microsoft Visual Studio\\") ||
343  has_prefix(file_str, "C:\\Program Files\\Microsoft Visual Studio\\")) &&
344  file_str.find("\\include\\") != std::string::npos)
345  {
346  const std::string::size_type prefix_len =
347  file_str.find("\\include\\") + std::string("\\include\\").size();
348  out_system_headers.insert(file_str.substr(prefix_len));
349 
350  return true;
351  }
352  }
353 
354  return false;
355 }
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
const irep_idt & get_file() const
Symbol table entry.
Definition: symbol.h:28
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
irep_idt name
The unique identifier.
Definition: symbol.h:40
void add_to_system_library(irep_idt header_file, std::list< irep_idt > symbols)
To add the symbols from a specific header file to the system library map.
void init_system_library_map()
To generate a map of header file names -> list of symbols The symbol names are reserved as the header...
bool is_symbol_internal_symbol(const symbolt &symbol, std::set< std::string > &out_system_headers) const
To find out if a symbol is an internal symbol.
std::map< irep_idt, irep_idt > system_library_map
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
#define CPROVER_PREFIX
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
Symbol table entry.
#define size_type
Definition: unistd.c:347
dstringt irep_idt