Exemple #1
0
void
dwarf2_move_insn (int delta)
{
  struct line_subseg *lss;
  struct line_entry *e;
  valueT now;

  if (delta == 0)
    return;

  lss = get_line_subseg (now_seg, now_subseg, FALSE);
  if (!lss)
    return;

  now = frag_now_fix ();
  while ((e = *lss->pmove_tail))
    {
      if (S_GET_VALUE (e->label) == now)
	S_SET_VALUE (e->label, now + delta);
      lss->pmove_tail = &e->next;
    }
}
static void
dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
{
    struct cfi_escape_data *head, **tail, *e;
    struct cfi_insn_data *insn;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    /* If the last address was not at the current PC, advance to current.  */
    if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
            || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
            != frag_now_fix ())
        cfi_add_advance_loc (symbol_temp_new_now ());

    tail = &head;
    do
    {
        e = xmalloc (sizeof (*e));
        do_parse_cons_expression (&e->exp, 1);
        *tail = e;
        tail = &e->next;
    }
    while (*input_line_pointer++ == ',');
    *tail = NULL;

    insn = alloc_cfi_insn_data ();
    insn->insn = CFI_escape;
    insn->u.esc = head;

    --input_line_pointer;
    demand_empty_rest_of_line ();
}
Exemple #3
0
/*
 * layout_addresses() is called after all the assembly code has been read and
 * fragments, symbols and fixups have been created.  This routine sets the
 * address of the fragments and symbols.  Then it does the fixups of the frags
 * and prepares the fixes so relocation entries can be created from them.
 */
void
layout_addresses(
void)
{
    struct frchain *frchainP;
    fragS *fragP;
    relax_addressT slide, tmp;
    symbolS *symbolP;
    uint32_t nbytes, fill_size, repeat_expression, partial_bytes, layout_pass;
    relax_stateT old_fr_type;
    int changed;

	if(frchain_root == NULL)
	    return;

	/*
	 * If there is any current frag close it off.
	 */
	if(frag_now != NULL && frag_now->fr_fix == 0){
	    frag_now->fr_fix = obstack_next_free(&frags) -
			       frag_now->fr_literal;
	    frag_wane(frag_now);
	}

	/*
	 * For every section, add a last ".fill 0" frag that will later be used
	 * as the ending address of that section.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    /*
	     * We must do the obstack_finish(), so the next object we put on
	     * obstack frags will not appear to start at the fr_literal of the
	     * current frag.  Also, it ensures that the next object will begin
	     * on a address that is aligned correctly for the engine that runs
	     * the assembler.
	     */
	    (void)obstack_finish(&frags);

	    /*
	     * Make a fresh frag for the last frag.
	     */
	    frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
	    memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
	    frag_now->fr_next = NULL;
	    (void)obstack_finish(&frags);

	    /*
	     * Append the new frag to current frchain.
	     */
	    frchainP->frch_last->fr_next = frag_now;
	    frchainP->frch_last = frag_now;
	    frag_wane(frag_now);

	}

	/*
	 * Now set the relative addresses of frags within the section by
	 * relaxing each section.  That is all sections will start at address
	 * zero and addresses of the frags in that section will increase from
	 * there.
	 *
	 * The debug sections are done last as other section are needed to be
	 * done first becase debug sections may have line numbers with .loc
	 * directives in them and their sizes need to be set before processing
	 * the line number sections.  We also do sections that have rs_leb128s
	 * in them before debug sections but after other sections since they
	 * are used for things like exception tables and they may be refering to
	 * sections such that their sizes too must be known first.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if((frchainP->frch_section.flags & S_ATTR_DEBUG) == S_ATTR_DEBUG)
		frchainP->layout_pass = 2;
	    else if(frchainP->has_rs_leb128s == TRUE)
		frchainP->layout_pass = 1;
	    else
		frchainP->layout_pass = 0;
	}
	for(layout_pass = 0; layout_pass < 3; layout_pass++){
	    do{
		changed = 0;
		for(frchainP = frchain_root;
		    frchainP;
		    frchainP = frchainP->frch_next){
		    if(frchainP->layout_pass != layout_pass)
			continue;
		    if((frchainP->frch_section.flags & SECTION_TYPE) ==
		       S_ZEROFILL)
			continue;
		    /*
		     * This is done so in case md_estimate_size_before_relax()
		     * (called by relax_section) wants to make fixSs they are
		     * for this section.
		     */
		    frchain_now = frchainP;

		    changed += relax_section(frchainP->frch_root,
					    frchainP->frch_nsect);
		}
	    }
	    while(changed != 0);
	}

	/*
	 * Now set the absolute addresses of all frags by sliding the frags in
	 * each non-zerofill section by the address ranges taken up by the
	 * sections before it.
	 */ 
	slide = 0;
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL)
		continue;
	    slide = round(slide, 1 << frchainP->frch_section.align);
	    tmp = frchainP->frch_last->fr_address;
	    if(slide != 0){
		for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){
		    fragP->fr_address += slide;
		}
	    }
	    slide += tmp;
	}
	/*
	 * Now with the non-zerofill section addresses set set all of the
	 * addresses of the zerofill sections.  Comming in the fr_address is
	 * the size of the section and going out it is the start address.  This
	 * will make layout_symbols() work out naturally.  The only funky thing
	 * is that section numbers do not end up in address order.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if((frchainP->frch_section.flags & SECTION_TYPE) != S_ZEROFILL)
		continue;
	    slide = round(slide, 1 << frchainP->frch_section.align);

	    tmp = frchainP->frch_root->fr_address;
	    frchainP->frch_root->fr_address = slide;
	    frchainP->frch_last->fr_address = tmp + slide;
	    slide += tmp;
	}

	/*
	 * Set the symbol addresses based on their frag's address.
	 * First forward references are handled.
	 */
	for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
	    if(symbolP->sy_forward != NULL){
		if(symbolP->sy_nlist.n_type & N_STAB)
		    symbolP->sy_other = symbolP->sy_forward->sy_other;
		symbolP->sy_value += symbolP->sy_forward->sy_value +
				     symbolP->sy_forward->sy_frag->fr_address;
		symbolP->sy_forward = 0;
	    }
	}
	for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
	    symbolP->sy_value += symbolP->sy_frag->fr_address;
	}

	/*
	 * At this point the addresses of frags now reflect addresses we use in 
	 * the object file and the symbol values are correct.
	 * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
	 * Also converting any machine-dependent frags using md_convert_frag();
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    /*
	     * This is done so any fixes created by md_convert_frag() are for
	     * this section.
	     */
	    frchain_now = frchainP;

	    for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){
		switch(fragP->fr_type){
		case rs_align:
		case rs_org:
		    old_fr_type = fragP->fr_type;
		    /* convert this frag to an rs_fill type */
		    fragP->fr_type = rs_fill;
		    /*
		     * Calculate the number of bytes the variable part of the
		     * the rs_fill frag will need to fill.  Then calculate this
		     * as the fill_size * repeat_expression + partial_bytes.
		     */
		    know(fragP->fr_next != NULL);
		    nbytes = fragP->fr_next->fr_address -
			     fragP->fr_address -
			     fragP->fr_fix;
		    if(nbytes < 0){
			as_warn("rs_org invalid, dot past value by %d bytes",
				nbytes);
			nbytes = 0;
		    }
		    fill_size = fragP->fr_var;
		    repeat_expression = nbytes / fill_size;
#ifdef I386
		    /*
		     * For x86 architecures in sections containing only
		     * instuctions being padded with nops that are aligned to 16
		     * bytes or less and are assembled with -dynamic we will
		     * actually end up padding with the optimal nop sequence.
		     * Previously there has been the maximum number of bytes
		     * allocated in the frag to use for this.
		     */
		    if(old_fr_type == rs_align &&
		       (frchain_now->frch_section.flags &
			S_ATTR_PURE_INSTRUCTIONS) != 0 &&
			 fill_size == 1 &&
			 fragP->fr_literal[fragP->fr_fix] == (char)0x90 &&
			 nbytes > 0 && nbytes < 16 &&
			 flagseen['k'] == TRUE){
			i386_align_code(fragP, nbytes);
			/*
			 * The call to i386_align_code() has set the fill_size
			 * in fragP->fr_var to nbytes. So we set the fr_offset
			 * to the fill repeat_expression to 1 to match for this
			 * now an rs_fill type frag.
			 */ 
			fragP->fr_offset = 1;
			break;
		    }
#endif /* I386 */
		    partial_bytes = nbytes - (repeat_expression * fill_size);
		    /*
		     * Now set the fr_offset to the fill repeat_expression
		     * since this is now an rs_fill type.  The fr_var is still
		     * the fill_size.
		     */
		    fragP->fr_offset = repeat_expression;
		    /*
		     * For rs_align frags there may be partial_bytes to fill
		     * with zeros before we can fill with the fill_expression
		     * of fill_size.  When the rs_align frag was created it was
		     * created with fill_size-1 extra bytes in the fixed part.
		     */
		    if(partial_bytes != 0){
			/* moved the fill_expression bytes foward */
			memmove(fragP->fr_literal +fragP->fr_fix +partial_bytes,
				fragP->fr_literal +fragP->fr_fix,
				fragP->fr_var);
    			/* zero out the partial_bytes */
    			memset(fragP->fr_literal + fragP->fr_fix,
			       '\0',
			       partial_bytes);
			/* adjust the fixed part of the frag */
    			fragP->fr_fix += partial_bytes;
		    }
		    break;

		case rs_fill:
		    break;

		case rs_machine_dependent:
		    md_convert_frag(fragP);
		    /*
		     * After md_convert_frag, we make the frag into a ".fill 0"
		     * md_convert_frag() should set up any fixSs and constants
		     * required.
		     */
		    frag_wane(fragP);
		    break;

		case rs_dwarf2dbg:
		    dwarf2dbg_convert_frag(fragP);
		    break;

		case rs_leb128:
		  {
		    int size;
#ifdef OLD
		    valueT value = S_GET_VALUE (fragP->fr_symbol);
#else
		    valueT value;
  		      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;
			if(expression->X_subtract_symbol != NULL)
			   value -= 
			     expression->X_subtract_symbol->sy_nlist.n_value;
			value += expression->X_add_number;
		      }
		      else{
			value = fragP->fr_symbol->sy_nlist.n_value +
				fragP->fr_address;
		      }
#endif

		    size = output_leb128 (fragP->fr_literal + fragP->fr_fix,
					  value,
					  fragP->fr_subtype);
	       
		    fragP->fr_fix += size;
		    fragP->fr_type = rs_fill;
		    fragP->fr_var = 0;
		    fragP->fr_offset = 0;
		    fragP->fr_symbol = NULL; 
		  }
		  break;


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

	/*
	 * For each section do the fixups for the frags.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    now_seg = frchainP->frch_nsect;
	    fixup_section(frchainP->frch_fix_root, frchainP->frch_nsect);
	}
}
static void
output_cfi_insn (struct cfi_insn_data *insn)
{
    offsetT offset;
    unsigned int regno;

    switch (insn->insn)
    {
    case DW_CFA_advance_loc:
    {
        symbolS *from = insn->u.ll.lab1;
        symbolS *to = insn->u.ll.lab2;

        if (symbol_get_frag (to) == symbol_get_frag (from))
        {
            addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
            addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;

            if (scaled <= 0x3F)
                out_one (DW_CFA_advance_loc + scaled);
            else if (delta <= 0xFF)
            {
                out_one (DW_CFA_advance_loc1);
                out_one (delta);
            }
            else if (delta <= 0xFFFF)
            {
                out_one (DW_CFA_advance_loc2);
                out_two (delta);
            }
            else
            {
                out_one (DW_CFA_advance_loc4);
                out_four (delta);
            }
        }
        else
        {
            expressionS exp;

            exp.X_op = O_subtract;
            exp.X_add_symbol = to;
            exp.X_op_symbol = from;
            exp.X_add_number = 0;

            /* The code in ehopt.c expects that one byte of the encoding
               is already allocated to the frag.  This comes from the way
               that it scans the .eh_frame section looking first for the
               .byte DW_CFA_advance_loc4.  */
            frag_more (1);

            frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
                      make_expr_symbol (&exp), frag_now_fix () - 1,
                      (char *) frag_now);
        }
    }
    break;

    case DW_CFA_def_cfa:
        offset = insn->u.ri.offset;
        if (offset < 0)
        {
            out_one (DW_CFA_def_cfa_sf);
            out_uleb128 (insn->u.ri.reg);
            out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
        }
        else
        {
            out_one (DW_CFA_def_cfa);
            out_uleb128 (insn->u.ri.reg);
            out_uleb128 (offset);
        }
        break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_undefined:
    case DW_CFA_same_value:
        out_one (insn->insn);
        out_uleb128 (insn->u.r);
        break;

    case DW_CFA_def_cfa_offset:
        offset = insn->u.i;
        if (offset < 0)
        {
            out_one (DW_CFA_def_cfa_offset_sf);
            out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
        }
        else
        {
            out_one (DW_CFA_def_cfa_offset);
            out_uleb128 (offset);
        }
        break;

    case DW_CFA_restore:
        regno = insn->u.r;
        if (regno <= 0x3F)
        {
            out_one (DW_CFA_restore + regno);
        }
        else
        {
            out_one (DW_CFA_restore_extended);
            out_uleb128 (regno);
        }
        break;

    case DW_CFA_offset:
        regno = insn->u.ri.reg;
        offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
        if (offset < 0)
        {
            out_one (DW_CFA_offset_extended_sf);
            out_uleb128 (regno);
            out_sleb128 (offset);
        }
        else if (regno <= 0x3F)
        {
            out_one (DW_CFA_offset + regno);
            out_uleb128 (offset);
        }
        else
        {
            out_one (DW_CFA_offset_extended);
            out_uleb128 (regno);
            out_uleb128 (offset);
        }
        break;

    case DW_CFA_register:
        out_one (DW_CFA_register);
        out_uleb128 (insn->u.rr.reg1);
        out_uleb128 (insn->u.rr.reg2);
        break;

    case DW_CFA_remember_state:
    case DW_CFA_restore_state:
        out_one (insn->insn);
        break;

    case DW_CFA_GNU_window_save:
        out_one (DW_CFA_GNU_window_save);
        break;

    case CFI_escape:
    {
        struct cfi_escape_data *e;
        for (e = insn->u.esc; e ; e = e->next)
            emit_expr (&e->exp, 1);
        break;
    }

    default:
        abort ();
    }
}
static void
dot_cfi (int arg)
{
    offsetT offset;
    unsigned reg1, reg2;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    /* If the last address was not at the current PC, advance to current.  */
    if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
            || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
            != frag_now_fix ())
        cfi_add_advance_loc (symbol_temp_new_now ());

    switch (arg)
    {
    case DW_CFA_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1, offset);
        break;

    case CFI_rel_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1,
                            offset - frchain_now->frch_cfi_data->cur_cfa_offset);
        break;

    case DW_CFA_def_cfa:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa (reg1, offset);
        break;

    case DW_CFA_register:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        reg2 = cfi_parse_reg ();
        cfi_add_CFA_register (reg1, reg2);
        break;

    case DW_CFA_def_cfa_register:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_def_cfa_register (reg1);
        break;

    case DW_CFA_def_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (offset);
        break;

    case CFI_adjust_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
                                    + offset);
        break;

    case DW_CFA_restore:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_restore (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_undefined:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_undefined (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_same_value:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_same_value (reg1);
        break;

    case CFI_return_column:
        reg1 = cfi_parse_reg ();
        cfi_set_return_column (reg1);
        break;

    case DW_CFA_remember_state:
        cfi_add_CFA_remember_state ();
        break;

    case DW_CFA_restore_state:
        cfi_add_CFA_restore_state ();
        break;

    case DW_CFA_GNU_window_save:
        cfi_add_CFA_insn (DW_CFA_GNU_window_save);
        break;

    case CFI_signal_frame:
        frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
        break;

    default:
        abort ();
    }

    demand_empty_rest_of_line ();
}
Exemple #6
0
static void
process_entries (segT seg, struct line_entry *e)
{
  unsigned filenum = 1;
  unsigned line = 1;
  unsigned column = 0;
  unsigned isa = 0;
  unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  fragS *last_frag = NULL, *frag;
  addressT last_frag_ofs = 0, frag_ofs;
  symbolS *last_lab = NULL, *lab;
  struct line_entry *next;

  do
    {
      int line_delta;

      if (filenum != e->loc.filenum)
	{
	  filenum = e->loc.filenum;
	  out_opcode (DW_LNS_set_file);
	  out_uleb128 (filenum);
	}

      if (column != e->loc.column)
	{
	  column = e->loc.column;
	  out_opcode (DW_LNS_set_column);
	  out_uleb128 (column);
	}

      if (e->loc.discriminator != 0)
	{
	  out_opcode (DW_LNS_extended_op);
	  out_leb128 (1 + sizeof_leb128 (e->loc.discriminator, 0));
	  out_opcode (DW_LNE_set_discriminator);
	  out_uleb128 (e->loc.discriminator);
	}

      if (isa != e->loc.isa)
	{
	  isa = e->loc.isa;
	  out_opcode (DW_LNS_set_isa);
	  out_uleb128 (isa);
	}

      if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT)
	{
	  flags = e->loc.flags;
	  out_opcode (DW_LNS_negate_stmt);
	}

      if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
	out_opcode (DW_LNS_set_basic_block);

      if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
	out_opcode (DW_LNS_set_prologue_end);

      if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
	out_opcode (DW_LNS_set_epilogue_begin);

      /* Don't try to optimize away redundant entries; gdb wants two
	 entries for a function where the code starts on the same line as
	 the {, and there's no way to identify that case here.  Trust gcc
	 to optimize appropriately.  */
      line_delta = e->loc.line - line;
      lab = e->label;
      frag = symbol_get_frag (lab);
      frag_ofs = S_GET_VALUE (lab);

      if (last_frag == NULL)
	{
	  out_set_addr (lab);
	  out_inc_line_addr (line_delta, 0);
	}
      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
      else
	relax_inc_line_addr (line_delta, lab, last_lab);

      line = e->loc.line;
      last_lab = lab;
      last_frag = frag;
      last_frag_ofs = frag_ofs;

      next = e->next;
      free (e);
      e = next;
    }
  while (e);

  /* Emit a DW_LNE_end_sequence for the end of the section.  */
  frag = last_frag_for_seg (seg);
  frag_ofs = get_frag_fix (frag, seg);
  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
    out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
  else
    {
      lab = symbol_temp_new (seg, frag_ofs, frag);
      relax_inc_line_addr (INT_MAX, lab, last_lab);
    }
}
Exemple #7
0
static void
list_symbol_table (void)
{
  extern symbolS *symbol_rootP;
  int got_some = 0;

  symbolS *ptr;
  eject = 1;
  listing_page (NULL);

  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
    {
      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
	  || S_GET_SEGMENT (ptr) == absolute_section)
	{
	  /* Don't report section symbols.  They are not interesting.  */
	  if (symbol_section_p (ptr))
	    continue;

	  if (S_GET_NAME (ptr))
	    {
	      char buf[30], fmt[8];
	      valueT val = S_GET_VALUE (ptr);

	      /* @@ Note that this is dependent on the compilation options,
		 not solely on the target characteristics.  */
	      if (sizeof (val) == 4 && sizeof (int) == 4)
		sprintf (buf, "%08lx", (unsigned long) val);
	      else if (sizeof (val) <= sizeof (unsigned long))
		{
		  sprintf (fmt, "%%0%lulx",
			   (unsigned long) (sizeof (val) * 2));
		  sprintf (buf, fmt, (unsigned long) val);
		}
#if defined (BFD64)
	      else if (sizeof (val) > 4)
		sprintf_vma (buf, val);
#endif
	      else
		abort ();

	      if (!got_some)
		{
		  fprintf (list_file, "DEFINED SYMBOLS\n");
		  on_page++;
		  got_some = 1;
		}

	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
		{
		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
			   symbol_get_frag (ptr)->line->file->filename,
			   symbol_get_frag (ptr)->line->line,
			   segment_name (S_GET_SEGMENT (ptr)),
			   buf, S_GET_NAME (ptr));
		}
	      else
		{
		  fprintf (list_file, "%33s:%s %s\n",
			   segment_name (S_GET_SEGMENT (ptr)),
			   buf, S_GET_NAME (ptr));
		}

	      on_page++;
	      listing_page (NULL);
	    }
	}

    }
  if (!got_some)
    {
      fprintf (list_file, "NO DEFINED SYMBOLS\n");
      on_page++;
    }
  emit_line (NULL, "\n");

  got_some = 0;

  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
    {
      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
	{
	  if (S_GET_SEGMENT (ptr) == undefined_section)
	    {
	      if (!got_some)
		{
		  got_some = 1;

		  emit_line (NULL, "UNDEFINED SYMBOLS\n");
		}

	      emit_line (NULL, "%s\n", S_GET_NAME (ptr));
	    }
	}
    }

  if (!got_some)
    emit_line (NULL, "NO UNDEFINED SYMBOLS\n");
}
Exemple #8
0
static void
dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED)
{
  struct cfi_insn_data *insn_ptr;
  offsetT encoding;

  if (frchain_now->frch_cfi_data == NULL)
    {
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
      ignore_rest_of_line ();
      return;
    }

  /* If the last address was not at the current PC, advance to current.  */
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
      || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
	 != frag_now_fix ())
    cfi_add_advance_loc (symbol_temp_new_now ());

  insn_ptr = alloc_cfi_insn_data ();
  insn_ptr->insn = CFI_val_encoded_addr;

  insn_ptr->u.ea.reg = cfi_parse_reg ();

  cfi_parse_separator ();
  encoding = cfi_parse_const ();
  if ((encoding & 0xff) != encoding
      || ((encoding & 0x70) != 0
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
	  && (encoding & 0x70) != DW_EH_PE_pcrel
#endif
	  )
	 /* leb128 can be handled, but does something actually need it?  */
      || (encoding & 7) == DW_EH_PE_uleb128
      || (encoding & 7) > DW_EH_PE_udata8)
    {
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
      encoding = DW_EH_PE_omit;
    }

  cfi_parse_separator ();
  expression_and_evaluate (&insn_ptr->u.ea.exp);
  switch (insn_ptr->u.ea.exp.X_op)
    {
    case O_symbol:
      break;
    case O_constant:
      if ((encoding & 0x70) != DW_EH_PE_pcrel)
        break;
    default:
      encoding = DW_EH_PE_omit;
      break;
    }

  insn_ptr->u.ea.encoding = encoding;
  if (encoding == DW_EH_PE_omit)
    {
      as_bad (_("wrong third argument to .cfi_val_encoded_addr"));
      ignore_rest_of_line ();
      return;
    }

  demand_empty_rest_of_line ();
}
Exemple #9
0
static void
output_cfi_insn (struct cfi_insn_data *insn)
{
  offsetT offset;
  unsigned int regno;

  switch (insn->insn)
    {
    case DW_CFA_advance_loc:
      {
	symbolS *from = insn->u.ll.lab1;
	symbolS *to = insn->u.ll.lab2;

	if (symbol_get_frag (to) == symbol_get_frag (from))
	  {
	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;

	    if (scaled <= 0x3F)
	      out_one (DW_CFA_advance_loc + scaled);
	    else if (scaled <= 0xFF)
	      {
		out_one (DW_CFA_advance_loc1);
		out_one (scaled);
	      }
	    else if (scaled <= 0xFFFF)
	      {
		out_one (DW_CFA_advance_loc2);
		out_two (scaled);
	      }
	    else
	      {
		out_one (DW_CFA_advance_loc4);
		out_four (scaled);
	      }
	  }
	else
	  {
	    expressionS exp;

	    exp.X_op = O_subtract;
	    exp.X_add_symbol = to;
	    exp.X_op_symbol = from;
	    exp.X_add_number = 0;

	    /* The code in ehopt.c expects that one byte of the encoding
	       is already allocated to the frag.  This comes from the way
	       that it scans the .eh_frame section looking first for the
	       .byte DW_CFA_advance_loc4.  */
	    *frag_more (1) = DW_CFA_advance_loc4;

	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
		      make_expr_symbol (&exp), frag_now_fix () - 1,
		      (char *) frag_now);
	  }
      }
      break;

    case DW_CFA_def_cfa:
      offset = insn->u.ri.offset;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_sf);
	  out_uleb128 (insn->u.ri.reg);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa);
	  out_uleb128 (insn->u.ri.reg);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_undefined:
    case DW_CFA_same_value:
      out_one (insn->insn);
      out_uleb128 (insn->u.r);
      break;

    case DW_CFA_def_cfa_offset:
      offset = insn->u.i;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_offset_sf);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa_offset);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_restore:
      regno = insn->u.r;
      if (regno <= 0x3F)
	{
	  out_one (DW_CFA_restore + regno);
	}
      else
	{
	  out_one (DW_CFA_restore_extended);
	  out_uleb128 (regno);
	}
      break;

    case DW_CFA_offset:
      regno = insn->u.ri.reg;
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
      if (offset < 0)
	{
	  out_one (DW_CFA_offset_extended_sf);
	  out_uleb128 (regno);
	  out_sleb128 (offset);
	}
      else if (regno <= 0x3F)
	{
	  out_one (DW_CFA_offset + regno);
	  out_uleb128 (offset);
	}
      else
	{
	  out_one (DW_CFA_offset_extended);
	  out_uleb128 (regno);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_register:
      out_one (DW_CFA_register);
      out_uleb128 (insn->u.rr.reg1);
      out_uleb128 (insn->u.rr.reg2);
      break;

    case DW_CFA_remember_state:
    case DW_CFA_restore_state:
      out_one (insn->insn);
      break;

    case DW_CFA_GNU_window_save:
      out_one (DW_CFA_GNU_window_save);
      break;

    case CFI_escape:
      {
	struct cfi_escape_data *e;
	for (e = insn->u.esc; e ; e = e->next)
	  emit_expr (&e->exp, 1);
	break;
      }

    case CFI_val_encoded_addr:
      {
        unsigned encoding = insn->u.ea.encoding;
        offsetT encoding_size;

	if (encoding == DW_EH_PE_omit)
	  break;
	out_one (DW_CFA_val_expression);
	out_uleb128 (insn->u.ea.reg);

        switch (encoding & 0x7)
	  {
	  case DW_EH_PE_absptr:
	    encoding_size = DWARF2_ADDR_SIZE (stdoutput);
	    break;
	  case DW_EH_PE_udata2:
	    encoding_size = 2;
	    break;
	  case DW_EH_PE_udata4:
	    encoding_size = 4;
	    break;
	  case DW_EH_PE_udata8:
	    encoding_size = 8;
	    break;
	  default:
	    abort ();
	  }

	/* If the user has requested absolute encoding,
	   then use the smaller DW_OP_addr encoding.  */
	if (insn->u.ea.encoding == DW_EH_PE_absptr)
	  {
	    out_uleb128 (1 + encoding_size);
	    out_one (DW_OP_addr);
	  }
	else
	  {
	    out_uleb128 (1 + 1 + encoding_size);
	    out_one (DW_OP_GNU_encoded_addr);
	    out_one (encoding);

	    if ((encoding & 0x70) == DW_EH_PE_pcrel)
	      {
#if CFI_DIFF_EXPR_OK
		insn->u.ea.exp.X_op = O_subtract;
		insn->u.ea.exp.X_op_symbol = symbol_temp_new_now ();
#elif defined (tc_cfi_emit_pcrel_expr)
		tc_cfi_emit_pcrel_expr (&insn->u.ea.exp, encoding_size);
		break;
#else
		abort ();
#endif
	      }
	  }
	emit_expr (&insn->u.ea.exp, encoding_size);
      }
      break;

    default:
      abort ();
    }
}
Exemple #10
0
void
coff_frob_symbol (symbolS *symp, int *punt)
{
  static symbolS *last_tagP;
  static stack *block_stack;
  static symbolS *set_end;
  symbolS *next_set_end = NULL;

  if (symp == &abs_symbol)
    {
      *punt = 1;
      return;
    }

  if (current_lineno_sym)
    coff_add_linesym (NULL);

  if (!block_stack)
    block_stack = stack_init (512, sizeof (symbolS*));

#ifdef TE_PE
  if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
      && ! S_IS_WEAK (symp)
      && weak_is_altname (S_GET_NAME (symp)))
    {
      /* This is a weak alternate symbol.  All processing of
	 PECOFFweak symbols is done here, through the alternate.  */
      symbolS *weakp = symbol_find_noref (weak_altname2name
					  (S_GET_NAME (symp)), 1);

      assert (weakp);
      assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);

      if (! S_IS_WEAK (weakp))
	{
	  /* The symbol was turned from weak to strong.  Discard altname.  */
	  *punt = 1;
	  return;
	}
      else if (symbol_equated_p (weakp))
	{
	  /* The weak symbol has an alternate specified; symp is unneeded.  */
	  S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
	  SA_SET_SYM_TAGNDX (weakp,
	    symbol_get_value_expression (weakp)->X_add_symbol);

	  S_CLEAR_EXTERNAL (symp);
	  *punt = 1;
	  return;
	}
      else
	{
	  /* The weak symbol has been assigned an alternate value.
             Copy this value to symp, and set symp as weakp's alternate.  */
	  if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
	    {
	      S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
	      S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
	    }

	  if (S_IS_DEFINED (weakp))
	    {
	      /* This is a defined weak symbol.  Copy value information
	         from the weak symbol itself to the alternate symbol.  */
	      symbol_set_value_expression (symp,
					   symbol_get_value_expression (weakp));
	      symbol_set_frag (symp, symbol_get_frag (weakp));
	      S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
	    }
	  else
	    {
	      /* This is an undefined weak symbol.
		 Define the alternate symbol to zero.  */
	      S_SET_VALUE (symp, 0);
	      S_SET_SEGMENT (symp, absolute_section);
	    }

	  S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
	  S_SET_STORAGE_CLASS (symp, C_EXT);

	  S_SET_VALUE (weakp, 0);
	  S_SET_SEGMENT (weakp, undefined_section);
	}
    }
#else /* TE_PE */
  if (S_IS_WEAK (symp))
    S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
#endif /* TE_PE */

  if (!S_IS_DEFINED (symp)
      && !S_IS_WEAK (symp)
      && S_GET_STORAGE_CLASS (symp) != C_STAT)
    S_SET_STORAGE_CLASS (symp, C_EXT);

  if (!SF_GET_DEBUG (symp))
    {
      symbolS * real;

      if (!SF_GET_LOCAL (symp)
	  && !SF_GET_STATICS (symp)
	  && S_GET_STORAGE_CLASS (symp) != C_LABEL
	  && symbol_constant_p (symp)
	  && (real = symbol_find_noref (S_GET_NAME (symp), 1))
	  && S_GET_STORAGE_CLASS (real) == C_NULL
	  && real != symp)
	{
	  c_symbol_merge (symp, real);
	  *punt = 1;
	  return;
	}

      if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
	{
	  assert (S_GET_VALUE (symp) == 0);
	  if (S_IS_WEAKREFD (symp))
	    *punt = 1;
	  else
	    S_SET_EXTERNAL (symp);
	}
      else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
	{
	  if (S_GET_SEGMENT (symp) == text_section
	      && symp != seg_info (text_section)->sym)
	    S_SET_STORAGE_CLASS (symp, C_LABEL);
	  else
	    S_SET_STORAGE_CLASS (symp, C_STAT);
	}

      if (SF_GET_PROCESS (symp))
	{
	  if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
	    {
	      if (streq (S_GET_NAME (symp), ".bb"))
		stack_push (block_stack, (char *) &symp);
	      else
		{
		  symbolS *begin;

		  begin = *(symbolS **) stack_pop (block_stack);
		  if (begin == 0)
		    as_warn (_("mismatched .eb"));
		  else
		    next_set_end = begin;
		}
	    }

	  if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
	    {
	      union internal_auxent *auxp;

	      coff_last_function = symp;
	      if (S_GET_NUMBER_AUXILIARY (symp) < 1)
		S_SET_NUMBER_AUXILIARY (symp, 1);
	      auxp = SYM_AUXENT (symp);
	      memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
		      sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
	    }

	  if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
	    {
	      if (coff_last_function == 0)
		as_fatal (_("C_EFCN symbol for %s out of scope"),
			  S_GET_NAME (symp));
	      SA_SET_SYM_FSIZE (coff_last_function,
				(long) (S_GET_VALUE (symp)
					- S_GET_VALUE (coff_last_function)));
	      next_set_end = coff_last_function;
	      coff_last_function = 0;
	    }
	}

      if (S_IS_EXTERNAL (symp))
	S_SET_STORAGE_CLASS (symp, C_EXT);
      else if (SF_GET_LOCAL (symp))
	*punt = 1;

      if (SF_GET_FUNCTION (symp))
	symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
    }

  /* Double check weak symbols.  */
  if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
    as_bad (_("Symbol `%s' can not be both weak and common"),
	    S_GET_NAME (symp));

  if (SF_GET_TAG (symp))
    last_tagP = symp;
  else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
    next_set_end = last_tagP;

#ifdef OBJ_XCOFF
  /* This is pretty horrible, but we have to set *punt correctly in
     order to call SA_SET_SYM_ENDNDX correctly.  */
  if (! symbol_used_in_reloc_p (symp)
      && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
	  || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
	      && ! symbol_get_tc (symp)->output
	      && S_GET_STORAGE_CLASS (symp) != C_FILE)))
    *punt = 1;
#endif

  if (set_end != (symbolS *) NULL
      && ! *punt
      && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
	  || (S_IS_DEFINED (symp)
	      && ! S_IS_COMMON (symp)
	      && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
    {
      SA_SET_SYM_ENDNDX (set_end, symp);
      set_end = NULL;
    }

  if (next_set_end != NULL)
    {
      if (set_end != NULL)
	as_warn ("Warning: internal error: forgetting to set endndx of %s",
		 S_GET_NAME (set_end));
      set_end = next_set_end;
    }

#ifndef OBJ_XCOFF
  if (! *punt
      && S_GET_STORAGE_CLASS (symp) == C_FCN
      && streq (S_GET_NAME (symp), ".bf"))
    {
      if (coff_last_bf != NULL)
	SA_SET_SYM_ENDNDX (coff_last_bf, symp);
      coff_last_bf = symp;
    }
#endif
  if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
    {
      int i;
      struct line_no *lptr;
      alent *l;

      lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
      for (i = 0; lptr; lptr = lptr->next)
	i++;
      lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;

      /* We need i entries for line numbers, plus 1 for the first
	 entry which BFD will override, plus 1 for the last zero
	 entry (a marker for BFD).  */
      l = xmalloc ((i + 2) * sizeof (* l));
      coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
      l[i + 1].line_number = 0;
      l[i + 1].u.sym = NULL;
      for (; i > 0; i--)
	{
	  if (lptr->frag)
	    lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
	  l[i] = lptr->l;
	  lptr = lptr->next;
	}
    }
}
static void nemaweaver_s_lcomm (int xxx ATTRIBUTE_UNUSED)
{
    char *name;
    char c;
    char *p;
    offsetT size;
    symbolS *symbolP;
    offsetT align;
    char *pfrag;
    int align2;
    segT    current_seg    = now_seg;
    subsegT current_subseg = now_subseg;

    name = input_line_pointer;
    c = get_symbol_end ();

    /* Just after name is now '\0'.  */
    p = input_line_pointer;
    *p = c;
    SKIP_WHITESPACE ();
    if (*input_line_pointer != ',')
    {
	as_bad (_("Expected comma after symbol-name: rest of line ignored."));
	ignore_rest_of_line ();
	return;
    }

    input_line_pointer++;		/* skip ',' */
    if ((size = get_absolute_expression ()) < 0)
    {
	as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
	ignore_rest_of_line ();
	return;
    }

    /* The third argument to .lcomm is the alignment.  */
    if (*input_line_pointer != ',')
	align = 8;
    else
    {
	++input_line_pointer;
	align = get_absolute_expression ();
	if (align <= 0)
	{
	    as_warn (_("ignoring bad alignment"));
	    align = 8;
	}
    }

    *p = 0;
    symbolP = symbol_find_or_make (name);
    *p = c;

    if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
    {
	as_bad (_("Ignoring attempt to re-define symbol `%s'."),
		S_GET_NAME (symbolP));
	ignore_rest_of_line ();
	return;
    }

    if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
    {
	as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
		S_GET_NAME (symbolP),
		(long) S_GET_VALUE (symbolP),
		(long) size);

	ignore_rest_of_line ();
	return;
    }

    /* Allocate_bss.  */
    if (align)
    {
	/* Convert to a power of 2 alignment.  */
	for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
	if (align != 1)
	{
	    as_bad (_("Common alignment not a power of 2"));
	    ignore_rest_of_line ();
	    return;
	}
    }
    else