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)