diff options
author | Cary Coutant <ccoutant@gmail.com> | 2018-06-22 23:36:50 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2018-06-22 23:36:50 -0700 |
commit | a2575bec2413d361c6ecfc4aecb2a31c86123f95 (patch) | |
tree | 100be502c00550c9c70593d47c36625b3c4f8e4f /gold/x86_64.cc | |
parent | a1893a821c4a2e953d13b97360b85650f2127134 (diff) | |
download | gdb-a2575bec2413d361c6ecfc4aecb2a31c86123f95.zip gdb-a2575bec2413d361c6ecfc4aecb2a31c86123f95.tar.gz gdb-a2575bec2413d361c6ecfc4aecb2a31c86123f95.tar.bz2 |
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.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r-- | gold/x86_64.cc | 116 |
1 files changed, 95 insertions, 21 deletions
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. |