#include "bfd.h"
#include "libbfd.h"
+static const bfd_arch_info_type *
+arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b);
+
#define ARC(mach, print_name, default_p, next) \
{ \
32, /* 32 bits in a word */ \
print_name, \
4, /* section alignment power */ \
default_p, \
- bfd_default_compatible, \
+ arc_compatible, \
bfd_default_scan, \
bfd_arch_default_fill, \
next, \
const bfd_arch_info_type bfd_arc_arch =
ARC (bfd_mach_arc_arc600, "ARC600", TRUE, &arch_info_struct[0]);
+
+/* ARC-specific "compatible" function. The general rule is that if A and B are
+ compatible, then this function should return architecture that is more
+ "feature-rich", that is, can run both A and B. ARCv2, EM and HS all has
+ same mach number, so bfd_default_compatible assumes they are the same, and
+ returns an A. That causes issues with GDB, because GDB assumes that if
+ machines are compatible, then "compatible ()" always returns same machine
+ regardless of argument order. As a result GDB gets confused because, for
+ example, compatible (ARCv2, EM) returns ARCv2, but compatible (EM, ARCv2)
+ returns EM, hence GDB is not sure if they are compatible and prints a
+ warning. */
+
+static const bfd_arch_info_type *
+arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
+{
+ const bfd_arch_info_type * const em = &arch_info_struct[5];
+ const bfd_arch_info_type * const hs = &arch_info_struct[6];
+
+ /* Trivial case where a and b is the same instance. Some callers already
+ check this condition but some do not and get an invalid result. */
+ if (a == b)
+ return a;
+
+ /* If a & b are for different architecture we can do nothing. */
+ if (a->arch != b->arch)
+ return NULL;
+
+ if (a->bits_per_word != b->bits_per_word)
+ return NULL;
+
+ /* ARCv2|EM and EM. */
+ if ((a->mach == bfd_mach_arc_arcv2 && b == em)
+ || (b->mach == bfd_mach_arc_arcv2 && a == em))
+ return em;
+
+ /* ARCv2|HS and HS. */
+ if ((a->mach == bfd_mach_arc_arcv2 && b == hs)
+ || (b->mach == bfd_mach_arc_arcv2 && a == hs))
+ return hs;
+
+ return bfd_default_compatible (a, b);
+}