[binutils-gdb] Update support for .note.gnu.property sections.

Cary Coutant ccoutant@sourceware.org
Sat Jun 23 06:37:00 GMT 2018


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a2575bec2413d361c6ecfc4aecb2a31c86123f95

commit a2575bec2413d361c6ecfc4aecb2a31c86123f95
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Fri Jun 22 23:36:50 2018 -0700

    Update support for .note.gnu.property sections.
    
    The original patch did not give the target enough hooks to discover that
    an input object file does not have a particular property. For the
    GNU_PROPERTY_X86_FEATURE_1_AND property, for example, where a missing
    property should be assumed to be all zeroes, and ANDed with other
    object modules, this is essential. We now store the target-specific
    properties locally in the Target structure as native uint32_t fields,
    then AND the per-object feature bits with the program's feature bits
    when we're finished processing each input object file. The target-specific
    properties are then added back to the output note section during
    finalization.
    
    gold/
    	PR gold/22914
    	* layout.cc (read_sized_value): Fix spelling of section name.
    	(Layout::layout_gnu_property): Call Sized_target::record_gnu_property
    	for target-specific properties;
    	don't store them with target-independent properties yet.
    	(Layout::merge_gnu_properties): New method.
    	(Layout::add_gnu_property): New method.
    	(Layout::create_gnu_properties_note): Call target to finalize
    	target-specific properties. Fix spelling of output section name.
    	* layout.h (Layout::merge_gnu_properties): New method.
    	(Layout::add_gnu_property): New method.
    	* object.cc (Sized_relobj_file::do_layout): Call
    	Layout::merge_gnu_properties.
    	* target.h (Target::merge_gnu_property): Remove.
    	(Target::finalize_gnu_properties): New method.
    	(Target::do_merge_gnu_property): Move to Sized_target and rename.
    	(Target::do_finalize_gnu_properties): New virtual method.
    	(Sized_target::record_gnu_property): Moved and renamed from
    	Target::do_merge_gnu_property.
    	(Sized_target::merge_gnu_properties): New virtual method.
    	* x86_64.cc (Target_x86_64::isa_1_used_, isa_1_needed_)
    	(feature_1_, object_feature_1_, seen_first_object_): New data members.
    	(Target_x86_64::do_merge_gnu_property): Rename to ...
    	(Target_x86_64::record_gnu_property): ... this.  Save target-specific
    	properties in Target class object.
    	(Target_x86_64::merge_gnu_properties): New method.
    	(add_property): New static inline function.
    	(Target_x86_64::do_finalize_gnu_properties): New method.
    	* testsuite/Makefile.am (gnu_property_test): Remove C source file;
    	link directly without compiler driver.
    	* testsuite/Makefile.in: Regenerate.
    	* testsuite/gnu_property_a.S: Add _start.

Diff:
---
 gold/ChangeLog                  |  35 ++++++++
 gold/layout.cc                  | 186 ++++++++++++++++++++++++++++++++--------
 gold/layout.h                   |  13 ++-
 gold/object.cc                  |   5 +-
 gold/target.h                   |  35 ++++----
 gold/testsuite/Makefile.am      |   4 +-
 gold/testsuite/Makefile.in      |   4 +-
 gold/testsuite/gnu_property_a.S |   5 ++
 gold/x86_64.cc                  | 116 ++++++++++++++++++++-----
 9 files changed, 320 insertions(+), 83 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 1010513..f4c6f0a 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,40 @@
 2018-06-22  Cary Coutant  <ccoutant@gmail.com>
 
+	PR gold/22914
+	* layout.cc (read_sized_value): Fix spelling of section name.
+	(Layout::layout_gnu_property): Call Sized_target::record_gnu_property
+	for target-specific properties;
+	don't store them with target-independent properties yet.
+	(Layout::merge_gnu_properties): New method.
+	(Layout::add_gnu_property): New method.
+	(Layout::create_gnu_properties_note): Call target to finalize
+	target-specific properties. Fix spelling of output section name.
+	* layout.h (Layout::merge_gnu_properties): New method.
+	(Layout::add_gnu_property): New method.
+	* object.cc (Sized_relobj_file::do_layout): Call
+	Layout::merge_gnu_properties.
+	* target.h (Target::merge_gnu_property): Remove.
+	(Target::finalize_gnu_properties): New method.
+	(Target::do_merge_gnu_property): Move to Sized_target and rename.
+	(Target::do_finalize_gnu_properties): New virtual method.
+	(Sized_target::record_gnu_property): Moved and renamed from
+	Target::do_merge_gnu_property.
+	(Sized_target::merge_gnu_properties): New virtual method.
+	* x86_64.cc (Target_x86_64::isa_1_used_, isa_1_needed_)
+	(feature_1_, object_feature_1_, seen_first_object_): New data members.
+	(Target_x86_64::do_merge_gnu_property): Rename to ...
+	(Target_x86_64::record_gnu_property): ... this.  Save target-specific
+	properties in Target class object.
+	(Target_x86_64::merge_gnu_properties): New method.
+	(add_property): New static inline function.
+	(Target_x86_64::do_finalize_gnu_properties): New method.
+	* testsuite/Makefile.am (gnu_property_test): Remove C source file;
+	link directly without compiler driver.
+	* testsuite/Makefile.in: Regenerate.
+	* testsuite/gnu_property_a.S: Add _start.
+
+2018-06-22  Cary Coutant  <ccoutant@gmail.com>
+
 	* incremental.cc (Sized_incremental_binary::setup_readers): Use
 	emplace_back for GCC 5 and later.
 	* incremental.h (Incremental_binary::Input_reader): Provide copy
diff --git a/gold/layout.cc b/gold/layout.cc
index 9ce38c3..0df7ed3 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -2217,7 +2217,7 @@ read_sized_value(size_t size, const unsigned char* buf, bool is_big_endian,
     }
   else
     {
-      gold_warning(_("%s: in .note.gnu.properties section, "
+      gold_warning(_("%s: in .note.gnu.property section, "
 		     "pr_datasz must be 4 or 8"),
 		   object->name().c_str());
     }
@@ -2262,6 +2262,63 @@ Layout::layout_gnu_property(unsigned int note_type,
   // We currently support only the one note type.
   gold_assert(note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0);
 
+  if (pr_type >= elfcpp::GNU_PROPERTY_LOPROC
+      && pr_type < elfcpp::GNU_PROPERTY_HIPROC)
+    {
+      // Target-dependent property value; call the target to record.
+      const int size = parameters->target().get_size();
+      const bool is_big_endian = parameters->target().is_big_endian();
+      if (size == 32)
+        {
+          if (is_big_endian)
+            {
+#ifdef HAVE_TARGET_32_BIG
+	      parameters->sized_target<32, true>()->
+		  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
+				      object);
+#else
+	      gold_unreachable();
+#endif
+            }
+          else
+            {
+#ifdef HAVE_TARGET_32_LITTLE
+	      parameters->sized_target<32, false>()->
+		  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
+				      object);
+#else
+	      gold_unreachable();
+#endif
+            }
+        }
+      else if (size == 64)
+        {
+          if (is_big_endian)
+            {
+#ifdef HAVE_TARGET_64_BIG
+	      parameters->sized_target<64, true>()->
+		  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
+				      object);
+#else
+	      gold_unreachable();
+#endif
+            }
+          else
+            {
+#ifdef HAVE_TARGET_64_LITTLE
+	      parameters->sized_target<64, false>()->
+		  record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
+				      object);
+#else
+	      gold_unreachable();
+#endif
+            }
+        }
+      else
+        gold_unreachable();
+      return;
+    }
+
   Gnu_properties::iterator pprop = this->gnu_properties_.find(pr_type);
   if (pprop == this->gnu_properties_.end())
     {
@@ -2273,46 +2330,99 @@ Layout::layout_gnu_property(unsigned int note_type,
     }
   else
     {
-      if (pr_type >= elfcpp::GNU_PROPERTY_LOPROC
-	  && pr_type < elfcpp::GNU_PROPERTY_HIPROC)
+      const bool is_big_endian = parameters->target().is_big_endian();
+      switch (pr_type)
+	{
+	case elfcpp::GNU_PROPERTY_STACK_SIZE:
+	  // Record the maximum value seen.
+	  {
+	    uint64_t val1 = read_sized_value(pprop->second.pr_datasz,
+					     pprop->second.pr_data,
+					     is_big_endian, object);
+	    uint64_t val2 = read_sized_value(pr_datasz, pr_data,
+					     is_big_endian, object);
+	    if (val2 > val1)
+	      write_sized_value(val2, pprop->second.pr_datasz,
+				pprop->second.pr_data, is_big_endian);
+	  }
+	  break;
+	case elfcpp::GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+	  // No data to merge.
+	  break;
+	default:
+	  gold_warning(_("%s: unknown program property type %d "
+			 "in .note.gnu.property section"),
+		       object->name().c_str(), pr_type);
+	}
+    }
+}
+
+// Merge per-object properties with program properties.
+// This lets the target identify objects that are missing certain
+// properties, in cases where properties must be ANDed together.
+
+void
+Layout::merge_gnu_properties(const Object* object)
+{
+  const int size = parameters->target().get_size();
+  const bool is_big_endian = parameters->target().is_big_endian();
+  if (size == 32)
+    {
+      if (is_big_endian)
+	{
+#ifdef HAVE_TARGET_32_BIG
+	  parameters->sized_target<32, true>()->merge_gnu_properties(object);
+#else
+	  gold_unreachable();
+#endif
+	}
+      else
+	{
+#ifdef HAVE_TARGET_32_LITTLE
+	  parameters->sized_target<32, false>()->merge_gnu_properties(object);
+#else
+	  gold_unreachable();
+#endif
+	}
+    }
+  else if (size == 64)
+    {
+      if (is_big_endian)
 	{
-	  // Target-dependent property value; call the target to merge.
-	  parameters->target().merge_gnu_property(note_type,
-						  pr_type,
-						  pr_datasz,
-						  pr_data,
-						  pprop->second.pr_datasz,
-						  pprop->second.pr_data,
-						  object);
+#ifdef HAVE_TARGET_64_BIG
+	  parameters->sized_target<64, true>()->merge_gnu_properties(object);
+#else
+	  gold_unreachable();
+#endif
 	}
       else
 	{
-	  const bool is_big_endian = parameters->target().is_big_endian();
-	  switch (pr_type)
-	    {
-	    case elfcpp::GNU_PROPERTY_STACK_SIZE:
-	      // Record the maximum value seen.
-	      {
-		uint64_t val1 = read_sized_value(pprop->second.pr_datasz,
-						 pprop->second.pr_data,
-						 is_big_endian, object);
-		uint64_t val2 = read_sized_value(pr_datasz, pr_data,
-						 is_big_endian, object);
-		if (val2 > val1)
-		  write_sized_value(val2, pprop->second.pr_datasz,
-				    pprop->second.pr_data, is_big_endian);
-	      }
-	      break;
-	    case elfcpp::GNU_PROPERTY_NO_COPY_ON_PROTECTED:
-	      // No data to merge.
-	      break;
-	    default:
-	      gold_warning(_("%s: unknown program property type %d "
-			     "in .note.gnu.properties section"),
-			   object->name().c_str(), pr_type);
-	    }
+#ifdef HAVE_TARGET_64_LITTLE
+	  parameters->sized_target<64, false>()->merge_gnu_properties(object);
+#else
+	  gold_unreachable();
+#endif
 	}
     }
+  else
+    gold_unreachable();
+}
+
+// Add a target-specific property for the output .note.gnu.property section.
+
+void
+Layout::add_gnu_property(unsigned int note_type,
+			 unsigned int pr_type,
+			 size_t pr_datasz,
+			 const unsigned char* pr_data)
+{
+  gold_assert(note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0);
+
+  Gnu_property prop;
+  prop.pr_datasz = pr_datasz;
+  prop.pr_data = new unsigned char[pr_datasz];
+  memcpy(prop.pr_data, pr_data, pr_datasz);
+  this->gnu_properties_[pr_type] = prop;
 }
 
 // Create automatic note sections.
@@ -3144,12 +3254,14 @@ Layout::create_note(const char* name, int note_type,
   return os;
 }
 
-// Create a .note.gnu.properties section to record program properties
+// Create a .note.gnu.property section to record program properties
 // accumulated from the input files.
 
 void
 Layout::create_gnu_properties_note()
 {
+  parameters->target().finalize_gnu_properties(this);
+
   if (this->gnu_properties_.empty())
     return;
 
@@ -3168,7 +3280,7 @@ Layout::create_gnu_properties_note()
   // Create the note section.
   size_t trailing_padding;
   Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_PROPERTY_TYPE_0,
-					 ".note.gnu.properties", descsz,
+					 ".note.gnu.property", descsz,
 					 true, &trailing_padding);
   if (os == NULL)
     return;
diff --git a/gold/layout.h b/gold/layout.h
index d71d291..8305b2a 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -701,6 +701,17 @@ class Layout
 		      const unsigned char* pr_data,
 		      const Object* object);
 
+  // Merge per-object properties with program properties.
+  void
+  merge_gnu_properties(const Object* object);
+
+  // Add a target-specific property for the output .note.gnu.property section.
+  void
+  add_gnu_property(unsigned int note_type,
+		   unsigned int pr_type,
+		   size_t pr_datasz,
+		   const unsigned char* pr_data);
+
   // Add an Output_section_data to the layout.  This is used for
   // special sections like the GOT section.  ORDER is where the
   // section should wind up in the output segment.  IS_RELRO is true
@@ -1359,7 +1370,7 @@ class Layout
     std::vector<Section_info> section_infos_;
   };
 
-  // Program properties from .note.gnu.properties sections.
+  // Program properties from .note.gnu.property sections.
   struct Gnu_property
   {
     size_t pr_datasz;
diff --git a/gold/object.cc b/gold/object.cc
index 8c874fe..374340f 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -1862,7 +1862,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
     }
 
   if (!is_pass_two)
-    layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
+    {
+      layout->merge_gnu_properties(this);
+      layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
+    }
 
   // Handle the .eh_frame sections after the other sections.
   gold_assert(!is_pass_one || eh_frame_sections.empty());
diff --git a/gold/target.h b/gold/target.h
index 1f8f757..bb31206 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -509,22 +509,10 @@ class Target
   should_include_section(elfcpp::Elf_Word sh_type) const
   { return this->do_should_include_section(sh_type); }
 
-  // Merge a target-specific program property in the .note.gnu.properties
-  // section.
+  // Finalize the target-specific properties in the .note.gnu.property section.
   void
-  merge_gnu_property(int note_type,
-		     int pr_type,
-		     size_t new_pr_datasz,
-		     const unsigned char* new_pr_data,
-		     size_t old_pr_datasz,
-		     unsigned char* old_pr_data,
-		     const Object* object) const
-  {
-    return this->do_merge_gnu_property(note_type, pr_type,
-				       new_pr_datasz, new_pr_data,
-				       old_pr_datasz, old_pr_data,
-				       object);
-  }
+  finalize_gnu_properties(Layout* layout) const
+  { this->do_finalize_gnu_properties(layout); }
 
  protected:
   // This struct holds the constant information for a child class.  We
@@ -832,11 +820,9 @@ class Target
   do_should_include_section(elfcpp::Elf_Word) const
   { return true; }
 
-  // Merge a target-specific program property in the .note.gnu.properties
-  // section.
+  // Finalize the target-specific properties in the .note.gnu.property section.
   virtual void
-  do_merge_gnu_property(int, int, size_t, const unsigned char*,
-			size_t, unsigned char*, const Object*) const
+  do_finalize_gnu_properties(Layout*) const
   { }
 
  private:
@@ -1158,6 +1144,17 @@ class Sized_target : public Target
     return elfcpp::elf_r_sym<size>(rel.get_r_info());
   }
 
+  // Record a target-specific program property in the .note.gnu.property
+  // section.
+  virtual void
+  record_gnu_property(int, int, size_t, const unsigned char*, const Object*)
+  { }
+
+  // Merge the target-specific program properties from the current object.
+  virtual void
+  merge_gnu_properties(const Object*)
+  { }
+
  protected:
   Sized_target(const Target::Target_info* pti)
     : Target(pti)
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index f439011..5f7d981 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -3260,8 +3260,8 @@ check_SCRIPTS += gnu_property_test.sh
 check_DATA += gnu_property_test.stdout
 gnu_property_test.stdout: gnu_property_test
 	$(TEST_READELF) -n $< >$@
-gnu_property_test: gcctestdir/ld gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
-	$(LINK) -Bgcctestdir/ -o $@ gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
+gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
+	gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
 gnu_property_main.o: gnu_property_main.c
 	$(COMPILE) -c -o $@ $<
 gnu_property_a.o: gnu_property_a.S
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index ee44c95..b4729bc 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -9465,8 +9465,8 @@ uninstall-am:
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(CXXCOMPILE) -c -Bgcctestdir/ -Wa,-madd-bnd-prefix -o $@ $<
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test.stdout: gnu_property_test
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(TEST_READELF) -n $< >$@
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test: gcctestdir/ld gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(LINK) -Bgcctestdir/ -o $@ gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@	gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_main.o: gnu_property_main.c
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(COMPILE) -c -o $@ $<
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_a.o: gnu_property_a.S
diff --git a/gold/testsuite/gnu_property_a.S b/gold/testsuite/gnu_property_a.S
index 2fa073d..463bc8e 100644
--- a/gold/testsuite/gnu_property_a.S
+++ b/gold/testsuite/gnu_property_a.S
@@ -11,6 +11,11 @@
 # define ALIGN 2
 #endif
 
+	.text
+	.globl _start
+_start:
+	ret
+
         .section ".note.gnu.property", "a"
         .p2align ALIGN
 
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index e6fa47e..a27f84d 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -590,7 +590,8 @@ class Target_x86_64 : public Sized_target<size, false>
       got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
       rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY),
       got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
-      tls_base_symbol_defined_(false)
+      tls_base_symbol_defined_(false), isa_1_used_(0), isa_1_needed_(0),
+      feature_1_(0), object_feature_1_(0), seen_first_object_(false)
   { }
 
   // Hook for a new output section.
@@ -1188,11 +1189,19 @@ class Target_x86_64 : public Sized_target<size, false>
 				  this->rela_dyn_section(layout));
   }
 
-  // Merge a target-specific program property in the .note.gnu.properties
+  // Record a target-specific program property in the .note.gnu.property
   // section.
   void
-  do_merge_gnu_property(int, int, size_t, const unsigned char*,
-			size_t, unsigned char*, const Object*) const;
+  record_gnu_property(int, int, size_t, const unsigned char*, const Object*);
+
+  // Merge the target-specific program properties from the current object.
+  void
+  merge_gnu_properties(const Object*);
+
+  // Finalize the target-specific program properties and add them back to
+  // the layout.
+  void
+  do_finalize_gnu_properties(Layout*) const;
 
   // Information about this specific target which we pass to the
   // general Target structure.
@@ -1251,6 +1260,17 @@ class Target_x86_64 : public Sized_target<size, false>
   std::vector<Tlsdesc_info> tlsdesc_reloc_info_;
   // True if the _TLS_MODULE_BASE_ symbol has been defined.
   bool tls_base_symbol_defined_;
+  // Target-specific program properties, from .note.gnu.property section.
+  // Each bit represents a specific feature.
+  uint32_t isa_1_used_;
+  uint32_t isa_1_needed_;
+  uint32_t feature_1_;
+  // Target-specific properties from the current object.
+  // These bits get ANDed into FEATURE_1_ after all properties for the object
+  // have been processed.
+  uint32_t object_feature_1_;
+  // Whether we have seen our first object, for use in initializing FEATURE_1_.
+  bool seen_first_object_;
 };
 
 template<>
@@ -1439,37 +1459,91 @@ Target_x86_64<size>::rela_irelative_section(Layout* layout)
   return this->rela_irelative_;
 }
 
-// Merge a target-specific program property in the .note.gnu.properties
+// Record a target-specific program property from the .note.gnu.property
 // section.
 template<int size>
 void
-Target_x86_64<size>::do_merge_gnu_property(
+Target_x86_64<size>::record_gnu_property(
     int, int pr_type,
-    size_t new_pr_datasz, const unsigned char* new_pr_data,
-    size_t old_pr_datasz, unsigned char* old_pr_data,
-    const Object*) const
+    size_t pr_datasz, const unsigned char* pr_data,
+    const Object* object)
 {
-  size_t min_datasz = (new_pr_datasz > old_pr_datasz
-		       ? old_pr_datasz
-		       : new_pr_datasz);
+  uint32_t val;
+
   switch (pr_type)
     {
     case elfcpp::GNU_PROPERTY_X86_ISA_1_USED:
     case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED:
-      {
-        for (size_t i = 0; i < min_datasz; ++i)
-          old_pr_data[i] |= new_pr_data[i];
-      }
-      break;
     case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND:
-      {
-        for (size_t i = 0; i < min_datasz; ++i)
-          old_pr_data[i] &= new_pr_data[i];
-      }
+      if (pr_datasz != 4)
+	{
+	  gold_warning(_("%s: corrupt .note.gnu.property section "
+			 "(pr_datasz for property %d is not 4)"),
+		       object->name().c_str(), pr_type);
+	  return;
+	}
+      val = elfcpp::Swap<32, false>::readval(pr_data);
       break;
     default:
+      gold_warning(_("%s: unknown program property type 0x%x "
+		     "in .note.gnu.property section"),
+		   object->name().c_str(), pr_type);
       break;
     }
+
+  switch (pr_type)
+    {
+    case elfcpp::GNU_PROPERTY_X86_ISA_1_USED:
+      this->isa_1_used_ |= val;
+      break;
+    case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED:
+      this->isa_1_needed_ |= val;
+      break;
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND:
+      // If we see multiple feature props in one object, OR them together.
+      this->object_feature_1_ |= val;
+      break;
+    }
+}
+
+// Merge the target-specific program properties from the current object.
+template<int size>
+void
+Target_x86_64<size>::merge_gnu_properties(const Object*)
+{
+  if (this->seen_first_object_)
+    this->feature_1_ &= this->object_feature_1_;
+  else
+    {
+      this->feature_1_ = this->object_feature_1_;
+      this->seen_first_object_ = true;
+    }
+  this->object_feature_1_ = 0;
+}
+
+static inline void
+add_property(Layout* layout, unsigned int pr_type, uint32_t val)
+{
+  unsigned char buf[4];
+  elfcpp::Swap<32, false>::writeval(buf, val);
+  layout->add_gnu_property(elfcpp::NT_GNU_PROPERTY_TYPE_0, pr_type, 4, buf);
+}
+
+// Finalize the target-specific program properties and add them back to
+// the layout.
+template<int size>
+void
+Target_x86_64<size>::do_finalize_gnu_properties(Layout* layout) const
+{
+  if (this->isa_1_used_ != 0)
+    add_property(layout, elfcpp::GNU_PROPERTY_X86_ISA_1_USED,
+		 this->isa_1_used_);
+  if (this->isa_1_needed_ != 0)
+    add_property(layout, elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED,
+		 this->isa_1_needed_);
+  if (this->feature_1_ != 0)
+    add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND,
+		 this->feature_1_);
 }
 
 // Write the first three reserved words of the .got.plt section.



More information about the Binutils-cvs mailing list