This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: QNX MIPS Support Patch


I know it's huge, but has anyone gotten a chance to take a quick look at this?

Jeff Baker wrote:

The attached files comprise a patch to add QNX MIPS support to the binutils. The changes to 'bfd/elfxx-mips.c' as they appear here are obviously not supposed to be complete, though they are functional. Everything else looks (to me) to be reasonable.

Please look it over and let me know what I have to change to get it accepted. As for 'bfd/elfxx-mips.c' I'm still trying to figure out how to piece it together proplerly as I have time. I just want to get the ball rolling on the rest.



------------------------------------------------------------------------

? ld/emulparams/elf32bmipnto.sh
? ld/emulparams/elf32lmipnto.sh
Index: ltconfig
===================================================================
RCS file: /cvs/src/src/ltconfig,v
retrieving revision 1.21
diff -w -u -1 -0 -p -r1.21 ltconfig
--- ltconfig 21 Jul 2004 19:21:41 -0000 1.21
+++ ltconfig 17 Aug 2004 17:16:20 -0000
@@ -1389,20 +1389,31 @@ dgux*)
sysv4*MP*)
if test -d /usr/nec ;then
version_type=linux
library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
soname_spec='$libname.so.$major'
shlibpath_var=LD_LIBRARY_PATH
fi
;;
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ deplibs_check_method='pass_all'
+ ;;
+ *)
dynamic_linker=no
;;
esac
echo "$ac_t$dynamic_linker" 1>&6
test "$dynamic_linker" = no && can_build_shared=no
# Check for command to grab the raw symbol name followed by C symbol from nm.
echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.296
diff -w -u -1 -0 -p -r1.296 bfd-in2.h
--- bfd/bfd-in2.h 17 Aug 2004 09:07:34 -0000 1.296
+++ bfd/bfd-in2.h 17 Aug 2004 17:16:21 -0000
@@ -2361,20 +2361,21 @@ to compensate for the borrow when the lo
BFD_RELOC_MIPS_SHIFT6,
BFD_RELOC_MIPS_INSERT_A,
BFD_RELOC_MIPS_INSERT_B,
BFD_RELOC_MIPS_DELETE,
BFD_RELOC_MIPS_HIGHEST,
BFD_RELOC_MIPS_HIGHER,
BFD_RELOC_MIPS_SCN_DISP,
BFD_RELOC_MIPS_REL16,
BFD_RELOC_MIPS_RELGOT,
BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_MIPS_QNX_COPY,
/* Fujitsu Frv Relocations. */
BFD_RELOC_FRV_LABEL16,
BFD_RELOC_FRV_LABEL24,
BFD_RELOC_FRV_LO16,
BFD_RELOC_FRV_HI16,
BFD_RELOC_FRV_GPREL12,
BFD_RELOC_FRV_GPRELU12,
BFD_RELOC_FRV_GPREL32,
Index: bfd/config.bfd
===================================================================
RCS file: /cvs/src/src/bfd/config.bfd,v
retrieving revision 1.168
diff -w -u -1 -0 -p -r1.168 config.bfd
--- bfd/config.bfd 29 Jul 2004 03:48:12 -0000 1.168
+++ bfd/config.bfd 17 Aug 2004 17:16:21 -0000
@@ -828,20 +828,35 @@ case "${targ}" in
targ_selvecs=ecoff_little_vec
;;
mips*el-*-elf* | mips*el-*-rtems* | mips*el-*-vxworks* | mips*-*-chorus*)
targ_defvec=bfd_elf32_littlemips_vec
targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
;;
mips*-*-elf* | mips*-*-rtems* | mips*-*-vxworks | mips*-*-windiss)
targ_defvec=bfd_elf32_bigmips_vec
targ_selvecs="bfd_elf32_littlemips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
;;
+ mips*eb-*-nto*)
+ targ_defvec=bfd_elf32_bigmips_vec
+ targ_selvecs="bfd_elf32_littlemips_vec"
+ targ_cflags=-D__QNXTARGET__
+ ;;
+ mips*el-*-nto*)
+ targ_defvec=bfd_elf32_littlemips_vec
+ targ_selvecs="bfd_elf32_bigmips_vec"
+ targ_cflags=-D__QNXTARGET__
+ ;;
+ mips*-*-nto*)
+ targ_defvec=bfd_elf32_littlemips_vec
+ targ_selvecs="bfd_elf32_bigmips_vec"
+ targ_cflags=-D__QNXTARGET__
+ ;;
mips*-*-none)
targ_defvec=bfd_elf32_bigmips_vec
targ_selvecs="bfd_elf32_littlemips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
;;
mips*el-*-openbsd*)
targ_defvec=bfd_elf32_littlemips_vec
targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec ecoff_little_vec ecoff_big_vec"
;;
mips*-*-openbsd*)
targ_defvec=bfd_elf32_bigmips_vec
Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.178
diff -w -u -1 -0 -p -r1.178 elf32-mips.c
--- bfd/elf32-mips.c 29 Jun 2004 13:46:30 -0000 1.178
+++ bfd/elf32-mips.c 17 Aug 2004 17:16:21 -0000
@@ -592,20 +592,41 @@ static reloc_howto_type elf_mips16_gprel
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips16_gprel_reloc, /* special_function */
"R_MIPS16_GPREL", /* name */
TRUE, /* partial_inplace */
0x07ff001f, /* src_mask */
0x07ff001f, /* dst_mask */
FALSE); /* pcrel_offset */
+/* Do a QNX pic copy relocation. This is used only with dynamic linking.
+ This works in the same way as copy relocs on other platforms: the data
+ object must exist both in the object and in the shared lib. The dynamic
+ linker copies the data from the shared object to the executable at runtime.
+ This is needed because the exec. does not access the data through the GOT.
+ */
+static reloc_howto_type elf_mips_qnx_copy_howto =
+ HOWTO (R_MIPS_QNX_COPY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_QNX_COPY", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
/* 16 bit offset for pc-relative branches. */
static reloc_howto_type elf_mips_gnu_rel16_s2 =
HOWTO (R_MIPS_GNU_REL16_S2, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
_bfd_mips_elf_generic_reloc, /* special_function */
@@ -1039,21 +1060,22 @@ static const struct elf_reloc_map mips_r
{ BFD_RELOC_16_PCREL, R_MIPS_PC16 },
{ BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
{ BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
{ BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
{ BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
{ BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
{ BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
{ BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
{ BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
{ BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
- { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
+ { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP },
+ { BFD_RELOC_MIPS_QNX_COPY, R_MIPS_QNX_COPY }
};
/* Given a BFD reloc type, return a howto structure. */
static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
{
unsigned int i;
reloc_howto_type *howto_table = elf_mips_howto_table_rel;
@@ -1315,21 +1337,23 @@ static const struct ecoff_debug_swap mip
ecoff_swap_ext_out,
_bfd_ecoff_swap_tir_out,
_bfd_ecoff_swap_rndx_out,
/* Function to read in symbolic data. */
_bfd_mips_elf_read_ecoff_info
};

#define ELF_ARCH bfd_arch_mips
#define ELF_MACHINE_CODE EM_MIPS
+#if !defined(__QNXNTO__) && !defined(__QNXTARGET__)
#define elf_backend_collect TRUE
+#endif
#define elf_backend_type_change_ok TRUE
#define elf_backend_can_gc_sections TRUE
#define elf_info_to_howto mips_info_to_howto_rela
#define elf_info_to_howto_rel mips_info_to_howto_rel
#define elf_backend_sym_is_global mips_elf_sym_is_global
#define elf_backend_object_p mips_elf32_object_p
#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
#define elf_backend_section_processing _bfd_mips_elf_section_processing
#define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
#define elf_backend_fake_sections _bfd_mips_elf_fake_sections
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.96
diff -w -u -1 -0 -p -r1.96 elflink.c
--- bfd/elflink.c 17 Aug 2004 08:51:07 -0000 1.96
+++ bfd/elflink.c 17 Aug 2004 17:16:21 -0000
@@ -2645,20 +2645,25 @@ _bfd_elf_add_dynamic_entry (struct bfd_l
const struct elf_backend_data *bed;
asection *s;
bfd_size_type newsize;
bfd_byte *newcontents;
Elf_Internal_Dyn dyn;
hash_table = elf_hash_table (info);
if (! is_elf_hash_table (hash_table))
return FALSE;
+ if (info->warn_shared_textrel && info->shared && tag == DT_TEXTREL) {
+ (*_bfd_error_handler)
+ (_("warning: creating a DT_TEXTREL in a shared object."));
+ }
+ bed = get_elf_backend_data (hash_table->dynobj);
s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
BFD_ASSERT (s != NULL);
newsize = s->size + bed->s->sizeof_dyn;
newcontents = bfd_realloc (s->contents, newsize);
if (newcontents == NULL)
return FALSE;
dyn.d_tag = tag;
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.109
diff -w -u -1 -0 -p -r1.109 elfxx-mips.c
--- bfd/elfxx-mips.c 13 Aug 2004 03:15:59 -0000 1.109
+++ bfd/elfxx-mips.c 17 Aug 2004 17:16:22 -0000
@@ -608,20 +608,28 @@ static bfd *reldyn_sorting_bfd;
((ABI_64_P (abfd) \
? 0x03e0782d /* daddu t7,ra */ \
: 0x03e07821)) /* addu t7,ra */
#define STUB_JALR 0x0320f809 /* jalr t9,ra */
#define STUB_LI16(abfd) \
((ABI_64_P (abfd) \
? 0x64180000 /* daddiu t8,zero,0 */ \
: 0x24180000)) /* addiu t8,zero,0 */
#define MIPS_FUNCTION_STUB_SIZE (16)
+/* Stubs for QNX pic function calls. Allow calling a lib from non-pic code */
+#define STUB_QNX_LW(abfd) \
+ (SGI_COMPAT (abfd) \
+ ? 0x8f998010 /* lw at,0x8010(gp) */ \
+ : 0x8f998000) /* lw at,0x8000(gp) */
+#define STUB_QNX_NOP 0x00000000
+#define STUB_QNX_JR 0x03200008 /* jal t9 */ +
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#define ELF_DYNAMIC_INTERPRETER(abfd) \
(ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" \
: ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" \
: "/usr/lib/libc.so.1")
#ifdef BFD64
#define MNAME(bfd,pre,pos) \
@@ -1173,20 +1181,32 @@ _bfd_mips_elf_got16_reloc (bfd *abfd, ar
bfd *output_bfd, char **error_message)
{
if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
|| bfd_is_und_section (bfd_get_section (symbol))
|| bfd_is_com_section (bfd_get_section (symbol)))
/* The relocation is against a global symbol. */
return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd,
error_message);
+#ifdef __QNXTARGET__
+/* Else we might be doing a reloc from a local symbol, but we want it
+ to be a got16 reloc, instead of a reloc against a section */
+if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_GLOBAL))
+ {
+ reloc_entry->address += input_section->output_offset;
+ // reloc_entry->addend = 0;
+ return bfd_reloc_ok;
+ }
+#endif
+
return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
}
/* A howto special_function for REL *LO16 relocations. The *LO16 itself
is a straightforward 16 bit inplace relocation, but we must deal with
any partnering high-part relocations as well. */
bfd_reloc_status_type
_bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
@@ -2134,20 +2154,30 @@ mips_elf_record_global_got_symbol (struc
memcpy (*loc, &entry, sizeof entry);
if (h->got.offset != MINUS_ONE)
return TRUE;
/* By setting this to a value other than -1, we are indicating that
there needs to be a GOT entry for H. Avoid using zero, as the
generic ELF copy_indirect_symbol tests for <= 0. */
h->got.offset = 1;
+#ifdef __QNXTARGET__
+ if (g==NULL)
+ return TRUE;
+/* Note the index of the first global got symbol in .dynsym. */
+if (g->global_gotsym == NULL
+ || g->global_gotsym->dynindx > h->dynindx) {
+ g->global_gotsym = h;
+ }
+#endif
+
return TRUE;
}
/* Reserve space in G for a GOT entry containing the value of symbol
SYMNDX in input bfd ABDF, plus ADDEND. */
static bfd_boolean
mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
struct mips_got_info *g)
{
@@ -3296,21 +3326,25 @@ mips_elf_calculate_relocation (bfd *abfd
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
if ((info->shared
|| (elf_hash_table (info)->dynamic_sections_created
&& h != NULL
&& ((h->root.elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0)
&& ((h->root.elf_link_hash_flags
+#ifdef __QNXTARGET__
+ & (ELF_LINK_HASH_DEF_REGULAR|ELF_LINK_HASH_NEEDS_COPY)) == 0)))
+#else
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
+#endif
&& r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0)
{
/* If we're creating a shared library, or this relocation is
against a symbol in a shared library, then we can't know
where the symbol will end up. So, we create a relocation
record in the output, and leave the job up to the dynamic
linker. */
value = addend;
if (!mips_elf_create_dynamic_relocation (abfd,
@@ -4996,20 +5030,67 @@ _bfd_mips_elf_create_dynamic_sections (b
h = (struct elf_link_hash_entry *) bh;
h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
}
+#ifdef __QNXTARGET__
+ /* QNX - The .rel.bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! info->shared)
+ {
+ s = bfd_make_section (abfd, ".rel.bss");
+
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 3))
+ return FALSE;
+ }
+
+ /* We also make a .bss and .sbss section here. This is needed in
+ case we have copy relocs, but didn't have a bss section in
+ from the normal symbols. */
+
+ if ((! info->shared)
+ && bfd_get_section_by_name (abfd, ".bss") == NULL)
+ {
+ s = bfd_make_section (abfd, ".bss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, SEC_RELOC | SEC_ALLOC | SEC_HAS_CONTENTS)
+ || ! bfd_set_section_alignment (abfd, s, 3))
+ return FALSE;
+ }
+
+ if ((! info->shared)
+ && bfd_get_section_by_name (abfd, ".sbss") == NULL)
+ {
+ s = bfd_make_section (abfd, ".sbss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, SEC_RELOC | SEC_ALLOC | SEC_HAS_CONTENTS)
+ || ! bfd_set_section_alignment (abfd, s, 3))
+ return FALSE;
+ }
+#endif
+
return TRUE;
}

/* Look through the relocs for a section during the first phase, and
allocate space in the global offset table. */
bfd_boolean
_bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
asection *sec, const Elf_Internal_Rela *relocs)
{
@@ -5260,20 +5341,21 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
if (dynobj == NULL)
elf_hash_table (info)->dynobj = dynobj = abfd;
if (! mips_elf_create_got_section (dynobj, info, FALSE))
return FALSE;
g = mips_elf_got_info (dynobj, &sgot);
break;
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
+ case R_MIPS_QNX_COPY:
if (dynobj == NULL
&& (info->shared || h != NULL)
&& (sec->flags & SEC_ALLOC) != 0)
elf_hash_table (info)->dynobj = dynobj = abfd;
break;
default:
break;
}
}
@@ -5351,20 +5433,21 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
case R_MIPS_GOT_LO16:
case R_MIPS_GOT_DISP:
/* This symbol requires a global offset table entry. */
if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g))
return FALSE;
break;
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
+ case R_MIPS_QNX_COPY:
if ((info->shared || h != NULL)
&& (sec->flags & SEC_ALLOC) != 0)
{
if (sreloc == NULL)
{
sreloc = mips_elf_rel_dyn_section (dynobj, TRUE);
if (sreloc == NULL)
return FALSE;
}
#define MIPS_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
@@ -5661,45 +5744,63 @@ _bfd_mips_relax_section (bfd *abfd, asec
dynamic object, but we're not including those sections. We have to
change the definition to something the rest of the link can
understand. */
bfd_boolean
_bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
+#ifdef __QNXTARGET__
+ asection *s, *sreldyn=NULL;
+ unsigned int power_of_two;
+#else
asection *s;
+#endif
dynobj = elf_hash_table (info)->dynobj;
+#ifdef __QNXTARGET__
+ if (h->got.offset == MINUS_ONE)
+ {
+ h->got.offset = 1;
+ }
+#endif
+
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+#ifdef __QNXTARGET__
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY)
+#endif
|| h->weakdef != NULL
|| ((h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)));
/* If this symbol is defined in a dynamic object, we need to copy
any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
file. */
hmips = (struct mips_elf_link_hash_entry *) h;
if (! info->relocatable
&& hmips->possibly_dynamic_relocs != 0
&& (h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))
{
+#ifdef __QNXTARGET__
+ sreldyn = bfd_get_section_by_name (dynobj, ".rel.dyn");
+#endif
mips_elf_allocate_dynamic_relocations (dynobj,
hmips->possibly_dynamic_relocs);
if (hmips->readonly_reloc)
/* We tell the dynamic linker that there are relocations
against the text segment. */
info->flags |= DF_TEXTREL;
}
/* For a function, create a stub, if allowed. */
if (! hmips->no_fn_stub
@@ -5732,38 +5833,130 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
of this symbol in .dynsym section. */
return TRUE;
}
}
else if ((h->type == STT_FUNC)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
{
/* This will set the entry for this symbol in the GOT to 0, and
the dynamic linker will take care of this. */
h->root.u.def.value = 0;
+#ifdef __QNXTARGET__
+ /* If this symbol is not defined in a regular file, then set
+ the symbol to the stub location. This is required to make
+ function pointers compare as equal between the normal
+ executable and the shared library. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* We need .stub section. */
+ s = bfd_get_section_by_name (dynobj,
+ MIPS_ELF_STUB_SECTION_NAME (dynobj));
+ BFD_ASSERT (s != NULL);
+
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ if ( sreldyn != NULL ) {
+ sreldyn->size -= hmips->possibly_dynamic_relocs * sizeof (Elf32_External_Rel);
+ if ( sreldyn->size == sizeof(Elf32_External_Rel) ) {
+ sreldyn->reloc_count--;
+ sreldyn->size = 0;
+ }
+ }
+
+ /* XXX Write this stub address somewhere. */
+ h->plt.offset = s->size;
+
+ /* Make room for this stub code. */
+ s->size += MIPS_FUNCTION_STUB_SIZE;
+
+ /* The last half word of the stub will be filled with the index
+ of this symbol in .dynsym section. */
+ return TRUE;
+ }
+#endif
return TRUE;
}
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
if (h->weakdef != NULL)
{
BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
|| h->weakdef->root.type == bfd_link_hash_defweak);
h->root.u.def.section = h->weakdef->root.u.def.section;
h->root.u.def.value = h->weakdef->root.u.def.value;
return TRUE;
}
/* This is a reference to a symbol defined by a dynamic object which
is not a function. */
+#ifdef __QNXTARGET__
+ if (info->shared)
+ return FALSE;
+ /* In this case, it is a data reference; we must therefore allocate it
+ in the bss/sbss, and generate a copy relocation for it.
+ */
+ if(h->size <= elf_gp_size (dynobj))
+ s = bfd_get_section_by_name(dynobj, ".sbss");
+ else
+ s = bfd_get_section_by_name(dynobj, ".bss");
+ BFD_ASSERT (s != NULL);
+
+ /* Now we need to set up a copy relocation for this object */
+ /* Come back and check flags here for QNX_COPY... */
+ if (1 || (h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ asection *srel;
+ srel = bfd_get_section_by_name(dynobj, ".rel.bss");
+ BFD_ASSERT (srel != NULL);
+ srel->rawsize += sizeof (Elf32_External_Rel);
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+
+ if ( sreldyn != NULL ) {
+ sreldyn->rawsize -= hmips->possibly_dynamic_relocs * sizeof (Elf32_External_Rel);
+ if ( sreldyn->rawsize == sizeof(Elf32_External_Rel) ) {
+ sreldyn->reloc_count--;
+ sreldyn->rawsize = 0;
+ }
+ }
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->rawsize = BFD_ALIGN (s->rawsize,
+ (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+ return FALSE;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->rawsize;
+
+ /* Increment the section size to make room for the symbol. */
+ s->rawsize += h->size;
+ /* Work around bug in sbss handling */
+ s->size = s->rawsize;
+
+#endif
+
return TRUE;
}

/* This function is called after all the input files have been read,
and the input sections have been assigned to output sections. We
check for any mips16 stub sections that we can discard. */
bfd_boolean
_bfd_mips_elf_always_size_sections (bfd *output_bfd,
struct bfd_link_info *info)
@@ -5780,21 +5973,20 @@ _bfd_mips_elf_always_size_sections (bfd /* The .reginfo section has a fixed size. */
ri = bfd_get_section_by_name (output_bfd, ".reginfo");
if (ri != NULL)
bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
if (! (info->relocatable
|| ! mips_elf_hash_table (info)->mips16_stubs_seen))
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
mips_elf_check_mips16_stubs, NULL);
-
dynobj = elf_hash_table (info)->dynobj;
if (dynobj == NULL)
/* Relocatable links don't have it. */
return TRUE;
g = mips_elf_got_info (dynobj, &s);
if (s == NULL)
return TRUE;
/* Calculate the total loadable size of the output. That
@@ -5949,20 +6141,89 @@ _bfd_mips_elf_size_dynamic_sections (bfd
else if (strncmp (name, ".got", 4) == 0)
{
/* _bfd_mips_elf_always_size_sections() has already done
most of the work, but some symbols may have been mapped
to versions that we must now resolve in the got_entries
hash tables. */
struct mips_got_info *gg = mips_elf_got_info (dynobj, NULL);
struct mips_got_info *g = gg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
unsigned int needed_relocs = 0;
+#ifdef __QNXTARGET__
+ bfd *dynobj;
+ asection *s;
+ int i;
+ bfd_size_type loadable_size = 0;
+ bfd_size_type local_gotno;
+ bfd *sub;
+
+dynobj = elf_hash_table (info)->dynobj;
+ if (dynobj == NULL)
+ /* Relocatable links don't have it. */
+ return TRUE;
+ g = mips_elf_got_info (dynobj, &s);
+ if (s == NULL)
+ return TRUE;
+
+ /* Calculate the total loadable size of the output. That
+ will give us the maximum number of GOT_PAGE entries
+ required. */
+ for (sub = info->input_bfds; sub; sub = sub->link_next)
+ {
+ asection *subsection;
+
+ for (subsection = sub->sections;
+ subsection;
+ subsection = subsection->next)
+ {
+ if ((subsection->flags & SEC_ALLOC) == 0)
+ continue;
+ loadable_size += ((subsection->size + 0xf)
+ &~ (bfd_size_type) 0xf);
+ }
+ }
+
+ /* There has to be a global GOT entry for every symbol with
+ a dynamic symbol table index of DT_MIPS_GOTSYM or
+ higher. Therefore, it make sense to put those symbols
+ that need GOT entries at the end of the symbol table. We
+ do that here. */
+
+ if (! mips_elf_sort_hash_table (info, 1))
+ return FALSE;
+
+ if (g->global_gotsym != NULL)
+ i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
+ else + /* If there are no global symbols, or none requiring
+ relocations, then GLOBAL_GOTSYM will be NULL. */
+ i = 0;
+
+ /* In the worst case, we'll get one stub per dynamic symbol, plus
+ one to account for the dummy entry at the end required by IRIX
+ rld. */
+ loadable_size += MIPS_FUNCTION_STUB_SIZE * (i + 1);
+
+ /* Assume there are two loadable segments consisting of
+ contiguous sections. Is 5 enough? */
+ local_gotno = (loadable_size >> 16) + 5;
+
+ g->local_gotno += local_gotno;
+ s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
+
+ g->global_gotno = i;
+ s->size += i * MIPS_ELF_GOT_SIZE (output_bfd);
+
+ if (s->size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)
+ && ! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
+ return FALSE;
+#endif
if (gg->next)
{
set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
set_got_offset_arg.info = info;
mips_elf_resolve_final_got_entries (gg);
for (g = gg->next; g && g->next != gg; g = g->next)
{
unsigned int save_assign;
@@ -6067,21 +6328,26 @@ _bfd_mips_elf_size_dynamic_sections (bfd
if ((info->flags & DF_TEXTREL) != 0)
{
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
return FALSE;
}
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
return FALSE;
+#ifdef __QNXTARGET__
+ if (mips_elf_rel_dyn_section (dynobj, FALSE)
+ || (bfd_get_section_by_name (dynobj, ".rel.bss")))
+#else
if (mips_elf_rel_dyn_section (dynobj, FALSE))
+#endif
{
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
return FALSE;
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
return FALSE;
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
return FALSE;
}
@@ -6560,69 +6826,98 @@ mips_elf_irix6_finish_dynamic_symbol (bf
bfd_boolean
_bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
struct bfd_link_info *info,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
bfd *dynobj;
asection *sgot;
struct mips_got_info *g, *gg;
const char *name;
+#ifdef __QNXTARGET__
+ + flagword flags;
+
+ /* To see if we are linking PIC */
+ flags = elf_elfheader (output_bfd)->e_flags;
+#endif
dynobj = elf_hash_table (info)->dynobj;
+ sgot = mips_elf_got_section (dynobj, FALSE);
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
+ g = mips_elf_section_data (sgot)->u.got_info;
+ BFD_ASSERT (g != NULL)
+
if (h->plt.offset != MINUS_ONE)
{
asection *s;
bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
/* This symbol has a stub. Set it up. */
BFD_ASSERT (h->dynindx != -1);
s = bfd_get_section_by_name (dynobj,
MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
/* FIXME: Can h->dynindex be more than 64K? */
if (h->dynindx & 0xffff0000)
return FALSE;
/* Fill the stub. */
+#ifdef __QNXTARGET__
+ if ((flags & EF_MIPS_PIC) || (flags & EF_MIPS_CPIC)) {
+#endif
bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub);
bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + 4);
bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub + 12);
+#ifdef __QNXTARGET__
+ } else {
+ bfd_size_type offset;
+ if (g->global_gotsym)
+ offset = (h->dynindx - g->global_gotsym->dynindx + g->local_gotno) * 4;
+ else
+ offset = (h->dynindx + g->local_gotno) * 4;
+ bfd_put_32 (output_bfd, (STUB_LW(output_bfd) & 0xffff0000) | (0xffff & (0x8010 + offset)), stub);
+ bfd_put_32 (output_bfd, STUB_QNX_JR, stub+4);
+ bfd_put_32 (output_bfd, STUB_QNX_NOP, stub+8);
+ bfd_put_32 (output_bfd, STUB_QNX_NOP, stub+12);
+ }
+#endif
BFD_ASSERT (h->plt.offset <= s->size);
memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
/* Mark the symbol as undefined. plt.offset != -1 occurs
only for the referenced symbol. */
sym->st_shndx = SHN_UNDEF;
/* The run-time linker uses the st_value field of the symbol
to reset the global offset table entry for this external
to its stub address when unlinking a shared object. */
- sym->st_value = (s->output_section->vma + s->output_offset
- + h->plt.offset);
+#ifdef __QNXTARGET__
+ if ((flags & EF_MIPS_PIC) || (flags & EF_MIPS_CPIC) || !info->shared)
+#endif
+ sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset);
+#ifdef __QNXTARGET__
+ else
+ sym->st_value = 0;
+#endif
}
BFD_ASSERT (h->dynindx != -1
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
- sgot = mips_elf_got_section (dynobj, FALSE);
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- g = mips_elf_section_data (sgot)->u.got_info;
- BFD_ASSERT (g != NULL);
-
/* Run through the global symbol table, creating GOT entries for all
the symbols that need them. */
if (g->global_gotsym != NULL
&& h->dynindx >= g->global_gotsym->dynindx)
{
bfd_vma offset;
bfd_vma value;
value = sym->st_value;
offset = mips_elf_global_got_index (dynobj, output_bfd, h);
@@ -6749,20 +7044,42 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
{
/* IRIX6 does not use a .rld_map section. */
if (IRIX_COMPAT (output_bfd) == ict_irix5
|| IRIX_COMPAT (output_bfd) == ict_none)
BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
!= NULL);
mips_elf_hash_table (info)->rld_value = sym->st_value;
}
}
+#ifdef __QNXTARGET__
+ /* Finish handling the QNX_COPY relocs if there are any */
+ if (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY)
+ {
+ asection *s;
+ Elf_Internal_Rela rel;
+
+ /* Set up the copy reloc */
+ BFD_ASSERT (h->dynindx != -1);
+ s = bfd_get_section_by_name (h->root.u.def.section->owner,
+ ".rel.bss");
+ BFD_ASSERT (s != NULL);
+
+ rel.r_offset = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_QNX_COPY);
+ bfd_elf32_swap_reloc_out (output_bfd, &rel,
+ (s->contents + s->reloc_count * sizeof (Elf32_External_Rel)));
+ ++s->reloc_count;
+ }
+#endif
/* If this is a mips16 symbol, force the value to be even. */
if (sym->st_other == STO_MIPS16)
sym->st_value &= ~1;
return TRUE;
}
/* Finish up the dynamic sections. */
bfd_boolean
@@ -6810,20 +7127,23 @@ _bfd_mips_elf_finish_dynamic_sections (b
/* Read in the current dynamic entry. */
(*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
/* Assume that we're going to modify it and write it out. */
swap_out_p = TRUE;
switch (dyn.d_tag)
{
case DT_RELENT:
s = mips_elf_rel_dyn_section (dynobj, FALSE);
+#ifdef __QNXTARGET__
+ if (s == NULL) s = bfd_get_section_by_name (dynobj, ".rel.bss");
+#endif
BFD_ASSERT (s != NULL);
dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
break;
case DT_STRSZ:
/* Rewrite DT_STRSZ. */
dyn.d_un.d_val =
_bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
break;
@@ -7909,20 +8229,25 @@ _bfd_elf_mips_get_relocated_section_cont
reloc_vector = bfd_malloc (reloc_size);
if (reloc_vector == NULL && reloc_size != 0)
goto error_return;
/* read in the section */
sz = input_section->rawsize ? input_section->rawsize : input_section->size;
if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
goto error_return;
+#ifdef __QNXTARGET__
+ /* We're not relaxing the section, so just copy the size info */
+ input_section->size = input_section->rawsize;
+ input_section->reloc_done = TRUE;
+#endif
reloc_count = bfd_canonicalize_reloc (input_bfd,
input_section,
reloc_vector,
symbols);
if (reloc_count < 0)
goto error_return;
if (reloc_count > 0)
{
arelent **parent;
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.121
diff -w -u -1 -0 -p -r1.121 libbfd.h
--- bfd/libbfd.h 6 Aug 2004 16:18:02 -0000 1.121
+++ bfd/libbfd.h 17 Aug 2004 17:16:22 -0000
@@ -912,21 +912,21 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_MIPS_SHIFT6",
"BFD_RELOC_MIPS_INSERT_A",
"BFD_RELOC_MIPS_INSERT_B",
"BFD_RELOC_MIPS_DELETE",
"BFD_RELOC_MIPS_HIGHEST",
"BFD_RELOC_MIPS_HIGHER",
"BFD_RELOC_MIPS_SCN_DISP",
"BFD_RELOC_MIPS_REL16",
"BFD_RELOC_MIPS_RELGOT",
"BFD_RELOC_MIPS_JALR",
-
+ "BFD_RELOC_MIPS_QNX_COPY",
"BFD_RELOC_FRV_LABEL16",
"BFD_RELOC_FRV_LABEL24",
"BFD_RELOC_FRV_LO16",
"BFD_RELOC_FRV_HI16",
"BFD_RELOC_FRV_GPREL12",
"BFD_RELOC_FRV_GPRELU12",
"BFD_RELOC_FRV_GPREL32",
"BFD_RELOC_FRV_GPRELHI",
"BFD_RELOC_FRV_GPRELLO",
"BFD_RELOC_FRV_GOT12",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.110
diff -w -u -1 -0 -p -r1.110 reloc.c
--- bfd/reloc.c 6 Aug 2004 16:18:02 -0000 1.110
+++ bfd/reloc.c 17 Aug 2004 17:16:22 -0000
@@ -2105,20 +2105,22 @@ ENUMX
ENUMX
BFD_RELOC_MIPS_HIGHER
ENUMX
BFD_RELOC_MIPS_SCN_DISP
ENUMX
BFD_RELOC_MIPS_REL16
ENUMX
BFD_RELOC_MIPS_RELGOT
ENUMX
BFD_RELOC_MIPS_JALR
+ENUMX
+ BFD_RELOC_MIPS_QNX_COPY
ENUMDOC
MIPS ELF relocations.
COMMENT
ENUM
BFD_RELOC_FRV_LABEL16
ENUMX
BFD_RELOC_FRV_LABEL24
ENUMX
BFD_RELOC_FRV_LO16
Index: gas/configure
===================================================================
RCS file: /cvs/src/src/gas/configure,v
retrieving revision 1.175
diff -w -u -1 -0 -p -r1.175 configure
--- gas/configure 16 Aug 2004 08:25:44 -0000 1.175
+++ gas/configure 17 Aug 2004 17:16:23 -0000
@@ -4435,20 +4435,21 @@ echo "$as_me: error: Unknown vendor for mips-*-ecoff*) fmt=ecoff ;;
mips-*-pe*) fmt=coff endian=little em=pe ;;
mips-*-irix6*) fmt=elf em=irix ;;
mips-*-irix5*) fmt=elf em=irix ;;
mips-*-irix*) fmt=ecoff em=irix ;;
mips-*-lnews*) fmt=ecoff em=lnews ;;
mips-*-riscos*) fmt=ecoff ;;
mips*-*-linux*) fmt=elf em=tmips ;;
mips-*-sysv4*MP* | mips-*-gnu*) fmt=elf em=tmips ;;
mips-*-sysv*) fmt=ecoff ;;
+ mips*-*-nto*) fmt=elf ;;
mips-*-elf* | mips-*-rtems*) fmt=elf ;;
mips-*-netbsd*) fmt=elf ;;
mips-*-openbsd*) fmt=elf ;;
mmix-*-*) fmt=elf ;;
mn10200-*-*) fmt=elf ;;
# cpu_type for am33_2.0 is set to mn10300
mn10300-*-linux*) fmt=elf bfd_gas=yes em=linux ;;
mn10300-*-*) fmt=elf ;;
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.159
diff -w -u -1 -0 -p -r1.159 configure.in
--- gas/configure.in 16 Aug 2004 08:25:44 -0000 1.159
+++ gas/configure.in 17 Aug 2004 17:16:23 -0000
@@ -387,20 +387,21 @@ changequote([,])dnl
mips-*-ecoff*) fmt=ecoff ;;
mips-*-pe*) fmt=coff endian=little em=pe ;;
mips-*-irix6*) fmt=elf em=irix ;;
mips-*-irix5*) fmt=elf em=irix ;;
mips-*-irix*) fmt=ecoff em=irix ;;
mips-*-lnews*) fmt=ecoff em=lnews ;;
mips-*-riscos*) fmt=ecoff ;;
mips*-*-linux*) fmt=elf em=tmips ;;
mips-*-sysv4*MP* | mips-*-gnu*) fmt=elf em=tmips ;;
mips-*-sysv*) fmt=ecoff ;;
+ mips*-*-nto*) fmt=elf ;;
mips-*-elf* | mips-*-rtems*) fmt=elf ;;
mips-*-netbsd*) fmt=elf ;;
mips-*-openbsd*) fmt=elf ;;
mmix-*-*) fmt=elf ;;
mn10200-*-*) fmt=elf ;;
# cpu_type for am33_2.0 is set to mn10300
mn10300-*-linux*) fmt=elf bfd_gas=yes em=linux ;;
mn10300-*-*) fmt=elf ;;
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.269
diff -w -u -1 -0 -p -r1.269 tc-mips.c
--- gas/config/tc-mips.c 20 Jul 2004 17:55:02 -0000 1.269
+++ gas/config/tc-mips.c 17 Aug 2004 17:16:24 -0000
@@ -877,20 +877,22 @@ static size_t my_getSmallExpression
static void my_getExpression (expressionS *, char *);
static void s_align (int);
static void s_change_sec (int);
static void s_change_section (int);
static void s_cons (int);
static void s_float_cons (int);
static void s_mips_globl (int);
static void s_option (int);
static void s_mipsset (int);
static void s_abicalls (int);
+static void s_qnxpiccalls PARAMS ((int));
+static void s_noqnxpiccalls PARAMS ((int));
static void s_cpload (int);
static void s_cpsetup (int);
static void s_cplocal (int);
static void s_cprestore (int);
static void s_cpreturn (int);
static void s_gpvalue (int);
static void s_gpword (int);
static void s_gpdword (int);
static void s_cpadd (int);
static void s_insn (int);
@@ -943,20 +945,22 @@ static const struct mips_cpu_info *mips_
static const pseudo_typeS mips_pseudo_table[] =
{
/* MIPS specific pseudo-ops. */
{"option", s_option, 0},
{"set", s_mipsset, 0},
{"rdata", s_change_sec, 'r'},
{"sdata", s_change_sec, 's'},
{"livereg", s_ignore, 0},
{"abicalls", s_abicalls, 0},
+ {"qnxpiccalls", s_qnxpiccalls, 0},
+ {"noqnxpiccalls", s_noqnxpiccalls, 0},
{"cpload", s_cpload, 0},
{"cpsetup", s_cpsetup, 0},
{"cplocal", s_cplocal, 0},
{"cprestore", s_cprestore, 0},
{"cpreturn", s_cpreturn, 0},
{"gpvalue", s_gpvalue, 0},
{"gpword", s_gpword, 0},
{"gpdword", s_gpdword, 0},
{"cpadd", s_cpadd, 0},
{"insn", s_insn, 0},
@@ -3876,21 +3880,21 @@ load_address (int reg, expressionS *ep, mips_gp_register, BFD_RELOC_GPREL16);
relax_switch ();
}
macro_build_lui (ep, reg);
macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j",
reg, reg, BFD_RELOC_LO16);
if (mips_relax.sequence)
relax_end ();
}
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! mips_big_got)
{
expressionS ex;
/* If this is a reference to an external symbol, we want
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
Otherwise we want
lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
If there is a constant, it must be added in after.
@@ -3900,58 +3904,58 @@ load_address (int reg, expressionS *ep, unless we're referencing a global symbol with a non-zero
offset, in which case cst must be added separately. */
if (HAVE_NEWABI)
{
if (ep->X_add_number)
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
relax_start (ep->X_add_symbol);
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j",
reg, reg, BFD_RELOC_LO16);
ep->X_add_number = ex.X_add_number;
relax_switch ();
}
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
if (mips_relax.sequence)
relax_end ();
}
else
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
load_delay_nop ();
relax_start (ep->X_add_symbol);
relax_switch ();
macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_LO16);
relax_end ();
if (ex.X_add_number != 0)
{
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j",
reg, reg, BFD_RELOC_LO16);
}
}
}
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
{
expressionS ex;
/* This is the large GOT case. If this is a reference to an
external symbol, we want
lui $reg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $reg,$reg,$gp
lw $reg,<sym>($reg) (BFD_RELOC_MIPS_GOT_LO16)
Otherwise, for a reference to a local symbol in old ABI, we want
@@ -3964,61 +3968,61 @@ load_address (int reg, expressionS *ep, lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
addiu $reg,$reg,<sym> (BFD_RELOC_MIPS_GOT_OFST)
*/
if (HAVE_NEWABI)
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
relax_start (ep->X_add_symbol);
macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_GOT_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- reg, reg, mips_gp_register);
+ reg, reg, GOT_REG);
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)",
reg, BFD_RELOC_MIPS_GOT_LO16, reg);
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
else if (ex.X_add_number)
{
ex.X_op = O_constant;
macro_build (&ex, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_LO16);
}
ep->X_add_number = ex.X_add_number;
relax_switch ();
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_PAGE, GOT_REG);
macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_MIPS_GOT_OFST);
relax_end ();
}
else
{
ex.X_add_number = ep->X_add_number;
ep->X_add_number = 0;
relax_start (ep->X_add_symbol);
macro_build (ep, "lui", "t,u", reg, BFD_RELOC_MIPS_GOT_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- reg, reg, mips_gp_register);
+ reg, reg, GOT_REG);
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)",
reg, BFD_RELOC_MIPS_GOT_LO16, reg);
relax_switch ();
- if (reg_needs_delay (mips_gp_register))
+ if (reg_needs_delay (GOT_REG))
{
/* We need a nop before loading from $gp. This special
check is required because the lui which starts the main
instruction stream does not refer to $gp, and so will not
insert the nop which may be required. */
macro_build (NULL, "nop", "");
}
macro_build (ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
load_delay_nop ();
macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
BFD_RELOC_LO16);
relax_end ();
if (ex.X_add_number != 0)
{
if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
ex.X_op = O_constant;
@@ -4057,24 +4061,24 @@ move_register (int dest, int source)
static void
load_got_offset (int dest, expressionS *local)
{
expressionS global;
global = *local;
global.X_add_number = 0;
relax_start (local->X_add_symbol);
macro_build (&global, ADDRESS_LOAD_INSN, "t,o(b)", dest,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
relax_switch ();
macro_build (local, ADDRESS_LOAD_INSN, "t,o(b)", dest,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
relax_end ();
}
static void
add_got_offset (int dest, expressionS *local)
{
expressionS global;
global.X_op = O_constant;
global.X_op_symbol = NULL;
@@ -4958,31 +4962,31 @@ macro (struct mips_cl_insn *ip)
tempreg, tempreg, BFD_RELOC_LO16);
}
}
else
{
if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
&& ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- tempreg, mips_gp_register, BFD_RELOC_GPREL16);
+ tempreg, GOT_REG, BFD_RELOC_GPREL16);
relax_switch ();
}
macro_build_lui (&offset_expr, tempreg);
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
if (mips_relax.sequence)
relax_end ();
}
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! mips_big_got && ! HAVE_NEWABI)
{
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* If this is a reference to an external symbol, and there
is no constant, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
or for lca or if tempreg is PIC_CALL_REG
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
@@ -5009,31 +5013,31 @@ macro (struct mips_cl_insn *ip)
addiu instruction.
*/
if (offset_expr.X_add_number == 0)
{
if (breg == 0 && (call || tempreg == PIC_CALL_REG))
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- lw_reloc_type, mips_gp_register);
+ lw_reloc_type, GOT_REG);
if (breg != 0)
{
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
load_delay_nop ();
}
relax_switch ();
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
- tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ tempreg, BFD_RELOC_MIPS_GOT16, GOT_REG);
load_delay_nop ();
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
relax_end ();
/* FIXME: If breg == 0, and the next instruction uses
$tempreg, then if this variant case is used an extra
nop will be generated. */
}
else if (offset_expr.X_add_number >= -0x8000
&& offset_expr.X_add_number < 0x8000)
@@ -5061,21 +5065,21 @@ macro (struct mips_cl_insn *ip)
load_delay_nop ();
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, AT, breg);
breg = 0;
tempreg = treg;
}
add_got_offset_hilo (tempreg, &offset_expr, AT);
used_at = 1;
}
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got && HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! mips_big_got && HAVE_NEWABI)
{
int add_breg_early = 0;
/* If this is a reference to an external, and there is no
constant, or local symbol (*), with or without a
constant, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_DISP)
or for lca or if tempreg is PIC_CALL_REG
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
@@ -5095,21 +5099,21 @@ macro (struct mips_cl_insn *ip)
local symbols, even though it introduces an additional
instruction. */
if (offset_expr.X_add_number)
{
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
}
else if (IS_SEXT_32BIT_NUM (expr1.X_add_number + 0x8000))
{
int dreg;
@@ -5138,47 +5142,47 @@ macro (struct mips_cl_insn *ip)
used_at = 1;
}
else
as_bad (_("PIC code offset overflow (max 32 signed bits)"));
relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
if (add_breg_early)
{
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, tempreg, breg);
breg = 0;
tempreg = treg;
}
relax_end ();
}
else if (breg == 0 && (call || tempreg == PIC_CALL_REG))
{
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_CALL16, mips_gp_register);
+ BFD_RELOC_MIPS_CALL16, GOT_REG);
relax_switch ();
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
relax_end ();
}
else
{
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_DISP, GOT_REG);
}
}
- else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! HAVE_NEWABI)
{
int gpdelay;
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
int local_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* This is the large GOT case. If this is a reference to an
external symbol, and there is no constant, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $tempreg,$tempreg,$gp
@@ -5215,30 +5219,30 @@ macro (struct mips_cl_insn *ip)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
lui $at,<hiconstant>
addiu $at,$at,<loconstant> (BFD_RELOC_LO16)
addu $tempreg,$tempreg,$at
*/
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
relax_start (offset_expr.X_add_symbol);
- gpdelay = reg_needs_delay (mips_gp_register);
+ gpdelay = reg_needs_delay (GOT_REG);
if (expr1.X_add_number == 0 && breg == 0
&& (call || tempreg == PIC_CALL_REG))
{
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
macro_build (&offset_expr, "lui", "t,u", tempreg, lui_reloc_type);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, mips_gp_register);
+ tempreg, tempreg, GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
{
if (breg != 0)
{
/* We're going to put in an addu instruction using
tempreg, so we may as well insert the nop right
now. */
load_delay_nop ();
@@ -5283,21 +5287,21 @@ macro (struct mips_cl_insn *ip)
relax_switch ();
if (gpdelay)
{
/* This is needed because this instruction uses $gp, but
the first instruction on the main stream does not. */
macro_build (NULL, "nop", "");
}
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- local_reloc_type, mips_gp_register);
+ local_reloc_type, GOT_REG);
if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
load_delay_nop ();
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
/* FIXME: If add_number is 0, and there was no base
register, the external symbol case ended with a load,
so if the symbol turns out to not be external, and
the next instruction uses tempreg, an unnecessary nop
@@ -5320,21 +5324,21 @@ macro (struct mips_cl_insn *ip)
}
macro_build_lui (&expr1, AT);
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
AT, AT, BFD_RELOC_LO16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, AT);
}
relax_end ();
}
- else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && HAVE_NEWABI)
{
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
int add_breg_early = 0;
/* This is the large GOT case. If this is a reference to an
external symbol, and there is no constant, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
add $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
@@ -5370,21 +5374,21 @@ macro (struct mips_cl_insn *ip)
offset_expr.X_add_number = 0;
if (expr1.X_add_number == 0 && breg == 0
&& (call || tempreg == PIC_CALL_REG))
{
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
macro_build (&offset_expr, "lui", "t,u", tempreg, lui_reloc_type);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, mips_gp_register);
+ tempreg, tempreg, GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
;
else if (expr1.X_add_number >= -0x8000
&& expr1.X_add_number < 0x8000)
{
macro_build (&expr1, ADDRESS_ADDI_INSN, "t,r,j",
tempreg, tempreg, BFD_RELOC_LO16);
@@ -5415,21 +5419,21 @@ macro (struct mips_cl_insn *ip)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", dreg, dreg, AT);
used_at = 1;
}
else
as_bad (_("PIC code offset overflow (max 32 signed bits)"));
relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_PAGE, GOT_REG);
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
tempreg, BFD_RELOC_MIPS_GOT_OFST);
if (add_breg_early)
{
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
treg, tempreg, breg);
breg = 0;
tempreg = treg;
}
relax_end ();
@@ -5466,61 +5470,64 @@ macro (struct mips_cl_insn *ip)
/* The jal instructions must be handled as macros because when
generating PIC code they expand to multi-instruction
sequences. Normally they are simple instructions. */
case M_JAL_1:
dreg = RA;
/* Fall through. */
case M_JAL_2:
if (mips_pic == NO_PIC)
macro_build (NULL, "jalr", "d,s", dreg, sreg);
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
{
- if (sreg != PIC_CALL_REG)
+ if ((sreg != PIC_CALL_REG) && (mips_pic != QNX_PIC))
as_warn (_("MIPS PIC call to register other than $25"));
macro_build (NULL, "jalr", "d,s", dreg, sreg);
if (! HAVE_NEWABI)
{
- if (mips_cprestore_offset < 0)
+ if (mips_cprestore_offset < 0){
+ if (mips_pic != QNX_PIC)
as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ }
else
{
if (! mips_frame_reg_valid)
{
as_warn (_("No .frame pseudo-op used in PIC code"));
/* Quiet this warning. */
mips_frame_reg_valid = 1;
}
if (! mips_cprestore_valid)
{
+ if (mips_pic != QNX_PIC)
as_warn (_("No .cprestore pseudo-op used in PIC code"));
/* Quiet this warning. */
mips_cprestore_valid = 1;
}
expr1.X_add_number = mips_cprestore_offset;
macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN,
- mips_gp_register,
+ GOT_REG,
mips_frame_reg,
HAVE_64BIT_ADDRESSES);
}
}
}
else
abort ();
return;
case M_JAL_A:
if (mips_pic == NO_PIC)
macro_build (&offset_expr, "jal", "a");
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
{
/* If this is a reference to an external symbol, and we are
using a small GOT, we want
lw $25,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
nop
jalr $ra,$25
nop
lw $gp,cprestore($sp)
The cprestore value is set using the .cprestore
pseudo-op. If we are using a big GOT, we want
@@ -5543,107 +5550,117 @@ macro (struct mips_cl_insn *ip)
sequences above, minus nops, unless the symbol is local,
which enables us to use GOT_PAGE/GOT_OFST (big got) or
GOT_DISP. */
if (HAVE_NEWABI)
{
if (! mips_big_got)
{
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
- mips_gp_register);
+ GOT_REG);
relax_switch ();
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_GOT_DISP,
- mips_gp_register);
+ GOT_REG);
relax_end ();
}
else
{
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, "lui", "t,u", PIC_CALL_REG,
BFD_RELOC_MIPS_CALL_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", PIC_CALL_REG,
- PIC_CALL_REG, mips_gp_register);
+ PIC_CALL_REG, GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_CALL_LO16,
PIC_CALL_REG);
relax_switch ();
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_GOT_PAGE,
- mips_gp_register);
+ GOT_REG);
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
PIC_CALL_REG, PIC_CALL_REG,
BFD_RELOC_MIPS_GOT_OFST);
relax_end ();
}
macro_build_jalr (&offset_expr);
}
else
{
relax_start (offset_expr.X_add_symbol);
if (! mips_big_got)
{
+ if(mips_pic != QNX_PIC)
+ macro_build (&offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
+ ? "lw" : "ld"),
+ "t,o(b)", PIC_CALL_REG,
+ (int) BFD_RELOC_MIPS_CALL16, GOT_REG);
+ else
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_CALL16,
- mips_gp_register);
+ GOT_REG);
load_delay_nop ();
relax_switch ();
}
else
{
int gpdelay;
- gpdelay = reg_needs_delay (mips_gp_register);
+ gpdelay = reg_needs_delay (GOT_REG);
macro_build (&offset_expr, "lui", "t,u", PIC_CALL_REG,
BFD_RELOC_MIPS_CALL_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", PIC_CALL_REG,
- PIC_CALL_REG, mips_gp_register);
+ PIC_CALL_REG, GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_CALL_LO16,
PIC_CALL_REG);
load_delay_nop ();
relax_switch ();
if (gpdelay)
macro_build (NULL, "nop", "");
}
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
PIC_CALL_REG, BFD_RELOC_MIPS_GOT16,
- mips_gp_register);
+ GOT_REG);
load_delay_nop ();
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
PIC_CALL_REG, PIC_CALL_REG, BFD_RELOC_LO16);
relax_end ();
macro_build_jalr (&offset_expr);
- if (mips_cprestore_offset < 0)
+ if (mips_cprestore_offset < 0) {
+ if (mips_pic != QNX_PIC)
as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ }
else
{
if (! mips_frame_reg_valid)
{
as_warn (_("No .frame pseudo-op used in PIC code"));
/* Quiet this warning. */
mips_frame_reg_valid = 1;
}
if (! mips_cprestore_valid)
{
as_warn (_("No .cprestore pseudo-op used in PIC code"));
/* Quiet this warning. */
mips_cprestore_valid = 1;
}
if (mips_opts.noreorder)
macro_build (NULL, "nop", "");
expr1.X_add_number = mips_cprestore_offset;
macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN,
- mips_gp_register,
+ GOT_REG,
mips_frame_reg,
HAVE_64BIT_ADDRESSES);
}
}
}
else
abort ();
return;
@@ -5978,52 +5995,52 @@ macro (struct mips_cl_insn *ip)
&& ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000))
as_bad (_("load/store address overflow (max 32 bits)"));
if (breg == 0)
{
if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
&& ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16,
- mips_gp_register);
+ GOT_REG);
relax_switch ();
used_at = 0;
}
macro_build_lui (&offset_expr, tempreg);
macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_LO16, tempreg);
if (mips_relax.sequence)
relax_end ();
}
else
{
if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
&& ! nopic_need_relax (offset_expr.X_add_symbol, 1))
{
relax_start (offset_expr.X_add_symbol);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, breg, mips_gp_register);
+ tempreg, breg, GOT_REG);
macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_GPREL16, tempreg);
relax_switch ();
}
macro_build_lui (&offset_expr, tempreg);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_LO16, tempreg);
if (mips_relax.sequence)
relax_end ();
}
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! mips_big_got)
{
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* If this is a reference to an external symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
<op> $treg,0($tempreg)
Otherwise we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
@@ -6037,51 +6054,51 @@ macro (struct mips_cl_insn *ip)
If there is a base register, we add it to $tempreg before
the <op>. If there is a constant, we stick it in the
<op> instruction. We don't handle constants larger than
16 bits, because we have no way to load the upper 16 bits
(actually, we could handle them for the subset of cases
in which we are not using $at). */
assert (offset_expr.X_op == O_symbol);
if (HAVE_NEWABI)
{
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_PAGE, GOT_REG);
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_MIPS_GOT_OFST, tempreg);
if (! used_at)
return;
break;
}
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- lw_reloc_type, mips_gp_register);
+ lw_reloc_type, GOT_REG);
load_delay_nop ();
relax_start (offset_expr.X_add_symbol);
relax_switch ();
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
tempreg, BFD_RELOC_LO16);
relax_end ();
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
}
- else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! HAVE_NEWABI)
{
int gpdelay;
/* If this is a reference to an external symbol, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
<op> $treg,0($tempreg)
Otherwise we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
@@ -6093,75 +6110,75 @@ macro (struct mips_cl_insn *ip)
<op> instruction. We don't handle constants larger than
16 bits, because we have no way to load the upper 16 bits
(actually, we could handle them for the subset of cases
in which we are not using $at). */
assert (offset_expr.X_op == O_symbol);
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- gpdelay = reg_needs_delay (mips_gp_register);
+ gpdelay = reg_needs_delay (GOT_REG);
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, "lui", "t,u", tempreg,
BFD_RELOC_MIPS_GOT_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
- mips_gp_register);
+ GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
BFD_RELOC_MIPS_GOT_LO16, tempreg);
relax_switch ();
if (gpdelay)
macro_build (NULL, "nop", "");
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
load_delay_nop ();
macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
tempreg, BFD_RELOC_LO16);
relax_end ();
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
}
- else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && HAVE_NEWABI)
{
/* If this is a reference to an external symbol, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
add $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
<op> $treg,<ofst>($tempreg)
Otherwise, for local symbols, we want:
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
<op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_OFST) */
assert (offset_expr.X_op == O_symbol);
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, "lui", "t,u", tempreg,
BFD_RELOC_MIPS_GOT_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
- mips_gp_register);
+ GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
BFD_RELOC_MIPS_GOT_LO16, tempreg);
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ BFD_RELOC_MIPS_GOT_PAGE, GOT_REG);
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
macro_build (&offset_expr, s, fmt, treg,
BFD_RELOC_MIPS_GOT_OFST, tempreg);
relax_end ();
}
else
abort ();
@@ -6187,21 +6204,21 @@ macro (struct mips_cl_insn *ip)
break;
}
else
{
assert (offset_expr.X_op == O_symbol
&& strcmp (segment_name (S_GET_SEGMENT
(offset_expr.X_add_symbol)),
".lit4") == 0
&& offset_expr.X_add_number == 0);
macro_build (&offset_expr, "lwc1", "T,o(b)", treg,
- BFD_RELOC_MIPS_LITERAL, mips_gp_register);
+ BFD_RELOC_MIPS_LITERAL, GOT_REG);
return;
}
case M_LI_D:
/* Check if we have a constant in IMM_EXPR. If the GPRs are 64 bits
wide, IMM_EXPR is the entire value. Otherwise IMM_EXPR is the high
order 32 bits of the value and the low order 32 bits are either
zero or in OFFSET_EXPR. */
if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
{
@@ -6237,24 +6254,24 @@ macro (struct mips_cl_insn *ip)
}
return;
}
/* We know that sym is in the .rdata section. First we get the
upper 16 bits of the address. */
if (mips_pic == NO_PIC)
{
macro_build_lui (&offset_expr, AT);
}
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
{
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
}
else
abort ();
/* Now we load the register(s). */
if (HAVE_64BIT_GPRS)
macro_build (&offset_expr, "ld", "t,o(b)", treg, BFD_RELOC_LO16, AT);
else
{
macro_build (&offset_expr, "lw", "t,o(b)", treg, BFD_RELOC_LO16, AT);
@@ -6299,33 +6316,33 @@ macro (struct mips_cl_insn *ip)
}
assert (offset_expr.X_op == O_symbol
&& offset_expr.X_add_number == 0);
s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
if (strcmp (s, ".lit8") == 0)
{
if (mips_opts.isa != ISA_MIPS1)
{
macro_build (&offset_expr, "ldc1", "T,o(b)", treg,
- BFD_RELOC_MIPS_LITERAL, mips_gp_register);
+ BFD_RELOC_MIPS_LITERAL, GOT_REG);
return;
}
- breg = mips_gp_register;
+ breg = GOT_REG;
r = BFD_RELOC_MIPS_LITERAL;
goto dob;
}
else
{
assert (strcmp (s, RDATA_SECTION_NAME) == 0);
- if (mips_pic == SVR4_PIC)
+ if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
else
{
/* FIXME: This won't work for a 64 bit address. */
macro_build_lui (&offset_expr, AT);
}
if (mips_opts.isa != ISA_MIPS1)
{
macro_build (&offset_expr, "ldc1", "T,o(b)",
treg, BFD_RELOC_LO16, AT);
@@ -6461,27 +6478,27 @@ macro (struct mips_cl_insn *ip)
lui instruction. If there is a constant, we always use
the last case. */
if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET
|| nopic_need_relax (offset_expr.X_add_symbol, 1))
used_at = 1;
else
{
relax_start (offset_expr.X_add_symbol);
if (breg == 0)
{
- tempreg = mips_gp_register;
+ tempreg = GOT_REG;
used_at = 0;
}
else
{
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, mips_gp_register);
+ AT, breg, GOT_REG);
tempreg = AT;
used_at = 1;
}
/* Itbl support may require additional care here. */
macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_GPREL16, tempreg);
offset_expr.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an
@@ -6523,21 +6540,21 @@ macro (struct mips_cl_insn *ip)
macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
/* FIXME: How do we handle overflow here? */
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
if (mips_relax.sequence)
relax_end ();
}
- else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && ! mips_big_got)
{
/* If this is a reference to an external symbol, we want
lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
<op> $treg,0($at)
<op> $treg+1,4($at)
Otherwise we want
lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
<op> $treg,<sym>($at) (BFD_RELOC_LO16)
@@ -6570,21 +6587,21 @@ macro (struct mips_cl_insn *ip)
relax_switch ();
macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
offset_expr.X_add_number += 4;
macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
relax_end ();
mips_optimize = hold_mips_optimize;
}
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
{
int gpdelay;
/* If this is a reference to an external symbol, we want
lui $at,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $at,$at,$gp
lw $at,<sym>($at) (BFD_RELOC_MIPS_GOT_LO16)
nop
<op> $treg,0($at)
<op> $treg+1,4($at)
@@ -6595,26 +6612,26 @@ macro (struct mips_cl_insn *ip)
<op> $treg+1,<sym>+4($at) (BFD_RELOC_LO16)
If there is a base register we add it to $at before the
lwc1 instructions. If there is a constant we include it
in the lwc1 instructions. */
used_at = 1;
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
if (expr1.X_add_number < -0x8000
|| expr1.X_add_number >= 0x8000 - 4)
as_bad (_("PIC code offset overflow (max 16 signed bits)"));
- gpdelay = reg_needs_delay (mips_gp_register);
+ gpdelay = reg_needs_delay (GOT_REG);
relax_start (offset_expr.X_add_symbol);
macro_build (&offset_expr, "lui", "t,u",
AT, BFD_RELOC_MIPS_GOT_HI16);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, AT, mips_gp_register);
+ AT, AT, GOT_REG);
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
AT, BFD_RELOC_MIPS_GOT_LO16, AT);
load_delay_nop ();
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
macro_build (&expr1, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
expr1.X_add_number += 4;
@@ -6626,21 +6643,21 @@ macro (struct mips_cl_insn *ip)
macro_build (&expr1, s, fmt, coproc ? treg : treg + 1,
BFD_RELOC_LO16, AT);
mips_optimize = hold_mips_optimize;
expr1.X_add_number -= 4;
relax_switch ();
offset_expr.X_add_number = expr1.X_add_number;
if (gpdelay)
macro_build (NULL, "nop", "");
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
+ BFD_RELOC_MIPS_GOT16, GOT_REG);
load_delay_nop ();
if (breg != 0)
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
BFD_RELOC_LO16, AT);
offset_expr.X_add_number += 4;
/* Set mips_optimize to 2 to avoid inserting an undesired
nop. */
@@ -10119,20 +10136,22 @@ struct option md_longopts[] =
#define OPTION_64 (OPTION_ELF_BASE + 6)
{"64", no_argument, NULL, OPTION_64},
#define OPTION_MDEBUG (OPTION_ELF_BASE + 7)
{"mdebug", no_argument, NULL, OPTION_MDEBUG},
#define OPTION_NO_MDEBUG (OPTION_ELF_BASE + 8)
{"no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG},
#define OPTION_PDR (OPTION_ELF_BASE + 9)
{"mpdr", no_argument, NULL, OPTION_PDR},
#define OPTION_NO_PDR (OPTION_ELF_BASE + 10)
{"mno-pdr", no_argument, NULL, OPTION_NO_PDR},
+#define OPTION_QNX_PIC (OPTION_ELF_BASE + 11)
+ {"qnx_pic", no_argument, NULL, OPTION_QNX_PIC},
#endif /* OBJ_ELF */
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
/* Set STRING_PTR (either &mips_arch_string or &mips_tune_string) to
NEW_VALUE. Warn if another value was already specified. Note:
we have to defer parsing the -march and -mtune arguments in order
to handle 'from-abi' correctly, since the ABI might be specified
@@ -10460,20 +10479,36 @@ md_parse_option (int c, char *arg)
mips_flag_mdebug = FALSE;
break;
case OPTION_PDR:
mips_flag_pdr = TRUE;
break;
case OPTION_NO_PDR:
mips_flag_pdr = FALSE;
break;
+
+ case OPTION_QNX_PIC:
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad ("-qnx_pic is supported only for ELF format");
+ return 0;
+ }
+ mips_pic = QNX_PIC;
+ if (g_switch_seen && g_switch_value != 0)
+ {
+ as_bad ("-G may not be used with QNX PIC code");
+ return 0;
+ }
+ g_switch_value = 0;
+ break;
+ #endif /* OBJ_ELF */
default:
return 0;
}
return 1;
}

/* Set up globals to generate code for the ISA or processor
@@ -10864,21 +10899,21 @@ mips_validate_fix (struct fix *fixP, ase
else if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Cannot branch to symbol in another section."));
fixP->fx_done = 1;
}
else if (S_IS_EXTERNAL (fixP->fx_addsy))
{
symbolS *sym = fixP->fx_addsy;
- if (mips_pic == SVR4_PIC)
+ if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
as_warn_where (fixP->fx_file, fixP->fx_line,
_("Pretending global symbol used as branch target is local."));
fixP->fx_addsy = symbol_create (S_GET_NAME (sym),
S_GET_SEGMENT (sym),
S_GET_VALUE (sym),
symbol_get_frag (sym));
copy_symbol_attributes (fixP->fx_addsy, sym);
S_CLEAR_EXTERNAL (fixP->fx_addsy);
assert (symbol_resolved_p (sym));
@@ -11758,62 +11793,150 @@ s_abicalls (int ignore ATTRIBUTE_UNUSED)
mips_abicalls = TRUE;
if (g_switch_seen && g_switch_value != 0)
as_warn (_("-G may not be used with SVR4 PIC code"));
g_switch_value = 0;
bfd_set_gp_size (stdoutput, 0);
demand_empty_rest_of_line ();
}
+/* This handles the .qnxpiccalls pseudo-op.i */
+
+static void
+s_qnxpiccalls (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ mips_pic = QNX_PIC;
+ if (g_switch_seen && g_switch_value != 0)
+ as_warn ("-G may not be used with QNX PIC code");
+ g_switch_value = 0;
+ bfd_set_gp_size (stdoutput, 0);
+ demand_empty_rest_of_line ();
+}
+
+/* Allows us to turn off PIC code gen, in case that is needed */
+
+static void
+s_noqnxpiccalls (ignore)
+ int ignore ATTRIBUTE_UNUSED;
+{
+ mips_pic = NO_PIC;
+ demand_empty_rest_of_line ();
+}
+
+
/* Handle the .cpload pseudo-op. This is used when generating SVR4
PIC code. It sets the $gp register for the function based on the
function address, which is in the register named in the argument.
This uses a relocation against _gp_disp, which is handled specially
by the linker. The result is:
lui $gp,%hi(_gp_disp)
addiu $gp,$gp,%lo(_gp_disp)
addu $gp,$gp,.cpload argument
- The .cpload argument is normally $25 == $t9. */
+ The .cpload argument is normally $25 == $t9. +
+ In the case of QNX pic code, we always compute the full address
+ of the GOT, therefore we do:
+ bltzal 0, 0f
+ nop
+ 0: lui $23, %hi(_gp_disp)
+ addiu $23, $23, %lo(_gp_disp)
+ addu $23, $23, $31
+ One possible optimization would be to move the opcode
+ right before the bltzal into the nop slot. */
static void
s_cpload (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cpload is ignored. */
- if (mips_pic != SVR4_PIC || HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || HAVE_NEWABI)
{
s_ignore (0);
return;
}
/* .cpload should be in a .set noreorder section. */
- if (mips_opts.noreorder == 0)
+ if ((mips_opts.noreorder == 0) && (mips_pic != QNX_PIC))
as_warn (_(".cpload not in noreorder section"));
ex.X_op = O_symbol;
ex.X_add_symbol = symbol_find_or_make ("_gp_disp");
ex.X_op_symbol = NULL;
ex.X_add_number = 0;
/* In ELF, this symbol is implicitly an STT_OBJECT symbol. */
symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
+ if (mips_pic == QNX_PIC) {
+ expressionS ep;
+ /* In our case, we do a bltzal first to get the current IP, and
+ * then add the offset to the got... Thus, we always do "cpload $31"
+ */
+ ep.X_op = O_constant;
+ ep.X_add_number = 4;
+ tc_get_register(0); // Flush any arg to cpload...
+
+ /* See if we can swap the bltzal with the previous insn and save
+ * the nop...
+ * For simplicity, we only check that the insn is a move or sw,
+ * which are really the only two we should encounter.
+ * If it is anything else, we don't swap for now.
+ */
+ if(0 && (mips_optimize > 1)
+ && prev_insn_valid
+ && (mips_opts.isa > 1)
+ && !(mips_opts.noreorder)
+ && (((prev_insn.insn_opcode & 0xfc1f07ff) == 0x00000021)
+ || ((prev_insn.insn_opcode & 0xfc000000) == 0xac000000)))
+ {
+ char *prev_f;
+ char temp[4];
+
+ prev_f = prev_insn_frag->fr_literal + prev_insn_where;
+ memcpy (temp, prev_f, 4);
+ *(unsigned long *)(prev_f) = 0x04100001;
+ macro_build (&ep,
+ "bltzal", "s,p", 0);
+
+ prev_f = prev_insn_frag->fr_literal + prev_insn_where;
+ memcpy (prev_f, temp, 4);
+ mips_opts.noreorder ++;
+ }
+ else
+ { /* We need a NOP... */
+ mips_opts.noreorder ++;
+ macro_build (&ep,
+ "bltzal", "s,p", 0);
+ macro_build ((expressionS *) NULL, "nop", "");
+ }
+ macro_build_lui (&ex, 23);
+ macro_build (&ex, "addiu", "t,r,j", 23, 23,
+ (int) BFD_RELOC_LO16);
+ mips_opts.noreorder --;
+
+ macro_build ((expressionS *) NULL, "addu", "d,v,t",
+ 23, 23, RA);
+ } else
+ {
+
macro_start ();
- macro_build_lui (&ex, mips_gp_register);
- macro_build (&ex, "addiu", "t,r,j", mips_gp_register,
- mips_gp_register, BFD_RELOC_LO16);
- macro_build (NULL, "addu", "d,v,t", mips_gp_register,
- mips_gp_register, tc_get_register (0));
+ macro_build_lui (&ex, GOT_REG);
+ macro_build (&ex, "addiu", "t,r,j", GOT_REG,
+ GOT_REG, BFD_RELOC_LO16);
+ macro_build (NULL, "addu", "d,v,t", GOT_REG,
+ GOT_REG, tc_get_register (0));
macro_end ();
+}
demand_empty_rest_of_line ();
}
/* Handle the .cpsetup pseudo-op defined for NewABI PIC code. The syntax is:
.cpsetup $reg1, offset|$reg2, label
If offset is given, this results in:
sd $gp, offset($sp)
lui $gp, %hi(%neg(%gp_rel(label)))
@@ -11829,21 +11952,21 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
static void
s_cpsetup (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex_off;
expressionS ex_sym;
int reg1;
char *f;
/* If we are not generating SVR4 PIC code, .cpsetup is ignored.
We also need NewABI support. */
- if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC)|| ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
reg1 = tc_get_register (0);
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("missing argument separator ',' for .cpsetup"));
@@ -11874,147 +11997,147 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
expression (&ex_sym);
macro_start ();
if (mips_cpreturn_register == -1)
{
ex_off.X_op = O_constant;
ex_off.X_add_symbol = NULL;
ex_off.X_op_symbol = NULL;
ex_off.X_add_number = mips_cpreturn_offset;
- macro_build (&ex_off, "sd", "t,o(b)", mips_gp_register,
+ macro_build (&ex_off, "sd", "t,o(b)", GOT_REG,
BFD_RELOC_LO16, SP);
}
else
macro_build (NULL, "daddu", "d,v,t", mips_cpreturn_register,
- mips_gp_register, 0);
+ GOT_REG, 0);
/* Ensure there's room for the next two instructions, so that `f'
doesn't end up with an address in the wrong frag. */
frag_grow (8);
f = frag_more (0);
- macro_build (&ex_sym, "lui", "t,u", mips_gp_register, BFD_RELOC_GPREL16);
+ macro_build (&ex_sym, "lui", "t,u", GOT_REG, BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
4, NULL, 0, 0, BFD_RELOC_HI16_S);
f = frag_more (0);
- macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register,
- mips_gp_register, BFD_RELOC_GPREL16);
+ macro_build (&ex_sym, "addiu", "t,r,j", GOT_REG,
+ GOT_REG, BFD_RELOC_GPREL16);
fix_new (frag_now, f - frag_now->fr_literal,
8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, f - frag_now->fr_literal,
4, NULL, 0, 0, BFD_RELOC_LO16);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
- mips_gp_register, reg1);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", GOT_REG,
+ GOT_REG, reg1);
macro_end ();
demand_empty_rest_of_line ();
}
static void
s_cplocal (int ignore ATTRIBUTE_UNUSED)
{
/* If we are not generating SVR4 PIC code, or if this is not NewABI code,
.cplocal is ignored. */
- if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
mips_gp_register = tc_get_register (0);
demand_empty_rest_of_line ();
}
/* Handle the .cprestore pseudo-op. This stores $gp into a given
offset from $sp. The offset is remembered, and after making a PIC
call $gp is restored from that location. */
static void
s_cprestore (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cprestore is ignored. */
- if (mips_pic != SVR4_PIC || HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || HAVE_NEWABI)
{
s_ignore (0);
return;
}
mips_cprestore_offset = get_absolute_expression ();
mips_cprestore_valid = 1;
ex.X_op = O_constant;
ex.X_add_symbol = NULL;
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cprestore_offset;
macro_start ();
- macro_build_ldst_constoffset (&ex, ADDRESS_STORE_INSN, mips_gp_register,
+ macro_build_ldst_constoffset (&ex, ADDRESS_STORE_INSN, GOT_REG,
SP, HAVE_64BIT_ADDRESSES);
macro_end ();
demand_empty_rest_of_line ();
}
/* Handle the .cpreturn pseudo-op defined for NewABI PIC code. If an offset
was given in the preceding .cpsetup, it results in:
ld $gp, offset($sp)
If a register $reg2 was given there, it results in:
daddu $gp, $reg2, $0
*/
static void
s_cpreturn (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
/* If we are not generating SVR4 PIC code, .cpreturn is ignored.
We also need NewABI support. */
- if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
macro_start ();
if (mips_cpreturn_register == -1)
{
ex.X_op = O_constant;
ex.X_add_symbol = NULL;
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cpreturn_offset;
- macro_build (&ex, "ld", "t,o(b)", mips_gp_register, BFD_RELOC_LO16, SP);
+ macro_build (&ex, "ld", "t,o(b)", GOT_REG, BFD_RELOC_LO16, SP);
}
else
- macro_build (NULL, "daddu", "d,v,t", mips_gp_register,
+ macro_build (NULL, "daddu", "d,v,t", GOT_REG,
mips_cpreturn_register, 0);
macro_end ();
demand_empty_rest_of_line ();
}
/* Handle the .gpvalue pseudo-op. This is used when generating NewABI PIC
code. It sets the offset to use in gp_rel relocations. */
static void
s_gpvalue (int ignore ATTRIBUTE_UNUSED)
{
/* If we are not generating SVR4 PIC code, .gpvalue is ignored.
We also need NewABI support. */
- if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
+ if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
mips_gprel_offset = get_absolute_expression ();
demand_empty_rest_of_line ();
}
@@ -12022,21 +12145,21 @@ s_gpvalue (int ignore ATTRIBUTE_UNUSED)
code. It generates a 32 bit GP relative reloc. */
static void
s_gpword (int ignore ATTRIBUTE_UNUSED)
{
symbolS *label;
expressionS ex;
char *p;
/* When not generating PIC code, this is treated as .word. */
- if (mips_pic != SVR4_PIC)
+ if (mips_pic != SVR4_PIC && mips_pic != QNX_PIC)
{
s_cons (2);
return;
}
label = insn_labels != NULL ? insn_labels->label : NULL;
mips_emit_delays (TRUE);
if (auto_align)
mips_align (2, 0, label);
mips_clear_insn_labels ();
@@ -12058,21 +12181,21 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
}
static void
s_gpdword (int ignore ATTRIBUTE_UNUSED)
{
symbolS *label;
expressionS ex;
char *p;
/* When not generating PIC code, this is treated as .dword. */
- if (mips_pic != SVR4_PIC)
+ if (mips_pic != SVR4_PIC && mips_pic != QNX_PIC)
{
s_cons (3);
return;
}
label = insn_labels != NULL ? insn_labels->label : NULL;
mips_emit_delays (TRUE);
if (auto_align)
mips_align (3, 0, label);
mips_clear_insn_labels ();
@@ -12102,30 +12225,30 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
/* Handle the .cpadd pseudo-op. This is used when dealing with switch
tables in SVR4 PIC code. */
static void
s_cpadd (int ignore ATTRIBUTE_UNUSED)
{
int reg;
/* This is ignored when not generating SVR4 PIC code. */
- if (mips_pic != SVR4_PIC)
+ if (mips_pic != SVR4_PIC && mips_pic != QNX_PIC)
{
s_ignore (0);
return;
}
/* Add $gp to the register named as an argument. */
macro_start ();
reg = tc_get_register (0);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", reg, reg, mips_gp_register);
+ macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", reg, reg, GOT_REG);
macro_end ();
demand_empty_rest_of_line ();
}
/* Handle the .insn pseudo-op. This marks instruction labels in
mips16 mode. This permits the linker to handle them specially,
such as generating jalx instructions when needed. We also make
them odd for the duration of the assembly, in order to generate the
right sort of code. We will make them even in the adjust_symtab
@@ -12697,34 +12820,33 @@ relaxed_branch_length (fragS *fragp, ase
encoded in the subtype information. For the mips16, we have to
decide whether we are using an extended opcode or not. */
int
md_estimate_size_before_relax (fragS *fragp, asection *segtype)
{
int change;
if (RELAX_BRANCH_P (fragp->fr_subtype))
{
-
fragp->fr_var = relaxed_branch_length (fragp, segtype, FALSE);
return fragp->fr_var;
}
if (RELAX_MIPS16_P (fragp->fr_subtype))
/* We don't want to modify the EXTENDED bit here; it might get us
into infinite loops. We change it only in mips_relax_frag(). */
return (RELAX_MIPS16_EXTENDED (fragp->fr_subtype) ? 4 : 2);
if (mips_pic == NO_PIC)
change = nopic_need_relax (fragp->fr_symbol, 0);
- else if (mips_pic == SVR4_PIC)
+ else if (mips_pic == SVR4_PIC || mips_pic == QNX_PIC)
change = pic_need_relax (fragp->fr_symbol, segtype);
else
abort ();
if (change)
{
fragp->fr_subtype |= RELAX_USE_SECOND;
return -RELAX_FIRST (fragp->fr_subtype);
}
else
@@ -12742,20 +12864,28 @@ mips_fix_adjustable (fixS *fixp)
if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
return 0;
if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0;
if (fixp->fx_addsy == NULL)
return 1;
+ if ((mips_pic == QNX_PIC) &&
+ (fixp->fx_r_type == BFD_RELOC_MIPS_GOT16 || fixp->fx_r_type == BFD_RELOC_32))
+ {
+ symbolS * sym = fixp->fx_addsy;
+ if (S_IS_EXTERN(sym) || S_IS_WEAK(sym)) return 0;
+ }
+ + /* If symbol SYM is in a mergeable section, relocations of the form
SYM + 0 can usually be made section-relative. The mergeable data
is then identified by the section offset rather than by the symbol.
However, if we're generating REL LO16 relocations, the offset is split
between the LO16 and parterning high part relocation. The linker will
need to recalculate the complete offset in order to correctly identify
the merge data.
The linker has traditionally not looked for the parterning high part
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.35
diff -w -u -1 -0 -p -r1.35 tc-mips.h
--- gas/config/tc-mips.h 29 Apr 2004 05:14:22 -0000 1.35
+++ gas/config/tc-mips.h 17 Aug 2004 17:16:24 -0000
@@ -68,24 +68,30 @@ extern const char *mips_target_format (v
/* MIPS PIC level. */
enum mips_pic_level
{
/* Do not generate PIC code. */
NO_PIC,
/* Generate PIC code as in the SVR4 MIPS ABI. */
SVR4_PIC,
+
+ /* Generate QNX PIC code. */
+ QNX_PIC,
};
extern enum mips_pic_level mips_pic;
+/* Macro to define the GOT pointer register */
+#define GOT_REG ((mips_pic == SVR4_PIC) ? mips_gp_register : 23)
+
struct mips_cl_insn
{
unsigned long insn_opcode;
const struct mips_opcode *insn_mo;
/* The next two fields are used when generating mips16 code. */
bfd_boolean use_extend;
unsigned short extend;
};
extern int tc_get_register (int frame);
Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.45
diff -w -u -1 -0 -p -r1.45 bfdlink.h
--- include/bfdlink.h 13 Aug 2004 03:16:01 -0000 1.45
+++ include/bfdlink.h 17 Aug 2004 17:16:25 -0000
@@ -390,20 +390,23 @@ struct bfd_link_info
unsigned int spare_dynamic_tags;
/* May be used to set DT_FLAGS for ELF. */
bfd_vma flags;
/* May be used to set DT_FLAGS_1 for ELF. */
bfd_vma flags_1;
/* Start and end of RELRO region. */
bfd_vma relro_start, relro_end;
+
+ /* Warn if adding a DT_TEXTREL to a shared object. */
+ bfd_boolean warn_shared_textrel;
};
/* This structures holds a set of callback functions. These are
called by the BFD linker routines. The first argument to each
callback function is the bfd_link_info structure being used. Each
function returns a boolean value. If the function returns FALSE,
then the BFD function which called it will return with a failure
indication. */
struct bfd_link_callbacks
Index: include/elf/mips.h
===================================================================
RCS file: /cvs/src/src/include/elf/mips.h,v
retrieving revision 1.23
diff -w -u -1 -0 -p -r1.23 mips.h
--- include/elf/mips.h 14 Jun 2004 18:25:10 -0000 1.23
+++ include/elf/mips.h 17 Aug 2004 17:16:25 -0000
@@ -69,20 +69,22 @@ START_RELOC_NUMBERS (elf_mips_reloc_type
RELOC_NUMBER (R_MIPS_SCN_DISP, 32)
RELOC_NUMBER (R_MIPS_REL16, 33)
RELOC_NUMBER (R_MIPS_ADD_IMMEDIATE, 34)
RELOC_NUMBER (R_MIPS_PJUMP, 35)
RELOC_NUMBER (R_MIPS_RELGOT, 36)
RELOC_NUMBER (R_MIPS_JALR, 37)
RELOC_NUMBER (R_MIPS_max, 38)
/* These relocs are used for the mips16. */
RELOC_NUMBER (R_MIPS16_26, 100)
RELOC_NUMBER (R_MIPS16_GPREL, 101)
+ /* And this is used with QNX pic for data copy relocs */
+ RELOC_NUMBER (R_MIPS_QNX_COPY, 126)
/* This was a GNU extension used by embedded-PIC. It was co-opted by
mips-linux for exception-handling data. It is no longer used, but
should continue to be supported by the linker for backward
compatibility. (GCC stopped using it in May, 2004.) */
RELOC_NUMBER (R_MIPS_PC32, 248)
/* FIXME: this relocation is used internally by gas. */
RELOC_NUMBER (R_MIPS_GNU_REL16_S2, 250)
/* These are GNU extensions to enable C++ vtable garbage collection. */
RELOC_NUMBER (R_MIPS_GNU_VTINHERIT, 253)
RELOC_NUMBER (R_MIPS_GNU_VTENTRY, 254)
Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.157
diff -w -u -1 -0 -p -r1.157 Makefile.am
--- ld/Makefile.am 26 Jul 2004 12:29:02 -0000 1.157
+++ ld/Makefile.am 17 Aug 2004 17:16:25 -0000
@@ -145,35 +145,37 @@ ALL_EMULATIONS = \
edelta68.o \
eelf32_dlx.o \
eebmon29k.o \
eelf32_i960.o \
eelf32_i860.o \
eelf32_sparc.o \
eelf32b4300.o \
eelf32cr16c.o \
eelf32bmip.o \
eelf32bmipn32.o \
+ eelf32bmipsnto.o \
eelf32btsmip.o \
eelf32crx.o \
eelf32btsmipn32.o \
eelf32ltsmip.o \
eelf32ltsmipn32.o \
eelf32ebmip.o \
eelf32elmip.o \
eelf32fr30.o \
eelf32frv.o \
eelf32i370.o \
eelf32ip2k.o \
eelf32iq2000.o \
eelf32iq10.o \
eelf32l4300.o \
eelf32lmip.o \
+ eelf32lmipnto.o \
eelf32lppc.o \
eelf32lppcnto.o \
eelf32lppcsim.o \
eelf32mcore.o \
eelf32mipswindiss.o \
eelf32openrisc.o \
eelf32ppc.o \
eelf32ppc_fbsd.o \
eelf32ppclinux.o \
eelf32ppcnto.o \
@@ -641,20 +643,26 @@ eelf32b4300.c: $(srcdir)/emulparams/elf3
$(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32b4300 "$(tdir_elf32b4300)"
eelf32cr16c.c: $(srcdir)/emulparams/elf32cr16c.sh \
$(srcdir)/emultempl/elf32.em \
$(srcdir)/scripttempl/elf32cr16c.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32cr16c "$(tdir_elf32cr16c)"
eelf32bmip.c: $(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bmip "$(tdir_elf32bmip)"
+eelf32bmipnto.c: $(srcdir)/emulparams/elf32bmipnto.sh \
+ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} elf32bmipnto "$(tdir_elf32bmipnto)"
+eelf32lmipnto.c: $(srcdir)/emulparams/elf32lmipnto.sh \
+ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} elf32lmipnto "$(tdir_elf32lmipnto)"
eelf32bsmip.c: $(srcdir)/emulparams/elf32bsmip.sh \
$(srcdir)/emulparams/elf32bmip.sh $(srcdir)/emultempl/irix.em \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bsmip "$(tdir_elf32bsmip)"
eelf32btsmip.c: $(srcdir)/emulparams/elf32btsmip.sh \
$(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32btsmip "$(tdir_elf32btsmip)"
eelf32crx.c: $(srcdir)/emulparams/elf32crx.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/crxelf.em \
Index: ld/Makefile.in
===================================================================
RCS file: /cvs/src/src/ld/Makefile.in,v
retrieving revision 1.169
diff -w -u -1 -0 -p -r1.169 Makefile.in
--- ld/Makefile.in 26 Jul 2004 12:29:02 -0000 1.169
+++ ld/Makefile.in 17 Aug 2004 17:16:25 -0000
@@ -259,35 +259,37 @@ ALL_EMULATIONS = \
edelta68.o \
eelf32_dlx.o \
eebmon29k.o \
eelf32_i960.o \
eelf32_i860.o \
eelf32_sparc.o \
eelf32b4300.o \
eelf32cr16c.o \
eelf32bmip.o \
eelf32bmipn32.o \
+ eelf32bmipnto.o \
eelf32btsmip.o \
eelf32crx.o \
eelf32btsmipn32.o \
eelf32ltsmip.o \
eelf32ltsmipn32.o \
eelf32ebmip.o \
eelf32elmip.o \
eelf32fr30.o \
eelf32frv.o \
eelf32i370.o \
eelf32ip2k.o \
eelf32iq2000.o \
eelf32iq10.o \
eelf32l4300.o \
eelf32lmip.o \
+ eelf32lmipnto.o \
eelf32lppc.o \
eelf32lppcnto.o \
eelf32lppcsim.o \
eelf32mcore.o \
eelf32mipswindiss.o \
eelf32openrisc.o \
eelf32ppc.o \
eelf32ppc_fbsd.o \
eelf32ppclinux.o \
eelf32ppcnto.o \
@@ -1367,20 +1369,26 @@ eelf32b4300.c: $(srcdir)/emulparams/elf3
$(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32b4300 "$(tdir_elf32b4300)"
eelf32cr16c.c: $(srcdir)/emulparams/elf32cr16c.sh \
$(srcdir)/emultempl/elf32.em \
$(srcdir)/scripttempl/elf32cr16c.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32cr16c "$(tdir_elf32cr16c)"
eelf32bmip.c: $(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bmip "$(tdir_elf32bmip)"
+eelf32bmipnto.c: $(srcdir)/emulparams/elf32bmipnto.sh \
+ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} elf32bmipnto "$(tdir_elf32bmipnto)"
+eelf32lmipnto.c: $(srcdir)/emulparams/elf32lmipnto.sh \
+ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} elf32lmipnto "$(tdir_elf32lmipnto)"
eelf32bsmip.c: $(srcdir)/emulparams/elf32bsmip.sh \
$(srcdir)/emulparams/elf32bmip.sh $(srcdir)/emultempl/irix.em \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bsmip "$(tdir_elf32bsmip)"
eelf32btsmip.c: $(srcdir)/emulparams/elf32btsmip.sh \
$(srcdir)/emulparams/elf32bmip.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32btsmip "$(tdir_elf32btsmip)"
eelf32crx.c: $(srcdir)/emulparams/elf32crx.sh \
$(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/crxelf.em \
Index: ld/configure.tgt
===================================================================
RCS file: /cvs/src/src/ld/configure.tgt,v
retrieving revision 1.153
diff -w -u -1 -0 -p -r1.153 configure.tgt
--- ld/configure.tgt 26 Jul 2004 12:29:02 -0000 1.153
+++ ld/configure.tgt 17 Aug 2004 17:16:25 -0000
@@ -421,20 +421,23 @@ mips*-*-netbsd*) targ_emul=elf32bmip
;;
mips*-*-bsd*) targ_emul=mipsbig ;;
mips*vr4300el-*-elf*) targ_emul=elf32l4300 ;;
mips*vr4300-*-elf*) targ_emul=elf32b4300 ;;
mips*vr4100el-*-elf*) targ_emul=elf32l4300 ;;
mips*vr4100-*-elf*) targ_emul=elf32b4300 ;;
mips*vr5000el-*-elf*) targ_emul=elf32l4300 ;;
mips*vr5000-*-elf*) targ_emul=elf32b4300 ;;
mips*el-*-elf*) targ_emul=elf32elmip ;;
mips*-*-elf*) targ_emul=elf32ebmip ;;
+mips*-*-nto*) targ_emul=elf32lmipnto
+ targ_extra_emuls="elf32bmipnto"
+ ;;
mips*el-*-rtems*) targ_emul=elf32elmip ;;
mips*-*-rtems*) targ_emul=elf32ebmip ;;
mips*el-*-vxworks*) targ_emul=elf32elmip ;;
mips*-*-vxworks*) targ_emul=elf32ebmip
targ_extra_emuls="elf32elmip" ;;
mips*-*-windiss) targ_emul=elf32mipswindiss ;;
mips64*el-*-linux-gnu*) targ_emul=elf32ltsmipn32
targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
;;
mips64*-*-linux-gnu*) targ_emul=elf32btsmipn32
Index: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.76
diff -w -u -1 -0 -p -r1.76 lexsup.c
--- ld/lexsup.c 19 Jul 2004 16:40:52 -0000 1.76
+++ ld/lexsup.c 17 Aug 2004 17:16:26 -0000
@@ -139,21 +139,22 @@ enum option_values
OPTION_NOSTDLIB,
OPTION_NO_OMAGIC,
OPTION_STRIP_DISCARDED,
OPTION_NO_STRIP_DISCARDED,
OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH,
OPTION_PIE,
OPTION_UNRESOLVED_SYMBOLS,
OPTION_WARN_UNRESOLVED_SYMBOLS,
OPTION_ERROR_UNRESOLVED_SYMBOLS,
- OPTION_REDUCE_MEMORY_OVERHEADS
+ OPTION_REDUCE_MEMORY_OVERHEADS,
+ OPTION_WARN_SHARED_TEXTREL
};
/* The long options. This structure is used for both the option
parsing and the help text. */
struct ld_option
{
/* The long option information. */
struct option opt;
/* The short option with the same meaning ('\0' if none). */
@@ -489,20 +490,23 @@ static const struct ld_option ld_options
"\t\t\t\tfollowing dynamic libs"), TWO_DASHES },
{ {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_NEEDED},
'\0', NULL, N_("Do not set DT_NEEDED tags for DT_NEEDED entries\n"
"\t\t\t\tin following dynamic libs"), TWO_DASHES },
{ {"as-needed", no_argument, NULL, OPTION_AS_NEEDED},
'\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"),
TWO_DASHES },
{ {"no-as-needed", no_argument, NULL, OPTION_NO_AS_NEEDED},
'\0', NULL, N_("Always set DT_NEEDED for following dynamic libs"),
TWO_DASHES },
+ { {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_SHARED_TEXTREL},
+ '\0', NULL, N_("Warn if shared object has DT_TEXTREL"),
+ TWO_DASHES },
{ {"wrap", required_argument, NULL, OPTION_WRAP},
'\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
};
#define OPTION_COUNT ARRAY_SIZE (ld_options)
void
parse_args (unsigned argc, char **argv)
{
unsigned i;
@@ -1209,20 +1213,23 @@ parse_args (unsigned argc, char **argv)
break;
case OPTION_NO_ADD_NEEDED:
add_needed = FALSE;
break;
case OPTION_AS_NEEDED:
as_needed = TRUE;
break;
case OPTION_NO_AS_NEEDED:
as_needed = FALSE;
break;
+ case OPTION_WARN_SHARED_TEXREL:
+ link_info.warn_shared_textrel = true;
+ break;
case OPTION_WRAP:
add_wrap (optarg);
break;
case OPTION_DISCARD_NONE:
link_info.discard = discard_none;
break;
case 'X':
link_info.discard = discard_l;
break;
case 'x':



------------------------------------------------------------------------


SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-bigmips"
BIG_OUTPUT_FORMAT="elf32-bigmips"
LITTLE_OUTPUT_FORMAT="elf32-littlemips"
TEXT_START_ADDR=0x08020000
DATA_ADDR="ALIGN (0x1000) + (. & (${MAXPAGESIZE} - 1))"
MAXPAGESIZE=0x1000
NONPAGED_TEXT_START_ADDR=0x08020000
TEXT_DYNAMIC=
INITIAL_READONLY_SECTIONS="
  .reginfo      ${RELOCATING-0} : { *(.reginfo) }
"
OTHER_TEXT_SECTIONS='*(.mips16.fn.*) *(.mips16.call.*)'
OTHER_GOT_SYMBOLS='
  _gp = ALIGN(16) + 0x7ff0;
'
OTHER_SDATA_SECTIONS="
  .lit8         ${RELOCATING-0} : { *(.lit8) }
  .lit4         ${RELOCATING-0} : { *(.lit4) }
"
TEXT_START_SYMBOLS='_btext = . ;'
DATA_START_SYMBOLS='_bdata = . ;'
OTHER_BSS_SYMBOLS='_fbss = .;'
OTHER_SECTIONS='
  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
'
STRICT_DATA_ALIGN=yes
ARCH=mips
MACHINE=
TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes


------------------------------------------------------------------------


. ${srcdir}/emulparams/elf32bmipnto.sh
OUTPUT_FORMAT="elf32-littlemips"
BIG_OUTPUT_FORMAT="elf32-bigmips"
LITTLE_OUTPUT_FORMAT="elf32-littlemips"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]