This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

patch for gas/dwarf2dbg.c, can fail when new frags are created


Addresses are kept track of as offsets within the current frag.  When a new
frag is created, we need to emit an absolute address before we can use offsets
again.  The current code that checks for a new frag does not work.  It assumes
that if the offset decreases then we are in a new frag, but this is not good
enough.

If gcc emits alignment after branches, then it is common to get something like
	.align X
	.loc 0 10 0
	alu insn 1
	branch insn
	.align X
	.loc 0 11 0
	alu insn 2
In this case, we emit an absolute address and set the offset to 0 when we see
alu insn 1.  When we get to alu insn 2, the offset is again 0, and the
	if (addr < ls.sm.addr)
test does not notice the new frag.  This results in linenumber table info that
claims lines 10 and 11 are at the same address.

The following patch fixes this by directly keeping track of frags, so that we
can tell when we are in a new one.

Thu Aug 26 15:44:52 1999  Jim Wilson  <wilson@cygnus.com>

	* dwarf2dbg.c (MAX_SPECIAL_ADDR_DELTA): Correct typo in comment.
	(struct ls): Add frag field.  Initialize it to zero.
	(out_end_sequence): New local text_frag.  Set it while in text section.
	Replace address check with frag check.  Set ls.frag to text_frag if
	out_set_addr called.
	(dwarf2_gen_line_info): Add explanatory comment.  New local saved_frag.
	Set it before switching sections.  Replace address check with frag
	check.  Set ls.frag to saved_frag if out_set_addr called.

Index: dwarf2dbg.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/dwarf2dbg.c,v
retrieving revision 1.9
diff -p -r1.9 dwarf2dbg.c
*** dwarf2dbg.c	1999/08/26 05:16:45	1.9
--- dwarf2dbg.c	1999/08/26 22:41:40
***************
*** 86,92 ****
     DWARF2_LINE_MIN_INSN_LENGTH.  */
  #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
  
! /* The maximum address skip amont that can be encoded with a special op: */
  #define MAX_SPECIAL_ADDR_DELTA		SPECIAL_ADDR(255)
  
  #define INITIAL_STATE						\
--- 86,92 ----
     DWARF2_LINE_MIN_INSN_LENGTH.  */
  #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
  
! /* The maximum address skip amount that can be encoded with a special op: */
  #define MAX_SPECIAL_ADDR_DELTA		SPECIAL_ADDR(255)
  
  #define INITIAL_STATE						\
*************** static struct
*** 118,123 ****
--- 118,124 ----
      unsigned int
        any_dwarf2_directives : 1;	/* did we emit any DWARF2 line debug directives? */
  
+     fragS *frag;	/* frag that "addr" is relative to */
      segT text_seg;	/* text segment "addr" is relative to */
      subsegT text_subseg;
      segT line_seg;	/* ".debug_line" segment */
*************** ls =
*** 149,154 ****
--- 150,156 ----
      0,
      0,
      0,
+     0,
      NULL,
      { NULL, 0, 0, 0, 0 },
      0,
*************** static void
*** 324,329 ****
--- 326,332 ----
  out_end_sequence ()
  {
    addressT addr, delta;
+   fragS *text_frag;
  
    if (ls.text_seg)
      {
*************** out_end_sequence ()
*** 333,343 ****
  #else
        addr = frag_now_fix ();
  #endif
        subseg_set (ls.line_seg, DL_BODY);
!       if (addr < ls.sm.addr)
  	{
  	  out_set_addr (addr);
  	  ls.sm.addr = addr;
  	}
        else
  	{
--- 336,348 ----
  #else
        addr = frag_now_fix ();
  #endif
+       text_frag = frag_now;
        subseg_set (ls.line_seg, DL_BODY);
!       if (text_frag != ls.frag)
  	{
  	  out_set_addr (addr);
  	  ls.sm.addr = addr;
+ 	  ls.frag = text_frag;
  	}
        else
  	{
*************** get_filenum (filenum, file)
*** 407,412 ****
--- 412,420 ----
    return ++ls.num_filenames;
  }
  
+ /* Emit an entry in the line number table if the address or line has changed.
+    ADDR is relative to the current frag in the text section.  */
+ 
  void
  dwarf2_gen_line_info (addr, l)
       addressT addr;
*************** dwarf2_gen_line_info (addr, l)
*** 416,421 ****
--- 424,430 ----
    unsigned int any_output = 0;
    subsegT saved_subseg;
    segT saved_seg;
+   fragS *saved_frag;
  
    if (flag_debug)
      fprintf (stderr, "line: addr %lx file `%s' line %u col %u flags %x\n",
*************** dwarf2_gen_line_info (addr, l)
*** 438,443 ****
--- 447,453 ----
       them.  */
    saved_seg = now_seg;
    saved_subseg = now_subseg;
+   saved_frag = frag_now;
  
    if (!ls.line_seg)
      {
*************** dwarf2_gen_line_info (addr, l)
*** 473,478 ****
--- 483,489 ----
        ls.text_subseg = saved_subseg;
        out_set_addr (addr);
        ls.sm.addr = addr;
+       ls.frag = saved_frag;
      }
  
    if (ls.sm.filenum != filenum)
*************** dwarf2_gen_line_info (addr, l)
*** 506,523 ****
    if (ls.sm.line != l->line)
      {
        any_output = 1;
!       if (addr < ls.sm.addr)
  	{
! 	  /* This happens when a new frag got allocated (for whatever
! 	     reason).  Deal with it by generating a reference symbol.
! 	     Note: no end_sequence needs to be generated because the
! 	     address did not really decrease (only the reference point
! 	     changed).
! 
! 	     ??? Perhaps we should directly check for a change of
! 	     frag_now instead?  */
  	  out_set_addr (addr);
  	  ls.sm.addr = addr;
  	}
        gen_addr_line (l->line - ls.sm.line,
  		     (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH);
--- 517,531 ----
    if (ls.sm.line != l->line)
      {
        any_output = 1;
!       if (saved_frag != ls.frag)
  	{
! 	  /* If a new frag got allocated (for whatever reason), then
! 	     deal with it by generating a reference symbol.  Note: no
! 	     end_sequence needs to be generated because the address did
! 	     not really decrease (only the reference point changed).  */
  	  out_set_addr (addr);
  	  ls.sm.addr = addr;
+ 	  ls.frag = saved_frag;
  	}
        gen_addr_line (l->line - ls.sm.line,
  		     (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]