[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #15 from Jakub Jelinek --- (In reply to Jan Hubicka from comment #13) > Author: hubicka > Date: Wed Jan 13 23:47:45 2016 > New Revision: 232356 > > URL: https://gcc.gnu.org/viewcvs?rev=232356=gcc=rev > Log: > > PR ipa/66487 > * ipa-polymorphic-call.c (inlined_polymorphic_ctor_dtor_block_p): > use block_ultimate_origin > (noncall-stmt_may_be_vtbl_ptr_store): Likewise. > > Modified: > trunk/gcc/ChangeLog > trunk/gcc/ipa-polymorphic-call.c Has this commit fixed the remaining issues?
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #14 from Jakub Jelinek --- (In reply to Jason Merrill from comment #4) > Actually, I guess checking for this is more of a fit for an uninitialized > read detector such as MemorySanitizer or Valgrind memcheck. Well, AddressSanitizer should be able to do that too with some extra work, what we need is know not just when the lifetime of a variable ends, but also when it starts, and instrument those two, plus disable reusing variable stack slots when instrumenting. In the function prologue we'd then mark the variables as unavailable, not just their padding, and then when they get into scope (that is the first clobber these days), we'd mark them enabled and when they get out of scope (second clobber) mark them unavailable again. GCC7 material.
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #17 from Martin Liška --- (In reply to Jakub Jelinek from comment #15) > (In reply to Jan Hubicka from comment #13) > > Author: hubicka > > Date: Wed Jan 13 23:47:45 2016 > > New Revision: 232356 > > > > URL: https://gcc.gnu.org/viewcvs?rev=232356=gcc=rev > > Log: > > > > PR ipa/66487 > > * ipa-polymorphic-call.c (inlined_polymorphic_ctor_dtor_block_p): > > use block_ultimate_origin > > (noncall-stmt_may_be_vtbl_ptr_store): Likewise. > > > > Modified: > > trunk/gcc/ChangeLog > > trunk/gcc/ipa-polymorphic-call.c > > Has this commit fixed the remaining issues? There's still a remaining issue that is caused by -flifetime-dse that is *probably* caused by an undefined behavior in Firefox. I've been working on reduction of the issue. As shown it's caused by a store to a memory that is clobbered by constructor. Trevor is also focused on the issue, hope we'll hunt the problem very soon. Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #16 from Martin Liška --- (In reply to Jakub Jelinek from comment #14) > (In reply to Jason Merrill from comment #4) > > Actually, I guess checking for this is more of a fit for an uninitialized > > read detector such as MemorySanitizer or Valgrind memcheck. > > Well, AddressSanitizer should be able to do that too with some extra work, > what we need is know not just when the lifetime of a variable ends, but also > when it starts, and instrument those two, plus disable reusing variable > stack slots when instrumenting. In the function prologue we'd then mark the > variables as unavailable, not just their padding, and then when they get > into scope (that is the first clobber these days), we'd mark them enabled > and when they get out of scope (second clobber) mark them unavailable again. > GCC7 material. Hi Jakub. I've already made a prototype implementation that can do that: https://groups.google.com/forum/#!topic/address-sanitizer/WYdZIo6lnyA It's quite limited to just heap allocation and memory sizes different from multiples of 8B are not correctly handled, but I'm rewriting the patch to prepare it as GCC 7 material. Moreover, Honza suggested that we can use the scaffolding to do a run-time memory aliasing sanitizer that will verify that a memory is accessed just from compatible alias sets. Also GCC 7 material. Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #18 from Martin Liška --- (In reply to Martin Liška from comment #16) > (In reply to Jakub Jelinek from comment #14) > > (In reply to Jason Merrill from comment #4) > > > Actually, I guess checking for this is more of a fit for an uninitialized > > > read detector such as MemorySanitizer or Valgrind memcheck. > > > > Well, AddressSanitizer should be able to do that too with some extra work, > > what we need is know not just when the lifetime of a variable ends, but also > > when it starts, and instrument those two, plus disable reusing variable > > stack slots when instrumenting. In the function prologue we'd then mark the > > variables as unavailable, not just their padding, and then when they get > > into scope (that is the first clobber these days), we'd mark them enabled > > and when they get out of scope (second clobber) mark them unavailable again. > > GCC7 material. > > Hi Jakub. > > I've already made a prototype implementation that can do that: > https://groups.google.com/forum/#!topic/address-sanitizer/WYdZIo6lnyA > > It's quite limited to just heap allocation and memory sizes different from > multiples of 8B are not correctly handled, but I'm rewriting the patch to > prepare it as GCC 7 material. > > Moreover, Honza suggested that we can use the scaffolding to do a run-time > memory aliasing sanitizer that will verify that a memory is accessed just > from compatible alias sets. Also GCC 7 material. > > Martin Another update: looks the desired feature is already implemented by MemorySanitizer: https://github.com/google/sanitizers/wiki/MemorySanitizer Thus, writing just code emission on side of the GCC compiler should enable the functionality. I'll take a look. Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #13 from Jan Hubicka --- Author: hubicka Date: Wed Jan 13 23:47:45 2016 New Revision: 232356 URL: https://gcc.gnu.org/viewcvs?rev=232356=gcc=rev Log: PR ipa/66487 * ipa-polymorphic-call.c (inlined_polymorphic_ctor_dtor_block_p): use block_ultimate_origin (noncall-stmt_may_be_vtbl_ptr_store): Likewise. Modified: trunk/gcc/ChangeLog trunk/gcc/ipa-polymorphic-call.c
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #6 from Martin Liška --- (In reply to Marek Polacek from comment #5) > Martin, is this still an issue or we can close this? Still issue, currently bisecting debugging counter for devirt, that is responsible for the SEGFAULT. I will keep the bug up to date. Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 Marek Polacek changed: What|Removed |Added CC||mpolacek at gcc dot gnu.org --- Comment #5 from Marek Polacek --- Martin, is this still an issue or we can close this?
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #7 from Martin Liška --- So the problematic transformation is: devirtualizing call in _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50/986945 to __builtin_unreachable/39579 _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50/986945 (_ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50) @0x7f909d3bfcf0 Type: function definition analyzed Visibility: artificial References: _ZTV22nsSafeFileOutputStream/985700 (addr)_ZTV22nsSafeFileOutputStream/985700 (addr)_ZTV22nsSafeFileOutputStream/985700 (addr)_ZTV22nsSafeFileOutputStream/985700 (addr)_ZTV22nsSafeFileOutputStream/985700 (read) Referring: Read from file: /home/marxin/Programming/gecko-dev/obj-lto/toolkit/library/../../netwerk/build/nsNetModule.o First run: 1 Function flags: local Called by: _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv/979522 (0.03 per call) Calls: moz_xmalloc/985262 (1.00 per call) _ZN16nsFileStreamBaseC2Ev/985698 (1.00 per call) Polymorphic indirect call of type struct nsAtomicFileOutputStream token:1(0.53 per call) Outer type (dynamic):struct nsFileStreamBase offset 0 Speculative outer type:struct nsSafeFileOutputStream (or a derived type) at offset 0 Polymorphic indirect call of type struct nsAtomicFileOutputStream token:0(0.53 per call) Speculative outer type:struct nsFileStreamBase at offset 0 Polymorphic indirect call of type struct nsAtomicFileOutputStream token:2(0.53 per call) Speculative outer type:struct nsFileStreamBase at offset 0 Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #8 from Martin Liška --- The transformation is applied here: (gdb) p *current_pass $2 = { = {type = IPA_PASS, name = 0x1615fdd "pure-const", optinfo_flags = 0, tv_id = TV_IPA_PURE_CONST, properties_required = 0, properties_provided = 0, properties_destroyed = 0, todo_flags_start = 524288, todo_flags_finish = 0}, _vptr.opt_pass = 0x1601638 , sub = 0x0, next = 0x1c01c50, static_pass_number = 78, graph_dump_initialized = false, m_ctxt = 0x1bbae40} (gdb) bt #0 walk_polymorphic_call_targets (before_inlining_p=, reachable=0x7fffcfc0, first=0x7fffcf80, edge=0x7fffcc09d068, reachable_call_targets=0x7fffd020) at ../../gcc/ipa.c:240 #1 symbol_table::remove_unreachable_nodes (this=0x768d10a8, file=0x0) at ../../gcc/ipa.c:421 #2 0x005e724d in read_cgraph_and_symbols (fnames=, nfiles=) at ../../gcc/lto/lto.c:2939 #3 lto_main () at ../../gcc/lto/lto.c:3304 #4 0x0093a43f in compile_file () at ../../gcc/toplev.c:464 #5 0x005beb81 in do_compile () at ../../gcc/toplev.c:1985 #6 toplev::main (this=this@entry=0x7fffd200, argc=1735, argc@entry=147, argv=0x1bbc390, argv@entry=0x7fffd308) at ../../gcc/toplev.c:2092 #7 0x005c0da7 in main (argc=147, argv=0x7fffd308) at ../../gcc/main.c:39 (gdb) p *current_pass $3 = { = {type = IPA_PASS, name = 0x1615fdd "pure-const", optinfo_flags = 0, tv_id = TV_IPA_PURE_CONST, properties_required = 0, properties_provided = 0, properties_destroyed = 0, todo_flags_start = 524288, todo_flags_finish = 0}, _vptr.opt_pass = 0x1601638 , sub = 0x0, next = 0x1c01c50, static_pass_number = 78, graph_dump_initialized = false, m_ctxt = 0x1bbae40}
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #9 from Martin Liška --- release_ssa dump of the object file: ;; Function nsSafeFileOutputStreamConstructor(nsISupports*, nsID const&, void**) (_ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv, funcdef_no=17674, decl_uid=332170, cgraph_uid=11812, symbol_order=12340) Released 34 names, 340.00%, removed 34 holes nsSafeFileOutputStreamConstructor(nsISupports*, nsID const&, void**) (struct nsISupports * aOuter, const struct nsIID & aIID, void * * aResult) { nsresult _1; nsresult _2; : *aResult_4(D) = 0B; if (aOuter_6(D) != 0B) goto ; else goto ; : _2 = nsSafeFileOutputStreamConstructor (aIID_8(D), aResult_4(D)); : # _1 = PHI <2147746064(2), _2(3)> return _1; } ipa-devirt dump of the _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50: Procesing function _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50/986945 Targets of polymorphic call of type 5592:struct nsAtomicFileOutputStream token 0 Speculative outer type:struct nsFileStreamBase at offset 0 This is partial list; extra targets may be defined in other units. (base types included) (derived types included) nsAtomicFileOutputStream::QueryInterface/440618 nsCheckSummedOutputStream::QueryInterface/13271075 Dropping polymorphic call info; it can not be used by ipa-prop More than one likely target Targets of polymorphic call of type 5592:struct nsAtomicFileOutputStream token 2 Speculative outer type:struct nsFileStreamBase at offset 0 This is partial list; extra targets may be defined in other units. (base types included) (derived types included) nsAtomicFileOutputStream::Release/440632 nsCheckSummedOutputStream::Release/13271089 Dropping polymorphic call info; it can not be used by ipa-prop More than one likely target
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #10 from Martin Liška --- _ZL33nsSafeFileOutputStreamConstructorP11nsISupportsRK4nsIDPPv.part.50 (const struct nsIID & aIID, void * * aResult) { nsresult rv; struct nsSafeFileOutputStream * inst; void * D.4108055; struct nsISupports * aOuter; : : _1 = moz_xmalloc (96); MEM[(struct nsSafeFileOutputStream *)_1] = {}; _2 = [(struct nsFileOutputStream *)_1].D.310165; __base_ctor (_2); MEM[(struct nsCOMPtr_base *)_1 + 72B].mRawPtr = 0B; MEM[(struct nsCOMPtr_base *)_1 + 80B].mRawPtr = 0B; MEM[(struct nsAtomicFileOutputStream *)_1].mTargetFileExists = 1; MEM[(struct nsAtomicFileOutputStream *)_1].mWriteResult = 0; MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310176.D.310165.D.310152.D.135481._vptr.nsISupports = [(void *)&_ZTV22nsSafeFileOutputStream + 16B]; MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310176.D.310165.D.310151.D.309908._vptr.nsISupports = [(void *)&_ZTV22nsSafeFileOutputStream + 184B]; MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310176.D.310164.D.121781.D.40458._vptr.nsISupports = [(void *)&_ZTV22nsSafeFileOutputStream + 240B]; MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310175.D.121735._vptr.nsISupports = [(void *)&_ZTV22nsSafeFileOutputStream + 336B]; if (_1 == 0B) goto ; else goto ; : _3 = [(struct nsSafeFileOutputStream *)_1].D.311327; _4 = MEM[(int (*__vtbl_ptr_type) () *)&_ZTV22nsSafeFileOutputStream + 24B]; OBJ_TYPE_REF(_4;(struct nsAtomicFileOutputStream)_3->1) (_3); _5 = MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310176.D.310165.D.310152.D.135481._vptr.nsISupports; _6 = *_5; rv_9 = OBJ_TYPE_REF(_6;(struct nsAtomicFileOutputStream)_3->0) (_3, aIID_7(D), aResult_8(D)); _10 = MEM[(struct nsSafeFileOutputStream *)_1].D.311327.D.310176.D.310165.D.310152.D.135481._vptr.nsISupports; _11 = MEM[(int (*__vtbl_ptr_type) () *)_10 + 16B]; OBJ_TYPE_REF(_11;(struct nsAtomicFileOutputStream)_3->2) (_3); : # _12 = PHI <2147942414(2), rv_9(3)> return _12; }
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #11 from Martin Liška --- Created attachment 37318 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37318=edit pre-processed source file
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 Jan Hubicka changed: What|Removed |Added CC||hubicka at gcc dot gnu.org --- Comment #12 from Jan Hubicka --- The problem is that BLOCK_ABSTRACT_ORIGIN can iterate, while DECL_ABSTRACT_ORIGIN can not. Iterated inlining and/or function splitting may make us to miss the fact that vtbl store is vtbl store. Index: ipa-polymorphic-call.c === --- ipa-polymorphic-call.c (revision 232227) +++ ipa-polymorphic-call.c (working copy) @@ -477,6 +477,19 @@ contains_type_p (tree outer_type, HOST_W consider_bases); } +/* Unlike ABSTRACT_ORIGIN, the BLOCK_ABSTRACT_ORIGIN can iterate. Look up + the real origin of BLOCK. */ + +static tree +block_origin (tree block) +{ + if (!BLOCK_ABSTRACT_ORIGIN (block)) +return NULL; + while (TREE_CODE (block) == BLOCK && BLOCK_ABSTRACT_ORIGIN (block)) +block = BLOCK_ABSTRACT_ORIGIN (block); + return DECL_P (block) ? DECL_ORIGIN (block) : block; +} + /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor. If CHECK_CLONES is true, also check for clones of ctor/dtors. */ @@ -484,7 +497,7 @@ contains_type_p (tree outer_type, HOST_W tree inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones) { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); + tree fn = block_origin (block); if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL) return NULL_TREE; @@ -1142,8 +1155,8 @@ noncall_stmt_may_be_vtbl_ptr_store (gimp block of CTOR/DTOR. */ for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK; block = BLOCK_SUPERCONTEXT (block)) -if (BLOCK_ABSTRACT_ORIGIN (block) - && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) +if (block_origin (block) + && TREE_CODE (block_origin (block)) == FUNCTION_DECL) return inlined_polymorphic_ctor_dtor_block_p (block, false); return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #2 from Martin Liška marxin at gcc dot gnu.org --- Back trace: #0 0x in () #1 0x74a5c337 in nsComponentManagerImpl::CreateInstanceByContractID(char const*, nsISupports*, nsID const, void**) [clone .part.32] [clone .constprop.53402] (this=optimized out, aContractID=0x751a1e60 @mozilla.org/network/safe-file-output-stream;1, aDelegate=0xc3adb0, aIID=..., aResult=0x7fffbc48) at /home/marxin/Programming/gecko-dev/xpcom/components/nsComponentManager.cpp:1223 #2 0x7273fa5b in nsCreateInstanceByContractID::operator()(nsID const, void**) const () at /home/marxin/Programming/gecko-dev/xpcom/glue/nsComponentManagerUtils.cpp:151 #3 0x7273fa5b in nsCreateInstanceByContractID::operator()(nsID const, void**) const (this=0x7fffbcb0, aIID=..., aInstancePtr=0x7fffbc48) at /home/marxin/Programming/gecko-dev/xpcom/glue/nsComponentManagerUtils.cpp:197 #4 0x727a0a68 in nsCOMPtr_base::assign_from_helper(nsCOMPtr_helper const, nsID const) (this=this@entry=0x7fffbca0, aHelper=..., aIID=...) at /home/marxin/Programming/gecko-dev/xpcom/glue/nsCOMPtr.cpp:125 #5 0x74a224e3 in WritePrefFile () at ../../dist/include/nsCOMPtr.h:531 #6 0x74a224e3 in WritePrefFile (behaviorFlags=0, perm=384, ioFlags=-1, file=0xc33970, result=0x7fffbc80) at ../../dist/include/nsNetUtil.h:1358 #7 0x74a224e3 in WritePrefFile (aFile=0xc33970, this=optimized out) at /home/marxin/Programming/gecko-dev/modules/libpref/Preferences.cpp:952 #8 0x74c53c85 in TrackStartupCrashBegin (this=0x87f950, aIsSafeModeNecessary=0x7fffbeaf) at /home/marxin/Programming/gecko-dev/toolkit/components/startup/nsAppStartup.cpp:910 #9 0x7459ad8f in nsXREDirProvider::DoStartup() [clone .part.20] [clone .constprop.4887] (this=0x7fffc5f8) at /home/marxin/Programming/gecko-dev/toolkit/xre/nsXREDirProvider.cpp:831 #10 0x74c00225 in nsXREDirProvider::DoStartup() (this=this@entry=0x7fffc5f8) at /home/marxin/Programming/gecko-dev/toolkit/xre/nsXREDirProvider.cpp:879 #11 0x74580697 in XREMain::XRE_mainRun() [clone .constprop.4884] (this=this@entry=0x7fffc5b0) at /home/marxin/Programming/gecko-dev/toolkit/xre/nsAppRunner.cpp:4140 #12 0x74ce1606 in XRE_main (aAppData=optimized out, argv=optimized out, argc=optimized out, this=0x7fffc5b0) at /home/marxin/Programming/gecko-dev/toolkit/xre/nsAppRunner.cpp:4342 #13 0x74ce1606 in XRE_main (argc=optimized out, argv=optimized out, aAppData=optimized out, aFlags=optimized out) at /home/marxin/Programming/gecko-dev/toolkit/xre/nsAppRunner.cpp:4431 #14 0x0040f3c0 in do_main(int, char**, nsIFile*) [clone .constprop.14] (argc=2, argv=0x7fffdea8, xreDirectory=0x456170) at /home/marxin/Programming/gecko-dev/browser/app/nsBrowserApp.cpp:214 #15 0x004038a8 in main(int, char**) (argc=2, argv=0x7fffdea8) at /home/marxin/Programming/gecko-dev/browser/app/nsBrowserApp.cpp:478
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #3 from Martin Liška marxin at gcc dot gnu.org --- (In reply to Jason Merrill from comment #1) Compiling with -fno-lifetime-dse should make it work again. -fsanitize=undefined doesn't currently catch this issue (relying on the value of storage persisting into the lifetime of an object created there). I see, I will try to contact someone from Firefox about it. Are there any plans of integration to ubsan sanitizer? Martin
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #4 from Jason Merrill jason at gcc dot gnu.org --- Actually, I guess checking for this is more of a fit for an uninitialized read detector such as MemorySanitizer or Valgrind memcheck.
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 Richard Biener rguenth at gcc dot gnu.org changed: What|Removed |Added Target Milestone|--- |6.0
[Bug c++/66487] [6 Regression] Firefox segfault with LTO enabled
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66487 --- Comment #1 from Jason Merrill jason at gcc dot gnu.org --- Compiling with -fno-lifetime-dse should make it work again. -fsanitize=undefined doesn't currently catch this issue (relying on the value of storage persisting into the lifetime of an object created there).