PowerPC: downgrade FP mismatch error for shared libraries to a warning

PR 25882
bfd/
	* elf32-ppc.c (_bfd_elf_ppc_merge_fp_attributes): Don't init FP
	attributes from shared libraries, and do not return an error if
	they don't match.
gold/
	* powerpc.cc (merge_object_attributes): Replace name param with
	obj param.  Update callers.  Don't init FP attributes from shared
	libraries, and do not emit an error if they don't match.
This commit is contained in:
Alan Modra 2020-05-22 11:42:43 +09:30
parent 1b2e4380eb
commit 6f3fe02b0b
4 changed files with 73 additions and 28 deletions

View File

@ -1,3 +1,10 @@
2020-05-22 Alan Modra <amodra@gmail.com>
PR 25882
* elf32-ppc.c (_bfd_elf_ppc_merge_fp_attributes): Don't init FP
attributes from shared libraries, and do not return an error if
they don't match.
2020-05-21 Alan Modra <amodra@gmail.com> 2020-05-21 Alan Modra <amodra@gmail.com>
PR 25993 PR 25993

View File

@ -3557,6 +3557,17 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
obj_attribute *in_attr, *in_attrs; obj_attribute *in_attr, *in_attrs;
obj_attribute *out_attr, *out_attrs; obj_attribute *out_attr, *out_attrs;
bfd_boolean ret = TRUE; bfd_boolean ret = TRUE;
bfd_boolean warn_only;
/* We only warn about shared library mismatches, because common
libraries advertise support for a particular long double variant
but actually support more than one variant. For example, glibc
typically supports 128-bit IBM long double in the shared library
but has a compatibility static archive for 64-bit long double.
The linker doesn't have the smarts to see that an app using
object files marked as 64-bit long double call the compatibility
layer objects and only from there call into the shared library. */
warn_only = (ibfd->flags & DYNAMIC) != 0;
in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
@ -3573,18 +3584,21 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
if (in_fp == 0) if (in_fp == 0)
; ;
else if (out_fp == 0) else if (out_fp == 0)
{
if (!warn_only)
{ {
out_attr->type = ATTR_TYPE_FLAG_INT_VAL; out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i ^= in_fp; out_attr->i ^= in_fp;
last_fp = ibfd; last_fp = ibfd;
} }
}
else if (out_fp != 2 && in_fp == 2) else if (out_fp != 2 && in_fp == 2)
{ {
_bfd_error_handler _bfd_error_handler
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses hard float, %pB uses soft float"), (_("%pB uses hard float, %pB uses soft float"),
last_fp, ibfd); last_fp, ibfd);
ret = FALSE; ret = warn_only;
} }
else if (out_fp == 2 && in_fp != 2) else if (out_fp == 2 && in_fp != 2)
{ {
@ -3592,7 +3606,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses hard float, %pB uses soft float"), (_("%pB uses hard float, %pB uses soft float"),
ibfd, last_fp); ibfd, last_fp);
ret = FALSE; ret = warn_only;
} }
else if (out_fp == 1 && in_fp == 3) else if (out_fp == 1 && in_fp == 3)
{ {
@ -3600,7 +3614,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses double-precision hard float, " (_("%pB uses double-precision hard float, "
"%pB uses single-precision hard float"), last_fp, ibfd); "%pB uses single-precision hard float"), last_fp, ibfd);
ret = FALSE; ret = warn_only;
} }
else if (out_fp == 3 && in_fp == 1) else if (out_fp == 3 && in_fp == 1)
{ {
@ -3608,7 +3622,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses double-precision hard float, " (_("%pB uses double-precision hard float, "
"%pB uses single-precision hard float"), ibfd, last_fp); "%pB uses single-precision hard float"), ibfd, last_fp);
ret = FALSE; ret = warn_only;
} }
in_fp = in_attr->i & 0xc; in_fp = in_attr->i & 0xc;
@ -3616,18 +3630,21 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
if (in_fp == 0) if (in_fp == 0)
; ;
else if (out_fp == 0) else if (out_fp == 0)
{
if (!warn_only)
{ {
out_attr->type = ATTR_TYPE_FLAG_INT_VAL; out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i ^= in_fp; out_attr->i ^= in_fp;
last_ld = ibfd; last_ld = ibfd;
} }
}
else if (out_fp != 2 * 4 && in_fp == 2 * 4) else if (out_fp != 2 * 4 && in_fp == 2 * 4)
{ {
_bfd_error_handler _bfd_error_handler
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses 64-bit long double, " (_("%pB uses 64-bit long double, "
"%pB uses 128-bit long double"), ibfd, last_ld); "%pB uses 128-bit long double"), ibfd, last_ld);
ret = FALSE; ret = warn_only;
} }
else if (in_fp != 2 * 4 && out_fp == 2 * 4) else if (in_fp != 2 * 4 && out_fp == 2 * 4)
{ {
@ -3635,7 +3652,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses 64-bit long double, " (_("%pB uses 64-bit long double, "
"%pB uses 128-bit long double"), last_ld, ibfd); "%pB uses 128-bit long double"), last_ld, ibfd);
ret = FALSE; ret = warn_only;
} }
else if (out_fp == 1 * 4 && in_fp == 3 * 4) else if (out_fp == 1 * 4 && in_fp == 3 * 4)
{ {
@ -3643,7 +3660,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses IBM long double, " (_("%pB uses IBM long double, "
"%pB uses IEEE long double"), last_ld, ibfd); "%pB uses IEEE long double"), last_ld, ibfd);
ret = FALSE; ret = warn_only;
} }
else if (out_fp == 3 * 4 && in_fp == 1 * 4) else if (out_fp == 3 * 4 && in_fp == 1 * 4)
{ {
@ -3651,7 +3668,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%pB uses IBM long double, " (_("%pB uses IBM long double, "
"%pB uses IEEE long double"), ibfd, last_ld); "%pB uses IEEE long double"), ibfd, last_ld);
ret = FALSE; ret = warn_only;
} }
} }

View File

@ -1,3 +1,10 @@
2020-05-22 Alan Modra <amodra@gmail.com>
PR 25882
* powerpc.cc (merge_object_attributes): Replace name param with
obj param. Update callers. Don't init FP attributes from shared
libraries, and do not emit an error if they don't match.
2020-05-15 Nikita Ermakov <coffe92@gmail.com> 2020-05-15 Nikita Ermakov <coffe92@gmail.com>
* powerpc.cc (do_gc_mark_symbol): Don't segfault on plugin symbols. * powerpc.cc (do_gc_mark_symbol): Don't segfault on plugin symbols.

View File

@ -1204,7 +1204,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
// Merge object attributes from input object with those in the output. // Merge object attributes from input object with those in the output.
void void
merge_object_attributes(const char*, const Attributes_section_data*); merge_object_attributes(const Object*, const Attributes_section_data*);
private: private:
@ -9481,7 +9481,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections(
Powerpc_relobj<size, big_endian>* ppc_relobj Powerpc_relobj<size, big_endian>* ppc_relobj
= static_cast<Powerpc_relobj<size, big_endian>*>(*p); = static_cast<Powerpc_relobj<size, big_endian>*>(*p);
if (ppc_relobj->attributes_section_data()) if (ppc_relobj->attributes_section_data())
this->merge_object_attributes(ppc_relobj->name().c_str(), this->merge_object_attributes(ppc_relobj,
ppc_relobj->attributes_section_data()); ppc_relobj->attributes_section_data());
} }
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
@ -9491,7 +9491,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections(
Powerpc_dynobj<size, big_endian>* ppc_dynobj Powerpc_dynobj<size, big_endian>* ppc_dynobj
= static_cast<Powerpc_dynobj<size, big_endian>*>(*p); = static_cast<Powerpc_dynobj<size, big_endian>*>(*p);
if (ppc_dynobj->attributes_section_data()) if (ppc_dynobj->attributes_section_data())
this->merge_object_attributes(ppc_dynobj->name().c_str(), this->merge_object_attributes(ppc_dynobj,
ppc_dynobj->attributes_section_data()); ppc_dynobj->attributes_section_data());
} }
@ -9514,7 +9514,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections(
template<int size, bool big_endian> template<int size, bool big_endian>
void void
Target_powerpc<size, big_endian>::merge_object_attributes( Target_powerpc<size, big_endian>::merge_object_attributes(
const char* name, const Object* obj,
const Attributes_section_data* pasd) const Attributes_section_data* pasd)
{ {
// Return if there is no attributes section data. // Return if there is no attributes section data.
@ -9530,24 +9530,29 @@ Target_powerpc<size, big_endian>::merge_object_attributes(
Object_attribute* out_attr Object_attribute* out_attr
= this->attributes_section_data_->known_attributes(vendor); = this->attributes_section_data_->known_attributes(vendor);
const char* name = obj->name().c_str();
const char* err; const char* err;
const char* first; const char* first;
const char* second; const char* second;
int tag = elfcpp::Tag_GNU_Power_ABI_FP; int tag = elfcpp::Tag_GNU_Power_ABI_FP;
int in_fp = in_attr[tag].int_value() & 0xf; int in_fp = in_attr[tag].int_value() & 0xf;
int out_fp = out_attr[tag].int_value() & 0xf; int out_fp = out_attr[tag].int_value() & 0xf;
bool warn_only = obj->is_dynamic();
if (in_fp != out_fp) if (in_fp != out_fp)
{ {
err = NULL; err = NULL;
if ((in_fp & 3) == 0) if ((in_fp & 3) == 0)
; ;
else if ((out_fp & 3) == 0) else if ((out_fp & 3) == 0)
{
if (!warn_only)
{ {
out_fp |= in_fp & 3; out_fp |= in_fp & 3;
out_attr[tag].set_int_value(out_fp); out_attr[tag].set_int_value(out_fp);
out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL);
this->last_fp_ = name; this->last_fp_ = name;
} }
}
else if ((out_fp & 3) != 2 && (in_fp & 3) == 2) else if ((out_fp & 3) != 2 && (in_fp & 3) == 2)
{ {
err = N_("%s uses hard float, %s uses soft float"); err = N_("%s uses hard float, %s uses soft float");
@ -9578,12 +9583,15 @@ Target_powerpc<size, big_endian>::merge_object_attributes(
if (err || (in_fp & 0xc) == 0) if (err || (in_fp & 0xc) == 0)
; ;
else if ((out_fp & 0xc) == 0) else if ((out_fp & 0xc) == 0)
{
if (!warn_only)
{ {
out_fp |= in_fp & 0xc; out_fp |= in_fp & 0xc;
out_attr[tag].set_int_value(out_fp); out_attr[tag].set_int_value(out_fp);
out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL);
this->last_ld_ = name; this->last_ld_ = name;
} }
}
else if ((out_fp & 0xc) != 2 * 4 && (in_fp & 0xc) == 2 * 4) else if ((out_fp & 0xc) != 2 * 4 && (in_fp & 0xc) == 2 * 4)
{ {
err = N_("%s uses 64-bit long double, %s uses 128-bit long double"); err = N_("%s uses 64-bit long double, %s uses 128-bit long double");
@ -9612,9 +9620,15 @@ Target_powerpc<size, big_endian>::merge_object_attributes(
if (err) if (err)
{ {
if (parameters->options().warn_mismatch()) if (parameters->options().warn_mismatch())
{
if (warn_only)
gold_warning(_(err), first, second);
else
gold_error(_(err), first, second); gold_error(_(err), first, second);
}
// Arrange for this attribute to be deleted. It's better to // Arrange for this attribute to be deleted. It's better to
// say "don't know" about a file than to wrongly claim compliance. // say "don't know" about a file than to wrongly claim compliance.
if (!warn_only)
out_attr[tag].set_type(0); out_attr[tag].set_type(0);
} }
} }