* fbsd-proc.c: Include "regcache.h", "regset.h" and
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
index c71129e694fbd17195935c2b2611f65a049abe22..6dfd01ca828db103908b35b644608018481dcf5c 100644 (file)
@@ -1,5 +1,5 @@
 /* .eh_frame section optimization.
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Written by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -372,6 +372,9 @@ _bfd_elf_discard_section_eh_frame
                 all FDEs.  Also, it can be removed if we have removed
                 all FDEs using it.  */
              if ((!info->relocatable
+                  && hdr_info->last_cie_sec
+                  && (sec->output_section
+                      == hdr_info->last_cie_sec->output_section)
                   && cie_compare (&cie, &hdr_info->last_cie) == 0)
                  || cie_usage_count == 0)
                {
@@ -407,7 +410,7 @@ _bfd_elf_discard_section_eh_frame
          cie.version = *buf++;
 
          /* Cannot handle unknown versions.  */
-         if (cie.version != 1)
+         if (cie.version != 1 && cie.version != 3)
            goto free_no_table;
          if (strlen (buf) > sizeof (cie.augmentation) - 1)
            goto free_no_table;
@@ -426,12 +429,10 @@ _bfd_elf_discard_section_eh_frame
            }
          read_uleb128 (cie.code_align, buf);
          read_sleb128 (cie.data_align, buf);
-         /* Note - in DWARF2 the return address column is an unsigned byte.
-            In DWARF3 it is a ULEB128.  We are following DWARF3.  For most
-            ports this will not matter as the value will be less than 128.
-            For the others (eg FRV, SH, MMIX, IA64) they need a fixed GCC
-            which conforms to the DWARF3 standard.  */
-         read_uleb128 (cie.ra_column, buf);
+         if (cie.version == 1)
+           cie.ra_column = *buf++;
+         else
+           read_uleb128 (cie.ra_column, buf);
          ENSURE_NO_RELOCS (buf);
          cie.lsda_encoding = DW_EH_PE_omit;
          cie.fde_encoding = DW_EH_PE_omit;
@@ -515,10 +516,16 @@ _bfd_elf_discard_section_eh_frame
          /* For shared libraries, try to get rid of as many RELATIVE relocs
             as possible.  */
           if (info->shared
+             && (get_elf_backend_data (abfd)
+                 ->elf_backend_can_make_relative_eh_frame
+                 (abfd, info, sec))
              && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
            cie.make_relative = 1;
 
          if (info->shared
+             && (get_elf_backend_data (abfd)
+                 ->elf_backend_can_make_lsda_relative_eh_frame
+                 (abfd, info, sec))
              && (cie.lsda_encoding & 0xf0) == DW_EH_PE_absptr)
            cie.make_lsda_relative = 1;
 
@@ -1026,6 +1033,42 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
                                           and 3xDW_CFA_nop as pad  */
       p += 16;
     }
+  else
+    {
+      unsigned int alignment = 1 << sec->alignment_power;
+      unsigned int pad = sec->_cooked_size % alignment;
+
+      /* Don't pad beyond the raw size of the output section. It
+        can happen at the last input section.  */
+      if (pad
+         && ((sec->output_offset + sec->_cooked_size + pad)
+             <= sec->output_section->_raw_size))
+       {
+         /* Find the last CIE/FDE.  */
+         for (i = sec_info->count - 1; i > 0; i--)
+           if (! sec_info->entry[i].removed)
+             break;
+
+         /* The size of the last CIE/FDE must be at least 4.  */
+         if (sec_info->entry[i].removed
+             || sec_info->entry[i].size < 4)
+           abort ();
+
+         pad = alignment - pad;
+
+         buf = contents + sec_info->entry[i].new_offset;
+
+         /* Update length.  */
+         sec_info->entry[i].size += pad;
+         bfd_put_32 (abfd, sec_info->entry[i].size - 4, buf);
+
+         /* Pad it with DW_CFA_nop  */
+         memset (p, 0, pad);
+         p += pad;
+
+         sec->_cooked_size += pad;
+       }
+    }
 
   BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);
 
@@ -1081,6 +1124,7 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
   asection *eh_frame_sec;
   bfd_size_type size;
   bfd_boolean retval;
+  bfd_vma encoded_eh_frame;
 
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
@@ -1104,7 +1148,10 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
 
   memset (contents, 0, EH_FRAME_HDR_SIZE);
   contents[0] = 1;                             /* Version.  */
-  contents[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; /* .eh_frame offset.  */
+  contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
+    (abfd, info, eh_frame_sec, 0, sec, 4,
+     &encoded_eh_frame);                       /* .eh_frame offset.  */
+
   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
     {
       contents[2] = DW_EH_PE_udata4;           /* FDE count encoding.  */
@@ -1115,8 +1162,8 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
       contents[2] = DW_EH_PE_omit;
       contents[3] = DW_EH_PE_omit;
     }
-  bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,
-             contents + 4);
+  bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
+
   if (contents[2] != DW_EH_PE_omit)
     {
       unsigned int i;
@@ -1142,3 +1189,29 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
   free (contents);
   return retval;
 }
+
+/* Decide whether we can use a PC-relative encoding within the given
+   EH frame section.  This is the default implementation.  */
+
+bfd_boolean
+_bfd_elf_can_make_relative (bfd *input_bfd ATTRIBUTE_UNUSED,
+                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                           asection *eh_frame_section ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/* Select an encoding for the given address.  Preference is given to
+   PC-relative addressing modes.  */
+
+bfd_byte
+_bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED,
+                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                           asection *osec, bfd_vma offset,
+                           asection *loc_sec, bfd_vma loc_offset,
+                           bfd_vma *encoded)
+{
+  *encoded = osec->vma + offset -
+    (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset);
+  return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+}
This page took 0.024977 seconds and 4 git commands to generate.