From 2f0e9800f7dbaa0a17632f43f9b757a9e8578ac4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 29 Jul 2008 22:58:02 +0000 Subject: [PATCH] * script.cc (Script_options::finalize_symbols): Finalize SECTIONS symbols before other symbols. * testsuite/script_test_2.cc (test_addr): Declare. (test_addr_alias): Declare. (main): Check that test_addr and test_addr_alias have the right values. * testsuite/script_test_2.t: Define test_addr_alias and test_addr. --- gold/ChangeLog | 1856 +++++++++++++++++++++++++++++ gold/script.cc | 2517 +++++++++++++++++++++++++++++++++++++++ gold/testsuite/script_test_2.cc | 74 ++ gold/testsuite/script_test_2.t | 68 ++ 4 files changed, 4515 insertions(+) create mode 100644 gold/ChangeLog create mode 100644 gold/script.cc create mode 100644 gold/testsuite/script_test_2.cc create mode 100644 gold/testsuite/script_test_2.t diff --git a/gold/ChangeLog b/gold/ChangeLog new file mode 100644 index 0000000000..48508a9f29 --- /dev/null +++ b/gold/ChangeLog @@ -0,0 +1,1856 @@ +2008-07-29 Ian Lance Taylor + + * script.cc (Script_options::finalize_symbols): Finalize SECTIONS + symbols before other symbols. + * testsuite/script_test_2.cc (test_addr): Declare. + (test_addr_alias): Declare. + (main): Check that test_addr and test_addr_alias have the right + values. + * testsuite/script_test_2.t: Define test_addr_alias and + test_addr. + +2008-07-24 Ian Lance Taylor + + PR 5990 + * descriptors.cc: New file. + * descriptors.h: New file. + * gold-threads.h (class Hold_optional_lock): New class. + * fileread.cc: Include "descriptors.h". + (File_read::~File_read): Release descriptor rather than closing + it. + (File_read::open) [file]: Call open_descriptor rather than open. + Set is_descriptor_opened_. + (File_read::open) [memory]: Assert that descriptor is not open. + (File_read::reopen_descriptor): New function. + (File_read::release): Release descriptor. + (File_read::do_read): Make non-const. Reopen descriptor. + (File_read::read): Make non-const. + (File_read::make_view): Reopen descriptor. + (File_read::do_readv): Likewise. + * fileread.h (class File_read): Add is_descriptor_opened_ field. + Update declarations. + * layout.cc: Include "descriptors.h". + (Layout::create_build_id): Use open_descriptor rather than open. + * output.cc: Include "descriptors.h". + (Output_file::open): Use open_descriptor rather than open. + * archive.cc (Archive::const_iterator): Change Archive to be + non-const. + (Archive::begin, Archive::end): Make non-const. + (Archive::count_members): Likewise. + * archive.h (class Archive): Update declarations. + * object.h (Object::read): Make non-const. + * Makefile.am (CCFILES): Add descriptors.cc. + (HFILES): Add descriptors.h. + * Makefile.in: Rebuild. + + PR 6716 + * gold.h: Always include . Add Solaris workarounds + following code in binutils/sysdep.h. + + PR 6048 + * ehframe.cc (Eh_frame::add_ehframe_input_section): Check whether + this->eh_frame_hdr_ is NULL before using it. + + * dynobj.cc (Versions::Versions): Update comment. + + * dynobj.cc (Versions::Versions): If there is an soname, use it as + the base version name. + + * stringpool.cc (Stringpool_template::add_with_length): Set key to + array size plus one. + (Stringpool_template::set_string_offsets): Subtract one from key + before using it as an array index. + (Stringpool_template::get_offset_with_length): Likewise. + (Stringpool_template::write_to_buffer): Likewise. + * stringpool.h (Stringpool_template::get_offset_from_key): + Likewise. + +2008-07-23 Ian Lance Taylor + + PR 6658 + * object.h (Merged_symbol_value::value): Do our best to handle a + negative addend. + + PR 6647 + * script.cc (Version_script_info::get_versions): Don't add empty + version tag to return value. + (Version_script_info::get_symbol_version_helper): Change return + type to bool. Add pversion parameter. Change all callers. + (script_register_vers_node): Don't require a non-NULL tag. + * script.h (class Version_script_info): Update declarations. + (Version_script_info::get_symbol_version): Change return type to + bool. Add version parameter. Change all callers. + * symtab.cc (Sized_symbol::add_from_relobj): Rework version + handling. Handle an empty version from a version script. + (Symbol_table::define_special_symbol): Likewise. + * testsuite/ver_test_10.script: New file. + * testsuite/ver_test_10.sh: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_10.sh. + (check_DATA): Add ver_test_10.syms. + (ver_test_10.syms, ver_test_10.so): New target. + * testsuite/Makefile.in: Rebuild. + +2008-07-23 Simon Baldwin + + * symtab.cc (Symbol_table::sized_write_symbol): Only set st_size + to zero for undefined symbols from dynamic libraries. + +2008-07-23 Ian Lance Taylor + + * symtab.cc (Symbol_table::resolve): Remove version parameter. + Change all callers. + * symtab.h (class Symbol_table): Update declaration. + * testsuite/ver_test_9.cc: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add ver_test_9. + (ver_test_9_SOURCES, ver_test_9_DEPENDENCIES): Define. + (ver_test_9_LDFLAGS, ver_test_9_LDADD): Define. + (ver_test_9.so, ver_test_9.o): New targets. + * testsuite/Makefile.in: Rebuild. + +2008-07-22 Ian Lance Taylor + + * options.h (class General_options): Define --check-sections. + * layout.cc (Layout::set_segment_offsets): Handle + --check-sections. + + * options.h (class General_options): Define -n/--nmagic and + -N/--omagic. + * options.cc (General_options::finalize): For -n/--nmagic or + -N/--omagic, set -static. + * layout.cc (Layout::attach_allocated_section_to_segment): If + -N/--omagic, don't put read-only and read-write sections in + different segments. + (Layout::find_first_load_seg): If -N/--omagic, don't insist on + finding a read-only segment. + (Layout::set_segment_offsets): If -N/--omagic or -n/--nmagic, + don't set the minimum segment alignment to the common page size, + and don't set the file offset to the address modulo the page size. + * script-sections.cc (Script_sections::create_segments): If + -n/--omagic, don't put read-only and read-write sections in + different segments. + + * cref.cc: New file. + * cref.h: New file. + * options.h (class General_options): Add --print-symbol-counts. + * main.cc (main): Issue defined symbol report if requested. + * archive.cc (Archive::interpret_header): Make into a const member + function. + (Archive::add_symbols): Call Input_objects::archive_start and + archive_stop. + (Archive::const_iterator): Define new class. + (Archive::begin, Archive::end): New functions. + (Archive::include_all_members): Rewrite to use iterator. + (Archive::count_members): New function. + * archive.h (class Archive): Update declarations. + (Archive::filename): New function. + * object.cc: Include "cref.h". + (Sized_relobj::Sized_relobj): Initialize defined_count_. + (Sized_relobj::do_get_global_symbol_counts): New function. + (Input_objects::add_object): Add object to cross-referencer. + (Input_objects::archive_start): New function. + (Input_objects::archive_stop): New function. + (Input_objects::print_symbol_counts): New function. + * object.h: Declare Cref and Archive. + (Object::get_global_symbol_counts): New function. + (Object::do_get_global_symbol_counts): New pure virtual function. + (class Sized_relobj): Add defined_count_ field. Update + declarations. + (class Input_objects): Add cref_ field. Update constructor. + Update declarations. + * dynobj.cc (Sized_dynobj::Sized_dynobj): Initialize symbols_ and + defined_count_. + (Sized_dynobj::do_add_symbols): Allocate symbols_ if printing + symbol counts. + (Sized_dynobj::do_get_global_symbol_counts): New function. + * dynobj.h (class Sized_dynobj): Add fields symbols_ and + defined_count_. Update declarations. Define Symbols typedef. + * symtab.cc (Symbol_table::add_from_relobj): Add defined + parameter. Change all callers. + (Symbol_table::add_from_dynobj): Add sympointers and defined + parameters. Change all callers. + * symtab.h (class Symbol_table): Update declarations. + * Makefile.am (CCFILES): Add cref.cc. + (HFILES): Add cref.h. + * Makefile.in: Rebuild. + +2008-07-22 Simon Baldwin + + * symtab.cc (Symbol_table::sized_write_symbol): Set symbol size + to zero when writing undefined symbols. + +2008-07-22 Ian Lance Taylor + + * output.cc (Output_section::add_input_section): Don't try to + merge empty merge sections. + +2008-07-21 Craig Silverstein + + * symtab.cc (Symbol_table::warn_about_undefined_dynobj_symbol): + Include symbol version in error message. + +2008-07-20 Chris Demetriou + + * configure.ac (gold_cv_c_random_seed): New configured variable. + (RANDOM_SEED_CFLAGS): New substituted variable. + * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Add $(RANDOM_SEED_CFLAGS). + * configure: Rebuild. + * Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2008-07-18 Ian Lance Taylor + + * symtab.cc (Symbol_table::add_from_object): Rewrite the case + where we see NAME/NULL and NAME/VERSION as separate symbols. + * testsuite/ver_test_main.cc (main): Call t4. + (t4, t4_2a): Define. + * testsuite/ver_test_2.cc (t4_2): Define. + * testsuite/ver_test_2.script: Put t4_2a in VER2. + * testsuite/ver_test_4.cc (t4_2a): Define. + * testsuite/ver_test_4.script: Put t4_2a in VER2. + * testsuite/ver_test.h (t4, t4_2, t4_2a): Declare. + +2008-07-17 Ian Lance Taylor + + * dynobj.cc (Versions::add_def): If we give an error about a + missing version, go ahead and create the version anyhow. + +2008-07-10 Ian Lance Taylor + + Handle output sections with more than 0x7fffffff bytes. + * object.h (class Relobj): Change map_to_output_ to + output_sections_, and just keep a section pointer. Change all + uses. Move comdat group support to Sized_relobj. + (Relobj::is_section_specially_mapped): Remove. + (Relobj::output_section): Remove poff parameter. Change all + callers. + (Relobj::output_section_offset): New function. + (Relobj::set_section_offset): Rewrite. + (Relobj::map_to_output): Remove. + (Relobj::output_sections): New function. + (Relobj::do_output_section_offset): New pure virtual function. + (Relobj::do_set_section_offset): Likewise. + (class Sized_relobj): Add section_offsets_ field. Add comdat + group support from Relobj. Update declarations. + (Sized_relobj::get_output_section_offset): New function. + (Sized_relobj::do_output_section_offset): New function. + (Sized_relobj::do_set_section_offset): New function. + * object.cc (Relobj::output_section_address): Remove. + (Sized_relobj::Sized_relobj): Initialize new fields. + (Sized_relobj::include_section_group): Cast find_kept_object to + Sized_relobj. + (Sized_relobj::include_linkonce_section): Likewise. + (Sized_relobj::do_layout): Use separate arrays for output section + and output offset. + (Sized_relobj::do_count_local_symbols): Change map_to_output to + output_sections. + (Sized_relobj::do_finalize_local_symbols): Change map_to_output to + output_sections and section_offsets. + (Sized_relobj::write_local_symbols): Likewise. + (map_to_kept_section): Compute output address directly. + * reloc.cc (Sized_relobj::do_read_relocs): Change map_to_output to + output_sections and section_offsets. + (Sized_relobj::write_sections): Likewise. + (Sized_relobj::relocate_sections): Likewise. + * symtab.cc (sized_finalize_symbol): Use output_section_offset. + * output.h (class Output_reloc): Update declarations. Change + u2_.relobj to Sized_relobj*. + (class Output_data_reloc): Change add functions to use + Sized_relobj*. + * output.cc (Output_reloc::Output_reloc): Change relobj to + Sized_relobj*. + (Output_reloc::local_section_offset): Change return type to + Elf_Addr. Use get_output_section_offset. + (Output_reloc::get_address): Likewise. + (Output_section::is_input_address_mapped): Don't call + is_section_specially_mapped. + (Output_section::output_offset): Likewise. + (Output_section::output_address): Likewise. + (Output_section::starting_output_address): Likewise. + * copy-relocs.cc (Copy_relocs::copy_reloc): Change object + parameter to Sized_relobj*. + (Copy_relocs::need_copy_reloc): Likewise. + (Copy_relocs::save): Likewise. + * copy-relocs.h (class Copy_relocs): Update declarations. + (class Copy_relocs::Copy_reloc_entry): Change constructor to use + Sized_relobj*. Change relobj_ field to Sized_relobj*. + * target-reloc.h (relocate_for_relocatable): Change + offset_in_output_section type to Elf_Addr. Change code that uses + it as well. + * layout.cc (Layout::layout): Always set *off. + * mapfile.cc (Mapfile::print_input_section): Use + output_section_offset. + * i386.cc (Target_i386::copy_reloc): Change object parameter to + Sized_relobj*. + * powerpc.cc (Target_powerpc::copy_reloc): Likewise. + * sparc.cc (Target_sparc::copy_reloc): Likewise. + * x86_64.cc (Target_x86_64::copy_reloc): Likewise. + +2008-07-03 Ian Lance Taylor + + * layout.cc (Layout::include_section): Do not discard unrecognized + SHT_STRTAB sections. + +2008-06-30 Craig Silverstein + + * script.cc (Lex::can_continue_name): Make '?' allowable in + version-script names. + * testsuite/version_script.map: Change glob pattern to use '?' + +2008-06-30 Manish Singh + + PR 6585 + * symtab.cc (Symbol_table::add_undefined_symbols_from_command_line): + Correct typo. + +2008-06-30 Ian Lance Taylor + + PR 6660 + PR 6682 + * powerpc.cc (Powerpc_relocate_functions::addr16_ha) [both + versions]: Don't try to read the value in the contents, since we + don't use it. Use the template endianness when writing. + +2008-06-25 Cary Coutant + + * fileread.cc (File_read::make_view): Assert on zero-length view. + * object.cc (Sized_relobj::do_read_symbols): Don't try to read + symbol table when there are no symbols to read. + +2008-06-23 Craig Silverstein + + * version.cc (version_string): Bump to 1.7 + +2008-06-18 Craig Silverstein + + * powerpc.cc (Powerpc_relocate_functions::addr16_ha): cast + constant 0xFFFF to type Valtype. + (Powerpc_relocate_functions::rel16_ha): Likewise. + +2008-06-17 Ian Lance Taylor + + * output.h (Output_section::Input_section): Initialize p2align_ to + zero for Output_section_data constructors. + (Output_section::Input_section::addralign): If not an input + section, return the alignment of the Output_section_data. + * testsuite/copy_test.cc: New file. + * testsuite/copy_test_1.cc: New file. + * testsuite/copy_test_2.cc: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add copy_test. + (copy_test_SOURCES, copy_test_DEPENDENCIES): New variables. + (copy_test_LDFLAGS, copy_test_LDADD): New variables. + (copy_test_1_pic.o, copy_test_1.so): New targets. + (copy_test_2_pic.o, copy_test_2.so): New targets. + * testsuite/Makefile.in: Rebuild. + + * script-sections.cc (Script_sections::place_orphan): Initialize + local variable exact. + +2008-06-13 David Edelsohn + + * powerpc.cc (Output_data_plt_powerpc::do_write): 8 + 4 = 0xC. + +2008-06-12 David Edelsohn + David S. Miller + + * powerpc.cc: New file. + * Makefile.am (TARGETSOURCES): Add powerpc.cc + (ALL_TARGETOBJS): Add powerpc.$(OBJEXT) + * configure.tgt: Add entries for powerpc-* and powerpc64-*. + * Makefile.in: Rebuild. + +2008-06-09 Ian Lance Taylor + + * testsuite/relro_test.cc: Include , , and + . + (throwing, orig_terminate): New static variables. + (terminate_handler): New static function. + (t2): Set terminate handler. + +2008-06-05 Kris Van Hees + + PR 6584 + * binary.cc (Binary_to_elf::sized_convert): Fix .data + alignment. + +2008-05-30 Cary Coutant + + * archive.cc (Archive::include_all_members) Correct to step + over symbol table and extended name table in thin archives. + +2008-05-29 Kris Van Hees + + PR 6407 + * target-reloc.h (relocate_for_relocatable): Fix new_offset + calculation. + +2008-05-28 Caleb Howe + + * reduced_debug_output.cc: New file. + * reduced_debug_output.h: New file. + * options.h (class General_options): Add --strip-debug-non-line. + * options.cc (General_options::finalize): Add strip_debug_non_line + to the strip heirarchy. + * layout.h (class Layout): Add debug_abbrev_ and debug_info_ + fields. + * layout.cc: Include "reduced_debug_output.h". + (Layout::Layout): Initialize new fields. + (line_only_debug_sections): New static array. + (is_lines_only_debug_sections): New static inline function. + (Layout::include_section): Handle --strip-debug-non-line. + (Layout::make_output_section): If --strip-debug-non-line, build + new output sections for .debug_abbrev and .debug_info. + * dwarf_reader.cc (read_unsigned_LEB_128): Move to namespace + gold. Warn about possible overflow. + (read_signed_LEB_128): Likewise. + * dwarf_reader.h: (read_unsigned_LEB_128): Declare. + (read_signed_LEB_128): Declare. + * Makefile.am (CCFILES): Add reduced_debug_output.cc. + (HFILES): Add reduced_debug_output.h. + * Makefile.in: Rebuild. + +2008-05-21 Ian Lance Taylor + + * mapfile.cc: New file. + * mapfile.h: New file. + * options.h (class General_options): Add -M/--print-map and -Map. + * options.cc (General_options::finalize): Make -M equivalent to + -Map -. + * main.cc: Include and "mapfile.h". + (main): Open mapfile if requested. + * gold.cc (class Middle_runner): Add mapfile_ field. Update + constructor. Change caller. + (queue_initial_tasks): Add mapfile parameter. Change caller. + (queue_middle_tasks): Likewise. + * gold.h (queue_initial_tasks, queue_middle_tasks): Update + declarations. + * archive.cc: Include "mapfile.h". + (Archive::add_symbols): Add mapfile parameter. Change all + callers. Pass mapfile, symbol, and reason to include_member. + (Archive::include_all_members): Add mapfile parameter. Change all + callers. + (Archive::include_member): Add mapfile, sym, and why parameters. + Change all callers. Report inclusion to map file. + * archive.h: Include "fileread.h". + (class Archive): Update declarations. + (Archive::file): New const method. + (class Add_archive_symbols): Add mapfile_ field. Update + constructor. Change all callers. + * readsyms.h (class Read_symbols): Likewise. + (class Finish_group): Likewise. + (class Read_script): Likewise. + * common.cc: Include "mapfile.h". + (Symbol_table::allocate_commons): Add mapfile parameter. Change + all callers. + (Symbol_table::do_allocate_commons): Likewise. + (Symbol_table::do_allocate_commons_list): Likewise. Report common + symbol allocation to mapfile. + * common.h (class Allocate_commons_task): Add mapfile_ field. + Update constructor. Change all callers. + * symtab.h (class Symbol_table): Update declarations. + * layout.cc: Include "mapfile.h". + (Layout_task_runner::run): Print information to mapfile. + (Layout::create_gold_note): Change Output_data_fixed_space to + Output_data_zero_fill. + (Layout::create_build_id): Likewise. + (Layout::print_to_mapfile): New function. + * layout.h (class Layout_task_runner): Add mapfile_ field. Update + constructor. Change caller. + (class Layout): Declare print_to_mapfile. + * output.cc (Output_section::Input_section::print_to_mapfile): New + function. + (Output_section::add_input_section): If producing a map, always + add to input_sections_ list. + (Output_section::do_print_to_mapfile): New function. + (Output_segment::print_sections_to_mapfile): New function. + (Output_segment::print_section_list_to_mapfile): New function. + * output.h: Include "mapfile.h". + (Output_data::print_to_mapfile): New function. + (Output_data::do_print_to_mapfile): New virtual function. + (Output_segment_headers::do_print_to_mapfile): New function. + (Output_file_header::do_print_to_mapfile): New function. + (Output_data_const::do_print_to_mapfile): New function. + (class Output_data_const_buffer): Add map_name_ field. Update + constructor. Change all callers. Add do_print_to_mapfile + function. + (class Output_data_fixed_space): Likewise. + (class Output_data_space): Likewise. + (class Output_data_zero_fill): New class. + (Output_data_strtab::do_print_to_mapfile): New function. + (Output_data_reloc_base::do_print_to_mapfile): New function. + (Output_relocatable_relocs::do_print_to_mapfile): New function. + (Output_data_group::do_print_to_mapfile): New function. + (Output_data_got::do_print_to_mapfile): New function. + (Output_data_dynamic::do_print_to_mapfile): New function. + (Output_symtab_xindex::do_print_to_mapfile): New function. + (class Output_section): Declare do_print_to_mapflie. Declare + print_to_mapfile in Input_section. + (class Output_segment): Declare new functions. + * object.h (Sized_relobj::symbol_count): New function. + * script-sections.cc + (Output_section_element_dot_assignment::set_section_addresses): + Change Output_data_fixed_space to Output_data_zero_fill. + (Output_data_expression::do_print_to_mapfile): New function. + * script.cc (read_input_script): Add mapfile parameter. Change + all callers. + * script.h (read_input_script): Update declaration. + * ehframe.h (Eh_frame_hdr::do_print_to_mapfile): New function. + (Eh_frame::do_print_to_mapfile): New function. + * merge.h (Output_merge_data::do_print_to_mapfile): New function. + (Output_merge_string::do_print_to_mapfile): New function. + * i386.cc (Output_data_plt_i386::do_print_to_mapfile): New + function. + * sparc.cc (Output_data_plt_sparc::do_print_to_mapfile): New + function. + * x86_64.cc (Output_data_plt_x86_64::do_print_to_mapfile): New + function. + * Makefile.am (CCFILES): Add mapfile.cc. + (HFILES): Add mapfile.h. + * Makefile.in: Rebuild. + +2008-05-19 Ian Lance Taylor + + * options.h (class General_options): Add -z relro. + * layout.cc (Layout::Layout): Initialize relro_segment_. + (Layout::add_output_section_data): Return the output section. + (Layout::make_output_section): Rcognize relro sections and mark + them appropriately. + (Layout::attach_allocated_section_to_segment): Put relro sections + in a PT_GNU_RELRO segment. + (Layout::create_initial_dynamic_sections): Mark the .dynamic + section as relro. + (Layout::segment_precedes): Sort PT_GNU_RELRO segments after + PT_TLS segments. + (Layout::linkonce_mapping): Map d.rel.ro.local to + .data.rel.ro.local. + (Layout::output_section_name): Us .data.rel.ro.local for any + section which begins with that. + * layout.h (class Layout): Update add_output_section_data + declaration. Add relro_segment_ field. + * output.cc (Output_section::Output_section): Initialize is_relro_ + and is_relro_local_ fields. + (Output_segment::add_output_section): Group relro sections. + (Output_segment::is_first_section_relro): New function. + (Output_segment::maximum_alignment): If there is a relro section, + align the segment to the common page size. + (Output_segment::set_section_addresses): Track whether we are + looking at relro sections. If the last section is a relro + section, align to the common page size. + (Output_segment::set_section_list_addresses): Add in_relro + parameter. Change all callers. Align to the page size when + moving from relro to non-relro section. + (Output_segment::set_offset): Align memsz of a PT_GNU_RELRO + segment. + * output.h (class Output_section): Add is_relro_ and + is_relro_local_ fields. + (Output_section::is_relro): New function. + (Output_section::set_is_relro): New function. + (Output_section::is_relro_local): New function. + (Output_section::set_is_relro_local): New function. + (class Output_segment): Update declarations. + * i386.cc (Target_i386::got_section): Mark .got section as relro. + * sparc.cc (Target_sparc::got_section): Likewise. + * x86_64.cc (Target_x86_64::got_section): Likewise. + * testsuite/relro_test_main.cc: New file. + * testsuite/relro_test.cc: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add relro_test. + (relro_test_SOURCES, relro_test_DEPENDENCIES): New variables. + (relro_test_LDFLAGS, relro_test_LDADD): New variables. + (relro_test.so, relro_test_pic.o): New targets. + * testsuite/Makefile.in: Rebuild. + +2008-05-16 Ian Lance Taylor + + * output.cc (Output_segment::add_output_section): Remove front + parameter. + * output.h (class Output_segment): Remove + add_initial_output_section and overloaded add_output_section. + Update declaration of remaining add_output_section. + * layout.cc (Layout::create_interp): Call add_output_section + rather than add_initial_output_section. + (Layout::finish_dynamic_section): Likewise. + + * i386.cc (Target_i386::Relocate::relocate_tls): Set dynamic type + for TLS_GOTDESC and TLS_DESC_CALL. Only optimize TLS_LDO_32 if we + know the dynamic type. + * x86_64.cc (Target_x86_64::Relocate): Add saw_tls_block_reloc_ + field. Initialize it in constructor. + (Target_x86_64::Relocate::relocate_tls): Record that we saw a TLS + block reloc for TLSGD, GOTPC32_TLSDESC, TLSDESC_CALL, and TLSLD. + Only optimize DTPOFF32 and DTPOFF64 if we have seen a TLS block + reloc. + + * output.cc (Output_reloc::get_address): Change return type to + Elf_Addr. + * output.h (class Output_reloc): Update get_address declaration. + * x86_64.cc (Output_data_plt_x86_64::do_write): Use 64-bit types + for section addresses. + +2008-05-09 Ian Lance Taylor + + PR 6493 + * gold.cc (gold_nomem): Use return value of write. + +2008-05-08 Ian Lance Taylor + + * symtab.c (Symbol::init_base_output_data): Add version + parameter. Change all callers. + (Symbol::init_base_output_segment): Likewise. + (Symbol::init_base_constant): Likewise. + (Symbol::init_base_undefined): Likewise. + (Sized_symbol::init_output_data): Likewise. + (Sized_symbol::init_output_segment): Likewise. + (Sized_symbol::init_constant): Likewise. + (Sized_symbol::init_undefined): Likewise. + (Symbol_table::do_define_in_output_data): If the new symbol has a + version, mark it as the default. + (Symbol_table::do_define_in_output_segment): Likewise. + (Symbol_table::do_define_as_constant): Likewise. + * symtab.h (class Symbol): Update declarations. + (class Sized_symbol): Likewise. + * resolve.cc (Symbol::override_version): New function. + (Symbol::override_base): Call override_version. + (Symbol::override_base_with_special): Likewise. + * testsuite/ver_script_8.script: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add ver_test_8. + (ver_test_8_SOURCES, ver_test_8_DEPENDENCIES): Define. + (ver_test_8_LDFLAGS, ver_test_8_LDADD): Define. + (ver_test_8_1.so, ver_test_8_2.so): New targets. + +2008-05-06 Ian Lance Taylor + + PR 6049 + * options.h (DEFINE_set): Add VARNAME_begin and VARNAME_end + functions. + (class General_options): Remove existing --undefined, and add + --no-undefined instead. Add new --undefined as synonym for -u. + * archive.cc (Archive::add_symbols): Check whether symbol was + named with -u. + * gold.cc (queue_middle_tasks): Add -u symbols to symbol table. + * symtab.h (class Symbol): Rename CONSTANT to IS_CONSTANT; change + all uses. Add IS_UNDEFINED. Update declarations to split + different versions of init_base. Declare init_base_undefined. + (Symbol::is_defined): Handle IS_UNDEFINED. + (Symbol::is_undefined): Likewise. + (Symbol::is_weak_undefined): Call is_undefined. + (Symbol::is_absolute): Handle IS_CONSTANT. + (class Sized_symbol): Update declarations to split different + versions of init. Declare init_undefined. + (class Symbol_table): Declare new functions. + * symtab.cc (Symbol::init_base_object): Rename from init_base. + Change all callers. + (Symbol::init_base_output_data): Likewise. + (Symbol::init_base_output_segment): Likewise. + (Symbol::init_base_constant): Likewise. + (Symbol::init_base_undefined): New function. + (Sized_symbol::init_object): Rename from init. Change all + callers. + (Sized_symbol::init_output_data): Likewise. + (Sized_symbol::init_output_segment): Likewise. + (Sized_symbol::init_constant): Likewise. + (Sized_symbol::init_undefined): New function. + (Symbol_table::add_undefined_symbols_from_command_line): New + function. + (Symbol_table::do_add_undefined_symbols_from_command_line): New + function. + (Symbol::final_value_is_known): Handle IS_UNDEFINED. + (Symbol::output_section): Likewise. + (Symbol::set_output_section): Likewise. + (Symbol_table::sized_finalize_symbol): Likewise. + (Symbol_table::sized_write_globals): Likewise. + * resolve.cc (Symbol_table::should_override): Likewise. + (Symbol::override_base_with_special): Likewise. + + * symtab.cc (Symbol_table::add_from_dynobj): If we see a protected + symbol, change it to have default visibility. + * testsuite/protected_1.cc: New file. + * testsuite/protected_2.cc: New file. + * testsuite/protected_3.cc: New file. + * testsuite/protected_main_1.cc: New file. + * testsuite/protected_main_2.cc: New file. + * testsuite/protected_main_3.cc: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add protected_1. + (protected_1_SOURCES, protected_1_DEPENDENCIES): Define. + (protected_1_LDFLAGS, protected_1_LDADD): Define. + (protected_1.so): New target. + (protected_1_pic.o, protected_2_pic.o): New targets. + (protected_3_pic.o): New target. + (check_PROGRAMS): Add protected_2. + (protected_2_SOURCES, protected_2_DEPENDENCIES): Define. + (protected_2_LDFLAGS, protected_2_LDADD): Define. + * testsuite/Makefile.in: Rebuild. + + * options.h (DEFINE_var): Add set_user_set_##varname__. + (DEFINE_bool_alias): New macro. + (class General_options): Define -Bstatic using DEFINE_bool_alias + rather than DEFINE_special. Add --undefined as an alias for -z + defs. + * options.cc (General_options::parse_Bstatic): Remove. + + * options.h (class General_options): Add --fatal-warnings. + * main.cc (main): Implement --fatal-warnings. + * errors.h (Errors::warning_count): New function. + + * options.h (class General_options): Add -Bsymbolic-functions. + * symtab.h (Symbol::is_preemptible): Check for + -Bsymbolic-functions. + +2008-05-05 Ian Lance Taylor + + * options.h (DEFINE_bool): For DASH_Z, create the negative option + as noVARNAME rather than no-VARNAME. + (class General_options): Add option -z combreloc. + * output.h (class Output_reloc) [SHT_REL]: Declare compare and + get_address. + (Output_reloc::sort_before) [SHT_REL]: New function. + (Output_reloc::sort_before) [SHT_RELA]: New function. + (class Output_data_reloc_base): Add sort_relocs_ field. Define + Sort_relocs_comparison. + (Output_data_reloc_base::Output_data_reloc_base): Add sort_relocs + parameter. Change all callers. + (Output_data_reloc::Output_data_reloc) [both versions]: Add + sort_relocs parameter. Change all callers. + * output.cc (Output_reloc::get_address): New function, broken out + of write_rel. + (Output_reloc::write_rel): Call it. + (Output_reloc::compare): New function. + (Output_data_reloc_base::do_write): Optionally sort relocs. + + * configure.ac: If targ_extra_obj is set, link it in. + * configure.tgt: Initialize all variables. + (x86_64*): Set targ_extra_obj and targ_extra_size. + * configure: Rebuild. + + * object.cc (Sized_relobj::include_section_group): Adjust section + indexes read from group data. Build vector to pass to + layout_group. + * layout.cc (Layout::layout_group): Add flags and shndxes + parameters. Remove contents parameter. Change caller. Update + explicit instantiations. + * layout.h (class Layout): Update layout_group declaration. + * output.cc (Output_data_group::Output_data_group): Add flags and + input_shndxes parameters. Remove contents parameter. Change + caller. + (Output_data_group::do_write): Change input_sections_ to + input_shndxes_. + * output.h (class Output_data_group): Update constructor + declaration. Rename input_sections_ to input_shndxes_. + * testsuite/many_sections_test.cc: Add template. + +2008-04-30 Cary Coutant + + * target-reloc.h (relocate_section): Fix dead-pointer bug. + + * layout.cc (Layout::include_section): Refactored check for debug + info section. + (Layout::add_comdat): Add new parameters. Change type + of signature parameter. Add object and shndx to signatures table. + (Layout::find_kept_object): New function. + * layout.h: Include . + (Layout::is_debug_info_section): New function. + (Layout::add_comdat): Add new parameters. + (Layout::find_kept_object): New function. + (Layout::Kept_section): New struct. + (Layout::Signatures): Change type of map range. + * object.cc (Relobj::output_section_address): New function. + (Sized_relobj::include_section_group): Add new parameters. Change + calls to Layout::add_comdat. Change to build table of kept comdat + groups and table mapping discarded sections to kept sections. + (Sized_relobj::include_linkonce_section): Likewise. Add new parameter. + (Sized_relobj::do_layout): Change calls to include_section_group and + include_linkonce_section. + (Sized_relobj::do_finalize_local_symbols): Do not set local symbol + value to zero when section is discarded. + (Sized_relobj::map_to_kept_section): New function. + * object.h (Relobj::output_section_address): New function. + (Relobj::Comdat_group): New type. + (Relobj::find_comdat_group): New function. + (Relobj::Comdat_group_table): New type. + (Relobj::Kept_comdat_section): New type. + (Relobj::Kept_comdat_section_table): New type. + (Relobj::add_comdat_group): New function. + (Relobj::set_kept_comdat_section): New function. + (Relobj::get_kept_comdat_section): New function. + (Relobj::comdat_groups_): New field. + (Relobj::kept_comdat_sections_): New field. + (Symbol_value::input_value): Update comment. + (Sized_relobj::map_to_kept_section) New function. + (Sized_relobj::include_linkonce_section): Add new parameter. + * target-reloc.h (Comdat_behavior): New type. + (get_comdat_behavior): New function. + (relocate_section): Add code to map a discarded section to the + corresponding kept section when applying a relocation. + +2008-04-30 Craig Silverstein + + * dwarf_reader.cc (next_generation_count): New static var. + (Addr2line_cache_entry): New struct. + (addr2line_cache): New static var. + (Dwarf_line_info::one_addr2line): Added caching. + (Dwarf_line_info::clear_addr2line_cache): New function. + * dwarf_reader.h (Dwarf_line_info::one_addr2line): Add + cache-size parameter. + (Dwarf_line_info::one_addr2line_cache): New function. + * symtab.cc (Symbol_table::detect_odr_violations): Pass + new cache-size argument to one_addr2line(), and clear cache. + +2008-04-28 Cary Coutant + + * i386.cc (Relocate::relocate): Fix typos for R_386_PC16 and + R_386_PC8 relocations. + +2008-04-23 Ian Lance Taylor + + * object.cc (Sized_relobj::include_section_group): Check for + invalid section group. + + * object.cc (make_elf_object): Correct test for 64-bit ELF file + header size. + + * readsyms.cc (Read_symbols::do_read_symbols): Use get_view rather + than read for file header. + * archive.cc (Archive::include_member): Likewise. + +2008-04-23 Paolo Bonzini + + * aclocal.m4: Regenerate. + * configure: Regenerate. + +2008-04-19 Ian Lance Taylor + + * version.cc (version_string): Bump to 1.6. + + * testsuite/Makefile.am (many_sections_r_test): New target. + (many_sections_r_test_SOURCES): Remove. + (many_sections_r_test_DEPENDENCIES): Remove. + (many_sections_r_test_LDFLAGS): Remove. + (many_sections_r_test_LDADD): Remove. + + * object.cc (Sized_relobj::do_add_symbols): Always pass + local_symbol_count_ to add_from_relobj. + + * testsuite/Makefile.am (many_sections_check.h): Only check one in + every thousand variables. + * testsuite/Makefile.in: Rebuild. + + * object.cc (Xindex::initialize_symtab_xindex): New function. + (Xindex::read_symtab_xindex): New function. + (Xindex::sym_xindex_to_shndx): New function. + (Sized_relobj::find_symtab): Pick up SHT_SYMTAB_SHNDX section if + available. + (Sized_relobj::do_initialize_xindex): New function. + (Sized_relobj::do_read_symbols): Adjust section links. + (Sized_relobj::symbol_section_and_value): Add is_ordinary + parameter. Change all callers. + (Sized_relobj::include_section_group): Adjust section links and + symbol section indexes. + (Sized_relobj::do_layout): Adjust section links. + (Sized_relobj::do_count_local_symbols): Adjust section links and + symbol section indexes. + (Sized_relobj::do_finalize_local_symbols): Distinguish between + ordinary and special symbols. + (Sized_relobj::write_local_symbols): Add symtab_xindex and + dynsym_xindex parameters. Change all callers. Adjust section + links. Use SHN_XINDEX when needed. + (Sized_relobj::get_symbol_location_info): Adjust section links. + Don't get fooled by special symbols. + * object.h (class Xindex): Define. + (class Object): Add xindex_ parameter. Declare virtual functoin + do_initialize_xindex. + (Object::adjust_sym_shndx): New function. + (Object::set_xindex): New protected function. + (class Symbol_value): Add is_ordinary_shndx_ field. + (Symbol_value::Symbol_value): Initialize is_ordinary_shndx_. + (Symbol_value::value): Assert ordinary section. + (Symbol_value::initialize_input_to_output_map): Likewise. + (Symbol_value::set_input_shndx): Add is_ordinary parameter. + Change all callers. + (Symbol_value::input_shndx): Add is_ordinary parameter. Change + all callers. + (class Sized_relobj): Update declarations. + (Sized_relobj::local_symbol_input_shndx): Add is_ordinary + parameter. Change all callers. + (Sized_relobj::adjust_shndx): New function. + * dynobj.cc (Sized_dynobj::Sized_dynobj): Initialize dynsym_shndx_ + field. + (Sized_dynobj::find_dynsym_sections): Remove pdynsym_shndx + parameter. Change all callers. Pick up SHT_DYNSYM_SHNDX section + for SHT_DYNSYM section if available. Set dynsym_shndx_ field. + (Sized_dynobj::read_dynsym_section): Adjust section links. + (Sized_dynobj::read_dynamic): Likewise. + (Sized_dynobj::do_read_symbols): Use dynsym_shndx_ field. Adjust + section links. + (Sized_dynobj::do_initialize_xindex): New function. + * dynobj.h (class Sized_dynobj): Add dynsym_shndx_ field. Declare + do_initialize_xindex. + (Sized_dynobj::adjust_shndx): New function. + * layout.cc (Layout::Layout): Initialize symtab_xindex_ and + dynsym_xindex_ fields. + (Layout::finalize): Add a call to set_section_indexes before + creating the symtab sections. + (Layout::set_section_indexes): Don't do anything if the section + already has a section index. + (Layout::create_symtab_sections): Add shnum parameter. Change + caller. Create .symtab_shndx section if needed. + (Layout::create_shdrs): Add shstrtab_section parameter. Change + caller. + (Layout::allocated_output_section_count): New function. + (Layout::create_dynamic_symtab): Create .dynsym_shndx section if + needed. + * layout.h (class Layout): Add symtab_xindex_ and dynsym_xindex_ + fields. Update declarations. + (Layout::symtab_xindex): New function. + (Layout::dynsym_xindex): New function. + (class Write_symbols_task): Add layout_ field. + (Write_symbols_task::Write_symbols_task): Add layout parameter. + Change caller. + * output.cc (Output_section_headers::Output_section_headers): Add + shstrtab_section parameter. Change all callers. + (Output_section_headers::do_sized_write): Store overflow values + for section count and section string table section index in + section header zero. + (Output_file_header::do_sized_write): Check for overflow of + section count and section string table section index. + (Output_symtab_xindex::do_write): New function. + (Output_symtab_xindex::endian_do_write): New function. + * output.h (class Output_section_headers): Add shstrtab_section_. + Update declarations. + (class Output_symtab_xindex): Define. + (Output_section::has_out_shndx): New function. + * symtab.cc (Symbol::init_fields): Initialize is_ordinary_shndx_ + field. + (Symbol::init_base): Add st_shndx and is_ordinary parameters. + Change all callers. + (Sized_symbol::init): Likewise. + (Symbol::output_section): Check for ordinary symbol. + (Symbol_table::add_from_object): Remove orig_sym parameter. Add + st_shndx, is_ordinary, and orig_st_shndx parameters. Change all + callers. + (Symbol_table::add_from_relobj): Add symndx_offset parameter. + Change all callers. Simplify handling of symbols from sections + not included in the link. + (Symbol_table::add_from_dynobj): Handle ordinary symbol + distinction. + (Weak_alias_sorter::operator()): Assert that symbols are + ordinary. + (Symbol_table::sized_finalize_symbol): Handle ordinary symbol + distinction. + (Symbol_table::write_globals): Add symtab_xindex and dynsym_xindex + parameters. Change all callers. + (Symbol_table::sized_write_globals): Likewise. Handle ordinary + symbol distinction. Use SHN_XINDEX when needed. + (Symbol_table::write_section_symbol): Add symtab_xindex + parameter. Change all callers. + (Symbol_table::sized_write_section_symbol): Likewise. Use + SHN_XINDEX when needed. + * symtab.h (class Symbol): Add is_ordinary_shndx_ field. Update + declarations. + (Symbol::shndx): Add is_ordinary parameter. Change all callers. + (Symbol::is_defined): Check is_ordinary. + (Symbol::is_undefined, Symbol::is_weak_undefined): Likewise. + (Symbol::is_absolute, Symbol::is_common): Likewise. + (class Sized_symbol): Update declarations. + (class Symbol_table): Update declarations. + * resolve.cc (Symbol::override_base): Add st_shndx and is_ordinary + parameters. Change all callers. + (Sized_symbol::override): Likewise. + (Symbol_table::override): Likewise. + (symbol_to_bits): Add is_ordinary parameter. Change all callers. + (Symbol_table::resolve): Remove orig_sym parameter. Add st_shndx, + is_ordinary, and orig_st_shndx parameters. Change all callers. + * copy-relocs.cc (Copy_relocs::emit_copy_reloc): Require symbol + to be in an ordinary section. + * dwarf_reader.cc (Sized_dwarf_line_info::symbol_section): Add + object and is_ordinary parameters. Change all callers. + (Sized_dwarf_line_info::read_relocs): Add object parameter. + Change all callers. Don't add undefined or non-ordinary symbols + to reloc_map_. + (Sized_dwarf_line_info::read_line_mappings): Add object parameter. + Change all callers. + * dwarf_reader.h (class Sized_dwarf_line_info): Update + declarations. + * ehframe.cc (Eh_frame::read_fde): Check for ordinary symbol. + * reloc.cc (Sized_relobj::do_read_relocs): Adjust section links. + (Sized_relobj::relocate_sections): Likewise. + * target-reloc.h (scan_relocs): Adjust section symbol index. + (scan_relocatable_relocs): Likewise. + * i386.cc (Scan::local): Check for ordinary symbols. + * sparc.cc (Scan::local): Likewise. + * x86_64.cc (Scan::local): Likewise. + * testsuite/binary_unittest.cc (Sized_binary_test): Update calls + to symbol_section_and_value. + * testsuite/many_sections_test.cc: New file. + * testsuite/Makefile.am (BUILT_SOURCES): Define. + (check_PROGRAMS): Add many_sections_test. + (many_sections_test_SOURCES): Define. + (many_sections_test_DEPENDENCIES): Define. + (many_sections_test_LDFLAGS): Define. + (BUILT_SOURCES): Add many_sections_define.h. + (many_sections_define.h): New target. + (BUILT_SOURCES): Add many_sections_check.h. + (many_sections_check.h): New target. + (check_PROGRAMS): Add many_sections_r_test. + (many_sections_r_test_SOURCES): Define. + (many_sections_r_test_DEPENDENCIES): Define. + (many_sections_r_test_LDFLAGS): Define. + (many_sections_r_test_LDADD): Define. + (many_sections_r_test.o): New target. + * testsuite/Makefile.in: Rebuild. + +2008-04-17 Cary Coutant + + * errors.cc (Errors::info): New function. + (gold_info): New function. + * errors.h (Errors::info): New function. + * gold.h (gold_info): New function. + * object.cc (Input_objects::add_object): Print trace output. + * options.cc (options::parse_set): New function. + (General_options::parse_wrap): Deleted. + (General_options::General_options): Deleted initializer. + * options.h (options::String_set): New typedef. + (options::parse_set): New function. + (DEFINE_set): New macro. + (General_options::wrap): Changed to use DEFINE_set. Changed + callers of any_wrap_symbols and is_wrap_symbol. + (General_options::trace, General_options::trace_symbol): + New options. + (General_options::any_wrap_symbols, General_options::is_wrap_symbol) + (General_options::wrap_symbols_): Deleted. + * symtab.cc (Symbol_table::add_from_object): Print trace output. + +2008-04-17 David S. Miller + + * options.cc (General_options::parse_V): New function. + * options.h: Add entries for -V and -Qy. + +2008-04-17 Ian Lance Taylor + + * common.cc (Symbol_table::allocate_commons): Remove options + parameter. Change caller. + (Symbol_table::do_allocate_commons): Remove options parameter. + Change caller. Just call do_allocate_commons_list twice. + (Symbol_table::do_allocate_commons_list): New function, broken out + of do_allocate_commons. + * common.h (class Allocate_commons_task): Remove options_ field. + Update constructor. + * symtab.cc (Symbol_table::Symbol_table): Initialize + tls_commons_. + (Symbol_table::add_from_object): Put TLS common symbols on + tls_commons_ list. + (Symbol_table::sized_finalize_symbol): Handle STT_TLS symbols + which are IN_OUTPUT_DATA. + * symtab.h (class Symbol_table): Add tls_commons_ field. Update + allocate_commons and do_allocate_commons declarations. Declare + do_allocate_commons_list. + * gold.cc (queue_middle_tasks): Update creation of + Allocate_commons_task to not pass options. + * testsuite/Makefile.am (INCLUDES): Add -I.. . + (TLS_TEST_C_FLAGS): New variable. + (tls_test_c_pic.o): New target. + (tls_test_shared.so): Link in tls_test_c_pic.o. + (tls_test_c_pic_ie.o): New target. + (tls_test_ie_shared.so): Link in tls_test_c_pic_ie.o. + (tls_test_DEPENDENCIES, tls_test_LDADD): Add tls_test_c.o. + (tls_test_c.o): New target. + (tls_pic_test_DEPENDENCIES): Add tls_test_c_pic.o. + (tls_pic_test_LDADD): Likewise. + (tls_shared_gd_to_ie_test_DEPENDENCIES): Add tls_test_c_pic.o. + (tls_shared_gd_to_ie_test_LDADD): Likewise. + (tls_test_c_gnu2.o): New target. + (tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES): Add + tls_test_c_gnu2.o. + (tls_shared_gnu2_gd_to_ie_test_LDADD): Likewise. + (tls_test_gnu2_shared.so): Link in tls_test_c_gnu2.o. + (tls_test_shared_nonpic.so): Link in tls_test_c.o. + * testsuite/tls_test.cc: Include "config.h". + (t_last): Call t11_last. + * testsuite/tls_test.h (t11, t11_last): Declare. + * testsuite/tls_test_c.c: New file. + * testsuite/tls_test_main.cc (thread_routine): Call t11. + * configure.ac: Check for OpenMP support. + * configure, config.in, Makefile.in: Rebuild. + * testsuite/Makefile.in: Rebuild. + +2008-04-16 Cary Coutant + + * i386.cc (Target_i386::define_tls_base_symbol): New function. + (Target_i386::tls_base_symbol_defined_): New field. + (Target_i386::Scan::local): Define _TLS_MODULE_BASE_ symbol. + (Target_i386::Scan::global): Likewise. + * symtab.cc (sized_finalize_symbol): Add check for TLS symbol. + * x86_64.cc (Target_x86_64::define_tls_base_symbol): New function. + (Target_x86_64::tls_base_symbol_defined_): New field. + (Target_x86_64::Scan::local): Define _TLS_MODULE_BASE_ symbol. + (Target_x86_64::Scan::global): Likewise. + +2008-04-16 Cary Coutant + + * symtab.h (Symbol::is_strong_undefined): Removed unused function. + (Symbol::needs_plt_entry): Allow weak undefined symbols. + (Symbol::needs_dynamic_reloc): Allow weak undefined symbols when + building shared libraries. + * testsuite/Makefile.am (weak_undef_nonpic_test): New target. + (weak_undef_file1_nonpic.o, weak_undef_file2_nonpic.o) + (weak_undef_lib_nonpic.so, alt/weak_undef_lib_nonpic.so): New targets. + * testsuite/Makefile.in: Rebuild. + * testsuite/weak_undef.h: New file. + * testsuite/weak_undef_file1.cc: Add extra test cases. + * testsuite/weak_undef_file2.cc: Likewise. + * testsuite/weak_undef_test.cc: Likewise. + +2008-04-16 David S. Miller + + * sparc.cc (Target_sparc::Scan): Change from struct to class. + Add issued_non_pic_error_ field. Declare check_non_pic. + (Target_sparc::Scan::check_non_pic): New function. + (Target_sparc::Scan::local): Call check_non_pic as appropriate. + (Target_sparc::Scan::global): Likewise. + + * configure.ac (FN_PTRS_IN_SO_WITHOUT_PIC): Add sparc64. + * configure: Rebuild. + + * options.h (DEFINE_enable): New macro. + (new_dtags): New enable option. + (initfirst, interpose, loadfltr, nodefaultlib, + nodelete, nodlopen, nodump): New -z options. + * layout.cc (Layout:finish_dynamic_section): If new + dtags enabled, emit DT_RUNPATH. Also, emit a + DT_FLAGS_1 containing any specified -z flags. + +2008-04-16 Ian Lance Taylor + + * copy-relocs.cc: New file. + * copy-relocs.h: New file. + * reloc.cc: Remove Copy_relocs code. + * reloc.h: Likewise. + * reloc-types.h (struct Reloc_types) [both versions]: Add + get_reloc_addend_noerror. + * output.h (class Output_data_reloc): Add + variants of add_global which take an addend which must be zero. + * i386.cc: Include "copy-relocs.h". + (class Target_i386): Change type of copy_relocs_ to variable, + update initializer. + (Target_i386::copy_reloc): Rewrite to pass to Copy_relocs class. + Change all callers. + (Target_i386::do_finalize_sections): Change handling of + copy_relocs_. + * sparc.cc: Include "copy-relocs.h". + (class Target_sparc): Change type of copy_relocs_ to variable, + update initializer. + (Target_sparc::copy_reloc): Rewrite to pass to Copy_relocs class. + Change all callers. + (Target_sparc::do_finalize_sections): Change handling of + copy_relocs_. + * x86_64.cc: Include "copy-relocs.h". + (class Target_x86_64): Change type of copy_relocs_ to variable, + update initializer. + (Target_x86_64::copy_reloc): Rewrite to pass to Copy_relocs + class. Change all callers. + (Target_x86_64::do_finalize_sections): Change handling of + copy_relocs_. + * Makefile.am (CCFILES): Add copy-relocs.cc. + (HFILES): Add copy-relocs.h. + + * Makefile.in, aclocal.m4, testsuite/Makefile.in: Rebuild. + + * testsuite/script_test_4.sh: Permit leading zeroes. + +2008-04-15 Ian Lance Taylor + + * script-sections.cc (Script_sections::create_segments): Use + header_size_adjustment even when there is enough room for the + headers. + * testsuite/script_test_4.sh: New file. + * testsuite/script_test_4.t: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add script_test_4.sh. + (check_DATA): Add script_test_4.stdout. + (MOSTLYCLEANFILES): Likewise. + (script_test_4): New target. + (script_test_4.stdout): New target. + * testsuite/Makefile.in: Rebuild. + + * sparc.cc: Add definitions for Output_data_plt_sparc class + constants. + +2008-04-14 David S. Miller + + * sparc.cc: New file. + * Makefile.am (TARGETSOURCES): Add sparc.cc + (ALL_TARGETOBJS): Add sparc.$(OBJEXT) + * configure.tgt: Document targ_extra_size and + targ_extra_big_endian. Add entries for sparc-* and + sparc64-*. + * configure.ac: Handle targ_extra_size and + targ_extra_big_endian. + * Makefile.in: Rebuild. + * configure: Likewise. + * po/POTFILES.in: Likewise. + * po/gold.pot: Likewise. + +2008-04-14 Ian Lance Taylor + + * layout.cc (Layout::Layout): Initialize sections_are_attached_. + (Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR + in the name/type/flags to section mapping. Don't call + allocate_output_section. + (Layout::choose_output_section): Change parameter from adjust_name + to is_input_section. Don't permit input sections after sections + are attached to segments. Don't call allocate_output_section. + (Layout::layout_eh_frame): Call update_flags_for_input_section, + not write_enable_output_section. + (Layout::make_output_section): Don't push to + unattached_section_list_ nor call attach_to_segment. Call + attach_section_to_segment if sections are attached. + (Layout::attach_sections_to_segments): New function. + (Layout::attach_section_to_segment): New function. + (Layout::attach_allocated_section_to_segment): Rename from + attach_to_segment. Remove flags parameter. + (Layout::allocate_output_section): Remove function. + (Layout::write_enable_output_section): Remove function. + * layout.h (class Layout): Update for above changes. Add new + field sections_are_attached_. + * output.h (Output_section::update_flags_for_input_section): New + function. + * output.cc (Output_section::add_input_section): Call + update_flags_for_input_section. + * gold.cc (queue_middle_tasks): Call attach_sections_to_segments. + +2008-04-11 Cary Coutant + + * i386.cc (Target_i386::got_mod_index_entry): Restore code previously + thought unnecessary. + * x86_64.cc (Target_x86_64::got_mod_index_entry): Likewise. + +2008-04-11 Ian Lance Taylor + + * output.h (class Output_section_data): Remove inline definition + of set_addralign. + * output.cc (Output_section_data::set_addralign): New function. + +2008-04-11 Cary Coutant + + Add support for TLS descriptors for i386 and x86_64. + * i386.cc (Target_i386::Relocate::tls_desc_gd_to_ie): New function. + (Target_i386::Relocate::tls_desc_gd_to_le): New function. + (Target_i386::Got_type): Add GOT_TYPE_TLS_NOFFSET and + GOT_TYPE_TLS_DESC. + (Target_i386::got_mod_index_entry): Remove unnecessary code. + (Target_i386::Scan::local): Implement R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL relocations. Fix problem with initial-exec + relocations. + (Target_i386::Scan::global): Fix problem with GD-to-IE relaxation. + Implement R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL relocations; + Fix problem with initial-exec relocations. + (Target_i386::Relocate::relocate_tls): Likewise. + (Target_i386::Relocate::tls_gd_to_ie): Fix problem with GD-to-IE + relaxation. + * output.cc (Output_data_dynamic::Dynamic_entry::write): Add + support for section-plus-offset dynamic table entries. + * output.h (Output_data_dynamic::add_section_plus_offset): New function. + (Output_data_dynamic::Dynamic_entry): Add support for + section-plus-offset dynamic table entries. + (Output_data_dynamic::Classification): Likewise. + (Output_data_dynamic::classification_): Renamed offset_. + * x86_64.cc (Target_x86_64::Relocate::tls_desc_gd_to_ie): New function. + (Target_x86_64::Relocate::tls_desc_gd_to_le): New function. + (Target_x86_64::make_plt_section): New function. + (Target_x86_64::reserve_tlsdesc_entries): New function. + (Output_data_plt_x86_64::Output_data_plt_x86_64): Add new parameter. + (Output_data_plt_x86_64::reserve_tlsdesc_entry): New function. + (Output_data_plt_x86_64::has_tlsdesc_entry): New function. + (Output_data_plt_x86_64::get_tlsdesc_got_offset): New function. + (Output_data_plt_x86_64::get_tlsdesc_plt_offset): New function. + (Output_data_plt_x86_64::tlsdesc_plt_entry): New field. + (Output_data_plt_x86_64::set_final_data_size): Move out of line; + add extra PLT entry for TLS descriptors. + (Output_data_plt_x86_64::got_): New field. + (Output_data_plt_x86_64::tlsdesc_got_offset_): New field. + (Output_data_plt_x86_64::Output_data_plt_x86_64): Initialize new + fields. + (Output_data_plt_x86_64::do_write): Write extra PLT entry for TLS + descriptors. + (Target_x86_64::make_plt_entry): Factor out make_plt_section. + (Target_x86_64::got_mod_index_entry): Remove unnecessary code. + (Target_x86_64::Scan::local): Implement R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL relocations. + (Target_x86_64::Scan::global): Likewise. + (Target_x86_64::do_finalize_sections): Add dynamic table entries + for TLS descriptors. + (Relocate::relocate_tls): Fix problem with GD-to-IE relaxation. + Implement R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL relocations. + (Target_x86_64::Relocate::tls_gd_to_ie): Fix problem with + GD-to-IE relaxation. + * configure.ac: Export new conditional variables TLS_GNU2_DIALECT + and TLS_DESCRIPTORS. + * Makefile.in: Rebuild. + * configure: Rebuild. + * testsuite/Makefile.am (tls_shared_gd_to_ie_test): New target. + (tls_test_shared2.so): New target. + (tls_shared_gd_to_ie_test_SOURCES): New variable. + (tls_shared_gd_to_ie_test_DEPENDENCIES): New variable. + (tls_shared_gd_to_ie_test_LDFLAGS): New variable. + (tls_shared_gd_to_ie_test_LDADD): New variable. + (tls_shared_gnu2_gd_to_ie_test): New target. + (tls_test_gnu2.o, tls_test_file2_gnu2.o, tls_test_gnu2_shared2.so): + New targets. + (tls_shared_gnu2_gd_to_ie_test_SOURCES): New variable. + (ls_shared_gnu2_gd_to_ie_test_DEPENDENCIES): New variable. + (tls_shared_gnu2_gd_to_ie_test_LDFLAGS): New variable. + (tls_shared_gnu2_gd_to_ie_test_LDADD): New variable. + (tls_shared_gnu2_test): New target. + (tls_test_gnu2_shared.so): New target. + (tls_shared_gnu2_test_SOURCES): New variable. + (tls_shared_gnu2_test_DEPENDENCIES): New variable. + (tls_shared_gnu2_test_LDFLAGS): New variable. + (tls_shared_gnu2_test_LDADD): New variable. + * testsuite/Makefile.in: Rebuild. + * testsuite/Makefile. + +2008-04-11 Ian Lance Taylor + + * testsuite/Makefile.am (justsyms_2r.o): Add dependency on + justsyms.t. + * testsuite/Makefile.in: Rebuild. + + * testsuite/script_test_2a.cc (script_test_string_a): Make 8 bytes + long. + * testsuite/script_test_2.cc (main): Adjust test. + +2008-04-11 David S. Miller + Ian Lance Taylor + + * options.h (General_options): Add entries for '-Y' and + '-relax'. + * options.cc (General_options:finalize): If -Y was used, add those + entries to the library path instead of the default "/lib" and + "/usr/lib". + +2008-04-11 David S. Miller + + * testsuite/justsyms.t: Start at 0x100. + * testsuite/justsyms_1.cc: Adjust justsyms_string assertion. + * testsuite/script_test_2b.cc (script_test_string_b): Make 8 bytes + long. + * testsuite/script_test_2.cc: Adjust string and section length + checks. + +2008-04-09 Ian Lance Taylor + + PR gold/5996 + * script-sections.cc (Sections_element::allocate_to_segment): Add + orphan parameter. + (Output_section_definition::allocate_to_segment): Likewise. + (Orphan_output_section::allocate_to_segment): Likewise. + (Script_sections::attach_sections_using_phdrs_clause): Don't + propagate non-PT_LOAD segments to orphan sections. + * testsuite/Makefile.am (script_test_3.stdout): Generate using + readelf rather than objdump. + * testsuite/script_test_3.sh: Adjust accordingly. Test that + .interp section and PT_INTERP segment are the same size. + * testsuite/Makefile.in: Rebuild. + + * symtab.cc (Symbol_table::add_from_dynobj): Only look for weak + aliases for symbols defined in the same object. + * testsuite/Makefile.am (check_PROGRAMS): Add weak_alias_test. + (weak_alias_test_SOURCES): New variable. + (weak_alias_test_DEPENDENCIES): New variable. + (weak_alias_test_LDFLAGS): New variable. + (weak_alias_test_LDADD): New variable. + (weak_alias_test_1_pic.o, weak_alias_test_1.so): New targets. + (weak_alias_test_2_pic.o, weak_alias_test_2.so): New targets. + (weak_alias_test_3.o): New target. + (weak_alias_test_4_pic.o, weak_alias_test_4.so): New targets. + * testsuite/weak_alias_test_main.cc: New file. + * testsuite/weak_alias_test_1.cc: New file. + * testsuite/weak_alias_test_2.cc: New file. + * testsuite/weak_alias_test_3.cc: New file. + +2008-04-08 Ian Lance Taylor + + * options.h (class General_options): Add --noinhibit-exec option. + * main.cc (main): Check --noinhibit-exec. + + * options.h (class General_options): Define --wrap as a special + option. Add wrap_symbols_ field. + (General_options::any_wrap_symbols): New function. + (General_options::is_wrap_symbol): New function. + * options.cc (General_options::parse_wrap): New function. + (General_options::General_options): Initialize wrap_symbols_. + * symtab.cc (Symbol_table::wrap_symbol): New function. + (Symbol_table::add_from_object): Handle --wrap. + * symtab.h (class Symbol_table): Declare wrap_symbol. + * target.h (Target::wrap_char): New function. + (Target::Target_info): Add wrap_char field. + * i386.cc (Target_i386::i386_info): Initialize wrap_char. + * x86_64.cc (Target_x86_64::x86_64_info): Likewise. + * testsuite/testfile.cc (Target_test::test_target_info): + Likewise. + + * errors.cc (Errors::undefined_symbol): Mention symbol version if + there is one. + + * layout.h (class Layout): Add added_eh_frame_data_ field. + * layout.cc (Layout::Layout): Initialize new field. + (Layout::layout_eh_frame): Don't add eh_frame_data_ to .eh_frame + output section until we find a section we merged successfully. + * object.cc (Sized_relobj::check_eh_frame_flags): Don't require + that the size be non-zero. + + * merge.cc (Object_merge_map::get_output_offset): Remove inline + qualifier. + +2008-04-08 Craig Silverstein + + * configure.ac: Export new conditional variable HAVE_ZLIB. + * testsuite/Makefile.am (flagstest_o_specialfile): Condition + on HAVE_ZLIB. + (flagstest_o_specialfile_and_compress_debug_sections): Likewise. + * configure, Makefile.in, testsuite/Makefile.in: Rebuild. + +2008-04-07 Ian Lance Taylor + + * version.cc (version_string): Set to "1.5". + + * x86_64.cc (Target_x86_64::Scan): Change from struct to class. + Add issued_non_pic_error_ field. Declare check_non_pic. + (Target_x86_64::Scan::check_non_pic): New function. + (Target_x86_64::Scan::local): Call check_non_pic as appropriate. + (Target_x86_64::Scan::global): Likewise. + + * output.cc (Output_reloc::local_section_offset): Add + addend parameter. Change caller. Handle merge sections. + (Output_reloc::symbol_value): Change parameter type from + Address to Addend. Don't add in the result of + local_section_offset, pass down the addend and use the returned + value. + * output.h (class Output_reloc): Add Addend typedef. + Update declarations of local_section_offset and symbol_value. + * testsuite/two_file_test_1.cc (t18): New function. + * testsuite/two_file_test_2.cc (f18): New function. + * testsuite/two_file_test_main.cc (main): Call t18. + * testsuite/two_file_test.h (t18, f18): Declare. + + * configure.ac: Don't test for objdump, c++filt, or readelf. + * testsuite/Makefile.am: Remove READELF and OBJDUMP_AND_CPPFILT + conditionals. + (TEST_READELF): New variable. + (TEST_OBJDUMP, TEST_CXXFILT, TEST_STRIP): New variables. + (check_PROGRAMS): Add two_file_strip_test. + (two_file_strip_test): New target. + (check_PROGRAMS): Add two_file_same_shared_strip_test. + (two_file_same_shared_strip_test_SOURCES): New variable. + (two_file_same_shared_strip_test_DEPENDENCIES): New variable. + (two_file_same_shared_strip_test_LDFLAGS): New variable. + (two_file_same_shared_strip_test_LDADD): New variable. + (two_file_shared_strip.so): New target. + (ver_test_2.syms, ver_test_4.syms): Use TEST_READELF. + (ver_test_5.syms, ver_test_7.syms): Likewise. + (ver_matching_test.stdout): Use TEST_OBJDUMP and TEST_CXXFILT. + (strip_test_3.stdout): Use TEST_OBJDUMP. + * configure, Makefile.in, testsuite/Makefile.in: Rebuild. + +2008-04-04 Cary Coutant + + * symtab.h (Symbol::is_weak_undefined): New function. + (Symbol::is_strong_undefined): New function. + (Symbol::is_absolute): New function. + (Symbol::needs_plt_entry): Exclude weak undefined symbols. + (Symbol::needs_dynamic_reloc): Exclude weak undefined and + absolute symbols. + * testsuite/Makefile.am (check_PROGRAMS): Add weak_undef_test. + (weak_undef_test): New target. + * testsuite/Makefile.in: Rebuild. + * testsuite/weak_undef_file1.cc: New file. + * testsuite/weak_undef_file2.cc: New file. + * testsuite/weak_undef_test.cc: New file. + +2008-04-03 Craig Silverstein + + * compressed_output.h (class Output_compressed_section): Use + unsigned buffer. + * compressed_output.cc (zlib_compress): Use unsigned buffers, + add zlib header. + (zlib_compressed_suffix): Removed. + (Output_compressed_section::set_final_data_size): Use unsigned + buffers. + * testsuite/Makefile.am (flagstest_compress_debug_sections): + Fix linker invocation. + (flagstest_o_specialfile_and_compress_debug_sections): + Likewise. + * testsuite/Makefile.in: Regenerated. + +2008-04-02 David S. Miller + + * dwarf_reader.cc (Sized_dwarf_line_info::read_header_prolog, + Sized_dwarf_line_info::process_one_opcode): Use Swap_unaligned. + +2008-04-02 Craig Silverstein + + * TODO: New file. + +2008-04-02 Ian Lance Taylor + + * fileread.cc (File_read::find_view): Add byteshift and vshifted + parameters. Update for new key type to views_. Change all + callers. + (File_read::read): Adjust for byteshift in returned view. + (File_read::add_view): New function, broken out of + find_and_make_view. + (File_read::make_view): New function, broken out of + find_and_make_view. + (File_read::find_or_make_view): Add offset and aligned + parameters. Rewrite accordingly. Change all callers. + (File_read::get_view): Add offset and aligned parameters. Adjust + for byteshift in return value. + (File_read::get_lasting_view): Likewise. + * fileread.h (class File_read): Update declarations. + (class File_read::View): Add byteshift_ field. Add byteshift to + constructor. Add byteshift method. + * archive.h (Archive::clear_uncached_views): New function. + (Archive::get_view): Add aligned parameter. Change all callers. + * object.h (Object::get_view): Add aligned parameter. Change all + callers. + (Object::get_lasting_view): Likewise. + + * fileread.cc (File_read::release): Don't call clear_views if + there are multiple objects. + * fileread.h (File_read::clear_uncached_views): New function. + * archive.cc (Add_archive_symbols::run): Call clear_uncached_views + on the archive. + +2008-03-31 Cary Coutant + + Add thin archive support. + * archive.cc (Archive::armagt): New const. + (Archive::setup): Remove task parameter and calls to unlock. + (Archive::unlock_nested_archives): New function. + (Archive::read_header): Add nested_off parameter. Change + all callers. + (Archive::interpret_header): Likewise. + (Archive::include_all_members): Change to handle thin + archives. + (Archive::include_member): Likewise. + * archive.h (Archive::Archive): Add new parameters and + initializers. + (Archive::armagt): New const. + (Archive::setup): Remove task parameter. + (Archive::unlock_nested_archives): New function. + (Archive::read_header): Add nested_off parameter. + (Archive::interpret_header): Likewise. + (Archive::Nested_archive_table): New typedef. + (Archive::is_thin_archive_): New field. + (Archive::nested_archives_): New field. + (Archive::options_): New field. + (Archive::dirpath_): New field. + (Archive::task_): New field. + * readsyms.cc (Read_symbols::do_read_symbols): Add check + for thin archives. Pass additional parameters to + Archive::Archive. Unlock the archive file after calling + Archive::setup. + +2008-03-29 Ian Lance Taylor + + * symtab.cc (Symbol_table::do_define_as_constant): Don't force a + version symbol to be local. + * testsuite/ver_test_4.sh: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_4.sh. + (check_DATA): Add ver_test_4.syms. + (ver_test_4.syms): New target. + * testsuite/Makefile.in: Rebuild. + + * output.cc + (Output_section::Input_section_sort_entry::has_priority): New + function. + (Output_section::Input_section_sort_entry::match_file_name): New + function. + (Output_section::Input_section_sort_entry::match_section_name): + Remove. + (Output_section::Input_section_sort_entry::match_section_name_prefix): + Remove. + (Output_section::Input_section_sort_entry::match_section_file): + Remove. + (Output_section::Input_section_sort_compare::operator()): Rewrite + using new Input_section_sort_entry functions. Sort crtbegin and + crtend first. Sort sections with no priority before sections with + a priority. + * testsuite/initpri1.c (d3): Check j != 4. + (cd5): New constructor/destructor function. + (main): Check j != 2. + + * symtab.cc (Symbol_table::add_from_object): If we don't use the + new symbol when resolving, don't call set_is_default. + * testsuite/ver_test_7.cc: New file. + * testsuite/ver_test_7.sh: New file. + * testsuite/Makefile.am (ver_test_7.so): New target. + (ver_test_7.o): New target. + (check_SCRIPTS): Add ver_test_7.sh. + (check_DATA): Add ver_test_7.syms. + (ver_test_7.syms): New target. + +2008-03-28 Ian Lance Taylor + + * layout.cc (Layout::layout): If we see an input section with a + name that needs sorting, set the must_sort flag for the output + section. + (Layout::make_output_section): If the name of the output section + indicates that it might require sorting, set the may_sort flag. + * output.h (Output_section::may_sort_attached_input_sections): New + function. + (Output_section::set_may_sort_attached_input_sections): New + function. + (Output_section::must_sort_attached_input_sections): New + function. + (Output_section::set_must_sort_attached_input_sections): New + function. + (class Output_section): Declare Input_section_sort_entry. Define + Input_section_sort_compare. Declare + sort_attached_input_sections. Add new fields: + may_sort_attached_input_sections_, + must_sort_attached_input_sections_, + attached_input_sections_are_sorted_. + * output.cc (Output_section::Output_section): Initialize new + fields. + (Output_section::add_input_section): Add an entry to + input_sections_ if may_sort or must_sort are true. + (Output_section::set_final_data_size): Call + sort_attached_input_sections if necessary. + (Output_section::Input_section_sort_entry): Define new class. + (Output_section::Input_section_sort_compare::operator()): New + function. + (Output_section::sort_attached_input_sections): New function. + * configure.ac: Check whether the compiler supports constructor + priorities. Define a CONSTRUCTOR_PRIORITY automake conditional. + * testsuite/initpri1.c: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add initpri1 if + CONSTRUCTOR_PRIORITY. + (initpri1_SOURCES, initpri1_DEPENDENCIES): New variables. + (initpri1_LDFLAGS): New variable. + * configure, Makefile.in, testsuite/Makefile.in: Rebuild. + +2008-03-27 Ian Lance Taylor + + * common.cc (Sort_commons::operator): Correct sorting algorithm. + * testsuite/common_test_1.c: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add common_test_1. + (common_test_1_SOURCES): New variable. + (common_test_1_DEPENDENCIES): New variable. + (common_test_1_LDFLAGS): New variable. + + * symtab.cc (Symbol_table::add_from_object): Handle saw_undefined_ + and commons_ correctly when NAME/VERSION does not override + NAME/NULL. + * testsuite/ver_test_6.c: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add ver_test_6 + (ver_test_6_SOURCES, ver_test_6_DEPENDENCIES): New variables. + (ver_test_6_LDFLAGS, ver_test_6_LDADD): New variables. + +2008-03-26 Ian Lance Taylor + + * symtab.cc (Symbol_table::add_from_relobj): Don't set the version + of an undefined symbol from a version script. + * testsuite/Makefile.am (ver_test_5.so): New target. + (ver_test_5.o): New target. + (check_SCRIPTS): Add ver_test_5.sh. + (check_DATA): Add ver_test_5.syms. + (ver_test_5.syms): New target. + * testsuite/ver_test_5.cc: New file. + * testsuite/ver_test_5.script: New file. + * testsuite/ver_test_5.sh: New file. + * Makefile.in, testsuite/Makefile.in: Rebuild. + + PR gold/5986 + Fix problems building gold with gcc 4.3.0. + * gold.h (TEMPLATE_ATTRIBUTE_PRINTF_4): Define. + (gold_error_at_location, gold_warning_at_location): Use it. + * configure.ac: Check whether we can compile and use a template + function with a printf attribute. + * x86_64.cc (Target_x86_64::do_code_fill): Swap out a 32-bit value + when jumping over bytes. + * object.cc: Instantiate Object::read_section_data. + * debug.h: Include + * dwarf_reader.cc: Include + * main.cc: Include . + * options.cc: Include . + * output.cc: Include . + * script.cc: Include . + * script.h: Include . + * symtab.cc: Include and . + * target-select.cc: Include . + * version.cc: Include . + * testsuite/testmain.cc: Include . + * configure, config.in: Rebuild. + +2008-03-25 Ian Lance Taylor + + * options.cc: Include "../bfd/bfdver.h". + (options::help): Print bug reporting address. + + * version.cc (print_version): Adjust output for current value of + BFD_VERSION_STRING. + + * NEWS: New file. + + * options.cc (options::help): Print list of supported targets. + * target-select.h: Include . + (class Target_selector): Make machine_, size_, and is_big_endian_ + fields const. Add bfd_name_ and instantiated_target_ fields. + (Target_selector::Target_selector): Add bfd_name parameter. + (Target_selector::recognize): Make non-virtual, call + do_recognize. + (Target_selector::recognize_by_name): Make non-virtual, call + do_recognize_by_name. + (Target_selector::supported_names): New function. + (Target_selector::bfd_name): New function. + (Target_selector::do_instantiate_target): New pure virtual + function. + (Target_selector::do_recognize): New virtual function. + (Target_selector::do_recognize_by_name): New virtual function. + (Target_selector::instantiate_target): New private function. + (supported_target_names): Declare. + * target-select.cc (Target_selector::Target_selector): Update for + new parameter and fields. + (select_target_by_name): Check that the name matches before + calling recognize_by_name. + (supported_target_names): New function. + * i386.cc (class Target_selector_i386): Update Target_selector + constructor call. Remove recognize and recognize_by_name. Add + do_instantiate_target. + * x86_64.cc (class Target_selector_x86_64): Likewise. + * testsuite/testfile.cc (class Target_selector_test): Update for + changes to Target_selector. + + * README: Rewrite, with some notes on unsupported features. + +2008-03-24 Cary Coutant + + * i386.cc (Target_i386::Got_type): New enum declaration. + (Target_i386::Scan::local): Updated callers of Output_data_got + member functions. + (Target_i386::Scan::global): Likewise. + (Target_i386::Relocate::relocate): Likewise. + (Target_i386::Relocate::relocate_tls): Likewise. + * object.h (Got_offset_list): New class. + (Sized_relobj::local_has_got_offset): Added got_type parameter. + (Sized_relobj::local_got_offset): Likewise. + (Sized_relobj::set_local_got_offset): Likewise. + (Sized_relobj::local_has_tls_got_offset): Removed. + (Sized_relobj::local_tls_got_offset): Removed. + (Sized_relobj::set_local_tls_got_offset): Removed. + (Sized_relobj::Local_got_offsets): Changed to store a list of offsets. + * output.cc (Output_data_got::add_global): Added got_type parameter. + (Output_data_got::add_global_with_rel): Likewise. + (Output_data_got::add_global_with_rela): Likewise. + (Output_data_got::add_global_pair_with_rel): New function. + (Output_data_got::add_global_pair_with_rela): New function. + (Output_data_got::add_local): Added got_type parameter. + (Output_data_got::add_local_with_rel): Likewise. + (Output_data_got::add_local_with_rela): Likewise. + (Output_data_got::add_local_pair_with_rel): New function. + (Output_data_got::add_local_pair_with_rela): New function. + (Output_data_got::add_global_tls): Removed. + (Output_data_got::add_global_tls_with_rel): Removed. + (Output_data_got::add_global_tls_with_rela): Removed. + (Output_data_got::add_local_tls): Removed. + (Output_data_got::add_local_tls_with_rel): Removed. + (Output_data_got::add_local_tls_with_rela): Removed. + * output.h (Output_data_got::add_global): Added got_type parameter. + (Output_data_got::add_global_with_rel): Likewise. + (Output_data_got::add_global_with_rela): Likewise. + (Output_data_got::add_global_pair_with_rel): New function. + (Output_data_got::add_global_pair_with_rela): New function. + (Output_data_got::add_local): Added got_type parameter. + (Output_data_got::add_local_with_rel): Likewise. + (Output_data_got::add_local_with_rela): Likewise. + (Output_data_got::add_local_pair_with_rel): New function. + (Output_data_got::add_local_pair_with_rela): New function. + (Output_data_got::add_global_tls): Removed. + (Output_data_got::add_global_tls_with_rel): Removed. + (Output_data_got::add_global_tls_with_rela): Removed. + (Output_data_got::add_local_tls): Removed. + (Output_data_got::add_local_tls_with_rel): Removed. + (Output_data_got::add_local_tls_with_rela): Removed. + * resolve.cc (Symbol::override_base_with_special): Removed + reference to has_got_offset_ field. + * symtab.cc (Symbol::init_fields): Replaced initialization + of got_offset_ with got_offsets_. Removed initialization + of has_got_offset_ + * symtab.h (Symbol::has_got_offset): Aded got_type parameter. + (Symbol::got_offset): Likewise. + (Symbol::set_got_offset): Likewise. + (Symbol::has_tls_got_offset): Removed. + (Symbol::tls_got_offset): Removed. + (Symbol::set_tls_got_offset): Removed. + (Symbol::got_offset_): Removed. + (Symbol::tls_mod_got_offset_): Removed. + (Symbol::tls_pair_got_offset_): Removed. + (Symbol::got_offsets_): New field. + (Symbol::has_got_offset): Removed. + (Symbol::has_tls_mod_got_offset): Removed. + (Symbol::has_tls_pair_got_offset): Removed. + * x86_64.cc (Target_x86_64::Got_type): New enum declaration. + (Target_x86_64::Scan::local): Updated callers of Output_data_got + member functions. + (Target_x86_64::Scan::global): Likewise. + (Target_x86_64::Relocate::relocate): Likewise. + (Target_x86_64::Relocate::relocate_tls): Likewise. + +2008-03-25 Ben Elliston + + * yyscript.y: Fix spelling error in comment. + +2008-03-24 Ian Lance Taylor + + * options.h (class General_options): Define build_id option. + * layout.h (class Layout): Declare write_build_id, create_note, + create_build_id. Add build_id_note_ member. + * layout.cc: Include , , , + "libiberty.h", "md5.h", "sha1.h". + (Layout::Layout): Initialize eh_frame_data_, + eh_frame_hdr_section_, and build_id_note_. + (Layout::finalize): Call create_build_id. + (Layout::create_note): New function, broken out of + Layout::create_gold_note. + (Layout::create_gold_note): Call create_note. + (Layout::create_build_id): New function. + (Layout::write_build_id): New function. + (Close_task_runner::run): Call write_build_id. + + * x86_64.cc: Correct license to GPLv3. + +2008-03-23 Ian Lance Taylor + + * options.cc: Include "demangle.h". + (parse_optional_string): New function. + (parse_long_option): Handle takes_optional_argument. + (parse_short_option): Update dash_z initializer. Handle + takes_optional_argument. + (General_options::General_options): Initialize do_demangle_. + (General_options::finalize): Set do_demangle_. Handle demangling + style. + * options.h (parse_optional_string): Declare. + (struct One_option): Add optional_arg field. Update constructor. + Update call constructor calls. Add takes_optional_argument + function. + (DEFINE_var): Add optional_arg__ parameter. Change all callers. + (DEFINE_optional_string): Define. + (General_options::demangle): Change from DEFINE_bool to + DEFINE_optional_string. + (General_options::no_demangle): New function. + (General_options::do_demangle): New function. + (General_options::set_do_demangle): New function. + (General_options::execstack_status_): Move definition to end of + class definition. + (General_options::static_): Likewise. + (General_options::do_demangle_): New field. + * object.cc (big_endian>::get_symbol_location_info): Call + Options::do_demangle, not Options::demangle. + * symtab.cc (demangle): Likewise. + +2008-03-22 Ian Lance Taylor + + * gold.h: Include and + * options.h: Include . + +2008-03-21 Ian Lance Taylor + + * Added source code to GNU binutils. + diff --git a/gold/script.cc b/gold/script.cc new file mode 100644 index 0000000000..f6e4a396f2 --- /dev/null +++ b/gold/script.cc @@ -0,0 +1,2517 @@ +// script.cc -- handle linker scripts for gold. + +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include +#include +#include +#include +#include +#include +#include "filenames.h" + +#include "elfcpp.h" +#include "demangle.h" +#include "dirsearch.h" +#include "options.h" +#include "fileread.h" +#include "workqueue.h" +#include "readsyms.h" +#include "parameters.h" +#include "layout.h" +#include "symtab.h" +#include "script.h" +#include "script-c.h" + +namespace gold +{ + +// A token read from a script file. We don't implement keywords here; +// all keywords are simply represented as a string. + +class Token +{ + public: + // Token classification. + enum Classification + { + // Token is invalid. + TOKEN_INVALID, + // Token indicates end of input. + TOKEN_EOF, + // Token is a string of characters. + TOKEN_STRING, + // Token is a quoted string of characters. + TOKEN_QUOTED_STRING, + // Token is an operator. + TOKEN_OPERATOR, + // Token is a number (an integer). + TOKEN_INTEGER + }; + + // We need an empty constructor so that we can put this STL objects. + Token() + : classification_(TOKEN_INVALID), value_(NULL), value_length_(0), + opcode_(0), lineno_(0), charpos_(0) + { } + + // A general token with no value. + Token(Classification classification, int lineno, int charpos) + : classification_(classification), value_(NULL), value_length_(0), + opcode_(0), lineno_(lineno), charpos_(charpos) + { + gold_assert(classification == TOKEN_INVALID + || classification == TOKEN_EOF); + } + + // A general token with a value. + Token(Classification classification, const char* value, size_t length, + int lineno, int charpos) + : classification_(classification), value_(value), value_length_(length), + opcode_(0), lineno_(lineno), charpos_(charpos) + { + gold_assert(classification != TOKEN_INVALID + && classification != TOKEN_EOF); + } + + // A token representing an operator. + Token(int opcode, int lineno, int charpos) + : classification_(TOKEN_OPERATOR), value_(NULL), value_length_(0), + opcode_(opcode), lineno_(lineno), charpos_(charpos) + { } + + // Return whether the token is invalid. + bool + is_invalid() const + { return this->classification_ == TOKEN_INVALID; } + + // Return whether this is an EOF token. + bool + is_eof() const + { return this->classification_ == TOKEN_EOF; } + + // Return the token classification. + Classification + classification() const + { return this->classification_; } + + // Return the line number at which the token starts. + int + lineno() const + { return this->lineno_; } + + // Return the character position at this the token starts. + int + charpos() const + { return this->charpos_; } + + // Get the value of a token. + + const char* + string_value(size_t* length) const + { + gold_assert(this->classification_ == TOKEN_STRING + || this->classification_ == TOKEN_QUOTED_STRING); + *length = this->value_length_; + return this->value_; + } + + int + operator_value() const + { + gold_assert(this->classification_ == TOKEN_OPERATOR); + return this->opcode_; + } + + uint64_t + integer_value() const + { + gold_assert(this->classification_ == TOKEN_INTEGER); + // Null terminate. + std::string s(this->value_, this->value_length_); + return strtoull(s.c_str(), NULL, 0); + } + + private: + // The token classification. + Classification classification_; + // The token value, for TOKEN_STRING or TOKEN_QUOTED_STRING or + // TOKEN_INTEGER. + const char* value_; + // The length of the token value. + size_t value_length_; + // The token value, for TOKEN_OPERATOR. + int opcode_; + // The line number where this token started (one based). + int lineno_; + // The character position within the line where this token started + // (one based). + int charpos_; +}; + +// This class handles lexing a file into a sequence of tokens. + +class Lex +{ + public: + // We unfortunately have to support different lexing modes, because + // when reading different parts of a linker script we need to parse + // things differently. + enum Mode + { + // Reading an ordinary linker script. + LINKER_SCRIPT, + // Reading an expression in a linker script. + EXPRESSION, + // Reading a version script. + VERSION_SCRIPT + }; + + Lex(const char* input_string, size_t input_length, int parsing_token) + : input_string_(input_string), input_length_(input_length), + current_(input_string), mode_(LINKER_SCRIPT), + first_token_(parsing_token), token_(), + lineno_(1), linestart_(input_string) + { } + + // Read a file into a string. + static void + read_file(Input_file*, std::string*); + + // Return the next token. + const Token* + next_token(); + + // Return the current lexing mode. + Lex::Mode + mode() const + { return this->mode_; } + + // Set the lexing mode. + void + set_mode(Mode mode) + { this->mode_ = mode; } + + private: + Lex(const Lex&); + Lex& operator=(const Lex&); + + // Make a general token with no value at the current location. + Token + make_token(Token::Classification c, const char* start) const + { return Token(c, this->lineno_, start - this->linestart_ + 1); } + + // Make a general token with a value at the current location. + Token + make_token(Token::Classification c, const char* v, size_t len, + const char* start) + const + { return Token(c, v, len, this->lineno_, start - this->linestart_ + 1); } + + // Make an operator token at the current location. + Token + make_token(int opcode, const char* start) const + { return Token(opcode, this->lineno_, start - this->linestart_ + 1); } + + // Make an invalid token at the current location. + Token + make_invalid_token(const char* start) + { return this->make_token(Token::TOKEN_INVALID, start); } + + // Make an EOF token at the current location. + Token + make_eof_token(const char* start) + { return this->make_token(Token::TOKEN_EOF, start); } + + // Return whether C can be the first character in a name. C2 is the + // next character, since we sometimes need that. + inline bool + can_start_name(char c, char c2); + + // If C can appear in a name which has already started, return a + // pointer to a character later in the token or just past + // it. Otherwise, return NULL. + inline const char* + can_continue_name(const char* c); + + // Return whether C, C2, C3 can start a hex number. + inline bool + can_start_hex(char c, char c2, char c3); + + // If C can appear in a hex number which has already started, return + // a pointer to a character later in the token or just past + // it. Otherwise, return NULL. + inline const char* + can_continue_hex(const char* c); + + // Return whether C can start a non-hex number. + static inline bool + can_start_number(char c); + + // If C can appear in a decimal number which has already started, + // return a pointer to a character later in the token or just past + // it. Otherwise, return NULL. + inline const char* + can_continue_number(const char* c) + { return Lex::can_start_number(*c) ? c + 1 : NULL; } + + // If C1 C2 C3 form a valid three character operator, return the + // opcode. Otherwise return 0. + static inline int + three_char_operator(char c1, char c2, char c3); + + // If C1 C2 form a valid two character operator, return the opcode. + // Otherwise return 0. + static inline int + two_char_operator(char c1, char c2); + + // If C1 is a valid one character operator, return the opcode. + // Otherwise return 0. + static inline int + one_char_operator(char c1); + + // Read the next token. + Token + get_token(const char**); + + // Skip a C style /* */ comment. Return false if the comment did + // not end. + bool + skip_c_comment(const char**); + + // Skip a line # comment. Return false if there was no newline. + bool + skip_line_comment(const char**); + + // Build a token CLASSIFICATION from all characters that match + // CAN_CONTINUE_FN. The token starts at START. Start matching from + // MATCH. Set *PP to the character following the token. + inline Token + gather_token(Token::Classification, + const char* (Lex::*can_continue_fn)(const char*), + const char* start, const char* match, const char** pp); + + // Build a token from a quoted string. + Token + gather_quoted_string(const char** pp); + + // The string we are tokenizing. + const char* input_string_; + // The length of the string. + size_t input_length_; + // The current offset into the string. + const char* current_; + // The current lexing mode. + Mode mode_; + // The code to use for the first token. This is set to 0 after it + // is used. + int first_token_; + // The current token. + Token token_; + // The current line number. + int lineno_; + // The start of the current line in the string. + const char* linestart_; +}; + +// Read the whole file into memory. We don't expect linker scripts to +// be large, so we just use a std::string as a buffer. We ignore the +// data we've already read, so that we read aligned buffers. + +void +Lex::read_file(Input_file* input_file, std::string* contents) +{ + off_t filesize = input_file->file().filesize(); + contents->clear(); + contents->reserve(filesize); + + off_t off = 0; + unsigned char buf[BUFSIZ]; + while (off < filesize) + { + off_t get = BUFSIZ; + if (get > filesize - off) + get = filesize - off; + input_file->file().read(off, get, buf); + contents->append(reinterpret_cast(&buf[0]), get); + off += get; + } +} + +// Return whether C can be the start of a name, if the next character +// is C2. A name can being with a letter, underscore, period, or +// dollar sign. Because a name can be a file name, we also permit +// forward slash, backslash, and tilde. Tilde is the tricky case +// here; GNU ld also uses it as a bitwise not operator. It is only +// recognized as the operator if it is not immediately followed by +// some character which can appear in a symbol. That is, when we +// don't know that we are looking at an expression, "~0" is a file +// name, and "~ 0" is an expression using bitwise not. We are +// compatible. + +inline bool +Lex::can_start_name(char c, char c2) +{ + switch (c) + { + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'Q': case 'P': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'q': case 'p': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '_': case '.': case '$': + return true; + + case '/': case '\\': + return this->mode_ == LINKER_SCRIPT; + + case '~': + return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2); + + case '*': case '[': + return (this->mode_ == VERSION_SCRIPT + || (this->mode_ == LINKER_SCRIPT + && can_continue_name(&c2))); + + default: + return false; + } +} + +// Return whether C can continue a name which has already started. +// Subsequent characters in a name are the same as the leading +// characters, plus digits and "=+-:[],?*". So in general the linker +// script language requires spaces around operators, unless we know +// that we are parsing an expression. + +inline const char* +Lex::can_continue_name(const char* c) +{ + switch (*c) + { + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'Q': case 'P': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'q': case 'p': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '_': case '.': case '$': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return c + 1; + + case '/': case '\\': case '~': + case '=': case '+': + case ',': + if (this->mode_ == LINKER_SCRIPT) + return c + 1; + return NULL; + + case '[': case ']': case '*': case '?': case '-': + if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT) + return c + 1; + return NULL; + + case '^': + if (this->mode_ == VERSION_SCRIPT) + return c + 1; + return NULL; + + case ':': + if (this->mode_ == LINKER_SCRIPT) + return c + 1; + else if (this->mode_ == VERSION_SCRIPT && (c[1] == ':')) + { + // A name can have '::' in it, as that's a c++ namespace + // separator. But a single colon is not part of a name. + return c + 2; + } + return NULL; + + default: + return NULL; + } +} + +// For a number we accept 0x followed by hex digits, or any sequence +// of digits. The old linker accepts leading '$' for hex, and +// trailing HXBOD. Those are for MRI compatibility and we don't +// accept them. The old linker also accepts trailing MK for mega or +// kilo. FIXME: Those are mentioned in the documentation, and we +// should accept them. + +// Return whether C1 C2 C3 can start a hex number. + +inline bool +Lex::can_start_hex(char c1, char c2, char c3) +{ + if (c1 == '0' && (c2 == 'x' || c2 == 'X')) + return this->can_continue_hex(&c3); + return false; +} + +// Return whether C can appear in a hex number. + +inline const char* +Lex::can_continue_hex(const char* c) +{ + switch (*c) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return c + 1; + + default: + return NULL; + } +} + +// Return whether C can start a non-hex number. + +inline bool +Lex::can_start_number(char c) +{ + switch (c) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return true; + + default: + return false; + } +} + +// If C1 C2 C3 form a valid three character operator, return the +// opcode (defined in the yyscript.h file generated from yyscript.y). +// Otherwise return 0. + +inline int +Lex::three_char_operator(char c1, char c2, char c3) +{ + switch (c1) + { + case '<': + if (c2 == '<' && c3 == '=') + return LSHIFTEQ; + break; + case '>': + if (c2 == '>' && c3 == '=') + return RSHIFTEQ; + break; + default: + break; + } + return 0; +} + +// If C1 C2 form a valid two character operator, return the opcode +// (defined in the yyscript.h file generated from yyscript.y). +// Otherwise return 0. + +inline int +Lex::two_char_operator(char c1, char c2) +{ + switch (c1) + { + case '=': + if (c2 == '=') + return EQ; + break; + case '!': + if (c2 == '=') + return NE; + break; + case '+': + if (c2 == '=') + return PLUSEQ; + break; + case '-': + if (c2 == '=') + return MINUSEQ; + break; + case '*': + if (c2 == '=') + return MULTEQ; + break; + case '/': + if (c2 == '=') + return DIVEQ; + break; + case '|': + if (c2 == '=') + return OREQ; + if (c2 == '|') + return OROR; + break; + case '&': + if (c2 == '=') + return ANDEQ; + if (c2 == '&') + return ANDAND; + break; + case '>': + if (c2 == '=') + return GE; + if (c2 == '>') + return RSHIFT; + break; + case '<': + if (c2 == '=') + return LE; + if (c2 == '<') + return LSHIFT; + break; + default: + break; + } + return 0; +} + +// If C1 is a valid operator, return the opcode. Otherwise return 0. + +inline int +Lex::one_char_operator(char c1) +{ + switch (c1) + { + case '+': + case '-': + case '*': + case '/': + case '%': + case '!': + case '&': + case '|': + case '^': + case '~': + case '<': + case '>': + case '=': + case '?': + case ',': + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + return c1; + default: + return 0; + } +} + +// Skip a C style comment. *PP points to just after the "/*". Return +// false if the comment did not end. + +bool +Lex::skip_c_comment(const char** pp) +{ + const char* p = *pp; + while (p[0] != '*' || p[1] != '/') + { + if (*p == '\0') + { + *pp = p; + return false; + } + + if (*p == '\n') + { + ++this->lineno_; + this->linestart_ = p + 1; + } + ++p; + } + + *pp = p + 2; + return true; +} + +// Skip a line # comment. Return false if there was no newline. + +bool +Lex::skip_line_comment(const char** pp) +{ + const char* p = *pp; + size_t skip = strcspn(p, "\n"); + if (p[skip] == '\0') + { + *pp = p + skip; + return false; + } + + p += skip + 1; + ++this->lineno_; + this->linestart_ = p; + *pp = p; + + return true; +} + +// Build a token CLASSIFICATION from all characters that match +// CAN_CONTINUE_FN. Update *PP. + +inline Token +Lex::gather_token(Token::Classification classification, + const char* (Lex::*can_continue_fn)(const char*), + const char* start, + const char* match, + const char **pp) +{ + const char* new_match = NULL; + while ((new_match = (this->*can_continue_fn)(match))) + match = new_match; + *pp = match; + return this->make_token(classification, start, match - start, start); +} + +// Build a token from a quoted string. + +Token +Lex::gather_quoted_string(const char** pp) +{ + const char* start = *pp; + const char* p = start; + ++p; + size_t skip = strcspn(p, "\"\n"); + if (p[skip] != '"') + return this->make_invalid_token(start); + *pp = p + skip + 1; + return this->make_token(Token::TOKEN_QUOTED_STRING, p, skip, start); +} + +// Return the next token at *PP. Update *PP. General guideline: we +// require linker scripts to be simple ASCII. No unicode linker +// scripts. In particular we can assume that any '\0' is the end of +// the input. + +Token +Lex::get_token(const char** pp) +{ + const char* p = *pp; + + while (true) + { + if (*p == '\0') + { + *pp = p; + return this->make_eof_token(p); + } + + // Skip whitespace quickly. + while (*p == ' ' || *p == '\t') + ++p; + + if (*p == '\n') + { + ++p; + ++this->lineno_; + this->linestart_ = p; + continue; + } + + // Skip C style comments. + if (p[0] == '/' && p[1] == '*') + { + int lineno = this->lineno_; + int charpos = p - this->linestart_ + 1; + + *pp = p + 2; + if (!this->skip_c_comment(pp)) + return Token(Token::TOKEN_INVALID, lineno, charpos); + p = *pp; + + continue; + } + + // Skip line comments. + if (*p == '#') + { + *pp = p + 1; + if (!this->skip_line_comment(pp)) + return this->make_eof_token(p); + p = *pp; + continue; + } + + // Check for a name. + if (this->can_start_name(p[0], p[1])) + return this->gather_token(Token::TOKEN_STRING, + &Lex::can_continue_name, + p, p + 1, pp); + + // We accept any arbitrary name in double quotes, as long as it + // does not cross a line boundary. + if (*p == '"') + { + *pp = p; + return this->gather_quoted_string(pp); + } + + // Check for a number. + + if (this->can_start_hex(p[0], p[1], p[2])) + return this->gather_token(Token::TOKEN_INTEGER, + &Lex::can_continue_hex, + p, p + 3, pp); + + if (Lex::can_start_number(p[0])) + return this->gather_token(Token::TOKEN_INTEGER, + &Lex::can_continue_number, + p, p + 1, pp); + + // Check for operators. + + int opcode = Lex::three_char_operator(p[0], p[1], p[2]); + if (opcode != 0) + { + *pp = p + 3; + return this->make_token(opcode, p); + } + + opcode = Lex::two_char_operator(p[0], p[1]); + if (opcode != 0) + { + *pp = p + 2; + return this->make_token(opcode, p); + } + + opcode = Lex::one_char_operator(p[0]); + if (opcode != 0) + { + *pp = p + 1; + return this->make_token(opcode, p); + } + + return this->make_token(Token::TOKEN_INVALID, p); + } +} + +// Return the next token. + +const Token* +Lex::next_token() +{ + // The first token is special. + if (this->first_token_ != 0) + { + this->token_ = Token(this->first_token_, 0, 0); + this->first_token_ = 0; + return &this->token_; + } + + this->token_ = this->get_token(&this->current_); + + // Don't let an early null byte fool us into thinking that we've + // reached the end of the file. + if (this->token_.is_eof() + && (static_cast(this->current_ - this->input_string_) + < this->input_length_)) + this->token_ = this->make_invalid_token(this->current_); + + return &this->token_; +} + +// class Symbol_assignment. + +// Add the symbol to the symbol table. This makes sure the symbol is +// there and defined. The actual value is stored later. We can't +// determine the actual value at this point, because we can't +// necessarily evaluate the expression until all ordinary symbols have +// been finalized. + +// The GNU linker lets symbol assignments in the linker script +// silently override defined symbols in object files. We are +// compatible. FIXME: Should we issue a warning? + +void +Symbol_assignment::add_to_table(Symbol_table* symtab) +{ + elfcpp::STV vis = this->hidden_ ? elfcpp::STV_HIDDEN : elfcpp::STV_DEFAULT; + this->sym_ = symtab->define_as_constant(this->name_.c_str(), + NULL, // version + 0, // value + 0, // size + elfcpp::STT_NOTYPE, + elfcpp::STB_GLOBAL, + vis, + 0, // nonvis + this->provide_, + true); // force_override +} + +// Finalize a symbol value. + +void +Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout) +{ + this->finalize_maybe_dot(symtab, layout, false, 0, NULL); +} + +// Finalize a symbol value which can refer to the dot symbol. + +void +Symbol_assignment::finalize_with_dot(Symbol_table* symtab, + const Layout* layout, + uint64_t dot_value, + Output_section* dot_section) +{ + this->finalize_maybe_dot(symtab, layout, true, dot_value, dot_section); +} + +// Finalize a symbol value, internal version. + +void +Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab, + const Layout* layout, + bool is_dot_available, + uint64_t dot_value, + Output_section* dot_section) +{ + // If we were only supposed to provide this symbol, the sym_ field + // will be NULL if the symbol was not referenced. + if (this->sym_ == NULL) + { + gold_assert(this->provide_); + return; + } + + if (parameters->target().get_size() == 32) + { +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) + this->sized_finalize<32>(symtab, layout, is_dot_available, dot_value, + dot_section); +#else + gold_unreachable(); +#endif + } + else if (parameters->target().get_size() == 64) + { +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) + this->sized_finalize<64>(symtab, layout, is_dot_available, dot_value, + dot_section); +#else + gold_unreachable(); +#endif + } + else + gold_unreachable(); +} + +template +void +Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout, + bool is_dot_available, uint64_t dot_value, + Output_section* dot_section) +{ + Output_section* section; + uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true, + is_dot_available, + dot_value, dot_section, + §ion); + Sized_symbol* ssym = symtab->get_sized_symbol(this->sym_); + ssym->set_value(final_val); + if (section != NULL) + ssym->set_output_section(section); +} + +// Set the symbol value if the expression yields an absolute value. + +void +Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, + bool is_dot_available, uint64_t dot_value) +{ + if (this->sym_ == NULL) + return; + + Output_section* val_section; + uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false, + is_dot_available, dot_value, + NULL, &val_section); + if (val_section != NULL) + return; + + if (parameters->target().get_size() == 32) + { +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) + Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(this->sym_); + ssym->set_value(val); +#else + gold_unreachable(); +#endif + } + else if (parameters->target().get_size() == 64) + { +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) + Sized_symbol<64>* ssym = symtab->get_sized_symbol<64>(this->sym_); + ssym->set_value(val); +#else + gold_unreachable(); +#endif + } + else + gold_unreachable(); +} + +// Print for debugging. + +void +Symbol_assignment::print(FILE* f) const +{ + if (this->provide_ && this->hidden_) + fprintf(f, "PROVIDE_HIDDEN("); + else if (this->provide_) + fprintf(f, "PROVIDE("); + else if (this->hidden_) + gold_unreachable(); + + fprintf(f, "%s = ", this->name_.c_str()); + this->val_->print(f); + + if (this->provide_ || this->hidden_) + fprintf(f, ")"); + + fprintf(f, "\n"); +} + +// Class Script_assertion. + +// Check the assertion. + +void +Script_assertion::check(const Symbol_table* symtab, const Layout* layout) +{ + if (!this->check_->eval(symtab, layout, true)) + gold_error("%s", this->message_.c_str()); +} + +// Print for debugging. + +void +Script_assertion::print(FILE* f) const +{ + fprintf(f, "ASSERT("); + this->check_->print(f); + fprintf(f, ", \"%s\")\n", this->message_.c_str()); +} + +// Class Script_options. + +Script_options::Script_options() + : entry_(), symbol_assignments_(), version_script_info_(), + script_sections_() +{ +} + +// Add a symbol to be defined. + +void +Script_options::add_symbol_assignment(const char* name, size_t length, + Expression* value, bool provide, + bool hidden) +{ + if (length != 1 || name[0] != '.') + { + if (this->script_sections_.in_sections_clause()) + this->script_sections_.add_symbol_assignment(name, length, value, + provide, hidden); + else + { + Symbol_assignment* p = new Symbol_assignment(name, length, value, + provide, hidden); + this->symbol_assignments_.push_back(p); + } + } + else + { + if (provide || hidden) + gold_error(_("invalid use of PROVIDE for dot symbol")); + if (!this->script_sections_.in_sections_clause()) + gold_error(_("invalid assignment to dot outside of SECTIONS")); + else + this->script_sections_.add_dot_assignment(value); + } +} + +// Add an assertion. + +void +Script_options::add_assertion(Expression* check, const char* message, + size_t messagelen) +{ + if (this->script_sections_.in_sections_clause()) + this->script_sections_.add_assertion(check, message, messagelen); + else + { + Script_assertion* p = new Script_assertion(check, message, messagelen); + this->assertions_.push_back(p); + } +} + +// Create sections required by any linker scripts. + +void +Script_options::create_script_sections(Layout* layout) +{ + if (this->saw_sections_clause()) + this->script_sections_.create_sections(layout); +} + +// Add any symbols we are defining to the symbol table. + +void +Script_options::add_symbols_to_table(Symbol_table* symtab) +{ + for (Symbol_assignments::iterator p = this->symbol_assignments_.begin(); + p != this->symbol_assignments_.end(); + ++p) + (*p)->add_to_table(symtab); + this->script_sections_.add_symbols_to_table(symtab); +} + +// Finalize symbol values. Also check assertions. + +void +Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout) +{ + // We finalize the symbols defined in SECTIONS first, because they + // are the ones which may have changed. This way if symbol outside + // SECTIONS are defined in terms of symbols inside SECTIONS, they + // will get the right value. + this->script_sections_.finalize_symbols(symtab, layout); + + for (Symbol_assignments::iterator p = this->symbol_assignments_.begin(); + p != this->symbol_assignments_.end(); + ++p) + (*p)->finalize(symtab, layout); + + for (Assertions::iterator p = this->assertions_.begin(); + p != this->assertions_.end(); + ++p) + (*p)->check(symtab, layout); +} + +// Set section addresses. We set all the symbols which have absolute +// values. Then we let the SECTIONS clause do its thing. This +// returns the segment which holds the file header and segment +// headers, if any. + +Output_segment* +Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout) +{ + for (Symbol_assignments::iterator p = this->symbol_assignments_.begin(); + p != this->symbol_assignments_.end(); + ++p) + (*p)->set_if_absolute(symtab, layout, false, 0); + + return this->script_sections_.set_section_addresses(symtab, layout); +} + +// This class holds data passed through the parser to the lexer and to +// the parser support functions. This avoids global variables. We +// can't use global variables because we need not be called by a +// singleton thread. + +class Parser_closure +{ + public: + Parser_closure(const char* filename, + const Position_dependent_options& posdep_options, + bool in_group, bool is_in_sysroot, + Command_line* command_line, + Script_options* script_options, + Lex* lex) + : filename_(filename), posdep_options_(posdep_options), + in_group_(in_group), is_in_sysroot_(is_in_sysroot), + command_line_(command_line), script_options_(script_options), + version_script_info_(script_options->version_script_info()), + lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL) + { + // We start out processing C symbols in the default lex mode. + language_stack_.push_back(""); + lex_mode_stack_.push_back(lex->mode()); + } + + // Return the file name. + const char* + filename() const + { return this->filename_; } + + // Return the position dependent options. The caller may modify + // this. + Position_dependent_options& + position_dependent_options() + { return this->posdep_options_; } + + // Return whether this script is being run in a group. + bool + in_group() const + { return this->in_group_; } + + // Return whether this script was found using a directory in the + // sysroot. + bool + is_in_sysroot() const + { return this->is_in_sysroot_; } + + // Returns the Command_line structure passed in at constructor time. + // This value may be NULL. The caller may modify this, which modifies + // the passed-in Command_line object (not a copy). + Command_line* + command_line() + { return this->command_line_; } + + // Return the options which may be set by a script. + Script_options* + script_options() + { return this->script_options_; } + + // Return the object in which version script information should be stored. + Version_script_info* + version_script() + { return this->version_script_info_; } + + // Return the next token, and advance. + const Token* + next_token() + { + const Token* token = this->lex_->next_token(); + this->lineno_ = token->lineno(); + this->charpos_ = token->charpos(); + return token; + } + + // Set a new lexer mode, pushing the current one. + void + push_lex_mode(Lex::Mode mode) + { + this->lex_mode_stack_.push_back(this->lex_->mode()); + this->lex_->set_mode(mode); + } + + // Pop the lexer mode. + void + pop_lex_mode() + { + gold_assert(!this->lex_mode_stack_.empty()); + this->lex_->set_mode(this->lex_mode_stack_.back()); + this->lex_mode_stack_.pop_back(); + } + + // Return the current lexer mode. + Lex::Mode + lex_mode() const + { return this->lex_mode_stack_.back(); } + + // Return the line number of the last token. + int + lineno() const + { return this->lineno_; } + + // Return the character position in the line of the last token. + int + charpos() const + { return this->charpos_; } + + // Return the list of input files, creating it if necessary. This + // is a space leak--we never free the INPUTS_ pointer. + Input_arguments* + inputs() + { + if (this->inputs_ == NULL) + this->inputs_ = new Input_arguments(); + return this->inputs_; + } + + // Return whether we saw any input files. + bool + saw_inputs() const + { return this->inputs_ != NULL && !this->inputs_->empty(); } + + // Return the current language being processed in a version script + // (eg, "C++"). The empty string represents unmangled C names. + const std::string& + get_current_language() const + { return this->language_stack_.back(); } + + // Push a language onto the stack when entering an extern block. + void push_language(const std::string& lang) + { this->language_stack_.push_back(lang); } + + // Pop a language off of the stack when exiting an extern block. + void pop_language() + { + gold_assert(!this->language_stack_.empty()); + this->language_stack_.pop_back(); + } + + private: + // The name of the file we are reading. + const char* filename_; + // The position dependent options. + Position_dependent_options posdep_options_; + // Whether we are currently in a --start-group/--end-group. + bool in_group_; + // Whether the script was found in a sysrooted directory. + bool is_in_sysroot_; + // May be NULL if the user chooses not to pass one in. + Command_line* command_line_; + // Options which may be set from any linker script. + Script_options* script_options_; + // Information parsed from a version script. + Version_script_info* version_script_info_; + // The lexer. + Lex* lex_; + // The line number of the last token returned by next_token. + int lineno_; + // The column number of the last token returned by next_token. + int charpos_; + // A stack of lexer modes. + std::vector lex_mode_stack_; + // A stack of which extern/language block we're inside. Can be C++, + // java, or empty for C. + std::vector language_stack_; + // New input files found to add to the link. + Input_arguments* inputs_; +}; + +// FILE was found as an argument on the command line. Try to read it +// as a script. Return true if the file was handled. + +bool +read_input_script(Workqueue* workqueue, const General_options& options, + Symbol_table* symtab, Layout* layout, + Dirsearch* dirsearch, Input_objects* input_objects, + Mapfile* mapfile, Input_group* input_group, + const Input_argument* input_argument, + Input_file* input_file, Task_token* next_blocker, + bool* used_next_blocker) +{ + *used_next_blocker = false; + + std::string input_string; + Lex::read_file(input_file, &input_string); + + Lex lex(input_string.c_str(), input_string.length(), PARSING_LINKER_SCRIPT); + + Parser_closure closure(input_file->filename().c_str(), + input_argument->file().options(), + input_group != NULL, + input_file->is_in_sysroot(), + NULL, + layout->script_options(), + &lex); + + if (yyparse(&closure) != 0) + return false; + + if (!closure.saw_inputs()) + return true; + + Task_token* this_blocker = NULL; + for (Input_arguments::const_iterator p = closure.inputs()->begin(); + p != closure.inputs()->end(); + ++p) + { + Task_token* nb; + if (p + 1 == closure.inputs()->end()) + nb = next_blocker; + else + { + nb = new Task_token(true); + nb->add_blocker(); + } + workqueue->queue_soon(new Read_symbols(options, input_objects, symtab, + layout, dirsearch, mapfile, &*p, + input_group, this_blocker, nb)); + this_blocker = nb; + } + + *used_next_blocker = true; + + return true; +} + +// Helper function for read_version_script() and +// read_commandline_script(). Processes the given file in the mode +// indicated by first_token and lex_mode. + +static bool +read_script_file(const char* filename, Command_line* cmdline, + int first_token, Lex::Mode lex_mode) +{ + // TODO: if filename is a relative filename, search for it manually + // using "." + cmdline->options()->search_path() -- not dirsearch. + Dirsearch dirsearch; + + // The file locking code wants to record a Task, but we haven't + // started the workqueue yet. This is only for debugging purposes, + // so we invent a fake value. + const Task* task = reinterpret_cast(-1); + + // We don't want this file to be opened in binary mode. + Position_dependent_options posdep = cmdline->position_dependent_options(); + if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY) + posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF); + Input_file_argument input_argument(filename, false, "", false, posdep); + Input_file input_file(&input_argument); + if (!input_file.open(cmdline->options(), dirsearch, task)) + return false; + + std::string input_string; + Lex::read_file(&input_file, &input_string); + + Lex lex(input_string.c_str(), input_string.length(), first_token); + lex.set_mode(lex_mode); + + Parser_closure closure(filename, + cmdline->position_dependent_options(), + false, + input_file.is_in_sysroot(), + cmdline, + &cmdline->script_options(), + &lex); + if (yyparse(&closure) != 0) + { + input_file.file().unlock(task); + return false; + } + + input_file.file().unlock(task); + + gold_assert(!closure.saw_inputs()); + + return true; +} + +// FILENAME was found as an argument to --script (-T). +// Read it as a script, and execute its contents immediately. + +bool +read_commandline_script(const char* filename, Command_line* cmdline) +{ + return read_script_file(filename, cmdline, + PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT); +} + +// FILE was found as an argument to --version-script. Read it as a +// version script, and store its contents in +// cmdline->script_options()->version_script_info(). + +bool +read_version_script(const char* filename, Command_line* cmdline) +{ + return read_script_file(filename, cmdline, + PARSING_VERSION_SCRIPT, Lex::VERSION_SCRIPT); +} + +// Implement the --defsym option on the command line. Return true if +// all is well. + +bool +Script_options::define_symbol(const char* definition) +{ + Lex lex(definition, strlen(definition), PARSING_DEFSYM); + lex.set_mode(Lex::EXPRESSION); + + // Dummy value. + Position_dependent_options posdep_options; + + Parser_closure closure("command line", posdep_options, false, false, NULL, + this, &lex); + + if (yyparse(&closure) != 0) + return false; + + gold_assert(!closure.saw_inputs()); + + return true; +} + +// Print the script to F for debugging. + +void +Script_options::print(FILE* f) const +{ + fprintf(f, "%s: Dumping linker script\n", program_name); + + if (!this->entry_.empty()) + fprintf(f, "ENTRY(%s)\n", this->entry_.c_str()); + + for (Symbol_assignments::const_iterator p = + this->symbol_assignments_.begin(); + p != this->symbol_assignments_.end(); + ++p) + (*p)->print(f); + + for (Assertions::const_iterator p = this->assertions_.begin(); + p != this->assertions_.end(); + ++p) + (*p)->print(f); + + this->script_sections_.print(f); + + this->version_script_info_.print(f); +} + +// Manage mapping from keywords to the codes expected by the bison +// parser. We construct one global object for each lex mode with +// keywords. + +class Keyword_to_parsecode +{ + public: + // The structure which maps keywords to parsecodes. + struct Keyword_parsecode + { + // Keyword. + const char* keyword; + // Corresponding parsecode. + int parsecode; + }; + + Keyword_to_parsecode(const Keyword_parsecode* keywords, + int keyword_count) + : keyword_parsecodes_(keywords), keyword_count_(keyword_count) + { } + + // Return the parsecode corresponding KEYWORD, or 0 if it is not a + // keyword. + int + keyword_to_parsecode(const char* keyword, size_t len) const; + + private: + const Keyword_parsecode* keyword_parsecodes_; + const int keyword_count_; +}; + +// Mapping from keyword string to keyword parsecode. This array must +// be kept in sorted order. Parsecodes are looked up using bsearch. +// This array must correspond to the list of parsecodes in yyscript.y. + +static const Keyword_to_parsecode::Keyword_parsecode +script_keyword_parsecodes[] = +{ + { "ABSOLUTE", ABSOLUTE }, + { "ADDR", ADDR }, + { "ALIGN", ALIGN_K }, + { "ALIGNOF", ALIGNOF }, + { "ASSERT", ASSERT_K }, + { "AS_NEEDED", AS_NEEDED }, + { "AT", AT }, + { "BIND", BIND }, + { "BLOCK", BLOCK }, + { "BYTE", BYTE }, + { "CONSTANT", CONSTANT }, + { "CONSTRUCTORS", CONSTRUCTORS }, + { "CREATE_OBJECT_SYMBOLS", CREATE_OBJECT_SYMBOLS }, + { "DATA_SEGMENT_ALIGN", DATA_SEGMENT_ALIGN }, + { "DATA_SEGMENT_END", DATA_SEGMENT_END }, + { "DATA_SEGMENT_RELRO_END", DATA_SEGMENT_RELRO_END }, + { "DEFINED", DEFINED }, + { "ENTRY", ENTRY }, + { "EXCLUDE_FILE", EXCLUDE_FILE }, + { "EXTERN", EXTERN }, + { "FILL", FILL }, + { "FLOAT", FLOAT }, + { "FORCE_COMMON_ALLOCATION", FORCE_COMMON_ALLOCATION }, + { "GROUP", GROUP }, + { "HLL", HLL }, + { "INCLUDE", INCLUDE }, + { "INHIBIT_COMMON_ALLOCATION", INHIBIT_COMMON_ALLOCATION }, + { "INPUT", INPUT }, + { "KEEP", KEEP }, + { "LENGTH", LENGTH }, + { "LOADADDR", LOADADDR }, + { "LONG", LONG }, + { "MAP", MAP }, + { "MAX", MAX_K }, + { "MEMORY", MEMORY }, + { "MIN", MIN_K }, + { "NEXT", NEXT }, + { "NOCROSSREFS", NOCROSSREFS }, + { "NOFLOAT", NOFLOAT }, + { "ONLY_IF_RO", ONLY_IF_RO }, + { "ONLY_IF_RW", ONLY_IF_RW }, + { "OPTION", OPTION }, + { "ORIGIN", ORIGIN }, + { "OUTPUT", OUTPUT }, + { "OUTPUT_ARCH", OUTPUT_ARCH }, + { "OUTPUT_FORMAT", OUTPUT_FORMAT }, + { "OVERLAY", OVERLAY }, + { "PHDRS", PHDRS }, + { "PROVIDE", PROVIDE }, + { "PROVIDE_HIDDEN", PROVIDE_HIDDEN }, + { "QUAD", QUAD }, + { "SEARCH_DIR", SEARCH_DIR }, + { "SECTIONS", SECTIONS }, + { "SEGMENT_START", SEGMENT_START }, + { "SHORT", SHORT }, + { "SIZEOF", SIZEOF }, + { "SIZEOF_HEADERS", SIZEOF_HEADERS }, + { "SORT", SORT_BY_NAME }, + { "SORT_BY_ALIGNMENT", SORT_BY_ALIGNMENT }, + { "SORT_BY_NAME", SORT_BY_NAME }, + { "SPECIAL", SPECIAL }, + { "SQUAD", SQUAD }, + { "STARTUP", STARTUP }, + { "SUBALIGN", SUBALIGN }, + { "SYSLIB", SYSLIB }, + { "TARGET", TARGET_K }, + { "TRUNCATE", TRUNCATE }, + { "VERSION", VERSIONK }, + { "global", GLOBAL }, + { "l", LENGTH }, + { "len", LENGTH }, + { "local", LOCAL }, + { "o", ORIGIN }, + { "org", ORIGIN }, + { "sizeof_headers", SIZEOF_HEADERS }, +}; + +static const Keyword_to_parsecode +script_keywords(&script_keyword_parsecodes[0], + (sizeof(script_keyword_parsecodes) + / sizeof(script_keyword_parsecodes[0]))); + +static const Keyword_to_parsecode::Keyword_parsecode +version_script_keyword_parsecodes[] = +{ + { "extern", EXTERN }, + { "global", GLOBAL }, + { "local", LOCAL }, +}; + +static const Keyword_to_parsecode +version_script_keywords(&version_script_keyword_parsecodes[0], + (sizeof(version_script_keyword_parsecodes) + / sizeof(version_script_keyword_parsecodes[0]))); + +// Comparison function passed to bsearch. + +extern "C" +{ + +struct Ktt_key +{ + const char* str; + size_t len; +}; + +static int +ktt_compare(const void* keyv, const void* kttv) +{ + const Ktt_key* key = static_cast(keyv); + const Keyword_to_parsecode::Keyword_parsecode* ktt = + static_cast(kttv); + int i = strncmp(key->str, ktt->keyword, key->len); + if (i != 0) + return i; + if (ktt->keyword[key->len] != '\0') + return -1; + return 0; +} + +} // End extern "C". + +int +Keyword_to_parsecode::keyword_to_parsecode(const char* keyword, + size_t len) const +{ + Ktt_key key; + key.str = keyword; + key.len = len; + void* kttv = bsearch(&key, + this->keyword_parsecodes_, + this->keyword_count_, + sizeof(this->keyword_parsecodes_[0]), + ktt_compare); + if (kttv == NULL) + return 0; + Keyword_parsecode* ktt = static_cast(kttv); + return ktt->parsecode; +} + +// The following structs are used within the VersionInfo class as well +// as in the bison helper functions. They store the information +// parsed from the version script. + +// A single version expression. +// For example, pattern="std::map*" and language="C++". +// pattern and language should be from the stringpool +struct Version_expression { + Version_expression(const std::string& pattern, + const std::string& language, + bool exact_match) + : pattern(pattern), language(language), exact_match(exact_match) {} + + std::string pattern; + std::string language; + // If false, we use glob() to match pattern. If true, we use strcmp(). + bool exact_match; +}; + + +// A list of expressions. +struct Version_expression_list { + std::vector expressions; +}; + + +// A list of which versions upon which another version depends. +// Strings should be from the Stringpool. +struct Version_dependency_list { + std::vector dependencies; +}; + + +// The total definition of a version. It includes the tag for the +// version, its global and local expressions, and any dependencies. +struct Version_tree { + Version_tree() + : tag(), global(NULL), local(NULL), dependencies(NULL) {} + + std::string tag; + const struct Version_expression_list* global; + const struct Version_expression_list* local; + const struct Version_dependency_list* dependencies; +}; + +Version_script_info::~Version_script_info() +{ + this->clear(); +} + +void +Version_script_info::clear() +{ + for (size_t k = 0; k < dependency_lists_.size(); ++k) + delete dependency_lists_[k]; + this->dependency_lists_.clear(); + for (size_t k = 0; k < version_trees_.size(); ++k) + delete version_trees_[k]; + this->version_trees_.clear(); + for (size_t k = 0; k < expression_lists_.size(); ++k) + delete expression_lists_[k]; + this->expression_lists_.clear(); +} + +std::vector +Version_script_info::get_versions() const +{ + std::vector ret; + for (size_t j = 0; j < version_trees_.size(); ++j) + if (!this->version_trees_[j]->tag.empty()) + ret.push_back(this->version_trees_[j]->tag); + return ret; +} + +std::vector +Version_script_info::get_dependencies(const char* version) const +{ + std::vector ret; + for (size_t j = 0; j < version_trees_.size(); ++j) + if (version_trees_[j]->tag == version) + { + const struct Version_dependency_list* deps = + version_trees_[j]->dependencies; + if (deps != NULL) + for (size_t k = 0; k < deps->dependencies.size(); ++k) + ret.push_back(deps->dependencies[k]); + return ret; + } + return ret; +} + +// Look up SYMBOL_NAME in the list of versions. If CHECK_GLOBAL is +// true look at the globally visible symbols, otherwise look at the +// symbols listed as "local:". Return true if the symbol is found, +// false otherwise. If the symbol is found, then if PVERSION is not +// NULL, set *PVERSION to the version. + +bool +Version_script_info::get_symbol_version_helper(const char* symbol_name, + bool check_global, + std::string* pversion) const +{ + for (size_t j = 0; j < version_trees_.size(); ++j) + { + // Is it a global symbol for this version? + const Version_expression_list* explist = + check_global ? version_trees_[j]->global : version_trees_[j]->local; + if (explist != NULL) + for (size_t k = 0; k < explist->expressions.size(); ++k) + { + const char* name_to_match = symbol_name; + const struct Version_expression& exp = explist->expressions[k]; + char* demangled_name = NULL; + if (exp.language == "C++") + { + demangled_name = cplus_demangle(symbol_name, + DMGL_ANSI | DMGL_PARAMS); + // This isn't a C++ symbol. + if (demangled_name == NULL) + continue; + name_to_match = demangled_name; + } + else if (exp.language == "Java") + { + demangled_name = cplus_demangle(symbol_name, + (DMGL_ANSI | DMGL_PARAMS + | DMGL_JAVA)); + // This isn't a Java symbol. + if (demangled_name == NULL) + continue; + name_to_match = demangled_name; + } + bool matched; + if (exp.exact_match) + matched = strcmp(exp.pattern.c_str(), name_to_match) == 0; + else + matched = fnmatch(exp.pattern.c_str(), name_to_match, + FNM_NOESCAPE) == 0; + if (demangled_name != NULL) + free(demangled_name); + if (matched) + { + if (pversion != NULL) + *pversion = this->version_trees_[j]->tag; + return true; + } + } + } + return false; +} + +struct Version_dependency_list* +Version_script_info::allocate_dependency_list() +{ + dependency_lists_.push_back(new Version_dependency_list); + return dependency_lists_.back(); +} + +struct Version_expression_list* +Version_script_info::allocate_expression_list() +{ + expression_lists_.push_back(new Version_expression_list); + return expression_lists_.back(); +} + +struct Version_tree* +Version_script_info::allocate_version_tree() +{ + version_trees_.push_back(new Version_tree); + return version_trees_.back(); +} + +// Print for debugging. + +void +Version_script_info::print(FILE* f) const +{ + if (this->empty()) + return; + + fprintf(f, "VERSION {"); + + for (size_t i = 0; i < this->version_trees_.size(); ++i) + { + const Version_tree* vt = this->version_trees_[i]; + + if (vt->tag.empty()) + fprintf(f, " {\n"); + else + fprintf(f, " %s {\n", vt->tag.c_str()); + + if (vt->global != NULL) + { + fprintf(f, " global :\n"); + this->print_expression_list(f, vt->global); + } + + if (vt->local != NULL) + { + fprintf(f, " local :\n"); + this->print_expression_list(f, vt->local); + } + + fprintf(f, " }"); + if (vt->dependencies != NULL) + { + const Version_dependency_list* deps = vt->dependencies; + for (size_t j = 0; j < deps->dependencies.size(); ++j) + { + if (j < deps->dependencies.size() - 1) + fprintf(f, "\n"); + fprintf(f, " %s", deps->dependencies[j].c_str()); + } + } + fprintf(f, ";\n"); + } + + fprintf(f, "}\n"); +} + +void +Version_script_info::print_expression_list( + FILE* f, + const Version_expression_list* vel) const +{ + std::string current_language; + for (size_t i = 0; i < vel->expressions.size(); ++i) + { + const Version_expression& ve(vel->expressions[i]); + + if (ve.language != current_language) + { + if (!current_language.empty()) + fprintf(f, " }\n"); + fprintf(f, " extern \"%s\" {\n", ve.language.c_str()); + current_language = ve.language; + } + + fprintf(f, " "); + if (!current_language.empty()) + fprintf(f, " "); + + if (ve.exact_match) + fprintf(f, "\""); + fprintf(f, "%s", ve.pattern.c_str()); + if (ve.exact_match) + fprintf(f, "\""); + + fprintf(f, "\n"); + } + + if (!current_language.empty()) + fprintf(f, " }\n"); +} + +} // End namespace gold. + +// The remaining functions are extern "C", so it's clearer to not put +// them in namespace gold. + +using namespace gold; + +// This function is called by the bison parser to return the next +// token. + +extern "C" int +yylex(YYSTYPE* lvalp, void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + const Token* token = closure->next_token(); + switch (token->classification()) + { + default: + gold_unreachable(); + + case Token::TOKEN_INVALID: + yyerror(closurev, "invalid character"); + return 0; + + case Token::TOKEN_EOF: + return 0; + + case Token::TOKEN_STRING: + { + // This is either a keyword or a STRING. + size_t len; + const char* str = token->string_value(&len); + int parsecode = 0; + switch (closure->lex_mode()) + { + case Lex::LINKER_SCRIPT: + parsecode = script_keywords.keyword_to_parsecode(str, len); + break; + case Lex::VERSION_SCRIPT: + parsecode = version_script_keywords.keyword_to_parsecode(str, len); + break; + default: + break; + } + if (parsecode != 0) + return parsecode; + lvalp->string.value = str; + lvalp->string.length = len; + return STRING; + } + + case Token::TOKEN_QUOTED_STRING: + lvalp->string.value = token->string_value(&lvalp->string.length); + return QUOTED_STRING; + + case Token::TOKEN_OPERATOR: + return token->operator_value(); + + case Token::TOKEN_INTEGER: + lvalp->integer = token->integer_value(); + return INTEGER; + } +} + +// This function is called by the bison parser to report an error. + +extern "C" void +yyerror(void* closurev, const char* message) +{ + Parser_closure* closure = static_cast(closurev); + gold_error(_("%s:%d:%d: %s"), closure->filename(), closure->lineno(), + closure->charpos(), message); +} + +// Called by the bison parser to add a file to the link. + +extern "C" void +script_add_file(void* closurev, const char* name, size_t length) +{ + Parser_closure* closure = static_cast(closurev); + + // If this is an absolute path, and we found the script in the + // sysroot, then we want to prepend the sysroot to the file name. + // For example, this is how we handle a cross link to the x86_64 + // libc.so, which refers to /lib/libc.so.6. + std::string name_string(name, length); + const char* extra_search_path = "."; + std::string script_directory; + if (IS_ABSOLUTE_PATH(name_string.c_str())) + { + if (closure->is_in_sysroot()) + { + const std::string& sysroot(parameters->options().sysroot()); + gold_assert(!sysroot.empty()); + name_string = sysroot + name_string; + } + } + else + { + // In addition to checking the normal library search path, we + // also want to check in the script-directory. + const char *slash = strrchr(closure->filename(), '/'); + if (slash != NULL) + { + script_directory.assign(closure->filename(), + slash - closure->filename() + 1); + extra_search_path = script_directory.c_str(); + } + } + + Input_file_argument file(name_string.c_str(), false, extra_search_path, + false, closure->position_dependent_options()); + closure->inputs()->add_file(file); +} + +// Called by the bison parser to start a group. If we are already in +// a group, that means that this script was invoked within a +// --start-group --end-group sequence on the command line, or that +// this script was found in a GROUP of another script. In that case, +// we simply continue the existing group, rather than starting a new +// one. It is possible to construct a case in which this will do +// something other than what would happen if we did a recursive group, +// but it's hard to imagine why the different behaviour would be +// useful for a real program. Avoiding recursive groups is simpler +// and more efficient. + +extern "C" void +script_start_group(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + if (!closure->in_group()) + closure->inputs()->start_group(); +} + +// Called by the bison parser at the end of a group. + +extern "C" void +script_end_group(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + if (!closure->in_group()) + closure->inputs()->end_group(); +} + +// Called by the bison parser to start an AS_NEEDED list. + +extern "C" void +script_start_as_needed(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->position_dependent_options().set_as_needed(true); +} + +// Called by the bison parser at the end of an AS_NEEDED list. + +extern "C" void +script_end_as_needed(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->position_dependent_options().set_as_needed(false); +} + +// Called by the bison parser to set the entry symbol. + +extern "C" void +script_set_entry(void* closurev, const char* entry, size_t length) +{ + // We'll parse this exactly the same as --entry=ENTRY on the commandline + // TODO(csilvers): FIXME -- call set_entry directly. + std::string arg("--entry="); + arg.append(entry, length); + script_parse_option(closurev, arg.c_str(), arg.size()); +} + +// Called by the bison parser to set whether to define common symbols. + +extern "C" void +script_set_common_allocation(void* closurev, int set) +{ + const char* arg = set != 0 ? "--define-common" : "--no-define-common"; + script_parse_option(closurev, arg, strlen(arg)); +} + +// Called by the bison parser to define a symbol. + +extern "C" void +script_set_symbol(void* closurev, const char* name, size_t length, + Expression* value, int providei, int hiddeni) +{ + Parser_closure* closure = static_cast(closurev); + const bool provide = providei != 0; + const bool hidden = hiddeni != 0; + closure->script_options()->add_symbol_assignment(name, length, value, + provide, hidden); +} + +// Called by the bison parser to add an assertion. + +extern "C" void +script_add_assertion(void* closurev, Expression* check, const char* message, + size_t messagelen) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->add_assertion(check, message, messagelen); +} + +// Called by the bison parser to parse an OPTION. + +extern "C" void +script_parse_option(void* closurev, const char* option, size_t length) +{ + Parser_closure* closure = static_cast(closurev); + // We treat the option as a single command-line option, even if + // it has internal whitespace. + if (closure->command_line() == NULL) + { + // There are some options that we could handle here--e.g., + // -lLIBRARY. Should we bother? + gold_warning(_("%s:%d:%d: ignoring command OPTION; OPTION is only valid" + " for scripts specified via -T/--script"), + closure->filename(), closure->lineno(), closure->charpos()); + } + else + { + bool past_a_double_dash_option = false; + const char* mutable_option = strndup(option, length); + gold_assert(mutable_option != NULL); + closure->command_line()->process_one_option(1, &mutable_option, 0, + &past_a_double_dash_option); + // The General_options class will quite possibly store a pointer + // into mutable_option, so we can't free it. In cases the class + // does not store such a pointer, this is a memory leak. Alas. :( + } +} + +// Called by the bison parser to handle SEARCH_DIR. This is handled +// exactly like a -L option. + +extern "C" void +script_add_search_dir(void* closurev, const char* option, size_t length) +{ + Parser_closure* closure = static_cast(closurev); + if (closure->command_line() == NULL) + gold_warning(_("%s:%d:%d: ignoring SEARCH_DIR; SEARCH_DIR is only valid" + " for scripts specified via -T/--script"), + closure->filename(), closure->lineno(), closure->charpos()); + else + { + std::string s = "-L" + std::string(option, length); + script_parse_option(closurev, s.c_str(), s.size()); + } +} + +/* Called by the bison parser to push the lexer into expression + mode. */ + +extern "C" void +script_push_lex_into_expression_mode(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->push_lex_mode(Lex::EXPRESSION); +} + +/* Called by the bison parser to push the lexer into version + mode. */ + +extern "C" void +script_push_lex_into_version_mode(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->push_lex_mode(Lex::VERSION_SCRIPT); +} + +/* Called by the bison parser to pop the lexer mode. */ + +extern "C" void +script_pop_lex_mode(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->pop_lex_mode(); +} + +// Register an entire version node. For example: +// +// GLIBC_2.1 { +// global: foo; +// } GLIBC_2.0; +// +// - tag is "GLIBC_2.1" +// - tree contains the information "global: foo" +// - deps contains "GLIBC_2.0" + +extern "C" void +script_register_vers_node(void*, + const char* tag, + int taglen, + struct Version_tree *tree, + struct Version_dependency_list *deps) +{ + gold_assert(tree != NULL); + tree->dependencies = deps; + if (tag != NULL) + tree->tag = std::string(tag, taglen); +} + +// Add a dependencies to the list of existing dependencies, if any, +// and return the expanded list. + +extern "C" struct Version_dependency_list * +script_add_vers_depend(void* closurev, + struct Version_dependency_list *all_deps, + const char *depend_to_add, int deplen) +{ + Parser_closure* closure = static_cast(closurev); + if (all_deps == NULL) + all_deps = closure->version_script()->allocate_dependency_list(); + all_deps->dependencies.push_back(std::string(depend_to_add, deplen)); + return all_deps; +} + +// Add a pattern expression to an existing list of expressions, if any. +// TODO: In the old linker, the last argument used to be a bool, but I +// don't know what it meant. + +extern "C" struct Version_expression_list * +script_new_vers_pattern(void* closurev, + struct Version_expression_list *expressions, + const char *pattern, int patlen, int exact_match) +{ + Parser_closure* closure = static_cast(closurev); + if (expressions == NULL) + expressions = closure->version_script()->allocate_expression_list(); + expressions->expressions.push_back( + Version_expression(std::string(pattern, patlen), + closure->get_current_language(), + static_cast(exact_match))); + return expressions; +} + +// Attaches b to the end of a, and clears b. So a = a + b and b = {}. + +extern "C" struct Version_expression_list* +script_merge_expressions(struct Version_expression_list *a, + struct Version_expression_list *b) +{ + a->expressions.insert(a->expressions.end(), + b->expressions.begin(), b->expressions.end()); + // We could delete b and remove it from expressions_lists_, but + // that's a lot of work. This works just as well. + b->expressions.clear(); + return a; +} + +// Combine the global and local expressions into a a Version_tree. + +extern "C" struct Version_tree * +script_new_vers_node(void* closurev, + struct Version_expression_list *global, + struct Version_expression_list *local) +{ + Parser_closure* closure = static_cast(closurev); + Version_tree* tree = closure->version_script()->allocate_version_tree(); + tree->global = global; + tree->local = local; + return tree; +} + +// Handle a transition in language, such as at the +// start or end of 'extern "C++"' + +extern "C" void +version_script_push_lang(void* closurev, const char* lang, int langlen) +{ + Parser_closure* closure = static_cast(closurev); + closure->push_language(std::string(lang, langlen)); +} + +extern "C" void +version_script_pop_lang(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->pop_language(); +} + +// Called by the bison parser to start a SECTIONS clause. + +extern "C" void +script_start_sections(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->script_sections()->start_sections(); +} + +// Called by the bison parser to finish a SECTIONS clause. + +extern "C" void +script_finish_sections(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->script_sections()->finish_sections(); +} + +// Start processing entries for an output section. + +extern "C" void +script_start_output_section(void* closurev, const char* name, size_t namelen, + const struct Parser_output_section_header* header) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->script_sections()->start_output_section(name, + namelen, + header); +} + +// Finish processing entries for an output section. + +extern "C" void +script_finish_output_section(void* closurev, + const struct Parser_output_section_trailer* trail) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->script_sections()->finish_output_section(trail); +} + +// Add a data item (e.g., "WORD (0)") to the current output section. + +extern "C" void +script_add_data(void* closurev, int data_token, Expression* val) +{ + Parser_closure* closure = static_cast(closurev); + int size; + bool is_signed = true; + switch (data_token) + { + case QUAD: + size = 8; + is_signed = false; + break; + case SQUAD: + size = 8; + break; + case LONG: + size = 4; + break; + case SHORT: + size = 2; + break; + case BYTE: + size = 1; + break; + default: + gold_unreachable(); + } + closure->script_options()->script_sections()->add_data(size, is_signed, val); +} + +// Add a clause setting the fill value to the current output section. + +extern "C" void +script_add_fill(void* closurev, Expression* val) +{ + Parser_closure* closure = static_cast(closurev); + closure->script_options()->script_sections()->add_fill(val); +} + +// Add a new input section specification to the current output +// section. + +extern "C" void +script_add_input_section(void* closurev, + const struct Input_section_spec* spec, + int keepi) +{ + Parser_closure* closure = static_cast(closurev); + bool keep = keepi != 0; + closure->script_options()->script_sections()->add_input_section(spec, keep); +} + +// Create a new list of string/sort pairs. + +extern "C" String_sort_list_ptr +script_new_string_sort_list(const struct Wildcard_section* string_sort) +{ + return new String_sort_list(1, *string_sort); +} + +// Add an entry to a list of string/sort pairs. The way the parser +// works permits us to simply modify the first parameter, rather than +// copy the vector. + +extern "C" String_sort_list_ptr +script_string_sort_list_add(String_sort_list_ptr pv, + const struct Wildcard_section* string_sort) +{ + if (pv == NULL) + return script_new_string_sort_list(string_sort); + else + { + pv->push_back(*string_sort); + return pv; + } +} + +// Create a new list of strings. + +extern "C" String_list_ptr +script_new_string_list(const char* str, size_t len) +{ + return new String_list(1, std::string(str, len)); +} + +// Add an element to a list of strings. The way the parser works +// permits us to simply modify the first parameter, rather than copy +// the vector. + +extern "C" String_list_ptr +script_string_list_push_back(String_list_ptr pv, const char* str, size_t len) +{ + if (pv == NULL) + return script_new_string_list(str, len); + else + { + pv->push_back(std::string(str, len)); + return pv; + } +} + +// Concatenate two string lists. Either or both may be NULL. The way +// the parser works permits us to modify the parameters, rather than +// copy the vector. + +extern "C" String_list_ptr +script_string_list_append(String_list_ptr pv1, String_list_ptr pv2) +{ + if (pv1 == NULL) + return pv2; + if (pv2 == NULL) + return pv1; + pv1->insert(pv1->end(), pv2->begin(), pv2->end()); + return pv1; +} + +// Add a new program header. + +extern "C" void +script_add_phdr(void* closurev, const char* name, size_t namelen, + unsigned int type, const Phdr_info* info) +{ + Parser_closure* closure = static_cast(closurev); + bool includes_filehdr = info->includes_filehdr != 0; + bool includes_phdrs = info->includes_phdrs != 0; + bool is_flags_valid = info->is_flags_valid != 0; + Script_sections* ss = closure->script_options()->script_sections(); + ss->add_phdr(name, namelen, type, includes_filehdr, includes_phdrs, + is_flags_valid, info->flags, info->load_address); +} + +// Convert a program header string to a type. + +#define PHDR_TYPE(NAME) { #NAME, sizeof(#NAME) - 1, elfcpp::NAME } + +static struct +{ + const char* name; + size_t namelen; + unsigned int val; +} phdr_type_names[] = +{ + PHDR_TYPE(PT_NULL), + PHDR_TYPE(PT_LOAD), + PHDR_TYPE(PT_DYNAMIC), + PHDR_TYPE(PT_INTERP), + PHDR_TYPE(PT_NOTE), + PHDR_TYPE(PT_SHLIB), + PHDR_TYPE(PT_PHDR), + PHDR_TYPE(PT_TLS), + PHDR_TYPE(PT_GNU_EH_FRAME), + PHDR_TYPE(PT_GNU_STACK), + PHDR_TYPE(PT_GNU_RELRO) +}; + +extern "C" unsigned int +script_phdr_string_to_type(void* closurev, const char* name, size_t namelen) +{ + for (unsigned int i = 0; + i < sizeof(phdr_type_names) / sizeof(phdr_type_names[0]); + ++i) + if (namelen == phdr_type_names[i].namelen + && strncmp(name, phdr_type_names[i].name, namelen) == 0) + return phdr_type_names[i].val; + yyerror(closurev, _("unknown PHDR type (try integer)")); + return elfcpp::PT_NULL; +} diff --git a/gold/testsuite/script_test_2.cc b/gold/testsuite/script_test_2.cc new file mode 100644 index 0000000000..7104551692 --- /dev/null +++ b/gold/testsuite/script_test_2.cc @@ -0,0 +1,74 @@ +// script_test_2.cc -- linker script test 2 for gold -*- C++ -*- + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// A test of some uses of the SECTIONS clause. Look at +// script_test_2.t to make sense of this test. + +#include +#include +#include +#include + +extern char start_test_area[]; +extern char start_test_area_1[]; +extern char start_data[]; +extern char end_data[]; +extern char start_fill[]; +extern char end_fill[]; +extern char end_test_area[]; +extern char test_addr[]; +extern char test_addr_alias[]; + +int +main(int, char**) +{ + assert(reinterpret_cast(start_test_area) == 0x20000001); + assert(reinterpret_cast(start_test_area_1) == 0x20000010); + + // We should see the string from script_test_2b.o next. The + // subalign should move it up to 0x20000020. + for (int i = 0; i < 16; ++i) + assert(start_test_area_1[i] == 0); + assert(strcmp(start_test_area_1 + 16, "test bb") == 0); + + // Next the string from script_test_2a.o, after the subalign. + for (int i = 16 + 7; i < 48; ++i) + assert(start_test_area_1[i] == 0); + assert(strcmp(start_test_area_1 + 48, "test aa") == 0); + + // Move four bytes forward to start_data. + assert(reinterpret_cast(start_test_area_1 + 48 + 8 + 4) + == reinterpret_cast(start_data)); + assert(memcmp(start_data, "\1\2\0\4\0\0\0\010\0\0\0\0\0\0\0", 15) == 0 + || memcmp(start_data, "\1\0\2\0\0\0\4\0\0\0\0\0\0\0\010", 15) == 0); + assert(end_data == start_data + 15); + + // Check that FILL works as expected. + assert(start_fill == end_data); + assert(memcmp(start_fill, "\x12\x34\x56\x78\x12\x34\x56\0", 8) == 0); + assert(end_fill == start_fill + 8); + + assert(end_test_area == end_fill); + + assert(test_addr == start_test_area_1); + assert(test_addr_alias == test_addr); +} diff --git a/gold/testsuite/script_test_2.t b/gold/testsuite/script_test_2.t new file mode 100644 index 0000000000..73d39df530 --- /dev/null +++ b/gold/testsuite/script_test_2.t @@ -0,0 +1,68 @@ +/* script_test_2.t -- linker script test 2 for gold + + Copyright 2008 Free Software Foundation, Inc. + Written by Ian Lance Taylor . + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +test_addr_alias = test_addr; + +SECTIONS +{ + /* With luck this will work everywhere. */ + . = 0x10000000; + + /* With luck this will be enough to get the program working. */ + .text : { *(.text) } + . += 0x100000; + . = ALIGN(0x100); + .data : { *(.data) } + .bss : { *(.bss) } + + /* Now the real test. */ + . = 0x20000001; + start_test_area = .; + .gold_test ALIGN(16) : SUBALIGN(32) { + start_test_area_1 = .; + + /* No sections should wind up here, because of the EXCLUDE_FILE. */ + *( EXCLUDE_FILE(script_test*) .gold_test) + + /* This should match only script_test_2b.o. */ + script_test_2b.o(.gold_test) + + /* This should match the remaining sections. */ + *(.gold_test) + + . = . + 4; + start_data = .; + BYTE(1) + SHORT(2) + LONG(4) + QUAD(8) + end_data = .; + + start_fill = .; + FILL(0x12345678); + . = . + 7; + BYTE(0) + end_fill = .; + } + end_test_area = .; + test_addr = ADDR(.gold_test); +} -- 2.11.0