https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70760
Bug ID: 70760 Summary: [6 regression] wrong generated code for std::make_unique with -fipa-pta Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: ipa Assignee: unassigned at gcc dot gnu.org Reporter: david.abdurachmanov at gmail dot com Target Milestone: --- Created attachment 38325 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38325&action=edit untouched preprocessed file Hopefully this is truly the last issues I see with GCC 6 on x86_64 and our software. Compiler with GCC 5.3.0, ASan and valgrind shows no issues. Compiled with GCC 6.0.1, ASan and valgrind shows issues, program segfaults. If we disable -fipa-pta the program compiles and runs successfully. Developers so far couldn't understand whats happening, at least at C++ level from their point of view everything is fine. No issues if compiled with latest Clang or ICC. TL;DR doing .get() on std::unique_ptr in a bizarre 0x100000000 pointer. Of course accessing later such address causes segfaults. GIT bisect tracked down the issue to a fix for PR ipa/68331 (https://gcc.gnu.org/viewcvs?rev=231498&root=gcc&view=rev) In git, first bad: 7ae97ba6651703d99d9f0e20a4e48eb7743c103c last good: 6c2acfc4892316b46df0fe4a6769fb6766ab1e0b The following code is failing on C++ level: 421 std::unique_ptr<ParameterDescriptionNode> node = std::make_unique<ParameterDescription<T>>(iLabel, value, isTracked); 422 ParameterDescriptionNode* pnode = addNode(std::move(node), isOptional, writeToCfi); addNode function segfauls once it tries access through 0x100000000 address which is from std::unique_ptr. I looked at addNode assembly and fully expected that it should segfault. Nothing wrong found with it. I went one frame up to edmtest::ProducerWithPSetDesc::fillDescriptions(edm::ConfigurationDescriptions&) symbol, but found no significant differences in generated assembly between those two commits. All differences were in offsets which looked fine. I knew that it's 2nd call to addNode inside edmtest::ProducerWithPSetDesc::fillDescriptions which caused the failure. Before 2nd addNode call is done it called to std::_MakeUniq<edm::ParameterDescription<int> >::__single_object std::make_unique<edm::ParameterDescription<int>, char const (&) [16], int const&, bool&>(char const (&) [16], int const&, bool&) [clone .isra.142] symbol and after it the second argument (to be passed to addNode) was damaged with bizarre 0x100000000 pointer at run-time. "Good code" annotated by me is below for this std::make_unique function. Due to -fipa-pta we loose one instruction which is related to return value from std::make_unique: 3 @@ -19,7 +19,6 @@ 4 48 89 df mov %rbx,%rdi 5 e8 75 e8 ff ff callq 17060 <edm 6 48 8b 05 a6 36 03 00 mov 0x336a6(%rip),%rax # 4be98 <_DYNAMIC+0x430> 7 - 49 89 1c 24 mov %rbx,(%r12) 8 48 83 c0 10 add $0x10,%rax 9 48 89 03 mov %rax,(%rbx) 10 41 8b 45 00 mov 0x0(%r13),%eax 11 @@ -34,9 +33,10 @@ 12 48 89 c5 mov %rax,%rbp 13 48 89 df mov %rbx,%rdi 14 be 28 00 00 00 mov $0x28,%esi 15 - e8 50 e4 ff ff callq 16c70 <operator delete(void*, unsigned long)@plt> 16 + e8 54 e4 ff ff callq 16c70 <operator delete(void*, unsigned long)@plt> 17 48 89 ef mov %rbp,%rdi 18 - e8 48 ef ff ff callq 17770 <_Unwind_Resume@plt> 19 - 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 20 - 00 21 + e8 4c ef ff ff callq 17770 <_Unwind_Resume@plt> 22 + 66 90 xchg %ax,%ax 23 + 66 2e 0f 1f 84 00 00 nopw %cs 24 + 00 00 00 In a "good code" it used to return a pointer to a pointer to internally allocated object. That missing instruction was storing address of allocation on heap to some memory location. Later we used to return R12. Without that instruction R12 contains RDI. Thus we are basically returning the first argument of std::make_unique. I have rushed a bit, thus hopefully didn't make too many mistakes. That's the only meaningful difference I can in see in assembly code in 3 related symbols. Attaching the preprocessed file (untouched). We compile it with: c++ -c -O2 -std=c++1z -ftree-vectorize -fvisibility-inlines-hidden -fno-math-errno --param vect-max-version-for-alias-checks=50 -fipa-pta -msse3 -felide-constructors -fPIC ProducerWithPSetDesc.ii Again, removing -fipa-pta seems to solve the issue (bring back the missing instruction). ##### GOOD ASM ##### 00000000000187b0 <std::_MakeUniq<edm::ParameterDescription<int> >::__single_object std::make_unique<edm::ParameterDescription<int>, char const (&) [16], int const&, bool&>(char const (&) [16], int const&, bool&) [clone .isra.142]>: 187b0: 41 56 push %r14 187b2: 41 55 push %r13 187b4: 49 89 f6 mov %rsi,%r14 187b7: 41 54 push %r12 187b9: 55 push %rbp 187ba: 49 89 fc mov %rdi,%r12 187bd: 53 push %rbx // Allocate 40 bytes on the heap 187be: bf 28 00 00 00 mov $0x28,%edi 187c3: 49 89 d5 mov %rdx,%r13 187c6: 0f b6 e9 movzbl %cl,%ebp 187c9: e8 62 e5 ff ff callq 16d30 <operator new(unsigned long)@plt> // Store returned pointer in RBX 187ce: 48 89 c3 mov %rax,%rbx 187d1: e8 da f8 ff ff callq 180b0 <edm::ParameterTypes edm::ParameterTypeToEnum::toEnum<int>()@plt> 187d6: 41 b8 01 00 00 00 mov $0x1,%r8d 187dc: 89 e9 mov %ebp,%ecx 187de: 89 c2 mov %eax,%edx 187e0: 4c 89 f6 mov %r14,%rsi // Call the ctor, pass pointer (this) from RBX 187e3: 48 89 df mov %rbx,%rdi 187e6: e8 75 e8 ff ff callq 17060 <edm::ParameterDescriptionBase::ParameterDescriptionBase(char const*, edm::ParameterTypes, bool, bool)@plt> 187eb: 48 8b 05 a6 36 03 00 mov 0x336a6(%rip),%rax # 4be98 <_DYNAMIC+0x430> // Store RBX to memory pointed by R12 187f2: 49 89 1c 24 mov %rbx,(%r12) 187f6: 48 83 c0 10 add $0x10,%rax 187fa: 48 89 03 mov %rax,(%rbx) 187fd: 41 8b 45 00 mov 0x0(%r13),%eax 18801: 89 43 20 mov %eax,0x20(%rbx) // Put address in R12 into return register 18804: 4c 89 e0 mov %r12,%rax 18807: 5b pop %rbx 18808: 5d pop %rbp 18809: 41 5c pop %r12 1880b: 41 5d pop %r13 1880d: 41 5e pop %r14 1880f: c3 retq 18810: 48 89 c5 mov %rax,%rbp 18813: 48 89 df mov %rbx,%rdi 18816: be 28 00 00 00 mov $0x28,%esi 1881b: e8 50 e4 ff ff callq 16c70 <operator delete(void*, unsigned long)@plt> 18820: 48 89 ef mov %rbp,%rdi 18823: e8 48 ef ff ff callq 17770 <_Unwind_Resume@plt> 18828: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 1882f: 00 ##### ASAN REPORT ##### ASAN:DEADLYSIGNAL ================================================================= ==11345==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc 0x2abffdb95e22 bp 0x7ffd8abe14b0 sp 0x7ffd8abe12c0 T0) #0 0x2abffdb95e21 in edm::ParameterDescriptionNode::checkAndGetLabelsAndTypes(std::set<std::string, std::less<std::string>, std::allocator<std::string> >&, std::set<edm::ParameterTypes, std::less<edm::ParameterTypes>, std::allocator<edm::ParameterTypes> >&, std::set<e dm::ParameterTypes, std::less<edm::ParameterTypes>, std::allocator<edm::ParameterTypes> >&) const /mnt/build/davidlt/CMSSW_8_1_X_2016-04-18-1100/src/FWCore/ParameterSet/interface/ParameterDescriptionNode.h:213 #1 0x2abffdb95e21 in edm::ParameterSetDescription::addNode(std::unique_ptr<edm::ParameterDescriptionNode, std::default_delete<edm::ParameterDescriptionNode> >, bool, bool) /mnt/build/davidlt/CMSSW_8_1_X_2016-04-18-1100/src/FWCore/ParameterSet/src/ParameterSetDescripti on.cc:92 #2 0x2ac0041a3961 in edm::ParameterDescriptionBase* edm::ParameterSetDescription::add<int, char [16]>(char const (&) [16], int const&, bool, bool, bool) /mnt/build/davidlt/CMSSW_8_1_X_2016-04-18-1100/src/FWCore/ParameterSet/interface/ParameterSetDescription.h:422 #3 0x2ac0041a3961 in edm::ParameterDescriptionBase* edm::ParameterSetDescription::addUntracked<int, char [16]>(char const (&) [16], int const&) /mnt/build/davidlt/CMSSW_8_1_X_2016-04-18-1100/src/FWCore/ParameterSet/interface/ParameterSetDescription.h:95 [..] ##### VALGRIND REPORT ##### These happens already after calling edm::ParameterSetDescription::addNode where the pointer is already wrong. ==31968== Use of uninitialised value of size 8 ==31968== at 0x40C7674: checkAndGetLabelsAndTypes (ParameterDescriptionNode.h:213) ==31968== by 0x40C7674: edm::ParameterSetDescription::addNode(std::unique_ptr<edm::ParameterDescriptionNode, std::default_delete<edm::ParameterDescriptionNode> >, bool, bool) (ParameterSetDescription.cc:92) ==31968== by 0x8705657: add<int, char [16]> (ParameterSetDescription.h:422) ==31968== by 0x8705657: addUntracked<int, char [16]> (ParameterSetDescription.h:95) ==31968== by 0x8705657: edmtest::ProducerWithPSetDesc::fillDescriptions(edm::ConfigurationDescriptions&) (ProducerWithPSetDesc.cc:459) ==31968== by 0x871ABBB: edm::ParameterSetDescriptionFiller<edmtest::ProducerWithPSetDesc>::fill(edm::ConfigurationDescriptions&) const (ParameterSetDescriptionFiller.h:55) ==31968== by 0x4059BF: operator() (edmWriteConfigs.cpp:90) ==31968== by 0x4059BF: wrap<(anonymous namespace)::writeCfisForPlugin(const string&, edm::ParameterSetDescriptionFillerPluginFactory*)::<lambda()> > (ConvertException.h:20) ==31968== by 0x4059BF: writeCfisForPlugin (edmWriteConfigs.cpp:91) ==31968== by 0x4059BF: __call<void, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, 0ul, 1ul> (functional:943) ==31968== by 0x4059BF: operator()<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (functional:1002) ==31968== by 0x4059BF: for_each<__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >, std::_Bind<void (*(std::_Placeholder<1>, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*))(const std::basic_string<cha r>&, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*)> > (stl_algo.h:3776) ==31968== by 0x4059BF: for_all<std::vector<std::basic_string<char> >, std::_Bind<void (*(std::_Placeholder<1>, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*))(const std::basic_string<char>&, edmplugin::PluginFactory<edm::ParameterSetDescription FillerBase*()>*)> > (Algorithms.h:17) ==31968== by 0x4059BF: operator() (edmWriteConfigs.cpp:285) ==31968== by 0x4059BF: wrap<main(int, char**)::<lambda()> > (ConvertException.h:20) ==31968== by 0x4059BF: main (edmWriteConfigs.cpp:286) ==31968== Uninitialised value was created by a stack allocation ==31968== at 0x8705544: edmtest::ProducerWithPSetDesc::fillDescriptions(edm::ConfigurationDescriptions&) (ProducerWithPSetDesc.cc:438) ==31968== ==31968== Invalid read of size 8 ==31968== at 0x40C7674: checkAndGetLabelsAndTypes (ParameterDescriptionNode.h:213) ==31968== by 0x40C7674: edm::ParameterSetDescription::addNode(std::unique_ptr<edm::ParameterDescriptionNode, std::default_delete<edm::ParameterDescriptionNode> >, bool, bool) (ParameterSetDescription.cc:92) ==31968== by 0x8705657: add<int, char [16]> (ParameterSetDescription.h:422) ==31968== by 0x8705657: addUntracked<int, char [16]> (ParameterSetDescription.h:95) ==31968== by 0x8705657: edmtest::ProducerWithPSetDesc::fillDescriptions(edm::ConfigurationDescriptions&) (ProducerWithPSetDesc.cc:459) ==31968== by 0x871ABBB: edm::ParameterSetDescriptionFiller<edmtest::ProducerWithPSetDesc>::fill(edm::ConfigurationDescriptions&) const (ParameterSetDescriptionFiller.h:55) ==31968== by 0x4059BF: operator() (edmWriteConfigs.cpp:90) ==31968== by 0x4059BF: wrap<(anonymous namespace)::writeCfisForPlugin(const string&, edm::ParameterSetDescriptionFillerPluginFactory*)::<lambda()> > (ConvertException.h:20) ==31968== by 0x4059BF: writeCfisForPlugin (edmWriteConfigs.cpp:91) ==31968== by 0x4059BF: __call<void, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, 0ul, 1ul> (functional:943) ==31968== by 0x4059BF: operator()<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (functional:1002) ==31968== by 0x4059BF: for_each<__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >, std::_Bind<void (*(std::_Placeholder<1>, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*))(const std::basic_string<cha r>&, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*)> > (stl_algo.h:3776) ==31968== by 0x4059BF: for_all<std::vector<std::basic_string<char> >, std::_Bind<void (*(std::_Placeholder<1>, edmplugin::PluginFactory<edm::ParameterSetDescriptionFillerBase*()>*))(const std::basic_string<char>&, edmplugin::PluginFactory<edm::ParameterSetDescription FillerBase*()>*)> > (Algorithms.h:17) ==31968== by 0x4059BF: operator() (edmWriteConfigs.cpp:285) ==31968== by 0x4059BF: wrap<main(int, char**)::<lambda()> > (ConvertException.h:20) ==31968== by 0x4059BF: main (edmWriteConfigs.cpp:286) ==31968== Address 0x1ffdfeb5400000 is not stack'd, malloc'd or (recently) free'd