Skip to content

Commit 24a68ed

Browse files
committed
Linker scripts processing updates symbol tables
Update the symbol table and auto-generate __CPROVER_initialize instead of hand-tweaking the function. This will ensure that any further rebuilding of __CPROVER_initialize preserves those changes.
1 parent fe285ec commit 24a68ed

File tree

2 files changed

+73
-84
lines changed

2 files changed

+73
-84
lines changed

src/goto-cc/linker_script_merge.cpp

Lines changed: 70 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Author: Kareem Khazem <[email protected]>, 2017
2525

2626
#include <linking/static_lifetime_init.h>
2727

28+
#include <goto-programs/goto_convert_functions.h>
2829
#include <goto-programs/goto_model.h>
2930
#include <goto-programs/read_goto_binary.h>
3031

@@ -72,28 +73,33 @@ int linker_script_merget::add_linker_script_definitions()
7273
return fail;
7374
}
7475

75-
fail=1;
7676
linker_valuest linker_values;
77-
const auto &pair =
78-
original_goto_model->goto_functions.function_map.find(INITIALIZE_FUNCTION);
79-
if(pair == original_goto_model->goto_functions.function_map.end())
80-
{
81-
log.error() << "No " << INITIALIZE_FUNCTION << " found in goto_functions"
82-
<< messaget::eom;
83-
return fail;
84-
}
8577
fail = ls_data2instructions(
8678
data,
8779
cmdline.get_value('T'),
88-
pair->second.body,
8980
original_goto_model->symbol_table,
9081
linker_values);
9182
if(fail!=0)
9283
{
93-
log.error() << "Could not add linkerscript defs to " INITIALIZE_FUNCTION
84+
log.error() << "Could not add linkerscript defs to symbol table"
9485
<< messaget::eom;
9586
return fail;
9687
}
88+
if(
89+
original_goto_model->goto_functions.function_map.erase(
90+
INITIALIZE_FUNCTION) != 0)
91+
{
92+
static_lifetime_init(
93+
original_goto_model->symbol_table,
94+
original_goto_model->symbol_table.lookup_ref(INITIALIZE_FUNCTION)
95+
.location);
96+
goto_convert(
97+
INITIALIZE_FUNCTION,
98+
original_goto_model->symbol_table,
99+
original_goto_model->goto_functions,
100+
log.get_message_handler());
101+
original_goto_model->goto_functions.update();
102+
}
97103

98104
fail=goto_and_object_mismatch(linker_defined_symbols, linker_values);
99105
if(fail!=0)
@@ -217,17 +223,6 @@ int linker_script_merget::pointerize_linker_defined_symbols(
217223
const namespacet ns(goto_model.symbol_table);
218224

219225
int ret=0;
220-
// First, pointerize the actual linker-defined symbols
221-
for(const auto &pair : linker_values)
222-
{
223-
const auto maybe_symbol = goto_model.symbol_table.get_writeable(pair.first);
224-
if(!maybe_symbol)
225-
continue;
226-
symbolt &entry=*maybe_symbol;
227-
entry.type=pointer_type(char_type());
228-
entry.is_extern=false;
229-
entry.value=pair.second.second;
230-
}
231226

232227
// Next, find all occurrences of linker-defined symbols that are _values_
233228
// of some symbol in the symbol table, and pointerize them too
@@ -421,12 +416,10 @@ the right behaviour for both implementations.
421416
int linker_script_merget::ls_data2instructions(
422417
jsont &data,
423418
const std::string &linker_script,
424-
goto_programt &gp,
425419
symbol_tablet &symbol_table,
426420
linker_valuest &linker_values)
427421
#if 1
428422
{
429-
goto_programt::instructionst initialize_instructions=gp.instructions;
430423
std::map<irep_idt, std::size_t> truncated_symbols;
431424
for(auto &d : to_json_array(data["regions"]))
432425
{
@@ -453,24 +446,46 @@ int linker_script_merget::ls_data2instructions(
453446

454447
constant_exprt array_size_expr=from_integer(array_size, size_type());
455448
array_typet array_type(char_type(), array_size_expr);
456-
symbol_exprt array_expr(array_name.str(), array_type);
457-
source_locationt array_loc;
458449

450+
source_locationt array_loc;
459451
array_loc.set_file(linker_script);
460452
std::ostringstream array_comment;
461453
array_comment << "Object section '" << d["section"].value << "' of size "
462454
<< array_size << " bytes";
463455
array_loc.set_comment(array_comment.str());
464-
array_expr.add_source_location()=array_loc;
456+
457+
namespacet ns(symbol_table);
458+
const auto zi = zero_initializer(array_type, array_loc, ns);
459+
CHECK_RETURN(zi.has_value());
460+
461+
// Add the array to the symbol table.
462+
symbolt array_sym;
463+
array_sym.is_static_lifetime = true;
464+
array_sym.is_lvalue = true;
465+
array_sym.is_state_var = true;
466+
array_sym.name = array_name.str();
467+
array_sym.type = array_type;
468+
array_sym.value = *zi;
469+
array_sym.location = array_loc;
470+
471+
bool failed = symbol_table.add(array_sym);
472+
CHECK_RETURN(!failed);
465473

466474
// Array start address
467-
index_exprt zero_idx(array_expr, from_integer(0, size_type()));
475+
index_exprt zero_idx{array_sym.symbol_expr(), from_integer(0, size_type())};
468476
address_of_exprt array_start(zero_idx);
469477

470478
// Linker-defined symbol_exprt pointing to start address
471-
symbol_exprt start_sym(d["start-symbol"].value, pointer_type(char_type()));
479+
symbolt start_sym;
480+
start_sym.is_static_lifetime = true;
481+
start_sym.is_lvalue = true;
482+
start_sym.is_state_var = true;
483+
start_sym.name = d["start-symbol"].value;
484+
start_sym.type = pointer_type(char_type());
485+
start_sym.value = array_start;
472486
linker_values.emplace(
473-
d["start-symbol"].value, std::make_pair(start_sym, array_start));
487+
d["start-symbol"].value,
488+
std::make_pair(start_sym.symbol_expr(), array_start));
474489

475490
// Since the value of the pointer will be a random CBMC address, write a
476491
// note about the real address in the object file
@@ -494,22 +509,26 @@ int linker_script_merget::ls_data2instructions(
494509
<< d["section"].value << "'. Original address in object file"
495510
<< " is " << (*it)["val"].value;
496511
start_loc.set_comment(start_comment.str());
497-
start_sym.add_source_location()=start_loc;
512+
start_sym.location = start_loc;
498513

499-
// Instruction for start-address pointer in __CPROVER_initialize
500-
code_assignt start_assign(start_sym, array_start);
501-
start_assign.add_source_location()=start_loc;
502-
goto_programt::instructiont start_assign_i =
503-
goto_programt::make_assignment(start_assign, start_loc);
504-
initialize_instructions.push_front(start_assign_i);
514+
auto start_sym_entry = symbol_table.insert(start_sym);
515+
if(!start_sym_entry.second)
516+
start_sym_entry.first = start_sym;
505517

506518
if(has_end) // Same for pointer to end of array
507519
{
508520
plus_exprt array_end(array_start, array_size_expr);
509521

510-
symbol_exprt end_sym(d["end-symbol"].value, pointer_type(char_type()));
522+
symbolt end_sym;
523+
end_sym.is_static_lifetime = true;
524+
end_sym.is_lvalue = true;
525+
end_sym.is_state_var = true;
526+
end_sym.name = d["end-symbol"].value;
527+
end_sym.type = pointer_type(char_type());
528+
end_sym.value = array_end;
511529
linker_values.emplace(
512-
d["end-symbol"].value, std::make_pair(end_sym, array_end));
530+
d["end-symbol"].value,
531+
std::make_pair(end_sym.symbol_expr(), array_end));
513532

514533
auto entry = std::find_if(
515534
to_json_array(data["addresses"]).begin(),
@@ -531,37 +550,12 @@ int linker_script_merget::ls_data2instructions(
531550
<< "'. Original address in object file"
532551
<< " is " << (*entry)["val"].value;
533552
end_loc.set_comment(end_comment.str());
534-
end_sym.add_source_location()=end_loc;
553+
end_sym.location = end_loc;
535554

536-
code_assignt end_assign(end_sym, array_end);
537-
end_assign.add_source_location()=end_loc;
538-
goto_programt::instructiont end_assign_i =
539-
goto_programt::make_assignment(end_assign, end_loc);
540-
initialize_instructions.push_front(end_assign_i);
555+
auto end_sym_entry = symbol_table.insert(end_sym);
556+
if(!end_sym_entry.second)
557+
end_sym_entry.first = end_sym;
541558
}
542-
543-
// Add the array to the symbol table. We don't add the pointer(s) to the
544-
// symbol table because they were already there, but declared as extern and
545-
// probably with a different type. We change the externness and type in
546-
// pointerize_linker_defined_symbols.
547-
symbolt array_sym;
548-
array_sym.name=array_name.str();
549-
array_sym.pretty_name=array_name.str();
550-
array_sym.is_lvalue=array_sym.is_static_lifetime=true;
551-
array_sym.type=array_type;
552-
array_sym.location=array_loc;
553-
symbol_table.add(array_sym);
554-
555-
// Push the array initialization to the front now, so that it happens before
556-
// the initialization of the symbols that point to it.
557-
namespacet ns(symbol_table);
558-
const auto zi = zero_initializer(array_type, array_loc, ns);
559-
CHECK_RETURN(zi.has_value());
560-
code_assignt array_assign(array_expr, *zi);
561-
array_assign.add_source_location()=array_loc;
562-
goto_programt::instructiont array_assign_i =
563-
goto_programt::make_assignment(array_assign, array_loc);
564-
initialize_instructions.push_front(array_assign_i);
565559
}
566560

567561
// We've added every linker-defined symbol that marks the start or end of a
@@ -597,8 +591,6 @@ int linker_script_merget::ls_data2instructions(
597591
loc.set_comment("linker script-defined symbol: char *"+
598592
d["sym"].value+"="+"(char *)"+id2string(symbol_value)+"u;");
599593

600-
symbol_exprt lhs(d["sym"].value, pointer_type(char_type()));
601-
602594
constant_exprt rhs(
603595
integer2bvrep(
604596
string2integer(id2string(symbol_value)),
@@ -607,14 +599,15 @@ int linker_script_merget::ls_data2instructions(
607599

608600
typecast_exprt rhs_tc(rhs, pointer_type(char_type()));
609601

610-
linker_values.emplace(
611-
irep_idt(d["sym"].value), std::make_pair(lhs, rhs_tc));
602+
symbolt &symbol = symbol_table.get_writeable_ref(d["sym"].value);
603+
symbol.is_extern = false;
604+
symbol.is_static_lifetime = true;
605+
symbol.location = loc;
606+
symbol.type = pointer_type(char_type());
607+
symbol.value = rhs_tc;
612608

613-
code_assignt assign(lhs, rhs_tc);
614-
assign.add_source_location()=loc;
615-
goto_programt::instructiont assign_i =
616-
goto_programt::make_assignment(assign, loc);
617-
initialize_instructions.push_front(assign_i);
609+
linker_values.emplace(
610+
irep_idt(d["sym"].value), std::make_pair(symbol.symbol_expr(), rhs_tc));
618611
}
619612
return 0;
620613
}

src/goto-cc/linker_script_merge.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,17 @@ class linker_script_merget
111111
const std::string &out_file,
112112
const std::string &def_out_file);
113113

114-
/// \brief Write a list of definitions derived from `data` into gp's
115-
/// `instructions` member.
114+
/// \brief Write a list of definitions derived from `data` into the
115+
/// `symbol_table`.
116116
/// \pre `data` is in the format verified by #linker_data_is_malformed.
117-
/// \post For every memory region in `data`, a function call to
118-
/// `__CPROVER_allocated_memory` is prepended to
119-
/// `initialize_instructions`.
120117
/// \post For every symbol in `data`, a declaration and initialization of that
121-
/// symbol is prepended to `initialize_instructions`.
118+
/// symbol is added to `symbol_table`.
122119
/// \post Every symbol in `data` shall be a key in `linker_values`; the value
123120
/// shall be a constant expression with the actual value of the symbol
124121
/// in the linker script.
125122
int ls_data2instructions(
126123
jsont &data,
127124
const std::string &linker_script,
128-
goto_programt &gp,
129125
symbol_tablet &symbol_table,
130126
linker_valuest &linker_values);
131127

0 commit comments

Comments
 (0)