OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf-eh-frame.c] - Diff between revs 157 and 225

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 157 Rev 225
Line 1... Line 1...
/* .eh_frame section optimization.
/* .eh_frame section optimization.
   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Jakub Jelinek <jakub@redhat.com>.
   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.
 
 
Line 22... Line 22...
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "libbfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf/dwarf2.h"
#include "dwarf2.h"
 
 
#define EH_FRAME_HDR_SIZE 8
#define EH_FRAME_HDR_SIZE 8
 
 
struct cie
struct cie
{
{
Line 213... Line 213...
/* Return one if C1 and C2 CIEs can be merged.  */
/* Return one if C1 and C2 CIEs can be merged.  */
 
 
static int
static int
cie_eq (const void *e1, const void *e2)
cie_eq (const void *e1, const void *e2)
{
{
  const struct cie *c1 = e1;
  const struct cie *c1 = (const struct cie *) e1;
  const struct cie *c2 = e2;
  const struct cie *c2 = (const struct cie *) e2;
 
 
  if (c1->hash == c2->hash
  if (c1->hash == c2->hash
      && c1->length == c2->length
      && c1->length == c2->length
      && c1->version == c2->version
      && c1->version == c2->version
      && c1->local_personality == c2->local_personality
      && c1->local_personality == c2->local_personality
Line 244... Line 244...
}
}
 
 
static hashval_t
static hashval_t
cie_hash (const void *e)
cie_hash (const void *e)
{
{
  const struct cie *c = e;
  const struct cie *c = (const struct cie *) e;
  return c->hash;
  return c->hash;
}
}
 
 
static hashval_t
static hashval_t
cie_compute_hash (struct cie *c)
cie_compute_hash (struct cie *c)
Line 527... Line 527...
        num_cies++;
        num_cies++;
 
 
      REQUIRE (skip_bytes (&buf, end, hdr_length - 4));
      REQUIRE (skip_bytes (&buf, end, hdr_length - 4));
    }
    }
 
 
  sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
  sec_info = (struct eh_frame_sec_info *)
 
      bfd_zmalloc (sizeof (struct eh_frame_sec_info)
                          + (num_entries - 1) * sizeof (struct eh_cie_fde));
                          + (num_entries - 1) * sizeof (struct eh_cie_fde));
  REQUIRE (sec_info);
  REQUIRE (sec_info);
 
 
  /* We need to have a "struct cie" for each CIE in this section.  */
  /* We need to have a "struct cie" for each CIE in this section.  */
  local_cies = bfd_zmalloc (num_cies * sizeof (*local_cies));
  local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies));
  REQUIRE (local_cies);
  REQUIRE (local_cies);
 
 
 
  /* FIXME: octets_per_byte.  */
#define ENSURE_NO_RELOCS(buf)                           \
#define ENSURE_NO_RELOCS(buf)                           \
  REQUIRE (!(cookie->rel < cookie->relend               \
  REQUIRE (!(cookie->rel < cookie->relend               \
             && (cookie->rel->r_offset                  \
             && (cookie->rel->r_offset                  \
                 < (bfd_size_type) ((buf) - ehbuf))     \
                 < (bfd_size_type) ((buf) - ehbuf))     \
             && cookie->rel->r_info != 0))
             && cookie->rel->r_info != 0))
 
 
 
  /* FIXME: octets_per_byte.  */
#define SKIP_RELOCS(buf)                                \
#define SKIP_RELOCS(buf)                                \
  while (cookie->rel < cookie->relend                   \
  while (cookie->rel < cookie->relend                   \
         && (cookie->rel->r_offset                      \
         && (cookie->rel->r_offset                      \
             < (bfd_size_type) ((buf) - ehbuf)))        \
             < (bfd_size_type) ((buf) - ehbuf)))        \
    cookie->rel++
    cookie->rel++
 
 
 
  /* FIXME: octets_per_byte.  */
#define GET_RELOC(buf)                                  \
#define GET_RELOC(buf)                                  \
  ((cookie->rel < cookie->relend                        \
  ((cookie->rel < cookie->relend                        \
    && (cookie->rel->r_offset                           \
    && (cookie->rel->r_offset                           \
        == (bfd_size_type) ((buf) - ehbuf)))            \
        == (bfd_size_type) ((buf) - ehbuf)))            \
   ? cookie->rel : NULL)
   ? cookie->rel : NULL)
Line 764... Line 768...
          ENSURE_NO_RELOCS (buf);
          ENSURE_NO_RELOCS (buf);
          REQUIRE (GET_RELOC (buf));
          REQUIRE (GET_RELOC (buf));
 
 
          /* Chain together the FDEs for each section.  */
          /* Chain together the FDEs for each section.  */
          rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
          rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
          REQUIRE (rsec && rsec->owner == abfd);
          /* RSEC will be NULL if FDE was cleared out as it was belonging to
 
             a discarded SHT_GROUP.  */
 
          if (rsec)
 
            {
 
              REQUIRE (rsec->owner == abfd);
          this_inf->u.fde.next_for_section = elf_fde_list (rsec);
          this_inf->u.fde.next_for_section = elf_fde_list (rsec);
          elf_fde_list (rsec) = this_inf;
          elf_fde_list (rsec) = this_inf;
 
            }
 
 
          /* Skip the initial location and address range.  */
          /* Skip the initial location and address range.  */
          start = buf;
          start = buf;
          length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
          length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size);
          REQUIRE (skip_bytes (&buf, end, 2 * length));
          REQUIRE (skip_bytes (&buf, end, 2 * length));
Line 799... Line 808...
          /* Skip over the augmentation data.  */
          /* Skip over the augmentation data.  */
          REQUIRE (skip_bytes (&buf, end, length));
          REQUIRE (skip_bytes (&buf, end, length));
          insns = buf;
          insns = buf;
 
 
          buf = last_fde + 4 + hdr_length;
          buf = last_fde + 4 + hdr_length;
 
 
 
          /* For NULL RSEC (cleared FDE belonging to a discarded section)
 
             the relocations are commonly cleared.  We do not sanity check if
 
             all these relocations are cleared as (1) relocations to
 
             .gcc_except_table will remain uncleared (they will get dropped
 
             with the drop of this unused FDE) and (2) BFD already safely drops
 
             relocations of any type to .eh_frame by
 
             elf_section_ignore_discarded_relocs.
 
             TODO: The .gcc_except_table entries should be also filtered as
 
             .eh_frame entries; or GCC could rather use COMDAT for them.  */
          SKIP_RELOCS (buf);
          SKIP_RELOCS (buf);
        }
        }
 
 
      /* Try to interpret the CFA instructions and find the first
      /* Try to interpret the CFA instructions and find the first
         padding nop.  Shrink this_inf's size so that it doesn't
         padding nop.  Shrink this_inf's size so that it doesn't
Line 828... Line 847...
              || this_inf->make_relative))
              || this_inf->make_relative))
        {
        {
          unsigned int cnt;
          unsigned int cnt;
          bfd_byte *p;
          bfd_byte *p;
 
 
          this_inf->set_loc = bfd_malloc ((set_loc_count + 1)
          this_inf->set_loc = (unsigned int *)
                                          * sizeof (unsigned int));
              bfd_malloc ((set_loc_count + 1) * sizeof (unsigned int));
          REQUIRE (this_inf->set_loc);
          REQUIRE (this_inf->set_loc);
          this_inf->set_loc[0] = set_loc_count;
          this_inf->set_loc[0] = set_loc_count;
          p = insns;
          p = insns;
          cnt = 0;
          cnt = 0;
          while (p < end)
          while (p < end)
Line 894... Line 913...
static bfd_boolean
static bfd_boolean
mark_entry (struct bfd_link_info *info, asection *sec,
mark_entry (struct bfd_link_info *info, asection *sec,
            struct eh_cie_fde *ent, elf_gc_mark_hook_fn gc_mark_hook,
            struct eh_cie_fde *ent, elf_gc_mark_hook_fn gc_mark_hook,
            struct elf_reloc_cookie *cookie)
            struct elf_reloc_cookie *cookie)
{
{
 
  /* FIXME: octets_per_byte.  */
  for (cookie->rel = cookie->rels + ent->reloc_index;
  for (cookie->rel = cookie->rels + ent->reloc_index;
       cookie->rel < cookie->relend
       cookie->rel < cookie->relend
         && cookie->rel->r_offset < ent->offset + ent->size;
         && cookie->rel->r_offset < ent->offset + ent->size;
       cookie->rel++)
       cookie->rel++)
    if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, cookie))
    if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, cookie))
Line 1034... Line 1054...
 
 
  new_cie = (struct cie *) *loc;
  new_cie = (struct cie *) *loc;
  if (new_cie == NULL)
  if (new_cie == NULL)
    {
    {
      /* Keep CIE_INF and record it in the hash table.  */
      /* Keep CIE_INF and record it in the hash table.  */
      new_cie = malloc (sizeof (struct cie));
      new_cie = (struct cie *) malloc (sizeof (struct cie));
      if (new_cie == NULL)
      if (new_cie == NULL)
        return cie_inf;
        return cie_inf;
 
 
      memcpy (new_cie, cie, sizeof (struct cie));
      memcpy (new_cie, cie, sizeof (struct cie));
      *loc = new_cie;
      *loc = new_cie;
Line 1075... Line 1095...
  if (sec_info == NULL)
  if (sec_info == NULL)
    return FALSE;
    return FALSE;
 
 
  hdr_info = &elf_hash_table (info)->eh_info;
  hdr_info = &elf_hash_table (info)->eh_info;
  for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
  for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
    if (!ent->cie)
    if (ent->size == 4)
 
      /* There should only be one zero terminator, on the last input
 
         file supplying .eh_frame (crtend.o).  Remove any others.  */
 
      ent->removed = sec->map_head.s != NULL;
 
    else if (!ent->cie)
      {
      {
        cookie->rel = cookie->rels + ent->reloc_index;
        cookie->rel = cookie->rels + ent->reloc_index;
 
        /* FIXME: octets_per_byte.  */
        BFD_ASSERT (cookie->rel < cookie->relend
        BFD_ASSERT (cookie->rel < cookie->relend
                    && cookie->rel->r_offset == ent->offset + 8);
                    && cookie->rel->r_offset == ent->offset + 8);
        if (!(*reloc_symbol_deleted_p) (ent->offset + 8, cookie))
        if (!(*reloc_symbol_deleted_p) (ent->offset + 8, cookie))
          {
          {
            if (info->shared
            if (info->shared
Line 1220... Line 1245...
  struct eh_frame_hdr_info *hdr_info;
  struct eh_frame_hdr_info *hdr_info;
  unsigned int lo, hi, mid;
  unsigned int lo, hi, mid;
 
 
  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
    return offset;
    return offset;
  sec_info = elf_section_data (sec)->sec_info;
  sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info;
 
 
  if (offset >= sec->rawsize)
  if (offset >= sec->rawsize)
    return offset - sec->rawsize + sec->size;
    return offset - sec->rawsize + sec->size;
 
 
  htab = elf_hash_table (info);
  htab = elf_hash_table (info);
Line 1302... Line 1327...
  struct eh_frame_hdr_info *hdr_info;
  struct eh_frame_hdr_info *hdr_info;
  unsigned int ptr_size;
  unsigned int ptr_size;
  struct eh_cie_fde *ent;
  struct eh_cie_fde *ent;
 
 
  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
  if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
 
    /* FIXME: octets_per_byte.  */
    return bfd_set_section_contents (abfd, sec->output_section, contents,
    return bfd_set_section_contents (abfd, sec->output_section, contents,
                                     sec->output_offset, sec->size);
                                     sec->output_offset, sec->size);
 
 
  ptr_size = (get_elf_backend_data (abfd)
  ptr_size = (get_elf_backend_data (abfd)
              ->elf_backend_eh_frame_address_size (abfd, sec));
              ->elf_backend_eh_frame_address_size (abfd, sec));
  BFD_ASSERT (ptr_size != 0);
  BFD_ASSERT (ptr_size != 0);
 
 
  sec_info = elf_section_data (sec)->sec_info;
  sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info;
  htab = elf_hash_table (info);
  htab = elf_hash_table (info);
  hdr_info = &htab->eh_info;
  hdr_info = &htab->eh_info;
 
 
  if (hdr_info->table && hdr_info->array == NULL)
  if (hdr_info->table && hdr_info->array == NULL)
    hdr_info->array
    hdr_info->array = (struct eh_frame_array_ent *)
      = bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
        bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array));
  if (hdr_info->array == NULL)
  if (hdr_info->array == NULL)
    hdr_info = NULL;
    hdr_info = NULL;
 
 
  /* The new offsets can be bigger or smaller than the original offsets.
  /* The new offsets can be bigger or smaller than the original offsets.
     We therefore need to make two passes over the section: one backward
     We therefore need to make two passes over the section: one backward
Line 1439... Line 1465...
                      {
                      {
                        bfd_vma val;
                        bfd_vma val;
 
 
                        val = read_value (abfd, buf, per_width,
                        val = read_value (abfd, buf, per_width,
                                          get_DW_EH_PE_signed (per_encoding));
                                          get_DW_EH_PE_signed (per_encoding));
                        val += ent->offset - ent->new_offset;
                        val += (bfd_vma) ent->offset - ent->new_offset;
                        val -= extra_string + extra_data;
                        val -= extra_string + extra_data;
                        write_value (abfd, buf, val, per_width);
                        write_value (abfd, buf, val, per_width);
                        action &= ~4;
                        action &= ~4;
                      }
                      }
                    buf += per_width;
                    buf += per_width;
Line 1498... Line 1524...
                    BFD_ASSERT (got != NULL);
                    BFD_ASSERT (got != NULL);
                    address += got->vma;
                    address += got->vma;
                  }
                  }
                  break;
                  break;
                case DW_EH_PE_pcrel:
                case DW_EH_PE_pcrel:
                  value += ent->offset - ent->new_offset;
                  value += (bfd_vma) ent->offset - ent->new_offset;
                  address += (sec->output_section->vma
                  address += (sec->output_section->vma
                              + sec->output_offset
                              + sec->output_offset
                              + ent->offset + 8);
                              + ent->offset + 8);
                  break;
                  break;
                }
                }
Line 1532... Line 1558...
              value = read_value (abfd, buf, width,
              value = read_value (abfd, buf, width,
                                  get_DW_EH_PE_signed (ent->lsda_encoding));
                                  get_DW_EH_PE_signed (ent->lsda_encoding));
              if (value)
              if (value)
                {
                {
                  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
                  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
                    value += ent->offset - ent->new_offset;
                    value += (bfd_vma) ent->offset - ent->new_offset;
                  else if (cie->u.cie.make_lsda_relative)
                  else if (cie->u.cie.make_lsda_relative)
                    value -= (sec->output_section->vma
                    value -= (sec->output_section->vma
                              + sec->output_offset
                              + sec->output_offset
                              + ent->new_offset + 8 + ent->lsda_offset);
                              + ent->new_offset + 8 + ent->lsda_offset);
                  write_value (abfd, buf, value, width);
                  write_value (abfd, buf, value, width);
Line 1571... Line 1597...
                                      get_DW_EH_PE_signed (ent->fde_encoding));
                                      get_DW_EH_PE_signed (ent->fde_encoding));
                  if (!value)
                  if (!value)
                    continue;
                    continue;
 
 
                  if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
                  if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
                    value += ent->offset + 8 - new_offset;
                    value += (bfd_vma) ent->offset + 8 - new_offset;
                  if (ent->make_relative)
                  if (ent->make_relative)
                    value -= (sec->output_section->vma
                    value -= (sec->output_section->vma
                              + sec->output_offset
                              + sec->output_offset
                              + new_offset + ent->set_loc[cnt]);
                              + new_offset + ent->set_loc[cnt]);
                  write_value (abfd, buf, value, width);
                  write_value (abfd, buf, value, width);
Line 1590... Line 1616...
     have padded CIE/FDE records to multiple of pointer size with
     have padded CIE/FDE records to multiple of pointer size with
     size_of_output_cie_fde.  */
     size_of_output_cie_fde.  */
  if ((sec->size % ptr_size) != 0)
  if ((sec->size % ptr_size) != 0)
    abort ();
    abort ();
 
 
 
  /* FIXME: octets_per_byte.  */
  return bfd_set_section_contents (abfd, sec->output_section,
  return bfd_set_section_contents (abfd, sec->output_section,
                                   contents, (file_ptr) sec->output_offset,
                                   contents, (file_ptr) sec->output_offset,
                                   sec->size);
                                   sec->size);
}
}
 
 
Line 1601... Line 1628...
   VMA of FDE initial location.  */
   VMA of FDE initial location.  */
 
 
static int
static int
vma_compare (const void *a, const void *b)
vma_compare (const void *a, const void *b)
{
{
  const struct eh_frame_array_ent *p = a;
  const struct eh_frame_array_ent *p = (const struct eh_frame_array_ent *) a;
  const struct eh_frame_array_ent *q = b;
  const struct eh_frame_array_ent *q = (const struct eh_frame_array_ent *) b;
  if (p->initial_loc > q->initial_loc)
  if (p->initial_loc > q->initial_loc)
    return 1;
    return 1;
  if (p->initial_loc < q->initial_loc)
  if (p->initial_loc < q->initial_loc)
    return -1;
    return -1;
  return 0;
  return 0;
Line 1653... Line 1680...
    return TRUE;
    return TRUE;
 
 
  size = EH_FRAME_HDR_SIZE;
  size = EH_FRAME_HDR_SIZE;
  if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
  if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
    size += 4 + hdr_info->fde_count * 8;
    size += 4 + hdr_info->fde_count * 8;
  contents = bfd_malloc (size);
  contents = (bfd_byte *) bfd_malloc (size);
  if (contents == NULL)
  if (contents == NULL)
    return FALSE;
    return FALSE;
 
 
  eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
  eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
  if (eh_frame_sec == NULL)
  if (eh_frame_sec == NULL)
Line 1701... Line 1728...
                      hdr_info->array[i].fde - sec->output_section->vma,
                      hdr_info->array[i].fde - sec->output_section->vma,
                      contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
                      contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
        }
        }
    }
    }
 
 
 
  /* FIXME: octets_per_byte.  */
  retval = bfd_set_section_contents (abfd, sec->output_section,
  retval = bfd_set_section_contents (abfd, sec->output_section,
                                     contents, (file_ptr) sec->output_offset,
                                     contents, (file_ptr) sec->output_offset,
                                     sec->size);
                                     sec->size);
  free (contents);
  free (contents);
  return retval;
  return retval;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.