From: Doug Kwan Date: Fri, 30 Oct 2009 18:49:59 +0000 (+0000) Subject: 2009-10-30 Doug Kwan X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d5b40221bcfffa99532547f0b94a852d834426aa;p=binutils-gdb.git 2009-10-30 Doug Kwan elfcpp/ChangeLog: * arm.h (EF_ARM_BE8, EF_ARM_EABIMASK, EF_ARM_EABI_UNKNOWN, EF_ARM_EABI_VER1, EF_ARM_EABI_VER2, EF_ARM_EABI_VER3, EF_ARM_EABI_VER4, EF_ARM_EABI_VER5): New enums for processor-specific flags. (arm_eabi_version): New inline function. * elfcpp.h: Add a comment about DT_ENCODING. gold/ChangeLog: * arm.cc (Arm_relobj::processor_specific_flags): New method definition. (Arm_relobj::do_read_symbols): New method declaration. (Arm_relobj::processor_specific_flags_): New data member declaration. (Arm_dynobj): New class definition. (Target_arm::do_finalize_sections): Add input_objects parameter. (Target_arm::do_adjust_elf_header): New method declaration. (Target_arm::are_eabi_versions_compatible, (Target_arm::merge_processor_specific_flags): New method declaration. (Target_arm::do_make_elf_object): New overloaded method definitions and declaration. (Arm_relobj::do_read_symbols): New method definition. (Arm_dynobj::do_read_symbols): Ditto. (Target_arm::do_finalize_sections): Add input_objects parameters. Merge processor-specific flags from all input objects. (Target_arm::are_eabi_versions_compatible, Target_arm::merge_processor_specific_flags, Target_arm::do_adjust_elf_header, Target_arm::do_make_elf_object): New method definitions. * i386.cc (Target_i386::do_finalize_sections): Add unnamed Input_objects pointer type parameter. * layout.cc (Layout::finalize): Pass input objects to target's. finalize_sections function. * output.cc (Output_file_header::do_sized_write): Set ELF file header's processor-specific flags. * powerpc.cc (Target_powerpc::do_finalize_sections): Add unnamed Input_objects pointer type parameter. * sparc.cc (Target_sparc::do_finalize_sections): Same. * target.h (Input_objects): New forward class declaration. (Target::processor_specific_flags, Target::are_processor_specific_flags_sect): New method definitions. (Target::finalize_sections): Add input_objects parameter. (Target::Target): Initialize processor_specific_flags_ and are_processor_specific_flags_set_. (Target::do_finalize_sections): Add unnamed Input_objects pointer type parameter. (Target::set_processor_specific_flags): New method definition. (Target::processor_specific_flags_, Target::are_processor_specific_flags_set_): New data member declarations. * x86_64.cc (Target_x86_64::do_finalize_sections): Add unnamed Input_objects pointer type parameter. --- diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog index 0a9906cc180..243988074e9 100644 --- a/elfcpp/ChangeLog +++ b/elfcpp/ChangeLog @@ -1,3 +1,12 @@ +2009-10-30 Doug Kwan + + * arm.h (EF_ARM_BE8, EF_ARM_EABIMASK, EF_ARM_EABI_UNKNOWN, + EF_ARM_EABI_VER1, EF_ARM_EABI_VER2, EF_ARM_EABI_VER3, + EF_ARM_EABI_VER4, EF_ARM_EABI_VER5): New enums for processor-specific + flags. + (arm_eabi_version): New inline function. + * elfcpp.h: Add a comment about DT_ENCODING. + 2009-10-16 Doug Kwan * elfcpp/elfcpp.h (DT_PREINIT_ARRAY): Correct enum value. diff --git a/elfcpp/arm.h b/elfcpp/arm.h index 7ad827a4221..027cf342247 100644 --- a/elfcpp/arm.h +++ b/elfcpp/arm.h @@ -199,6 +199,29 @@ enum // 160 - 255 Unallocated }; +// e_flags values used for ARM. We only support flags defined in AAELF. + +enum +{ + EF_ARM_BE8 = 0x00800000, + + // Mask to extract EABI version, not really a flag value. + EF_ARM_EABIMASK = 0xFF000000, + + EF_ARM_EABI_UNKNOWN = 0x00000000, + EF_ARM_EABI_VER1 = 0x01000000, + EF_ARM_EABI_VER2 = 0x02000000, + EF_ARM_EABI_VER3 = 0x03000000, + EF_ARM_EABI_VER4 = 0x04000000, + EF_ARM_EABI_VER5 = 0x05000000, +}; + +// Extract EABI version from flags. + +inline Elf_Word +arm_eabi_version(Elf_Word flags) +{ return flags & EF_ARM_EABIMASK; } + } // End namespace elfcpp. #endif // !defined(ELFCPP_ARM_H) diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index c5c93c31d92..4ace47c41a1 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -656,7 +656,11 @@ enum DT DT_FINI_ARRAYSZ = 28, DT_RUNPATH = 29, DT_FLAGS = 30, + + // This is used to mark a range of dynamic tags. It is not really + // a tag value. DT_ENCODING = 32, + DT_PREINIT_ARRAY = 32, DT_PREINIT_ARRAYSZ = 33, DT_LOOS = 0x6000000d, diff --git a/gold/ChangeLog b/gold/ChangeLog index 886b28c9635..a89b6ef58a3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,48 @@ +2009-10-30 Doug Kwan + + * arm.cc (Arm_relobj::processor_specific_flags): New method + definition. + (Arm_relobj::do_read_symbols): New method declaration. + (Arm_relobj::processor_specific_flags_): New data member declaration. + (Arm_dynobj): New class definition. + (Target_arm::do_finalize_sections): Add input_objects parameter. + (Target_arm::do_adjust_elf_header): New method declaration. + (Target_arm::are_eabi_versions_compatible, + (Target_arm::merge_processor_specific_flags): New method declaration. + (Target_arm::do_make_elf_object): New overloaded method definitions + and declaration. + (Arm_relobj::do_read_symbols): New method definition. + (Arm_dynobj::do_read_symbols): Ditto. + (Target_arm::do_finalize_sections): Add input_objects parameters. + Merge processor-specific flags from all input objects. + (Target_arm::are_eabi_versions_compatible, + Target_arm::merge_processor_specific_flags, + Target_arm::do_adjust_elf_header, Target_arm::do_make_elf_object): + New method definitions. + * i386.cc (Target_i386::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + * layout.cc (Layout::finalize): Pass input objects to target's. + finalize_sections function. + * output.cc (Output_file_header::do_sized_write): Set ELF file + header's processor-specific flags. + * powerpc.cc (Target_powerpc::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + * sparc.cc (Target_sparc::do_finalize_sections): Same. + * target.h (Input_objects): New forward class declaration. + (Target::processor_specific_flags, + Target::are_processor_specific_flags_sect): New method definitions. + (Target::finalize_sections): Add input_objects parameter. + (Target::Target): Initialize processor_specific_flags_ and + are_processor_specific_flags_set_. + (Target::do_finalize_sections): Add unnamed Input_objects pointer type + parameter. + (Target::set_processor_specific_flags): New method definition. + (Target::processor_specific_flags_, + Target::are_processor_specific_flags_set_): New data member + declarations. + * x86_64.cc (Target_x86_64::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + 2009-10-30 Doug Kwan * arm.cc: Use Arm_address instead of elfcpp::Elf_types<32>::Elf_Addr. diff --git a/gold/arm.cc b/gold/arm.cc index a25fc213ef0..210ccf73912 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -947,6 +947,12 @@ class Arm_relobj : public Sized_relobj<32, big_endian> as_arm_relobj(Relobj* relobj) { return static_cast*>(relobj); } + // Processor-specific flags in ELF file header. This is valid only after + // reading symbols. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + protected: // Post constructor setup. void @@ -971,6 +977,10 @@ class Arm_relobj : public Sized_relobj<32, big_endian> const unsigned char* pshdrs, typename Sized_relobj<32, big_endian>::Views* pivews); + // Read the symbol information. + void + do_read_symbols(Read_symbols_data* sd); + private: // List of stub tables. typedef std::vector*> Stub_table_list; @@ -978,6 +988,45 @@ class Arm_relobj : public Sized_relobj<32, big_endian> // Bit vector to tell if a local symbol is a thumb function or not. // This is only valid after do_count_local_symbol is called. std::vector local_symbol_is_thumb_function_; + // processor-specific flags in ELF file header. + elfcpp::Elf_Word processor_specific_flags_; +}; + +// Arm_dynobj class. + +template +class Arm_dynobj : public Sized_dynobj<32, big_endian> +{ + public: + Arm_dynobj(const std::string& name, Input_file* input_file, off_t offset, + const elfcpp::Ehdr<32, big_endian>& ehdr) + : Sized_dynobj<32, big_endian>(name, input_file, offset, ehdr), + processor_specific_flags_(0) + { } + + ~Arm_dynobj() + { } + + // Downcast a base pointer to an Arm_relobj pointer. This is + // not type-safe but we only use Arm_relobj not the base class. + static Arm_dynobj* + as_arm_dynobj(Dynobj* dynobj) + { return static_cast*>(dynobj); } + + // Processor-specific flags in ELF file header. This is valid only after + // reading symbols. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + + protected: + // Read the symbol information. + void + do_read_symbols(Read_symbols_data* sd); + + private: + // processor-specific flags in ELF file header. + elfcpp::Elf_Word processor_specific_flags_; }; // Utilities for manipulating integers of up to 32-bits @@ -1120,7 +1169,7 @@ class Target_arm : public Sized_target<32, big_endian> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*); // Return the value to use for a dynamic symbol which requires special // treatment. @@ -1196,6 +1245,10 @@ class Target_arm : public Sized_target<32, big_endian> return static_cast&>(parameters->target()); } + protected: + void + do_adjust_elf_header(unsigned char* view, int len) const; + private: // The class which scans relocations. class Scan @@ -1366,6 +1419,34 @@ class Target_arm : public Sized_target<32, big_endian> this->rel_dyn_section(layout)); } + // Whether two EABI versions are compatible. + static bool + are_eabi_versions_compatible(elfcpp::Elf_Word v1, elfcpp::Elf_Word v2); + + // Merge processor-specific flags from input object and those in the ELF + // header of the output. + void + merge_processor_specific_flags(const std::string&, elfcpp::Elf_Word); + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, big_endian>& ehdr); + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, !big_endian>&) + { gold_unreachable(); } + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<64, false>&) + { gold_unreachable(); } + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<64, true>&) + { gold_unreachable(); } + // Information about this specific target which we pass to the // general Target structure. static const Target::Target_info arm_info; @@ -3250,6 +3331,42 @@ Arm_relobj::do_relocate_sections( } } +// Read the symbol information. + +template +void +Arm_relobj::do_read_symbols(Read_symbols_data* sd) +{ + // Call parent class to read symbol information. + Sized_relobj<32, big_endian>::do_read_symbols(sd); + + // Read processor-specific flags in ELF file header. + const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, + elfcpp::Elf_sizes<32>::ehdr_size, + true, false); + elfcpp::Ehdr<32, big_endian> ehdr(pehdr); + this->processor_specific_flags_ = ehdr.get_e_flags(); +} + +// Arm_dynobj methods. + +// Read the symbol information. + +template +void +Arm_dynobj::do_read_symbols(Read_symbols_data* sd) +{ + // Call parent class to read symbol information. + Sized_dynobj<32, big_endian>::do_read_symbols(sd); + + // Read processor-specific flags in ELF file header. + const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, + elfcpp::Elf_sizes<32>::ehdr_size, + true, false); + elfcpp::Ehdr<32, big_endian> ehdr(pehdr); + this->processor_specific_flags_ = ehdr.get_e_flags(); +} + // A class to handle the PLT data. template @@ -3950,8 +4067,33 @@ Target_arm::scan_relocs(Symbol_table* symtab, template void -Target_arm::do_finalize_sections(Layout* layout) +Target_arm::do_finalize_sections( + Layout* layout, + const Input_objects* input_objects) { + // Merge processor-specific flags. + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Arm_relobj* arm_relobj = + Arm_relobj::as_arm_relobj(*p); + this->merge_processor_specific_flags( + arm_relobj->name(), + arm_relobj->processor_specific_flags()); + } + + for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); + p != input_objects->dynobj_end(); + ++p) + { + Arm_dynobj* arm_dynobj = + Arm_dynobj::as_arm_dynobj(*p); + this->merge_processor_specific_flags( + arm_dynobj->name(), + arm_dynobj->processor_specific_flags()); + } + // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); if (odyn != NULL) @@ -4588,6 +4730,130 @@ Target_arm::get_real_reloc_type (unsigned int r_type) } } +// Whether if two EABI versions V1 and V2 are compatible. + +template +bool +Target_arm::are_eabi_versions_compatible( + elfcpp::Elf_Word v1, + elfcpp::Elf_Word v2) +{ + // v4 and v5 are the same spec before and after it was released, + // so allow mixing them. + if ((v1 == elfcpp::EF_ARM_EABI_VER4 && v2 == elfcpp::EF_ARM_EABI_VER5) + || (v1 == elfcpp::EF_ARM_EABI_VER5 && v2 == elfcpp::EF_ARM_EABI_VER4)) + return true; + + return v1 == v2; +} + +// Combine FLAGS from an input object called NAME and the processor-specific +// flags in the ELF header of the output. Much of this is adapted from the +// processor-specific flags merging code in elf32_arm_merge_private_bfd_data +// in bfd/elf32-arm.c. + +template +void +Target_arm::merge_processor_specific_flags( + const std::string& name, + elfcpp::Elf_Word flags) +{ + if (this->are_processor_specific_flags_set()) + { + elfcpp::Elf_Word out_flags = this->processor_specific_flags(); + + // Nothing to merge if flags equal to those in output. + if (flags == out_flags) + return; + + // Complain about various flag mismatches. + elfcpp::Elf_Word version1 = elfcpp::arm_eabi_version(flags); + elfcpp::Elf_Word version2 = elfcpp::arm_eabi_version(out_flags); + if (!this->are_eabi_versions_compatible(version1, version2)) + gold_error(_("Source object %s has EABI version %d but output has " + "EABI version %d."), + name.c_str(), + (flags & elfcpp::EF_ARM_EABIMASK) >> 24, + (out_flags & elfcpp::EF_ARM_EABIMASK) >> 24); + } + else + { + // If the input is the default architecture and had the default + // flags then do not bother setting the flags for the output + // architecture, instead allow future merges to do this. If no + // future merges ever set these flags then they will retain their + // uninitialised values, which surprise surprise, correspond + // to the default values. + if (flags == 0) + return; + + // This is the first time, just copy the flags. + // We only copy the EABI version for now. + this->set_processor_specific_flags(flags & elfcpp::EF_ARM_EABIMASK); + } +} + +// Adjust ELF file header. +template +void +Target_arm::do_adjust_elf_header( + unsigned char* view, + int len) const +{ + gold_assert(len == elfcpp::Elf_sizes<32>::ehdr_size); + + elfcpp::Ehdr<32, big_endian> ehdr(view); + unsigned char e_ident[elfcpp::EI_NIDENT]; + memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT); + + if (elfcpp::arm_eabi_version(this->processor_specific_flags()) + == elfcpp::EF_ARM_EABI_UNKNOWN) + e_ident[elfcpp::EI_OSABI] = elfcpp::ELFOSABI_ARM; + else + e_ident[elfcpp::EI_OSABI] = 0; + e_ident[elfcpp::EI_ABIVERSION] = 0; + + // FIXME: Do EF_ARM_BE8 adjustment. + + elfcpp::Ehdr_write<32, big_endian> oehdr(view); + oehdr.put_e_ident(e_ident); +} + +// do_make_elf_object to override the same function in the base class. +// We need to use a target-specific sub-class of Sized_relobj<32, big_endian> +// to store ARM specific information. Hence we need to have our own +// ELF object creation. + +template +Object* +Target_arm::do_make_elf_object( + const std::string& name, + Input_file* input_file, + off_t offset, const elfcpp::Ehdr<32, big_endian>& ehdr) +{ + int et = ehdr.get_e_type(); + if (et == elfcpp::ET_REL) + { + Arm_relobj* obj = + new Arm_relobj(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else if (et == elfcpp::ET_DYN) + { + Sized_dynobj<32, big_endian>* obj = + new Arm_dynobj(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else + { + gold_error(_("%s: unsupported ELF file type %d"), + name.c_str(), et); + return NULL; + } +} + // The selector for arm object files. template diff --git a/gold/i386.cc b/gold/i386.cc index 0f270f447e7..2d7168b1252 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -95,7 +95,7 @@ class Target_i386 : public Target_freebsd<32, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*); // Return the value to use for a dynamic which requires special // treatment. @@ -1552,7 +1552,7 @@ Target_i386::scan_relocs(Symbol_table* symtab, // Finalize the sections. void -Target_i386::do_finalize_sections(Layout* layout) +Target_i386::do_finalize_sections(Layout* layout, const Input_objects*) { // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); diff --git a/gold/layout.cc b/gold/layout.cc index 028703ae1ce..07fa12fd7d4 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1509,7 +1509,7 @@ off_t Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, Target* target, const Task* task) { - target->finalize_sections(this); + target->finalize_sections(this, input_objects); this->count_local_symbols(task, input_objects); diff --git a/gold/output.cc b/gold/output.cc index 29dad2b60e4..61e5c875049 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -459,10 +459,7 @@ Output_file_header::do_sized_write(Output_file* of) oehdr.put_e_phoff(this->segment_header_->offset()); oehdr.put_e_shoff(this->section_header_->offset()); - - // FIXME: The target needs to set the flags. - oehdr.put_e_flags(0); - + oehdr.put_e_flags(this->target_->processor_specific_flags()); oehdr.put_e_ehsize(elfcpp::Elf_sizes::ehdr_size); if (this->segment_header_ == NULL) diff --git a/gold/powerpc.cc b/gold/powerpc.cc index a93e89571c2..081a8f5cd8c 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -92,7 +92,7 @@ class Target_powerpc : public Sized_target const unsigned char* plocal_symbols); // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*); // Return the value to use for a dynamic which requires special // treatment. @@ -1530,7 +1530,9 @@ Target_powerpc::scan_relocs( template void -Target_powerpc::do_finalize_sections(Layout* layout) +Target_powerpc::do_finalize_sections( + Layout* layout, + const Input_objects*) { // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); diff --git a/gold/sparc.cc b/gold/sparc.cc index 74a91e9384a..dc825f72d30 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -94,7 +94,7 @@ class Target_sparc : public Sized_target const unsigned char* plocal_symbols); // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*); // Return the value to use for a dynamic which requires special // treatment. @@ -2317,7 +2317,9 @@ Target_sparc::scan_relocs( template void -Target_sparc::do_finalize_sections(Layout* layout) +Target_sparc::do_finalize_sections( + Layout* layout, + const Input_objects*) { // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); diff --git a/gold/target.h b/gold/target.h index bbe06ad8a5a..e301b0b3385 100644 --- a/gold/target.h +++ b/gold/target.h @@ -54,6 +54,7 @@ template class Sized_symbol; class Symbol_table; class Output_section; +class Input_objects; // The abstract class for target specific handling. @@ -79,6 +80,16 @@ class Target machine_code() const { return this->pti_->machine_code; } + // Processor specific flags to store in e_flags field of ELF header. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + + // Whether processor specific flags are set at least once. + bool + are_processor_specific_flags_set() const + { return this->are_processor_specific_flags_set_; } + // Whether this target has a specific make_symbol function. bool has_make_symbol() const @@ -183,8 +194,8 @@ class Target // This is called to tell the target to complete any sections it is // handling. After this all sections must have their final size. void - finalize_sections(Layout* layout) - { return this->do_finalize_sections(layout); } + finalize_sections(Layout* layout, const Input_objects* input_objects) + { return this->do_finalize_sections(layout, input_objects); } // Return the value to use for a global symbol which needs a special // value in the dynamic symbol table. This will only be called if @@ -314,7 +325,8 @@ class Target }; Target(const Target_info* pti) - : pti_(pti) + : pti_(pti), processor_specific_flags_(0), + are_processor_specific_flags_set_(false) { } // Virtual function which may be implemented by the child class. @@ -324,7 +336,7 @@ class Target // Virtual function which may be implemented by the child class. virtual void - do_finalize_sections(Layout*) + do_finalize_sections(Layout*, const Input_objects*) { } // Virtual function which may be implemented by the child class. @@ -364,6 +376,14 @@ class Target // make_elf_object hooks. There are four versions of these for // different address sizes and endianities. + // Set processor specific flags. + void + set_processor_specific_flags(elfcpp::Elf_Word flags) + { + this->processor_specific_flags_ = flags; + this->are_processor_specific_flags_set_ = true; + } + #ifdef HAVE_TARGET_32_LITTLE // Virtual functions which may be overriden by the child class. virtual Object* @@ -433,6 +453,10 @@ class Target // The target information. const Target_info* pti_; + // Processor-specific flags. + elfcpp::Elf_Word processor_specific_flags_; + // Whether the processor-specific flags are set at least once. + bool are_processor_specific_flags_set_; }; // The abstract class for a specific size and endianness of target. diff --git a/gold/x86_64.cc b/gold/x86_64.cc index ea8915c0359..249d1f4cc05 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -102,7 +102,7 @@ class Target_x86_64 : public Target_freebsd<64, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*); // Return the value to use for a dynamic which requires special // treatment. @@ -1642,7 +1642,7 @@ Target_x86_64::scan_relocs(Symbol_table* symtab, // Finalize the sections. void -Target_x86_64::do_finalize_sections(Layout* layout) +Target_x86_64::do_finalize_sections(Layout* layout, const Input_objects*) { // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data();