Date: Thu, 13 Jul 2023 10:10:46 +0300
On Wed, 12 Jul 2023 at 17:47, Sebastian Wittmeier via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> For 2a) I do not think that functions in different executables (but the
> same DLL) necessarily should compare equal or compare at all.
>
Nothing is being compared across processes (is this what you mean by
"different executables"?). The problematic situation is code like:
// executable:
void ImplementedInLibA();
bool compareFuncPtrsInLibB(void (*)());
int main {
void (*pf1)() = &ImplementedInLibA();
compareFuncPtrsInLibB(pf1);
}
// shared lib B:
bool compareFuncPtrsInLibB(void (*pf)()) {
void (*pf2)() = &ImplementedInLibA();
return pf == pf2; // true on Linux, false on Windows
}
>
>
> But I am not convinced, that shared libs should be directly referenced in
> the standard. What real-life problems would you solve by doing it?
>
What real-life problems are solved by including these statements in the
standard? "Translation units can be separately translated and then later
linked to produce an executable program", "All such translator output is
collected into a program image which contains information needed for
execution in its execution environment".
Descriptive sections have little impact on implementations anyway - as
would any modifications to them. I just hope to make the standard more
accurate.
But I'm comfortable with dropping the modifications to the descriptive
sections, and submitting defects for the downright un-implementable
sections.
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Ofek Shilon via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Mi 12.07.2023 16:34
> *Betreff:* [std-proposals] "shared libraries are outside the scope of the
> C++ standard"
> *An:* std-proposals_at_[hidden];
> *CC:* Ofek Shilon <ofekshilon_at_[hidden]>;
> This is a statement one meets in many variations, when trying to
> understand C++'s stance on many real world problems. I imagine I'm not the
> only one who is deeply uncomfortable with this answer. Even the meaning of
> this statement is far from obvious: does it mean that code that is linked
> to a shlib is not susceptible to the standard restrictions? Perhaps
> programs that link against shared libraries are undefined behavior? (Note
> that's close to 100% of real programs, as most link to libc dynamically).
> Truth is, the standard doesn't even say something definite like 'undefined
> behavior': the abstract machine lives in an imaginary world where shared
> libs don't exist, so in a very real sense the c++ standard does not apply
> to most real world programs.
>
> I'd like to try and explore whether something can be done about that. I'm
> not aware of previous such attempts, would be happy to hear if you are.
> ---------------------------------------------------
>
> (1) First, a few general descriptive sections should be reviewed and
> mostly rephrased, probably introducing a concept like 'linkage-unit':
> [lex.phases] : http://eel.is/c++draft/lex.phases#1.9
> [lex.separate] http://eel.is/c++draft/lex.separate#2
> [basic.link] http://eel.is/c++draft/basic.link
>
> (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.
> In ELF systems an elaborate mechanism promises the comparison succeeds:
> the address of a function, even if implemented in a shared lib, is resolved
> by the loader and stored as a value in the *executable*'s symbol table
> (even if the executable doesn't use it). If the address of the function is
> taken anywhere in the process - from code in the executable or any shared
> library - it is resolved from the *executable*'s symbol table.
> No analogue apparatus is in place for PE, and comparison of pointers to
> the same function taken from code in different binaries will not return
> equal.
>
> (b) [replacement.functions]
> http://eel.is/c++draft/replacement.functions#3, lists flavours of
> new/delete that can be interposed (==overridden) from user code:
> "The program's definitions are used instead of the default versions
> supplied by the implementation.".
> This does happen in ELF systems, where (unless you build with -Bsymbolic)
> the loader searches the executable first while trying to resolve all
> symbols, including new/delete.
> This doesn't happen in PE DLLs, where the .idata section explicitly says
> from which DLL to import each function. So for example `new` will by
> default be imported from the Windows VC-Runtime Dlls, can also be resolved
> from a static library linked to the DLL - but *NOT* from the main
> executable.
>
>
> To bridge these gaps, either Microsoft's PE design needs to change or the
> standard needs to take a pragmatic approach and relax these clauses. The
> PE design cannot change (the world will quite literally break), so the only
> way I can see forward is to relax the standard's demands to have them
> applicable to all real world programs on real world operating systems. For
> example: "if two pointers both point to the same function *it is
> implementation defined whether* they compare equal".
>
> ---------------------------------------------------
>
> Would a paper investigating along these lines be of interest to the
> community? Any other opinions and additions are very welcome.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
> For 2a) I do not think that functions in different executables (but the
> same DLL) necessarily should compare equal or compare at all.
>
Nothing is being compared across processes (is this what you mean by
"different executables"?). The problematic situation is code like:
// executable:
void ImplementedInLibA();
bool compareFuncPtrsInLibB(void (*)());
int main {
void (*pf1)() = &ImplementedInLibA();
compareFuncPtrsInLibB(pf1);
}
// shared lib B:
bool compareFuncPtrsInLibB(void (*pf)()) {
void (*pf2)() = &ImplementedInLibA();
return pf == pf2; // true on Linux, false on Windows
}
>
>
> But I am not convinced, that shared libs should be directly referenced in
> the standard. What real-life problems would you solve by doing it?
>
What real-life problems are solved by including these statements in the
standard? "Translation units can be separately translated and then later
linked to produce an executable program", "All such translator output is
collected into a program image which contains information needed for
execution in its execution environment".
Descriptive sections have little impact on implementations anyway - as
would any modifications to them. I just hope to make the standard more
accurate.
But I'm comfortable with dropping the modifications to the descriptive
sections, and submitting defects for the downright un-implementable
sections.
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Ofek Shilon via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Mi 12.07.2023 16:34
> *Betreff:* [std-proposals] "shared libraries are outside the scope of the
> C++ standard"
> *An:* std-proposals_at_[hidden];
> *CC:* Ofek Shilon <ofekshilon_at_[hidden]>;
> This is a statement one meets in many variations, when trying to
> understand C++'s stance on many real world problems. I imagine I'm not the
> only one who is deeply uncomfortable with this answer. Even the meaning of
> this statement is far from obvious: does it mean that code that is linked
> to a shlib is not susceptible to the standard restrictions? Perhaps
> programs that link against shared libraries are undefined behavior? (Note
> that's close to 100% of real programs, as most link to libc dynamically).
> Truth is, the standard doesn't even say something definite like 'undefined
> behavior': the abstract machine lives in an imaginary world where shared
> libs don't exist, so in a very real sense the c++ standard does not apply
> to most real world programs.
>
> I'd like to try and explore whether something can be done about that. I'm
> not aware of previous such attempts, would be happy to hear if you are.
> ---------------------------------------------------
>
> (1) First, a few general descriptive sections should be reviewed and
> mostly rephrased, probably introducing a concept like 'linkage-unit':
> [lex.phases] : http://eel.is/c++draft/lex.phases#1.9
> [lex.separate] http://eel.is/c++draft/lex.separate#2
> [basic.link] http://eel.is/c++draft/basic.link
>
> (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.
> In ELF systems an elaborate mechanism promises the comparison succeeds:
> the address of a function, even if implemented in a shared lib, is resolved
> by the loader and stored as a value in the *executable*'s symbol table
> (even if the executable doesn't use it). If the address of the function is
> taken anywhere in the process - from code in the executable or any shared
> library - it is resolved from the *executable*'s symbol table.
> No analogue apparatus is in place for PE, and comparison of pointers to
> the same function taken from code in different binaries will not return
> equal.
>
> (b) [replacement.functions]
> http://eel.is/c++draft/replacement.functions#3, lists flavours of
> new/delete that can be interposed (==overridden) from user code:
> "The program's definitions are used instead of the default versions
> supplied by the implementation.".
> This does happen in ELF systems, where (unless you build with -Bsymbolic)
> the loader searches the executable first while trying to resolve all
> symbols, including new/delete.
> This doesn't happen in PE DLLs, where the .idata section explicitly says
> from which DLL to import each function. So for example `new` will by
> default be imported from the Windows VC-Runtime Dlls, can also be resolved
> from a static library linked to the DLL - but *NOT* from the main
> executable.
>
>
> To bridge these gaps, either Microsoft's PE design needs to change or the
> standard needs to take a pragmatic approach and relax these clauses. The
> PE design cannot change (the world will quite literally break), so the only
> way I can see forward is to relax the standard's demands to have them
> applicable to all real world programs on real world operating systems. For
> example: "if two pointers both point to the same function *it is
> implementation defined whether* they compare equal".
>
> ---------------------------------------------------
>
> Would a paper investigating along these lines be of interest to the
> community? Any other opinions and additions are very welcome.
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2023-07-13 07:11:00