Chapter 7. Loader Information #pragma Directives

Table 7-1 lists the #pragma directives discussed in this chapter, along with a brief description of each and the compiler versions in which the directive is supported.

Table 7-1. Loader Information #pragma Directives

#pragma

Short Description

Compiler Versions

#pragma hidden

Tells the compiler that the specified symbols are invisible to all executables or DSOs except the current one.

7.2 and later

#pragma internal

Tells the compiler that the specified symbols are not referenced outside the current executable or DSO.

7.2 and later

#pragma no_delete

Inhibits deletion of functions that are never referenced.

7.1 and later

#pragma optional

Tells the linker that the specified symbols are optional. This is the basic mechanism used for adding extensions to a library that can then be queried.

7.2.1 and later

#pragma protected

Tells the compiler that the specified symbols are not preemptible.

7.1 and later

#pragma section_gp

Causes an object to be placed in a gp_relative section.

7.2 and later

#pragma section_non_gp

Keeps an object from being placed in a gp_relative section.

7.2 and later

#pragma weak

Tells the link editor not to issue a warning if it does not find a defining declaration of the weak_symbol. Also allows the overriding of a current definition by a non-weak definition.

7.0 and later

#pragma weak

weak_symbol = strong_symbol

Sets weak_symbol to be an alias for the function or data object denoted by strong_symbol , unless a defining declaration for weak_symbol is encountered at static link time. If encountered, the defining declaration preempts the weak denotation.

7.0 and later


#pragma hidden

The #pragma hidden directive tells the compiler that the specified symbols are invisible to all executables or DSOs except the current one. This allows hidden data objects to be placed in the small data area and accessed using the (fast) gp-relative load/store. Hidden symbols need not be put into the hash table of a DSO because they are not globally visible.

The syntax of the #pragma hidden directive is as follows:

#pragma hidden symbol1 [, symbol2 ...]

#pragma hidden is not currently supported in C++, except for symbols marked extern “C”.

All of the listed symbols are marked as STO_HIDDEN. This means that the symbol definition can be referenced only within an object, not from outside. Even though a hidden symbol cannot be directly referenced from outside a DSO, its address may be taken and passed, so it is possible to call a hidden function from another DSO.

#pragma internal

The #pragma internal directive tells the compiler that the specified functions are not referenced outside the current executable or DSO. Internal symbols are the same as hidden symbols, except that they are guaranteed not to be referenced from outside a DSO, even through pointers or weak bindings.

The syntax of the #pragma internal directive is as follows:

#pragma internal func1 [, func2 ...]

#pragma internal is not currently supported in C++, except for symbols marked extern “C”.

The specified functions are marked STO_INTERNAL. This means that this function need not save, restore, or recalculate $gp (global pointer), because it is callable only from a location that has the same $gp (global pointer) value.

#pragma no_delete name

The #pragma no_delete directive inhibits deletion of functions that are never referenced.

The syntax of the #pragma no_delete directive is as follows:

#pragma no_delete

Note: This pragma applies only to C++ and is not available for C programs. It applies only to functions, not data. It changes the ELF symbol name from its current name to a local name, thus making the ELF name (as seen by dis(1)) unusual and causing the name to not appear to debuggers.


#pragma optional

The #pragma optional directive tells the linker that the specified symbols are optional.

The static linker (ld), converts references to optional definitions (in another DSO) to optional references. Unresolved optional references are not reported as errors.

The run-time linker (rld) resolves any unresolved optional references to a special symbol in libc.so.1.

Programs can check for the existence of an optional symbol by use of macros defined in the header file /usr/include/optional_sym.h.

This is the basic mechanism used for adding extensions to a library that you can then query. For example, when new functions are added to the next revision of libfoo.so, they can be added as optional functions; then programs can check for their existence and use them only when the new revision of the library is available and avoid them on older systems, thus giving backwards and forwards compatibility across a series of releases.

The syntax of the #pragma optional directive is as follows:

#pragma optional symbol1 [, symbol2 ... ]

The following rules apply to #pragma optional:

  • #pragma optional must come after the declaration or definition of symbol.

  • #pragma optional is not currently supported in C++, except for symbols marked extern “C”.

#pragma protected

The #pragma protected directive tells the compiler that the specified symbols are not preemptible, but are visible from outside of a DSO.

The syntax of the #pragma protected directive is as follows:

#pragma protected symbol1 [, symbol2 ...]

#pragma protected is not currently supported in C++, except for symbols marked extern “C”.

The specified symbols are marked STO_PROTECTED. This means that the symbol definition cannot be preempted by another definition.

#pragma section_gp

MIPS binaries have a global pointer (gp) that can be used to reference global data more efficiently (by using gp + offset) than constructing the entire address when that variable is referenced. Only a limited set of elements can be referenced in this fashion because the size of offset is limited to 16 bits. The compiler heuristically places global data in either gp-relative or non-gp-relative sections. However, it is sometimes useful to manually control which variables go within the gp-relative section and which need to be addressed explicitly.

The #pragma section_gp directive causes an object to be placed in a gp_relative section, while the #pragma section_non_gp directive causes an object to be placed in a non-gp-relative section.

The syntax of the #pragma section_gp directive is as follows:

#pragma section_gp symbol1[, symbol2 ...]

symbol must be a static or global variable.

#pragma section_non_gp

MIPS binaries have a global pointer (gp) that can be used to reference global data more efficiently (by using gp + offset) than constructing the entire address when that variable is referenced. Only a limited set of elements can be referenced in this fashion because the size of offset is limited to 16 bits. The compiler heuristically places global data in either gp-relative or non-gp-relative sections. However, it is sometimes useful to manually control which variables go within the gp-relative section and which need to be addressed explicitly.

The #pragma section_gp directive causes an object to be placed in a gp_relative section, while the #pragma section_non_gp directive causes an object to be placed in a non-gp-relative section.

The syntax of the #pragma section_non_gp directive is as follows:

#pragma section_non_gp symbol1[, symbol2 ...]

symbol must be a static or global variable.

#pragma weak

The #pragma weak directive can be used in two ways. It can instruct the link editor to not issue a warning if it does not find a defining declaration of the specified weak symbol, or it can allow the overriding of a current definition by a non-weak definition.

Weak definitions behave as follows:

  • A definition is weak if a symbol defined in an executable or DSO is marked as weak at the point of definition.

  • A weak definition is preemptible and will be preempted by any strong global definition of the same name in the executable, the DSOs linked in at static link time, or the DSOs linked in at run time. Multiple weak definitions follow the same preemption rules as for global symbols except that they will all be preempted by any strong definition of their name.

  • Multiple global weak definitions of a symbol may or may not result in an error:

    • At static link time, multiple global definitions of a weak symbol within a DSO or executable result in an error. For example, linking a.o and b.o when they both have definitions for the symbol x results in an error.

    • At run time, multiple global weak definitions of a symbol across the executable and its DSOs, result in the first definition preempting all others. No error message is generated. For example, if your executable, j, references the DSOs k.so and l.so that have weak definitions of the symbol y, the first definition encountered is used, and the other is ignored.

  • Unresolved weak references do not cause a run-time error, even if the environment variable LD_BIND_NOW is set. They have a value of 0 (that is, the symbol address is taken as 0). Attempting a call of a weak undefined function symbol gets either a core dump (if LD_BIND_NOW is 1) or a fatal run-time linker error on an attempted address of an unresolved symbol (if LD_BIND_NOW is not 1). Attempting a load or store of an undefined weak symbol results in a core dump because the address is 0, and 0 is normally not a legal virtual address.

  • Weak references do not trigger the loading of delay-loaded libraries. This implies that weak object references may go unresolved until some other event triggers the loading of the delay-load library.

The syntax of the #pragma weak directive is as follows:

#pragma weak weak_symbol [= strong_symbol]

When #pragma weak applies to a C++ function, weak_symbol and strong_symbol must be the mangled names.

The #pragma weak directive can be used in the following two ways:

  • #pragma weakweak_symbol

    Used in this way, the #pragma weak directive tells the link editor to not issue a warning if it does not find a defining declaration of weak_symbol. References to the symbol use the appropriate lvalue if the symbol is defined; otherwise, it uses memory location zero (0).

  • #pragma weak weak_symbol = strong_symbol

    In this case, the weak_symbol is an alias that denotes the same function or data object as that denoted by the strong_symbol, unless a defining declaration for the weak_symbol is encountered at static link time or in dynamically linked libraries. If encountered, the defining declaration preempts the weak denotation.

    Observe the following conventions when using this form of the directive:

    • Define the strong_symbol within the same compilation unit in which the directive occurs.

    • Declare the weak and strong symbols with compatible types. When the strong symbol is a data object, its declaration must be initialized.

    • Declare the weak_symbol with extern linkage in the same compilation unit. The extern declaration of the weak symbol is not required, unless the symbol is referenced within the compilation unit, but Silicon Graphics recommends it for type-checking purposes.

      Weak extern declarations are typically used to export non-ANSI C symbols from a library without polluting the ANSI C name-space. As an example, libc may export a weak symbol read(), which aliases a strong symbol _read(), where _read() is used in the implementation of the exported symbol fread(). You can either use the exported (weak) version of read(), or define your own version of read(), thereby preempting the weak denotation of this symbol. This will not alter the definition of fread(), because it depends only on the (strong) symbol _read(), which is outside of the ANSI C name-space.

      For example, the following code defines a new version of read() (which is a weak symbol in libc.so.1):

      /* read() is a weak symbol in libc.so.1
           This program omits error checking and makes no
           attempt at good style!
      */
      #include <stdio.h>
      char *read(int);
      
      int main(int argc, char **argv) 
      {
        char *var;
        int c;
      
        c = getchar();
      
        var = read(c);
        printf(“%s\n”,var);
        return c;
      }
      
      char *read(int val)
      {
        static char buf[100];
        sprintf(buf,”%d”,val);
        return buf;
      }

      This program reads a single character from standard input and prints the character's decimal value. Even though getchar() uses the libc.so version of fread(), the redefinition of read() has no effect on the internal processing in libc.so because fread() uses the strong symbol _read().


Caution: The #pragma weak directive is not supported in -o32 C++.