예제 #1
0
파일: trace.c 프로젝트: ChrisG0x20/gdb
static long
remove_useless_symbols (asymbol ** symbols, long count)
{
  asymbol **in_ptr = symbols, **out_ptr = symbols;

  while (-- count >= 0)
    {
      asymbol *sym = *in_ptr ++;

      if (strstr (sym->name, "gcc2_compiled"))
	continue;
      if (sym->name == NULL || sym->name[0] == '\0')
	continue;
      if (sym->flags & (BSF_DEBUGGING))
	continue;
      if (bfd_is_und_section (sym->section)
	  || bfd_is_com_section (sym->section))
	continue;
      
      if (sym->name[0] == '.' && sym->name[1] == 'L')
	continue;

      /* If the symbol ends in ^A or ^B it is
	 an assembler generated local label.  */
      if (sym->name[strlen (sym->name) - 1] < 32)
	continue;

      *out_ptr++ = sym;
    }
  return out_ptr - symbols;
}
예제 #2
0
파일: reloc16.c 프로젝트: ChrisG0x20/gdb
bfd_vma
bfd_coff_reloc16_get_value (arelent *reloc,
			    struct bfd_link_info *link_info,
			    asection *input_section)
{
  bfd_vma value;
  asymbol *symbol = *(reloc->sym_ptr_ptr);
  /* A symbol holds a pointer to a section, and an offset from the
     base of the section.  To relocate, we find where the section will
     live in the output and add that in.  */

  if (bfd_is_und_section (symbol->section)
      || bfd_is_com_section (symbol->section))
    {
      struct bfd_link_hash_entry *h;

      /* The symbol is undefined in this BFD.  Look it up in the
	 global linker hash table.  FIXME: This should be changed when
	 we convert this stuff to use a specific final_link function
	 and change the interface to bfd_relax_section to not require
	 the generic symbols.  */
      h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
					bfd_asymbol_name (symbol),
					FALSE, FALSE, TRUE);
      if (h != (struct bfd_link_hash_entry *) NULL
	  && (h->type == bfd_link_hash_defined
	      || h->type == bfd_link_hash_defweak))
	value = (h->u.def.value
		 + h->u.def.section->output_section->vma
		 + h->u.def.section->output_offset);
      else if (h != (struct bfd_link_hash_entry *) NULL
	       && h->type == bfd_link_hash_common)
	value = h->u.c.size;
      else if (h != (struct bfd_link_hash_entry *) NULL
	       && h->type == bfd_link_hash_undefweak)
	/* This is a GNU extension.  */
	value = 0;
      else
	{
	  if (!((*link_info->callbacks->undefined_symbol)
		(link_info, bfd_asymbol_name (symbol),
		 input_section->owner, input_section, reloc->address,
		 TRUE)))
	    abort ();
	  value = 0;
	}
    }
  else
    {
      value = symbol->value
	+ symbol->section->output_offset
	+ symbol->section->output_section->vma;
    }

  /* Add the value contained in the relocation.  */
  value += reloc->addend;

  return value;
}
예제 #3
0
static long
get_symbol_value (asymbol *symbol)
{
  long relocation = 0;

  if (bfd_is_com_section (symbol->section))
    relocation = 0;
  else
    relocation = symbol->value +
      symbol->section->output_section->vma + symbol->section->output_offset;

  return relocation;
}
예제 #4
0
void
add_cref (const char *name,
          bfd *abfd,
          asection *section,
          bfd_vma value ATTRIBUTE_UNUSED)
{
    struct cref_hash_entry *h;
    struct cref_ref *r;

    if (! cref_initialized)
    {
        if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
                                  sizeof (struct cref_hash_entry)))
            einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
        cref_initialized = TRUE;
    }

    h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
    if (h == NULL)
        einfo (_("%X%P: cref_hash_lookup failed: %E\n"));

    for (r = h->refs; r != NULL; r = r->next)
        if (r->abfd == abfd)
            break;

    if (r == NULL)
    {
        r = bfd_hash_allocate (&cref_table.root, sizeof *r);
        if (r == NULL)
            einfo (_("%X%P: cref alloc failed: %E\n"));
        r->next = h->refs;
        h->refs = r;
        r->abfd = abfd;
        r->def = FALSE;
        r->common = FALSE;
        r->undef = FALSE;
    }

    if (bfd_is_und_section (section))
        r->undef = TRUE;
    else if (bfd_is_com_section (section))
        r->common = TRUE;
    else
        r->def = TRUE;
}
예제 #5
0
파일: symbols.c 프로젝트: GREYFOXRGR/moflow
long
remove_useless_symbols_local (asymbol *symbols, long count)
{
  asymbol *in_ptr = symbols, *out_ptr = symbols;

  while (--count >= 0)
  {
    asymbol *sym = in_ptr++;

    if (sym->name == NULL || sym->name[0] == '\0')
      continue;
    if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
      continue;
    if (bfd_is_und_section (sym->section)
        || bfd_is_com_section (sym->section))
      continue;

    *out_ptr++ = *sym;
  }
  return out_ptr - symbols;
}
예제 #6
0
void ELFFile::remove_useless_symbols ()
{
    long count = this->sorted_symcount;
    asymbol** in_ptr = this->sorted_syms;
    asymbol** out_ptr = this->sorted_syms;

    while (--count >= 0)
    {
        asymbol *sym = *in_ptr++;

        if (sym->name == NULL || sym->name[0] == '\0')
            continue;
        if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
            continue;
        if (bfd_is_und_section (sym->section)
                || bfd_is_com_section (sym->section))
            continue;

        *out_ptr++ = sym;
    }
    this->sorted_symcount = out_ptr - this->sorted_syms;
}
예제 #7
0
파일: trace.c 프로젝트: bminor/binutils-gdb
static long
remove_useless_symbols (asymbol ** symbols, long count)
{
  register asymbol **in_ptr = symbols, **out_ptr = symbols;

  while (--count >= 0)
    {
      asymbol *sym = *in_ptr++;

      if (strstr (sym->name, "gcc2_compiled"))
	continue;
      if (sym->name == NULL || sym->name[0] == '\0')
	continue;
      if (sym->flags & (BSF_DEBUGGING))
	continue;
      if (bfd_is_und_section (sym->section)
	  || bfd_is_com_section (sym->section))
	continue;

      *out_ptr++ = sym;
    }
  return out_ptr - symbols;
}
예제 #8
0
/*
FUNCTION
	bfd_decode_symclass

DESCRIPTION
	Return a character corresponding to the symbol
	class of @var{symbol}, or '?' for an unknown class.

SYNOPSIS
	int bfd_decode_symclass (asymbol *symbol);
*/
int
bfd_decode_symclass (asymbol *symbol)
{
  char c;

  if (symbol->section && bfd_is_com_section (symbol->section))
    return 'C';
  if (bfd_is_und_section (symbol->section))
    {
      if (symbol->flags & BSF_WEAK)
	{
	  /* If weak, determine if it's specifically an object
	     or non-object weak.  */
	  if (symbol->flags & BSF_OBJECT)
	    return 'v';
	  else
	    return 'w';
	}
      else
	return 'U';
    }
  if (bfd_is_ind_section (symbol->section))
    return 'I';
  if (symbol->flags & BSF_GNU_INDIRECT_FUNCTION)
    return 'i';
  if (symbol->flags & BSF_WEAK)
    {
      /* If weak, determine if it's specifically an object
	 or non-object weak.  */
      if (symbol->flags & BSF_OBJECT)
	return 'V';
      else
	return 'W';
    }
  if (symbol->flags & BSF_GNU_UNIQUE)
    return 'u';
  if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
    return '?';

  if (bfd_is_abs_section (symbol->section))
    c = 'a';
  else if (symbol->section)
    {
      c = coff_section_type (symbol->section->name);
      if (c == '?')
	c = decode_section_type (symbol->section);
    }
  else
    return '?';
  if (symbol->flags & BSF_GLOBAL)
    c = TOUPPER (c);
  return c;

  /* We don't have to handle these cases just yet, but we will soon:
     N_SETV: 'v';
     N_SETA: 'l';
     N_SETT: 'x';
     N_SETD: 'z';
     N_SETB: 's';
     N_INDR: 'i';
     */
}
예제 #9
0
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
   and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
   the linker adds them to the linker hash table.  Mark those
   referenced from a non-IR file with non_ir_ref.  We have to
   notice_all symbols, because we won't necessarily know until later
   which ones will be contributed by IR files.  */
static bfd_boolean
plugin_notice (struct bfd_link_info *info,
               struct bfd_link_hash_entry *h,
               struct bfd_link_hash_entry *inh,
               bfd *abfd,
               asection *section,
               bfd_vma value,
               flagword flags)
{
    struct bfd_link_hash_entry *orig_h = h;

    if (h != NULL)
    {
        bfd *sym_bfd;

        if (h->type == bfd_link_hash_warning)
            h = h->u.i.link;

        /* Nothing to do here if this def/ref is from an IR dummy BFD.  */
        if (is_ir_dummy_bfd (abfd))
            ;

        /* Making an indirect symbol counts as a reference unless this
        is a brand new symbol.  */
        else if (bfd_is_ind_section (section)
                 || (flags & BSF_INDIRECT) != 0)
        {
            /* ??? Some of this is questionable.  See comments in
               _bfd_generic_link_add_one_symbol for case IND.  */
            if (h->type != bfd_link_hash_new)
            {
                h->non_ir_ref = TRUE;
                inh->non_ir_ref = TRUE;
            }
            else if (inh->type == bfd_link_hash_new)
                inh->non_ir_ref = TRUE;
        }

        /* Nothing to do here for warning symbols.  */
        else if ((flags & BSF_WARNING) != 0)
            ;

        /* Nothing to do here for constructor symbols.  */
        else if ((flags & BSF_CONSTRUCTOR) != 0)
            ;

        /* If this is a ref, set non_ir_ref.  */
        else if (bfd_is_und_section (section))
        {
            /* Replace the undefined dummy bfd with the real one.  */
            if ((h->type == bfd_link_hash_undefined
                    || h->type == bfd_link_hash_undefweak)
                    && (h->u.undef.abfd == NULL
                        || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
                h->u.undef.abfd = abfd;
            h->non_ir_ref = TRUE;
        }

        /* Otherwise, it must be a new def.  */
        else
        {
            /* A common symbol should be merged with other commons or
               defs with the same name.  In particular, a common ought
               to be overridden by a def in a -flto object.  In that
               sense a common is also a ref.  */
            if (bfd_is_com_section (section))
                h->non_ir_ref = TRUE;

            /* Ensure any symbol defined in an IR dummy BFD takes on a
               new value from a real BFD.  Weak symbols are not normally
               overridden by a new weak definition, and strong symbols
               will normally cause multiple definition errors.  Avoid
               this by making the symbol appear to be undefined.  */
            if (((h->type == bfd_link_hash_defweak
                    || h->type == bfd_link_hash_defined)
                    && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
                    || (h->type == bfd_link_hash_common
                        && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
            {
                h->type = bfd_link_hash_undefweak;
                h->u.undef.abfd = sym_bfd;
            }
        }
    }

    /* Continue with cref/nocrossref/trace-sym processing.  */
    if (orig_h == NULL
            || orig_notice_all
            || (info->notice_hash != NULL
                && bfd_hash_lookup (info->notice_hash, orig_h->root.string,
                                    FALSE, FALSE) != NULL))
        return (*orig_callbacks->notice) (info, orig_h, inh,
                                          abfd, section, value, flags);
    return TRUE;
}
예제 #10
0
파일: i386lynx.c 프로젝트: 5kg/gdb
static void
NAME(lynx,swap_std_reloc_out) (bfd *abfd,
			       arelent *g,
			       struct reloc_std_external *natptr)
{
  int r_index;
  asymbol *sym = *(g->sym_ptr_ptr);
  int r_extern;
  unsigned int r_length;
  int r_pcrel;
  int r_baserel, r_jmptable, r_relative;
  asection *output_section = sym->section->output_section;

  PUT_WORD (abfd, g->address, natptr->r_address);

  r_length = g->howto->size;	/* Size as a power of two */
  r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
  /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
  r_baserel = 0;
  r_jmptable = 0;
  r_relative = 0;

  /* name was clobbered by aout_write_syms to be symbol index */

  /* If this relocation is relative to a symbol then set the
     r_index to the symbols index, and the r_extern bit.

     Absolute symbols can come in in two ways, either as an offset
     from the abs section, or as a symbol which has an abs value.
     check for that here
  */

  if (bfd_is_com_section (output_section)
      || bfd_is_abs_section (output_section)
      || bfd_is_und_section (output_section))
    {
      if (bfd_abs_section_ptr->symbol == sym)
	{
	  /* Whoops, looked like an abs symbol, but is really an offset
	     from the abs section */
	  r_index = 0;
	  r_extern = 0;
	}
      else
	{
	  /* Fill in symbol */
	  r_extern = 1;
	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
	}
    }
  else
    {
      /* Just an ordinary section */
      r_extern = 0;
      r_index = output_section->target_index;
    }

  /* now the fun stuff */
  if (bfd_header_big_endian (abfd))
    {
      natptr->r_index[0] = r_index >> 16;
      natptr->r_index[1] = r_index >> 8;
      natptr->r_index[2] = r_index;
      natptr->r_type[0] =
	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
    }
  else
    {
예제 #11
0
int
_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
{
  asection *section;
  asymbol *symbol;
  unsigned int symnum;
  int last_index = -1;
  char dummy_name[10];
  char *sname;
  flagword new_flags, old_flags;

#if defined(VMS_DEBUG) && VMS_DEBUG
  vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype);
#endif

  /* Output sections.  */
  section = abfd->sections;
#if defined(VMS_DEBUG) && VMS_DEBUG
  vms_debug (3, "%d sections found\n", abfd->section_count);
#endif

  /* Egsd is quadword aligned.  */
  _bfd_vms_output_alignment (abfd, 8);

  _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
  _bfd_vms_output_long (abfd, 0);
  /* Prepare output for subrecords.  */
  _bfd_vms_output_push (abfd);

  while (section != 0)
    {
#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size);
#endif

      /* 13 bytes egsd, max 31 chars name -> should be 44 bytes.  */
      if (_bfd_vms_output_check (abfd, 64) < 0)
	{
	  _bfd_vms_output_pop (abfd);
	  _bfd_vms_output_end (abfd);
	  _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
	  _bfd_vms_output_long (abfd, 0);
	  /* Prepare output for subrecords.  */
	  _bfd_vms_output_push (abfd);
	}

      /* Create dummy sections to keep consecutive indices.  */
      while (section->index - last_index > 1)
	{
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (3, "index %d, last %d\n", section->index, last_index);
#endif
	  _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
	  _bfd_vms_output_short (abfd, 0);
	  _bfd_vms_output_short (abfd, 0);
	  _bfd_vms_output_long (abfd, 0);
	  sprintf (dummy_name, ".DUMMY%02d", last_index);
	  _bfd_vms_output_counted (abfd, dummy_name);
	  _bfd_vms_output_flush (abfd);
	  last_index++;
	}

      /* Don't know if this is necessary for the linker but for now it keeps
	 vms_slurp_gsd happy  */
      sname = (char *)section->name;
      if (*sname == '.')
	{
	  sname++;
	  if ((*sname == 't') && (strcmp (sname, "text") == 0))
	    sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
	  else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
	    sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
	  else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
	    sname = EVAX_BSS_NAME;
	  else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
	    sname = EVAX_LINK_NAME;
	  else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
	    sname = EVAX_READONLY_NAME;
	  else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
	    sname = EVAX_LITERAL_NAME;
	  else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
	    sname = EVAX_COMMON_NAME;
	  else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
	    sname = EVAX_LOCAL_NAME;
	}
      else
	sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);

      _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
      _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
      if (bfd_is_com_section (section))
	new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
      else
	new_flags = vms_esecflag_by_name (evax_section_flags, sname,
					  section->size > 0);

      _bfd_vms_output_short (abfd, new_flags);
      _bfd_vms_output_long (abfd, (unsigned long) section->size);
      _bfd_vms_output_counted (abfd, sname);
      _bfd_vms_output_flush (abfd);

      last_index = section->index;
      section = section->next;
    }

  /* Output symbols.  */
#if defined(VMS_DEBUG) && VMS_DEBUG
  vms_debug (3, "%d symbols found\n", abfd->symcount);
#endif

  bfd_set_start_address (abfd, (bfd_vma) -1);

  for (symnum = 0; symnum < abfd->symcount; symnum++)
    {
      char *hash;

      symbol = abfd->outsymbols[symnum];
      if (*(symbol->name) == '_')
	{
	  if (strcmp (symbol->name, "__main") == 0)
	    bfd_set_start_address (abfd, (bfd_vma)symbol->value);
	}
      old_flags = symbol->flags;

      if (old_flags & BSF_FILE)
	continue;

      if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0)	/* Not xdef...  */
	  && (!bfd_is_und_section (symbol->section)))	/* ...and not xref.  */
	continue;					/* Dont output.  */

      /* 13 bytes egsd, max 64 chars name -> should be 77 bytes.  */
      if (_bfd_vms_output_check (abfd, 80) < 0)
	{
	  _bfd_vms_output_pop (abfd);
	  _bfd_vms_output_end (abfd);
	  _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
	  _bfd_vms_output_long (abfd, 0);
	  /* Prepare output for subrecords.  */
	  _bfd_vms_output_push (abfd);
	}

      _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);

      /* Data type, alignment.  */
      _bfd_vms_output_short (abfd, 0);

      new_flags = 0;

      if (old_flags & BSF_WEAK)
	new_flags |= EGSY_S_V_WEAK;
      if (bfd_is_com_section (symbol->section))
	new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);

      if (old_flags & BSF_FUNCTION)
	{
	  new_flags |= EGSY_S_V_NORM;
	  new_flags |= EGSY_S_V_REL;
	}
      if (old_flags & (BSF_GLOBAL | BSF_WEAK))
	{
	  new_flags |= EGSY_S_V_DEF;
	  if (!bfd_is_abs_section (symbol->section))
	    new_flags |= EGSY_S_V_REL;
	}
      _bfd_vms_output_short (abfd, new_flags);

      if (old_flags & (BSF_GLOBAL | BSF_WEAK))
	{
	  /* Symbol definition.  */
	  uquad code_address = 0;
	  unsigned long ca_psindx = 0;
	  unsigned long psindx;

	  if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
	    {
	      code_address = ((asymbol *) (symbol->udata.p))->value;
	      ca_psindx = ((asymbol *) (symbol->udata.p))->section->index;
	    }
	  psindx = symbol->section->index;

	  _bfd_vms_output_quad (abfd, symbol->value);
	  _bfd_vms_output_quad (abfd, code_address);
	  _bfd_vms_output_long (abfd, ca_psindx);
	  _bfd_vms_output_long (abfd, psindx);
	}
      hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
      _bfd_vms_output_counted (abfd, hash);

      _bfd_vms_output_flush (abfd);

    }

  _bfd_vms_output_alignment (abfd, 8);
  _bfd_vms_output_pop (abfd);
  _bfd_vms_output_end (abfd);

  return 0;
}
예제 #12
0
파일: cpu-ns32k.c 프로젝트: npe9/spin
/* This is just like the standard perform_relocation except we
 * use get_data and put_data which know about the ns32k
 * storage methods.
 * This is probably a lot more complicated than it needs to be!
 */
static bfd_reloc_status_type
do_ns32k_reloc (bfd *abfd, arelent *reloc_entry,
                struct symbol_cache_entry *symbol, PTR data,
                asection *input_section, bfd *output_bfd,
                char **error_message, long (*get_data)(),
                int (*put_data)())
{
    int overflow = 0;
    bfd_vma relocation;
    bfd_reloc_status_type flag = bfd_reloc_ok;
    bfd_size_type addr = reloc_entry->address;
    bfd_vma output_base = 0;
    const reloc_howto_type *howto = reloc_entry->howto;
    asection *reloc_target_output_section;

    if ((symbol->section == &bfd_abs_section)
            && output_bfd != (bfd *) NULL)
    {
        reloc_entry->address += input_section->output_offset;
        return bfd_reloc_ok;
    }

    /* If we are not producing relocateable output, return an error if
       the symbol is not defined.  An undefined weak symbol is
       considered to have a value of zero (SVR4 ABI, p. 4-27).  */
    if (symbol->section == &bfd_und_section
            && (symbol->flags & BSF_WEAK) == 0
            && output_bfd == (bfd *) NULL)
        flag = bfd_reloc_undefined;


    /* Is the address of the relocation really within the section?  */
    if (reloc_entry->address > input_section->_cooked_size)
        return bfd_reloc_outofrange;

    /* Work out which section the relocation is targetted at and the
       initial relocation command value.  */

    /* Get symbol value.  (Common symbols are special.)  */
    if (bfd_is_com_section (symbol->section))
        relocation = 0;
    else
        relocation = symbol->value;


    reloc_target_output_section = symbol->section->output_section;

    /* Convert input-section-relative symbol value to absolute.  */
    if (output_bfd && howto->partial_inplace == false)
        output_base = 0;
    else
        output_base = reloc_target_output_section->vma;

    relocation += output_base + symbol->section->output_offset;

    /* Add in supplied addend.  */
    relocation += reloc_entry->addend;

    /* Here the variable relocation holds the final address of the
       symbol we are relocating against, plus any addend.  */

    if (howto->pc_relative == true)
    {
        /* This is a PC relative relocation.  We want to set RELOCATION
        to the distance between the address of the symbol and the
         location.  RELOCATION is already the address of the symbol.

         We start by subtracting the address of the section containing
         the location.

         If pcrel_offset is set, we must further subtract the position
         of the location within the section.  Some targets arrange for
         the addend to be the negative of the position of the location
         within the section; for example, i386-aout does this.  For
         i386-aout, pcrel_offset is false.  Some other targets do not
         include the position of the location; for example, m88kbcs,
         or ELF.  For those targets, pcrel_offset is true.

         If we are producing relocateable output, then we must ensure
         that this reloc will be correctly computed when the final
         relocation is done.  If pcrel_offset is false we want to wind
         up with the negative of the location within the section,
         which means we must adjust the existing addend by the change
         in the location within the section.  If pcrel_offset is true
         we do not want to adjust the existing addend at all.

         FIXME: This seems logical to me, but for the case of
         producing relocateable output it is not what the code
         actually does.  I don't want to change it, because it seems
         far too likely that something will break.  */

        relocation -=
            input_section->output_section->vma + input_section->output_offset;

        if (howto->pcrel_offset == true)
            relocation -= reloc_entry->address;
    }

    if (output_bfd != (bfd *) NULL)
    {
        if (howto->partial_inplace == false)
        {
            /* This is a partial relocation, and we want to apply the relocation
               to the reloc entry rather than the raw data. Modify the reloc
               inplace to reflect what we now know.  */
            reloc_entry->addend = relocation;
            reloc_entry->address += input_section->output_offset;
            return flag;
        }
        else
        {
            /* This is a partial relocation, but inplace, so modify the
               reloc record a bit.

               If we've relocated with a symbol with a section, change
               into a ref to the section belonging to the symbol.  */

            reloc_entry->address += input_section->output_offset;

            /* WTF?? */
            if (abfd->xvec->flavour == bfd_target_coff_flavour
                    && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0)
            {
#if 1
                /* For m68k-coff, the addend was being subtracted twice during
                relocation with -r.  Removing the line below this comment
                 fixes that problem; see PR 2953.

                However, Ian wrote the following, regarding removing the line below,
                which explains why it is still enabled:  --djm

                If you put a patch like that into BFD you need to check all the COFF
                linkers.  I am fairly certain that patch will break coff-i386 (e.g.,
                SCO); see coff_i386_reloc in coff-i386.c where I worked around the
                problem in a different way.  There may very well be a reason that the
                code works as it does.

                Hmmm.  The first obvious point is that bfd_perform_relocation should
                not have any tests that depend upon the flavour.  It's seem like
                entirely the wrong place for such a thing.  The second obvious point
                is that the current code ignores the reloc addend when producing
                relocateable output for COFF.  That's peculiar.  In fact, I really
                have no idea what the point of the line you want to remove is.

                A typical COFF reloc subtracts the old value of the symbol and adds in
                the new value to the location in the object file (if it's a pc
                relative reloc it adds the difference between the symbol value and the
                location).  When relocating we need to preserve that property.

                BFD handles this by setting the addend to the negative of the old
                value of the symbol.  Unfortunately it handles common symbols in a
                non-standard way (it doesn't subtract the old value) but that's a
                different story (we can't change it without losing backward
                compatibility with old object files) (coff-i386 does subtract the old
                value, to be compatible with existing coff-i386 targets, like SCO).

                So everything works fine when not producing relocateable output.  When
                we are producing relocateable output, logically we should do exactly
                what we do when not producing relocateable output.  Therefore, your
                patch is correct.  In fact, it should probably always just set
                reloc_entry->addend to 0 for all cases, since it is, in fact, going to
                add the value into the object file.  This won't hurt the COFF code,
                which doesn't use the addend; I'm not sure what it will do to other
                formats (the thing to check for would be whether any formats both use
                the addend and set partial_inplace).

                When I wanted to make coff-i386 produce relocateable output, I ran
                into the problem that you are running into: I wanted to remove that
                line.  Rather than risk it, I made the coff-i386 relocs use a special
                function; it's coff_i386_reloc in coff-i386.c.  The function
                specifically adds the addend field into the object file, knowing that
                bfd_perform_relocation is not going to.  If you remove that line, then
                coff-i386.c will wind up adding the addend field in twice.  It's
                trivial to fix; it just needs to be done.

                The problem with removing the line is just that it may break some
                working code.  With BFD it's hard to be sure of anything.  The right
                way to deal with this is simply to build and test at least all the
                supported COFF targets.  It should be straightforward if time and disk
                space consuming.  For each target:
                1) build the linker
                2) generate some executable, and link it using -r (I would
                 probably use paranoia.o and link against newlib/libc.a, which
                 for all the supported targets would be available in
                 /usr/cygnus/progressive/H-host/target/lib/libc.a).
                3) make the change to reloc.c
                4) rebuild the linker
                5) repeat step 2
                6) if the resulting object files are the same, you have at least
                 made it no worse
                7) if they are different you have to figure out which version is
                 right
                */
                relocation -= reloc_entry->addend;
#endif
                reloc_entry->addend = 0;
            }
            else
            {
                reloc_entry->addend = relocation;
            }
        }
    }
    else
    {
        reloc_entry->addend = 0;
    }

    /* FIXME: This overflow checking is incomplete, because the value
       might have overflowed before we get here.  For a correct check we
       need to compute the value in a size larger than bitsize, but we
       can't reasonably do that for a reloc the same size as a host
       machine word.
       FIXME: We should also do overflow checking on the result after
       adding in the value contained in the object file.  */
    if (howto->complain_on_overflow != complain_overflow_dont)
    {
        bfd_vma check;

        /* Get the value that will be used for the relocation, but
        starting at bit position zero.  */
        if (howto->rightshift > howto->bitpos)
            check = relocation >> (howto->rightshift - howto->bitpos);
        else
예제 #13
0
/*
 * Implementation
 */
void
jit_init_debug(const char *progname)
{
#if DISASSEMBLER
    bfd_init();

    if (progname)
	disasm_bfd = bfd_openr(progname, NULL);
    if (disasm_bfd == NULL) {
#if defined(__linux__)
	disasm_bfd = bfd_openr("/proc/self/exe", NULL);
	if (disasm_bfd == NULL)
#endif
	    return;
    }
    bfd_check_format(disasm_bfd, bfd_object);
    bfd_check_format(disasm_bfd, bfd_archive);
    disasm_print = disassembler(disasm_bfd);
    assert(disasm_print);
    INIT_DISASSEMBLE_INFO(disasm_info, disasm_stream, fprintf);
#  if defined(__i386__) || defined(__x86_64__)
    disasm_info.arch = bfd_arch_i386;
#    if defined(__x86_64__)
#      if __WORDSIZE == 32
    disasm_info.mach = bfd_mach_x64_32;
#      else
    disasm_info.mach = bfd_mach_x86_64;
#      endif
#    else
    disasm_info.mach = bfd_mach_i386_i386;
#    endif
#  endif
#  if defined(__powerpc__)
    disasm_info.arch = bfd_arch_powerpc;
    disasm_info.mach = bfd_mach_ppc64;
#    if HAVE_DISASSEMBLE_INIT_FOR_TARGET
    disassemble_init_for_target(&disasm_info);
#    elif HAVE_DISASSEMBLE_INIT_POWERPC
    disassemble_init_powerpc(&disasm_info);
#    endif
#    if defined(__powerpc64__)
    disasm_info.disassembler_options = "64";
#    endif
#    if HAVE_DISASSEMBLE_INIT_FOR_TARGET
    disassemble_init_for_target(&disasm_info);
#    elif HAVE_DISASSEMBLE_INIT_POWERPC
    disassemble_init_powerpc(&disasm_info);
#    endif
#  endif
#  if defined(__sparc__)
    disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG;
#  endif
#  if defined(__s390__) || defined(__s390x__)
    disasm_info.arch = bfd_arch_s390;
#    if __WORDSIZE == 32
    disasm_info.mach = bfd_mach_s390_31;
#    else
    disasm_info.mach = bfd_mach_s390_64;
#    endif
    disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG;
    disasm_info.disassembler_options = "zarch";
#  endif
#  if defined(__alpha__)
    disasm_info.arch = bfd_arch_alpha;
    disasm_info.mach = bfd_mach_alpha_ev6;
#  endif
    disasm_info.print_address_func = disasm_print_address;

    if (bfd_get_file_flags(disasm_bfd) & HAS_SYMS) {
	asymbol		**in;
	asymbol		**out;
	asymbol		 *symbol;
	long		  offset;
	long		  sym_count;
	long		  dyn_count;
	long		  sym_storage;
	long		  dyn_storage;

	if ((sym_storage = bfd_get_symtab_upper_bound(disasm_bfd)) >= 0) {

	    if (bfd_get_file_flags(disasm_bfd) & DYNAMIC) {
		dyn_storage = bfd_get_dynamic_symtab_upper_bound(disasm_bfd);
#  if defined(__alpha__)
		/* XXX */
		if (dyn_storage < 0)
		    dyn_storage = 0;
#  else
		assert(dyn_storage >= 0);
#  endif
	    }
	    else
		dyn_storage = 0;

	    jit_alloc((jit_pointer_t *)&disasm_symbols,
		      (sym_storage + dyn_storage) * sizeof(asymbol *));
	    sym_count = bfd_canonicalize_symtab(disasm_bfd, disasm_symbols);
	    assert(sym_count >= 0);
	    if (dyn_storage) {
		dyn_count = bfd_canonicalize_dynamic_symtab(disasm_bfd,
							    disasm_symbols +
							    sym_count);
		assert(dyn_count >= 0);
	    }
	    else
		dyn_count = 0;
	    disasm_num_symbols = sym_count + dyn_count;

	    disasm_num_synthetic = bfd_get_synthetic_symtab(disasm_bfd,
							    sym_count,
							    disasm_symbols,
							    dyn_count,
							    disasm_symbols +
							    sym_count,
							    &disasm_synthetic);
	    if (disasm_num_synthetic > 0) {
		jit_realloc((jit_pointer_t *)&disasm_symbols,
			    (sym_storage + dyn_storage) * sizeof(asymbol *),
			    (sym_storage + dyn_storage + disasm_num_synthetic) *
			    sizeof(asymbol *));
		for (offset = 0; offset < disasm_num_synthetic; offset++)
		    disasm_symbols[disasm_num_symbols++] =
			disasm_synthetic + offset;
	    }

	    /* remove symbols not useful for disassemble */
	    in = out = disasm_symbols;
	    for (offset = 0; offset < disasm_num_symbols; offset++) {
		symbol = *in++;
		if (symbol->name &&
		    symbol->name[0] != '\0' &&
		    !(symbol->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) &&
		    !bfd_is_und_section(symbol->section) &&
		    !bfd_is_com_section(symbol->section))
		    *out++ = symbol;
	    }
	    disasm_num_symbols = out - disasm_symbols;
	    qsort(disasm_symbols, disasm_num_symbols,
		  sizeof(asymbol *), disasm_compare_symbols);
	}
    }
#endif
}