On 2020-10-12 11:36:57 +0200, Michael Kerrisk (man-pages) via Gcc wrote:
> Hello Vincent,
> 
> On Thu, 8 Oct 2020 at 15:52, Vincent Lefevre <vinc...@vinc17.net> wrote:
> >
> > On 2020-10-01 18:55:04 +0200, Alejandro Colomar via Gcc wrote:
[...]
> > > The most explicit paragraph in dlsym is the following:
> > >
> > > [[
> > > Note that conversion from a void * pointer to a function pointer as in:
> > >
> > > fptr = (int (*)(int))dlsym(handle, "my_function");
> > >
> > > is not defined by the ISO C standard.
> > > This standard requires this conversion to work correctly
> > > on conforming implementations.
> > > ]]
> >
> > I think that "this conversion" applies only to the dlsym context,
> > and the conversion isn't defined in general. Imagine that the
> > void * pointer to function pointer conversion requires the compiler
> > to generate additional code. The compiler may be able to detect
> > that dlsym will not be used in some contexts (e.g. because of
> > always false condition) and do not generate such additional code,
> > making the conversion to have undefined behavior.
> 
> Thanks. It's a good point that you raise.
> 
> I agree that the wording in the standard is not too clear. But I
> believe the intent really is to allow
> [void *] <==> [function pointer] casts.

In this case, this should be standardized. In particular, there
is an issue with the rationale...

> The most relevant pieces I can find are as follows:
> 
> In the current standard, in CHANGE HISTORY for dlsum():
> 
> [[
> Issue 6
> IEEE Std 1003.1-2001/Cor 1-2002, item XSH/TC1/D6/14 is applied,
> correcting an example, and
> adding text to the RATIONALE describing issues related to conversion
> of pointers to functions
> and back again.
> Issue 7
> POSIX.1-2008, Technical Corrigendum 1, XSH/TC1-2008/0074 [74] is applied.
> ]]
> 
> https://www.austingroupbugs.net/view.php?id=74
> This is a little thin. The initial report says:
> "The intent is simply to permit dlsym to use a void * as its return type."
> and no one seems to have questioned that.
> 
> And then in https://pubs.opengroup.org/onlinepubs/7899949299/toc.pdf
> (TC1 for POSIXX.1-2001)
> 
> there is:
> 
> [[
> Change Number: XSH/TC1/D6/14 [XSH ERN 13]
> On Page: 259  Line: 8566,8590  Section: dlsym
> In the EXAMPLES section, change from:
> fptr = (int (*)(int))dlsym(handle, "my_function");
> to:
> *(void **)(&fptr) = dlsym(handle, "my_function");
> In the RATIONALE section on Page 260, Line 8590, change from:
> "None."
> to:
> "The C Standard does not require that pointers to functions can be
> cast back and forth to pointers to data. Indeed, the C Standard
> does not require that an object of type void* can hold a pointer
> to a function.  Systems supporting the X/Open System Interfaces
> Extension, however, do require that an object of type void* can
> hold a pointer to a function.  The result of converting a pointer
> to a function into a pointer to another data type (except void*)
> is still undefined, however.
> ]]

The last sentence is rather strange. This means that conversion
between pointers would not be transitive, contrary to the intent
of ISO C (via the transitivity of "correctly aligned").

In ISO C, the conversion of a void * to a pointer to another data type
is undefined only if the resulting pointer is not correctly aligned.

In particular, my interpretation of ISO C is that a conversion of
a void * to a char * is always defined. So, if the conversion of
a function pointer to void * is well-defined as a general rule, I
expect that the conversion of a function pointer to char * is also
well-defined, contrary to what the rationale says.

> And one finds the above text in POSIX.1-2001 TC1 spec for dlsym(),
> although it was removed in POSIX.1-2008, and now we have just the
> smaller text that is present in the dlsym() page. But along the way, I
> can find nothing that speaks against the notion that POSIX was aiming
> to allow the more general cast of [void *] <==> [function pointer].
> Your thoughts?

The equivalence of representation between function pointers and void *
may seem natural on von Neumann architectures, but what if functions,
or at least *some* functions (not those returned by dlsym), are from
a separate addressing model? For instance, one could think that some
compilers might implement particular standard functions only as
builtins, with some special handling when pointers to such functions
are used.

-- 
Vincent Lefèvre <vinc...@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

Reply via email to