[Patch] pr65779 - [5/6 Regression] undefined local symbol on powerpc

Jakub Jelinek jakub@redhat.com
Mon Apr 20 07:47:00 GMT 2015


On Mon, Apr 20, 2015 at 12:40:49PM +0930, Alan Modra wrote:
> with the log for the ubsan fails
> /src/gcc-5/gcc/testsuite/c-c++-common/ubsan/object-size-10.c:19:11: runtime error: index 128 out of bounds for type 'char [128]'
> /src/gcc-5/gcc/testsuite/c-c++-common/ubsan/object-size-10.c:19:11: runtime error: load of address 0x0804a000 with insufficient space for an object of type 'char'
> 0x0804a000: note: pointer points here
> <memory cannot be printed>

The issue here is that libsanitizer wants to print some context around the
variable, and doesn't try too hard, so if the variable is too close to the
end of the RW PT_LOAD, you get different message from what is expected.
In your case, most likely the end of the array happens to be exactly at the
end of the PT_LOAD segment.

So, the fix is either to try harder in ubsan renderMemorySnippet function
(it first computes the region it wishes to print, then has
  if (!IsAccessibleMemoryRange(Min, Max - Min)) {
    Printf("<memory cannot be printed>\n");
    return;
  }
).  Supposedly it could, if there are any page boundary crosses in the
Min .. Max region lower a little bit (to the page boundary) the end and/or
increase to the page boundary the start, and retry with that if it is
accessible.

Or we'd need to make the testcases that suffer from this accept also
the <memory cannot be printed> in place of the memory content line, line
with ^ marker (don't remember if there is yet another one).

> gcc/
> 	PR debug/65779
> 	* shrink-wrap.c (insn_uses_reg): New function.
> 	(move_insn_for_shrink_wrap): Remove debug insns using regs set
> 	by the moved insn.
> gcc/testsuite/
> 	* gcc.dg/pr65779.c: New.
> 
> Index: gcc/shrink-wrap.c
> ===================================================================
> --- gcc/shrink-wrap.c	(revision 222160)
> +++ gcc/shrink-wrap.c	(working copy)
> @@ -182,6 +182,21 @@ live_edge_for_reg (basic_block bb, int regno, int
>    return live_edge;
>  }
>  
> +static bool
> +insn_uses_reg (rtx_insn *insn, unsigned int regno, unsigned int end_regno)
> +{
> +  df_ref use;
> +
> +  FOR_EACH_INSN_USE (use, insn)
> +    {
> +      rtx reg = DF_REF_REG (use);
> +
> +      if (REG_P (reg) && REGNO (reg) >= regno && REGNO (reg) < end_regno)
> +	return true;
> +    }
> +  return false;
> +}
> +
>  /* Try to move INSN from BB to a successor.  Return true on success.
>     USES and DEFS are the set of registers that are used and defined
>     after INSN in BB.  SPLIT_P indicates whether a live edge from BB
> @@ -340,10 +355,15 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_ins
>        *split_p = true;
>      }
>  
> +  vec<basic_block> live_bbs;
> +  if (MAY_HAVE_DEBUG_INSNS)
> +    live_bbs.create (5);

Just wonder if using an
  auto_vec<basic_block, 5> live_bbs;

> +	  FOR_BB_INSNS_REVERSE (tmp_bb, dinsn)
> +	    {
> +	      if (dinsn == insn)
> +		break;
> +	      if (DEBUG_INSN_P (dinsn)
> +		  && insn_uses_reg (dinsn, dregno, end_dregno))
> +		{
> +		  if (*split_p)
> +		    /* If split, then we will be moving insn into a
> +		       newly created block immediately after the entry
> +		       block.  Move the debug info there too.  */
> +		    emit_debug_insn_after (PATTERN (dinsn), bb_note (bb));
> +		  delete_insn (dinsn);

Debug insns should never be deleted, nor moved.  You should either
reset them
(INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); plus
df_insn_rescan_debug_internal (insn);), or try to adjust them based on the
instruction setting the register (say, if insn sets the register to
some other register + 10 and the other register is still live, you could
replace the uses of the register with (plus (the other register) (const_int 10)).

> +      live_bbs.release ();

If live_bbs is auto_vec, this would not be needed.

	Jakub



More information about the Gcc-patches mailing list