summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-01-04 23:15:03 +0000
committerMaciej W. Rozycki <macro@imgtec.com>2016-01-04 23:15:03 +0000
commitb2e9744f80a002c06504ac1ef41ae1f7e48167c8 (patch)
treee66ea7ecdd11cd699416301631e9dbe96e362ffd
parent28d45e28be904a53fef4310b3d41e41b045885b0 (diff)
downloadbinutils-gdb-b2e9744f80a002c06504ac1ef41ae1f7e48167c8.tar.gz
MIPS/BFD: Factor out ELF file header flag checks
Factor out the parts of `_bfd_mips_elf_merge_private_bfd_data' responsible for ELF file header flag compatibility checks to `mips_elf_merge_obj_e_flags'. As a side effect remove a premature return point from `_bfd_mips_elf_merge_private_bfd_data'. No functional change otherwise. bfd/ * elfxx-mips.c (mips_elf_merge_obj_e_flags): New function, factored out from... (_bfd_mips_elf_merge_private_bfd_data): ... here.
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elfxx-mips.c376
2 files changed, 200 insertions, 182 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index cd9e1b1b616..cea56477586 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,11 @@
2016-01-04 Maciej W. Rozycki <macro@imgtec.com>
+ * elfxx-mips.c (mips_elf_merge_obj_e_flags): New function,
+ factored out from...
+ (_bfd_mips_elf_merge_private_bfd_data): ... here.
+
+2016-01-04 Maciej W. Rozycki <macro@imgtec.com>
+
* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Fold the
handling of input MIPS ABI flags together.
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 89d4409b097..f71be498bab 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -14867,6 +14867,199 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
return TRUE;
}
+/* Merge object file header flags from IBFD into OBFD. Raise an error
+ if there are conflicting settings. */
+
+static bfd_boolean
+mips_elf_merge_obj_e_flags (bfd *ibfd, bfd *obfd)
+{
+ struct mips_elf_obj_tdata *out_tdata = mips_elf_tdata (obfd);
+ flagword old_flags;
+ flagword new_flags;
+ bfd_boolean ok;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
+ old_flags = elf_elfheader (obfd)->e_flags;
+
+ /* Check flag compatibility. */
+
+ new_flags &= ~EF_MIPS_NOREORDER;
+ old_flags &= ~EF_MIPS_NOREORDER;
+
+ /* Some IRIX 6 BSD-compatibility objects have this bit set. It
+ doesn't seem to matter. */
+ new_flags &= ~EF_MIPS_XGOT;
+ old_flags &= ~EF_MIPS_XGOT;
+
+ /* MIPSpro generates ucode info in n64 objects. Again, we should
+ just be able to ignore this. */
+ new_flags &= ~EF_MIPS_UCODE;
+ old_flags &= ~EF_MIPS_UCODE;
+
+ /* DSOs should only be linked with CPIC code. */
+ if ((ibfd->flags & DYNAMIC) != 0)
+ new_flags |= EF_MIPS_PIC | EF_MIPS_CPIC;
+
+ if (new_flags == old_flags)
+ return TRUE;
+
+ ok = TRUE;
+
+ if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
+ != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
+ {
+ (*_bfd_error_handler)
+ (_("%B: warning: linking abicalls files with non-abicalls files"),
+ ibfd);
+ ok = TRUE;
+ }
+
+ if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
+ elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
+ if (! (new_flags & EF_MIPS_PIC))
+ elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
+
+ new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+ old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+
+ /* Compare the ISAs. */
+ if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
+ {
+ (*_bfd_error_handler)
+ (_("%B: linking 32-bit code with 64-bit code"),
+ ibfd);
+ ok = FALSE;
+ }
+ else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
+ {
+ /* OBFD's ISA isn't the same as, or an extension of, IBFD's. */
+ if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd)))
+ {
+ /* Copy the architecture info from IBFD to OBFD. Also copy
+ the 32-bit flag (if set) so that we continue to recognise
+ OBFD as a 32-bit binary. */
+ bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd));
+ elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
+ elf_elfheader (obfd)->e_flags
+ |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
+
+ /* Update the ABI flags isa_level, isa_rev, isa_ext fields. */
+ update_mips_abiflags_isa (obfd, &out_tdata->abiflags);
+
+ /* Copy across the ABI flags if OBFD doesn't use them
+ and if that was what caused us to treat IBFD as 32-bit. */
+ if ((old_flags & EF_MIPS_ABI) == 0
+ && mips_32bit_flags_p (new_flags)
+ && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI))
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI;
+ }
+ else
+ {
+ /* The ISAs aren't compatible. */
+ (*_bfd_error_handler)
+ (_("%B: linking %s module with previous %s modules"),
+ ibfd,
+ bfd_printable_name (ibfd),
+ bfd_printable_name (obfd));
+ ok = FALSE;
+ }
+ }
+
+ new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
+ old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
+
+ /* Compare ABIs. The 64-bit ABI does not use EF_MIPS_ABI. But, it
+ does set EI_CLASS differently from any 32-bit ABI. */
+ if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
+ || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
+ != elf_elfheader (obfd)->e_ident[EI_CLASS]))
+ {
+ /* Only error if both are set (to different values). */
+ if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
+ || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
+ != elf_elfheader (obfd)->e_ident[EI_CLASS]))
+ {
+ (*_bfd_error_handler)
+ (_("%B: ABI mismatch: linking %s module with previous %s modules"),
+ ibfd,
+ elf_mips_abi_name (ibfd),
+ elf_mips_abi_name (obfd));
+ ok = FALSE;
+ }
+ new_flags &= ~EF_MIPS_ABI;
+ old_flags &= ~EF_MIPS_ABI;
+ }
+
+ /* Compare ASEs. Forbid linking MIPS16 and microMIPS ASE modules together
+ and allow arbitrary mixing of the remaining ASEs (retain the union). */
+ if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE))
+ {
+ int old_micro = old_flags & EF_MIPS_ARCH_ASE_MICROMIPS;
+ int new_micro = new_flags & EF_MIPS_ARCH_ASE_MICROMIPS;
+ int old_m16 = old_flags & EF_MIPS_ARCH_ASE_M16;
+ int new_m16 = new_flags & EF_MIPS_ARCH_ASE_M16;
+ int micro_mis = old_m16 && new_micro;
+ int m16_mis = old_micro && new_m16;
+
+ if (m16_mis || micro_mis)
+ {
+ (*_bfd_error_handler)
+ (_("%B: ASE mismatch: linking %s module with previous %s modules"),
+ ibfd,
+ m16_mis ? "MIPS16" : "microMIPS",
+ m16_mis ? "microMIPS" : "MIPS16");
+ ok = FALSE;
+ }
+
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE;
+
+ new_flags &= ~ EF_MIPS_ARCH_ASE;
+ old_flags &= ~ EF_MIPS_ARCH_ASE;
+ }
+
+ /* Compare NaN encodings. */
+ if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008))
+ {
+ _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
+ ibfd,
+ (new_flags & EF_MIPS_NAN2008
+ ? "-mnan=2008" : "-mnan=legacy"),
+ (old_flags & EF_MIPS_NAN2008
+ ? "-mnan=2008" : "-mnan=legacy"));
+ ok = FALSE;
+ new_flags &= ~EF_MIPS_NAN2008;
+ old_flags &= ~EF_MIPS_NAN2008;
+ }
+
+ /* Compare FP64 state. */
+ if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64))
+ {
+ _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
+ ibfd,
+ (new_flags & EF_MIPS_FP64
+ ? "-mfp64" : "-mfp32"),
+ (old_flags & EF_MIPS_FP64
+ ? "-mfp64" : "-mfp32"));
+ ok = FALSE;
+ new_flags &= ~EF_MIPS_FP64;
+ old_flags &= ~EF_MIPS_FP64;
+ }
+
+ /* Warn about any other mismatches */
+ if (new_flags != old_flags)
+ {
+ (*_bfd_error_handler)
+ (_("%B: uses different e_flags (0x%lx) fields than previous modules "
+ "(0x%lx)"),
+ ibfd, (unsigned long) new_flags,
+ (unsigned long) old_flags);
+ ok = FALSE;
+ }
+
+ return ok;
+}
+
/* Merge object attributes from IBFD into OBFD. Raise an error if
there are conflicting attributes. */
static bfd_boolean
@@ -15026,9 +15219,6 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
{
struct mips_elf_obj_tdata *out_tdata;
struct mips_elf_obj_tdata *in_tdata;
- flagword old_flags;
- flagword new_flags;
- bfd_boolean ok;
bfd_boolean null_input_bfd = TRUE;
asection *sec;
obj_attribute *out_attr;
@@ -15186,185 +15376,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
out_tdata->abiflags.ases |= in_tdata->abiflags.ases;
out_tdata->abiflags.flags1 |= in_tdata->abiflags.flags1;
- new_flags = elf_elfheader (ibfd)->e_flags;
- elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
- old_flags = elf_elfheader (obfd)->e_flags;
-
- /* Check flag compatibility. */
-
- new_flags &= ~EF_MIPS_NOREORDER;
- old_flags &= ~EF_MIPS_NOREORDER;
-
- /* Some IRIX 6 BSD-compatibility objects have this bit set. It
- doesn't seem to matter. */
- new_flags &= ~EF_MIPS_XGOT;
- old_flags &= ~EF_MIPS_XGOT;
-
- /* MIPSpro generates ucode info in n64 objects. Again, we should
- just be able to ignore this. */
- new_flags &= ~EF_MIPS_UCODE;
- old_flags &= ~EF_MIPS_UCODE;
-
- /* DSOs should only be linked with CPIC code. */
- if ((ibfd->flags & DYNAMIC) != 0)
- new_flags |= EF_MIPS_PIC | EF_MIPS_CPIC;
-
- if (new_flags == old_flags)
- return TRUE;
-
- ok = TRUE;
-
- if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
- != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
- {
- (*_bfd_error_handler)
- (_("%B: warning: linking abicalls files with non-abicalls files"),
- ibfd);
- ok = TRUE;
- }
-
- if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
- elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
- if (! (new_flags & EF_MIPS_PIC))
- elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
-
- new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
- old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
-
- /* Compare the ISAs. */
- if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
- {
- (*_bfd_error_handler)
- (_("%B: linking 32-bit code with 64-bit code"),
- ibfd);
- ok = FALSE;
- }
- else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
- {
- /* OBFD's ISA isn't the same as, or an extension of, IBFD's. */
- if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd)))
- {
- /* Copy the architecture info from IBFD to OBFD. Also copy
- the 32-bit flag (if set) so that we continue to recognise
- OBFD as a 32-bit binary. */
- bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd));
- elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
- elf_elfheader (obfd)->e_flags
- |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
-
- /* Update the ABI flags isa_level, isa_rev, isa_ext fields. */
- update_mips_abiflags_isa (obfd, &out_tdata->abiflags);
-
- /* Copy across the ABI flags if OBFD doesn't use them
- and if that was what caused us to treat IBFD as 32-bit. */
- if ((old_flags & EF_MIPS_ABI) == 0
- && mips_32bit_flags_p (new_flags)
- && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI))
- elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI;
- }
- else
- {
- /* The ISAs aren't compatible. */
- (*_bfd_error_handler)
- (_("%B: linking %s module with previous %s modules"),
- ibfd,
- bfd_printable_name (ibfd),
- bfd_printable_name (obfd));
- ok = FALSE;
- }
- }
-
- new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
- old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
-
- /* Compare ABIs. The 64-bit ABI does not use EF_MIPS_ABI. But, it
- does set EI_CLASS differently from any 32-bit ABI. */
- if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
- || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
- != elf_elfheader (obfd)->e_ident[EI_CLASS]))
- {
- /* Only error if both are set (to different values). */
- if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
- || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
- != elf_elfheader (obfd)->e_ident[EI_CLASS]))
- {
- (*_bfd_error_handler)
- (_("%B: ABI mismatch: linking %s module with previous %s modules"),
- ibfd,
- elf_mips_abi_name (ibfd),
- elf_mips_abi_name (obfd));
- ok = FALSE;
- }
- new_flags &= ~EF_MIPS_ABI;
- old_flags &= ~EF_MIPS_ABI;
- }
-
- /* Compare ASEs. Forbid linking MIPS16 and microMIPS ASE modules together
- and allow arbitrary mixing of the remaining ASEs (retain the union). */
- if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE))
- {
- int old_micro = old_flags & EF_MIPS_ARCH_ASE_MICROMIPS;
- int new_micro = new_flags & EF_MIPS_ARCH_ASE_MICROMIPS;
- int old_m16 = old_flags & EF_MIPS_ARCH_ASE_M16;
- int new_m16 = new_flags & EF_MIPS_ARCH_ASE_M16;
- int micro_mis = old_m16 && new_micro;
- int m16_mis = old_micro && new_m16;
-
- if (m16_mis || micro_mis)
- {
- (*_bfd_error_handler)
- (_("%B: ASE mismatch: linking %s module with previous %s modules"),
- ibfd,
- m16_mis ? "MIPS16" : "microMIPS",
- m16_mis ? "microMIPS" : "MIPS16");
- ok = FALSE;
- }
-
- elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE;
-
- new_flags &= ~ EF_MIPS_ARCH_ASE;
- old_flags &= ~ EF_MIPS_ARCH_ASE;
- }
-
- /* Compare NaN encodings. */
- if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008))
- {
- _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
- ibfd,
- (new_flags & EF_MIPS_NAN2008
- ? "-mnan=2008" : "-mnan=legacy"),
- (old_flags & EF_MIPS_NAN2008
- ? "-mnan=2008" : "-mnan=legacy"));
- ok = FALSE;
- new_flags &= ~EF_MIPS_NAN2008;
- old_flags &= ~EF_MIPS_NAN2008;
- }
-
- /* Compare FP64 state. */
- if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64))
- {
- _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
- ibfd,
- (new_flags & EF_MIPS_FP64
- ? "-mfp64" : "-mfp32"),
- (old_flags & EF_MIPS_FP64
- ? "-mfp64" : "-mfp32"));
- ok = FALSE;
- new_flags &= ~EF_MIPS_FP64;
- old_flags &= ~EF_MIPS_FP64;
- }
-
- /* Warn about any other mismatches */
- if (new_flags != old_flags)
- {
- (*_bfd_error_handler)
- (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
- ibfd, (unsigned long) new_flags,
- (unsigned long) old_flags);
- ok = FALSE;
- }
-
- if (! ok)
+ if (!mips_elf_merge_obj_e_flags (ibfd, obfd))
{
bfd_set_error (bfd_error_bad_value);
return FALSE;