You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
6.8 KiB
193 lines
6.8 KiB
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.
|
|
|