Blob Blame History Raw
diff --git a/gold/i386.cc b/gold/i386.cc
index bf209fe9a86..31161ff091c 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -360,7 +360,11 @@ class Target_i386 : public Sized_target<32, false>
       got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
       got_tlsdesc_(NULL), global_offset_table_(NULL), rel_dyn_(NULL),
       rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY),
-      got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
+      got_mod_index_offset_(-1U), tls_base_symbol_defined_(false),
+      isa_1_used_(0), isa_1_needed_(0),
+      feature_1_(0), feature_2_used_(0), feature_2_needed_(0),
+      object_isa_1_used_(0), object_feature_1_(0),
+      object_feature_2_used_(0), seen_first_object_(false)
   { }
 
   // Process the relocations to determine unreferenced sections for
@@ -859,6 +863,21 @@ class Target_i386 : public Sized_target<32, false>
 				  this->rel_dyn_section(layout));
   }
 
+  // Record a target-specific program property in the .note.gnu.property
+  // section.
+  void
+  record_gnu_property(unsigned int, unsigned 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.
   static const Target::Target_info i386_info;
@@ -898,6 +917,26 @@ class Target_i386 : public Sized_target<32, false>
   unsigned int got_mod_index_offset_;
   // 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_;
+  uint32_t feature_2_used_;
+  uint32_t feature_2_needed_;
+  // Target-specific properties from the current object.
+  // These bits get ORed into ISA_1_USED_ after all properties for the object
+  // have been processed. But if either is all zeroes (as when the property
+  // is absent from an object), the result should be all zeroes.
+  // (See PR ld/23486.)
+  uint32_t object_isa_1_used_;
+  // These bits get ANDed into FEATURE_1_ after all properties for the object
+  // have been processed.
+  uint32_t object_feature_1_;
+  uint32_t object_feature_2_used_;
+  // Whether we have seen our first object, for use in initializing FEATURE_1_.
+  bool seen_first_object_;
 };
 
 const Target::Target_info Target_i386::i386_info =
@@ -1042,6 +1081,126 @@ Target_i386::rel_irelative_section(Layout* layout)
   return this->rel_irelative_;
 }
 
+// Record a target-specific program property from the .note.gnu.property
+// section.
+void
+Target_i386::record_gnu_property(
+    unsigned int, unsigned int pr_type,
+    size_t pr_datasz, const unsigned char* pr_data,
+    const Object* object)
+{
+  uint32_t val = 0;
+
+  switch (pr_type)
+    {
+    case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_USED:
+    case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED:
+    case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED:
+    case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED:
+    case elfcpp::GNU_PROPERTY_X86_ISA_1_USED:
+    case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED:
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND:
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED:
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED:
+      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->object_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;
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED:
+      this->object_feature_2_used_ |= val;
+      break;
+    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED:
+      this->feature_2_needed_ |= val;
+      break;
+    }
+}
+
+// Merge the target-specific program properties from the current object.
+void
+Target_i386::merge_gnu_properties(const Object*)
+{
+  if (this->seen_first_object_)
+    {
+      // If any object is missing the ISA_1_USED property, we must omit
+      // it from the output file.
+      if (this->object_isa_1_used_ == 0)
+	this->isa_1_used_ = 0;
+      else if (this->isa_1_used_ != 0)
+	this->isa_1_used_ |= this->object_isa_1_used_;
+      this->feature_1_ &= this->object_feature_1_;
+      // If any object is missing the FEATURE_2_USED property, we must
+      // omit it from the output file.
+      if (this->object_feature_2_used_ == 0)
+	this->feature_2_used_ = 0;
+      else if (this->feature_2_used_ != 0)
+	this->feature_2_used_ |= this->object_feature_2_used_;
+    }
+  else
+    {
+      this->isa_1_used_ = this->object_isa_1_used_;
+      this->feature_1_ = this->object_feature_1_;
+      this->feature_2_used_ = this->object_feature_2_used_;
+      this->seen_first_object_ = true;
+    }
+  this->object_isa_1_used_ = 0;
+  this->object_feature_1_ = 0;
+  this->object_feature_2_used_ = 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.
+void
+Target_i386::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_);
+  if (this->feature_2_used_ != 0)
+    add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED,
+		 this->feature_2_used_);
+  if (this->feature_2_needed_ != 0)
+    add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED,
+		 this->feature_2_needed_);
+}
+
 // Write the first three reserved words of the .got.plt section.
 // The remainder of the section is written while writing the PLT
 // in Output_data_plt_i386::do_write.
--- binutils.orig/elfcpp/elfcpp.h	2021-06-23 12:31:04.550738064 +0100
+++ binutils-2.30/elfcpp/elfcpp.h	2021-06-23 12:33:18.068875079 +0100
@@ -1008,9 +1008,21 @@ enum
   GNU_PROPERTY_STACK_SIZE = 1,
   GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2,
   GNU_PROPERTY_LOPROC = 0xc0000000,
-  GNU_PROPERTY_X86_ISA_1_USED = 0xc0000000,
-  GNU_PROPERTY_X86_ISA_1_NEEDED = 0xc0000001,
-  GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002,
+  GNU_PROPERTY_X86_COMPAT_ISA_1_USED = 0xc0000000,
+  GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED = 0xc0000001,
+  GNU_PROPERTY_X86_UINT32_AND_LO = 0xc0000002,
+  GNU_PROPERTY_X86_UINT32_AND_HI = 0xc0007fff,
+  GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000,
+  GNU_PROPERTY_X86_UINT32_OR_HI = 0xc000ffff,
+  GNU_PROPERTY_X86_UINT32_OR_AND_LO = 0xc0010000,
+  GNU_PROPERTY_X86_UINT32_OR_AND_HI = 0xc0017fff,
+  GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 0,
+  GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 0,
+  GNU_PROPERTY_X86_FEATURE_1_AND = GNU_PROPERTY_X86_UINT32_AND_LO + 0,
+  GNU_PROPERTY_X86_ISA_1_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 2,
+  GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1,
+  GNU_PROPERTY_X86_ISA_1_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 2,
+  GNU_PROPERTY_X86_FEATURE_2_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 1,
   GNU_PROPERTY_HIPROC = 0xdfffffff,
   GNU_PROPERTY_LOUSER = 0xe0000000,
   GNU_PROPERTY_HIUSER = 0xffffffff
--- binutils.orig/gold/i386.cc	2021-07-07 14:15:34.369441519 +0100
+++ binutils-2.30/gold/i386.cc	2021-07-07 14:36:11.932838272 +0100
@@ -362,9 +362,8 @@ class Target_i386 : public Sized_target<
       rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY),
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false),
       isa_1_used_(0), isa_1_needed_(0),
-      feature_1_(0), feature_2_used_(0), feature_2_needed_(0),
-      object_isa_1_used_(0), object_feature_1_(0),
-      object_feature_2_used_(0), seen_first_object_(false)
+      feature_1_(0), object_feature_1_(0),
+      seen_first_object_(false)
   { }
 
   // Process the relocations to determine unreferenced sections for
@@ -866,7 +865,7 @@ class Target_i386 : public Sized_target<
   // Record a target-specific program property in the .note.gnu.property
   // section.
   void
-  record_gnu_property(unsigned int, unsigned int, size_t,
+  record_gnu_property(int, int, size_t,
 		      const unsigned char*, const Object*);
 
   // Merge the target-specific program properties from the current object.
@@ -923,18 +922,10 @@ class Target_i386 : public Sized_target<
   uint32_t isa_1_used_;
   uint32_t isa_1_needed_;
   uint32_t feature_1_;
-  uint32_t feature_2_used_;
-  uint32_t feature_2_needed_;
   // Target-specific properties from the current object.
-  // These bits get ORed into ISA_1_USED_ after all properties for the object
-  // have been processed. But if either is all zeroes (as when the property
-  // is absent from an object), the result should be all zeroes.
-  // (See PR ld/23486.)
-  uint32_t object_isa_1_used_;
   // These bits get ANDed into FEATURE_1_ after all properties for the object
   // have been processed.
   uint32_t object_feature_1_;
-  uint32_t object_feature_2_used_;
   // Whether we have seen our first object, for use in initializing FEATURE_1_.
   bool seen_first_object_;
 };
@@ -1084,7 +1075,7 @@ Target_i386::rel_irelative_section(Layou
 // section.
 void
 Target_i386::record_gnu_property(
-    unsigned int, unsigned int pr_type,
+    int, int pr_type,
     size_t pr_datasz, const unsigned char* pr_data,
     const Object* object)
 {
@@ -1092,15 +1083,9 @@ Target_i386::record_gnu_property(
 
   switch (pr_type)
     {
-    case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_USED:
-    case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED:
-    case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED:
-    case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED:
     case elfcpp::GNU_PROPERTY_X86_ISA_1_USED:
     case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED:
     case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND:
-    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED:
-    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED:
       if (pr_datasz != 4)
 	{
 	  gold_warning(_("%s: corrupt .note.gnu.property section "
@@ -1120,7 +1105,7 @@ Target_i386::record_gnu_property(
   switch (pr_type)
     {
     case elfcpp::GNU_PROPERTY_X86_ISA_1_USED:
-      this->object_isa_1_used_ |= val;
+      this->isa_1_used_ |= val;
       break;
     case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED:
       this->isa_1_needed_ |= val;
@@ -1129,12 +1114,6 @@ Target_i386::record_gnu_property(
       // If we see multiple feature props in one object, OR them together.
       this->object_feature_1_ |= val;
       break;
-    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED:
-      this->object_feature_2_used_ |= val;
-      break;
-    case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED:
-      this->feature_2_needed_ |= val;
-      break;
     }
 }
 
@@ -1143,31 +1122,13 @@ void
 Target_i386::merge_gnu_properties(const Object*)
 {
   if (this->seen_first_object_)
-    {
-      // If any object is missing the ISA_1_USED property, we must omit
-      // it from the output file.
-      if (this->object_isa_1_used_ == 0)
-	this->isa_1_used_ = 0;
-      else if (this->isa_1_used_ != 0)
-	this->isa_1_used_ |= this->object_isa_1_used_;
-      this->feature_1_ &= this->object_feature_1_;
-      // If any object is missing the FEATURE_2_USED property, we must
-      // omit it from the output file.
-      if (this->object_feature_2_used_ == 0)
-	this->feature_2_used_ = 0;
-      else if (this->feature_2_used_ != 0)
-	this->feature_2_used_ |= this->object_feature_2_used_;
-    }
+    this->feature_1_ &= this->object_feature_1_;
   else
     {
-      this->isa_1_used_ = this->object_isa_1_used_;
       this->feature_1_ = this->object_feature_1_;
-      this->feature_2_used_ = this->object_feature_2_used_;
       this->seen_first_object_ = true;
     }
-  this->object_isa_1_used_ = 0;
   this->object_feature_1_ = 0;
-  this->object_feature_2_used_ = 0;
 }
 
 static inline void
@@ -1192,12 +1153,6 @@ Target_i386::do_finalize_gnu_properties(
   if (this->feature_1_ != 0)
     add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND,
 		 this->feature_1_);
-  if (this->feature_2_used_ != 0)
-    add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED,
-		 this->feature_2_used_);
-  if (this->feature_2_needed_ != 0)
-    add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED,
-		 this->feature_2_needed_);
 }
 
 // Write the first three reserved words of the .got.plt section.