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.