* elf32-sh.c (sh_elf_create_dynamic_sections): Return if dynamic
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
index 8938ecf32dc3042d7ef8a21b5ee954337cf2b40c..e422aa96a55a55ecba823fdb64d7d3f1750725b5 100644 (file)
@@ -1,22 +1,22 @@
 /* .eh_frame section optimization.
-   Copyright 2001, 2002 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
    Written by Jakub Jelinek <jakub@redhat.com>.
 
-This file is part of BFD, the Binary File Descriptor library.
+   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
-(at your option) any later version.
+   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
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -33,13 +33,13 @@ static bfd_signed_vma read_signed_leb128
 static int get_DW_EH_PE_width
   PARAMS ((int, int));
 static bfd_vma read_value
-  PARAMS ((bfd *, bfd_byte *, int));
+  PARAMS ((bfd *, bfd_byte *, int, int));
 static void write_value
   PARAMS ((bfd *, bfd_byte *, bfd_vma, int));
 static int cie_compare
   PARAMS ((struct cie *, struct cie *));
 static int vma_compare
-  PARAMS ((const PTR a, const PTR b));
+  PARAMS ((const PTR, const PTR));
 
 /* Helper function for reading uleb128 encoded data.  */
 
@@ -141,27 +141,47 @@ int get_DW_EH_PE_width (encoding, ptr_size)
   return 0;
 }
 
+#define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
+
 /* Read a width sized value from memory.  */
 
 static bfd_vma
-read_value (abfd, buf, width)
+read_value (abfd, buf, width, is_signed)
      bfd *abfd;
      bfd_byte *buf;
      int width;
+     int is_signed;
 {
   bfd_vma value;
 
   switch (width)
     {
-    case 2: value = bfd_get_16 (abfd, buf); break;
-    case 4: value = bfd_get_32 (abfd, buf); break;
-    case 8: value = bfd_get_64 (abfd, buf); break;
-    default: BFD_FAIL (); return 0;
+    case 2:
+      if (is_signed)
+       value = bfd_get_signed_16 (abfd, buf);
+      else
+       value = bfd_get_16 (abfd, buf);
+      break;
+    case 4:
+      if (is_signed)
+       value = bfd_get_signed_32 (abfd, buf);
+      else
+       value = bfd_get_32 (abfd, buf);
+      break;
+    case 8:
+      if (is_signed)
+       value = bfd_get_signed_64 (abfd, buf);
+      else
+       value = bfd_get_64 (abfd, buf);
+      break;
+    default:
+      BFD_FAIL ();
+      return 0;
     }
 
   return value;
 }
-    
+
 /* Store a width sized value to memory.  */
 
 static void
@@ -210,16 +230,16 @@ int cie_compare (c1, c2)
 
 /* This function is called for each input file before the .eh_frame
    section is relocated.  It discards duplicate CIEs and FDEs for discarded
-   functions.  The function returns true iff any entries have been
+   functions.  The function returns TRUE iff any entries have been
    deleted.  */
 
-boolean
+bfd_boolean
 _bfd_elf_discard_section_eh_frame (abfd, info, sec,
                                   reloc_symbol_deleted_p, cookie)
      bfd *abfd;
      struct bfd_link_info *info;
      asection *sec;
-     boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR));
+     bfd_boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR));
      struct elf_reloc_cookie *cookie;
 {
   bfd_byte *ehbuf = NULL, *buf;
@@ -238,7 +258,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
   if (sec->_raw_size == 0)
     {
       /* This file does not contain .eh_frame information.  */
-      return false;
+      return FALSE;
     }
 
   if ((sec->output_section != NULL
@@ -246,7 +266,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
     {
       /* At least one of the sections is being discarded from the
          link, so we should just ignore them.  */
-      return false;
+      return FALSE;
     }
 
   htab = elf_hash_table (info);
@@ -268,7 +288,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
     {
       /* Empty .eh_frame section.  */
       free (ehbuf);
-      return false;
+      return FALSE;
     }
 
   /* If .eh_frame section size doesn't fit into int, we cannot handle
@@ -383,7 +403,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
                 in which case we can remove it provided we adjust
                 all FDEs.  Also, it can be removed if we have removed
                 all FDEs using it.  */
-             if ((!info->relocateable
+             if ((!info->relocatable
                   && cie_compare (&cie, &hdr_info->last_cie) == 0)
                  || cie_usage_count == 0)
                {
@@ -578,7 +598,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
                     which we cannot turn into PC relative,
                     don't create the binary search table,
                     since it is affected by runtime relocations.  */
-                 hdr_info->table = false;
+                 hdr_info->table = FALSE;
                }
              cie_usage_count++;
              hdr_info->fde_count++;
@@ -605,7 +625,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec,
     }
 
   elf_section_data (sec)->sec_info = sec_info;
-  elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
+  sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
 
   /* Ok, now we can assign new offsets.  */
   offset = 0;
@@ -663,16 +683,16 @@ free_no_table:
     free (ehbuf);
   if (sec_info)
     free (sec_info);
-  hdr_info->table = false;
+  hdr_info->table = FALSE;
   hdr_info->last_cie.hdr.length = 0;
-  return false;
+  return FALSE;
 }
 
 /* This function is called for .eh_frame_hdr section after
    _bfd_elf_discard_section_eh_frame has been called on all .eh_frame
    input sections.  It finalizes the size of .eh_frame_hdr section.  */
 
-boolean
+bfd_boolean
 _bfd_elf_discard_section_eh_frame_hdr (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -685,7 +705,7 @@ _bfd_elf_discard_section_eh_frame_hdr (abfd, info)
   hdr_info = &htab->eh_info;
   sec = hdr_info->hdr_sec;
   if (sec == NULL)
-    return false;
+    return FALSE;
 
   sec->_cooked_size = EH_FRAME_HDR_SIZE;
   if (hdr_info->table)
@@ -694,7 +714,7 @@ _bfd_elf_discard_section_eh_frame_hdr (abfd, info)
   /* Request program headers to be recalculated.  */
   elf_tdata (abfd)->program_header_size = 0;
   elf_tdata (abfd)->eh_frame_hdr = sec;
-  return true;
+  return TRUE;
 }
 
 /* This function is called from size_dynamic_sections.
@@ -702,7 +722,7 @@ _bfd_elf_discard_section_eh_frame_hdr (abfd, info)
    because later on it is too late for calling _bfd_strip_section_from_output,
    since dynamic symbol table has been sized.  */
 
-boolean
+bfd_boolean
 _bfd_elf_maybe_strip_eh_frame_hdr (info)
      struct bfd_link_info *info;
 {
@@ -714,12 +734,12 @@ _bfd_elf_maybe_strip_eh_frame_hdr (info)
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
   if (hdr_info->hdr_sec == NULL)
-    return true;
+    return TRUE;
 
   if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
     {
       hdr_info->hdr_sec = NULL;
-      return true;
+      return TRUE;
     }
 
   abfd = NULL;
@@ -737,11 +757,11 @@ _bfd_elf_maybe_strip_eh_frame_hdr (info)
     {
       _bfd_strip_section_from_output (info, hdr_info->hdr_sec);
       hdr_info->hdr_sec = NULL;
-      return true;
+      return TRUE;
     }
 
-  hdr_info->table = true;
-  return true;
+  hdr_info->table = TRUE;
+  return TRUE;
 }
 
 /* Adjust an address in the .eh_frame section.  Given OFFSET within
@@ -758,7 +778,7 @@ _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)
   struct eh_frame_sec_info *sec_info;
   unsigned int lo, hi, mid;
 
-  if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
+  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
     return offset;
   sec_info = (struct eh_frame_sec_info *)
             elf_section_data (sec)->sec_info;
@@ -809,7 +829,7 @@ _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset)
 /* Write out .eh_frame section.  This is called with the relocated
    contents.  */
 
-boolean
+bfd_boolean
 _bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -828,7 +848,7 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
   ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
              == ELFCLASS64) ? 8 : 4;
 
-  if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
+  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
     return bfd_set_section_contents (abfd, sec->output_section,
                                     contents,
                                     (file_ptr) sec->output_offset,
@@ -925,7 +945,9 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
                      {
                        bfd_vma value;
 
-                       value = read_value (abfd, buf, per_width);
+                       value = read_value (abfd, buf, per_width,
+                                           get_DW_EH_PE_signed
+                                           (per_encoding));
                        value += (sec_info->entry[i].offset
                                  - sec_info->entry[i].new_offset);
                        write_value (abfd, buf, value, per_width);
@@ -954,14 +976,16 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
          unsigned int width;
 
          buf = contents + sec_info->entry[i].offset;
-         /* Skip length.  */   
+         /* Skip length.  */
          buf += 4;
          bfd_put_32 (abfd,
                      sec_info->entry[i].new_offset + 4 - cie_offset, buf);
          buf += 4;
          width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
                                      ptr_size);
-         address = value = read_value (abfd, buf, width);
+         address = value = read_value (abfd, buf, width,
+                                       get_DW_EH_PE_signed
+                                       (sec_info->entry[i].fde_encoding));
          if (value)
            {
              switch (sec_info->entry[i].fde_encoding & 0xf0)
@@ -1005,7 +1029,9 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
              buf += sec_info->entry[i].lsda_offset;
              width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding,
                                          ptr_size);
-             value = read_value (abfd, buf, width);
+             value = read_value (abfd, buf, width,
+                                 get_DW_EH_PE_signed
+                                 (sec_info->entry[i].lsda_encoding));
              if (value)
                {
                  if ((sec_info->entry[i].lsda_encoding & 0xf0)
@@ -1086,9 +1112,9 @@ vma_compare (a, b)
    fde_count x [encoded] initial_loc, fde
                                (array of encoded pairs containing
                                 FDE initial_location field and FDE address,
-                                sorted by increasing initial_loc)  */
+                                sorted by increasing initial_loc).  */
 
-boolean
+bfd_boolean
 _bfd_elf_write_section_eh_frame_hdr (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -1099,31 +1125,35 @@ _bfd_elf_write_section_eh_frame_hdr (abfd, info)
   bfd_byte *contents;
   asection *eh_frame_sec;
   bfd_size_type size;
+  bfd_boolean retval;
 
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
   sec = hdr_info->hdr_sec;
   if (sec == NULL)
-    return true;
+    return TRUE;
 
   size = EH_FRAME_HDR_SIZE;
   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
     size += 4 + hdr_info->fde_count * 8;
   contents = bfd_malloc (size);
   if (contents == NULL)
-    return false;
+    return FALSE;
 
   eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
   if (eh_frame_sec == NULL)
-    return false;
+    {
+      free (contents);
+      return FALSE;
+    }
 
   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[0] = 1;                             /* Version.  */
+  contents[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; /* .eh_frame offset.  */
   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
     {
-      contents[2] = DW_EH_PE_udata4;           /* FDE count encoding  */
-      contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* search table enc  */
+      contents[2] = DW_EH_PE_udata4;           /* FDE count encoding.  */
+      contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* Search table enc.  */
     }
   else
     {
@@ -1151,7 +1181,9 @@ _bfd_elf_write_section_eh_frame_hdr (abfd, info)
        }
     }
 
-  return bfd_set_section_contents (abfd, sec->output_section,
-                                  contents, (file_ptr) sec->output_offset,
-                                   sec->_cooked_size);
+  retval = bfd_set_section_contents (abfd, sec->output_section,
+                                    contents, (file_ptr) sec->output_offset,
+                                    sec->_cooked_size);
+  free (contents);
+  return retval;
 }
This page took 0.030118 seconds and 4 git commands to generate.