When processing assignment expressions in a linker script, gold processes
absolute assignments early, but when one of those assignments involves the
address of a section that has not yet been finalized, we get an internal
error in address. This patch fixes the problem by gracefully returning
from expression evaluation even if the address is not yet valid, and
deferring the assignment in such a case.
gold/
PR gold/14746
* expression.cc (Expression::Expression_eval_info): Add
is_valid_pointer field.
(Expression::eval_maybe_dot): Add is_valid_pointer parameter.
Adjust all callers.
(Addr_expression::value_from_output_section): Check whether address
is valid.
* script.cc (Symbol_assignment::set_if_absolute): Defer assignment
if evaluation failed due to address that is not yet valid.
* script.h: (Expression::eval_maybe_dot): Add is_valid_pointer
parameter.
Alan Modra committed a patch to Gnu ld to fix a problem encountered on
PPC where the --defsym option wasn't copying the st_other bits to the
newly-defined symbol.
https://sourceware.org/ml/binutils/2014-07/msg00094.html
Gold has the same problem, and additionally wasn't copying the symbol type.
This patch fixes both problems, by copying the symbol type, visibility, and
the remaining st_other bits to the new symbol for --defsym=sym1=sym2
assignments.
gold/
* expression.cc (struct Expression::Expression_eval_info): Add
new fields type_pointer, vis_pointer, and nonvis_pointer.
(Expression::eval_maybe_dot): Add type_pointer, vis_pointer, and
nonvis_pointer parameters. Adjust all calls.
(Symbol_expression::value): Update type, visibility, and nonvis bits
in caller.
* script.cc (Symbol_assignment::sized_finalize): Update type,
visibility, and remaining st_other bits for new symbol.
* script.h: (Expression::eval_maybe_dot): Add type_pointer,
vis_pointer, and nonvis_pointer parameters.
* symtab.h (Symbol::set_type): New method.
* testsuite/Makefile.am (defsym_test): New test.
* testsuite/Makefile.in: Regenerate.
* testsuite/defsym_test.c: New file.
* testsuite/defsym_test.sh: New file.
(Relobj::local_plt_offset): New function.
(Relobj::local_has_got_offset): New function.
(Relobj::local_got_offset): New function.
(Relobj::set_local_got_offset): New function.
(Relobj::do_local_symbol_value): New pure virtual function.
(Relobj::do_local_plt_offset): Likewise.
(Relobj::do_local_has_got_offset): Likewise.
(Relobj::do_local_got_offset): Likewise.
(Relobj::do_set_local_got_offset): Likewise.
(Sized_relobj::do_local_has_got_offset): Rename from
local_has_got_offset.
(Sized_relobj::do_local_got_offset): Rename from local_got_offset.
(Sized_relobj::do_set_local_got_offset): Rename from
set_local_got_offset.
(Sized_relobj_file::do_local_plt_offset): Rename from
local_plt_offset.
(Sized_relobj_file::do_local_symbol_value): New function.
* object.cc (Sized_relobj_file::do_local_plt_offset): Rename from
local_plt_offset.
* output.cc (Output_data_got::Got_entry::write): Change object to
Relobj. Use local_symbol_value.
(Output_data_got::add_global_with_rel): Change rel_dyn to
Output_data_reloc_generic*. Use add_global_generic.
(Output_data_got::add_global_with_rela): Remove. Change all
callers to use add_global_with_rel.
(Output_data_got::add_global_pair_with_rel): Change rel_dyn to
Output_data_reloc_generic*. Use add_global_generic.
(Output_data_got::add_global_pair_with_rela): Remove. Change all
callers to use add_global_pair_with_rel.
(Output_data_got::add_local): Change object to Relobj*.
(Output_data_got::add_local_plt): Likewise.
(Output_data_got::add_local_with_rel): Change object to Relobj*,
change rel_dyn to Output_data_reloc_generic*. Use
add_local_generic.
(Output_data_got::add_local_with_rela): Remove. Change all
callers to use all_local_with_rel.
(Output_data_got::add_local_pair_with_rel): Change object to
Relobj*, change rel_dyn to Output_data_reloc_generic*. Use
add_output_section_generic.
(Output_data_got::add_local_pair_with_rela): Remove. Change all
callers to use add_local_pair_with_rel.
(Output_data_got::reserve_local): Change object to Relobj*.
* output.h: (class Output_data_reloc_generic): Add pure virtual
declarations for add_global_generic, add_local_generic,
add_output_section_generic.
(class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new
functions for Output_data_reloc_generic. Update declarations for
changes listed in output.cc.
(class Output_data_got): Change template parameter to got_size.
Don't define Rel_dyn or Rela_dyn. Update declarations per above.
* incremental.h (Sized_relobj_incr::do_local_symbol_value): New
function.
(Sized_relobj_incr::do_local_plt_offset): New function.
* copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call
add_global_generic.
* expression.cc (Expression::eval_with_dot): Add
is_section_dot_assignment parameter.
(Expression::eval_maybe_dot): Likewise. Adjust value when rhs is
absolute and assigning to dot within a section.
* script-sections.cc
(Output_section_element_assignment::set_section_addresses): Pass
dot_section to set_if_absolute.
(Output_section_element_dot_assignment::finalize_symbols): Pass TRUE
as is_section_dot_assignment flag to eval_with_dot.
(Output_section_element_dot_assignment::set_section_addresses):
Likewise.
* script.cc (Symbol_assignment::set_if_absolute): Add dot_section
parameter. Also set value if relative to dot_section; set the
symbol's output_section.
* script.h (Expression::eval_with_dot): Add is_section_dot_assignment
parameter. Adjust all callers.
(Expression::eval_maybe_dot): Likewise.
(Symbol_assignment::set_if_absolute): Add dot_section parameter.
Adjust all callers.
* testsuite/script_test_2.t: Test assignment of an absolute value
to dot within an output section element.
* expression.cc (BINARY_EXPRESSION): Initialize left_alignment
and right_alignment to be zero. Store result alignment only if it is
greater than existing alignment.
* expression.cc (script_exp_function_origin)
(script_exp_function_length): Move from here to ...
* script.cc: ... here.
(script_set_section_region, script_add_memory)
(script_parse_memory_attr, script_include_directive): New
functions.
* script-sections.cc
(class Memory_region): New class.
(class Output_section_definition): Add set_memory_region,
set_section_vma, set_section_lma and get_section_name methods.
(class Script_Sections): Add add_memory_region,
find_memory_region, find_memory_region_origin,
find_memory_region_length and set_memory_region methods.
Have set_section_addresses method walk the list of set memory
regions.
Extend the print methos to display memory regions.
* script-sections.h: Add prototypes for new methods.
Add enum for MEMORY region attributes.
* yyscript.y: Add support for parsing MEMORY regions.
* script-c.h: Add prototypes for new functions.
* testsuite/Makefile.am: Add test of MEMORY region functionality.
* testsuite/Makefile.in: Regenerate.
* testsuite/memory_test.sh: New script.
* testsuite/memory_test.s: New assembler source file.
* testsuite/memory_test.t: New linker script.
* expression.cc (class Segment_start_expression): New class definition.
(Segment_start_expression::value): New method definition.
(script_exp_function_segment_start): Return a new
Segment_start_expression.
* gold/script-c.h (script_saw_segment_start_expression): New function
prototype.
* script-sections.cc (Script_sections::Script_sections): Initialize
SAW_SEGMENT_START_EXPRESSION_ to false.
(Script_sections::set_section_addresses): Use -Ttext, -Tdata
and -Tbbs options to specify section addresses if given in
command line and no SEGMENT_START expression is seen in a script.
* script-sections.h (Script_sections::saw_segment_start_expression,
Script_sections::set_saw_segment_start_expression): New method
definition.
(Script_sections::saw_segment_start_expression_): New data member
declaration.
* script.cc (script_saw_segment_start_expression): New function.
* yyscript.y (SEGMENT_START): Call script_saw_segment_start_expression.
* testsuite/Makefile.am (check_SCRIPTS): Add script_test_6.sh,
script_test_7.sh and script_test_8.sh.
(check_DATA): Add script_test_6.stdout, script_test_7.stdout and
script_test_8.stdout.
(MOSTLYCLEANFILES): Add script_test_6, script_test_7 and script_test_8.
(script_test_6, script_test_6.stdout, script_test_7,
script_test_7.stdout, script_test_8, script_test_8.stdout): New rules.
* Makefile.in: Regenerate.
* testsuite/script_test_6.sh: New file.
* testsuite/script_test_6.t: Same.
* testsuite/script_test_7.sh: Same.
* testsuite/script_test_7.t: Same.
* testsuite/script_test_8.sh: Same.