Email List: Xaustin-group-lX
[All Lists]

Re: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem

To: austin-group-l@xxxxxxxxxxxxx
Subject: Re: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem
From: Geoff Clare <gwc@xxxxxxxxxxxxx>
Date: Thu, 27 Aug 2009 15:58:51 +0100
References: <f6e89684e7d6fc9a7b734e179e7e9c6f@austingroupbugs.net>
> ---------------------------------------------------------------------- 
>  (0000205) Don Cragun (manager) - 2009-08-27 00:03
>  http://austingroupbugs.net/view.php?id=74#c205 
> ---------------------------------------------------------------------- 
[snip]
> ------------------------------------------------------------------------
> 
> Cross volume change:
>       Delete subclause 2.12.3 from XBD P541, L18881-18886.

Not a cross volume change; that page is in XSH.

> ------------------------------------------------------------------------
> 
> Replace the NAME, SYNOPSIS, DESCRIPTION, RETURN VALUE, ERRORS, EXAMPLES,
> and APPLICATION USAGE sections of the dlclose() descripion on P728,
> L24469-24513 with:
> 
> NAME
>       dlclose -- close a symbol table handle
> 
> SYNOPSIS
>       #include <dlfcn.h>
>       int dlclose(void *handle);
> 
> DESCRIPTION
>       The dlclose() function shall inform the system that the symbol
>       table handle specified by handle is no longer needed by the
>       application.
> 
>       An application writer may use dlclose() to make a statement of
>       intent on the part of the process, but this statemen does not
>       create any requirement upon the implementation.

This is contradicted by the last sentence of the same paragraph, which
states a requirement on the implementation (to close object files if
the handle contains their last reference).

I think the above sentence could just be removed.

>       When the symbol
>       table handle is closed, the implementation may unload the
>       executable object files that were loaded by dlopen() when the
>       symbol table handle was opened and those that were loaded by
>       dlsym() when using the symbol table handle identified by handle.
>       Once a symbol table handle has been closed, an application
>       should assume that any symbols (function identifiers and data
>       object identifiers) made visible using handle, are no longer
>       available to the process.  Executable object files opened as a
>       result of using handle shall be closed if this handle contains
>       their last reference.

I think "result of using" should be "result of opening or using".

> ------------------------------------------------------------------------
> 
> Replace the NAME, SYNOPSIS, DESCRIPTION, and RETURN VALUE sections of
> the dlopen() descripion on P732-733, L24575-24666:
> 
> NAME
>       dlopen -- open a symbol table handle
> 
> SYNOPSIS
>       #include <dlfcn.h>
>       void *dlopen(const char *file, int mode);
> 
> DESCRIPTION
>       The dlopen() function shall make the symbols (function
>       identifiers and data object identifiers) in the executable
>       object file specified by file available to the calling program.
>       The class of files eligible for this operation and the manner of
>       their construction are implementation-defined, though typically
>       such files are executable object files such as shared libraries
>       or programs.

Since the first sentence says that file refers to an executable object
file, this last part is effectively saying that executable object
files are typically executable object files.  I suggest:

        The class of executable object files eligible for this
        operation and the manner of their construction are
        implementation-defined, though typically such files are
        shared libraries or programs.

>       Note that some implementations permit the
>       construction of embedded dependencies in executable object
>       files.  In such cases, a dlopen() operation shall load those
>       dependencies in addition to the executable object file specified
>       by file.  Implementations may also impose specific constraints
>       on the construction of programs that can employ dlopen() and its
>       related services.
> 
>       A successful dlopen() shall return a symbol table handle which
>       the caller may use on subsequent calls to dlsym() and dlclose().
>       The value of this symbol table handle should not be interpreted
>       in any way by the caller.
> 
>       The file argument is used to construct a pathname to the
>       executable object file.  If file contains a <slash> character,
>       the file argument is used as the pathname for the file.
>       Otherwise, file is used in an implementation-defined manner to
>       yield a pathname.
> 
>       If file is NULL, dlopen() shall return a global symbol table

Should be: If file is a null pointer, ...

>       handle for the currently running process image.  This symbol
>       table handle shall provide access to the symbols from an ordered
>       set of executable object files consisting of the original
>       program image file, any executable object files loaded at
>       program start-up as specified by that process image file (for
>       example, shared libraries), and the set of executable object
>       files loaded using dlopen() operations with the RTLD_GLOBAL
>       flag.  As the latter set of executable object files can change
>       during execution, the set of symbols made available by this
>       symbol table handle can also change dynamically.
> 
>       Only a single copy of an executable object file shall be brought
>       into the address space, even if dlopen() is invoked multiple
>       times in reference to the executable object file, and even if
>       different pathnames are used to reference the executable object
>       file.
> 
>       The mode parameter describes how dlopen() shall operate upon
>       file with respect to the processing of relocations and the scope
>       of visibility of the symbols provided within file.  When an
>       executable object file is brought into the address space of a
>       process, it may contain references to symbols whose addresses
>       are not known until the executable object file is loaded.
>       These references shall be relocated before the symbols can be
>       accessed.  The mode parameter governs when these relocations
>       take place and may have the following values:
> 
>       RTLD_LAZY       Relocations shall be performed at an
>                       implementation-defined time, ranging from the
>                       time of the dlopen() call until the first
>                       reference to a given symbol occurs.  Specifying
>                       RTLD_LAZY should improve performance on
>                       implementations supporting dynamic symbol
>                       binding since a process might not reference all
>                       of the symbols in an executable object file.
>                       And, for systems supporting dynamic symbol
>                       resolution for normal process execution, this
>                       behavior mimics the normal handling of process
>                       execution.
> 
>       RTLD_NOW        All necessary relocations shall be performed
>                       when the executable object file is first loaded.
>                       This may waste some processing if relocations
>                       are performed for symbols that are never
>                       referenced.  This behavior may be useful for
>                       applications that need to know that all symbols
>                       referenced during execution will be available
>                       before dlopen() returns.
> 
>       Any executable object file loaded by dlopen() that requires
>       relocations against global symbols can reference the symbols in
>       the original process image file, any executable object files
>       loaded at program start-up, from the initial process image
>       itself, from any other executable object file included in the
>       same dlopen() invocation, and any executable object files that
>       were loaded in any dlopen() invocation and which specified the
>       RTLD_GLOBAL flag.  To determine the scope of visibility for the
>       symbols loaded with a dlopen() invocation, the mode parameter
>       should be a bitwise-inclusive OR with one of the following
>       values:
> 
>       RTLD_GLOBAL     The executable object file's symbols shall be
>                       made available for relocation processing of any
>                       other executable object file.  In addition,
>                       symbol lookup using dlopen(NULL, mode) and an
>                       associated dlsym() allows executable object
>                       files loaded with this mode to be searched.
> 
>       RTLD_LOCAL      The executable object file's symbols shall not
>                       be made available for relocation processing of
>                       any other executable object file.
> 
>       If neither RTLD_GLOBAL nor RTLD_LOCAL are specified, the default
>       behavior is unspecified.
> 
>       If an executable object file is specified in multiple dlopen()
>       invocations, mode is interpreted at each invocation.  Note,
>       however, that once RTLD_NOW has been specified, all relocations
>       shall have been completed rendering further RTLD_NOW operations
>       redundant and any further RTLD_LAZY operations irrelevant.
>       Similarly, note that once RTLD_GLOBAL has been specified, the
>       executable object file shall maintain the RTLD_GLOBAL status
>       regardless of any previous or future specification of
>       RTLD_LOCAL, as long as the executable object file remains in the
>       address space (see dlclose()).
> 
>       Symbols introduced into the process image through calls to
>       dlopen() may be used in relocation activities.  Symbols so
>       introduced may duplicate symbols already defined by the program
>       or previous dlopen() operations.  To resolve the ambiguities
>       such a situation might present, the resolution of a symbol
>       reference to symbol definition is based on a symbol resolution
>       order.  Two such resolution orders are defined: load order and
>       dependency order.  Load order establishes an ordering among
>       symbol definitions, such that the first definition loaded
>       (including definitions from the process image file and any
>       dependent executable object files loaded with it) has priority
>       over executable object files added later (by dlopen()).  Load
>       ordering is used in relocation processing.  Dependency ordering
>       uses a breadth-first order starting with a given executable
>       object file, then all of its dependencies, then any dependents
>       of those, iterating until all dependencies are satisfied.  With
>       the exception of the global symbol table handle obtained via a
>       dlopen() operation on a file of NULL, dependency ordering is

Should be: dlopen() operation with a null pointer as the file argument, ...

>       used by the dlsym() function.  Load ordering is used in dlsym()
>       operations upon the global symbol table handle.
> 
>       When an executable object file is first made accessible via
>       dlopen(), it and its dependent executable object files are added
>       in dependency order.  Once all the executable object files are
>       added, relocations are performed using load order.  Note that if
>       an executable object file or its dependencies had been
>       previously loaded, the load and dependency orders may yield
>       different resolutions.
> 
>       The symbols introduced by dlopen() operations and available
>       through dlsym() are at a minimum those which are exported as
>       identifiers of global scope by the executable object file.
>       Typically such identifiers shall be those that were specified in
>       (for example) C source code as having extern linkage.  The
>       precise manner in which an implementation constructs the set of
>       exported symbols for an executable object file is
>       implementation-defined.
> 
> RETURN VALUE
>       Upon successful completion, dlopen() shall return a symbol table
>       handle.  If file cannot be found, cannot be opened for reading,
>       is not of an appropriate executable object file format for
>       processing by dlopen(), or if an error occurs during the process
>       of loading file or relocating its symbolic references, dlopen()
>       shall return NULL.  More detailed diagnostic information shall
>       be available through dlerror().
> 
> ------------------------------------------------------------------------
> 
> Replace the NAME, SYNOPSIS, DESCRIPTION, RETURN VALUE, ERRORS, EXAMPLES,
> APPLICATION USAGE, and RATIONALE sections of the dlsym() descripion on
> P735-736, L24689-24748 with:
> 
> NAME
>       dlsym -- get the address of a symbol from a symbol table handle
> 
> SYNOPSIS
>       #include <dlfcn.h>
>       void *dlsym(void *restrict handle, const char *restrict name);
> 
> DESCRIPTION
>       The dlsym() function shall obtain the address of a symbol (a
>       function identifier or a data object identifier) defined in the
>       symbol table identified by the handle argument.  The handle
>       argument is a symbol table handle returned from a call to
>       dlopen() (and which has not since been released by a call to
>       dlclose()), and name is the symbol's name as a character
>       string.  The return value from dlsym(), cast to a pointer to the
>       type of the named symbol, may be used to call (in the case of a

s/may/can/

>       function) or access the contents of (in the case of a data
>       object) the named symbol.
> 
>       The dlsym() function shall search for the named symbol in
>       the symbol table referenced by handle.  If the symbol table was
>       created with lazy loading (see RTLD_LAZY in dlopen()), load
>       ordering shall be used in dlsym() operations to relocate
>       executable object files needed to resolve the symbol.  The
>       symbol resolution algorithm used shall be dependency order
>       as described in dlopen().
> 
>       The RTLD_DEFAULT and RTLD_NEXT symbolic constants (which may be
>       defined in <dlfcn.h>) are reserved for future use as special
>       values that applications may be allowed to use for handle.
> 
> RETURN VALUE
>       Upon successful completion, if name names a function identifier,
>       dlsym() shall return the address of the function converted from
>       type pointer to function to type pointer to void; otherwise
>       dlsym() shall return the address of the data object associated
>       with the data object identfier named by name converted from a
>       pointer to the type of the data object to a pointer to void.  If
>       handle does not refer to a valid symbol table handle or if the
>       symbol named by name cannot be found in the symbol table
>       associated with handle, dlsym() shall return NULL.  More
>       detailed diagnostic information shall be available through
>       dlerror().
> 
> ERRORS
>       No errors are defined.
> 
> EXAMPLES
>       The following example shows how dlopen() and dlsym() can be used
>       to access either a function or a data object.  For simplicity,
>       error checking has been omitted.
> 
>       void    *handle;
>       int     (*fptr)(int),
>               *iptr,
>               result;
> 
>       /* open the needed symbol table */
>       handle = dlopen("/usr/home/me/libfoo.so", RTLD_LOCAL | RTLD_LAZY);
> 
>       /* find the address of the function my_function */
>       *(void **)(&fptr) = dlsym(handle, "my_function");

Should be:
        fptr = (int (*)(int))dlsym(handle, "my_function");

> 
>       /* find the address of the data object my_object */
>       iptr = (int *)dlsym(handle, "my_OBJ");
> 
>       /* invoke my_function, passing the value of my_OBJ as the parameter */
>       result = (*fptr)(*iptr);
> 
> APPLICATION USAGE
>       The following special purpose values for handle are reserved for
>       future use and have the indicated meanings:
> 
>       RTLD_DEFAULT    The identifier lookup happens in the normal
>                       global scope; that is, a search for a identifier
>                       using handle would find the same definition as a
>                       direct use of this identifier in the program
>                       code.
> 
>       RTLD_NEXT       Specifies the next executable object file after
>                       this one that defines name.  This one refers to
>                       the executable object file containing the
>                       invocation of dlsym().  The next executable
>                       object file is the one found upon the
>                       application of a load order symbol resolution
>                       algorithm (see dlopen()).  The next symbol is
>                       either one of global scope (because it was
>                       introduced as part of the original process image
>                       or because it was added with a dlopen()
>                       operation including the RTLD_GLOBAL flag), or is
>                       in an executable object file that was included
>                       in the same dlopen() operation that loaded this
>                       one.
> 
>                       The RTLD_NEXT flag is useful to navigate an
>                       intentionally created hierarchy of
>                       multiply-defined symbols created through
>                       interposition.  For example, if a program wished
>                       to create an implementation of malloc() that
>                       embedded some statistics gathering about memory
>                       allocations, such an implementation could use
>                       the real malloc() definition to perform the
>                       memory allocation-and itself only embed the
>                       necessary logic to implement the statistics
>                       gathering function.
> 
>       Note that compilers conforming to the ISO C standard are
>       required to generate a warning if a conversion from a void *
>       pointer to a function pointer is attempted as in:
> 
>       fptr = (int (*)(int))dlsym(handle, "my_function");

I suggest adding:

        However, conversion using a cast like this is the only
        portable way of obtaining a function pointer from dlsym().
        Some earlier versions of this standard suggested the use
        of the following alternative to avoid the warning:

        *(void **)(&fptr) = dlsym(handle, "my_function");

        Execution of this code results in undefined behavior.

-- 
Geoff Clare <g.clare@opengroup.org>
The Open Group, Thames Tower, Station Road, Reading, RG1 1LX, England

<Prev in Thread] Current Thread [Next in Thread>