DMARC-Filter: OpenDMARC Filter v1.4.2 delorie.com 56PHTNa32298312 Authentication-Results: delorie.com; dmarc=pass (p=none dis=none) header.from=cygwin.com Authentication-Results: delorie.com; spf=pass smtp.mailfrom=cygwin.com DKIM-Filter: OpenDKIM Filter v2.11.0 delorie.com 56PHTNa32298312 Authentication-Results: delorie.com; dkim=pass (1024-bit key, unprotected) header.d=cygwin.com header.i=@cygwin.com header.a=rsa-sha256 header.s=default header.b=rm/9hRJ/ X-Recipient: archive-cygwin AT delorie DOT com DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 317F1384F001 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com; s=default; t=1753464562; bh=9Us0lMU1OelwK3mYFQW4sB3i8EvWQI6FDAoIT1kuE7s=; h=Date:To:cc:Subject:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=rm/9hRJ/BTbl12VVOhL9TZytMHdixWlntMMAVW6//ONFHsNrusMffCRqzGRuv6tuS BfFroGGR1zknQhzs64TJhjkhX6a9dESJ/+A9/WquALCd3ewwbEgNX7+lIU1GCX9gHH 50c9JiGuUZQpF4B6ZevrFVEtijihQhtw7txJXMUU= X-Original-To: cygwin AT cygwin DOT com Delivered-To: cygwin AT cygwin DOT com DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C8265385040F ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C8265385040F ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753464534; cv=none; b=wOw47a5RKN0LG46wikXX/EQVCCCxE94KpoJ18fz1P+G1o7G9UsUOaHHhGbwkz4QVIrcZn5X9FZICDKnnsVxmrt/J56iN34pIqadQ8Z5aLiNCjjtJUzIkVtFnBvW21/Yn1l67Dxoi5GUbwoZNvr2rwoiypmykcsAD3VkfUsCz7tU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753464534; c=relaxed/simple; bh=BDU1q34H5+VPiczRdXb/MjE8dNQ7JLTsmw/uKke2EEM=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=dYbqi1i/f7EpSucHFebN02uhIXkUmyd71q4apqiBxpNxAailfeBrgaY82YQ/yTLD31eYx8n2eCNLISnCymjGOMbKX4b45U7w/a5CaTuCQGYwKKVs7PuUNZiahi+YeMX0fcEXak59hQNyXin5PdW9g7dPDVybLN9h55cgxNaA4xY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C8265385040F Date: Fri, 25 Jul 2025 10:28:54 -0700 (PDT) X-X-Sender: jeremyd AT resin DOT csoft DOT net To: Corinna Vinschen via Cygwin cc: Corinna Vinschen Subject: Re: new c++ new/delete overloads need wrapping? In-Reply-To: Message-ID: <59ba736a-21c7-a004-e5a1-6554df3b58f1@jdrake.com> References: <81535510-8360-1c72-442a-0b630a6d937f AT jdrake DOT com> MIME-Version: 1.0 X-BeenThere: cygwin AT cygwin DOT com X-Mailman-Version: 2.1.30 Precedence: list List-Id: General Cygwin discussions and problem reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Jeremy Drake via Cygwin Reply-To: Jeremy Drake Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: cygwin-bounces~archive-cygwin=delorie DOT com AT cygwin DOT com Sender: "Cygwin" On Fri, 25 Jul 2025, Corinna Vinschen via Cygwin wrote: > On Jul 24 22:41, Jeremy Drake via Cygwin wrote: > > I was looking into C++ new/delete --wrap linker options, and noticed that > > in a quick test the wrapper for delete was not being called. This was > > because delete is being compiled to _ZdlPvm and that symbol is not present > > in the --wrap arguments in the GCC spec, and is not part of the > > per_process_cxx_malloc struct. I'm not seeing anything in that cxx_malloc > > struct like a size or version number, so I don't know a good way to > > extend it given that it is part of the startup code linked into every > > binary. > > > > Here are the current symbols from libc++ and how they demangle: > > > > _ZdaPv operator delete[](void*) > > _ZdaPvm operator delete[](void*, unsigned long) > > _ZdaPvmSt11align_val_t operator delete[](void*, unsigned long, std::align_val_t) > > _ZdaPvRKSt9nothrow_t operator delete[](void*, std::nothrow_t const&) > > _ZdaPvSt11align_val_t operator delete[](void*, std::align_val_t) > > _ZdaPvSt11align_val_tRKSt9nothrow_t operator delete[](void*, std::align_val_t, std::nothrow_t const&) > > _ZdlPv operator delete(void*) > > _ZdlPvm operator delete(void*, unsigned long) > > _ZdlPvmSt11align_val_t operator delete(void*, unsigned long, std::align_val_t) > > _ZdlPvRKSt9nothrow_t operator delete(void*, std::nothrow_t const&) > > _ZdlPvSt11align_val_t operator delete(void*, std::align_val_t) > > _ZdlPvSt11align_val_tRKSt9nothrow_t operator delete(void*, std::align_val_t, std::nothrow_t const&) > > _Znam operator new[](unsigned long) > > _ZnamRKSt9nothrow_t operator new[](unsigned long, std::nothrow_t const&) > > _ZnamSt11align_val_t operator new[](unsigned long, std::align_val_t) > > _ZnamSt11align_val_tRKSt9nothrow_t operator new[](unsigned long, std::align_val_t, std::nothrow_t const&) > > _Znwm operator new(unsigned long) > > _ZnwmRKSt9nothrow_t operator new(unsigned long, std::nothrow_t const&) > > _ZnwmSt11align_val_t operator new(unsigned long, std::align_val_t) > > _ZnwmSt11align_val_tRKSt9nothrow_t operator new(unsigned long, std::align_val_t, std::nothrow_t const&) > > Wow, these got a lot more since we started to support this back in > 2009 and ported to 64 bit in 2013. Yeah, it looks like they added aligned new/delete and sized delete, and then had a combinatorial explosion. > But first I have to tell you that I'm fuzzy on how this exactly is > working together. I can't tell you how this affects GCC or LD. I was looking at this because it's not working correctly with LLD. > Nevertheless, the code overriding the members in per_process_cxx_malloc > is living in the app (_cygwin_crt0_common.cc). If you just append members > to per_process_cxx_malloc nad implement the wrappers in cxx.cc and > libstdcxx_wrapper.cc, then old apps using the old _cygwin_crt0_common.cc > will just not see the new functions. So that should work out of the > box, shouldn't it? I missed a pointer dereference in _cygwin_crt0_common.cc that meant the struct was being copied rather than the pointer replaced. I was concerned that a pointer to the old struct might be used, and garbage found in the new fields. I see now that it copies the contents, and if the struct is smaller it will obviously leave the new fields alone. I came across this comment that concerned me though /* Broken DLLs built against Cygwin versions 1.7.0-49 up to 1.7.0-57 override the cxx_malloc pointer in their DLL initialization code, when loaded either statically or dynamically. Because this leaves a stale pointer into demapped memory space if the DLL is unloaded by a call to dlclose, we prevent this happening for dynamically loaded DLLs in dlopen by saving and restoring cxx_malloc around the call to LoadLibrary, which invokes the DLL's startup sequence. Modern DLLs won't even attempt to override the pointer when loaded statically, but will write their overrides directly into the struct it points to. With all modern DLLs, this will remain the default_cygwin_cxx_malloc struct in cxx.cc, but if any broken DLLs are in the mix they will have overridden the pointer and subsequent overrides will go into their embedded cxx_malloc structs. This is almost certainly not a problem as they can never be unloaded, but if we ever did want to do anything about it, we could check here to see if the pointer had been altered in the early parts of the DLL's startup, and if so copy back the new overrides and reset it here. However, that's just a note for the record; at the moment, we can't see any need to worry about this happening. */ I don't see the save and restore mentioned in dlopen... Are these old DLLs sufficiently old that there wasn't 64-bit yet, and therefore can't be used anymore? -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple