This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Devirtualization causing undefined symbol references at link?


On Tue, Nov 17, 2015 at 1:09 AM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
> On 2015.11.16 at 14:18 -0800, Steven Noonan wrote:
>> Hi folks,
>>
>> (I'm not subscribed to the list, so please CC me on all responses.)
>>
>> This is using GCC 5.2 on Linux x86_64. On a project at work I've found
>> that one of our shared libraries refuses to link because of some
>> symbol references it shouldn't be making. If I add "-fno-devirtualize
>> -fno-devirtualize-speculatively" to the compile flags, the issue goes
>> away and everything links/runs fine. The issue does *not* appear on
>> GCC 4.8 (which is used by our current production toolchain).
>>
>> First of all, does anyone have any ideas off the top of their head why
>> devirtualization would break like this?
>>
>> Second, I'm looking for any ideas on how to gather meaningful data to
>> submit a useful bug report for this issue. The best idea I've come up
>> with so far is to preprocess one of the sources with the incorrect
>> references and use 'delta' to reduce it to a minimal preprocessed
>> source file that references one of these incorrect symbols.
>> Unfortunately this is a sluggish process because such a minimal test
>> case would need to compile correctly to an object file -- so "delta"
>> is reducing it very slowly. So far I'm down from 11MB preprocessed
>> source to 1.1MB preprocessed source after running delta a few times.
>
> These undefined references are normally user errors. For example, when
> you define an inline function, you need to link with the symbols it
> uses.
>
> markus@x4 /tmp % cat main.ii
> struct A {
>   void foo();
> };
> struct B {
>   A v;
>   virtual void bar() { v.foo(); }
> };
> struct C {
>   B *w;
>   void Test() {
>     if (!w)
>       return;
>     while (1)
>       w->bar();
>   }
> };
> C a;
> int main() { a.Test(); }
>
> markus@x4 /tmp % g++ -fno-devirtualize -O2 -Wl,--no-undefined main.ii
> markus@x4 /tmp % g++ -O2 -Wl,--no-undefined main.ii
> /tmp/ccEvh2dL.o:main.ii:function B::bar(): error: undefined reference to 'A::foo()'
> /tmp/ccEvh2dL.o:main.ii:function main: error: undefined reference to 'A::foo()'
> collect2: error: ld returned 1 exit status
>
> Instead of using delta you could try creduce instead. It is normally
> much quicker:
>
> https://github.com/csmith-project/creduce
>

creduce did make a much smaller test case, and it's actually sort of
readable. I'm not sure that I selected for the right criteria in my
test script though. It appears to exhibit the negative behavior we're
observing at least.

---
namespace panorama {
class A {
public:
  virtual int *AccessIUIStyle() = 0;
};
class CUIPanel : A {
  int *AccessIUIStyle() { return AccessStyle(); }
  int *AccessStyle() const;
};
class B {
  float GetSplitterPosition();
  A *m_pIUIPanel;
};
}
using namespace panorama;
float B::GetSplitterPosition() {
  m_pIUIPanel->AccessIUIStyle();
  return 0.0f;
}
---

The test case is very different from the code it came from (e.g.
Access*Style functions weren't returning int pointers before, and the
results were actually used at the GetSplitterPosition call site). But
I only selected for the undefined symbols in the 'nm' output. Might
need to refine the test script a bit more, but I would need to really
think about how...

Bad:
$ gcc -O3 -c debugger1.ii; nm debugger1.o
0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv
0000000000000000 W _ZN8panorama8CUIPanel14AccessIUIStyleEv
                 U _ZNK8panorama8CUIPanel11AccessStyleEv

Good:
$ gcc -O3 -fno-devirtualize -fno-devirtualize-speculatively -c
debugger1.ii; nm debugger1.o
0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv
$ clang -O3 -c debugger1.ii; nm debugger1.o
0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv

$ gcc --version
gcc (GCC) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 3.7.0 (tags/RELEASE_370/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix


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