OSDN Git Service

2009-10-30 Doug Kwan <dougkwan@google.com>
authordougkwan <dougkwan>
Sat, 31 Oct 2009 03:49:59 +0000 (03:49 +0000)
committerdougkwan <dougkwan>
Sat, 31 Oct 2009 03:49:59 +0000 (03:49 +0000)
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.

12 files changed:
elfcpp/ChangeLog
elfcpp/arm.h
elfcpp/elfcpp.h
gold/ChangeLog
gold/arm.cc
gold/i386.cc
gold/layout.cc
gold/output.cc
gold/powerpc.cc
gold/sparc.cc
gold/target.h
gold/x86_64.cc

index 0a9906c..2439880 100644 (file)
@@ -1,3 +1,12 @@
+2009-10-30  Doug Kwan  <dougkwan@google.com>
+
+       * 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  <dougkwan@google.com>
 
        * elfcpp/elfcpp.h (DT_PREINIT_ARRAY): Correct enum value.
index 7ad827a..027cf34 100644 (file)
@@ -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)
index c5c93c3..4ace47c 100644 (file)
@@ -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,
index 886b28c..a89b6ef 100644 (file)
@@ -1,5 +1,50 @@
 2009-10-30  Doug Kwan  <dougkwan@google.com>
 
+       * 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  <dougkwan@google.com>
+
        * arm.cc: Use Arm_address instead of elfcpp::Elf_types<32>::Elf_Addr.
 
 2009-10-28  Ian Lance Taylor  <iant@google.com>
index a25fc21..210ccf7 100644 (file)
@@ -947,6 +947,12 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
   as_arm_relobj(Relobj* relobj)
   { return static_cast<Arm_relobj<big_endian>*>(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<big_endian>*> 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<bool> local_symbol_is_thumb_function_;
+  // processor-specific flags in ELF file header.
+  elfcpp::Elf_Word processor_specific_flags_;
+};
+
+// Arm_dynobj class.
+
+template<bool big_endian>
+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<big_endian>*
+  as_arm_dynobj(Dynobj* dynobj)
+  { return static_cast<Arm_dynobj<big_endian>*>(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<const Target_arm<big_endian>&>(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<big_endian>::do_relocate_sections(
     }
 }
 
+// Read the symbol information.
+
+template<bool big_endian>
+void
+Arm_relobj<big_endian>::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<bool big_endian>
+void
+Arm_dynobj<big_endian>::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<bool big_endian>
@@ -3950,8 +4067,33 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
 
 template<bool big_endian>
 void
-Target_arm<big_endian>::do_finalize_sections(Layout* layout)
+Target_arm<big_endian>::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<big_endian>* arm_relobj =
+       Arm_relobj<big_endian>::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<big_endian>* arm_dynobj =
+       Arm_dynobj<big_endian>::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<big_endian>::get_real_reloc_type (unsigned int r_type)
     }
 }
 
+// Whether if two EABI versions V1 and V2 are compatible.
+
+template<bool big_endian>
+bool
+Target_arm<big_endian>::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<bool big_endian>
+void
+Target_arm<big_endian>::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<bool big_endian>
+void
+Target_arm<big_endian>::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<bool big_endian>
+Object*
+Target_arm<big_endian>::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<big_endian>* obj =
+        new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
+      obj->setup();
+      return obj;
+    }
+  else if (et == elfcpp::ET_DYN)
+    {
+      Sized_dynobj<32, big_endian>* obj =
+        new Arm_dynobj<big_endian>(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<bool big_endian>
index 0f270f4..2d7168b 100644 (file)
@@ -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();
index 028703a..07fa12f 100644 (file)
@@ -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);
 
index 29dad2b..61e5c87 100644 (file)
@@ -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<size>::ehdr_size);
 
   if (this->segment_header_ == NULL)
index a93e895..081a8f5 100644 (file)
@@ -92,7 +92,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
              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<size, big_endian>::scan_relocs(
 
 template<int size, bool big_endian>
 void
-Target_powerpc<size, big_endian>::do_finalize_sections(Layout* layout)
+Target_powerpc<size, big_endian>::do_finalize_sections(
+    Layout* layout,
+    const Input_objects*)
 {
   // Fill in some more dynamic tags.
   Output_data_dynamic* const odyn = layout->dynamic_data();
index 74a91e9..dc825f7 100644 (file)
@@ -94,7 +94,7 @@ class Target_sparc : public Sized_target<size, big_endian>
              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<size, big_endian>::scan_relocs(
 
 template<int size, bool big_endian>
 void
-Target_sparc<size, big_endian>::do_finalize_sections(Layout* layout)
+Target_sparc<size, big_endian>::do_finalize_sections(
+    Layout* layout,
+    const Input_objects*)
 {
   // Fill in some more dynamic tags.
   Output_data_dynamic* const odyn = layout->dynamic_data();
index bbe06ad..e301b0b 100644 (file)
@@ -54,6 +54,7 @@ template<int size>
 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.
index ea8915c..249d1f4 100644 (file)
@@ -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();