2001-06-02 H.J. Lu <hjl@gnu.org>
[deliverable/binutils-gdb.git] / bfd / elf32-hppa.c
index e67a1ed5f67f3c67fae11c0654945560b9c0d2fe..9f46a3d5805b9dcf23655014463560b33db87b21 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for HP PA-RISC ELF files.
-   Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    Original code by
@@ -64,28 +64,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
    PIC long branch stub:
    :           b,l .+8,%r1
-   :           addil L'X - ($PIC_pcrel$0 - 4),%r1
-   :           be,n R'X - ($PIC_pcrel$0 - 8)(%sr4,%r1)
+   :           addil LR'X - ($PIC_pcrel$0 - 4),%r1
+   :           be,n RR'X - ($PIC_pcrel$0 - 8)(%sr4,%r1)
 
    Import stub to call shared library routine from normal object file
    (single sub-space version)
-   :           addil L'lt_ptr+ltoff,%dp        ; get procedure entry point
-   :           ldw R'lt_ptr+ltoff(%r1),%r21
+   :           addil LR'lt_ptr+ltoff,%dp       ; get procedure entry point
+   :           ldw RR'lt_ptr+ltoff(%r1),%r21
    :            bv %r0(%r21)
-   :           ldw R'lt_ptr+ltoff+4(%r1),%r19  ; get new dlt value.
+   :           ldw RR'lt_ptr+ltoff+4(%r1),%r19 ; get new dlt value.
 
    Import stub to call shared library routine from shared library
    (single sub-space version)
-   :           addil L'ltoff,%r19              ; get procedure entry point
-   :           ldw R'ltoff(%r1),%r21
+   :           addil LR'ltoff,%r19             ; get procedure entry point
+   :           ldw RR'ltoff(%r1),%r21
    :            bv %r0(%r21)
-   :           ldw R'ltoff+4(%r1),%r19         ; get new dlt value.
+   :           ldw RR'ltoff+4(%r1),%r19        ; get new dlt value.
 
    Import stub to call shared library routine from normal object file
    (multiple sub-space support)
-   :           addil L'lt_ptr+ltoff,%dp        ; get procedure entry point
-   :           ldw R'lt_ptr+ltoff(%r1),%r21
-   :           ldw R'lt_ptr+ltoff+4(%r1),%r19  ; get new dlt value.
+   :           addil LR'lt_ptr+ltoff,%dp       ; get procedure entry point
+   :           ldw RR'lt_ptr+ltoff(%r1),%r21
+   :           ldw RR'lt_ptr+ltoff+4(%r1),%r19 ; get new dlt value.
    :           ldsid (%r21),%r1
    :           mtsp %r1,%sr0
    :           be 0(%sr0,%r21)                 ; branch to target
@@ -93,9 +93,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
    Import stub to call shared library routine from shared library
    (multiple sub-space support)
-   :           addil L'ltoff,%r19              ; get procedure entry point
-   :           ldw R'ltoff(%r1),%r21
-   :           ldw R'ltoff+4(%r1),%r19         ; get new dlt value.
+   :           addil LR'ltoff,%r19             ; get procedure entry point
+   :           ldw RR'ltoff(%r1),%r21
+   :           ldw RR'ltoff+4(%r1),%r19        ; get new dlt value.
    :           ldsid (%r21),%r1
    :           mtsp %r1,%sr0
    :           be 0(%sr0,%r21)                 ; branch to target
@@ -225,6 +225,10 @@ struct elf32_hppa_link_hash_entry {
 #endif
 
   /* Set during a static link if we detect a function is PIC.  */
+  unsigned int maybe_pic_call:1;
+
+  /* Set if the only reason we need a .plt entry is for a non-PIC to
+     PIC function call.  */
   unsigned int pic_call:1;
 
   /* Set if this symbol is used by a plabel reloc.  */
@@ -272,6 +276,11 @@ struct elf32_hppa_link_hash_table {
   asection *sdynbss;
   asection *srelbss;
 
+  /* Used during a final link to store the base of the text and data
+     segments so that we can perform SEGREL relocations.  */
+  bfd_vma text_segment_base;
+  bfd_vma data_segment_base;
+
   /* Whether we support multiple sub-spaces for shared libs.  */
   unsigned int multi_subspace:1;
 
@@ -357,6 +366,9 @@ static boolean elf32_hppa_adjust_dynamic_symbol
 static boolean hppa_handle_PIC_calls
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
+static boolean allocate_plt_and_got
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+
 #if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
      || RELATIVE_DYNAMIC_RELOCS)
 static boolean hppa_discard_copies
@@ -369,6 +381,12 @@ static boolean clobber_millicode_symbols
 static boolean elf32_hppa_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
+static boolean elf32_hppa_final_link
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+static void hppa_record_segment_addr
+  PARAMS ((bfd *, asection *, PTR));
+
 static bfd_reloc_status_type final_link_relocate
   PARAMS ((asection *, bfd_byte *, const Elf_Internal_Rela *,
           bfd_vma, struct elf32_hppa_link_hash_table *, asection *,
@@ -378,6 +396,9 @@ static boolean elf32_hppa_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
           bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
+static int hppa_unwind_entry_compare
+  PARAMS ((const PTR, const PTR));
+
 static boolean elf32_hppa_finish_dynamic_symbol
   PARAMS ((bfd *, struct bfd_link_info *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
@@ -385,6 +406,9 @@ static boolean elf32_hppa_finish_dynamic_symbol
 static boolean elf32_hppa_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
+static void elf32_hppa_post_process_headers
+  PARAMS ((bfd *, struct bfd_link_info *));
+
 static int elf32_hppa_elf_get_symbol_type
   PARAMS ((Elf_Internal_Sym *, int));
 
@@ -473,6 +497,7 @@ hppa_link_hash_newfunc (entry, table, string)
 #if ! LONG_BRANCH_PIC_IN_SHLIB || RELATIVE_DYNAMIC_RELOCS
       ret->reloc_entries = NULL;
 #endif
+      ret->maybe_pic_call = 0;
       ret->pic_call = 0;
       ret->plabel = 0;
       ret->plt_abs = 0;
@@ -515,6 +540,8 @@ elf32_hppa_link_hash_table_create (abfd)
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->text_segment_base = (bfd_vma) -1;
+  ret->data_segment_base = (bfd_vma) -1;
   ret->multi_subspace = 0;
   ret->has_12bit_branch = 0;
   ret->has_17bit_branch = 0;
@@ -702,7 +729,7 @@ hppa_type_of_stub (input_sec, rel, hash, destination)
              && hash->elf.plt.offset != (bfd_vma) -1)
          || hash->elf.root.type == bfd_link_hash_undefweak
          || hash->elf.root.type == bfd_link_hash_undefined
-         || hash->pic_call))
+         || (hash->maybe_pic_call && !(input_sec->flags & SEC_HAS_GOT_REF))))
     {
       /* If output_section is NULL, then it's a symbol defined in a
         shared library.  We will need an import stub.  Decide between
@@ -742,7 +769,8 @@ hppa_type_of_stub (input_sec, rel, hash, destination)
 #if LONG_BRANCH_VIA_PLT
       if (hash != NULL
          && hash->elf.dynindx != -1
-         && hash->elf.plt.offset != (bfd_vma) -1)
+         && hash->elf.plt.offset != (bfd_vma) -1
+         && hash->elf.type != STT_PARISC_MILLI)
        {
          /* If we are doing a shared link and find we need a long
             branch stub, then go via the .plt if possible.  */
@@ -762,16 +790,16 @@ hppa_type_of_stub (input_sec, rel, hash, destination)
 #define BE_SR4_R1      0xe0202002      /* be,n  RR'XXX(%sr4,%r1)       */
 
 #define BL_R1          0xe8200000      /* b,l   .+8,%r1                */
-#define ADDIL_R1       0x28200000      /* addil L'XXX,%r1,%r1          */
+#define ADDIL_R1       0x28200000      /* addil LR'XXX,%r1,%r1         */
 #define DEPI_R1                0xd4201c1e      /* depi  0,31,2,%r1             */
 
-#define ADDIL_DP       0x2b600000      /* addil L'XXX,%dp,%r1          */
-#define LDW_R1_R21     0x48350000      /* ldw   R'XXX(%sr0,%r1),%r21   */
+#define ADDIL_DP       0x2b600000      /* addil LR'XXX,%dp,%r1         */
+#define LDW_R1_R21     0x48350000      /* ldw   RR'XXX(%sr0,%r1),%r21  */
 #define BV_R0_R21      0xeaa0c000      /* bv    %r0(%r21)              */
-#define LDW_R1_R19     0x48330000      /* ldw   R'XXX(%sr0,%r1),%r19   */
+#define LDW_R1_R19     0x48330000      /* ldw   RR'XXX(%sr0,%r1),%r19  */
 
-#define ADDIL_R19      0x2a600000      /* addil L'XXX,%r19,%r1         */
-#define LDW_R1_DP      0x483b0000      /* ldw   R'XXX(%sr0,%r1),%dp    */
+#define ADDIL_R19      0x2a600000      /* addil LR'XXX,%r19,%r1        */
+#define LDW_R1_DP      0x483b0000      /* ldw   RR'XXX(%sr0,%r1),%dp   */
 
 #define LDSID_R21_R1   0x02a010a1      /* ldsid (%sr0,%r21),%r1        */
 #define MTSP_R1                0x00011820      /* mtsp  %r1,%sr0               */
@@ -807,6 +835,7 @@ hppa_build_one_stub (gen_entry, in_arg)
   bfd_byte *loc;
   bfd_vma sym_value;
   bfd_vma insn;
+  bfd_vma off;
   int val;
   int size;
 
@@ -914,7 +943,12 @@ hppa_build_one_stub (gen_entry, in_arg)
 
     case hppa_stub_import:
     case hppa_stub_import_shared:
-      sym_value = (stub_entry->h->elf.plt.offset
+      off = stub_entry->h->elf.plt.offset;
+      if (off >= (bfd_vma) -2)
+       abort ();
+
+      off &= ~ (bfd_vma) 1;
+      sym_value = (off
                   + hplink->splt->output_offset
                   + hplink->splt->output_section->vma
                   - elf_gp (hplink->splt->output_section->owner));
@@ -973,8 +1007,9 @@ hppa_build_one_stub (gen_entry, in_arg)
          dynobj = hplink->root.dynobj;
          eh = (struct elf32_hppa_link_hash_entry *) stub_entry->h;
 
-         BFD_ASSERT (eh->elf.root.type == bfd_link_hash_defined
-                     || eh->elf.root.type == bfd_link_hash_defweak);
+         if (eh->elf.root.type != bfd_link_hash_defined
+             && eh->elf.root.type != bfd_link_hash_defweak)
+           abort ();
 
          value = (eh->elf.root.u.def.value
                   + eh->elf.root.u.def.section->output_offset
@@ -987,10 +1022,10 @@ hppa_build_one_stub (gen_entry, in_arg)
             <__gp>.  */
 
          bfd_put_32 (hplink->splt->owner, value,
-                     hplink->splt->contents + eh->elf.plt.offset);
+                     hplink->splt->contents + off);
          value = elf_gp (hplink->splt->output_section->owner);
          bfd_put_32 (hplink->splt->owner, value,
-                     hplink->splt->contents + eh->elf.plt.offset + 4);
+                     hplink->splt->contents + off + 4);
        }
       break;
 
@@ -1264,13 +1299,25 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
        case R_PARISC_PLABEL21L:
        case R_PARISC_PLABEL32:
          /* If the addend is non-zero, we break badly.  */
-         BFD_ASSERT (rel->r_addend == 0);
+         if (rel->r_addend != 0)
+           abort ();
 
          /* If we are creating a shared library, then we need to
             create a PLT entry for all PLABELs, because PLABELs with
             local symbols may be passed via a pointer to another
             object.  Additionally, output a dynamic relocation
-            pointing to the PLT entry.  */
+            pointing to the PLT entry.
+            For executables, the original 32-bit ABI allowed two
+            different styles of PLABELs (function pointers):  For
+            global functions, the PLABEL word points into the .plt
+            two bytes past a (function address, gp) pair, and for
+            local functions the PLABEL points directly at the
+            function.  The magic +2 for the first type allows us to
+            differentiate between the two.  As you can imagine, this
+            is a real pain when it comes to generating code to call
+            functions indirectly or to compare function pointers.
+            We avoid the mess by always pointing a PLABEL into the
+            .plt, even for local functions.  */
          need_entry = PLT_PLABEL | NEED_PLT | NEED_DYNREL;
          break;
 
@@ -1301,11 +1348,13 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                 where a symbol is forced local by versioning, or due
                 to symbolic linking, and we lose the .plt entry.  */
              need_entry = NEED_PLT | NEED_STUBREL;
+             if (h->elf.type == STT_PARISC_MILLI)
+               need_entry = NEED_STUBREL;
            }
          break;
 
        case R_PARISC_SEGBASE: /* Used to set segment base.  */
-       case R_PARISC_SEGREL32: /* Relative reloc.  */
+       case R_PARISC_SEGREL32: /* Relative reloc, used for unwind.  */
        case R_PARISC_PCREL14F: /* PC relative load/store.  */
        case R_PARISC_PCREL14R:
        case R_PARISC_PCREL17R: /* External branches.  */
@@ -1347,7 +1396,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
          /* Fall through.  */
 #endif
 
-       case R_PARISC_DIR32: /* .word, PARISC.unwind relocs.  */
+       case R_PARISC_DIR32: /* .word relocs.  */
          /* We may want to output a dynamic relocation later.  */
          need_entry = NEED_DYNREL;
          break;
@@ -1399,9 +1448,6 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                                                                  &h->elf))
                        return false;
                    }
-
-                 hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
-                 hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
                }
              else
                h->elf.got.refcount += 1;
@@ -1426,20 +1472,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                  memset (local_got_refcounts, -1, size);
                }
              if (local_got_refcounts[r_symndx] == -1)
-               {
-                 local_got_refcounts[r_symndx] = 1;
-
-                 hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
-                 if (info->shared)
-                   {
-                     /* If we are generating a shared object, we need to
-                        output a reloc so that the dynamic linker can
-                        adjust this GOT entry (because the address
-                        the shared library is loaded at is not fixed).  */
-                     hplink->srelgot->_raw_size +=
-                       sizeof (Elf32_External_Rela);
-                   }
-               }
+               local_got_refcounts[r_symndx] = 1;
              else
                local_got_refcounts[r_symndx] += 1;
            }
@@ -1741,8 +1774,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   struct elf_link_hash_entry *h;
   struct elf32_hppa_link_hash_table *hplink;
   bfd *dynobj;
-  asection *sgot;
-  asection *srelgot;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -1755,9 +1786,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   if (dynobj == NULL)
     return true;
 
-  sgot = hplink->sgot;
-  srelgot = hplink->srelgot;
-
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
     switch ((unsigned int) ELF32_R_TYPE (rel->r_info))
@@ -1770,27 +1798,12 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
          {
            h = sym_hashes[r_symndx - symtab_hdr->sh_info];
            if (h->got.refcount > 0)
-             {
-               h->got.refcount -= 1;
-               if (h->got.refcount == 0)
-                 {
-                   sgot->_raw_size -= GOT_ENTRY_SIZE;
-                   srelgot->_raw_size -= sizeof (Elf32_External_Rela);
-                 }
-             }
+             h->got.refcount -= 1;
          }
        else if (local_got_refcounts != NULL)
          {
            if (local_got_refcounts[r_symndx] > 0)
-             {
-               local_got_refcounts[r_symndx] -= 1;
-               if (local_got_refcounts[r_symndx] == 0)
-                 {
-                   sgot->_raw_size -= GOT_ENTRY_SIZE;
-                   if (info->shared)
-                     srelgot->_raw_size -= sizeof (Elf32_External_Rela);
-                 }
-             }
+             local_got_refcounts[r_symndx] -= 1;
          }
        break;
 
@@ -1839,7 +1852,8 @@ elf32_hppa_hide_symbol (info, h)
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      struct elf_link_hash_entry *h;
 {
-  h->dynindx = -1;
+  if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+    h->dynindx = -1;
   if (! ((struct elf32_hppa_link_hash_entry *) h)->plabel)
     {
       h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
@@ -1847,6 +1861,17 @@ elf32_hppa_hide_symbol (info, h)
     }
 }
 
+/* This is the condition under which elf32_hppa_finish_dynamic_symbol
+   will be called from elflink.h.  If elflink.h doesn't call our
+   finish_dynamic_symbol routine, we'll need to do something about
+   initializing any .plt and .got entries in elf32_hppa_relocate_section.  */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+  ((DYN)                                                               \
+   && ((INFO)->shared                                                  \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)     \
+   && ((H)->dynindx != -1                                              \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -1871,6 +1896,14 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
   if (h->type == STT_FUNC
       || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
+      if (!info->shared
+         && h->plt.refcount > 0
+         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+         && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0)
+       {
+         ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;
+       }
+
       if (h->plt.refcount <= 0
          || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
              && h->root.type != bfd_link_hash_defweak
@@ -1887,14 +1920,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
 
          /* As a special sop to the hppa ABI, we keep a .plt entry
             for functions in sections containing PIC code.  */
-         if (!info->shared
-             && h->plt.refcount > 0
-             && (h->root.type == bfd_link_hash_defined
-                 || h->root.type == bfd_link_hash_defweak)
-             && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0)
-           {
-             ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
-           }
+         if (((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call)
+           ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
          else
            {
              h->plt.offset = (bfd_vma) -1;
@@ -1903,19 +1930,6 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
            }
        }
 
-      /* Make an entry in the .plt section.  */
-      s = hplink->splt;
-      h->plt.offset = s->_raw_size;
-      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
-         && ((struct elf32_hppa_link_hash_entry *) h)->plabel
-         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
-       {
-         /* Add some extra space for the dynamic linker to use.  */
-         s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
-       }
-      else
-       s->_raw_size += PLT_ENTRY_SIZE;
-
       if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
        {
          /* Make sure this symbol is output as a dynamic symbol.  */
@@ -1925,13 +1939,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
              if (! bfd_elf32_link_record_dynamic_symbol (info, h))
                return false;
            }
-
-         /* We also need to make an entry in the .rela.plt section.  */
-         s = hplink->srelplt;
-         s->_raw_size += sizeof (Elf32_External_Rela);
-
-         hplink->need_plt_stub = 1;
        }
+
       return true;
     }
 
@@ -1940,8 +1949,9 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
      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);
+      if (h->weakdef->root.type != bfd_link_hash_defined
+         && h->weakdef->root.type != bfd_link_hash_defweak)
+       abort ();
       h->root.u.def.section = h->weakdef->root.u.def.section;
       h->root.u.def.value = h->weakdef->root.u.def.value;
       return true;
@@ -2022,13 +2032,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
 static boolean
 hppa_handle_PIC_calls (h, inf)
      struct elf_link_hash_entry *h;
-     PTR inf;
+     PTR inf ATTRIBUTE_UNUSED;
 {
-  struct bfd_link_info *info;
-  bfd *dynobj;
-  struct elf32_hppa_link_hash_table *hplink;
-  asection *s;
-
   if (! (h->plt.refcount > 0
         && (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak)
@@ -2040,16 +2045,70 @@ hppa_handle_PIC_calls (h, inf)
     }
 
   h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+  ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;
   ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
 
+  return true;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+   global syms.  */
+
+static boolean
+allocate_plt_and_got (h, inf)
+     struct elf_link_hash_entry *h;
+     PTR inf;
+{
+  struct bfd_link_info *info;
+  struct elf32_hppa_link_hash_table *hplink;
+  asection *s;
+
   info = (struct bfd_link_info *) inf;
   hplink = hppa_link_hash_table (info);
-  dynobj = hplink->root.dynobj;
+  if ((hplink->root.dynamic_sections_created
+       && h->plt.refcount > 0)
+      || ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
+    {
+      /* Make an entry in the .plt section.  */
+      s = hplink->splt;
+      h->plt.offset = s->_raw_size;
+      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
+         && ((struct elf32_hppa_link_hash_entry *) h)->plabel
+         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+       {
+         /* Add some extra space for the dynamic linker to use.  */
+         s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
+       }
+      else
+       s->_raw_size += PLT_ENTRY_SIZE;
+
+      if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call
+         && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+       {
+         /* We also need to make an entry in the .rela.plt section.  */
+         hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+         hplink->need_plt_stub = 1;
+       }
+    }
+  else
+    {
+      h->plt.offset = (bfd_vma) -1;
+      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+    }
 
-  /* Make an entry in the .plt section.  */
-  s = hplink->splt;
-  h->plt.offset = s->_raw_size;
-  s->_raw_size += PLT_ENTRY_SIZE;
+  if (h->got.refcount > 0)
+    {
+      boolean dyn;
+
+      s = hplink->sgot;
+      h->got.offset = s->_raw_size;
+      s->_raw_size += GOT_ENTRY_SIZE;
+      dyn = hplink->root.dynamic_sections_created;
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+       hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+    }
+  else
+    h->got.offset = (bfd_vma) -1;
 
   return true;
 }
@@ -2116,10 +2175,16 @@ clobber_millicode_symbols (h, info)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
 {
-  /* Note!  We only want to remove these from the dynamic symbol
-     table.  Therefore we do not set ELF_LINK_FORCED_LOCAL.  */
+  /* We only want to remove these from the dynamic symbol table.
+     Therefore we do not leave ELF_LINK_FORCED_LOCAL set.  */
   if (h->type == STT_PARISC_MILLI)
-    elf32_hppa_hide_symbol(info, h);
+    {
+      unsigned short oldflags = h->elf_link_hash_flags;
+      h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+      elf32_hppa_hide_symbol (info, h);
+      h->elf_link_hash_flags &= ~ELF_LINK_FORCED_LOCAL;
+      h->elf_link_hash_flags |= oldflags & ELF_LINK_FORCED_LOCAL;
+    }
   return true;
 }
 
@@ -2138,7 +2203,8 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
 
   hplink = hppa_link_hash_table (info);
   dynobj = hplink->root.dynobj;
-  BFD_ASSERT (dynobj != NULL);
+  if (dynobj == NULL)
+    abort ();
 
   if (hplink->root.dynamic_sections_created)
     {
@@ -2148,7 +2214,8 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
       if (! info->shared)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
-         BFD_ASSERT (s != NULL);
+         if (s == NULL)
+           abort ();
          s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
@@ -2158,32 +2225,54 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
                              clobber_millicode_symbols,
                              info);
 
-      /* Set up .plt offsets for local plabels.  */
+      /* Set up .got and .plt offsets for local syms.  */
       for (i = info->input_bfds; i; i = i->link_next)
        {
+         bfd_signed_vma *local_got;
+         bfd_signed_vma *end_local_got;
          bfd_signed_vma *local_plt;
          bfd_signed_vma *end_local_plt;
          bfd_size_type locsymcount;
          Elf_Internal_Shdr *symtab_hdr;
+         asection *srel;
 
-         local_plt = elf_local_got_refcounts (i);
-         if (!local_plt)
+         if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+           continue;
+
+         local_got = elf_local_got_refcounts (i);
+         if (!local_got)
            continue;
 
          symtab_hdr = &elf_tdata (i)->symtab_hdr;
          locsymcount = symtab_hdr->sh_info;
-         local_plt += locsymcount;
-         end_local_plt = local_plt + locsymcount;
+         end_local_got = local_got + locsymcount;
+         s = hplink->sgot;
+         srel = hplink->srelgot;
+         for (; local_got < end_local_got; ++local_got)
+           {
+             if (*local_got > 0)
+               {
+                 *local_got = s->_raw_size;
+                 s->_raw_size += GOT_ENTRY_SIZE;
+                 if (info->shared)
+                   srel->_raw_size += sizeof (Elf32_External_Rela);
+               }
+             else
+               *local_got = (bfd_vma) -1;
+           }
 
+         local_plt = end_local_got;
+         end_local_plt = local_plt + locsymcount;
+         s = hplink->splt;
+         srel = hplink->srelplt;
          for (; local_plt < end_local_plt; ++local_plt)
            {
              if (*local_plt > 0)
                {
-                 s = hplink->splt;
                  *local_plt = s->_raw_size;
                  s->_raw_size += PLT_ENTRY_SIZE;
                  if (info->shared)
-                   hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+                   srel->_raw_size += sizeof (Elf32_External_Rela);
                }
              else
                *local_plt = (bfd_vma) -1;
@@ -2199,15 +2288,13 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
        elf_link_hash_traverse (&hplink->root,
                                hppa_handle_PIC_calls,
                                info);
-
-      /* We may have created entries in the .rela.got section.
-        However, if we are not creating the dynamic sections, we will
-        not actually use these entries.  Reset the size of .rela.got,
-        which will cause it to get stripped from the output file
-        below.  */
-      hplink->srelgot->_raw_size = 0;
     }
 
+  /* Allocate global sym .plt and .got entries.  */
+  elf_link_hash_traverse (&hplink->root,
+                         allocate_plt_and_got,
+                         info);
+
 #if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
      || RELATIVE_DYNAMIC_RELOCS)
   /* If this is a -Bsymbolic shared link, then we need to discard all
@@ -3005,7 +3092,9 @@ elf32_hppa_set_gp (abfd, info)
   h = elf_link_hash_lookup (&hplink->root, "$global$",
                            false, false, false);
 
-  if (h != NULL && h->root.type == bfd_link_hash_defined)
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak))
     {
       gp_val = h->root.u.def.value;
       sec = h->root.u.def.section;
@@ -3048,9 +3137,19 @@ elf32_hppa_set_gp (abfd, info)
              sec = bfd_get_section_by_name (abfd, ".data");
            }
        }
+
+      if (h != NULL)
+       {
+         h->root.type = bfd_link_hash_defined;
+         h->root.u.def.value = gp_val;
+         if (sec != NULL)
+           h->root.u.def.section = sec;
+         else
+           h->root.u.def.section = bfd_abs_section_ptr;
+       }
     }
 
-  if (sec != NULL)
+  if (sec != NULL && sec->output_section != NULL)
     gp_val += sec->output_section->vma + sec->output_offset;
 
   elf_gp (abfd) = gp_val;
@@ -3095,6 +3194,75 @@ elf32_hppa_build_stubs (info)
   return true;
 }
 
+/* Perform a final link.  */
+
+static boolean
+elf32_hppa_final_link (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  asection *s;
+
+  /* Invoke the regular ELF linker to do all the work.  */
+  if (!bfd_elf32_bfd_final_link (abfd, info))
+    return false;
+
+  /* If we're producing a final executable, sort the contents of the
+     unwind section.  Magic section names, but this is much safer than
+     having elf32_hppa_relocate_section remember where SEGREL32 relocs
+     occurred.  Consider what happens if someone inept creates a
+     linker script that puts unwind information in .text.  */
+  s = bfd_get_section_by_name (abfd, ".PARISC.unwind");
+  if (s != NULL)
+    {
+      bfd_size_type size;
+      char *contents;
+
+      size = s->_raw_size;
+      contents = bfd_malloc (size);
+      if (contents == NULL)
+       return false;
+
+      if (! bfd_get_section_contents (abfd, s, contents, (file_ptr) 0, size))
+       return false;
+
+      qsort (contents, size / 16, 16, hppa_unwind_entry_compare);
+
+      if (! bfd_set_section_contents (abfd, s, contents, (file_ptr) 0, size))
+       return false;
+    }
+  return true;
+}
+
+/* Record the lowest address for the data and text segments.  */
+
+static void
+hppa_record_segment_addr (abfd, section, data)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section;
+     PTR data;
+{
+  struct elf32_hppa_link_hash_table *hplink;
+
+  hplink = (struct elf32_hppa_link_hash_table *) data;
+
+  if ((section->flags & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+    {
+      bfd_vma value = section->vma - section->filepos;
+
+      if ((section->flags & SEC_READONLY) != 0)
+       {
+         if (value < hplink->text_segment_base)
+           hplink->text_segment_base = value;
+       }
+      else
+       {
+         if (value < hplink->data_segment_base)
+           hplink->data_segment_base = value;
+       }
+    }
+}
+
 /* Perform a relocation as part of a final link.  */
 
 static bfd_reloc_status_type
@@ -3143,11 +3311,12 @@ final_link_relocate (input_section, contents, rel, value, hplink, sym_sec, h)
         find the import stub in the stub hash.  */
       if (sym_sec == NULL
          || sym_sec->output_section == NULL
-         || (h != NULL &&
-             (h->pic_call
-              || (h->elf.root.type == bfd_link_hash_defweak
-                  && h->elf.dynindx != -1
-                  && h->elf.plt.offset != (bfd_vma) -1))))
+         || (h != NULL
+             && ((h->maybe_pic_call
+                  && !(input_section->flags & SEC_HAS_GOT_REF))
+                 || (h->elf.root.type == bfd_link_hash_defweak
+                     && h->elf.dynindx != -1
+                     && h->elf.plt.offset != (bfd_vma) -1))))
        {
          stub_entry = hppa_get_stub_entry (input_section, sym_sec,
                                            h, rel, hplink);
@@ -3161,10 +3330,13 @@ final_link_relocate (input_section, contents, rel, value, hplink, sym_sec, h)
          else if (sym_sec == NULL && h != NULL
                   && h->elf.root.type == bfd_link_hash_undefweak)
            {
-             /* It's OK if undefined weak.  Make undefined weak
-                branches go nowhere.  */
+             /* It's OK if undefined weak.  Calls to undefined weak
+                symbols behave as if the "called" function
+                immediately returns.  We can thus call to a weak
+                function without first checking whether the function
+                is defined.  */
              value = location;
-             addend = 0;
+             addend = 8;
            }
          else
            return bfd_reloc_notsupported;
@@ -3220,6 +3392,13 @@ final_link_relocate (input_section, contents, rel, value, hplink, sym_sec, h)
       value -= elf_gp (input_section->output_section->owner);
       break;
 
+    case R_PARISC_SEGREL32:
+      if ((sym_sec->flags & SEC_CODE) != 0)
+       value -= hplink->text_segment_base;
+      else
+       value -= hplink->data_segment_base;
+      break;
+
     default:
       break;
     }
@@ -3462,7 +3641,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
          else if (h->elf.root.type == bfd_link_hash_undefweak)
            ;
          else if (info->shared && !info->no_undefined
-                  && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT)
+                  && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
+                  && h->elf.type != STT_PARISC_MILLI)
            {
              if (info->symbolic)
                if (!((*info->callbacks->undefined_symbol)
@@ -3493,15 +3673,14 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
          if (h != NULL)
            {
              bfd_vma off;
+             boolean dyn;
 
              off = h->elf.got.offset;
-             BFD_ASSERT (off != (bfd_vma) -1);
+             if (off == (bfd_vma) -1)
+               abort ();
 
-             if (! hplink->root.dynamic_sections_created
-                 || (info->shared
-                     && (info->symbolic || h->elf.dynindx == -1)
-                     && (h->elf.elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) != 0))
+             dyn = hplink->root.dynamic_sections_created;
+             if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
                {
                  /* This is actually a static link, or it is a
                     -Bsymbolic link and the symbol is defined
@@ -3532,10 +3711,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
              /* Local symbol case.  */
              bfd_vma off;
 
-             BFD_ASSERT (local_got_offsets != NULL
-                         && local_got_offsets[r_symndx] != (bfd_vma) -1);
-
-             off = local_got_offsets[r_symndx];
+             if (local_got_offsets == NULL
+                 || (off = local_got_offsets[r_symndx]) == (bfd_vma) -1)
+               abort ();
 
              /* The offset must always be a multiple of 4.  We use
                 the least significant bit to record whether we have
@@ -3549,10 +3727,10 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
 
                  if (info->shared)
                    {
-                     /* Output a dynamic *ABS* relocation for this
-                        GOT entry.  In this case it is relative to
-                        the base of the object because the symbol
-                        index is zero.  */
+                     /* Output a dynamic relocation for this GOT
+                        entry.  In this case it is relative to the
+                        base of the object because the symbol index
+                        is zero.  */
                      Elf_Internal_Rela outrel;
                      asection *srelgot = hplink->srelgot;
 
@@ -3579,6 +3757,15 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                         + hplink->sgot->output_section->vma);
          break;
 
+       case R_PARISC_SEGREL32:
+         /* If this is the first SEGREL relocation, then initialize
+            the segment base values.  */
+         if (hplink->text_segment_base == (bfd_vma) -1)
+           bfd_map_over_sections (output_bfd,
+                                  hppa_record_segment_addr,
+                                  hplink);
+         break;
+
        case R_PARISC_PLABEL14R:
        case R_PARISC_PLABEL21L:
        case R_PARISC_PLABEL32:
@@ -3591,6 +3778,24 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
              if (h != NULL)
                {
                  off = h->elf.plt.offset;
+                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, &h->elf))
+                   {
+                     /* In a non-shared link, adjust_dynamic_symbols
+                        isn't called for symbols forced local.  We
+                        need to write out the plt entry here.  */ 
+                     if ((off & 1) != 0)
+                       off &= ~1;
+                     else
+                       {
+                         bfd_put_32 (output_bfd,
+                                     relocation,
+                                     hplink->splt->contents + off);
+                         bfd_put_32 (output_bfd,
+                                     elf_gp (hplink->splt->output_section->owner),
+                                     hplink->splt->contents + off + 4);
+                         h->elf.plt.offset |= 1;
+                       }
+                   }
                }
              else
                {
@@ -3636,7 +3841,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                    }
                }
 
-             BFD_ASSERT (off < (bfd_vma) -2);
+             if (off >= (bfd_vma) -2 || (off & 1) != 0)
+               abort ();
 
              /* PLABELs contain function pointers.  Relocation is to
                 the entry for the function in the .plt.  The magic +2
@@ -3703,7 +3909,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                  if (name == NULL)
                    return false;
                  sreloc = bfd_get_section_by_name (dynobj, name);
-                 BFD_ASSERT (sreloc != NULL);
+                 if (sreloc == NULL)
+                   abort ();
                }
 
              outrel.r_offset = rel->r_offset;
@@ -3823,6 +4030,32 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
   return true;
 }
 
+/* Comparison function for qsort to sort unwind section during a
+   final link.  */
+
+static int
+hppa_unwind_entry_compare (a, b)
+     const PTR a;
+     const PTR b;
+{
+  const bfd_byte *ap, *bp;
+  unsigned long av, bv;
+
+  ap = (const bfd_byte *) a;
+  av = (unsigned long) ap[0] << 24;
+  av |= (unsigned long) ap[1] << 16;
+  av |= (unsigned long) ap[2] << 8;
+  av |= (unsigned long) ap[3];
+
+  bp = (const bfd_byte *) b;
+  bv = (unsigned long) bp[0] << 24;
+  bv |= (unsigned long) bp[1] << 16;
+  bv |= (unsigned long) bp[2] << 8;
+  bv |= (unsigned long) bp[3];
+
+  return av < bv ? -1 : av > bv ? 1 : 0;
+}
+
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
@@ -3843,6 +4076,9 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       bfd_vma value;
 
+      if (h->plt.offset & 1)
+       abort ();
+
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.
 
@@ -3873,8 +4109,8 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
            {
              /* To support lazy linking, the function pointer is
                 initialised to point to a special stub stored at the
-                end of the .plt.  This is only done for plt entries
-                with a non-*ABS* dynamic relocation.  */
+                end of the .plt.  This is not done for plt entries
+                with a base-relative dynamic relocation.  */
              value = (hplink->splt->output_offset
                       + hplink->splt->output_section->vma
                       + hplink->splt->_raw_size
@@ -3932,15 +4168,14 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + hplink->sgot->output_offset
                      + hplink->sgot->output_section->vma);
 
-      /* If this is a static link, or it is a -Bsymbolic link and the
-        symbol is defined locally or was forced to be local because
-        of a version file, we just want to emit a RELATIVE reloc.
-        The entry in the global offset table will already have been
-        initialized in the relocate_section function.  */
-      if (! hplink->root.dynamic_sections_created
-         || (info->shared
-             && (info->symbolic || h->dynindx == -1)
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+      /* If this is a -Bsymbolic link and the symbol is defined
+        locally or was forced to be local because of a version file,
+        we just want to emit a RELATIVE reloc.  The entry in the
+        global offset table will already have been initialized in the
+        relocate_section function.  */
+      if (info->shared
+         && (info->symbolic || h->dynindx == -1)
+         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
        {
          rel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
          rel.r_addend = (h->root.u.def.value
@@ -3949,7 +4184,8 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
        }
       else
        {
-         BFD_ASSERT((h->got.offset & 1) == 0);
+         if ((h->got.offset & 1) != 0)
+           abort ();
          bfd_put_32 (output_bfd, (bfd_vma) 0,
                      hplink->sgot->contents + h->got.offset);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_DIR32);
@@ -3970,9 +4206,10 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
-      BFD_ASSERT (h->dynindx != -1
-                 && (h->root.type == bfd_link_hash_defined
-                     || h->root.type == bfd_link_hash_defweak));
+      if (! (h->dynindx != -1
+            && (h->root.type == bfd_link_hash_defined
+                || h->root.type == bfd_link_hash_defweak)))
+       abort ();
 
       s = hplink->srelbss;
 
@@ -4018,7 +4255,8 @@ elf32_hppa_finish_dynamic_sections (output_bfd, info)
     {
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      BFD_ASSERT (sdyn != NULL);
+      if (sdyn == NULL)
+       abort ();
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
@@ -4105,6 +4343,27 @@ elf32_hppa_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 
+/* Tweak the OSABI field of the elf header.  */
+
+static void
+elf32_hppa_post_process_headers (abfd, link_info)
+     bfd *abfd;
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+{
+  Elf_Internal_Ehdr * i_ehdrp;
+
+  i_ehdrp = elf_elfheader (abfd);
+
+  if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
+    {
+      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+    }
+  else
+    {
+      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+    }
+}
+
 /* Called when writing out an object file to decide the type of a
    symbol.  */
 static int
@@ -4125,7 +4384,7 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type)
 #define elf_info_to_howto_rel               elf_hppa_info_to_howto_rel
 
 /* Stuff for the BFD linker.  */
-#define bfd_elf32_bfd_final_link            _bfd_elf32_gc_common_final_link
+#define bfd_elf32_bfd_final_link            elf32_hppa_final_link
 #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create
 #define elf_backend_add_symbol_hook         elf32_hppa_add_symbol_hook
 #define elf_backend_adjust_dynamic_symbol    elf32_hppa_adjust_dynamic_symbol
@@ -4141,6 +4400,7 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type)
 #define elf_backend_gc_sweep_hook           elf32_hppa_gc_sweep_hook
 #define elf_backend_object_p                elf32_hppa_object_p
 #define elf_backend_final_write_processing   elf_hppa_final_write_processing
+#define elf_backend_post_process_headers     elf32_hppa_post_process_headers
 #define elf_backend_get_symbol_type         elf32_hppa_elf_get_symbol_type
 
 #define elf_backend_can_gc_sections         1
@@ -4157,3 +4417,11 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type)
 #define ELF_MAXPAGESIZE                0x1000
 
 #include "elf32-target.h"
+
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM                 bfd_elf32_hppa_linux_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME                        "elf32-hppa-linux"
+
+#define INCLUDED_TARGET_FILE 1
+#include "elf32-target.h"
This page took 0.03833 seconds and 4 git commands to generate.