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.
This commit is contained in:
parent
a1893a821c
commit
a2575bec24
|
@ -1,3 +1,38 @@
|
|||
2018-06-22 Cary Coutant <ccoutant@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
2018-06-22 Cary Coutant <ccoutant@gmail.com>
|
||||
|
||||
* incremental.cc (Sized_incremental_binary::setup_readers): Use
|
||||
|
|
186
gold/layout.cc
186
gold/layout.cc
|
@ -2217,7 +2217,7 @@ read_sized_value(size_t size, const unsigned char* buf, bool is_big_endian,
|
|||
}
|
||||
else
|
||||
{
|
||||
gold_warning(_("%s: in .note.gnu.properties section, "
|
||||
gold_warning(_("%s: in .note.gnu.property section, "
|
||||
"pr_datasz must be 4 or 8"),
|
||||
object->name().c_str());
|
||||
}
|
||||
|
@ -2262,6 +2262,63 @@ Layout::layout_gnu_property(unsigned int note_type,
|
|||
// We currently support only the one note type.
|
||||
gold_assert(note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0);
|
||||
|
||||
if (pr_type >= elfcpp::GNU_PROPERTY_LOPROC
|
||||
&& pr_type < elfcpp::GNU_PROPERTY_HIPROC)
|
||||
{
|
||||
// Target-dependent property value; call the target to record.
|
||||
const int size = parameters->target().get_size();
|
||||
const bool is_big_endian = parameters->target().is_big_endian();
|
||||
if (size == 32)
|
||||
{
|
||||
if (is_big_endian)
|
||||
{
|
||||
#ifdef HAVE_TARGET_32_BIG
|
||||
parameters->sized_target<32, true>()->
|
||||
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
|
||||
object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TARGET_32_LITTLE
|
||||
parameters->sized_target<32, false>()->
|
||||
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
|
||||
object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (size == 64)
|
||||
{
|
||||
if (is_big_endian)
|
||||
{
|
||||
#ifdef HAVE_TARGET_64_BIG
|
||||
parameters->sized_target<64, true>()->
|
||||
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
|
||||
object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TARGET_64_LITTLE
|
||||
parameters->sized_target<64, false>()->
|
||||
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
|
||||
object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
gold_unreachable();
|
||||
return;
|
||||
}
|
||||
|
||||
Gnu_properties::iterator pprop = this->gnu_properties_.find(pr_type);
|
||||
if (pprop == this->gnu_properties_.end())
|
||||
{
|
||||
|
@ -2273,46 +2330,99 @@ Layout::layout_gnu_property(unsigned int note_type,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (pr_type >= elfcpp::GNU_PROPERTY_LOPROC
|
||||
&& pr_type < elfcpp::GNU_PROPERTY_HIPROC)
|
||||
const bool is_big_endian = parameters->target().is_big_endian();
|
||||
switch (pr_type)
|
||||
{
|
||||
// Target-dependent property value; call the target to merge.
|
||||
parameters->target().merge_gnu_property(note_type,
|
||||
pr_type,
|
||||
pr_datasz,
|
||||
pr_data,
|
||||
pprop->second.pr_datasz,
|
||||
pprop->second.pr_data,
|
||||
object);
|
||||
case elfcpp::GNU_PROPERTY_STACK_SIZE:
|
||||
// Record the maximum value seen.
|
||||
{
|
||||
uint64_t val1 = read_sized_value(pprop->second.pr_datasz,
|
||||
pprop->second.pr_data,
|
||||
is_big_endian, object);
|
||||
uint64_t val2 = read_sized_value(pr_datasz, pr_data,
|
||||
is_big_endian, object);
|
||||
if (val2 > val1)
|
||||
write_sized_value(val2, pprop->second.pr_datasz,
|
||||
pprop->second.pr_data, is_big_endian);
|
||||
}
|
||||
break;
|
||||
case elfcpp::GNU_PROPERTY_NO_COPY_ON_PROTECTED:
|
||||
// No data to merge.
|
||||
break;
|
||||
default:
|
||||
gold_warning(_("%s: unknown program property type %d "
|
||||
"in .note.gnu.property section"),
|
||||
object->name().c_str(), pr_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge per-object properties with program properties.
|
||||
// This lets the target identify objects that are missing certain
|
||||
// properties, in cases where properties must be ANDed together.
|
||||
|
||||
void
|
||||
Layout::merge_gnu_properties(const Object* object)
|
||||
{
|
||||
const int size = parameters->target().get_size();
|
||||
const bool is_big_endian = parameters->target().is_big_endian();
|
||||
if (size == 32)
|
||||
{
|
||||
if (is_big_endian)
|
||||
{
|
||||
#ifdef HAVE_TARGET_32_BIG
|
||||
parameters->sized_target<32, true>()->merge_gnu_properties(object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool is_big_endian = parameters->target().is_big_endian();
|
||||
switch (pr_type)
|
||||
{
|
||||
case elfcpp::GNU_PROPERTY_STACK_SIZE:
|
||||
// Record the maximum value seen.
|
||||
{
|
||||
uint64_t val1 = read_sized_value(pprop->second.pr_datasz,
|
||||
pprop->second.pr_data,
|
||||
is_big_endian, object);
|
||||
uint64_t val2 = read_sized_value(pr_datasz, pr_data,
|
||||
is_big_endian, object);
|
||||
if (val2 > val1)
|
||||
write_sized_value(val2, pprop->second.pr_datasz,
|
||||
pprop->second.pr_data, is_big_endian);
|
||||
}
|
||||
break;
|
||||
case elfcpp::GNU_PROPERTY_NO_COPY_ON_PROTECTED:
|
||||
// No data to merge.
|
||||
break;
|
||||
default:
|
||||
gold_warning(_("%s: unknown program property type %d "
|
||||
"in .note.gnu.properties section"),
|
||||
object->name().c_str(), pr_type);
|
||||
}
|
||||
#ifdef HAVE_TARGET_32_LITTLE
|
||||
parameters->sized_target<32, false>()->merge_gnu_properties(object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (size == 64)
|
||||
{
|
||||
if (is_big_endian)
|
||||
{
|
||||
#ifdef HAVE_TARGET_64_BIG
|
||||
parameters->sized_target<64, true>()->merge_gnu_properties(object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TARGET_64_LITTLE
|
||||
parameters->sized_target<64, false>()->merge_gnu_properties(object);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Add a target-specific property for the output .note.gnu.property section.
|
||||
|
||||
void
|
||||
Layout::add_gnu_property(unsigned int note_type,
|
||||
unsigned int pr_type,
|
||||
size_t pr_datasz,
|
||||
const unsigned char* pr_data)
|
||||
{
|
||||
gold_assert(note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0);
|
||||
|
||||
Gnu_property prop;
|
||||
prop.pr_datasz = pr_datasz;
|
||||
prop.pr_data = new unsigned char[pr_datasz];
|
||||
memcpy(prop.pr_data, pr_data, pr_datasz);
|
||||
this->gnu_properties_[pr_type] = prop;
|
||||
}
|
||||
|
||||
// Create automatic note sections.
|
||||
|
@ -3144,12 +3254,14 @@ Layout::create_note(const char* name, int note_type,
|
|||
return os;
|
||||
}
|
||||
|
||||
// Create a .note.gnu.properties section to record program properties
|
||||
// Create a .note.gnu.property section to record program properties
|
||||
// accumulated from the input files.
|
||||
|
||||
void
|
||||
Layout::create_gnu_properties_note()
|
||||
{
|
||||
parameters->target().finalize_gnu_properties(this);
|
||||
|
||||
if (this->gnu_properties_.empty())
|
||||
return;
|
||||
|
||||
|
@ -3168,7 +3280,7 @@ Layout::create_gnu_properties_note()
|
|||
// Create the note section.
|
||||
size_t trailing_padding;
|
||||
Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_PROPERTY_TYPE_0,
|
||||
".note.gnu.properties", descsz,
|
||||
".note.gnu.property", descsz,
|
||||
true, &trailing_padding);
|
||||
if (os == NULL)
|
||||
return;
|
||||
|
|
|
@ -701,6 +701,17 @@ class Layout
|
|||
const unsigned char* pr_data,
|
||||
const Object* object);
|
||||
|
||||
// Merge per-object properties with program properties.
|
||||
void
|
||||
merge_gnu_properties(const Object* object);
|
||||
|
||||
// Add a target-specific property for the output .note.gnu.property section.
|
||||
void
|
||||
add_gnu_property(unsigned int note_type,
|
||||
unsigned int pr_type,
|
||||
size_t pr_datasz,
|
||||
const unsigned char* pr_data);
|
||||
|
||||
// Add an Output_section_data to the layout. This is used for
|
||||
// special sections like the GOT section. ORDER is where the
|
||||
// section should wind up in the output segment. IS_RELRO is true
|
||||
|
@ -1359,7 +1370,7 @@ class Layout
|
|||
std::vector<Section_info> section_infos_;
|
||||
};
|
||||
|
||||
// Program properties from .note.gnu.properties sections.
|
||||
// Program properties from .note.gnu.property sections.
|
||||
struct Gnu_property
|
||||
{
|
||||
size_t pr_datasz;
|
||||
|
|
|
@ -1862,7 +1862,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
|||
}
|
||||
|
||||
if (!is_pass_two)
|
||||
layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
|
||||
{
|
||||
layout->merge_gnu_properties(this);
|
||||
layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
|
||||
}
|
||||
|
||||
// Handle the .eh_frame sections after the other sections.
|
||||
gold_assert(!is_pass_one || eh_frame_sections.empty());
|
||||
|
|
|
@ -509,22 +509,10 @@ class Target
|
|||
should_include_section(elfcpp::Elf_Word sh_type) const
|
||||
{ return this->do_should_include_section(sh_type); }
|
||||
|
||||
// Merge a target-specific program property in the .note.gnu.properties
|
||||
// section.
|
||||
// Finalize the target-specific properties in the .note.gnu.property section.
|
||||
void
|
||||
merge_gnu_property(int note_type,
|
||||
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* object) const
|
||||
{
|
||||
return this->do_merge_gnu_property(note_type, pr_type,
|
||||
new_pr_datasz, new_pr_data,
|
||||
old_pr_datasz, old_pr_data,
|
||||
object);
|
||||
}
|
||||
finalize_gnu_properties(Layout* layout) const
|
||||
{ this->do_finalize_gnu_properties(layout); }
|
||||
|
||||
protected:
|
||||
// This struct holds the constant information for a child class. We
|
||||
|
@ -832,11 +820,9 @@ class Target
|
|||
do_should_include_section(elfcpp::Elf_Word) const
|
||||
{ return true; }
|
||||
|
||||
// Merge a target-specific program property in the .note.gnu.properties
|
||||
// section.
|
||||
// Finalize the target-specific properties in the .note.gnu.property section.
|
||||
virtual void
|
||||
do_merge_gnu_property(int, int, size_t, const unsigned char*,
|
||||
size_t, unsigned char*, const Object*) const
|
||||
do_finalize_gnu_properties(Layout*) const
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
@ -1158,6 +1144,17 @@ class Sized_target : public Target
|
|||
return elfcpp::elf_r_sym<size>(rel.get_r_info());
|
||||
}
|
||||
|
||||
// Record a target-specific program property in the .note.gnu.property
|
||||
// section.
|
||||
virtual void
|
||||
record_gnu_property(int, int, size_t, const unsigned char*, const Object*)
|
||||
{ }
|
||||
|
||||
// Merge the target-specific program properties from the current object.
|
||||
virtual void
|
||||
merge_gnu_properties(const Object*)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
Sized_target(const Target::Target_info* pti)
|
||||
: Target(pti)
|
||||
|
|
|
@ -3260,8 +3260,8 @@ check_SCRIPTS += gnu_property_test.sh
|
|||
check_DATA += gnu_property_test.stdout
|
||||
gnu_property_test.stdout: gnu_property_test
|
||||
$(TEST_READELF) -n $< >$@
|
||||
gnu_property_test: gcctestdir/ld gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
$(LINK) -Bgcctestdir/ -o $@ gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
gnu_property_main.o: gnu_property_main.c
|
||||
$(COMPILE) -c -o $@ $<
|
||||
gnu_property_a.o: gnu_property_a.S
|
||||
|
|
|
@ -9465,8 +9465,8 @@ uninstall-am:
|
|||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -Bgcctestdir/ -Wa,-madd-bnd-prefix -o $@ $<
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test.stdout: gnu_property_test
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -n $< >$@
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test: gcctestdir/ld gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -o $@ gnu_property_main.o gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_main.o: gnu_property_main.c
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -o $@ $<
|
||||
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_a.o: gnu_property_a.S
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
# define ALIGN 2
|
||||
#endif
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align ALIGN
|
||||
|
||||
|
|
116
gold/x86_64.cc
116
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.
|
||||
|
|
Loading…
Reference in New Issue