Back to index

cell-binutils  2.17cvs20070401
Functions
elf32-avr.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void elf32_avr_setup_params (struct bfd_link_info *, bfd *, asection *, bfd_boolean, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean)
int elf32_avr_setup_section_lists (bfd *, struct bfd_link_info *)
bfd_boolean elf32_avr_size_stubs (bfd *, struct bfd_link_info *, bfd_boolean)
bfd_boolean elf32_avr_build_stubs (struct bfd_link_info *)

Function Documentation

Definition at line 2902 of file elf32-avr.c.

{
  asection *stub_sec;
  struct bfd_hash_table *table;
  struct elf32_avr_link_hash_table *htab;
  bfd_size_type total_size = 0;

  htab = avr_link_hash_table (info);
  if (htab == NULL)
    return FALSE;

  /* In case that there were several stub sections:  */
  for (stub_sec = htab->stub_bfd->sections;
       stub_sec != NULL;
       stub_sec = stub_sec->next)
    {
      bfd_size_type size;

      /* Allocate memory to hold the linker stubs.  */
      size = stub_sec->size;
      total_size += size;

      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
      if (stub_sec->contents == NULL && size != 0)
       return FALSE;
      stub_sec->size = 0;
    }

  /* Allocate memory for the adress mapping table.  */
  htab->amt_entry_cnt = 0;
  htab->amt_max_entry_cnt = total_size / 4;
  htab->amt_stub_offsets = bfd_malloc (sizeof (bfd_vma)
                                       * htab->amt_max_entry_cnt);
  htab->amt_destination_addr = bfd_malloc (sizeof (bfd_vma)
                                      * htab->amt_max_entry_cnt );

  if (debug_stubs)
    printf ("Allocating %i entries in the AMT\n", htab->amt_max_entry_cnt);

  /* Build the stubs as directed by the stub hash table.  */
  table = &htab->bstab;
  bfd_hash_traverse (table, avr_build_one_stub, info);

  if (debug_stubs)
    printf ("Final Stub section Size: %i\n", (int) htab->stub_sec->size);

  return TRUE;
}

Here is the call graph for this function:

Definition at line 2492 of file elf32-avr.c.

{
  struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);

  if (htab == NULL)
    return;
  htab->stub_sec = avr_stub_section;
  htab->stub_bfd = avr_stub_bfd;
  htab->no_stubs = no_stubs;

  debug_relax = deb_relax;
  debug_stubs = deb_stubs;
  avr_pc_wrap_around = pc_wrap_around;
  avr_replace_call_ret_sequences = call_ret_replacement;
}

Definition at line 2523 of file elf32-avr.c.

{
  bfd *input_bfd;
  unsigned int bfd_count;
  int top_id, top_index;
  asection *section;
  asection **input_list, **list;
  bfd_size_type amt;
  struct elf32_avr_link_hash_table *htab = avr_link_hash_table(info);

  if (htab == NULL || htab->no_stubs)
    return 0;

  /* Count the number of input BFDs and find the top input section id.  */
  for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
       input_bfd != NULL;
       input_bfd = input_bfd->link_next)
    {
      bfd_count += 1;
      for (section = input_bfd->sections;
           section != NULL;
           section = section->next)
       if (top_id < section->id)
         top_id = section->id;
    }

  htab->bfd_count = bfd_count;

  /* We can't use output_bfd->section_count here to find the top output
     section index as some sections may have been removed, and
     strip_excluded_output_sections doesn't renumber the indices.  */
  for (section = output_bfd->sections, top_index = 0;
       section != NULL;
       section = section->next)
    if (top_index < section->index)
      top_index = section->index;

  htab->top_index = top_index;
  amt = sizeof (asection *) * (top_index + 1);
  input_list = bfd_malloc (amt);
  htab->input_list = input_list;
  if (input_list == NULL)
    return -1;

  /* For sections we aren't interested in, mark their entries with a
     value we can check later.  */
  list = input_list + top_index;
  do
    *list = bfd_abs_section_ptr;
  while (list-- != input_list);

  for (section = output_bfd->sections;
       section != NULL;
       section = section->next)
    if ((section->flags & SEC_CODE) != 0)
      input_list[section->index] = NULL;

  return 1;
}

Here is the call graph for this function:

Definition at line 2644 of file elf32-avr.c.

{
  struct elf32_avr_link_hash_table *htab;
  int stub_changed = 0;

  htab = avr_link_hash_table (info);
  if (htab == NULL)
    return FALSE;

  /* At this point we initialize htab->vector_base
     To the start of the text output section.  */
  htab->vector_base = htab->stub_sec->output_section->vma;

  if (get_local_syms (info->input_bfds, info))
    {
      if (htab->all_local_syms)
       goto error_ret_free_local;
      return FALSE;
    }

  if (ADD_DUMMY_STUBS_FOR_DEBUGGING)
    {
      struct elf32_avr_stub_hash_entry *test;

      test = avr_add_stub ("Hugo",htab);
      test->target_value = 0x123456;
      test->stub_offset = 13;

      test = avr_add_stub ("Hugo2",htab);
      test->target_value = 0x84210;
      test->stub_offset = 14;
    }

  while (1)
    {
      bfd *input_bfd;
      unsigned int bfd_indx;

      /* We will have to re-generate the stub hash table each time anything
         in memory has changed.  */

      bfd_hash_traverse (&htab->bstab, avr_mark_stub_not_to_be_necessary, htab);
      for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
           input_bfd = input_bfd->link_next, bfd_indx++)
        {
          Elf_Internal_Shdr *symtab_hdr;
          asection *section;
          Elf_Internal_Sym *local_syms;

          /* We'll need the symbol table in a second.  */
          symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
          if (symtab_hdr->sh_info == 0)
            continue;

          local_syms = htab->all_local_syms[bfd_indx];

          /* Walk over each section attached to the input bfd.  */
          for (section = input_bfd->sections;
               section != NULL;
               section = section->next)
            {
              Elf_Internal_Rela *internal_relocs, *irelaend, *irela;

              /* If there aren't any relocs, then there's nothing more
                 to do.  */
              if ((section->flags & SEC_RELOC) == 0
                  || section->reloc_count == 0)
                continue;

              /* If this section is a link-once section that will be
                 discarded, then don't create any stubs.  */
              if (section->output_section == NULL
                  || section->output_section->owner != output_bfd)
                continue;

              /* Get the relocs.  */
              internal_relocs
                = _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL,
                                             info->keep_memory);
              if (internal_relocs == NULL)
                goto error_ret_free_local;

              /* Now examine each relocation.  */
              irela = internal_relocs;
              irelaend = irela + section->reloc_count;
              for (; irela < irelaend; irela++)
                {
                  unsigned int r_type, r_indx;
                  struct elf32_avr_stub_hash_entry *hsh;
                  asection *sym_sec;
                  bfd_vma sym_value;
                  bfd_vma destination;
                  struct elf_link_hash_entry *hh;
                  char *stub_name;

                  r_type = ELF32_R_TYPE (irela->r_info);
                  r_indx = ELF32_R_SYM (irela->r_info);

                  /* Only look for 16 bit GS relocs. No other reloc will need a
                     stub.  */
                  if (!((r_type == R_AVR_16_PM)
                        || (r_type == R_AVR_LO8_LDI_GS)
                        || (r_type == R_AVR_HI8_LDI_GS)))
                    continue;

                  /* Now determine the call target, its name, value,
                     section.  */
                  sym_sec = NULL;
                  sym_value = 0;
                  destination = 0;
                  hh = NULL;
                  if (r_indx < symtab_hdr->sh_info)
                    {
                      /* It's a local symbol.  */
                      Elf_Internal_Sym *sym;
                      Elf_Internal_Shdr *hdr;

                      sym = local_syms + r_indx;
                      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
                      sym_sec = hdr->bfd_section;
                      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
                        sym_value = sym->st_value;
                      destination = (sym_value + irela->r_addend
                                     + sym_sec->output_offset
                                     + sym_sec->output_section->vma);
                    }
                  else
                    {
                      /* It's an external symbol.  */
                      int e_indx;

                      e_indx = r_indx - symtab_hdr->sh_info;
                      hh = elf_sym_hashes (input_bfd)[e_indx];

                      while (hh->root.type == bfd_link_hash_indirect
                             || hh->root.type == bfd_link_hash_warning)
                        hh = (struct elf_link_hash_entry *)
                              (hh->root.u.i.link);

                      if (hh->root.type == bfd_link_hash_defined
                          || hh->root.type == bfd_link_hash_defweak)
                        {
                          sym_sec = hh->root.u.def.section;
                          sym_value = hh->root.u.def.value;
                          if (sym_sec->output_section != NULL)
                          destination = (sym_value + irela->r_addend
                                         + sym_sec->output_offset
                                         + sym_sec->output_section->vma);
                        }
                      else if (hh->root.type == bfd_link_hash_undefweak)
                        {
                          if (! info->shared)
                            continue;
                        }
                      else if (hh->root.type == bfd_link_hash_undefined)
                        {
                          if (! (info->unresolved_syms_in_objects == RM_IGNORE
                                 && (ELF_ST_VISIBILITY (hh->other)
                                     == STV_DEFAULT)))
                             continue;
                        }
                      else
                        {
                          bfd_set_error (bfd_error_bad_value);

                          error_ret_free_internal:
                          if (elf_section_data (section)->relocs == NULL)
                            free (internal_relocs);
                          goto error_ret_free_local;
                        }
                    }

                  if (! avr_stub_is_required_for_16_bit_reloc
                    (destination - htab->vector_base))
                    {
                      if (!is_prealloc_run)
                     /* We are having a reloc that does't need a stub.  */
                     continue;

                    /* We don't right now know if a stub will be needed.
                      Let's rather be on the safe side.  */
                    }

                  /* Get the name of this stub.  */
                  stub_name = avr_stub_name (sym_sec, sym_value, irela);

                  if (!stub_name)
                    goto error_ret_free_internal;


                  hsh = avr_stub_hash_lookup (&htab->bstab,
                                              stub_name,
                                              FALSE, FALSE);
                  if (hsh != NULL)
                    {
                      /* The proper stub has already been created.  Mark it
                         to be used and write the possibly changed destination
                         value.  */
                      hsh->is_actually_needed = TRUE;
                      hsh->target_value = destination;
                      free (stub_name);
                      continue;
                    }

                  hsh = avr_add_stub (stub_name, htab);
                  if (hsh == NULL)
                    {
                      free (stub_name);
                      goto error_ret_free_internal;
                    }

                  hsh->is_actually_needed = TRUE;
                  hsh->target_value = destination;

                  if (debug_stubs)
                    printf ("Adding stub with destination 0x%x to the"
                            " hash table.\n", (unsigned int) destination);
                  if (debug_stubs)
                    printf ("(Pre-Alloc run: %i)\n", is_prealloc_run);

                  stub_changed = TRUE;
                }

              /* We're done with the internal relocs, free them.  */
              if (elf_section_data (section)->relocs == NULL)
                free (internal_relocs);
            }
        }

      /* Re-Calculate the number of needed stubs.  */
      htab->stub_sec->size = 0;
      bfd_hash_traverse (&htab->bstab, avr_size_one_stub, htab);

      if (!stub_changed)
        break;

      stub_changed = FALSE;
    }

  free (htab->all_local_syms);
  return TRUE;

 error_ret_free_local:
  free (htab->all_local_syms);
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function: