summaryrefslogtreecommitdiff
path: root/gold/x86_64.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2018-06-22 23:36:50 -0700
committerCary Coutant <ccoutant@gmail.com>2018-06-22 23:36:50 -0700
commita2575bec2413d361c6ecfc4aecb2a31c86123f95 (patch)
tree100be502c00550c9c70593d47c36625b3c4f8e4f /gold/x86_64.cc
parenta1893a821c4a2e953d13b97360b85650f2127134 (diff)
downloadbinutils-gdb-a2575bec2413d361c6ecfc4aecb2a31c86123f95.tar.gz
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.cc116
1 files changed, 95 insertions, 21 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index e6fa47ea8f9..a27f84d723f 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.