This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] (Attempt to) Fix link compatibility check (was: Re: recent mips-elf linker "architecture ... incompatible" regressions)
Alan Modra wrote:
> On Thu, Mar 14, 2002 at 01:50:46PM +0100, Thiemo Seufer wrote:
> >
> > How will this work? It seems to do as it did before, but I don't
> > understand why it worked ever. The bfd_mach_mips* defines are not
> > always upward compatible to all of the lower numbers. E.g.
> >
> > #define bfd_mach_mips6000 6000
> >
> > and
> >
> > #define bfd_mach_mipsisa64 64
> >
> > are obvious exceptions.
>
> I don't pretend to understand mips. Please rewrite the function
> properly. ;)
The patch below fixes at least some obvious cases. I'm not sure about
the r4xxx compatibility, especially WRT r4010 which is defined as
64bit below but the disassembler calls it a MIPS II ISA. I also don't
know how mips16 should be handled, there are 32bit and 64bit CPU's
which implement the MIPS 16 extension.
Thiemo
/bfd/ChangeLog
* cpu-mips.c (compat_tree): How MIPS CPU's are upward
comapatible.
(mips_compatible): Check for CPU compatibility instead of
comparing arbitrary numbers.
diff -BurpN source-orig/bfd/cpu-mips.c source/bfd/cpu-mips.c
--- source-orig/bfd/cpu-mips.c Fri Mar 15 09:41:59 2002
+++ source/bfd/cpu-mips.c Fri Mar 15 15:25:37 2002
@@ -23,24 +23,120 @@ Foundation, Inc., 59 Temple Place - Suit
#include "sysdep.h"
#include "libbfd.h"
+static const bfd_arch_info_type *mips_compatible
+ PARAMS((const bfd_arch_info_type *, const bfd_arch_info_type *));
+
+/* MIPS CPU's aren't upward compatible in one straightforward line.
+ We can't even test for common ISA's because of additional CPU
+ specific insns. The compatibility tree is given below. */
+
+static const struct compat_tree
+{
+ unsigned int cpu;
+ unsigned int compatible;
+} compat_tree[] = {
+ {bfd_mach_mips3000, 0},
+ {bfd_mach_mips3900, bfd_mach_mips3000},
+ {bfd_mach_mips6000, bfd_mach_mips3000},
+ /* First 64bit CPU, some CP0 instructions are different. */
+ {bfd_mach_mips4000, 0},
+ {bfd_mach_mips4010, bfd_mach_mips4000},
+ {bfd_mach_mips4100, bfd_mach_mips4000},
+ {bfd_mach_mips4111, bfd_mach_mips4000},
+ {bfd_mach_mips4300, bfd_mach_mips4000},
+ {bfd_mach_mips4400, bfd_mach_mips4000},
+ {bfd_mach_mips4600, bfd_mach_mips4000},
+ {bfd_mach_mips4650, bfd_mach_mips4000},
+ {bfd_mach_mips5000, bfd_mach_mips4000},
+ {bfd_mach_mips8000, bfd_mach_mips4000},
+ {bfd_mach_mips10000, bfd_mach_mips8000},
+ {bfd_mach_mips12000, bfd_mach_mips10000},
+ /* Generic MIPS V ISA. */
+ {bfd_mach_mips5, bfd_mach_mips12000},
+ /* Generic MIPS 64 ISA. */
+ {bfd_mach_mipsisa64, bfd_mach_mips5},
+ /* Sibyte sb1. */
+ {bfd_mach_mips_sb1, bfd_mach_mipsisa64},
+ /* Generic MIPS 32 ISA. */
+ {bfd_mach_mipsisa32, 0},
+ /* Generic CPU with MIPS 16 extension. */
+ {bfd_mach_mips16, bfd_mach_mips3000},
+ /* Table termination. */
+ {0, 0}
+};
+
/* The default routine tests bits_per_word, which is wrong on mips as
mips word size doesn't correlate with reloc size. */
-const bfd_arch_info_type *
+static const bfd_arch_info_type *
mips_compatible (a, b)
const bfd_arch_info_type *a;
const bfd_arch_info_type *b;
{
+ int i;
+ int j;
+
if (a->arch != b->arch)
return NULL;
- if (a->mach > b->mach)
+ /* Check if a and b have the same mach. */
+ if (a->mach == b->mach)
return a;
- if (b->mach > a->mach)
- return b;
+ /* Check if a is upward compatible to b. */
+ for (i = 0; compat_tree[i].cpu; i++)
+ {
+ if (a->mach == compat_tree[i].cpu)
+ {
+ while (compat_tree[i].compatible
+ && (compat_tree[i].compatible != b->mach))
+ {
+ for (j = 0; compat_tree[j].cpu; j++)
+ {
+ if (compat_tree[i].compatible == compat_tree[j].cpu)
+ i = j;
+ }
+ }
+ if (compat_tree[i].compatible == b->mach)
+ return a;
+ break;
+ }
+ if (! compat_tree[i].cpu)
+ {
+ (*_bfd_error_handler)
+ (_("Internal error: %s architecture unknown"), a->printable_name);
+ abort();
+ }
+ }
+
+ /* Check if b is upward compatible to a. */
+ for (i = 0; compat_tree[i].cpu; i++)
+ {
+ if (b->mach == compat_tree[i].cpu)
+ {
+ while (compat_tree[i].compatible
+ && (compat_tree[i].compatible != a->mach))
+ {
+ for (j = 0; compat_tree[j].cpu; j++)
+ {
+ if (compat_tree[i].compatible == compat_tree[j].cpu)
+ i = j;
+ }
+ }
+ if (compat_tree[i].compatible == b->mach)
+ return b;
+ break;
+ }
+ if (! compat_tree[i].cpu)
+ {
+ (*_bfd_error_handler)
+ (_("Internal error: %s architecture unknown"), b->printable_name);
+ abort();
+ }
+ }
- return a;
+ /* a and b are incompatible. */
+ return NULL;
}
#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \