Skip to content

Commit 3e1ed90

Browse files
Use the linker when adding library functions
This enables type checking of missing functions vs library-provided functions, and also enables type sanitisation as done by the linker. Co-authored-by: Peter Schrammel <[email protected]>
1 parent 9bd9dfe commit 3e1ed90

File tree

12 files changed

+121
-40
lines changed

12 files changed

+121
-40
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#include <assert.h>
22
#include <errno.h>
33

4-
int main()
4+
int main(int arc, char *argv[])
55
{
6-
__errno_location();
7-
assert(0);
6+
// errno expands to use of __errno_location() with glibc
7+
assert(errno == 0);
88
return 0;
99
}

regression/cbmc-library/__errno_location-01/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--pointer-check --bounds-check
44
^EXIT=0$

regression/cbmc-library/memcpy-06/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ CORE
22
main.c
33

44
function 'memcpy' is not declared
5-
parameter "memcpy::dst" type mismatch
6-
^EXIT=6$
5+
Linking library function 'memcpy' failed
6+
^EXIT=0$
77
^SIGNAL=0$
88
--
99
^warning: ignoring

regression/cbmc-library/memcpy-07/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// #include <string.h> intentionally omitted
2+
void *memcpy();
23

34
struct c
45
{

regression/cbmc/String_Abstraction17/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
strcpy-no-decl.c
33
--string-abstraction --validate-goto-model
4-
Condition: strlen type inconsistency
4+
^Condition: fct_type.parameters\(\).size\(\) == parameter_identifiers.size\(\)$
55
^EXIT=(127|134)$
66
^SIGNAL=0$
77
--

regression/goto-cc-goto-analyzer/instrument_preconditions_locations/s2n_hash_inlined.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <stdlib.h>
2+
13
// This file is highly reduced from some open source projects.
24
// The following four lines are adapted from the openssl library
35
// Full repository here:

src/ansi-c/cprover_library.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ std::string get_cprover_library_text(
9494

9595
void cprover_c_library_factory(
9696
const std::set<irep_idt> &functions,
97-
symbol_tablet &symbol_table,
97+
const symbol_tablet &symbol_table,
98+
symbol_tablet &dest_symbol_table,
9899
message_handlert &message_handler)
99100
{
100101
if(config.ansi_c.lib==configt::ansi_ct::libt::LIB_NONE)
@@ -104,7 +105,7 @@ void cprover_c_library_factory(
104105

105106
library_text=get_cprover_library_text(functions, symbol_table);
106107

107-
add_library(library_text, symbol_table, message_handler);
108+
add_library(library_text, dest_symbol_table, message_handler);
108109
}
109110

110111
void add_library(

src/ansi-c/cprover_library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void add_library(
3636

3737
void cprover_c_library_factory(
3838
const std::set<irep_idt> &functions,
39+
const symbol_tablet &,
3940
symbol_tablet &,
4041
message_handlert &);
4142

src/cpp/cprover_library.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ static std::string get_cprover_library_text(
3737

3838
void cprover_cpp_library_factory(
3939
const std::set<irep_idt> &functions,
40-
symbol_tablet &symbol_table,
40+
const symbol_tablet &symbol_table,
41+
symbol_tablet &dest_symbol_table,
4142
message_handlert &message_handler)
4243
{
4344
if(config.ansi_c.lib == configt::ansi_ct::libt::LIB_NONE)
@@ -46,5 +47,5 @@ void cprover_cpp_library_factory(
4647
const std::string library_text =
4748
get_cprover_library_text(functions, symbol_table);
4849

49-
add_library(library_text, symbol_table, message_handler);
50+
add_library(library_text, dest_symbol_table, message_handler);
5051
}

src/cpp/cprover_library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class symbol_tablet;
1818

1919
void cprover_cpp_library_factory(
2020
const std::set<irep_idt> &functions,
21+
const symbol_tablet &,
2122
symbol_tablet &,
2223
message_handlert &);
2324

src/goto-programs/link_to_library.cpp

Lines changed: 98 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,60 @@ Author: Daniel Kroening, [email protected]
1414
#include "compute_called_functions.h"
1515
#include "goto_convert_functions.h"
1616
#include "goto_model.h"
17+
#include "link_goto_model.h"
18+
19+
#include <linking/static_lifetime_init.h>
20+
21+
/// Try to add \p missing_function from \p library to \p goto_model.
22+
static optionalt<replace_symbolt::expr_mapt> add_one_function(
23+
goto_modelt &goto_model,
24+
message_handlert &message_handler,
25+
const std::function<void(
26+
const std::set<irep_idt> &,
27+
const symbol_tablet &,
28+
symbol_tablet &,
29+
message_handlert &)> &library,
30+
const irep_idt &missing_function)
31+
{
32+
goto_modelt library_model;
33+
library(
34+
{missing_function},
35+
goto_model.symbol_table,
36+
library_model.symbol_table,
37+
message_handler);
38+
39+
// convert to CFG
40+
if(
41+
library_model.symbol_table.symbols.find(missing_function) !=
42+
library_model.symbol_table.symbols.end())
43+
{
44+
goto_convert(
45+
missing_function,
46+
library_model.symbol_table,
47+
library_model.goto_functions,
48+
message_handler);
49+
}
50+
51+
// check whether additional initialization may be required
52+
if(
53+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION) !=
54+
goto_model.goto_functions.function_map.end())
55+
{
56+
for(const auto &entry : library_model.symbol_table)
57+
{
58+
if(
59+
entry.second.is_static_lifetime && !entry.second.is_type &&
60+
!entry.second.is_macro && entry.second.type.id() != ID_code &&
61+
!goto_model.symbol_table.has_symbol(entry.first))
62+
{
63+
goto_model.unload(INITIALIZE_FUNCTION);
64+
break;
65+
}
66+
}
67+
}
68+
69+
return link_goto_model(goto_model, std::move(library_model), message_handler);
70+
}
1771

1872
/// Complete missing function definitions using the \p library.
1973
/// \param goto_model: goto model that may contain function calls and symbols
@@ -25,24 +79,27 @@ Author: Daniel Kroening, [email protected]
2579
void link_to_library(
2680
goto_modelt &goto_model,
2781
message_handlert &message_handler,
28-
const std::function<
29-
void(const std::set<irep_idt> &, symbol_tablet &, message_handlert &)>
30-
&library)
82+
const std::function<void(
83+
const std::set<irep_idt> &,
84+
const symbol_tablet &,
85+
symbol_tablet &,
86+
message_handlert &)> &library)
3187
{
3288
// this needs a fixedpoint, as library functions
3389
// may depend on other library functions
3490

3591
std::set<irep_idt> added_functions;
92+
replace_symbolt::expr_mapt object_type_updates;
93+
const bool had_init =
94+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION) !=
95+
goto_model.goto_functions.function_map.end();
3696

3797
while(true)
3898
{
3999
std::unordered_set<irep_idt> called_functions =
40100
compute_called_functions(goto_model.goto_functions);
41101

42-
// eliminate those for which we already have a body
43-
44-
std::set<irep_idt> missing_functions;
45-
102+
bool changed = false;
46103
for(const auto &id : called_functions)
47104
{
48105
goto_functionst::function_mapt::const_iterator f_it =
@@ -59,30 +116,44 @@ void link_to_library(
59116
// already added
60117
}
61118
else
62-
missing_functions.insert(id);
119+
{
120+
changed = true;
121+
added_functions.insert(id);
122+
123+
auto updates_opt =
124+
add_one_function(goto_model, message_handler, library, id);
125+
if(!updates_opt.has_value())
126+
{
127+
messaget log{message_handler};
128+
log.warning() << "Linking library function '" << id << "' failed"
129+
<< messaget::eom;
130+
continue;
131+
}
132+
object_type_updates.insert(updates_opt->begin(), updates_opt->end());
133+
}
63134
}
64135

65136
// done?
66-
if(missing_functions.empty())
137+
if(!changed)
67138
break;
139+
}
68140

69-
library(missing_functions, goto_model.symbol_table, message_handler);
70-
71-
// convert to CFG
72-
for(const auto &id : missing_functions)
73-
{
74-
if(
75-
goto_model.symbol_table.symbols.find(id) !=
76-
goto_model.symbol_table.symbols.end())
77-
{
78-
goto_convert(
79-
id,
80-
goto_model.symbol_table,
81-
goto_model.goto_functions,
82-
message_handler);
83-
}
84-
85-
added_functions.insert(id);
86-
}
141+
if(
142+
had_init &&
143+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION) ==
144+
goto_model.goto_functions.function_map.end())
145+
{
146+
static_lifetime_init(
147+
goto_model.symbol_table,
148+
goto_model.symbol_table.lookup_ref(INITIALIZE_FUNCTION).location);
149+
goto_convert(
150+
INITIALIZE_FUNCTION,
151+
goto_model.symbol_table,
152+
goto_model.goto_functions,
153+
message_handler);
154+
goto_model.goto_functions.update();
87155
}
156+
157+
if(!object_type_updates.empty())
158+
finalize_linking(goto_model, object_type_updates);
88159
}

src/goto-programs/link_to_library.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ class symbol_tablet;
2424
void link_to_library(
2525
goto_modelt &,
2626
message_handlert &,
27-
const std::function<
28-
void(const std::set<irep_idt> &, symbol_tablet &, message_handlert &)> &);
27+
const std::function<void(
28+
const std::set<irep_idt> &,
29+
const symbol_tablet &,
30+
symbol_tablet &,
31+
message_handlert &)> &);
2932

3033
#endif // CPROVER_GOTO_PROGRAMS_LINK_TO_LIBRARY_H

0 commit comments

Comments
 (0)