daily update
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
index 63640f1baf18e310e52c6a1b990f49fcd9b2605b..473e890663f450eb4355417bc1d6cf04ca2454db 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,7 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #include "sysdep.h"
 #include "bfd.h"
@@ -32,12 +33,16 @@ struct cie
   unsigned int length;
   unsigned int hash;
   unsigned char version;
+  unsigned char local_personality;
   char augmentation[20];
   bfd_vma code_align;
   bfd_signed_vma data_align;
   bfd_vma ra_column;
   bfd_vma augmentation_size;
-  struct elf_link_hash_entry *personality;
+  union {
+    struct elf_link_hash_entry *h;
+    bfd_vma val;
+  } personality;
   asection *output_sec;
   struct eh_cie_fde *cie_inf;
   unsigned char per_encoding;
@@ -216,13 +221,15 @@ cie_eq (const void *e1, const void *e2)
   if (c1->hash == c2->hash
       && c1->length == c2->length
       && c1->version == c2->version
+      && c1->local_personality == c2->local_personality
       && strcmp (c1->augmentation, c2->augmentation) == 0
       && strcmp (c1->augmentation, "eh") != 0
       && c1->code_align == c2->code_align
       && c1->data_align == c2->data_align
       && c1->ra_column == c2->ra_column
       && c1->augmentation_size == c2->augmentation_size
-      && c1->personality == c2->personality
+      && memcmp (&c1->personality, &c2->personality,
+                sizeof (c1->personality)) == 0
       && c1->output_sec == c2->output_sec
       && c1->per_encoding == c2->per_encoding
       && c1->lsda_encoding == c2->lsda_encoding
@@ -670,8 +677,7 @@ _bfd_elf_discard_section_eh_frame
                          REQUIRE (skip_bytes (&buf, end, length));
                        }
                      ENSURE_NO_RELOCS (buf);
-                     /* Ensure we have a reloc here, against
-                        a global symbol.  */
+                     /* Ensure we have a reloc here.  */
                      if (GET_RELOC (buf) != NULL)
                        {
                          unsigned long r_symndx;
@@ -682,7 +688,9 @@ _bfd_elf_discard_section_eh_frame
                          else
 #endif
                            r_symndx = ELF32_R_SYM (cookie->rel->r_info);
-                         if (r_symndx >= cookie->locsymcount)
+                         if (r_symndx >= cookie->locsymcount
+                             || ELF_ST_BIND (cookie->locsyms[r_symndx]
+                                             .st_info) != STB_LOCAL)
                            {
                              struct elf_link_hash_entry *h;
 
@@ -694,15 +702,39 @@ _bfd_elf_discard_section_eh_frame
                                h = (struct elf_link_hash_entry *)
                                    h->root.u.i.link;
 
-                             cie->personality = h;
+                             cie->personality.h = h;
                            }
+                         else
+                           {
+                             Elf_Internal_Sym *sym;
+                             asection *sym_sec;
+                             bfd_vma val;
+
+                             sym = &cookie->locsyms[r_symndx];
+                             sym_sec = (bfd_section_from_elf_index
+                                        (abfd, sym->st_shndx));
+                             if (sym_sec != NULL)
+                               {
+                                 if (sym_sec->kept_section != NULL)
+                                   sym_sec = sym_sec->kept_section;
+                                 if (sym_sec->output_section != NULL)
+                                   {
+                                     val = (sym->st_value
+                                            + sym_sec->output_offset
+                                            + sym_sec->output_section->vma);
+                                     cie->personality.val = val;
+                                     cie->local_personality = 1;
+                                   }
+                               }
+                           }
+
                          /* Cope with MIPS-style composite relocations.  */
                          do
                            cookie->rel++;
                          while (GET_RELOC (buf) != NULL);
                        }
                      REQUIRE (skip_bytes (&buf, end, per_width));
-                     REQUIRE (cie->personality);
+                     REQUIRE (cie->local_personality || cie->personality.h);
                    }
                    break;
                  default:
@@ -921,7 +953,7 @@ _bfd_elf_discard_section_eh_frame
       {
        if (!ent->cie)
          {
-           ecie = ecies + (unsigned long) ent->cie_inf;
+           ecie = ecies + (bfd_hostptr_t) ent->cie_inf;
            ent->cie_inf = ecie->cie.cie_inf;
          }
        ent->new_offset = offset;
@@ -1447,7 +1479,7 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
 
   /* We don't align the section to its section alignment since the
      runtime library only expects all CIE/FDE records aligned at
-     the pointer size. _bfd_elf_discard_section_eh_frame should 
+     the pointer size. _bfd_elf_discard_section_eh_frame should
      have padded CIE/FDE records to multiple of pointer size with
      size_of_output_cie_fde.  */
   if ((sec->size % ptr_size) != 0)
This page took 0.024593 seconds and 4 git commands to generate.