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.
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: chapter.xml 1999 2007-09-22 04:00:46Z peter $"]
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
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 7.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
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