9.3. ELF Directives

ELF adds additional assembler directives to define weak symbols (WEAK), set symbol size (SIZE), and indicate whether a symbol is specifically a function or an object (TYPE). ELF also adds a directive to assist in identifying the source file or version, IDENT.

9.3.1. IDENT: Add file identification

The IDENT directive allows adding arbitrary string data to an ELF object file that will be saved in the object and executable file, but will not be loaded into memory like data in the .data section. It is often used for saving version control keyword information from tools such as cvs or svn into files so that the source revision the object was created with can be read using the ident command found on most Unix systems.

The directive takes one or more string parameters. Each parameter is saved in sequence as a 0-terminated string in the .comment section of the object file. Multiple uses of the IDENT directive are legal, and the strings will be saved into the .comment section in the order given in the source file.

In NASM syntax, no wrapper macro is provided for IDENT, so it must be wrapped in square brackets. Example use in NASM syntax:

[ident "$Id$"]

9.3.2. SIZE: Set symbol size

ELF’s symbol table has the capability of storing a size for a symbol. This is commonly used for functions or data objects. While the size can be specificed directly for COMMON symbols, the SIZE directive allows for specifying the size of any symbol, including local symbols.

The directive takes two parameters; the first parameter is the symbol name, and the second is the size. The size may be a constant or an expression. Example:

func:
        ret
.end:
size func func.end-func

9.3.3. TYPE: Set symbol type

ELF’s symbol table has the capability of indicating whether a symbol is a function or data. While this can be specified directly in the GLOBAL directive (see Section 9.4), the TYPE directive allows specifying the symbol type for any symbol, including local symbols.

The directive takes two parameters; the first parameter is the symbol name, and the second is the symbol type. The symbol type must be either function or object. An unrecognized type will cause a warning to be generated. Example of use:

func:
        ret
type func function
section .data
var dd 4
type var object

9.3.4. WEAK: Create weak symbol

ELF allows defining certain symbols as weak. Weak symbols are similar to global symbols, except during linking, weak symbols are only chosen after global and local symbols during symbol resolution. Unlike global symbols, multiple object files may declare the same weak symbol, and references to a symbol get resolved against a weak symbol only if no global or local symbols have the same name.

This functionality is primarily useful for libraries that want to provide common functions but not come into conflict with user programs. For example, libc has a syscall (function) called read. However, to implement a threaded process using POSIX threads in user-space, libpthread needs to supply a function also called read that provides a blocking interface to the programmer, but actually does non-blocking calls to the kernel. To allow an application to be linked to both libc and libpthread (to share common code), libc needs to have its version of the syscall with a non-weak name like _sys_read with a weak symbol called read. If an application is linked against libc only, the linker won’t find a non-weak symbol for read, so it will use the weak one. If the same application is linked against libc and libpthread, then the linker will link read calls to the symbol in libpthread, ignoring the weak one in libc, regardless of library link order. If libc used a non-weak name, which read function the program ended up with might depend on a variety of factors; a weak symbol is a way to tell the linker that a symbol is less important resolution-wise.

The WEAK directive takes a single parameter, the symbol name to declare weak. Example:

weakfunc:
strongfunc:
        ret
weak weakfunc
global strongfunc