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]

I need help getting QNX MIPS support working


I'm once again (I was sidetracked for a LONG time) working on adding QNX
MIPS support to the binutils.  I'm no binutils expert by any means so I'm
relegated to doing this by attempting to move our changes to the 2.12.1
binutils into the current HEAD branch.  As I'm sure you can imagine it's not
a smooth transition.  I'm at the point now where I'm fairly certain
everything works but dynamic linking.  The problem that I'm having is that
no information is being added to the .got section.  I've attached the patch,
as it is (contents of 3 new files at the end).

I know the problem revolves around this code somehow but I'm basically
taking shots in the dark to figure out how.

(bfd/elfxx-mips.c)
+   /* This will make sure that the dynamic object is put into the GOT */
+   if ( h->got.offset == MINUS_ONE )
+   {
+         h->got.offset = 1;
+   }
+

Can someone spare the time to assist me in fixing and cleaning up this
patch?


Index: ltconfig
===================================================================
RCS file: /cvs/src/src/ltconfig,v
retrieving revision 1.20
diff -c -3 -p -r1.20 ltconfig
*** ltconfig	4 Oct 2003 04:54:47 -0000	1.20
--- ltconfig	6 Nov 2003 22:38:08 -0000
*************** sysv4*MP*)
*** 1385,1390 ****
--- 1385,1401 ----
    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
    ;;
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.249
diff -c -3 -p -r1.249 bfd-in2.h
*** bfd/bfd-in2.h	4 Nov 2003 10:41:50 -0000	1.249
--- bfd/bfd-in2.h	6 Nov 2003 22:38:08 -0000
*************** to compensate for the borrow when the lo
*** 2343,2348 ****
--- 2343,2349 ----
    BFD_RELOC_MIPS_REL16,
    BFD_RELOC_MIPS_RELGOT,
    BFD_RELOC_MIPS_JALR,
+   BFD_RELOC_MIPS_QNX_COPY,
  
  
  /* Fujitsu Frv Relocations.  */
Index: bfd/config.bfd
===================================================================
RCS file: /cvs/src/src/bfd/config.bfd,v
retrieving revision 1.148
diff -c -3 -p -r1.148 config.bfd
*** bfd/config.bfd	30 Oct 2003 09:05:14 -0000	1.148
--- bfd/config.bfd	6 Nov 2003 22:38:09 -0000
*************** case "${targ}" in
*** 170,175 ****
--- 170,176 ----
    arm-*-nto* | nto*arm*)
      targ_defvec=bfd_elf32_littlearm_vec
      targ_selvecs=bfd_elf32_bigarm_vec
+     targ_cflags=-D__QNXTARGET__
      ;;
    arm-*-riscix*)
      targ_defvec=riscix_vec
*************** case "${targ}" in
*** 828,833 ****
--- 829,849 ----
      targ_selvecs="bfd_elf32_tradlittlemips_vec ecoff_big_vec
ecoff_little_vec bfd_elf32_ntradbigmips_vec bfd_elf64_tradbigmips_vec
bfd_elf32_ntradlittlemips_vec bfd_elf64_tradlittlemips_vec"
      want64=true
      ;;
+    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__
+      ;;
  #ifdef BFD64
    mmix-*-*)
      targ_defvec=bfd_elf64_mmix_vec
*************** case "${targ}" in
*** 950,955 ****
--- 966,972 ----
    powerpc-*-nto*)
      targ_defvec=bfd_elf32_powerpc_vec
      targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec ppcboot_vec"
+     targ_cflags=-D__QNXTARGET__
      ;;
    powerpcle-*-nto*)
      targ_defvec=bfd_elf32_powerpcle_vec
*************** case "${targ}" in
*** 1073,1078 ****
--- 1090,1096 ----
      targ_defvec=bfd_elf32_sh_vec
      targ_selvecs="bfd_elf32_shl_vec shcoff_vec shlcoff_vec
shcoff_small_vec shlcoff_small_vec"
      targ_underscore=yes
+     targ_cflags=-D__QNXTARGET__
      ;;
    sh-*-pe)
      targ_defvec=shlpe_vec
Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.170
diff -c -3 -p -r1.170 elf32-mips.c
*** bfd/elf32-mips.c	3 Nov 2003 15:17:38 -0000	1.170
--- bfd/elf32-mips.c	6 Nov 2003 22:38:09 -0000
*************** static reloc_howto_type elf_mips16_gprel
*** 608,613 ****
--- 608,634 ----
  	 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 */
+ 
  /* GNU extensions for embedded-pic.  */
  /* High 16 bits of symbol value, pc-relative.  */
  static reloc_howto_type elf_mips_gnu_rel_hi16 =
*************** static const struct elf_reloc_map mips_r
*** 1447,1453 ****
    { 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 }
  };
  
  /* Given a BFD reloc type, return a howto structure.  */
--- 1468,1475 ----
    { 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_QNX_COPY, R_MIPS_QNX_COPY }
  };
  
  /* Given a BFD reloc type, return a howto structure.  */
*************** static const struct ecoff_debug_swap mip
*** 1895,1901 ****
     a value of 0x1000, and we are compatible.  */
  #define ELF_MAXPAGESIZE			0x1000
  
! #define elf_backend_collect		TRUE
  #define elf_backend_type_change_ok	TRUE
  #define elf_backend_can_gc_sections	TRUE
  #define elf_info_to_howto		mips_info_to_howto_rela
--- 1917,1925 ----
     a value of 0x1000, and we are compatible.  */
  #define ELF_MAXPAGESIZE			0x1000
  
! #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
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.80
diff -c -3 -p -r1.80 elfxx-mips.c
*** bfd/elfxx-mips.c	4 Nov 2003 10:41:51 -0000	1.80
--- bfd/elfxx-mips.c	6 Nov 2003 22:38:10 -0000
*************** static bfd *reldyn_sorting_bfd;
*** 603,608 ****
--- 603,618 ----
     : 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,0x0000(gp) */
+ #define STUB_QNX_NOP 0x00000000
+ #define STUB_QNX_JR  0x03200008 /* jal t9 */
+ 
+ #define USE_REL 1               /* MIPS uses REL relocations instead of
RELA */
+ 
  /* The name of the dynamic interpreter.  This is put in the .interp
     section.  */
  
*************** mips_elf_record_global_got_symbol (h, ab
*** 2055,2060 ****
--- 2065,2075 ----
       generic ELF copy_indirect_symbol tests for <= 0.  */
    h->got.offset = 1;
  
+ /* 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;
+ 
    return TRUE;
  }
  
*************** mips_elf_calculate_relocation (abfd, inp
*** 3261,3267 ****
  	       && ((h->root.elf_link_hash_flags
  		    & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
  	       && ((h->root.elf_link_hash_flags
! 		    & ELF_LINK_HASH_DEF_REGULAR) == 0)))
  	  && r_symndx != 0
  	  && (input_section->flags & SEC_ALLOC) != 0)
  	{
--- 3276,3282 ----
  	       && ((h->root.elf_link_hash_flags
  		    & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
  	       && ((h->root.elf_link_hash_flags
! 		    & (ELF_LINK_HASH_DEF_REGULAR|ELF_LINK_HASH_NEEDS_COPY))
== 0)))
  	  && r_symndx != 0
  	  && (input_section->flags & SEC_ALLOC) != 0)
  	{
*************** _bfd_mips_elf_create_dynamic_sections (a
*** 4973,4978 ****
--- 4988,5038 ----
  	}
      }
  
+   /* 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;
+     }
+ 
    return TRUE;
  }
  

*************** _bfd_mips_elf_check_relocs (abfd, info, 
*** 5241,5246 ****
--- 5301,5307 ----
  	    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)
*************** _bfd_mips_elf_check_relocs (abfd, info, 
*** 5347,5352 ****
--- 5408,5414 ----
  	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)
  	    {
*************** _bfd_mips_elf_adjust_dynamic_symbol (inf
*** 5667,5679 ****
  {
    bfd *dynobj;
    struct mips_elf_link_hash_entry *hmips;
!   asection *s;
  
    dynobj = elf_hash_table (info)->dynobj;
  
    /* Make sure we know what is going on here.  */
    BFD_ASSERT (dynobj != NULL
  	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
  		  || h->weakdef != NULL
  		  || ((h->elf_link_hash_flags
  		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
--- 5729,5749 ----
  {
    bfd *dynobj;
    struct mips_elf_link_hash_entry *hmips;
!   asection *s, *sreldyn = NULL;
!   unsigned int power_of_two;
  
    dynobj = elf_hash_table (info)->dynobj;
  
+   /* This will make sure that the dynamic object is put into the GOT */
+   if ( h->got.offset == MINUS_ONE )
+   {
+         h->got.offset = 1;
+   }
+ 
    /* Make sure we know what is going on here.  */
    BFD_ASSERT (dynobj != NULL
  	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+               || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY)
  		  || h->weakdef != NULL
  		  || ((h->elf_link_hash_flags
  		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
*************** _bfd_mips_elf_adjust_dynamic_symbol (inf
*** 5692,5697 ****
--- 5763,5769 ----
  	  || (h->elf_link_hash_flags
  	      & ELF_LINK_HASH_DEF_REGULAR) == 0))
      {
+       sreldyn = mips_elf_rel_dyn_section (dynobj, FALSE);
        mips_elf_allocate_dynamic_relocations (dynobj,
 
hmips->possibly_dynamic_relocs);
        if (hmips->readonly_reloc)
*************** _bfd_mips_elf_adjust_dynamic_symbol (inf
*** 5738,5743 ****
--- 5810,5848 ----
        /* 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;
+       /* 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->_raw_size;
+ 
+         h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+         if ( sreldyn != NULL ) {
+           sreldyn->_raw_size -= hmips->possibly_dynamic_relocs * sizeof
(Elf32_External_Rel);
+           if ( sreldyn->_raw_size == sizeof(Elf32_External_Rel) ) {
+             sreldyn->reloc_count--;
+             sreldyn->_raw_size = 0;
+           }
+         }
+ 
+         /* XXX Write this stub address somewhere.  */
+         h->plt.offset = s->_raw_size;
+ 
+         /* Make room for this stub code.  */
+         s->_raw_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;
+       }
        return TRUE;
      }
  
*************** _bfd_mips_elf_adjust_dynamic_symbol (inf
*** 5755,5761 ****
--- 5860,5918 ----
  
    /* This is a reference to a symbol defined by a dynamic object which
       is not a function.  */
+   if (info->shared)
+         return TRUE;
+   /* 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->_raw_size += sizeof (Elf32_External_Rel);
+       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ 
+       if ( sreldyn != NULL ) {
+         sreldyn->_raw_size -= hmips->possibly_dynamic_relocs * sizeof
(Elf32_External_Rel);
+         if ( sreldyn->_raw_size == sizeof(Elf32_External_Rel) ) {
+           sreldyn->reloc_count--;
+           sreldyn->_raw_size = 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->_raw_size = BFD_ALIGN (s->_raw_size,
+                             (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->_raw_size;
+ 
+   /* Increment the section size to make room for the symbol.  */
+   s->_raw_size += h->size;
+   /* Work around bug in sbss handling */
+   s->_cooked_size = s->_raw_size;
    return TRUE;
  }
  

*************** _bfd_mips_elf_size_dynamic_sections (out
*** 6077,6083 ****
        if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
  	return FALSE;
  
!       if (mips_elf_rel_dyn_section (dynobj, FALSE))
  	{
  	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
  	    return FALSE;
--- 6234,6241 ----
        if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
  	return FALSE;
  
!        if ((mips_elf_rel_dyn_section (dynobj, FALSE))
!       ||(bfd_get_section_by_name (dynobj, ".rel.bss")))
  	{
  	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
  	    return FALSE;
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6592,6603 ****
    bfd *dynobj;
    bfd_vma gval;
    asection *sgot;
!   struct mips_got_info *g, *gg;
    const char *name;
  
    dynobj = elf_hash_table (info)->dynobj;
    gval = sym->st_value;
  
    if (h->plt.offset != (bfd_vma) -1)
      {
        asection *s;
--- 6750,6773 ----
    bfd *dynobj;
    bfd_vma gval;
    asection *sgot;
!   asection *smsym;
!   struct mips_got_info *g = NULL, *gg = NULL;
    const char *name;
+   struct mips_elf_link_hash_entry *mh;
+   flagword flags;
+ 
+   /* To see if we are linking PIC */
+   flags = elf_elfheader (output_bfd)->e_flags;
  
    dynobj = elf_hash_table (info)->dynobj;
    gval = sym->st_value;
  
+   sgot = bfd_get_section_by_name (dynobj, ".got");
+   BFD_ASSERT (sgot != NULL);
+   BFD_ASSERT (elf_section_data (sgot) != NULL);
+   g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+   BFD_ASSERT (g != NULL);
+ 
    if (h->plt.offset != (bfd_vma) -1)
      {
        asection *s;
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6611,6625 ****
  				   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.  */
!       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);
  
        BFD_ASSERT (h->plt.offset <= s->_raw_size);
        memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
--- 6781,6810 ----
  				   MIPS_ELF_STUB_SECTION_NAME (dynobj));
        BFD_ASSERT (s != NULL);
  
!       if ((flags & EF_MIPS_PIC) || (flags & EF_MIPS_CPIC)) {
!         /* Fill the stub.  */
!         bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub);
!         bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + 4);
! 
! 
!         /* FIXME: Can h->dynindex be more than 64K?  */
!         if (h->dynindx & 0xffff0000)
!         return FALSE;
! 
!         bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
!         bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub
+ 12);
!       } else { /* Non-pic case: stub is used to jump to shared lib */
!           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);
!       }
  
        BFD_ASSERT (h->plt.offset <= s->_raw_size);
        memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6632,6647 ****
  	 to reset the global offset table entry for this external
  	 to its stub address when unlinking a shared object.  */
        gval = s->output_section->vma + s->output_offset + h->plt.offset;
!       sym->st_value = gval;
      }
  
    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
--- 6821,6843 ----
  	 to reset the global offset table entry for this external
  	 to its stub address when unlinking a shared object.  */
        gval = s->output_section->vma + s->output_offset + h->plt.offset;
!       if ((flags & EF_MIPS_PIC) || (flags & EF_MIPS_CPIC) ||
!info->shared)
!         {
!           sym->st_value = gval;
!         }
!       else
!         {
!           sym->st_value = 0;
!         }
      }
  
    BFD_ASSERT (h->dynindx != -1
  	      || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
  
!   sgot = mips_elf_got_section (dynobj);
    BFD_ASSERT (sgot != NULL);
!   BFD_ASSERT (elf_section_data (sgot) != NULL);
!   g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
    BFD_ASSERT (g != NULL);
  
    /* Run through the global symbol table, creating GOT entries for all
*************** _bfd_mips_elf_finish_dynamic_symbol (out
*** 6783,6788 ****
--- 6979,7005 ----
  	}
      }
  
+   /* 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;
+     }
+ 
    /* If this is a mips16 symbol, force the value to be even.  */
    if (sym->st_other == STO_MIPS16
        && (sym->st_value & 1) != 0)
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 6846,6851 ****
--- 7063,7069 ----
  	    {
  	    case DT_RELENT:
  	      s = mips_elf_rel_dyn_section (dynobj, FALSE);
+ 	      if (s==NULL) s=bfd_get_section_by_name(dynobj, ".rel.bss");
  	      BFD_ASSERT (s != NULL);
  	      dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
  	      break;
*************** _bfd_mips_elf_final_link (abfd, info)
*** 8230,8240 ****
        dynobj = elf_hash_table (info)->dynobj;
        got = mips_elf_got_section (dynobj, FALSE);
        g = mips_elf_section_data (got)->u.got_info;
! 
!       if (g->global_gotsym != NULL)
  	BFD_ASSERT ((elf_hash_table (info)->dynsymcount
  		     - g->global_gotsym->dynindx)
  		    <= g->global_gotno);
      }
  
  #if 0
--- 8448,8458 ----
        dynobj = elf_hash_table (info)->dynobj;
        got = mips_elf_got_section (dynobj, FALSE);
        g = mips_elf_section_data (got)->u.got_info;
!       if (g->global_gotsym != NULL) {
  	BFD_ASSERT ((elf_hash_table (info)->dynsymcount
  		     - g->global_gotsym->dynindx)
  		    <= g->global_gotno);
+ 	}
      }
  
  #if 0
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.98
diff -c -3 -p -r1.98 libbfd.h
*** bfd/libbfd.h	4 Nov 2003 10:41:51 -0000	1.98
--- bfd/libbfd.h	6 Nov 2003 22:38:10 -0000
*************** static const char *const bfd_reloc_code_
*** 854,860 ****
    "BFD_RELOC_MIPS_REL16",
    "BFD_RELOC_MIPS_RELGOT",
    "BFD_RELOC_MIPS_JALR",
! 
    "BFD_RELOC_FRV_LABEL16",
    "BFD_RELOC_FRV_LABEL24",
    "BFD_RELOC_FRV_LO16",
--- 854,860 ----
    "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",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.95
diff -c -3 -p -r1.95 reloc.c
*** bfd/reloc.c	31 Oct 2003 05:32:46 -0000	1.95
--- bfd/reloc.c	6 Nov 2003 22:38:11 -0000
*************** ENUMX
*** 2120,2126 ****
  ENUMDOC
    MIPS ELF relocations.
  COMMENT
! 
  ENUM
    BFD_RELOC_FRV_LABEL16
  ENUMX
--- 2120,2127 ----
  ENUMDOC
    MIPS ELF relocations.
  COMMENT
! ENUMX
!   BFD_RELOC_MIPS_QNX_COPY
  ENUM
    BFD_RELOC_FRV_LABEL16
  ENUMX
Index: gas/configure
===================================================================
RCS file: /cvs/src/src/gas/configure,v
retrieving revision 1.158
diff -c -3 -p -r1.158 configure
*** gas/configure	29 Oct 2003 19:47:59 -0000	1.158
--- gas/configure	6 Nov 2003 22:38:13 -0000
*************** echo "$as_me: error: Unknown vendor for 
*** 4236,4242 ****
        mips-*-elf* | mips-*-rtems*)	fmt=elf ;;
        mips-*-netbsd*)			fmt=elf ;;
        mips-*-openbsd*)			fmt=elf ;;
! 
        mmix-*-*)				fmt=elf ;;
        mn10200-*-*)			fmt=elf ;;
        mn10300-*-*)			fmt=elf ;;
--- 4236,4243 ----
        mips-*-elf* | mips-*-rtems*)	fmt=elf ;;
        mips-*-netbsd*)			fmt=elf ;;
        mips-*-openbsd*)			fmt=elf ;;
!       mips-**-nto*)			fmt=elf endian=little ;;
!       mips-*-vxworks*)			fmt=elf ;;
        mmix-*-*)				fmt=elf ;;
        mn10200-*-*)			fmt=elf ;;
        mn10300-*-*)			fmt=elf ;;
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.143
diff -c -3 -p -r1.143 configure.in
*** gas/configure.in	29 Oct 2003 19:48:00 -0000	1.143
--- gas/configure.in	6 Nov 2003 22:38:13 -0000
*************** changequote([,])dnl
*** 391,397 ****
        mips-*-elf* | mips-*-rtems*)	fmt=elf ;;
        mips-*-netbsd*)			fmt=elf ;;
        mips-*-openbsd*)			fmt=elf ;;
! 
        mmix-*-*)				fmt=elf ;;
        mn10200-*-*)			fmt=elf ;;
        mn10300-*-*)			fmt=elf ;;
--- 391,398 ----
        mips-*-elf* | mips-*-rtems*)	fmt=elf ;;
        mips-*-netbsd*)			fmt=elf ;;
        mips-*-openbsd*)			fmt=elf ;;
!       mips-**-nto*)			fmt=elf endian=little ;;
!       mips-*-vxworks*)			fmt=elf ;;
        mmix-*-*)				fmt=elf ;;
        mn10200-*-*)			fmt=elf ;;
        mn10300-*-*)			fmt=elf ;;
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.236
diff -c -3 -p -r1.236 tc-mips.c
*** gas/config/tc-mips.c	19 Oct 2003 21:50:43 -0000	1.236
--- gas/config/tc-mips.c	6 Nov 2003 22:38:16 -0000
*************** static offsetT mips_cprestore_offset = -
*** 473,479 ****
     offset and even an other register than $gp as global pointer.  */
  static offsetT mips_cpreturn_offset = -1;
  static int mips_cpreturn_register = -1;
! static int mips_gp_register = GP;
  static int mips_gprel_offset = 0;
  
  /* Whether mips_cprestore_offset has been set in the current function
--- 473,479 ----
     offset and even an other register than $gp as global pointer.  */
  static offsetT mips_cpreturn_offset = -1;
  static int mips_cpreturn_register = -1;
! static int mips_gp_register = GOT_REG;
  static int mips_gprel_offset = 0;
  
  /* Whether mips_cprestore_offset has been set in the current function
*************** static void s_mips_globl (int);
*** 857,862 ****
--- 857,864 ----
  static void s_option (int);
  static void s_mipsset (int);
  static void s_abicalls (int);
+ static void s_qnxpiccalls (int);
+ static void s_noqnxpiccalls (int);
  static void s_cpload (int);
  static void s_cpsetup (int);
  static void s_cplocal (int);
*************** static const pseudo_typeS mips_pseudo_ta
*** 923,928 ****
--- 925,932 ----
    {"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},
*************** load_address (int *counter, int reg, exp
*** 3780,3786 ****
  		       BFD_RELOC_LO16);
  	}
      }
!   else if (mips_pic == SVR4_PIC && ! mips_big_got)
      {
        expressionS ex;
  
--- 3784,3790 ----
  		       BFD_RELOC_LO16);
  	}
      }
!   else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
mips_big_got)
      {
        expressionS ex;
  
*************** load_address (int *counter, int reg, exp
*** 3838,3849 ****
  	  macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
  		       BFD_RELOC_MIPS_GOT16,
  		       mips_gp_register);
! 	  macro_build (NULL, counter, NULL, "nop", "");
  	  p = frag_var (rs_machine_dependent, 4, 0,
! 			RELAX_ENCODE (0, 4, -8, 0, 0,
mips_opts.warn_about_macros),
! 			ep->X_add_symbol, 0, NULL);
! 	  macro_build (p, counter, ep, ADDRESS_ADDI_INSN, "t,r,j", reg, reg,
! 		       BFD_RELOC_LO16);
  
  	  if (ex.X_add_number != 0)
  	    {
--- 3842,3854 ----
  	  macro_build (NULL, counter, ep, ADDRESS_LOAD_INSN, "t,o(b)", reg,
  		       BFD_RELOC_MIPS_GOT16,
  		       mips_gp_register);
!           if (NOP_NEEDED)
!   	    macro_build (NULL, counter, NULL, "nop", "");
  	  p = frag_var (rs_machine_dependent, 4, 0,
! 			RELAX_ENCODE (0, 4, NOP_NEEDED ? -8 : -4, 0, 0,
mips_opts.warn_about_macros),
! 			ep->X_add_symbol, (offsetT) 0, (char *) NULL);
! 	  macro_build (p, counter, ep, ADDRESS_ADDI_INSN,
! 		       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
  
  	  if (ex.X_add_number != 0)
  	    {
*************** load_address (int *counter, int reg, exp
*** 3855,3861 ****
  	    }
  	}
      }
!   else if (mips_pic == SVR4_PIC)
      {
        expressionS ex;
        int off;
--- 3860,3866 ----
  	    }
  	}
      }
!   else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
      {
        expressionS ex;
        int off;
*************** macro (struct mips_cl_insn *ip)
*** 4949,4955 ****
  			   "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
  	    }
  	}
!       else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI)
  	{
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
  
--- 4954,4960 ----
  			   "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
  	    }
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
mips_big_got && ! HAVE_NEWABI)
  	{
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
  
*************** macro (struct mips_cl_insn *ip)
*** 4995,5002 ****
  	      int off;
  	      char *p;
  
! 	      if (breg == 0)
! 		off = 0;
  	      else
  		{
  		  /* We're going to put in an addu instruction using
--- 5000,5009 ----
  	      int off;
  	      char *p;
  
! 	      if ((breg == 0) && (NOP_NEEDED))
!     	        off = 0;
! 	      else if (!NOP_NEEDED)
!                 off = 4;
  	      else
  		{
  		  /* We're going to put in an addu instruction using
*************** macro (struct mips_cl_insn *ip)
*** 5006,5017 ****
  		  off = 4;
  		}
  	      p = frag_var (rs_machine_dependent, 8 - off, 0,
! 			    RELAX_ENCODE (0, 8 - off, -4 - off, 4 - off, 0,
  					  (breg == 0
  					   ? mips_opts.warn_about_macros
  					   : 0)),
  			    offset_expr.X_add_symbol, 0, NULL);
! 	      if (breg == 0)
  		{
  		  macro_build (p, &icnt, NULL, "nop", "");
  		  p += 4;
--- 5013,5024 ----
  		  off = 4;
  		}
  	      p = frag_var (rs_machine_dependent, 8 - off, 0,
! 			    RELAX_ENCODE (0, 8 - off, NOP_NEEDED ? (-4 -
off) : (0 - off), 4 - off, 0,
  					  (breg == 0
  					   ? mips_opts.warn_about_macros
  					   : 0)),
  			    offset_expr.X_add_symbol, 0, NULL);
! 		if ((breg == 0) && (NOP_NEEDED))
  		{
  		  macro_build (p, &icnt, NULL, "nop", "");
  		  p += 4;
*************** macro (struct mips_cl_insn *ip)
*** 5025,5035 ****
  	  else if (expr1.X_add_number >= -0x8000
  		   && expr1.X_add_number < 0x8000)
  	    {
! 	      macro_build (NULL, &icnt, NULL, "nop", "");
! 	      macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
! 			   "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
  	      frag_var (rs_machine_dependent, 0, 0,
! 			RELAX_ENCODE (0, 0, -12, -4, 0, 0),
  			offset_expr.X_add_symbol, 0, NULL);
  	    }
  	  else
--- 5032,5044 ----
  	  else if (expr1.X_add_number >= -0x8000
  		   && expr1.X_add_number < 0x8000)
  	    {
!  	      if (NOP_NEEDED)
! 	        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
! 			   "nop", "");
! 	      macro_build ((char *) NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
! 			   "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
  	      frag_var (rs_machine_dependent, 0, 0,
! 			RELAX_ENCODE (0, 0, NOP_NEEDED ? -12 : -8, -4, 0,
0),
  			offset_expr.X_add_symbol, 0, NULL);
  	    }
  	  else
*************** macro (struct mips_cl_insn *ip)
*** 5047,5058 ****
  		off1 = 0;
  	      else
  		{
! 		  macro_build (NULL, &icnt, NULL, "nop", "");
! 		  macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
! 			       treg, AT, breg);
  		  breg = 0;
  		  tempreg = treg;
! 		  off1 = -8;
  		}
  
  	      /* Set mips_optimize around the lui instruction to avoid
--- 5056,5069 ----
  		off1 = 0;
  	      else
  		{
! 		  if (NOP_NEEDED) 
! 		    macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
! 			       "nop", "");
! 		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
! 			       ADDRESS_ADD_INSN, "d,v,t", treg, AT, breg);
  		  breg = 0;
  		  tempreg = treg;
! 		  off1 = (NOP_NEEDED) ? -8 : -4;
  		}
  
  	      /* Set mips_optimize around the lui instruction to avoid
*************** macro (struct mips_cl_insn *ip)
*** 5072,5078 ****
  	      used_at = 1;
  	    }
  	}
!       else if (mips_pic == SVR4_PIC && ! mips_big_got && HAVE_NEWABI)
  	{
  	  char *p = NULL;
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
--- 5083,5089 ----
  	      used_at = 1;
  	    }
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
mips_big_got && HAVE_NEWABI)
  	{
  	  char *p = NULL;
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
*************** macro (struct mips_cl_insn *ip)
*** 5193,5199 ****
  	      frag_new (0);
  	    }
  	}
!       else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
  	{
  	  int gpdel;
  	  char *p;
--- 5204,5210 ----
  	      frag_new (0);
  	    }
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
HAVE_NEWABI)
  	{
  	  int gpdel;
  	  char *p;
*************** macro (struct mips_cl_insn *ip)
*** 5398,5404 ****
  	      p += 4;
  	    }
  	}
!       else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
  	{
  	  char *p = NULL;
  	  int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
--- 5409,5415 ----
  	      p += 4;
  	    }
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) &&
HAVE_NEWABI)
  	{
  	  char *p = NULL;
  	  int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
*************** macro (struct mips_cl_insn *ip)
*** 5574,5581 ****
      case M_JAL_2:
        if (mips_pic == NO_PIC
  	  || mips_pic == EMBEDDED_PIC)
! 	macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
!       else if (mips_pic == SVR4_PIC)
  	{
  	  if (sreg != PIC_CALL_REG)
  	    as_warn (_("MIPS PIC call to register other than $25"));
--- 5585,5593 ----
      case M_JAL_2:
        if (mips_pic == NO_PIC
  	  || mips_pic == EMBEDDED_PIC)
! 	macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",
! 		     "d,s", dreg, sreg);
!       else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
  	{
  	  if (sreg != PIC_CALL_REG)
  	    as_warn (_("MIPS PIC call to register other than $25"));
*************** macro (struct mips_cl_insn *ip)
*** 5583,5591 ****
  	  macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
  	  if (! HAVE_NEWABI)
  	    {
! 	      if (mips_cprestore_offset < 0)
! 		as_warn (_("No .cprestore pseudo-op used in PIC code"));
! 	      else
  		{
  		  if (! mips_frame_reg_valid)
  		    {
--- 5595,5604 ----
  	  macro_build (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
  	  if (! HAVE_NEWABI)
  	    {
! 	      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)
  		    {
*************** macro (struct mips_cl_insn *ip)
*** 5595,5601 ****
  		    }
  		  if (! mips_cprestore_valid)
  		    {
! 		      as_warn (_("No .cprestore pseudo-op used in PIC
code"));
  		      /* Quiet this warning.  */
  		      mips_cprestore_valid = 1;
  		    }
--- 5608,5615 ----
  		    }
  		  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;
  		    }
*************** macro (struct mips_cl_insn *ip)
*** 5615,5622 ****
  
      case M_JAL_A:
        if (mips_pic == NO_PIC)
! 	macro_build (NULL, &icnt, &offset_expr, "jal", "a");
!       else if (mips_pic == SVR4_PIC)
  	{
  	  char *p;
  
--- 5629,5636 ----
  
      case M_JAL_A:
        if (mips_pic == NO_PIC)
! 	macro_build ((char *) NULL, &icnt, &offset_expr, "jal", "a");
!       else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
  	{
  	  char *p;
  
*************** macro (struct mips_cl_insn *ip)
*** 5688,5699 ****
  	      frag_grow (40);
  	      if (! mips_big_got)
  		{
! 		  macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
! 			       "t,o(b)", PIC_CALL_REG,
BFD_RELOC_MIPS_CALL16,
! 			       mips_gp_register);
! 		  macro_build (NULL, &icnt, NULL, "nop", "");
  		  p = frag_var (rs_machine_dependent, 4, 0,
! 				RELAX_ENCODE (0, 4, -8, 0, 0, 0),
  				offset_expr.X_add_symbol, 0, NULL);
  		}
  	      else
--- 5702,5723 ----
  	      frag_grow (40);
  	      if (! mips_big_got)
  		{
!            	  if(mips_pic != QNX_PIC)
!            	    macro_build ((char *) NULL, &icnt, &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, mips_gp_register);
!            	  else
! 		  macro_build ((char *) NULL, &icnt, &offset_expr,
! 			       ADDRESS_LOAD_INSN, "t,o(b)", PIC_CALL_REG,
! 			       (int) BFD_RELOC_MIPS_CALL16,
mips_gp_register);
! 		  if (NOP_NEEDED)
! 		    macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
! 			       "nop", "");
  		  p = frag_var (rs_machine_dependent, 4, 0,
! 				RELAX_ENCODE (0, 4, NOP_NEEDED ? -8 : -4, 0,
0, 0),
  				offset_expr.X_add_symbol, 0, NULL);
  		}
  	      else
*************** macro (struct mips_cl_insn *ip)
*** 5733,5741 ****
  			   BFD_RELOC_LO16);
  	      macro_build_jalr (icnt, &offset_expr);
  
! 	      if (mips_cprestore_offset < 0)
! 		as_warn (_("No .cprestore pseudo-op used in PIC code"));
! 	      else
  		{
  		  if (! mips_frame_reg_valid)
  		    {
--- 5757,5766 ----
  			   BFD_RELOC_LO16);
  	      macro_build_jalr (icnt, &offset_expr);
  
! 	      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)
  		    {
*************** macro (struct mips_cl_insn *ip)
*** 6202,6208 ****
  			   BFD_RELOC_LO16, tempreg);
  	    }
  	}
!       else if (mips_pic == SVR4_PIC && ! mips_big_got)
  	{
  	  char *p;
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
--- 6227,6233 ----
  			   BFD_RELOC_LO16, tempreg);
  	    }
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
mips_big_got)
  	{
  	  char *p;
  	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
*************** macro (struct mips_cl_insn *ip)
*** 6264,6270 ****
  	  macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
  		       tempreg);
  	}
!       else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI)
  	{
  	  int gpdel;
  	  char *p;
--- 6289,6295 ----
  	  macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
  		       tempreg);
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
HAVE_NEWABI)
  	{
  	  int gpdel;
  	  char *p;
*************** macro (struct mips_cl_insn *ip)
*** 6313,6329 ****
  	  macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
  		       tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register);
  	  p += 4;
! 	  macro_build (p, &icnt, NULL, "nop", "");
! 	  p += 4;
! 	  macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
! 		       tempreg, tempreg, BFD_RELOC_LO16);
  	  if (breg != 0)
  	    macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
  			 tempreg, tempreg, breg);
  	  macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
  		       tempreg);
  	}
!       else if (mips_pic == SVR4_PIC && HAVE_NEWABI)
  	{
  	  char *p;
  	  int bregsz = breg != 0 ? 4 : 0;
--- 6338,6356 ----
  	  macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
  		       tempreg, BFD_RELOC_MIPS_GOT16, mips_gp_register);
  	  p += 4;
! 	  if (NOP_NEEDED) {
!             macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
! 	    p += 4;
!           }
! 	  macro_build (p, &icnt, &offset_expr, ADDRESS_ADDI_INSN,
! 		       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
  	  if (breg != 0)
  	    macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
  			 tempreg, tempreg, breg);
  	  macro_build (NULL, &icnt, &expr1, s, fmt, treg, BFD_RELOC_LO16,
  		       tempreg);
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) &&
HAVE_NEWABI)
  	{
  	  char *p;
  	  int bregsz = breg != 0 ? 4 : 0;
*************** macro (struct mips_cl_insn *ip)
*** 6474,6480 ****
  	{
  	  macro_build_lui (NULL, &icnt, &offset_expr, AT);
  	}
!       else if (mips_pic == SVR4_PIC)
  	{
  	  macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
"t,o(b)",
  		       AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
--- 6501,6507 ----
  	{
  	  macro_build_lui (NULL, &icnt, &offset_expr, AT);
  	}
!       else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
  	{
  	  macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
"t,o(b)",
  		       AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
*************** macro (struct mips_cl_insn *ip)
*** 6563,6572 ****
        else
  	{
  	  assert (strcmp (s, RDATA_SECTION_NAME) == 0);
! 	  if (mips_pic == SVR4_PIC)
! 	    macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
! 			 "t,o(b)", AT, BFD_RELOC_MIPS_GOT16,
! 			 mips_gp_register);
  	  else
  	    {
  	      /* FIXME: This won't work for a 64 bit address.  */
--- 6590,6599 ----
        else
  	{
  	  assert (strcmp (s, RDATA_SECTION_NAME) == 0);
! 	  if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
! 	    macro_build ((char *) NULL, &icnt, &offset_expr,
! 			 ADDRESS_LOAD_INSN, "t,o(b)", AT,
! 			 (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
  	  else
  	    {
  	      /* FIXME: This won't work for a 64 bit address.  */
*************** macro (struct mips_cl_insn *ip)
*** 6818,6824 ****
  		       coproc ? treg : treg + 1,
  		       BFD_RELOC_LO16, AT);
  	}
!       else if (mips_pic == SVR4_PIC && ! mips_big_got)
  	{
  	  int off;
  
--- 6845,6851 ----
  		       coproc ? treg : treg + 1,
  		       BFD_RELOC_LO16, AT);
  	}
!       else if ((mips_pic == SVR4_PIC || mips_pic == QNX_PIC) && !
mips_big_got)
  	{
  	  int off;
  
*************** macro (struct mips_cl_insn *ip)
*** 6846,6854 ****
  	  else
  	    off = 4;
  	  frag_grow (24 + off);
! 	  macro_build (NULL, &icnt, &offset_expr, ADDRESS_LOAD_INSN,
"t,o(b)",
! 		       AT, BFD_RELOC_MIPS_GOT16, mips_gp_register);
! 	  macro_build (NULL, &icnt, NULL, "nop", "");
  	  if (breg != 0)
  	    macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
  			 AT, breg, AT);
--- 6873,6883 ----
  	  else
  	    off = 4;
  	  frag_grow (24 + off);
! 	  macro_build ((char *) NULL, &icnt, &offset_expr,
ADDRESS_LOAD_INSN,
! 		       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16,
! 		       mips_gp_register);
! 	  if (NOP_NEEDED)
! 	    macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop",
"");
  	  if (breg != 0)
  	    macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
  			 AT, breg, AT);
*************** macro (struct mips_cl_insn *ip)
*** 6867,6876 ****
  	  mips_optimize = hold_mips_optimize;
  
  	  (void) frag_var (rs_machine_dependent, 0, 0,
! 			   RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),
  			   offset_expr.X_add_symbol, 0, NULL);
  	}
!       else if (mips_pic == SVR4_PIC)
  	{
  	  int gpdel, off;
  	  char *p;
--- 6896,6905 ----
  	  mips_optimize = hold_mips_optimize;
  
  	  (void) frag_var (rs_machine_dependent, 0, 0,
! 			   RELAX_ENCODE (0, 0, NOP_NEEDED ? (-16 - off) :
(-12 - off), -8, 1, 0),
  			   offset_expr.X_add_symbol, 0, NULL);
  	}
!       else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
  	{
  	  int gpdel, off;
  	  char *p;
*************** struct option md_longopts[] =
*** 10560,10565 ****
--- 10589,10596 ----
    {"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}
*************** md_parse_option (int c, char *arg)
*** 10783,10788 ****
--- 10814,10835 ----
        g_switch_value = 0;
        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;
+       mips_abicalls = TRUE;
+       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;
+ 
      case OPTION_NON_SHARED:
        if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
  	{
*************** md_parse_option (int c, char *arg)
*** 10807,10813 ****
  	  as_bad (_("-G is not supported for this configuration"));
  	  return 0;
  	}
!       else if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC)
  	{
  	  as_bad (_("-G may not be used with SVR4 or embedded PIC code"));
  	  return 0;
--- 10854,10860 ----
  	  as_bad (_("-G is not supported for this configuration"));
  	  return 0;
  	}
!       else if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC ||
mips_pic == QNX_PIC)
  	{
  	  as_bad (_("-G may not be used with SVR4 or embedded PIC code"));
  	  return 0;
*************** s_abicalls (int ignore ATTRIBUTE_UNUSED)
*** 12344,12349 ****
--- 12391,12423 ----
    demand_empty_rest_of_line ();
  }
  
+ /* This handles the .qnxpiccalls pseudo-op.i */
+ 
+ static void
+ s_qnxpiccalls (ignore)
+      int ignore;
+ {
+   mips_pic = QNX_PIC;
+   if (USE_GLOBAL_POINTER_OPT)
+     {
+       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;
+ {
+   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.
*************** s_abicalls (int ignore ATTRIBUTE_UNUSED)
*** 12352,12358 ****
  	lui	$gp,%hi(_gp_disp)
  	addiu	$gp,$gp,%lo(_gp_disp)
  	addu	$gp,$gp,.cpload argument
!    The .cpload argument is normally $25 == $t9.  */
  
  static void
  s_cpload (int ignore ATTRIBUTE_UNUSED)
--- 12426,12441 ----
  	lui	$gp,%hi(_gp_disp)
  	addiu	$gp,$gp,%lo(_gp_disp)
  	addu	$gp,$gp,.cpload argument
!    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)
*************** s_cpload (int ignore ATTRIBUTE_UNUSED)
*** 12362,12375 ****
  
    /* If we are not generating SVR4 PIC code, or if this is NewABI code,
       .cpload is ignored.  */
!   if (mips_pic != SVR4_PIC || HAVE_NEWABI)
      {
        s_ignore (0);
        return;
      }
  
    /* .cpload should be in a .set noreorder section.  */
!   if (mips_opts.noreorder == 0)
      as_warn (_(".cpload not in noreorder section"));
  
    ex.X_op = O_symbol;
--- 12445,12458 ----
  
    /* If we are not generating SVR4 PIC code, or if this is NewABI code,
       .cpload is ignored.  */
!   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) && (mips_pic != QNX_PIC))
      as_warn (_(".cpload not in noreorder section"));
  
    ex.X_op = O_symbol;
*************** s_cpload (int ignore ATTRIBUTE_UNUSED)
*** 12380,12391 ****
    /* In ELF, this symbol is implicitly an STT_OBJECT symbol.  */
    symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
  
!   macro_build_lui (NULL, &icnt, &ex, mips_gp_register);
!   macro_build (NULL, &icnt, &ex, "addiu", "t,r,j", mips_gp_register,
! 	       mips_gp_register, BFD_RELOC_LO16);
! 
!   macro_build (NULL, &icnt, NULL, "addu", "d,v,t", mips_gp_register,
! 	       mips_gp_register, tc_get_register (0));
  
    demand_empty_rest_of_line ();
  }
--- 12463,12526 ----
    /* 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_prev_f,*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;
! //                prev_insn.insn_opcode = 0x04100001;
!                   macro_build ((char *) NULL, &icnt, &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 ((char *) NULL, &icnt, &ep,
!                        "bltzal", "s,p", 0);
!                 macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
"nop", "");
!           }
!         macro_build_lui ((char *) NULL, &icnt, &ex, 23);
!         macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", 23, 23,
!                        (int) BFD_RELOC_LO16);
!         mips_opts.noreorder --;
! 
!         macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "addu",
"d,v,t",
!                        23, 23, RA);
!   } else {
! 	macro_build_lui (NULL, &icnt, &ex, mips_gp_register);
! 	macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j",
!              mips_gp_register, mips_gp_register, (int) BFD_RELOC_LO16);
! 
! 	macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "addu",
"d,v,t",
!              mips_gp_register, mips_gp_register, tc_get_register (0));
!   }
  
    demand_empty_rest_of_line ();
  }
*************** s_cpsetup (int ignore ATTRIBUTE_UNUSED)
*** 12416,12422 ****
  
    /* If we are not generating SVR4 PIC code, .cpsetup is ignored.
       We also need NewABI support.  */
!   if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
--- 12551,12557 ----
  
    /* If we are not generating SVR4 PIC code, .cpsetup is ignored.
       We also need NewABI support.  */
!   if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
*************** s_cplocal (int ignore ATTRIBUTE_UNUSED)
*** 12497,12503 ****
  {
    /* 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)
      {
        s_ignore (0);
        return;
--- 12632,12638 ----
  {
    /* If we are not generating SVR4 PIC code, or if this is not NewABI
code,
     .cplocal is ignored.  */
!   if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
*************** s_cprestore (int ignore ATTRIBUTE_UNUSED
*** 12519,12525 ****
  
    /* If we are not generating SVR4 PIC code, or if this is NewABI code,
       .cprestore is ignored.  */
!   if (mips_pic != SVR4_PIC || HAVE_NEWABI)
      {
        s_ignore (0);
        return;
--- 12654,12660 ----
  
    /* If we are not generating SVR4 PIC code, or if this is NewABI code,
       .cprestore is ignored.  */
!   if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || HAVE_NEWABI)
      {
        s_ignore (0);
        return;
*************** s_cpreturn (int ignore ATTRIBUTE_UNUSED)
*** 12554,12560 ****
  
    /* If we are not generating SVR4 PIC code, .cpreturn is ignored.
       We also need NewABI support.  */
!   if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
--- 12689,12695 ----
  
    /* If we are not generating SVR4 PIC code, .cpreturn is ignored.
       We also need NewABI support.  */
!   if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
*************** s_gpvalue (int ignore ATTRIBUTE_UNUSED)
*** 12585,12591 ****
  {
    /* If we are not generating SVR4 PIC code, .gpvalue is ignored.
       We also need NewABI support.  */
!   if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
--- 12720,12726 ----
  {
    /* If we are not generating SVR4 PIC code, .gpvalue is ignored.
       We also need NewABI support.  */
!   if ((mips_pic != SVR4_PIC && mips_pic != QNX_PIC) || ! HAVE_NEWABI)
      {
        s_ignore (0);
        return;
*************** s_gpword (int ignore ATTRIBUTE_UNUSED)
*** 12607,12613 ****
    char *p;
  
    /* When not generating PIC code, this is treated as .word.  */
!   if (mips_pic != SVR4_PIC)
      {
        s_cons (2);
        return;
--- 12742,12748 ----
    char *p;
  
    /* When not generating PIC code, this is treated as .word.  */
!   if ((mips_pic != SVR4_PIC) && (mips_pic != QNX_PIC))
      {
        s_cons (2);
        return;
*************** s_gpdword (int ignore ATTRIBUTE_UNUSED)
*** 12643,12649 ****
    char *p;
  
    /* When not generating PIC code, this is treated as .dword.  */
!   if (mips_pic != SVR4_PIC)
      {
        s_cons (3);
        return;
--- 12778,12784 ----
    char *p;
  
    /* When not generating PIC code, this is treated as .dword.  */
!   if ((mips_pic != SVR4_PIC) && (mips_pic != QNX_PIC))
      {
        s_cons (3);
        return;
*************** s_cpadd (int ignore ATTRIBUTE_UNUSED)
*** 12688,12694 ****
    int reg;
  
    /* This is ignored when not generating SVR4 PIC code.  */
!   if (mips_pic != SVR4_PIC)
      {
        s_ignore (0);
        return;
--- 12823,12829 ----
    int reg;
  
    /* This is ignored when not generating SVR4 PIC code.  */
!   if ((mips_pic != SVR4_PIC) && (mips_pic != QNX_PIC))
      {
        s_ignore (0);
        return;
*************** pic_need_relax (symbolS *sym, asection *
*** 12997,13002 ****
--- 13132,13138 ----
    /* This must duplicate the test in adjust_reloc_syms.  */
    return (symsec != &bfd_und_section
  	  && symsec != &bfd_abs_section
+ 	  && ((mips_pic != QNX_PIC) || ((mips_pic == QNX_PIC) &&
!S_IS_EXTERN(sym) && !S_IS_WEAK(sym)))
  	  && ! bfd_is_com_section (symsec)
  	  && !linkonce
  #ifdef OBJ_ELF
*************** md_estimate_size_before_relax (fragS *fr
*** 13297,13303 ****
  
    if (mips_pic == NO_PIC)
      change = nopic_need_relax (fragp->fr_symbol, 0);
!   else if (mips_pic == SVR4_PIC)
      change = pic_need_relax (fragp->fr_symbol, segtype);
    else
      abort ();
--- 13433,13439 ----
  
    if (mips_pic == NO_PIC)
      change = nopic_need_relax (fragp->fr_symbol, 0);
!   else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
      change = pic_need_relax (fragp->fr_symbol, segtype);
    else
      abort ();
*************** mips_fix_adjustable (fixS *fixp)
*** 13341,13347 ****
  
    if (fixp->fx_addsy == NULL)
      return 1;
! 
  #ifdef OBJ_ELF
    if (OUTPUT_FLAVOR == bfd_target_elf_flavour
        && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
--- 13477,13488 ----
  
    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;
!     }
  #ifdef OBJ_ELF
    if (OUTPUT_FLAVOR == bfd_target_elf_flavour
        && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
*************** tc_gen_reloc (asection *section ATTRIBUT
*** 13492,13498 ****
  	  assert (fixp->fx_r_type == BFD_RELOC_GPREL16);
  	  fixp->fx_r_type = BFD_RELOC_HI16_S;
  	}
!       else if (mips_pic == SVR4_PIC)
  	{
  	  switch (fixp->fx_r_type)
  	    {
--- 13633,13639 ----
  	  assert (fixp->fx_r_type == BFD_RELOC_GPREL16);
  	  fixp->fx_r_type = BFD_RELOC_HI16_S;
  	}
!       else if ((mips_pic == SVR4_PIC) || (mips_pic == QNX_PIC))
  	{
  	  switch (fixp->fx_r_type)
  	    {
*************** mips_elf_final_processing (void)
*** 14055,14061 ****
       sort of BFD interface for this.  */
    if (mips_any_noreorder)
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NOREORDER;
!   if (mips_pic != NO_PIC)
      {
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
        elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
--- 14196,14202 ----
       sort of BFD interface for this.  */
    if (mips_any_noreorder)
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NOREORDER;
!   if (mips_pic != NO_PIC && mips_pic != QNX_PIC)
      {
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
        elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.30
diff -c -3 -p -r1.30 tc-mips.h
*** gas/config/tc-mips.h	25 Jul 2003 14:35:54 -0000	1.30
--- gas/config/tc-mips.h	6 Nov 2003 22:38:16 -0000
*************** enum mips_pic_level
*** 84,91 ****
       segment has a maximum size of 64K, all data references are off
       the $gp register, and all text references are PC relative.  This
       is used on some embedded systems.  */
!   EMBEDDED_PIC
  };
  
  extern enum mips_pic_level mips_pic;
  
--- 84,107 ----
       segment has a maximum size of 64K, all data references are off
       the $gp register, and all text references are PC relative.  This
       is used on some embedded systems.  */
!   EMBEDDED_PIC,
!   /* Generate QNX PIC code for use on the MIPS, similar to the SVR4
!      code but the regular GP register is not used. Instead, we do all
!      references to the GOT through $23, and calculate our own adress in
!      every function. */
!   QNX_PIC
  };
+ 
+ /* Macro to define the GOT pointer register */
+ //#if defined (__QNXTARGET__)
+ #if 1
+ #define GOT_REG 23
+ #else
+ #define GOT_REG GP
+ #endif
+ 
+ /* Macro to get rid of some of the nops.. */
+ #define NOP_NEEDED ((mips_pic != QNX_PIC) || (mips_opts.isa < 2))
  
  extern enum mips_pic_level mips_pic;
  
Index: include/elf/mips.h
===================================================================
RCS file: /cvs/src/src/include/elf/mips.h,v
retrieving revision 1.21
diff -c -3 -p -r1.21 mips.h
*** include/elf/mips.h	30 Sep 2003 16:17:14 -0000	1.21
--- include/elf/mips.h	6 Nov 2003 22:38:22 -0000
*************** START_RELOC_NUMBERS (elf_mips_reloc_type
*** 76,81 ****
--- 76,83 ----
    /* 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)
    /* These are GNU extensions to handle embedded-pic.  */
    RELOC_NUMBER (R_MIPS_PC32, 248)
    RELOC_NUMBER (R_MIPS_PC64, 249)
Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.145
diff -c -3 -p -r1.145 Makefile.am
*** ld/Makefile.am	30 Oct 2003 09:47:14 -0000	1.145
--- ld/Makefile.am	6 Nov 2003 22:38:22 -0000
*************** ALL_EMULATIONS = \
*** 150,155 ****
--- 150,156 ----
  	eelf32_sparc.o \
  	eelf32b4300.o \
  	eelf32bmip.o \
+ 	eelf32bmipnto.o \
  	eelf32bmipn32.o \
  	eelf32btsmip.o \
  	eelf32btsmipn32.o \
*************** ALL_EMULATIONS = \
*** 165,170 ****
--- 166,172 ----
  	eelf32iq10.o \
  	eelf32l4300.o \
  	eelf32lmip.o \
+ 	eelf32lmipnto.o \
  	eelf32lppc.o \
  	eelf32lppcnto.o \
  	eelf32lppcsim.o \
*************** eelf32lmip.c: $(srcdir)/emulparams/elf32
*** 663,668 ****
--- 665,676 ----
    $(srcdir)/emulparams/elf32bmip.sh $(srcdir)/emultempl/mipself.em \
    $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32lmip "$(tdir_elf32lmip)"
+ 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)"
  eelf32mipswindiss.c: $(srcdir)/emulparams/elf32mipswindiss.sh \
    $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32mipswindiss "$(tdir_elf32mipswindiss)"
Index: ld/Makefile.in
===================================================================
RCS file: /cvs/src/src/ld/Makefile.in,v
retrieving revision 1.157
diff -c -3 -p -r1.157 Makefile.in
*** ld/Makefile.in	30 Oct 2003 09:56:26 -0000	1.157
--- ld/Makefile.in	6 Nov 2003 22:38:23 -0000
*************** ALL_EMULATIONS = \
*** 264,269 ****
--- 264,270 ----
  	eelf32_sparc.o \
  	eelf32b4300.o \
  	eelf32bmip.o \
+ 	eelf32bmipnto.o \
  	eelf32bmipn32.o \
  	eelf32btsmip.o \
  	eelf32btsmipn32.o \
*************** ALL_EMULATIONS = \
*** 279,284 ****
--- 280,286 ----
  	eelf32iq10.o \
  	eelf32l4300.o \
  	eelf32lmip.o \
+ 	eelf32lmipnto.o \
  	eelf32lppc.o \
  	eelf32lppcnto.o \
  	eelf32lppcsim.o \
*************** eelf32lmip.c: $(srcdir)/emulparams/elf32
*** 1389,1394 ****
--- 1391,1402 ----
    $(srcdir)/emulparams/elf32bmip.sh $(srcdir)/emultempl/mipself.em \
    $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32lmip "$(tdir_elf32lmip)"
+ 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)"
  eelf32mipswindiss.c: $(srcdir)/emulparams/elf32mipswindiss.sh \
    $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
  	${GENSCRIPTS} elf32mipswindiss "$(tdir_elf32mipswindiss)"
Index: ld/configure.tgt
===================================================================
RCS file: /cvs/src/src/ld/configure.tgt,v
retrieving revision 1.140
diff -c -3 -p -r1.140 configure.tgt
*** ld/configure.tgt	30 Oct 2003 09:47:14 -0000	1.140
--- ld/configure.tgt	6 Nov 2003 22:38:23 -0000
*************** mips*el-*-elf*)		targ_emul=elf32elmip ;;
*** 420,425 ****
--- 420,431 ----
  mips*-*-elf*)		targ_emul=elf32ebmip ;;
  mips*el-*-rtems*)	targ_emul=elf32elmip ;;
  mips*-*-rtems*)		targ_emul=elf32ebmip ;;
+ mips*el-*-nto*)         targ_emul=elf32lmipnto
+                         targ_extra_emuls="elf32bmipnto" ;;
+ mips*eb-*-nto*)         targ_emul=elf32bmipnto
+                         targ_extra_emuls="elf32lmipnto" ;;
+ mips*-*-nto*)           targ_emul=elf32lmipnto
+                         targ_extra_emuls="elf32bmipnto" ;;
  mips*el-*-vxworks*)	targ_emul=elf32elmip ;;
  mips*-*-vxworks*)	targ_emul=elf32ebmip
  		        targ_extra_emuls="elf32elmip" ;;


? ld/emulparams/elf32bmipnto.sh
===================================================================
OUTPUT_FORMAT="elf32-bigmips"
. ${srcdir}/emulparams/elf32mipnto.sh

? ld/emulparams/elf32lmipnto.sh
===================================================================
OUTPUT_FORMAT="elf32-littlemips"
. ${srcdir}/emulparams/elf32mipnto.sh

? ld/emulparams/elf32mipnto.sh
===================================================================
SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-bigmips"
BIG_OUTPUT_FORMAT="elf32-bigmips"
LITTLE_OUTPUT_FORMAT="elf32-littlemips"
TEXT_START_ADDR=0x08020000
MAXPAGESIZE=0x1000
NONPAGED_TEXT_START_ADDR=0x08020000
#SHLIB_TEXT_START_ADDR=0x78200000
TEXT_DYNAMIC=
INITIAL_READONLY_SECTIONS='.reginfo : { *(.reginfo) }'
OTHER_TEXT_SECTIONS='*(.mips16.fn.*) *(.mips16.call.*)'
OTHER_GOT_SYMBOLS='
  _gp = ALIGN(16) + 0x7ff0;
'
OTHER_GOT_SECTIONS='
  .lit8 : { *(.lit8) }
  .lit4 : { *(.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


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