Skip to content

Commit 7f1cc0f

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 7065034 commit 7f1cc0f

File tree

12 files changed

+133
-44
lines changed

12 files changed

+133
-44
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-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/strcpy-no-decl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
void *malloc(unsigned);
1+
#include <stdlib.h>
2+
// string.h intentionally omitted
23

34
char *make_str()
45
{
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
CORE
22
strcpy-no-decl.c
33
--string-abstraction --validate-goto-model
4-
Condition: strlen type inconsistency
5-
^EXIT=(127|134)$
4+
^EXIT=10$
65
^SIGNAL=0$
76
--
87
^warning: ignoring
98
--
10-
While this test currently passes when omitting --validate-goto-model, we should
11-
expect a report of type inconsistencies as no forward declarations are present.
9+
The linker is able to fix up type inconsistencies of the missing function
10+
declarations, but the absence of a declaration of strlen results in not picking
11+
up the library model. Consequently the assumption does not work as intended, and
12+
verification fails. Adding #include <string.h> makes verification pass as
13+
expected.

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
@@ -98,7 +98,8 @@ std::string get_cprover_library_text(
9898

9999
void cprover_c_library_factory(
100100
const std::set<irep_idt> &functions,
101-
symbol_table_baset &symbol_table,
101+
const symbol_table_baset &symbol_table,
102+
symbol_table_baset &dest_symbol_table,
102103
message_handlert &message_handler)
103104
{
104105
if(config.ansi_c.lib==configt::ansi_ct::libt::LIB_NONE)
@@ -107,7 +108,7 @@ void cprover_c_library_factory(
107108
std::string library_text =
108109
get_cprover_library_text(functions, symbol_table, false);
109110

110-
add_library(library_text, symbol_table, message_handler);
111+
add_library(library_text, dest_symbol_table, message_handler);
111112
}
112113

113114
void add_library(

src/ansi-c/cprover_library.h

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

4242
void cprover_c_library_factory(
4343
const std::set<irep_idt> &functions,
44+
const symbol_table_baset &,
4445
symbol_table_baset &,
4546
message_handlert &);
4647

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_table_baset &symbol_table,
40+
const symbol_table_baset &symbol_table,
41+
symbol_table_baset &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_table_baset;
1818

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

src/goto-programs/link_to_library.cpp

Lines changed: 105 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,100 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "link_to_library.h"
1313

14+
#include <linking/static_lifetime_init.h>
15+
1416
#include "compute_called_functions.h"
1517
#include "goto_convert_functions.h"
1618
#include "goto_model.h"
19+
#include "link_goto_model.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
2074
/// with missing function bodies
2175
/// \param message_handler: message handler to report library processing
2276
/// problems
23-
/// \param library: generator function that produces function definitions for a
24-
/// given set of symbol names that have no body.
77+
/// \param library: generator function that produces function definitions (in
78+
/// the symbol table that is the third parameter) for a given set of symbol
79+
/// names (first parameter) that have no body in the source symbol table
80+
/// (second parameter).
2581
void link_to_library(
2682
goto_modelt &goto_model,
2783
message_handlert &message_handler,
28-
const std::function<
29-
void(const std::set<irep_idt> &, symbol_tablet &, message_handlert &)>
30-
&library)
84+
const std::function<void(
85+
const std::set<irep_idt> &,
86+
const symbol_tablet &,
87+
symbol_tablet &,
88+
message_handlert &)> &library)
3189
{
3290
// this needs a fixedpoint, as library functions
3391
// may depend on other library functions
3492

3593
std::set<irep_idt> added_functions;
94+
// Linking in library functions (now seeing full definitions rather than
95+
// forward declarations, or perhaps even cases of missing forward
96+
// declarations) may result in type changes to objects.
97+
replace_symbolt::expr_mapt object_type_updates;
98+
const bool had_init =
99+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION) !=
100+
goto_model.goto_functions.function_map.end();
36101

37102
while(true)
38103
{
39104
std::unordered_set<irep_idt> called_functions =
40105
compute_called_functions(goto_model.goto_functions);
41106

42-
// eliminate those for which we already have a body
43-
44-
std::set<irep_idt> missing_functions;
45-
107+
bool changed = false;
46108
for(const auto &id : called_functions)
47109
{
48110
goto_functionst::function_mapt::const_iterator f_it =
@@ -59,30 +121,44 @@ void link_to_library(
59121
// already added
60122
}
61123
else
62-
missing_functions.insert(id);
124+
{
125+
changed = true;
126+
added_functions.insert(id);
127+
128+
auto updates_opt =
129+
add_one_function(goto_model, message_handler, library, id);
130+
if(!updates_opt.has_value())
131+
{
132+
messaget log{message_handler};
133+
log.warning() << "Linking library function '" << id << "' failed"
134+
<< messaget::eom;
135+
continue;
136+
}
137+
object_type_updates.insert(updates_opt->begin(), updates_opt->end());
138+
}
63139
}
64140

65141
// done?
66-
if(missing_functions.empty())
142+
if(!changed)
67143
break;
144+
}
68145

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-
}
146+
if(
147+
had_init &&
148+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION) ==
149+
goto_model.goto_functions.function_map.end())
150+
{
151+
static_lifetime_init(
152+
goto_model.symbol_table,
153+
goto_model.symbol_table.lookup_ref(INITIALIZE_FUNCTION).location);
154+
goto_convert(
155+
INITIALIZE_FUNCTION,
156+
goto_model.symbol_table,
157+
goto_model.goto_functions,
158+
message_handler);
159+
goto_model.goto_functions.update();
87160
}
161+
162+
if(!object_type_updates.empty())
163+
finalize_linking(goto_model, object_type_updates);
88164
}

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)