Esempio n. 1
0
static void
subseg_set_rest (segT seg, subsegT subseg)
{
  frchainS *frcP;		/* crawl frchain chain */
  frchainS **lastPP;		/* address of last pointer */
  frchainS *newP;		/* address of new frchain */
  segment_info_type *seginfo;

  mri_common_symbol = NULL;

  if (frag_now && frchain_now)
    frchain_now->frch_frag_now = frag_now;

  gas_assert (frchain_now == 0
	  || frchain_now->frch_last == frag_now);

  subseg_change (seg, (int) subseg);

  seginfo = seg_info (seg);

  /* Attempt to find or make a frchain for that subsection.
     We keep the list sorted by subsection number.  */
  for (frcP = *(lastPP = &seginfo->frchainP);
       frcP != NULL;
       frcP = *(lastPP = &frcP->frch_next))
    if (frcP->frch_subseg >= subseg)
      break;

  if (frcP == NULL || frcP->frch_subseg != subseg)
    {
      /* This should be the only code that creates a frchainS.  */

      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
      newP->frch_subseg = subseg;
      newP->fix_root = NULL;
      newP->fix_tail = NULL;
      obstack_begin (&newP->frch_obstack, chunksize);
#if __GNUC__ >= 2
      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
#endif
      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
      newP->frch_frag_now->fr_type = rs_fill;
      newP->frch_cfi_data = NULL;

      newP->frch_root = newP->frch_last = newP->frch_frag_now;

      *lastPP = newP;
      newP->frch_next = frcP;
      frcP = newP;
    }

  frchain_now = frcP;
  frag_now = frcP->frch_frag_now;

  gas_assert (frchain_now->frch_last == frag_now);
}
Esempio n. 2
0
static void
emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
			  char *p, int len)
{
  expressionS *pexp;
  segT line_seg;
  char *end = p + len;

  /* Line number sequences cannot go backward in addresses.  This means
     we've incorrectly ordered the statements in the sequence.  */
  gas_assert ((offsetT) addr_delta >= 0);

  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.  */
  if (line_delta != INT_MAX)
    {
      *p++ = DW_LNS_advance_line;
      p += output_leb128 (p, line_delta, 1);
    }

  pexp = symbol_get_value_expression (frag->fr_symbol);
  line_seg = subseg_get (".debug_line", 0);

  /* The DW_LNS_fixed_advance_pc opcode has a 2-byte operand so it can
     advance the address by at most 64K.  Linker relaxation (without
     which this function would not be used) could change the operand by
     an unknown amount.  If the address increment is getting close to
     the limit, just reset the address.  */
  if (addr_delta > 50000)
    {
      symbolS *to_sym;
      expressionS exp;

      gas_assert (pexp->X_op == O_subtract);
      to_sym = pexp->X_add_symbol;

      *p++ = DW_LNS_extended_op;
      p += output_leb128 (p, sizeof_address + 1, 0);
      *p++ = DW_LNE_set_address;
      exp.X_op = O_symbol;
      exp.X_add_symbol = to_sym;
      exp.X_add_number = 0;
      subseg_change (line_seg, 0);
      emit_expr_fix (&exp, sizeof_address, frag, p);
      p += sizeof_address;
    }
  else
    {
      *p++ = DW_LNS_fixed_advance_pc;
      subseg_change (line_seg, 0);
      emit_expr_fix (pexp, 2, frag, p);
      p += 2;
    }

  if (line_delta == INT_MAX)
    {
      *p++ = DW_LNS_extended_op;
      *p++ = 1;
      *p++ = DW_LNE_end_sequence;
    }
  else
    *p++ = DW_LNS_copy;

  gas_assert (p == end);
}