Date: Thu, 13 Jul 2023 14:01:16 +0300
On Thu, 13 Jul 2023 at 01:26, Thiago Macieira via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Wednesday, 12 July 2023 07:56:38 PDT Arthur O'Dwyer via Std-Proposals
> wrote:
> > (2) More importantly, I'm aware of 2 clauses that the clash with the
> >
> > > Windows PE model:
> > > (a) [expr.eq] http://eel.is/c++draft/expr.eq#3.2, has this to say
> about
> > >
> > > comparison of function-pointers: "... if the pointers ... both point to
> > > the
> > > same function ... they compare equal."
> > > This is not so simple if the function in question is implemented in a
> > > shared library: an actual `call` is made to the current binary's PLT
> (in
> > > ELF systems) or IAT (in PE systems), so the direct call address is
> > > different across binaries.
> >
> > IIUC, you're saying that an existing major implementation (MSVC on
> Windows,
> > and perhaps clang-cl on Windows also) is non-conforming to the letter of
> > the Standard.
> > This is worthy of a bug report (if easily fixed), or a paper (if not,
> and I
> > think you're saying not).
>
> It's not a *bug* because it's a design decision. You can call it a "flaw"
> if
> this was unintended, but more likely it's just "limitation".
>
> > Your paper's goal will be to change the wording of [expr.eq] to bring the
> > wording into line with the Windows reality. But, at the same time, your
> > proposed wording ("equality of function pointers is
> > implementation-defined") is simply too broad. We want to be able to rely
> on
> > pointer equality to Do The Right Thing in C++ programs, don't we?
> > So your paper should explore
> > - heroic ways to make MSVC conform to the existing wording
> > - ways to segregate functions at compile time into "those whose addresses
> > definitely compare equal" and "those whose comparisons are
> > implementation-defined"; this might relate to your (1) above, or it might
> > not
> > - ways to query at compile time whether we're on a weird platform or not,
> > e.g. `#if __FUNCTION_POINTERS_MIGHT_SPURIOUSLY_COMPARE_UNEQUAL`
> > - alternatively, what goes wrong with the status quo if we just say
> "okay,
> > MSVC isn't conforming in this regard" and move on?
>
> Please note function pointers themselves and their comparisons are not the
> issue, because the compiler can (and does) compare to the address stored
> in
> the IAT. See https://msvc.godbolt.org/z/9nxYeM7Pv.
>
> I believe your snippet demonstrates the opposite. `__imp__exit` is the
import stub, created in the static import lib alongside the dll and merged
into *the current binary's* Directory-Table (in the .idata section) by
statically linking this import library. The address of __imp_exit is
different across binaries.
> Or you cop out by claiming you've stepped outside the standard: the
> replacement is allowed and does work *within* each DLL. You just don't
> override code from other DLLs.
>
@Arthur O'Dwyer please note: this is a very common interpretation of
'stepping outside the standard', often encountered in such discussions and
which you seem to (reasonably) refer to as a misinterpretation of 'being
out of scope'. I think we all agree this is indeed a cop-out and the
standard should take steps not to allow such interpretations. C++ code
built into DLLs is still C++ code.
> On this one, I side with Microsoft: let's accept the limitation and
> deprecate
> this functionality in C++. It's much better to have a function like
> set_new_handler() or set_terminate() to do the overriding.
>
> BTW, I'll add a 2(c): _exit() runs global destructors in DLLs. This is not
> an
> OS ABI limitation, but caused by how _exit() is implemented (calls
> TerminateProcess()) and how the runtimes implement global destruction.
> That
> means it can be fixed without OS modifications, but still has a high cost.
>
Can you please elaborate on which clause this doesn't conform to? Perhaps
you're referring to runtime loading/unloading (LoadLibrary/UnloadLibrary on
windows) or Lazy-Binding? ("Delayed-Load" on windows)
>
> There's also a 2(d): after exit() starts, on Windows all threads
> disappear, so
> atexit() handlers (including destructors) are not able to join with
> pending
> threads or lock mutexes that were found locked at the time the exiting
> started. Combined with 2(c), this means code run from destructors that may
> touch resources under mutex protection may deadlock the application on
> exit,
> even after _exit(), abort(), or terminate().
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel DCAI Cloud Engineering
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
> On Wednesday, 12 July 2023 07:56:38 PDT Arthur O'Dwyer via Std-Proposals
> wrote:
> > (2) More importantly, I'm aware of 2 clauses that the clash with the
> >
> > > Windows PE model:
> > > (a) [expr.eq] http://eel.is/c++draft/expr.eq#3.2, has this to say
> about
> > >
> > > comparison of function-pointers: "... if the pointers ... both point to
> > > the
> > > same function ... they compare equal."
> > > This is not so simple if the function in question is implemented in a
> > > shared library: an actual `call` is made to the current binary's PLT
> (in
> > > ELF systems) or IAT (in PE systems), so the direct call address is
> > > different across binaries.
> >
> > IIUC, you're saying that an existing major implementation (MSVC on
> Windows,
> > and perhaps clang-cl on Windows also) is non-conforming to the letter of
> > the Standard.
> > This is worthy of a bug report (if easily fixed), or a paper (if not,
> and I
> > think you're saying not).
>
> It's not a *bug* because it's a design decision. You can call it a "flaw"
> if
> this was unintended, but more likely it's just "limitation".
>
> > Your paper's goal will be to change the wording of [expr.eq] to bring the
> > wording into line with the Windows reality. But, at the same time, your
> > proposed wording ("equality of function pointers is
> > implementation-defined") is simply too broad. We want to be able to rely
> on
> > pointer equality to Do The Right Thing in C++ programs, don't we?
> > So your paper should explore
> > - heroic ways to make MSVC conform to the existing wording
> > - ways to segregate functions at compile time into "those whose addresses
> > definitely compare equal" and "those whose comparisons are
> > implementation-defined"; this might relate to your (1) above, or it might
> > not
> > - ways to query at compile time whether we're on a weird platform or not,
> > e.g. `#if __FUNCTION_POINTERS_MIGHT_SPURIOUSLY_COMPARE_UNEQUAL`
> > - alternatively, what goes wrong with the status quo if we just say
> "okay,
> > MSVC isn't conforming in this regard" and move on?
>
> Please note function pointers themselves and their comparisons are not the
> issue, because the compiler can (and does) compare to the address stored
> in
> the IAT. See https://msvc.godbolt.org/z/9nxYeM7Pv.
>
> I believe your snippet demonstrates the opposite. `__imp__exit` is the
import stub, created in the static import lib alongside the dll and merged
into *the current binary's* Directory-Table (in the .idata section) by
statically linking this import library. The address of __imp_exit is
different across binaries.
> Or you cop out by claiming you've stepped outside the standard: the
> replacement is allowed and does work *within* each DLL. You just don't
> override code from other DLLs.
>
@Arthur O'Dwyer please note: this is a very common interpretation of
'stepping outside the standard', often encountered in such discussions and
which you seem to (reasonably) refer to as a misinterpretation of 'being
out of scope'. I think we all agree this is indeed a cop-out and the
standard should take steps not to allow such interpretations. C++ code
built into DLLs is still C++ code.
> On this one, I side with Microsoft: let's accept the limitation and
> deprecate
> this functionality in C++. It's much better to have a function like
> set_new_handler() or set_terminate() to do the overriding.
>
> BTW, I'll add a 2(c): _exit() runs global destructors in DLLs. This is not
> an
> OS ABI limitation, but caused by how _exit() is implemented (calls
> TerminateProcess()) and how the runtimes implement global destruction.
> That
> means it can be fixed without OS modifications, but still has a high cost.
>
Can you please elaborate on which clause this doesn't conform to? Perhaps
you're referring to runtime loading/unloading (LoadLibrary/UnloadLibrary on
windows) or Lazy-Binding? ("Delayed-Load" on windows)
>
> There's also a 2(d): after exit() starts, on Windows all threads
> disappear, so
> atexit() handlers (including destructors) are not able to join with
> pending
> threads or lock mutexes that were found locked at the time the exiting
> started. Combined with 2(c), this means code run from destructors that may
> touch resources under mutex protection may deadlock the application on
> exit,
> even after _exit(), abort(), or terminate().
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel DCAI Cloud Engineering
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2023-07-13 11:01:29