Beispiel #1
0
void
dwarf2dbg_convert_frag (fragS *frag)
{
  offsetT addr_diff;

  addr_diff = resolve_symbol_value (frag->fr_symbol);

  /* fr_var carries the max_chars that we created the fragment with.
     fr_subtype carries the current expected length.  We must, of
     course, have allocated enough memory earlier.  */
  gas_assert (frag->fr_var >= (int) frag->fr_subtype);

  if (DWARF2_USE_FIXED_ADVANCE_PC)
    emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
			      frag->fr_literal + frag->fr_fix,
			      frag->fr_subtype);
  else
    emit_inc_line_addr (frag->fr_offset, addr_diff,
			frag->fr_literal + frag->fr_fix, frag->fr_subtype);

  frag->fr_fix += frag->fr_subtype;
  frag->fr_type = rs_fill;
  frag->fr_var = 0;
  frag->fr_offset = 0;
}
symbolS *
make_expr_symbol (expressionS *expressionP)
{
#ifdef NOTYET
  expressionS zero;
#endif
  symbolS *symbolP;
#ifdef NOTYET
  struct expr_symbol_line *n;
#endif

  if (expressionP->X_op == O_symbol
      && expressionP->X_add_number == 0)
    return expressionP->X_add_symbol;

#ifndef NOTYET
  abort ();
#else
  if (expressionP->X_op == O_big)
    {
      /* This won't work, because the actual value is stored in
	 generic_floating_point_number or generic_bignum, and we are
	 going to lose it if we haven't already.  */
      if (expressionP->X_add_number > 0)
	as_bad (_("bignum invalid"));
      else
	as_bad (_("floating point number invalid"));
      zero.X_op = O_constant;
      zero.X_add_number = 0;
      zero.X_unsigned = 0;
      clean_up_expression (&zero);
      expressionP = &zero;
    }

  /* Putting constant symbols in absolute_section rather than
     expr_section is convenient for the old a.out code, for which
     S_GET_SEGMENT does not always retrieve the value put in by
     S_SET_SEGMENT.  */
  symbolP = symbol_create (FAKE_LABEL_NAME,
			   (expressionP->X_op == O_constant
			    ? absolute_section
			    : expr_section),
			   0, &zero_address_frag);
  symbol_set_value_expression (symbolP, expressionP);

  if (expressionP->X_op == O_constant)
    resolve_symbol_value (symbolP);

  n = (struct expr_symbol_line *) xmalloc (sizeof *n);
  n->sym = symbolP;
  as_where (&n->file, &n->line);
  n->next = expr_symbol_lines;
  expr_symbol_lines = n;
#endif

  return symbolP;
}
Beispiel #3
0
void
dwarf2dbg_convert_frag (fragS *frag)
{
  offsetT addr_diff;

  if (DWARF2_USE_FIXED_ADVANCE_PC)
    {
      /* If linker relaxation is enabled then the distance bewteen the two
	 symbols in the frag->fr_symbol expression might change.  Hence we
	 cannot rely upon the value computed by resolve_symbol_value.
	 Instead we leave the expression unfinalized and allow
	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
	 relocation) that will allow the linker to correctly compute the
	 actual address difference.  We have to use a fixed line advance for
	 this as we cannot (easily) relocate leb128 encoded values.  */
      int saved_finalize_syms = finalize_syms;

      finalize_syms = 0;
      addr_diff = resolve_symbol_value (frag->fr_symbol);
      finalize_syms = saved_finalize_syms;
    }
  else
    addr_diff = resolve_symbol_value (frag->fr_symbol);

  /* fr_var carries the max_chars that we created the fragment with.
     fr_subtype carries the current expected length.  We must, of
     course, have allocated enough memory earlier.  */
  gas_assert (frag->fr_var >= (int) frag->fr_subtype);

  if (DWARF2_USE_FIXED_ADVANCE_PC)
    emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
			      frag->fr_literal + frag->fr_fix,
			      frag->fr_subtype);
  else
    emit_inc_line_addr (frag->fr_offset, addr_diff,
			frag->fr_literal + frag->fr_fix, frag->fr_subtype);

  frag->fr_fix += frag->fr_subtype;
  frag->fr_type = rs_fill;
  frag->fr_var = 0;
  frag->fr_offset = 0;
}
Beispiel #4
0
int
dwarf2dbg_estimate_size_before_relax (fragS *frag)
{
  offsetT addr_delta;
  int size;

  addr_delta = resolve_symbol_value (frag->fr_symbol);
  size = size_inc_line_addr (frag->fr_offset, addr_delta);

  frag->fr_subtype = size;

  return size;
}
Beispiel #5
0
int
dwarf2dbg_estimate_size_before_relax (fragS *frag)
{
  offsetT addr_delta;
  int size;

  addr_delta = resolve_symbol_value (frag->fr_symbol);
  if (DWARF2_USE_FIXED_ADVANCE_PC)
    size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
  else
    size = size_inc_line_addr (frag->fr_offset, addr_delta);

  frag->fr_subtype = size;

  return size;
}
Beispiel #6
0
void
eh_frame_convert_frag (fragS *frag)
{
  offsetT diff;
  fragS *loc4_frag;
  int loc4_fix, ca;

  loc4_frag = (fragS *) frag->fr_opcode;
  loc4_fix = (int) frag->fr_offset;

  diff = resolve_symbol_value (frag->fr_symbol);

  ca = frag->fr_subtype >> 3;
  gas_assert (ca > 0);
  diff /= ca;
  switch (frag->fr_subtype & 7)
    {
    case 0:
      gas_assert (diff < 0x40);
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
      break;

    case 1:
      gas_assert (diff < 0x100);
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
      frag->fr_literal[frag->fr_fix] = diff;
      break;

    case 2:
      gas_assert (diff < 0x10000);
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
      md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
      break;

    default:
      md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
      break;
    }

  frag->fr_fix += frag->fr_subtype & 7;
  frag->fr_type = rs_fill;
  frag->fr_subtype = 0;
  frag->fr_offset = 0;
}
Beispiel #7
0
int
eh_frame_estimate_size_before_relax (fragS *frag)
{
  offsetT diff;
  int ca = frag->fr_subtype >> 3;
  int ret;

  diff = resolve_symbol_value (frag->fr_symbol);

  if (ca > 0 && diff % ca == 0 && diff / ca < 0x40)
    ret = 0;
  else if (diff < 0x100)
    ret = 1;
  else if (diff < 0x10000)
    ret = 2;
  else
    ret = 4;

  frag->fr_subtype = (frag->fr_subtype & ~7) | ret;

  return ret;
}
Beispiel #8
0
/*
 * relax_section() here we set the fr_address values in the frags.
 * After this, all frags in this segment have addresses that are correct
 * relative to the section (that is the section starts at address zero).
 * After all of the sections have been processed by this call and their sizes
 * are know then they can be slid to their final address.
 */
static
int
relax_section(
struct frag *frag_root,
int nsect)
{
    struct frag *fragP;
    relax_addressT address;

    int32_t stretch; /* May be any size, 0 or negative. */
		     /* Cumulative number of addresses we have */
		     /* relaxed this pass. */
		     /* We may have relaxed more than one address. */
    int32_t stretched;  /* Have we stretched on this pass? */
		    /* This is 'cuz stretch may be zero, when,
		       in fact some piece of code grew, and
		       another shrank.  If a branch instruction
		       doesn't fit anymore, we need another pass */

#ifndef ARM
    const relax_typeS *this_type;
    const relax_typeS *start_type;
    relax_substateT next_state;
    relax_substateT this_state;
    int32_t aim;
#endif /* !defined(ARM) */

    int32_t growth;
    uint32_t was_address;
    int32_t offset;
    symbolS *symbolP;
    int32_t target;
    int32_t after;
    uint32_t oldoff, newoff;
    int ret;

	ret = 0;
	growth = 0;

	/*
	 * For each frag in segment count and store (a 1st guess of) fr_address.
	 */
	address = 0;
	for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){
#ifdef ARM
            fragP->relax_marker = 0;
#endif /* ARM */
	    fragP->fr_address = address;
	    address += fragP->fr_fix;
	    switch(fragP->fr_type){
	    case rs_fill:
		address += fragP->fr_offset * fragP->fr_var;
		break;

	    case rs_align:
		offset = relax_align (address, (int) fragP->fr_offset);
		/*
		 * If a maximum number of bytes to fill was specified for this
		 * align (stored in fr_subtype) then check to see if this align
		 * can be done.  If not ignore it.  If so and this alignment is
		 * larger than any previous alignment then this becomes the
		 * section's alignment.
		 */
		if(fragP->fr_subtype != 0){
		    if(offset > (int32_t)fragP->fr_subtype){
			offset = 0;
		    }
		    else{
			if(frchain_now->frch_section.align <
			   (uint32_t)fragP->fr_offset)
			    frchain_now->frch_section.align = fragP->fr_offset;
		    }
		}
		address += offset;
		break;

	    case rs_org:
		/*
		 * Assume .org is nugatory. It will grow with 1st relax.
		 */
		break;

	    case rs_machine_dependent:
		address += md_estimate_size_before_relax(fragP, nsect);
		break;

	    case rs_dwarf2dbg:
		address += dwarf2dbg_estimate_size_before_relax(fragP);
		break;

	    case rs_leb128:
	      /* Initial guess is always 1; doing otherwise can result in
		 stable solutions that are larger than the minimum.  */
	      address += fragP->fr_offset = 1;
	      break;

	    default:
		BAD_CASE(fragP->fr_type);
		break;
	    }
	}

	/*
	 * Do relax().
	 * Make repeated passes over the chain of frags allowing each frag to
	 * grow if needed.  On each pass each frag's address is incremented by
	 * the accumulated growth, kept in stretched.  Passes are continued 
	 * until there is no stretch on the previous pass.
	 */
	do{
	    stretch = 0;
	    stretched = 0;
	    for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){
#ifdef ARM
                fragP->relax_marker ^= 1;
#endif /* ARM */
		was_address = fragP->fr_address;
		fragP->fr_address += stretch;
		address = fragP->fr_address;
		symbolP = fragP->fr_symbol;
		offset = fragP->fr_offset;
		switch(fragP->fr_type){
		case rs_fill:	/* .fill never relaxes. */
		    growth = 0;
		    break;

		case rs_align:
		    oldoff = relax_align(was_address + fragP->fr_fix, offset);
		    newoff = relax_align(address + fragP->fr_fix, offset);
		    /*
		     * Check if a maximum number of bytes to fill was specified
		     * for this align (stored in fr_subtype).
		     */
		    if(fragP->fr_subtype != 0){
			if(oldoff > fragP->fr_subtype)
			    oldoff = 0;
			if(newoff > fragP->fr_subtype)
			    newoff = 0;
		    }
		    growth = newoff - oldoff;
		    break;

		case rs_org:
		    target = offset;
		    if(symbolP != NULL){
			know(((symbolP->sy_type & N_TYPE) == N_ABS) ||
			     ((symbolP->sy_type & N_TYPE) == N_SECT));
			know(symbolP->sy_frag);
			know((symbolP->sy_type & N_TYPE) != N_ABS ||
			     symbolP->sy_frag == &zero_address_frag );
			target += symbolP->sy_value +
				  symbolP->sy_frag->fr_address;
		    }
		    know(fragP->fr_next);
		    after = fragP->fr_next->fr_address;
		    /*
		     * Growth may be negative, but variable part of frag cannot
		     * have < 0 chars. That is, we can't .org backwards.
		     */
		    growth = ((target - after ) > 0) ? (target - after) : 0;

		    growth -= stretch;	/* This is an absolute growth factor */
		    break;

		case rs_machine_dependent:
#ifdef ARM
		    growth = arm_relax_frag(nsect, fragP, stretch);
#else /* !defined(ARM) */
		    this_state = fragP->fr_subtype;
		    this_type = md_relax_table + this_state;
		    start_type = this_type;

		    target = offset;
		    if(symbolP){
			know(((symbolP->sy_type & N_TYPE) == N_ABS) ||
			     ((symbolP->sy_type & N_TYPE) == N_SECT));
			know(symbolP->sy_frag);
			know((symbolP->sy_type & N_TYPE) != N_ABS ||
			     symbolP->sy_frag == &zero_address_frag);

			target += symbolP->sy_value +
				  symbolP->sy_frag->fr_address;
			/*
			 * If frag has yet to be reached on this pass,
			 * assume it will move by STRETCH just as we did.
			 * If this is not so, it will be because some frag
			 * between grows, and that will force another pass.
			 */
			if(symbolP->sy_frag->fr_address >= was_address &&
			   is_down_range(fragP, symbolP->sy_frag))
			    target += stretch;
		    }
		    aim = target - address - fragP->fr_fix;
		    if(aim < 0){
			/* Look backwards. */
			for(next_state = this_type->rlx_more; next_state; ){
			    if(aim >= this_type->rlx_backward)
				next_state = 0;
			    else{	/* Grow to next state. */
				this_state = next_state;
				this_type = md_relax_table + this_state;
				next_state = this_type->rlx_more;
			    }
			}
		    }
		    else{
			/* Look forwards. */
			for(next_state = this_type->rlx_more; next_state; ){
			    if(aim <= this_type->rlx_forward)
				next_state = 0;
			    else{	/* Grow to next state. */
				this_state = next_state;
				this_type = md_relax_table + this_state;
				next_state = this_type->rlx_more;
			    }
			}
		    }
		    if((growth = this_type->rlx_length -start_type->rlx_length))
			  fragP->fr_subtype = this_state;
#endif /* !defined(ARM) */
		    break;
		  case rs_dwarf2dbg:
		      growth = dwarf2dbg_relax_frag(fragP);
		      break;

		  case rs_leb128:
		    {
		      valueT value;
		      offsetT size;
#ifdef OLD
		      value = resolve_symbol_value (fragP->fr_symbol);
#else
  		      expressionS *expression;
  		
		      if(fragP->fr_symbol->expression != NULL){
			expression =
			  (expressionS *)fragP->fr_symbol->expression;
			value = 0;
			if(expression->X_add_symbol != NULL)
			    value +=
			     (expression->X_add_symbol->sy_nlist.n_value +
			      expression->X_add_symbol->sy_frag->fr_address);
			if(expression->X_subtract_symbol != NULL)
			   value -= 
			     (expression->X_subtract_symbol->sy_nlist.n_value +
			      expression->X_subtract_symbol->
							   sy_frag->fr_address);
			value += expression->X_add_number;
		      }
		      else{
			value = fragP->fr_symbol->sy_nlist.n_value +
				fragP->fr_address;
		      }
#endif
		      size = sizeof_leb128 (value, fragP->fr_subtype);
		      growth = size - fragP->fr_offset;
		      fragP->fr_offset = size;
		    }
		    break;

		  default:
		      BAD_CASE(fragP->fr_type);
		      break;
		}
		if(growth) {
		    stretch += growth;
		    stretched++;
		}
	    }			/* For each frag in the segment. */
	}while(stretched);	/* Until nothing further to relax. */

	/*
	 * We now have valid fr_address'es for each frag.  All fr_address's
	 * are correct, relative to their own section.  We have made all the
	 * fixS for this section that will be made.
	 */

	for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){
	    if(fragP->last_fr_address != fragP->fr_address){
		fragP->last_fr_address = fragP->fr_address;
		ret = 1;
	    }
	}
	return(ret);
}