* addr2line.c (slurp_symtab): If canonicalization reveals that
[binutils-gdb.git] / bfd / elf32-ppc.c
index 4df92eeefc66a3da9156f43099ac532105f4fa68..c05f2f01a9fb48e91e68a55ba067c6cfb103e2f5 100644 (file)
@@ -37,6 +37,7 @@
 #include "elf32-ppc.h"
 #include "elf-vxworks.h"
 #include "dwarf2.h"
+#include "elf-linux-psinfo.h"
 
 typedef enum split16_format_type
 {
@@ -1415,7 +1416,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0,                     /* src_mask */
         0xff,                  /* dst_mask */
         TRUE),                 /* pcrel_offset */
-        
+
   /* A relative 15 bit branch.  */
   HOWTO (R_PPC_VLE_REL15,      /* type */
         1,                     /* rightshift */
@@ -1431,7 +1432,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0xfe,                  /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
-  /* A relative 24 bit branch.  */ 
+  /* A relative 24 bit branch.  */
   HOWTO (R_PPC_VLE_REL24,      /* type */
         1,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
@@ -1451,14 +1452,14 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */  /* FIXME: Does this apply to split relocs? */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc,  /* special_function */
         "R_PPC_VLE_LO16A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* The 16 LSBS in split16d format.  */
@@ -1488,7 +1489,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_HI16A",             /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 split16d format.  */
@@ -1518,7 +1519,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_HA16A",             /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (High Adjusted) in split16d format.  */
@@ -1578,7 +1579,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_LO16A",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16d format.  */
@@ -1609,7 +1610,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_HI16A",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
@@ -1639,7 +1640,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_SDAREL_HA16A",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f00fff,             /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
@@ -1777,6 +1778,58 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
 };
+
+/* External 32-bit PPC structure for PRPSINFO.  This structure is
+   ABI-defined, thus we choose to use char arrays here in order to
+   avoid dealing with different types in different architectures.
+
+   The PPC 32-bit structure uses int for `pr_uid' and `pr_gid' while
+   most non-PPC architectures use `short int'.
+
+   This structure will ultimately be written in the corefile's note
+   section, as the PRPSINFO.  */
+
+struct elf_external_ppc_linux_prpsinfo32
+  {
+    char pr_state;                     /* Numeric process state.  */
+    char pr_sname;                     /* Char for pr_state.  */
+    char pr_zomb;                      /* Zombie.  */
+    char pr_nice;                      /* Nice val.  */
+    char pr_flag[4];                   /* Flags.  */
+    char pr_uid[4];
+    char pr_gid[4];
+    char pr_pid[4];
+    char pr_ppid[4];
+    char pr_pgrp[4];
+    char pr_sid[4];
+    char pr_fname[16];                 /* Filename of executable.  */
+    char pr_psargs[80];                        /* Initial part of arg list.  */
+  };
+
+/* Helper macro to swap (properly handling endianess) things from the
+   `elf_internal_prpsinfo' structure to the `elf_external_ppc_prpsinfo32'
+   structure.
+
+   Note that FROM should be a pointer, and TO should be the explicit type.  */
+
+#define PPC_LINUX_PRPSINFO32_SWAP_FIELDS(abfd, from, to)             \
+  do                                                                 \
+    {                                                                \
+      H_PUT_8 (abfd, from->pr_state, &to.pr_state);                  \
+      H_PUT_8 (abfd, from->pr_sname, &to.pr_sname);                  \
+      H_PUT_8 (abfd, from->pr_zomb, &to.pr_zomb);                    \
+      H_PUT_8 (abfd, from->pr_nice, &to.pr_nice);                    \
+      H_PUT_32 (abfd, from->pr_flag, to.pr_flag);                    \
+      H_PUT_32 (abfd, from->pr_uid, to.pr_uid);                              \
+      H_PUT_32 (abfd, from->pr_gid, to.pr_gid);                              \
+      H_PUT_32 (abfd, from->pr_pid, to.pr_pid);                              \
+      H_PUT_32 (abfd, from->pr_ppid, to.pr_ppid);                    \
+      H_PUT_32 (abfd, from->pr_pgrp, to.pr_pgrp);                    \
+      H_PUT_32 (abfd, from->pr_sid, to.pr_sid);                              \
+      strncpy (to.pr_fname, from->pr_fname, sizeof (to.pr_fname));    \
+      strncpy (to.pr_psargs, from->pr_psargs, sizeof (to.pr_psargs)); \
+    } while (0)
+
 \f
 /* Initialize the ppc_elf_howto_table, so that linear accesses can be done.  */
 
@@ -2163,10 +2216,10 @@ ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
     case 268:          /* Linux/PPC.  */
       /* pr_cursig */
-      elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+      elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
 
       /* pr_pid */
-      elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
+      elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
 
       /* pr_reg */
       offset = 72;
@@ -2189,11 +2242,11 @@ ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       return FALSE;
 
     case 128:          /* Linux/PPC elf_prpsinfo.  */
-      elf_tdata (abfd)->core_pid
+      elf_tdata (abfd)->core->pid
        = bfd_get_32 (abfd, note->descdata + 16);
-      elf_tdata (abfd)->core_program
+      elf_tdata (abfd)->core->program
        = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
-      elf_tdata (abfd)->core_command
+      elf_tdata (abfd)->core->command
        = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
     }
 
@@ -2202,7 +2255,7 @@ ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
      implementations, so strip it off if it exists.  */
 
   {
-    char *command = elf_tdata (abfd)->core_command;
+    char *command = elf_tdata (abfd)->core->command;
     int n = strlen (command);
 
     if (0 < n && command[n - 1] == ' ')
@@ -2212,6 +2265,19 @@ ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
   return TRUE;
 }
 
+char *
+elfcore_write_ppc_linux_prpsinfo32 (bfd *abfd, char *buf, int *bufsiz,
+                                     const struct elf_internal_linux_prpsinfo *prpsinfo)
+{
+  struct elf_external_ppc_linux_prpsinfo32 data;
+
+  memset (&data, 0, sizeof (data));
+  PPC_LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
+
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            "CORE", NT_PRPSINFO, &data, sizeof (data));
+}
+
 static char *
 ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...)
 {
@@ -2259,7 +2325,7 @@ ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...)
 }
 
 static flagword
-ppc_elf_lookup_section_flags (char *flag_name) 
+ppc_elf_lookup_section_flags (char *flag_name)
 {
 
   if (!strcmp (flag_name, "SHF_PPC_VLE"))
@@ -2353,7 +2419,7 @@ ppc_elf_additional_program_headers (bfd *abfd,
   return ret;
 }
 
-/* Modify the segment map for VLE executables.  */ 
+/* Modify the segment map for VLE executables.  */
 
 bfd_boolean
 ppc_elf_modify_segment_map (bfd *abfd,
@@ -2370,7 +2436,7 @@ ppc_elf_modify_segment_map (bfd *abfd,
      If we find that case, we split the segment.
      We maintain the original output section order.  */
 
-  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+  for (m = elf_seg_map (abfd); m != NULL; m = m->next)
     {
       if (m->count == 0)
        continue;
@@ -3413,7 +3479,7 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
   /* If we were called to copy over info for a weak sym, that's all.
      You might think dyn_relocs need not be copied over;  After all,
      both syms will be dynamic or both non-dynamic so we're just
-     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS 
+     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS
      code in ppc_elf_adjust_dynamic_symbol needs to check for
      dyn_relocs in read-only sections, and it does so on what is the
      DIR sym here.  */
@@ -7406,7 +7472,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        {
          if (got2 != NULL
              && r_type == R_PPC_PLTREL24
-             && rel->r_addend >= 32768)
+             && rel->r_addend != 0)
            {
              /* R_PPC_PLTREL24 is rather special.  If non-zero, the
                 addend specifies the GOT pointer offset within .got2.  */
@@ -8411,33 +8477,37 @@ ppc_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC_PLTREL24:
-         if (h == NULL || ifunc != NULL)
-           break;
-         /* Relocation is to the entry for this symbol in the
-            procedure linkage table.  */
-         {
-           struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
-                                                 info->shared ? addend : 0);
-           addend = 0;
-           if (ent == NULL
-               || htab->plt == NULL)
-             {
-               /* We didn't make a PLT entry for this symbol.  This
-                  happens when statically linking PIC code, or when
-                  using -Bsymbolic.  */
-               break;
-             }
+         if (h != NULL && ifunc == NULL)
+           {
+             struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
+                                                   info->shared ? addend : 0);
+             if (ent == NULL
+                 || htab->plt == NULL)
+               {
+                 /* We didn't make a PLT entry for this symbol.  This
+                    happens when statically linking PIC code, or when
+                    using -Bsymbolic.  */
+               }
+             else
+               {
+                 /* Relocation is to the entry for this symbol in the
+                    procedure linkage table.  */
+                 unresolved_reloc = FALSE;
+                 if (htab->plt_type == PLT_NEW)
+                   relocation = (htab->glink->output_section->vma
+                                 + htab->glink->output_offset
+                                 + ent->glink_offset);
+                 else
+                   relocation = (htab->plt->output_section->vma
+                                 + htab->plt->output_offset
+                                 + ent->plt.offset);
+               }
+           }
 
-           unresolved_reloc = FALSE;
-           if (htab->plt_type == PLT_NEW)
-             relocation = (htab->glink->output_section->vma
-                           + htab->glink->output_offset
-                           + ent->glink_offset);
-           else
-             relocation = (htab->plt->output_section->vma
-                           + htab->plt->output_offset
-                           + ent->plt.offset);
-         }
+         /* R_PPC_PLTREL24 is rather special.  If non-zero, the
+            addend specifies the GOT pointer offset within .got2.
+            Don't apply it to the relocation field.  */
+         addend = 0;
          break;
 
          /* Relocate against _SDA_BASE_.  */