Section 2.3. Executable Objects


2.3. Executable Objects

All processes originate as an executable file on disk. The process image defines what a process looks like when it is loaded in memory and ready for execution on a Solaris system. All processes begin life as programs, and programs are simply text files written in a computer programming language. The program is compiled and linked by the appropriate language-specific compiler. A successful compilation process results in the creation of an executable binary file on disk. This file becomes a process in the Solaris environment through invocation of the exec(2) system call, which is typically preceded by a fork(2) call. fork(2) creates a new process (a new proc_t), and exec(2) replaces the process image of the calling process with a new process image.

Once an executable object file is exec'd, the runtime linker, ld.so.1(1), is invoked to manage linking to other shared objects required for execution, typically a shared object library such as libc.so. This sequence of events is known as dynamic linking, whereby references in the program to shared object library functions (for example, printf(3), read(2)) are resolved at runtime by ld.so.1. It is possible to build statically linked executables through a compilation flag (-B static on the compile command line); this flag forces the inclusion of all referenced library functions in the executable object at build time. This technique requires that an archive version of the library be available (for example, libc.a for static linking and libc.so.1 for dynamic linking). However, as part of the merge of libthread into libc, archive libraries are no longer shipped in Solaris 10/usr/lib/ libc.a (among others) is no longer part of the distribution, so applications must dynamically link to system libraries.

A quick note on linkers is appropriate here before we continue. Two linkers are involved in the creation and execution of a process in Solaris: ld(1), which is commonly referred to as the link editor; and ld.so.1(1), which is the runtime linker. ld(1) is the link editor that executes as part of the compilation process. Specifically, it is called from the language-specific compiler (cc(1) for example, for compiling programs written in C) and is the last phase of the compilation process. ld(1) ultimately generates the executable file. Note that ld(1) can be executed as a standalone program for linking previously compiled object files to create an executable.

ld.so.1(1), the runtime linker, is invoked by the exec(2) system call when a new process image is loaded. The runtime linker takes over after exec(2), loads any required dependencies, and binds the associated objects together with the information generated by ld(1). The runtime linker can also be called upon by the application to load additional dependencies and to locate symbols.

Executable object files are generated in compliance with the industry-standard Executable and Linking Format (ELF). ELF is part of the System V application binary interface (ABI), which defines an operating system interface for compiled, executable programs. Since the ABI defines the binary interface for several implementations of UNIX System V across a variety of different hardware platforms, the ELF definition must be divided into two components: a platform-independent piece and a specification that is specific to a processor (for example, SPARC V8, SPARC V9, Intel 386, AMD64). Areas of the ABI that are processor specific include the definition of the function-calling sequence (system calls, stack management, etc.) and the operating system interface (signals, process initialization).

There are three different variations of ELF files: executable, relocatable, and shared object files. The type of ELF file generated depends on the options used during the compilation process. Relocatable files are generated by the compiler when the -c option is used (when the Sun Studio C compiler is used), and require further processing by the linker before executing (the -c option suppresses the running of the linker, ld(1)). Shared objects are created with the -G option and contain symbol information for the runtime linker, as well as executable code. Executable files are generated when the -G and -c flags are excluded from the compilation process, which includes running the link editor (ld(1)). Our focus for the remainder of this section is on the object file format, or ELF, as it applies to an executable file.

The ELF executable object file contains various sections, including an ELF header that provides specific information about the object file and a series of fields that describe the different components of the file. We use the elfdump(1) command to examine ELF object files.

sol10$  elfdump -e /bin/ls ELF Header   ei_magic:   { 0x7f, E, L, F }   ei_class:   ELFCLASS32          ei_data:      ELFDATA2MSB   e_machine:  EM_SPARC            e_version:    EV_CURRENT   e_type:     ET_EXEC   e_flags:                     0   e_entry:               0x10e08  e_ehsize:     52  e_shstrndx:    21   e_shoff:                0x66fc  e_shentsize:  40  e_shnum:       23   e_phoff:                  0x34  e_phentsize:  32  e_phnum:        6 


The example above displays the ELF header for the ls(1) command. The fields in the header tell us it is a 32-bit SPARC executable and provide information about the two major sections of the file: the section header and program header. The section header is defined by a section header table, or SHT, and locates linkable sections of the executable. A program header table, or PHT, defines the program segments of the object file, which are segments of executable code. The ELF header provides the offsets into the file for the SHT (e_shoff) and PHT (e_phoff), as well as their respective sizes and the number of entries. Additional elfdump(1) flags dump an object's SHT and PHT.

sol10$  elfdump -c /bin/ls . . . Section Header[9]:  sh_name: .text     sh_addr:      0x10e08         sh_flags:   [ SHF_ALLOC  SHF_EXECINSTR ]     sh_size:      0x3484          sh_type:    [ SHT_PROGBITS ]     sh_offset:    0xe08           sh_entsize: 0     sh_link:      0               sh_info:    0     sh_addralign: 0x8 Section Header[10]:  sh_name: .init     sh_addr:      0x1428c         sh_flags:   [ SHF_ALLOC  SHF_EXECINSTR ]     sh_size:      0xc             sh_type:    [ SHT_PROGBITS ]     sh_offset:    0x428c          sh_entsize: 0     sh_link:      0               sh_info:    0     sh_addralign: 0x4 . . . Section Header[17]:  sh_name: .data     sh_addr:      0x26370         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]     sh_size:      0x154           sh_type:    [ SHT_PROGBITS ]     sh_offset:    0x6370          sh_entsize: 0     sh_link:      0               sh_info:    0     sh_addralign: 0x8 . . . Section Header[19]:  sh_name: .bss     sh_addr:      0x26520         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]     sh_size:      0xbd0           sh_type:    [ SHT_NOBITS ]     sh_offset:    0x6520          sh_entsize: 0     sh_link:      0               sh_info:    0     sh_addralign: 0x8 


The section header listing for the ls(1) file is a partial listing, showing just a few of the sections with names that may sound familiarthe text section (.text), the initialization section (.init) and so on. The section header is a kind of road map used by exec(2) and the runtime linker to locate and load specific bits of the object file into memory for execution.

The runtime linker offers a wealth of features for understanding and debugging the linker operations and executable file shared object references. Using the LD_DEBUG environmental variable, the runtime linker reports symbol resolutions, search paths, files, bindings, etc. Try running:

sol10$ LD_DEBUG=help <my_exectuable> 


Setting LD_DEBUG to "help" causes the runtime linker to display all the options available for LD_DEBUG. Multiple options can be specified, separated by commas. Be aware that, depending on which options are specified and how many shared objects are linked to the executable, the LD_DEBUG flags can generate voluminous amounts of output (try LD_DEBUG=all). You can easily save the output to a file (highly recommended) with the following command.

sol10$ LD_DEBUG=all LD_DEBUG_OUTPUT=/var/tmp/ld.out <executable_file> 


The file name is the specified path and string, with the PID of the process appended to the end. For further information on ELF file formats and the use of the linker, refer to the Linker and Libraries Guide, available from http://docs.sun.com.




SolarisT Internals. Solaris 10 and OpenSolaris Kernel Architecture
Solaris Internals: Solaris 10 and OpenSolaris Kernel Architecture (2nd Edition)
ISBN: 0131482092
EAN: 2147483647
Year: 2004
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net