OSDN Git Service

2002-02-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
authorlaw <law>
Tue, 5 Mar 2002 17:55:53 +0000 (17:55 +0000)
committerlaw <law>
Tue, 5 Mar 2002 17:55:53 +0000 (17:55 +0000)
* bfd/elf-hppa.h (elf_hppa_is_dynamic_loader_symbol): New function.
(elf_hppa_relocate_section): Ignore undefined dynamic loader symbols.
(elf_hppa_final_link_relocate): Correct relocations for indirect
references to local data through the DLT.  Fix .opd creation for
local symbols using R_PARISC_LTOFF_FPTR32 and R_PARISC_FPTR64
relocations.  Use e_lsel selector for R_PARISC_DLTIND21L,
R_PARISC_LTOFF_FPTR21L and R_PARISC_LTOFF_TP21L as per
"Processor-Specific ELF for PA_RISC, Version 1.43" document.
Similarly, use e_rsel for DLT and LTOFF 'R' relocations.
* bfd/elf32-hppa.c (final_link_relocate): Revise relocation selectors
as per "Processor-Specific ELF for PA_RISC, Version 1.43" document.

bfd/ChangeLog
bfd/elf-hppa.h
bfd/elf32-hppa.c

index a53bcbc..4d55723 100644 (file)
@@ -1,3 +1,17 @@
+2002-03-05  John David Anglin  <dave@hiauly1.hia.nrc.ca>
+
+       * elf-hppa.h (elf_hppa_is_dynamic_loader_symbol): New function.
+       (elf_hppa_relocate_section): Ignore undefined dynamic loader symbols.
+       (elf_hppa_final_link_relocate): Correct relocations for indirect
+       references to local data through the DLT.  Fix .opd creation for
+       local symbols using R_PARISC_LTOFF_FPTR32 and R_PARISC_FPTR64
+       relocations.  Use e_lsel selector for R_PARISC_DLTIND21L,
+       R_PARISC_LTOFF_FPTR21L and R_PARISC_LTOFF_TP21L as per
+       "Processor-Specific ELF for PA_RISC, Version 1.43" document.
+       Similarly, use e_rsel for DLT and LTOFF 'R' relocations.
+       * elf32-hppa.c (final_link_relocate): Revise relocation selectors
+       as per "Processor-Specific ELF for PA_RISC, Version 1.43" document.
+
 2002-03-05  Jakub Jelinek  <jakub@redhat.com>
 
        * merge.c (_bfd_merge_sections): Don't segfault if there
index a98c2b0..8e477bd 100644 (file)
@@ -75,6 +75,9 @@ static boolean elf_hppa_unmark_useless_dynamic_symbols
 static boolean elf_hppa_remark_useless_dynamic_symbols
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
+static boolean elf_hppa_is_dynamic_loader_symbol
+  PARAMS ((const char *));
+
 static void elf_hppa_record_segment_addrs
   PARAMS ((bfd *, asection *, PTR));
 
@@ -1136,6 +1139,23 @@ elf_hppa_remark_useless_dynamic_symbols (h, data)
   return true;
 }
 
+static boolean
+elf_hppa_is_dynamic_loader_symbol (name)
+     const char * name;
+{
+  return (! strcmp (name, "__CPU_REVISION")
+         || ! strcmp (name, "__CPU_KEYBITS_1")
+         || ! strcmp (name, "__SYSTEM_ID_D")
+         || ! strcmp (name, "__FPU_MODEL")
+         || ! strcmp (name, "__FPU_REVISION")
+         || ! strcmp (name, "__ARGC")
+         || ! strcmp (name, "__ARGV")
+         || ! strcmp (name, "__ENVP")
+         || ! strcmp (name, "__TLS_SIZE_D")
+         || ! strcmp (name, "__LOAD_INFO")
+         || ! strcmp (name, "__systab"));
+}
+
 /* Record the lowest address for the data and text segments.  */
 static void
 elf_hppa_record_segment_addrs (abfd, section, data)
@@ -1419,11 +1439,17 @@ elf_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
            relocation = 0;
          else
            {
-             if (!((*info->callbacks->undefined_symbol)
-                   (info, h->root.root.string, input_bfd,
-                    input_section, rel->r_offset, true)))
-               return false;
-             break;
+             /* Ignore dynamic loader defined symbols.  */
+             if (elf_hppa_is_dynamic_loader_symbol (h->root.root.string))
+               relocation = 0;
+             else
+               {
+                 if (!((*info->callbacks->undefined_symbol)
+                       (info, h->root.root.string, input_bfd,
+                        input_section, rel->r_offset, true)))
+                   return false;
+                 break;
+               }
            }
        }
 
@@ -1620,11 +1646,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
           a local function which had its address taken.  */
        if (dyn_h->h == NULL)
          {
-           bfd_put_64 (hppa_info->dlt_sec->owner,
-                       value,
-                       hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
-
-           /* Now handle .opd creation if needed.  */
+           /* Now do .opd creation if needed.  */
            if (r_type == R_PARISC_LTOFF_FPTR14R
                || r_type == R_PARISC_LTOFF_FPTR14DR
                || r_type == R_PARISC_LTOFF_FPTR14WR
@@ -1638,7 +1660,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                        0, 16);
 
                /* The next word is the address of the function.  */
-               bfd_put_64 (hppa_info->opd_sec->owner, value,
+               bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
                            (hppa_info->opd_sec->contents
                             + dyn_h->opd_offset + 16));
 
@@ -1648,7 +1670,17 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                bfd_put_64 (hppa_info->opd_sec->owner, value,
                            (hppa_info->opd_sec->contents
                             + dyn_h->opd_offset + 24));
+
+               /* The DLT value is the address of the .opd entry.  */
+               value = (dyn_h->opd_offset
+                        + hppa_info->opd_sec->output_offset
+                        + hppa_info->opd_sec->output_section->vma);
+               addend = 0;
              }
+
+           bfd_put_64 (hppa_info->dlt_sec->owner,
+                       value + addend,
+                       hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
          }
 
        /* We want the value of the DLT offset for this symbol, not
@@ -1666,7 +1698,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
        if (r_type == R_PARISC_DLTIND21L
            || r_type == R_PARISC_LTOFF_FPTR21L
            || r_type == R_PARISC_LTOFF_TP21L)
-         value = hppa_field_adjust (value, addend, e_lrsel);
+         value = hppa_field_adjust (value, 0, e_lsel);
        else if (r_type == R_PARISC_DLTIND14F
                 || r_type == R_PARISC_LTOFF_FPTR16F
                 || r_type == R_PARISC_LTOFF_FPTR16WF
@@ -1677,9 +1709,9 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                 || r_type == R_PARISC_LTOFF_TP16F
                 || r_type == R_PARISC_LTOFF_TP16WF
                 || r_type == R_PARISC_LTOFF_TP16DF)
-         value = hppa_field_adjust (value, addend, e_fsel);
+         value = hppa_field_adjust (value, 0, e_fsel);
        else
-         value = hppa_field_adjust (value, addend, e_rrsel);
+         value = hppa_field_adjust (value, 0, e_rsel);
 
        insn = elf_hppa_relocate_insn (insn, (int) value, r_type);
        break;
@@ -1804,7 +1836,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
            memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
 
            /* The next word is the address of the function.  */
-           bfd_put_64 (hppa_info->opd_sec->owner, value,
+           bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
                        (hppa_info->opd_sec->contents
                         + dyn_h->opd_offset + 16));
 
@@ -1813,6 +1845,15 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                      (hppa_info->opd_sec->output_section->owner);
            bfd_put_64 (hppa_info->opd_sec->owner, value,
                        hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
+
+           /* The DLT value is the address of the .opd entry.  */
+           value = (dyn_h->opd_offset
+                    + hppa_info->opd_sec->output_offset
+                    + hppa_info->opd_sec->output_section->vma);
+
+           bfd_put_64 (hppa_info->dlt_sec->owner,
+                       value,
+                       hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
          }
 
        /* We want the value of the DLT offset for this symbol, not
@@ -1838,7 +1879,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
            memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
 
            /* The next word is the address of the function.  */
-           bfd_put_64 (hppa_info->opd_sec->owner, value,
+           bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
                        (hppa_info->opd_sec->contents
                         + dyn_h->opd_offset + 16));
 
@@ -1847,6 +1888,15 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                      (hppa_info->opd_sec->output_section->owner);
            bfd_put_64 (hppa_info->opd_sec->owner, value,
                        hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
+
+           /* The DLT value is the address of the .opd entry.  */
+           value = (dyn_h->opd_offset
+                    + hppa_info->opd_sec->output_offset
+                    + hppa_info->opd_sec->output_section->vma);
+
+           bfd_put_64 (hppa_info->dlt_sec->owner,
+                       value,
+                       hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
          }
 
        /* We want the value of the DLT offset for this symbol, not
@@ -1938,7 +1988,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
            memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
 
            /* The next word is the address of the function.  */
-           bfd_put_64 (hppa_info->opd_sec->owner, value,
+           bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
                        (hppa_info->opd_sec->contents
                         + dyn_h->opd_offset + 16));
 
@@ -1955,7 +2005,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
                 + hppa_info->opd_sec->output_offset
                 + hppa_info->opd_sec->output_section->vma);
 
-       bfd_put_64 (input_bfd, value + addend, hit_data);
+       bfd_put_64 (input_bfd, value, hit_data);
        return bfd_reloc_ok;
       }
 
index 1c0355e..74482f3 100644 (file)
@@ -3471,21 +3471,27 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h)
       r_field = e_fsel;
       break;
 
-    case R_PARISC_DIR21L:
+    case R_PARISC_DLTIND21L:
     case R_PARISC_PCREL21L:
-    case R_PARISC_DPREL21L:
     case R_PARISC_PLABEL21L:
-    case R_PARISC_DLTIND21L:
+      r_field = e_lsel;
+      break;
+
+    case R_PARISC_DIR21L:
+    case R_PARISC_DPREL21L:
       r_field = e_lrsel;
       break;
 
-    case R_PARISC_DIR17R:
     case R_PARISC_PCREL17R:
-    case R_PARISC_DIR14R:
     case R_PARISC_PCREL14R:
-    case R_PARISC_DPREL14R:
     case R_PARISC_PLABEL14R:
     case R_PARISC_DLTIND14R:
+      r_field = e_rsel;
+      break;
+
+    case R_PARISC_DIR17R:
+    case R_PARISC_DIR14R:
+    case R_PARISC_DPREL14R:
       r_field = e_rrsel;
       break;