Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
dwarf2dbg.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "dwarf2dbg.h"
#include <filenames.h>
#include "subsegs.h"
#include "elf/dwarf2.h"

Go to the source code of this file.

Classes

struct  line_entry
struct  line_subseg
struct  line_seg
struct  file_entry

Defines

#define INT_MAX   (int) (((unsigned) (-1)) >> 1)
#define INSERT_DIR_SEPARATOR(string, offset)   string[offset] = '/'
#define DWARF2_FORMAT()   dwarf2_format_32bit
#define DWARF2_ADDR_SIZE(bfd)   (bfd_arch_bits_per_address (bfd) / 8)
#define DL_PROLOG   0
#define DL_FILES   1
#define DL_BODY   2
#define DWARF2_USE_FIXED_ADVANCE_PC   0
#define DWARF2_LINE_OPCODE_BASE   13
#define DWARF2_LINE_BASE   -5
#define DWARF2_LINE_RANGE   14
#define DWARF2_LINE_MIN_INSN_LENGTH   1
#define DWARF2_LINE_DEFAULT_IS_STMT   1
#define SPECIAL_LINE(op)   (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE)
#define SPECIAL_ADDR(op)   (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
#define MAX_SPECIAL_ADDR_DELTA   SPECIAL_ADDR(255)
#define TC_DWARF2_EMIT_OFFSET   generic_dwarf2_emit_offset
#define scale_addr_delta(A)

Functions

static struct line_subsegget_line_subseg (segT, subsegT)
static unsigned int get_filenum (const char *, unsigned int)
static struct fragfirst_frag_for_seg (segT)
static struct fraglast_frag_for_seg (segT)
static void out_byte (int)
static void out_opcode (int)
static void out_two (int)
static void out_four (int)
static void out_abbrev (int, int)
static void out_uleb128 (addressT)
static void out_sleb128 (addressT)
static offsetT get_frag_fix (fragS *, segT)
static void out_set_addr (symbolS *)
static int size_inc_line_addr (int, addressT)
static void emit_inc_line_addr (int, addressT, char *, int)
static void out_inc_line_addr (int, addressT)
static void out_fixed_inc_line_addr (int, symbolS *, symbolS *)
static void relax_inc_line_addr (int, symbolS *, symbolS *)
static void process_entries (segT, struct line_entry *)
static void out_file_list (void)
static void out_debug_line (segT)
static void out_debug_aranges (segT, segT)
static void out_debug_abbrev (segT)
static void generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
static void dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
void dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
void dwarf2_where (struct dwarf2_line_info *line)
void dwarf2_set_isa (unsigned int isa)
void dwarf2_emit_insn (int size)
void dwarf2_emit_label (symbolS *label)
char * dwarf2_directive_file (int dummy ATTRIBUTE_UNUSED)
void dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
void dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
int dwarf2dbg_estimate_size_before_relax (fragS *frag)
int dwarf2dbg_relax_frag (fragS *frag)
void dwarf2dbg_convert_frag (fragS *frag)
static void out_debug_ranges (segT ranges_seg)
static void out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
void dwarf2_finish (void)

Variables

static struct line_segall_segs
static struct file_entryfiles
static unsigned int files_in_use
static unsigned int files_allocated
static char ** dirs
static unsigned int dirs_in_use
static unsigned int dirs_allocated
static bfd_boolean loc_directive_seen
bfd_boolean dwarf2_loc_mark_labels
static struct dwarf2_line_info
static unsigned int sizeof_address

Class Documentation

struct line_entry

Definition at line 135 of file dwarf2dbg.c.

Collaboration diagram for line_entry:
Class Members
symbolS * label
struct line_entry * next
struct line_subseg

Definition at line 141 of file dwarf2dbg.c.

Collaboration diagram for line_subseg:
Class Members
struct line_entry * head
struct line_subseg * next
struct line_entry ** ptail
subsegT subseg
struct line_seg

Definition at line 148 of file dwarf2dbg.c.

Collaboration diagram for line_seg:
Class Members
struct line_subseg * head
struct line_seg * next
segT seg
symbolS * text_end
symbolS * text_start
struct file_entry

Definition at line 159 of file dwarf2dbg.c.

Class Members
unsigned int dir
const char * filename

Define Documentation

#define DL_BODY   2

Definition at line 89 of file dwarf2dbg.c.

#define DL_FILES   1

Definition at line 88 of file dwarf2dbg.c.

#define DL_PROLOG   0

Definition at line 87 of file dwarf2dbg.c.

#define DWARF2_ADDR_SIZE (   bfd)    (bfd_arch_bits_per_address (bfd) / 8)

Definition at line 76 of file dwarf2dbg.c.

Definition at line 72 of file dwarf2dbg.c.

#define DWARF2_LINE_BASE   -5

Definition at line 107 of file dwarf2dbg.c.

Definition at line 122 of file dwarf2dbg.c.

Definition at line 118 of file dwarf2dbg.c.

#define DWARF2_LINE_OPCODE_BASE   13

Definition at line 102 of file dwarf2dbg.c.

#define DWARF2_LINE_RANGE   14

Definition at line 112 of file dwarf2dbg.c.

Definition at line 95 of file dwarf2dbg.c.

#define INSERT_DIR_SEPARATOR (   string,
  offset 
)    string[offset] = '/'

Definition at line 68 of file dwarf2dbg.c.

#define INT_MAX   (int) (((unsigned) (-1)) >> 1)

Definition at line 41 of file dwarf2dbg.c.

Definition at line 133 of file dwarf2dbg.c.

#define scale_addr_delta (   A)

Definition at line 826 of file dwarf2dbg.c.

Definition at line 130 of file dwarf2dbg.c.

Definition at line 125 of file dwarf2dbg.c.

Definition at line 216 of file dwarf2dbg.c.


Function Documentation

char* dwarf2_directive_file ( int dummy  ATTRIBUTE_UNUSED)

Definition at line 531 of file dwarf2dbg.c.

{
  offsetT num;
  char *filename;
  int filename_len;

  /* Continue to accept a bare string and pass it off.  */
  SKIP_WHITESPACE ();
  if (*input_line_pointer == '"')
    {
      s_app_file (0);
      return NULL;
    }

  num = get_absolute_expression ();
  filename = demand_copy_C_string (&filename_len);
  if (filename == NULL)
    return NULL;
  demand_empty_rest_of_line ();

  if (num < 1)
    {
      as_bad (_("file number less than one"));
      return NULL;
    }

  if (num < (int) files_in_use && files[num].filename != 0)
    {
      as_bad (_("file number %ld already allocated"), (long) num);
      return NULL;
    }

  get_filenum (filename, num);

  return filename;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2_directive_loc ( int dummy  ATTRIBUTE_UNUSED)

Definition at line 569 of file dwarf2dbg.c.

{
  offsetT filenum, line;

  filenum = get_absolute_expression ();
  SKIP_WHITESPACE ();
  line = get_absolute_expression ();

  if (filenum < 1)
    {
      as_bad (_("file number less than one"));
      return;
    }
  if (filenum >= (int) files_in_use || files[filenum].filename == 0)
    {
      as_bad (_("unassigned file number %ld"), (long) filenum);
      return;
    }

  current.filenum = filenum;
  current.line = line;

#ifndef NO_LISTING
  if (listing)
    {
      if (files[filenum].dir)
       {
         size_t dir_len = strlen (dirs[files[filenum].dir]);
         size_t file_len = strlen (files[filenum].filename);
         char *cp = (char *) alloca (dir_len + 1 + file_len + 1);

         memcpy (cp, dirs[files[filenum].dir], dir_len);
         INSERT_DIR_SEPARATOR (cp, dir_len);
         memcpy (cp + dir_len + 1, files[filenum].filename, file_len);
         cp[dir_len + file_len + 1] = '\0';
         listing_source_file (cp);
       }
      else
       listing_source_file (files[filenum].filename);
      listing_source_line (line);
    }
#endif

  SKIP_WHITESPACE ();
  if (ISDIGIT (*input_line_pointer))
    {
      current.column = get_absolute_expression ();
      SKIP_WHITESPACE ();
    }

  while (ISALPHA (*input_line_pointer))
    {
      char *p, c;
      offsetT value;

      p = input_line_pointer;
      c = get_symbol_end ();

      if (strcmp (p, "basic_block") == 0)
       {
         current.flags |= DWARF2_FLAG_BASIC_BLOCK;
         *input_line_pointer = c;
       }
      else if (strcmp (p, "prologue_end") == 0)
       {
         current.flags |= DWARF2_FLAG_PROLOGUE_END;
         *input_line_pointer = c;
       }
      else if (strcmp (p, "epilogue_begin") == 0)
       {
         current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
         *input_line_pointer = c;
       }
      else if (strcmp (p, "is_stmt") == 0)
       {
         *input_line_pointer = c;
         value = get_absolute_expression ();
         if (value == 0)
           current.flags &= ~DWARF2_FLAG_IS_STMT;
         else if (value == 1)
           current.flags |= DWARF2_FLAG_IS_STMT;
         else
           {
             as_bad (_("is_stmt value not 0 or 1"));
             return;
           }
       }
      else if (strcmp (p, "isa") == 0)
       {
          *input_line_pointer = c;
         value = get_absolute_expression ();
         if (value >= 0)
           current.isa = value;
         else
           {
             as_bad (_("isa number less than zero"));
             return;
           }
       }
      else
       {
         as_bad (_("unknown .loc sub-directive `%s'"), p);
          *input_line_pointer = c;
         return;
       }

      SKIP_WHITESPACE ();
    }

  demand_empty_rest_of_line ();
  loc_directive_seen = TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2_directive_loc_mark_labels ( int dummy  ATTRIBUTE_UNUSED)

Definition at line 683 of file dwarf2dbg.c.

{
  offsetT value = get_absolute_expression ();

  if (value != 0 && value != 1)
    {
      as_bad (_("expected 0 or 1"));
      ignore_rest_of_line ();
    }
  else
    {
      dwarf2_loc_mark_labels = value != 0;
      demand_empty_rest_of_line ();
    }
}

Here is the call graph for this function:

void dwarf2_emit_insn ( int  size)

Definition at line 364 of file dwarf2dbg.c.

{
  struct dwarf2_line_info loc;

  if (loc_directive_seen)
    {
      /* Use the last location established by a .loc directive, not
        the value returned by dwarf2_where().  That calls as_where()
        which will return either the logical input file name (foo.c)
       or the physical input file name (foo.s) and not the file name
       specified in the most recent .loc directive (eg foo.h).  */
      loc = current;

      /* Unless we generate DWARF2 debugging information for each
        assembler line, we only emit one line symbol for one LOC.  */
      if (debug_type != DEBUG_DWARF2)
       loc_directive_seen = FALSE;
    }
  else if (debug_type != DEBUG_DWARF2)
    return;
  else
    dwarf2_where (&loc);

  dwarf2_gen_line_info (frag_now_fix () - size, &loc);

  current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
                   | DWARF2_FLAG_PROLOGUE_END
                   | DWARF2_FLAG_EPILOGUE_BEGIN);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2_emit_label ( symbolS *  label)

Definition at line 398 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2_finish ( void  )

Definition at line 1644 of file dwarf2dbg.c.

{
  segT line_seg;
  struct line_seg *s;
  segT info_seg;
  int emit_other_sections = 0;

  info_seg = bfd_get_section_by_name (stdoutput, ".debug_info");
  emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg);

  if (!all_segs && emit_other_sections)
    /* There is no line information and no non-empty .debug_info
       section.  */
    return;

  /* Calculate the size of an address for the target machine.  */
  sizeof_address = DWARF2_ADDR_SIZE (stdoutput);

  /* Create and switch to the line number section.  */
  line_seg = subseg_new (".debug_line", 0);
  bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING);

  /* For each subsection, chain the debug entries together.  */
  for (s = all_segs; s; s = s->next)
    {
      struct line_subseg *ss = s->head;
      struct line_entry **ptail = ss->ptail;

      while ((ss = ss->next) != NULL)
       {
         *ptail = ss->head;
         ptail = ss->ptail;
       }
    }

  out_debug_line (line_seg);

  /* If this is assembler generated line info, and there is no
     debug_info already, we need .debug_info and .debug_abbrev
     sections as well.  */
  if (emit_other_sections)
    {
      segT abbrev_seg;
      segT aranges_seg;
      segT ranges_seg;

      assert (all_segs);
      
      info_seg = subseg_new (".debug_info", 0);
      abbrev_seg = subseg_new (".debug_abbrev", 0);
      aranges_seg = subseg_new (".debug_aranges", 0);

      bfd_set_section_flags (stdoutput, info_seg,
                          SEC_READONLY | SEC_DEBUGGING);
      bfd_set_section_flags (stdoutput, abbrev_seg,
                          SEC_READONLY | SEC_DEBUGGING);
      bfd_set_section_flags (stdoutput, aranges_seg,
                          SEC_READONLY | SEC_DEBUGGING);

      record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1);

      if (all_segs->next == NULL)
       ranges_seg = NULL;
      else
       {
         ranges_seg = subseg_new (".debug_ranges", 0);
         bfd_set_section_flags (stdoutput, ranges_seg, 
                             SEC_READONLY | SEC_DEBUGGING);
         record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1);
         out_debug_ranges (ranges_seg);
       }

      out_debug_aranges (aranges_seg, info_seg);
      out_debug_abbrev (abbrev_seg);
      out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 302 of file dwarf2dbg.c.

{
  static unsigned int line = -1;
  static unsigned int filenum = -1;

  symbolS *sym;

  /* Early out for as-yet incomplete location information.  */
  if (loc->filenum == 0 || loc->line == 0)
    return;

  /* Don't emit sequences of line symbols for the same line when the
     symbols apply to assembler code.  It is necessary to emit
     duplicate line symbols when a compiler asks for them, because GDB
     uses them to determine the end of the prologue.  */
  if (debug_type == DEBUG_DWARF2
      && line == loc->line && filenum == loc->filenum)
    return;

  line = loc->line;
  filenum = loc->filenum;

  sym = symbol_temp_new (now_seg, ofs, frag_now);
  dwarf2_gen_line_info_1 (sym, loc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dwarf2_gen_line_info_1 ( symbolS *  label,
struct dwarf2_line_info loc 
) [static]

Definition at line 284 of file dwarf2dbg.c.

{
  struct line_subseg *ss;
  struct line_entry *e;

  e = (struct line_entry *) xmalloc (sizeof (*e));
  e->next = NULL;
  e->label = label;
  e->loc = *loc;

  ss = get_line_subseg (now_seg, now_subseg);
  *ss->ptail = e;
  ss->ptail = &e->next;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2_set_isa ( unsigned int  isa)

Definition at line 353 of file dwarf2dbg.c.

{
  current.isa = isa;
}

Definition at line 334 of file dwarf2dbg.c.

{
  if (debug_type == DEBUG_DWARF2)
    {
      char *filename;
      as_where (&filename, &line->line);
      line->filenum = get_filenum (filename, 0);
      line->column = 0;
      line->flags = DWARF2_FLAG_IS_STMT;
      line->isa = current.isa;
    }
  else
    *line = current;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dwarf2dbg_convert_frag ( fragS *  frag)

Definition at line 1096 of file dwarf2dbg.c.

{
  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.  */
  assert (frag->fr_var >= (int) frag->fr_subtype);

  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1063 of file dwarf2dbg.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int dwarf2dbg_relax_frag ( fragS *  frag)

Definition at line 1081 of file dwarf2dbg.c.

{
  int old_size, new_size;

  old_size = frag->fr_subtype;
  new_size = dwarf2dbg_estimate_size_before_relax (frag);

  return new_size - old_size;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void emit_inc_line_addr ( int  line_delta,
addressT  addr_delta,
char *  p,
int  len 
) [static]

Definition at line 896 of file dwarf2dbg.c.

{
  unsigned int tmp, opcode;
  int need_copy = 0;
  char *end = p + len;

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

  /* Scale the address delta by the minimum instruction length.  */
  scale_addr_delta (&addr_delta);

  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.
     We cannot use special opcodes here, since we want the end_sequence
     to emit the matrix entry.  */
  if (line_delta == INT_MAX)
    {
      if (addr_delta == MAX_SPECIAL_ADDR_DELTA)
       *p++ = DW_LNS_const_add_pc;
      else
       {
         *p++ = DW_LNS_advance_pc;
         p += output_leb128 (p, addr_delta, 0);
       }

      *p++ = DW_LNS_extended_op;
      *p++ = 1;
      *p++ = DW_LNE_end_sequence;
      goto done;
    }

  /* Bias the line delta by the base.  */
  tmp = line_delta - DWARF2_LINE_BASE;

  /* If the line increment is out of range of a special opcode, we
     must encode it with DW_LNS_advance_line.  */
  if (tmp >= DWARF2_LINE_RANGE)
    {
      *p++ = DW_LNS_advance_line;
      p += output_leb128 (p, line_delta, 1);

      line_delta = 0;
      tmp = 0 - DWARF2_LINE_BASE;
      need_copy = 1;
    }

  /* Prettier, I think, to use DW_LNS_copy instead of a "line +0, addr +0"
     special opcode.  */
  if (line_delta == 0 && addr_delta == 0)
    {
      *p++ = DW_LNS_copy;
      goto done;
    }

  /* Bias the opcode by the special opcode base.  */
  tmp += DWARF2_LINE_OPCODE_BASE;

  /* Avoid overflow when addr_delta is large.  */
  if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA)
    {
      /* Try using a special opcode.  */
      opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
      if (opcode <= 255)
       {
         *p++ = opcode;
         goto done;
       }

      /* Try using DW_LNS_const_add_pc followed by special op.  */
      opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
      if (opcode <= 255)
       {
         *p++ = DW_LNS_const_add_pc;
         *p++ = opcode;
         goto done;
       }
    }

  /* Otherwise use DW_LNS_advance_pc.  */
  *p++ = DW_LNS_advance_pc;
  p += output_leb128 (p, addr_delta, 0);

  if (need_copy)
    *p++ = DW_LNS_copy;
  else
    *p++ = tmp;

 done:
  assert (p == end);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct frag * first_frag_for_seg ( segT  seg) [static, read]

Definition at line 700 of file dwarf2dbg.c.

{
  return seg_info (seg)->frchainP->frch_root;
}

Here is the caller graph for this function:

static void generic_dwarf2_emit_offset ( symbolS *  symbol,
unsigned int  size 
) [static]

Definition at line 221 of file dwarf2dbg.c.

{
  expressionS expr;

  expr.X_op = O_symbol;
  expr.X_add_symbol = symbol;
  expr.X_add_number = 0;
  emit_expr (&expr, size);
}

Here is the call graph for this function:

static unsigned int get_filenum ( const char *  filename,
unsigned int  num 
) [static]

Definition at line 431 of file dwarf2dbg.c.

{
  static unsigned int last_used, last_used_dir_len;
  const char *file;
  size_t dir_len;
  unsigned int i, dir;

  if (num == 0 && last_used)
    {
      if (! files[last_used].dir
         && strcmp (filename, files[last_used].filename) == 0)
       return last_used;
      if (files[last_used].dir
         && strncmp (filename, dirs[files[last_used].dir],
                    last_used_dir_len) == 0
         && IS_DIR_SEPARATOR (filename [last_used_dir_len])
         && strcmp (filename + last_used_dir_len + 1,
                   files[last_used].filename) == 0)
       return last_used;
    }

  file = lbasename (filename);
  /* Don't make empty string from / or A: from A:/ .  */
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  if (file <= filename + 3)
    file = filename;
#else
  if (file == filename + 1)
    file = filename;
#endif
  dir_len = file - filename;

  dir = 0;
  if (dir_len)
    {
      --dir_len;
      for (dir = 1; dir < dirs_in_use; ++dir)
       if (strncmp (filename, dirs[dir], dir_len) == 0
           && dirs[dir][dir_len] == '\0')
         break;

      if (dir >= dirs_in_use)
       {
         if (dir >= dirs_allocated)
           {
             dirs_allocated = dir + 32;
             dirs = (char **)
                   xrealloc (dirs, (dir + 32) * sizeof (const char *));
           }

         dirs[dir] = xmalloc (dir_len + 1);
         memcpy (dirs[dir], filename, dir_len);
         dirs[dir][dir_len] = '\0';
         dirs_in_use = dir + 1;
       }
    }

  if (num == 0)
    {
      for (i = 1; i < files_in_use; ++i)
       if (files[i].dir == dir
           && files[i].filename
           && strcmp (file, files[i].filename) == 0)
         {
           last_used = i;
           last_used_dir_len = dir_len;
           return i;
         }
    }
  else
    i = num;

  if (i >= files_allocated)
    {
      unsigned int old = files_allocated;

      files_allocated = i + 32;
      files = (struct file_entry *)
       xrealloc (files, (i + 32) * sizeof (struct file_entry));

      memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry));
    }

  files[i].filename = num ? file : xstrdup (file);
  files[i].dir = dir;
  if (files_in_use < i + 1)
    files_in_use = i + 1;
  last_used = i;
  last_used_dir_len = dir_len;

  return i;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static offsetT get_frag_fix ( fragS *  frag,
segT  seg 
) [static]

Definition at line 776 of file dwarf2dbg.c.

{
  frchainS *fr;

  if (frag->fr_next)
    return frag->fr_fix;

  /* If a fragment is the last in the chain, special measures must be
     taken to find its size before relaxation, since it may be pending
     on some subsegment chain.  */
  for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next)
    if (fr->frch_last == frag)
      return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal;

  abort ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct line_subseg * get_line_subseg ( segT  seg,
subsegT  subseg 
) [static, read]

Definition at line 235 of file dwarf2dbg.c.

{
  static segT last_seg;
  static subsegT last_subseg;
  static struct line_subseg *last_line_subseg;

  struct line_seg **ps, *s;
  struct line_subseg **pss, *ss;

  if (seg == last_seg && subseg == last_subseg)
    return last_line_subseg;

  for (ps = &all_segs; (s = *ps) != NULL; ps = &s->next)
    if (s->seg == seg)
      goto found_seg;

  s = (struct line_seg *) xmalloc (sizeof (*s));
  s->next = NULL;
  s->seg = seg;
  s->head = NULL;
  *ps = s;

 found_seg:
  for (pss = &s->head; (ss = *pss) != NULL ; pss = &ss->next)
    {
      if (ss->subseg == subseg)
       goto found_subseg;
      if (ss->subseg > subseg)
       break;
    }

  ss = (struct line_subseg *) xmalloc (sizeof (*ss));
  ss->next = *pss;
  ss->subseg = subseg;
  ss->head = NULL;
  ss->ptail = &ss->head;
  *pss = ss;

 found_subseg:
  last_seg = seg;
  last_subseg = subseg;
  last_line_subseg = ss;

  return ss;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct frag * last_frag_for_seg ( segT  seg) [static, read]

Definition at line 706 of file dwarf2dbg.c.

{
  frchainS *f = seg_info (seg)->frchainP;

  while (f->frch_next != NULL)
    f = f->frch_next;

  return f->frch_last;
}

Here is the caller graph for this function:

static void out_abbrev ( int  name,
int  form 
) [inline, static]

Definition at line 767 of file dwarf2dbg.c.

{
  out_uleb128 (name);
  out_uleb128 (form);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_byte ( int  byte) [inline, static]

Definition at line 719 of file dwarf2dbg.c.

{
  FRAG_APPEND_1_CHAR (byte);
}

Here is the caller graph for this function:

static void out_debug_abbrev ( segT  abbrev_seg) [static]

Definition at line 1481 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_debug_aranges ( segT  aranges_seg,
segT  info_seg 
) [static]

Definition at line 1405 of file dwarf2dbg.c.

{
  unsigned int addr_size = sizeof_address;
  addressT size, skip;
  struct line_seg *s;
  expressionS expr;
  char *p;

  size = 4 + 2 + 4 + 1 + 1;

  skip = 2 * addr_size - (size & (2 * addr_size - 1));
  if (skip == 2 * addr_size)
    skip = 0;
  size += skip;

  for (s = all_segs; s; s = s->next)
    size += 2 * addr_size;

  size += 2 * addr_size;

  subseg_set (aranges_seg, 0);

  /* Length of the compilation unit.  */
  out_four (size - 4);

  /* Version.  */
  out_two (2);

  /* Offset to .debug_info.  */
  /* ??? sizeof_offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), 4);

  /* Size of an address (offset portion).  */
  out_byte (addr_size);

  /* Size of a segment descriptor.  */
  out_byte (0);

  /* Align the header.  */
  if (skip)
    frag_align (ffs (2 * addr_size) - 1, 0, 0);

  for (s = all_segs; s; s = s->next)
    {
      fragS *frag;
      symbolS *beg, *end;

      frag = first_frag_for_seg (s->seg);
      beg = symbol_temp_new (s->seg, 0, frag);
      s->text_start = beg;

      frag = last_frag_for_seg (s->seg);
      end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
      s->text_end = end;

      expr.X_op = O_symbol;
      expr.X_add_symbol = beg;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);

      expr.X_op = O_subtract;
      expr.X_add_symbol = end;
      expr.X_op_symbol = beg;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);
    }

  p = frag_more (2 * addr_size);
  md_number_to_chars (p, 0, addr_size);
  md_number_to_chars (p + addr_size, 0, addr_size);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_debug_info ( segT  info_seg,
segT  abbrev_seg,
segT  line_seg,
segT  ranges_seg 
) [static]

Definition at line 1514 of file dwarf2dbg.c.

{
  char producer[128];
  char *comp_dir;
  expressionS expr;
  symbolS *info_start;
  symbolS *info_end;
  char *p;
  int len;
  enum dwarf2_format d2f;
  int sizeof_offset;

  subseg_set (info_seg, 0);

  info_start = symbol_temp_new_now ();
  info_end = symbol_temp_make ();

  /* Compilation Unit length.  */
  expr.X_op = O_subtract;
  expr.X_add_symbol = info_end;
  expr.X_op_symbol = info_start;

  d2f = DWARF2_FORMAT ();
  if (d2f == dwarf2_format_32bit)
    {
      expr.X_add_number = -4;
      emit_expr (&expr, 4);
      sizeof_offset = 4;
    }
  else if (d2f == dwarf2_format_64bit)
    {
      expr.X_add_number = -12;
      out_four (-1);
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else if (d2f == dwarf2_format_64bit_irix)
    {
      expr.X_add_number = -8;
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else
    {
      as_fatal (_("internal error: unknown dwarf2 format"));
    }

  /* DWARF version.  */
  out_two (2);

  /* .debug_abbrev offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);

  /* Target address size.  */
  out_byte (sizeof_address);

  /* DW_TAG_compile_unit DIE abbrev */
  out_uleb128 (1);

  /* DW_AT_stmt_list */
  /* ??? sizeof_offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (line_seg), 4);

  /* These two attributes are emitted if all of the code is contiguous.  */
  if (all_segs->next == NULL)
    {
      /* DW_AT_low_pc */
      expr.X_op = O_symbol;
      expr.X_add_symbol = all_segs->text_start;
      expr.X_add_number = 0;
      emit_expr (&expr, sizeof_address);

      /* DW_AT_high_pc */
      expr.X_op = O_symbol;
      expr.X_add_symbol = all_segs->text_end;
      expr.X_add_number = 0;
      emit_expr (&expr, sizeof_address);
    }
  else
    {
      /* This attribute is emitted if the code is disjoint.  */
      /* DW_AT_ranges.  */
      TC_DWARF2_EMIT_OFFSET (section_symbol (ranges_seg), sizeof_offset);
    }

  /* DW_AT_name.  We don't have the actual file name that was present
     on the command line, so assume files[1] is the main input file.
     We're not supposed to get called unless at least one line number
     entry was emitted, so this should always be defined.  */
  if (!files || files_in_use < 1)
    abort ();
  if (files[1].dir)
    {
      len = strlen (dirs[files[1].dir]);
      p = frag_more (len + 1);
      memcpy (p, dirs[files[1].dir], len);
      INSERT_DIR_SEPARATOR (p, len);
    }
  len = strlen (files[1].filename) + 1;
  p = frag_more (len);
  memcpy (p, files[1].filename, len);

  /* DW_AT_comp_dir */
  comp_dir = getpwd ();
  len = strlen (comp_dir) + 1;
  p = frag_more (len);
  memcpy (p, comp_dir, len);

  /* DW_AT_producer */
  sprintf (producer, "GNU AS %s", VERSION);
  len = strlen (producer) + 1;
  p = frag_more (len);
  memcpy (p, producer, len);

  /* DW_AT_language.  Yes, this is probably not really MIPS, but the
     dwarf2 draft has no standard code for assembler.  */
  out_two (DW_LANG_Mips_Assembler);

  symbol_set_value_now (info_end);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_debug_line ( segT  line_seg) [static]

Definition at line 1266 of file dwarf2dbg.c.

{
  expressionS expr;
  symbolS *line_start;
  symbolS *prologue_end;
  symbolS *line_end;
  struct line_seg *s;
  enum dwarf2_format d2f;
  int sizeof_offset;

  subseg_set (line_seg, 0);

  line_start = symbol_temp_new_now ();
  prologue_end = symbol_temp_make ();
  line_end = symbol_temp_make ();

  /* Total length of the information for this compilation unit.  */
  expr.X_op = O_subtract;
  expr.X_add_symbol = line_end;
  expr.X_op_symbol = line_start;

  d2f = DWARF2_FORMAT ();
  if (d2f == dwarf2_format_32bit)
    {
      expr.X_add_number = -4;
      emit_expr (&expr, 4);
      sizeof_offset = 4;
    }
  else if (d2f == dwarf2_format_64bit)
    {
      expr.X_add_number = -12;
      out_four (-1);
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else if (d2f == dwarf2_format_64bit_irix)
    {
      expr.X_add_number = -8;
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else
    {
      as_fatal (_("internal error: unknown dwarf2 format"));
    }

  /* Version.  */
  out_two (2);

  /* Length of the prologue following this length.  */
  expr.X_op = O_subtract;
  expr.X_add_symbol = prologue_end;
  expr.X_op_symbol = line_start;
  expr.X_add_number = - (4 + 2 + 4);
  emit_expr (&expr, sizeof_offset);

  /* Parameters of the state machine.  */
  out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
  out_byte (DWARF2_LINE_DEFAULT_IS_STMT);
  out_byte (DWARF2_LINE_BASE);
  out_byte (DWARF2_LINE_RANGE);
  out_byte (DWARF2_LINE_OPCODE_BASE);

  /* Standard opcode lengths.  */
  out_byte (0);                    /* DW_LNS_copy */
  out_byte (1);                    /* DW_LNS_advance_pc */
  out_byte (1);                    /* DW_LNS_advance_line */
  out_byte (1);                    /* DW_LNS_set_file */
  out_byte (1);                    /* DW_LNS_set_column */
  out_byte (0);                    /* DW_LNS_negate_stmt */
  out_byte (0);                    /* DW_LNS_set_basic_block */
  out_byte (0);                    /* DW_LNS_const_add_pc */
  out_byte (1);                    /* DW_LNS_fixed_advance_pc */
  out_byte (0);                    /* DW_LNS_set_prologue_end */
  out_byte (0);                    /* DW_LNS_set_epilogue_begin */
  out_byte (1);                    /* DW_LNS_set_isa */

  out_file_list ();

  symbol_set_value_now (prologue_end);

  /* For each section, emit a statement program.  */
  for (s = all_segs; s; s = s->next)
    process_entries (s->seg, s->head->head);

  symbol_set_value_now (line_end);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_debug_ranges ( segT  ranges_seg) [static]

Definition at line 1355 of file dwarf2dbg.c.

{
  unsigned int addr_size = sizeof_address;
  struct line_seg *s;
  expressionS expr;
  unsigned int i;

  subseg_set (ranges_seg, 0);

  /* Base Address Entry.  */
  for (i = 0; i < addr_size; i++) 
    out_byte (0xff);
  for (i = 0; i < addr_size; i++) 
    out_byte (0);

  /* Range List Entry.  */
  for (s = all_segs; s; s = s->next)
    {
      fragS *frag;
      symbolS *beg, *end;

      frag = first_frag_for_seg (s->seg);
      beg = symbol_temp_new (s->seg, 0, frag);
      s->text_start = beg;

      frag = last_frag_for_seg (s->seg);
      end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
      s->text_end = end;

      expr.X_op = O_symbol;
      expr.X_add_symbol = beg;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);

      expr.X_op = O_symbol;
      expr.X_add_symbol = end;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);
    }

  /* End of Range Entry.   */
  for (i = 0; i < addr_size; i++) 
    out_byte (0);
  for (i = 0; i < addr_size; i++) 
    out_byte (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_file_list ( void  ) [static]

Definition at line 1224 of file dwarf2dbg.c.

{
  size_t size;
  char *cp;
  unsigned int i;

  /* Emit directory list.  */
  for (i = 1; i < dirs_in_use; ++i)
    {
      size = strlen (dirs[i]) + 1;
      cp = frag_more (size);
      memcpy (cp, dirs[i], size);
    }
  /* Terminate it.  */
  out_byte ('\0');

  for (i = 1; i < files_in_use; ++i)
    {
      if (files[i].filename == NULL)
       {
         as_bad (_("unassigned file number %ld"), (long) i);
         /* Prevent a crash later, particularly for file 1.  */
         files[i].filename = "";
         continue;
       }

      size = strlen (files[i].filename) + 1;
      cp = frag_more (size);
      memcpy (cp, files[i].filename, size);

      out_uleb128 (files[i].dir);  /* directory number */
      out_uleb128 (0);                    /* last modification timestamp */
      out_uleb128 (0);                    /* filesize */
    }

  /* Terminate filename list.  */
  out_byte (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_fixed_inc_line_addr ( int  line_delta,
symbolS *  to_sym,
symbolS *  from_sym 
) [static]

Definition at line 1003 of file dwarf2dbg.c.

{
  expressionS expr;

  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.  */
  if (line_delta == INT_MAX)
    {
      out_opcode (DW_LNS_fixed_advance_pc);
      expr.X_op = O_subtract;
      expr.X_add_symbol = to_sym;
      expr.X_op_symbol = from_sym;
      expr.X_add_number = 0;
      emit_expr (&expr, 2);

      out_opcode (DW_LNS_extended_op);
      out_byte (1);
      out_opcode (DW_LNE_end_sequence);
      return;
    }

  out_opcode (DW_LNS_advance_line);
  out_sleb128 (line_delta);

  out_opcode (DW_LNS_fixed_advance_pc);
  expr.X_op = O_subtract;
  expr.X_add_symbol = to_sym;
  expr.X_op_symbol = from_sym;
  expr.X_add_number = 0;
  emit_expr (&expr, 2);

  out_opcode (DW_LNS_copy);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_four ( int  data) [inline, static]

Definition at line 743 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_inc_line_addr ( int  line_delta,
addressT  addr_delta 
) [static]

Definition at line 991 of file dwarf2dbg.c.

{
  int len = size_inc_line_addr (line_delta, addr_delta);
  emit_inc_line_addr (line_delta, addr_delta, frag_more (len), len);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_opcode ( int  opc) [inline, static]

Definition at line 727 of file dwarf2dbg.c.

{
  out_byte (opc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_set_addr ( symbolS *  sym) [static]

Definition at line 796 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_sleb128 ( addressT  value) [static]

Definition at line 759 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_two ( int  data) [inline, static]

Definition at line 735 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void out_uleb128 ( addressT  value) [static]

Definition at line 751 of file dwarf2dbg.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_entries ( segT  seg,
struct line_entry e 
) [static]

Definition at line 1120 of file dwarf2dbg.c.

{
  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 (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 (DWARF2_USE_FIXED_ADVANCE_PC)
       out_fixed_inc_line_addr (line_delta, lab, last_lab);
      else if (frag == last_frag)
       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 (DWARF2_USE_FIXED_ADVANCE_PC)
    {
      lab = symbol_temp_new (seg, frag_ofs, frag);
      out_fixed_inc_line_addr (INT_MAX, lab, last_lab);
    }
  else if (frag == last_frag)
    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);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void relax_inc_line_addr ( int  line_delta,
symbolS *  to_sym,
symbolS *  from_sym 
) [static]

Definition at line 1040 of file dwarf2dbg.c.

{
  expressionS expr;
  int max_chars;

  expr.X_op = O_subtract;
  expr.X_add_symbol = to_sym;
  expr.X_op_symbol = from_sym;
  expr.X_add_number = 0;

  /* The maximum size of the frag is the line delta with a maximum
     sized address delta.  */
  max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH);

  frag_var (rs_dwarf2dbg, max_chars, max_chars, 1,
           make_expr_symbol (&expr), line_delta, NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int size_inc_line_addr ( int  line_delta,
addressT  addr_delta 
) [static]

Definition at line 837 of file dwarf2dbg.c.

{
  unsigned int tmp, opcode;
  int len = 0;

  /* Scale the address delta by the minimum instruction length.  */
  scale_addr_delta (&addr_delta);

  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.
     We cannot use special opcodes here, since we want the end_sequence
     to emit the matrix entry.  */
  if (line_delta == INT_MAX)
    {
      if (addr_delta == MAX_SPECIAL_ADDR_DELTA)
       len = 1;
      else
       len = 1 + sizeof_leb128 (addr_delta, 0);
      return len + 3;
    }

  /* Bias the line delta by the base.  */
  tmp = line_delta - DWARF2_LINE_BASE;

  /* If the line increment is out of range of a special opcode, we
     must encode it with DW_LNS_advance_line.  */
  if (tmp >= DWARF2_LINE_RANGE)
    {
      len = 1 + sizeof_leb128 (line_delta, 1);
      line_delta = 0;
      tmp = 0 - DWARF2_LINE_BASE;
    }

  /* Bias the opcode by the special opcode base.  */
  tmp += DWARF2_LINE_OPCODE_BASE;

  /* Avoid overflow when addr_delta is large.  */
  if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA)
    {
      /* Try using a special opcode.  */
      opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
      if (opcode <= 255)
       return len + 1;

      /* Try using DW_LNS_const_add_pc followed by special op.  */
      opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
      if (opcode <= 255)
       return len + 2;
    }

  /* Otherwise use DW_LNS_advance_pc.  */
  len += 1 + sizeof_leb128 (addr_delta, 0);

  /* DW_LNS_copy or special opcode.  */
  len += 1;

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 157 of file dwarf2dbg.c.

char** dirs [static]

Definition at line 170 of file dwarf2dbg.c.

Definition at line 172 of file dwarf2dbg.c.

Definition at line 171 of file dwarf2dbg.c.

Initial value:

Definition at line 183 of file dwarf2dbg.c.

Definition at line 180 of file dwarf2dbg.c.

struct file_entry* files [static]

Definition at line 165 of file dwarf2dbg.c.

Definition at line 167 of file dwarf2dbg.c.

Definition at line 166 of file dwarf2dbg.c.

Definition at line 176 of file dwarf2dbg.c.

Definition at line 189 of file dwarf2dbg.c.