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