a48847eea5
While doing some powerpc Linux tests on a ppc 476 board using GCC 5.2, i noticed inline-bt.exp, inline-cmds.exp and inline-locals.exp failing. FAIL: gdb.opt/inline-bt.exp: continue to bar (1) FAIL: gdb.opt/inline-bt.exp: backtrace from bar (1) FAIL: gdb.opt/inline-bt.exp: continue to bar (2) FAIL: gdb.opt/inline-bt.exp: backtrace from bar (2) FAIL: gdb.opt/inline-bt.exp: continue to bar (3) FAIL: gdb.opt/inline-bt.exp: backtrace from bar (3) FAIL: gdb.opt/inline-cmds.exp: continue to bar (1) FAIL: gdb.opt/inline-cmds.exp: backtrace from bar (1) FAIL: gdb.opt/inline-cmds.exp: continue to bar (2) FAIL: gdb.opt/inline-cmds.exp: backtrace from bar (2) FAIL: gdb.opt/inline-cmds.exp: continue to marker FAIL: gdb.opt/inline-cmds.exp: backtrace from marker FAIL: gdb.opt/inline-cmds.exp: step into finish marker FAIL: gdb.opt/inline-locals.exp: continue to bar (1) FAIL: gdb.opt/inline-locals.exp: continue to bar (2) FAIL: gdb.opt/inline-locals.exp: backtrace from bar (2) FAIL: gdb.opt/inline-locals.exp: continue to bar (3) FAIL: gdb.opt/inline-locals.exp: backtrace from bar (3) They failed because the breakpoint supposedly inserted at bar was actually inserted at noinline. (gdb) break inline-markers.c:20^M Breakpoint 2 at 0x1000079c: file gdb/testsuite/gdb.opt/inline-markers.c, line 20.^M (gdb) continue^M Continuing.^M ^M Breakpoint 2, noinline () at gdb/testsuite/gdb.opt/inline-markers.c:35^M 35 inlined_fn (); /* inlined */^M As we can see, line 20 is really inside bar, not noinline: 18 void bar(void) 19 { 20 x += y; /* set breakpoint 1 here */ 21 } Further investigation shows that this is really due to GCC 5's new ICF pass (-fipa-icf), now enabled by default at -O2, which folds bar and marker into noinline, where the call to inlined_fn was inlined. This breaks the testcase since it expects to stop at specific spots. I thought about two possible fixes for this issue. - Disable the ICF pass manually when building the binary (-fno-ipa-icf). This has the advantage of not having to touch the testcase sources themselves, but the disadvantage of having to add conditional blocks to test the GCC version. If we ever change GCC's default, we will have to adjust the conditional block again to match GCC's behavior. - Modify the testcase sources to make the identical functions unique. This solution doesn't touch the testcase itself, but changes the source code slightly in order to make bar, marker and inlined_fn unique. This causes GCC's ICF pass to ignore these functions and not fold them into a common identical function. I'm good with either of them, but i'm more inclined to go with the second one. The attached patch implements this by adding the new global variable z, set to 0, that gets added in different ways to marker and inlined_fn. Since it is 0, it doesn't affect any possible value checks that we may wish to do in the future (we currently only check for values changed by bar). Ok? ps: I also noticed GDB doesn't do a great job at stating that the breakpoint was actually inserted at a different source line than previously requested, so this sounds like a bug that should be fixed, if it is not just wrong DWARF information (did not investigate it further). gdb/testsuite/ChangeLog: 2015-08-24 Luis Machado <lgustavo@codesourcery.com> * gdb.opt/inline-bt.c: New volatile global z. * gdb.opt/inline-cmds.c: Likewise. * gdb.opt/inline-locals.c: Likewise. * gdb.opt/inline-markers.c: New extern global z. (marker): Use z. (inline_fn): Likewise.
95 lines
1.8 KiB
C
95 lines
1.8 KiB
C
/* Copyright (C) 2008-2015 Free Software Foundation, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
/* This is only ever run if it is compiled with a new-enough GCC, but
|
|
we don't want the compilation to fail if compiled by some other
|
|
compiler. */
|
|
#ifdef __GNUC__
|
|
#define ATTR __attribute__((always_inline))
|
|
#else
|
|
#define ATTR
|
|
#endif
|
|
|
|
int x, y;
|
|
volatile int z = 0;
|
|
volatile int result;
|
|
|
|
void bar(void);
|
|
void marker(void);
|
|
void noinline(void);
|
|
|
|
inline ATTR int func1(void)
|
|
{
|
|
bar ();
|
|
return x * y;
|
|
}
|
|
|
|
inline ATTR int func2(void)
|
|
{
|
|
return x * func1 ();
|
|
}
|
|
|
|
inline ATTR void func3(void)
|
|
{
|
|
bar ();
|
|
}
|
|
|
|
inline ATTR void outer_inline1(void)
|
|
{
|
|
noinline ();
|
|
}
|
|
|
|
inline ATTR void outer_inline2(void)
|
|
{
|
|
outer_inline1 ();
|
|
}
|
|
|
|
int main (void)
|
|
{ /* start of main */
|
|
int val;
|
|
|
|
x = 7;
|
|
y = 8;
|
|
|
|
result = func1 ();
|
|
result = func2 ();
|
|
marker ();
|
|
|
|
result = 0;
|
|
result = 0; /* set breakpoint 3 here */
|
|
|
|
func1 (); /* first call */
|
|
func1 (); /* second call */
|
|
marker ();
|
|
|
|
result = 0;
|
|
result = 0; /* set breakpoint 4 here */
|
|
|
|
func1 ();
|
|
func3 ();
|
|
marker ();
|
|
|
|
result = 0;
|
|
result = 0; /* set breakpoint 5 here */
|
|
|
|
marker ();
|
|
func1 ();
|
|
func3 ();
|
|
marker (); /* set breakpoint 6 here */
|
|
|
|
outer_inline2 ();
|
|
|
|
return 0;
|
|
}
|