Switch sources over to use the GPL version 3
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
index acc75a8569effe85132c1b8f406792a22eefb84c..88197b3385e28d13be35017300ba2023acc9214e 100644 (file)
@@ -1,12 +1,13 @@
 /* .eh_frame section optimization.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
    Written by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    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,
 
    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 "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/dwarf2.h"
@@ -31,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;
@@ -215,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
@@ -669,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;
@@ -681,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;
 
@@ -693,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:
@@ -786,6 +819,9 @@ _bfd_elf_discard_section_eh_frame
                     don't create the binary search table,
                     since it is affected by runtime relocations.  */
                  hdr_info->table = FALSE;
+                 (*info->callbacks->einfo)
+                   (_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr"
+                      " table being created.\n"), abfd, sec);
                }
              ecie->usage_count++;
              hdr_info->fde_count++;
@@ -934,6 +970,9 @@ _bfd_elf_discard_section_eh_frame
   return offset != sec->rawsize;
 
 free_no_table:
+  (*info->callbacks->einfo)
+    (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"),
+     abfd, sec);
   if (ehbuf)
     free (ehbuf);
   if (sec_info)
@@ -1440,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.02548 seconds and 4 git commands to generate.