diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 45 | ||||
-rw-r--r-- | gold/ChangeLog | 7 | ||||
-rw-r--r-- | gold/powerpc.cc | 42 |
4 files changed, 73 insertions, 28 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3dc0356..9027489 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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> PR 25993 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index a900abe..d1c5e1b 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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 *out_attr, *out_attrs; 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]; out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; @@ -3574,9 +3585,12 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) ; else if (out_fp == 0) { - out_attr->type = ATTR_TYPE_FLAG_INT_VAL; - out_attr->i ^= in_fp; - last_fp = ibfd; + if (!warn_only) + { + out_attr->type = ATTR_TYPE_FLAG_INT_VAL; + out_attr->i ^= in_fp; + last_fp = ibfd; + } } else if (out_fp != 2 && in_fp == 2) { @@ -3584,7 +3598,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses hard float, %pB uses soft float"), last_fp, ibfd); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses hard float, %pB uses soft float"), ibfd, last_fp); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses double-precision hard float, " "%pB uses single-precision hard float"), last_fp, ibfd); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses double-precision hard float, " "%pB uses single-precision hard float"), ibfd, last_fp); - ret = FALSE; + ret = warn_only; } in_fp = in_attr->i & 0xc; @@ -3617,9 +3631,12 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) ; else if (out_fp == 0) { - out_attr->type = ATTR_TYPE_FLAG_INT_VAL; - out_attr->i ^= in_fp; - last_ld = ibfd; + if (!warn_only) + { + out_attr->type = ATTR_TYPE_FLAG_INT_VAL; + out_attr->i ^= in_fp; + last_ld = ibfd; + } } else if (out_fp != 2 * 4 && in_fp == 2 * 4) { @@ -3627,7 +3644,7 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* xgettext:c-format */ (_("%pB uses 64-bit long double, " "%pB uses 128-bit long double"), ibfd, last_ld); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses 64-bit long double, " "%pB uses 128-bit long double"), last_ld, ibfd); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses IBM long double, " "%pB uses IEEE long double"), last_ld, ibfd); - ret = FALSE; + ret = warn_only; } 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 */ (_("%pB uses IBM long double, " "%pB uses IEEE long double"), ibfd, last_ld); - ret = FALSE; + ret = warn_only; } } diff --git a/gold/ChangeLog b/gold/ChangeLog index e85669a..58cb3f3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -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> * powerpc.cc (do_gc_mark_symbol): Don't segfault on plugin symbols. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 2010c1e..318c417 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1204,7 +1204,7 @@ class Target_powerpc : public Sized_target<size, big_endian> // Merge object attributes from input object with those in the output. void - merge_object_attributes(const char*, const Attributes_section_data*); + merge_object_attributes(const Object*, const Attributes_section_data*); private: @@ -9481,7 +9481,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections( Powerpc_relobj<size, big_endian>* ppc_relobj = static_cast<Powerpc_relobj<size, big_endian>*>(*p); 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()); } 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 = static_cast<Powerpc_dynobj<size, big_endian>*>(*p); 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()); } @@ -9514,7 +9514,7 @@ Target_powerpc<size, big_endian>::do_finalize_sections( template<int size, bool big_endian> void Target_powerpc<size, big_endian>::merge_object_attributes( - const char* name, + const Object* obj, const Attributes_section_data* pasd) { // Return if there is no attributes section data. @@ -9530,12 +9530,14 @@ Target_powerpc<size, big_endian>::merge_object_attributes( Object_attribute* out_attr = this->attributes_section_data_->known_attributes(vendor); + const char* name = obj->name().c_str(); const char* err; const char* first; const char* second; int tag = elfcpp::Tag_GNU_Power_ABI_FP; int in_fp = in_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) { err = NULL; @@ -9543,10 +9545,13 @@ Target_powerpc<size, big_endian>::merge_object_attributes( ; else if ((out_fp & 3) == 0) { - out_fp |= in_fp & 3; - out_attr[tag].set_int_value(out_fp); - out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); - this->last_fp_ = name; + if (!warn_only) + { + out_fp |= in_fp & 3; + out_attr[tag].set_int_value(out_fp); + out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); + this->last_fp_ = name; + } } else if ((out_fp & 3) != 2 && (in_fp & 3) == 2) { @@ -9579,10 +9584,13 @@ Target_powerpc<size, big_endian>::merge_object_attributes( ; else if ((out_fp & 0xc) == 0) { - out_fp |= in_fp & 0xc; - out_attr[tag].set_int_value(out_fp); - out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); - this->last_ld_ = name; + if (!warn_only) + { + out_fp |= in_fp & 0xc; + out_attr[tag].set_int_value(out_fp); + out_attr[tag].set_type(Object_attribute::ATTR_TYPE_FLAG_INT_VAL); + this->last_ld_ = name; + } } else if ((out_fp & 0xc) != 2 * 4 && (in_fp & 0xc) == 2 * 4) { @@ -9612,10 +9620,16 @@ Target_powerpc<size, big_endian>::merge_object_attributes( if (err) { if (parameters->options().warn_mismatch()) - gold_error(_(err), first, second); + { + if (warn_only) + gold_warning(_(err), first, second); + else + gold_error(_(err), first, second); + } // Arrange for this attribute to be deleted. It's better to // say "don't know" about a file than to wrongly claim compliance. - out_attr[tag].set_type(0); + if (!warn_only) + out_attr[tag].set_type(0); } } |