This chapter provides information about the compiler system and includes information about topics such as object file format and compiler options. Specifically, this chapter contains these sections:
"Object File Format and Dynamic Linking" discusses the major differences between the latest version of IRIX and previous versions.
"Source File Considerations" explains source file naming conventions and the procedure for including header files.
"Compiler Drivers" lists and explains the general compiler-driver options.
"Linking" explains how to manually link programs (using ld or a compiler driver) and how to compile multilanguage programs. It also describes Dynamic Shared Objects and how to link them into your programs.
"Debugging" explains the compiler-driver options for debugging.
"Getting Information About Object Files" explains how to use the object file tools to analyze object files.
"Using the Archiver to Create Libraries" explains how to use the archiver, ar.
For information about tools such as dis and size, see Chapter 4, "Using the Performance Tools." For information about optimizing your program, see Chapter 5, "Optimizing Program Performance."
A new object file format was adopted in IRIX version 5.0. The major differences between the current compiler system and pre-5.0 compiler systems are summarized below:
The compiler system uses "Executable and Linking Format" (ELF) for object files.
The compiler system uses shared libraries, called "Dynamic Shared Objects" (DSOs).
The compiler system creates "Position-Independent Code," (PIC) by default, to support dynamic linking.
Previous versions of IRIX used an extended version of the Common Object File Format (COFF) for object files. The current compiler system produces ELF object files instead. ELF is the format specified by the System V Release 4 Applications Binary Interface (the SVR4 ABI). In addition, ELF provides support for Dynamic Shared Objects, described below. Types of ELF object files include:
Relocatable files contain code and data in a format suitable for linking with other object files to make a shared object or executable.
Dynamic Shared Objects contain code and data suitable for dynamic linking. Relocatable files may be linked with DSOs to create a dynamic executable. At run time, the run-time linker combines the executable and DSOs to produce a process image.
Executable files are programs ready for execution. They may or may not be dynamically linked.
COFF executables continue to run on new releases of IRIX, but the current compiler system has no facility for creating or linking COFF executables. COFF and ELF object files may not be linked together. To take advantage of new IRIX features, you must recompile your code.
IRIX executes all binaries that are compliant with the SVR4 ABI, as specified in the System V Applications Binary Interface—Revised Edition and the System V ABI MIPS Processor Supplement. However, binaries compiled under this version of the compiler system are not guaranteed to comply with the SVR4 ABI. The MIPS-specific version of the SVR4 ABI is referred to as the MIPS ABI. Programs that comply with the MIPS ABI can be run on any machine that supports the MIPS ABI.
IRIX 5.0 introduced a new kind of shared object called a Dynamic Shared Object, or DSO. The object code of a DSO is position-independent code (PIC), which can be mapped into the virtual address space of several different processes at once. DSOs are loaded at run time instead of at linking time, by the run-time loader, rld. As is true for static shared libraries, the code for DSOs is not included in executable files; thus, executables built with DSOs are smaller than those built with non-shared libraries, and multiple programs may use the same DSO at the same time.
Static shared libraries are only supported under this release for the purposes of running old (COFF) binaries. The current compiler system has no facilities for generating static shared libraries.
You can find additional information about DSOs in Chapter 3, "Dynamic Shared Objects."
Dynamic linking requires that all object code used in the executable be position-independent code. For source files in high-level languages, you just need to recompile to produce PIC. Assembly language files must be modified to produce PIC; see Appendix A, "Position-Independent Coding in Assembly Language," for details.
Position-independent code satisfies references indirectly by using a global offset table (GOT), which allows code to be relocated simply by updating the GOT. Each executable and each DSO has its own GOT.
The compiler system now produces PIC by default when compiling higher-level language files. All of the standard libraries are now provided as DSOs, and therefore contain PIC code; if you compile a program into non-PIC, you will be unable to use those DSOs. One of the few reasons to compile non-PIC is to build a device driver, which doesn't rely on standard libraries; in this case, you should use the –non_shared option to the compiler driver to negate the default option, –KPIC. For convenience, the C library and math library are provided in non-shared format as well as in DSO format (although the non-shared versions are not installed by default). These libraries can be linked –non_shared with other non-PIC files.
When running position-independent code, the global pointer is used to point to the global offset table, so you can no longer use the –G option to store data in the global pointer region (that is, –KPIC, the default, implies –G 0). The compiler ignores any user-specified –G number other than zero. For more information about this option, see the ld(1) reference page.
You can find additional information about PIC in Appendix A, "Position-Independent Coding in Assembly Language."
This section describes conventions for naming source files and including header files. Topics covered include:
Each compiler driver recognizes the type of an input file by the suffix assigned to the file name. Table 2-1 describes the possible file name suffixes.
Table 2-1. Driver Input File Suffixes
Suffix | Description |
---|---|
.s | Assembly source |
.i | Preprocessed source code in the language of the processing driver |
.c | C source |
.C, .cxx, .cc, .c++ | C++ source |
.f, .F, .for. .FOR | Fortran 77 source |
.p | Pascal source |
.u | Ucode object file |
.b | Ucode object library |
.o | Object file |
.a | Object library |
.so | Dynamic shared object library |
The following example compiles preprocessed source code:
f77 -c tickle.i |
The Fortran compiler, f77, assumes the file tickle.i contains Fortran statements (because the Fortran driver is specified). f77 also assumes the file has already been preprocessed (because the suffix is .i), and therefore does not invoke the preprocessor.
Header files, also called include files, contain information about the libraries they're associated with. They define such things as data structures, symbolic constants, and prototypes and parameters for the functions in the library.
For example, the stdio.h header file describes, among other things, the data types of the parameters required by printf(). To use those definitions without having to type them into each of your source files, you can use the #include command to tell the macro preprocessor to include the complete text of the given header file in the current source file. Including header files in your source files allows you to specify such definitions conveniently and consistently in each source file that uses any of the library routines.
By convention, header file names have a .h suffix. Each programming language handles these files the same way, via the macro preprocessor.
The #include command tells the preprocessor to replace the #include line with the text of the indicated header file. The usual way to specify a header file is with the line:
#include <filename> |
where filename is the name of the header file to be included. The angle brackets (< >) surrounding the file name tell the macro preprocessor to search for the specified file only in directories specified by command-line options and in the default header-file directory (/usr/include).
Another specification format exists, in which the file name is given between double quotation marks:
#include "filename" |
In this case, the macro preprocessor searches for the specified header file in the current directory first, then (if it doesn't find the requested file) goes on and searches in the other directories as in the angle-bracket specification.
![]() | Note: When you specify header files in your source files, the #include keyword should always start in column 1 (that is, the left-most column) to be recognized by the preprocessor. |
A single header file can contain definitions for multiple languages; this setup allows you to use the same header file for all programs that use a given library, no matter what language those programs are in.
To set up a shareable header file, create a .h file and enter the definitions for the various languages as follows:
#ifdef _LANGUAGE_C C definitions #endif #ifdef _LANGUAGE_C_PLUS_PLUS C++ definitions #endif #ifdef _LANGUAGE_FORTRAN Fortran definitions #endif and so on for other language definitions |
You can specify the various language definitions in any order, but you must specify _LANGUAGE_ before the language name.
The driver commands, such as cc, f77, and pc, call subsystems that compile, optimize, assemble, and link your programs. This section describes:
At compilation time, you can select one or more options that affect a variety of program development functions, including debugging, optimization, and profiling facilities. You can also specify the names assigned to output files. However, some options have default values that apply if you do not specify the option.
When you invoke a compiler driver with source files as arguments, the driver calls other commands that compile your source code into object code. It then optimizes the object code (if requested to do so) and links together the object files, the default libraries, and any other libraries you specify.
Given a source file foo.c, the default name for the object file is foo.o. The default name for an executable file is a.out. So the following example compiles source files foo.c and bar.c with the default options:
cc foo.c bar.c |
This example produces two object files (foo.o and bar.o), then links those together with the default C library libc to produce an executable called a.out.
![]() | Note: If you compile a single source directly to an executable, the compiler does not create an object file. |
The command-line options for IRIS-4D compiler drivers are listed and explained in Table 2-2. The table lists only the most frequently used options; for a list of all available options, refer to the appropriate compiler reference page. Note that not all of the options work with every driver.
You can use the compiler system to generate profiled programs that, when executed, provide operational statistics. To perform this procedure, use the –p compiler option (for pc sampling information) and the pixie program (for profiles of basic block counts). Refer to Chapter 4, "Using the Performance Tools," for details on prof and pixie.
In addition to the general options in Table 2-2, each driver has options that you typically won't use. These options primarily aid compiler development work. For information about nonstandard driver options, consult the appropriate driver reference page.
Table 2-2. General Driver Options
![]() | Note: To use 4.3 BSD extensions in C, compile using
–xansi or by using the
–D__EXTENSIONS__ option on the command line. For example: cc prog.c -ansi -prototypes -fullwarn -lm -D__EXTENSIONS__ |
The linker, ld, combines one or more object files and libraries (in the order specified) into one executable file, performing relocation, external symbol resolutions, and all other required processing. Unless directed otherwise, the linker names the executable file a.out.
This section summarizes the functions of the linker. Also described here are how to link a program manually (without using a compiler driver) and how to compile multilanguage programs. Refer to the ld(1) reference page for complete information on the linker.
Specifically, this section explains:
Usually the linker is invoked by the compiler driver as the final step in compilation (as explained in "Compiler Drivers"). If you have object files produced by previous compilations that you want to link together, you can invoke the linker using a compiler driver instead of calling ld directly; just pass the object-file names to the compiler driver in place of source-file names. If the original source files were in a single language, simply invoke the associated driver and specify the list of object files. (For information about linking together objects derived from several languages, see "Linking Multilanguage Programs.")
A few command-line options to ld, such as –p, have different meanings when used as command-line options to cc. To pass such options to ld through an invocation of a compiler driver, use the –Wl option to the driver (see the reference page for details).
Typically, the compiler driver invokes ld as necessary. Circumstances exist under which you may need to invoke ld directly, such as when you're building a shared object or doing special linking not supported by compiler drivers (such as building an embedded system). To build C++ shared objects, use the CC driver.
A summary of ld syntax follows.
ld options object1 [object2...objectn] |
options | One or more of the options listed in Table 2-3. | |
object | Specifies the name of the object file to be linked. |
Table 2-3 contains only a partial list of linker options. Many options that apply only to creating shared objects are discussed in the next chapter. For complete information on options and libraries that affect linker processing, refer to the ld(1) reference page.
Option | Purpose |
---|---|
–kllibname | Similar to –llibname, but the library is a ucode library named liblibname.b. |
–llibname | Specifies the name of a library, where libname is the library name. The linker searches for a liblibname.so (and then liblibname.a) first in any directories specified by –Ldirname options, and then in the standard directories: /lib, /usr/lib, and / usr/local/lib. |
–Ldirname | Adds dirname to the list of directories to be searched for along with libraries specified by subsequent –llibname options. |
–m | Produces a linker memory map, listing input and output sections of the code, in System V format. |
–M | Produces a link map in BSD format, listing the names of files to be loaded. |
–nostdlib | This option must be accompanied by the –Ldirname option. If the linker does not find the library in dirname, then it does not search any of the standard library directories. |
–ofilename | Specifies a name for your executable. If you do not specify filename, the linker names the executable a.out. |
–s | Strips symbol table information from the program object, reducing its size. This option is useful for linking routines that are frequently linked into other program objects. |
–v | Prints the name of each file as it is processed by the linker. |
–Xsortbss | Sorts bss symbols (this is the default in C but not in Fortran). |
–Xnobsschange | Overrides defaults, eliminating all global bss reordering. |
–ysymname | Reports all references to, and definitions of, the symbol symname. Useful for locating references to undefined symbols. |
The following command tells the linker to search for the DSO libcurses.so in the directory /lib. If it does not find that DSO, the linker then looks for libcurses.a in /lib; then for libcurses.so in /usr/lib, then in the same directory for libcurses.a. If it hasn't found an appropriate library by then, it looks in /usr/local/lib for libcurses.a. (Note that the linker does not look for DSOs in /usr/local/lib, so don't put shared objects there.) If found in any of those places, the DSO or library is linked with the objects foiled.o and again.o:
ld foiled.o again.o -lcurses |
![]() | Note: The –G option, which formerly allowed you to specify which data items should be stored in the global pointer region, is no longer useful. –KPIC, the default, implies –G 0, and the compiler ignores any user attempts to specify otherwise. Compiling –non_shared (to avoid –KPIC) is primarily useful only for creating device drivers, in which case there is no direct linking step in which to specify a –G number. For more information, see the cc and ld reference pages. |
The assembler driver as1 does not run the linker. To link a program written in assembly language, use one of these procedures:
The linker ld processes its arguments from left to right as they appear on the command line. Arguments to ld can be DSOs, object files, or libraries.
When ld reads a DSO, it adds all the symbols from that DSO to a cumulative symbol table. If it encounters a symbol that's already in the symbol table, it does not change the symbol table entry. If you define the same symbol in more than one DSO, only the first definition is used.
When ld reads an archive, usually denoted by a file name ending in .a, it uses only the object files from that archive that can resolve currently unresolved symbol references. (When a symbol is referred to but not defined in any of the object files that have been loaded so far, it's called unresolved.) Once a library has been searched in this way, it is never searched again. Therefore, libraries should come after object files on the command line in order to resolve as many references as possible. Note that if a symbol is already in the cumulative symbol table from having been encountered in a DSO, its definition in any subsequent library is ignored.
You can specify libraries and DSOs either by explicitly stating a pathname or by use of the library search rules. To specify a library or DSO by path, simply include that path on the command line (relative to the current directory, or else absolute):
ld myprog.o /usr/lib/libc.so.1 mylib.so |
![]() | Note: libc.so.1 is the name of the standard C DSO, replacing the older libc.a. Similarly, libX11.so.1 is the X11 DSO. Most other DSOs are simply named name.so, without a .1 extension. |
To use the linker's library search rules, specify the library with the –llibname option:
ld myprog.o -lmylib |
When the –lmylib argument is processed, ld searches for a file called libmylib.so. If it can't find libmylib.so in a given directory, it tries to find libmylib.a there; if it can't find that either, it moves on to the next directory in its search order. The default search order is to look first in /lib, then in /usr/lib. After looking in both of those directories, ld looks in /usr/local/lib for archives only (DSOs should not be installed in /usr/local/lib). You can modify these defaults by specifying the –Ldir and/or –nostdlib options. Directories specified by –Ldir before the –llibname argument are searched in the order they appear on the command line, before the default directories are searched. If –nostdlib is specified, then –Ldir must also be specified because the default directories aren't searched at all.
If ld is invoked from one of the compiler drivers, all –L and –nostdlib options are moved up on the command line so that they appear before any –llibname option. For example:
cc file1.o -lm -L mydir |
This command invokes, at the linking stage of compilation:
ld -L mydir file1.o -lm |
![]() | Note: There are three different kinds of files that contain object code files: non-shared libraries, PIC archives, and DSOs. Non-shared libraries are the old-fashioned kind of library, built using ar from .o files that were compiled with –non_shared. These archives must also be linked –non_shared. PIC archives are the default in IRIX 5.0, built using ar from .o files compiled with –KPIC (a default option); they can be linked with other PIC files. DSOs are built from PIC .o files by using ld –shared; see Chapter 3 for details. |
When compiling multilanguage programs, be sure to specify any required run-time libraries using the –llibname option. For a list of the libraries that a language uses, see the corresponding compiler driver reference page.
If the linker tells you that a reference to a certain function is unresolved, check that function's reference page to find out which library the function is in. If it isn't in one of the standard libraries (which ld links in by default), you may need to specify the appropriate library on the command line. For an alternative method of finding out where a function is defined, see "Finding a Symbol in an Unknown Library."
![]() | Note: Simply including the header file associated with a library routine is not enough; you also must specify the library itself when linking (unless it's a standard library). There is no magical connection between header files and libraries; header files only give prototypes for library routines, not the library code itself. |
This section describes how to link your source files with previously built DSOs; for more information about how to build your own DSOs, see Chapter 3, "Dynamic Shared Objects."
To build an executable that uses a DSO, call a compiler driver just as you would for a non-shared library. For instance,
cc needle.c -lthread |
links the resulting object file (needle.o) with the previously built DSO libthread.so (and the standard C DSO, libc.so.1), if available. If no libthread.so exists, but a PIC archive named libthread.a exists, that archive is used with libc.so.1, and you still get dynamic (run-time) linking. Note that even .a libraries now contain position-independent code by default, though it is also possible to build non-shared .a libraries that do not contain PIC.
When the source language of the main program differs from that of a subprogram, use the following steps to link (refer to Figure 2-1):
Compile object files from the source files of each language separately by using the –c option.
For example, if the source consists of a Fortran main program (main.f) and two files of C functions (more.c and rest.c), use the commands:
cc -c more.c rest.cf77 -c main.f |
These commands produce the object files main.o, more.o, and rest.o.
Use the driver associated with the language of the main program to link the objects together:
f77 main.o more.o rest.o |
The compiler drivers supply the default set of libraries necessary to produce an executable from the source of the associated language. However, when producing executables from source code in several languages, you may need to explicitly specify the default libraries for one or more of the languages used. For instructions on specifying libraries, see "Linking Libraries."
For specific details about compiling multilanguage programs, refer to the programming guides for the appropriate languages.
You can use ld to locate unresolved symbols. For example, suppose you're compiling a program, and ld tells you that you're using an unresolved symbol. However, you don't know where the unresolved symbol is referenced.
To find the unresolved symbol, enter:
ld -ysymbol file1... filen |
The output lists the source file that references symbol.
The compiler system provides a debugging tool, dbx, which is explained in the dbx User's Guide. In addition, CASEVision/WorkShop™ contains debugging tools. For information about obtaining WorkShop for your computer, contact your dealer or sales representative.
Before using a debugging tool, you must use one of the standard driver options, listed in Table 2-4, to produce executables containing information that the debugger can use.
Table 2-4. Driver Options for Debugging
Option | Purpose |
---|---|
–g0 | Produces a program object with a minimum of source-level debugging information. This is the default. Reduces the size of the program object but allows optimizations. Use this option with the –O option after you finish debugging. |
–g or –g2 | Produces additional debugging information for full symbolic debugging. This option overrides the optimization options ( –Onum). |
–g3 | Produces additional debugging information for full symbolic debugging of fully optimized code. This option makes the debugger less accurate. You can use –g3 with an optimization option ( –Onum). |
The following tools provide information on object files:
elfdump lists the contents (including the symbol table and header information) of an ELF-format object file.
file provides descriptive information on the general properties of the specified file.
size prints the size of each section of an object file (some such sections are named text, data, and sbss).
strip removes symbol table and relocation bits from an object file.
Note that you can trace system call and scheduling activity by using the par command. For more information, see the par(1) reference page.
The dis tool disassembles object files into machine instructions. You can disassemble an object, archive library, or executable file.
The syntax for dis is:
dis options filename1 [filename2... filenamen] |
options One or more of the options listed in Table 2-5.
filename | Specifies the name of one or more files to disassemble. |
Table 2-5 lists dis options. For more information, see the dis(1) reference page.
Option | Description |
---|---|
–bbegin_address | Starts disassembly at begin_address. You can specify the address as decimal, octal (with a leading 0), or hexadecimal (with a leading 0x). |
–dsection | Disassembles the named section as data, and prints the offset of the data from the beginning of the section. |
–Dsection | Disassembles the named section as data, and prints the address of the data. |
–eend_address | Stops disassembly at end_address. You can specify the address as decimal, octal (with a leading 0), or hexadecimal (with a leading 0x). |
–Ffunction | Disassembles the named function in each object file you specify on the command line. |
–h | Substitutes the hardware register names for the software register names in the output. |
–H | Removes the leading source line, and leaves the hex value and the instructions. |
–i | Removes the leading source line and hexadecimal value of disassembly, and leaves only the instructions. |
–Idirectory | Uses directory to help locate source code. |
–lstring | Disassembles the archive file specified by string. |
–L | Looks up source labels for subsequent printing. |
–o | Prints numbers in octal. The default is hexadecimal. |
–s | Performs symbolic disassembly where possible. Prints (using C syntax) symbol names on the line following the instruction. Displays source code mixed with assembly code |
–tsection | Disassembles the named section as text. |
–T | Specifies the trace flag for debugging the disassembler. |
–V | Prints (on stderr) the version number of the disassembler being executed. |
–w | Prints source code to the right of assembly code (produces wide output). Use this option with the –s option. |
–x | Prints offsets in hexadecimal (the default). |
The elfdump tool lists headers, tables, and other selected parts of an ELF-format object file or archive file.
The syntax for elfdump is:
elfdump options filename1 [filename2... filenamen] |
options | One or more of the options listed in Table 2-6. | |
filename | Specifies the name of one or more object files whose contents are to be dumped. |
Table 2-6 lists elfdump options. For more information, see the elfdump(1) reference page.
Option | Dumps |
---|---|
–c | String table information |
–cr | Compact relocation information. |
–Dc | Conflict list (.conflict) in Dynamic Shared Objects. |
–Dg | Global Offset Table (.got) in Dynamic Shared Objects. |
–Dinfo | The .MIPS.dclass section. |
–Dinst | The .MIPS.dinst section. |
–Dl | Library list (.liblist) in Dynamic Shared Objects. |
–Dmsym | The Msym table. |
–dsym | The .MIPS.dsym section. |
–Dsymlib | The library that resolves the symbols in the dynsym section. |
–Dt | String table entries (.dynsym) of the dynamic symbol table in Dynamic Shared Objects. |
–f | The ELF file header. |
–h | All section headers in the file. |
–hash | Hash table (.hash) entries. |
–info | Library information (for example, QuickStart enabled). |
–L | Dynamic section (.dynamic) in Dynamic Shared Objects. |
–o | Optional program header. |
–r | Relocation information. |
–reg | Register information (.reginfo) section. |
–rpt | Runtime procedure table. |
–t | Symbol table (.symtab) entries.
|
The file tool lists the properties of program source, text, object, and other files. This tool attempts to identify the contents of files using various heuristics. It is not exact and is occasionally fooled. For example, it often erroneously recognizes command files as C programs. For more information, see the file(1) reference page.
The syntax for file is:
file filename1 [filename2... filenamen] |
Each filename is the name of a file to be examined.
Information given by file is self-explanatory for most kinds of files. However, using file on object files and executables gives somewhat cryptic output.
file test.o a.out /lib/libc.so.1test.o: ELF 32-bit MSB relocatable MIPS - version 1 a.out: ELF 32-bit MSB dynamic executable (not stripped) MIPS - version 1 /lib/libc.so.1: ELF 32-bit MSB dynamic lib MIPS - version 1 |
In this example, MSB indicates Most Significant Byte, also called Big-Endian; dynamic executable indicates the executable was linked with DSO libraries; and (not stripped) indicates the executable contains at least some symbol table information. Dynamic lib indicates a DSO.
The nm tool lists symbol table information for object files and archive files.
The syntax for nm is:
nm options filename1 [filename2... filenamen] |
options | One or more of the options listed in Table 2-7. | |
filename | Specifies the object files or archive files from which symbol table information is to be extracted. If you do not specify a file name, nm assumes the file is called a.out. |
Table 2-7 lists symbol table dump options. For more information, see the nm(1) reference page.
Table 2-7. Symbol Table Dump Options
Option | Purpose |
---|---|
–a | Prints debugging information. If used with –B, uses BSD ordering with System V formatting. |
–A | Prints the listing in System V format (default). |
–b | Prints the value field in octal. |
–B | Prints the listing in BSD format. |
–d | Prints the value field in decimal (the default for System V output). |
–e | Prints only external and static variables. |
–h | Suppresses printing of headers. |
–n | Sorts external symbols by name for System V format. Sorts all symbols by value for Berkeley format (by name is the BSD default output). |
–o | Prints value field in octal (System V output). Prints the file name immediately before each symbol name (BSD output). |
–p | Lists symbols in the order they appear in the symbol table. |
–r | Reverses the sort that you specified for external symbols with the –n and –v options. |
–T | Truncates characters in exceedingly long symbol names; inserts an asterisk as the last character of the truncated name. This option may make the listing easier to read. |
–u | Prints only undefined symbols. |
–v | Sorts external symbols by value (default for Berkeley format). |
–V | Prints the version number of nm. |
–x | Prints the value field in hexadecimal. |
Table 2-8 defines the one-character codes shown in an nm listing. Refer to the example that follows the table for a sample listing.
Table 2-8. Character Code Meanings
Key | Description |
---|---|
a | Local absolute data |
A | External absolute data |
b | Local zeroed data |
B | External zeroed data |
C | Common data |
d | Local initialized data |
D | External initialized data |
E | Small common data |
G | External small initialized data |
N | Nil storage class (avoids loading of unused external references) |
r | Local read-only data |
R | External read-only data |
s | Local small zeroed data |
S | External small zeroed data |
t | Local text |
T | External text |
U | External undefined data |
V | External small undefined data |
This example demonstrates how to obtain a symbol table listing. Consider the following program, tnm.c:
#include <stdio.h> #include <math.h> #define LIMIT 12 int unused_item = 14; double mydata[LIMIT]; main() { int i; for(i = 0; i < LIMIT; i++) { mydata[i] = sqrt((double)i); } return 0; } |
Compile the program into an object file by entering:
cc -c tnm.c |
To obtain symbol table information for the object file tnm.o in BSD format, use the nm –B command:
nm -B tnm.o |
0000000000 T main 0000000000 B mydata 0000000000 U sqrt 0000000000 D unused_item 00000000 N _bufendtab |
To obtain symbol table information for the object file tnm.o in System V format use the nm command without any options:
nm tnm.o Symbols from tnm.o: [Index] Value Size Class Type Section Name [0] | 0| |File |ref=4 |Text | tnm.c [1] | 0| |Proc |end=3 int |Text | main [2] | 116| |End |ref=1 |Text | main [3] | 0| |End |ref=0 |Text | tnm.c [4] | 0| |File |ref=6 |Text | /usr/include/math.h [5] | 0| |End |ref=4 |Text | /usr/include/math.h [6] | 0| |Global | |Data | unused_item [7] | 0| |Global | |Bss | mydata [8] | 0| |Proc |ref=1 |Text | main [9] | 0| |Proc | |Undefined| sqrt [10] | 0| |Global | |Undefined| _gp_disp |
When ld indicates that a symbol is undefined, you can use nm to figure out which DSO or library needs to be linked in by piping nm's output through appropriate greps.
For example, you're compiling a program, and ld tells you that you're using an undefined symbol:
cc prog.c -lgl ld: Unresolved: XGetPixel |
However, you don't know where XGetPixel is defined. Use nm to list the symbol tables for all of the available DSOs, and filter that output to find only the places where XGetPixel is mentioned. Then filter the result to find the places where XGetPixel is defined, as indicated by the T character code.
nm -Bo /usr/lib/lib*.so* | grep XGetPixel | grep T/usr/lib/libX11.so.1: 0f790ff8 T XGetPixel |
Some DSOs end in .so, while others end in .so.1, so we need to use multiple wildcards to get all of them. Also, this command line has to be modified to look in PIC archives or non-shared libraries; as written it only looks in DSOs.Now that XGetPixel is defined in /usr/lib/libX11.so.1, the X11 DSO; use the –l option to tell cc to link in that library, and ld won't complain again.
cc prog.c -lgl -lX11 |
The odump tool lists headers, tables, and other selected parts of a COFF-format object or archive file. It is provided with this release of IRIX for compatibility; use elfdump for ELF-format files.
The syntax for odump is:
odump options filename1 [filename2... filenamen] |
options | One or more of the options listed in Table 2-9. | |
filename | Specifies the name of one or more object files whose contents are to be dumped. |
Table 2-9 lists odump options. For more information, see the odump(1) reference page.
Option | Dumps |
---|---|
–a | Archive header of each object file in the specified archive library file. |
–c | String table. |
–dnumber | The section numbered number, or a range of sections starting with number and ending with the last section number available (or the number you specify with the +d auxiliary option). |
+dnumber | All sections starting with the first section (or with the section specified with the –d option) and ending with the section numbered number. |
–f | File header for each object file in the specified file. |
–F | File descriptor table for each object file in the specified file. |
–g | Global symbols in the symbol table of an archive library file. |
–h | Section headers. |
–i | Symbolic information header. |
–l | Line number information. |
–nname | Information for section named name only. Use this option with the –h, –s, –r, –l, or –t option. |
–o | Optional header for each object file. |
–p | Suppresses the printing of headers. |
–P | Procedure descriptor table. |
–r | Relocation information. |
–R | Relative file index table. |
–s | Section contents. |
–t | Symbol table entries. |
–tindex | Only the indexed symbol table entry. Use the +t option with the –t option to specify a range of table entries. |
+tindex | Symbol table entries in a range that ends with the indexed entry. The range begins with the first symbol table entry or with the section that you specify with the –t option. |
–v | Information in symbolic rather than numeric representation. This option may be used with any odump option except –s. |
–zname, number | Line number entry (or a range of entries starting at the specified number) for the named function. |
+znumber | Line number entries starting with the function name or line number specified by the –z option and ending with number. |
The size tool prints information about the sections (such as text, rdata, and sbss) of the specified object or archive files. The a.out(4) reference page describes the format of these sections.
The syntax for size is:
size options [filename1 filename2... filenamen] |
options | Specifies the format of the listing (see Table 2-10). | |
filename | Specifies the object or archive files whose properties are to be listed. If you do not specify a file name, the default is a.out. |
Table 2-10 lists size options. For more information, see the size(1) reference page.
Option | Action |
---|---|
–A | Prints data section headers in System V format. |
–B | Prints data section headers in Berkeley format. |
–d | Prints sizes in decimal (default). |
–F | Prints data on loadable segments. |
–n | Prints symbol table, global pointer, and more. |
–o | Prints sizes in octal. |
–s | Follows shared libraries, adding them as they're encountered to the list of files to be sized. |
–V | Prints the version of size that you are using.
|
–x | Prints sizes in hexadecimal. |
The strip tool removes symbol table and relocation bits that are attached to the assembler and loader. Use strip to save space after you debug a program. The effect of strip is the same as that of using the -s option to ld.
The syntax for strip is:
strip options filename1 [filename2... filenamen] |
options | One or more of the options listed in Table 2-11. | |
filename | Specifies the name of one or more object files whose contents are to be stripped. |
Table 2-11 lists strip options. For more information, see the strip(1) reference page.
Option | Description |
---|---|
–l | Strips line number information, and keeps the symbol table and debugging information. |
–ofilename | Puts the stripped information in the filename that you specify. |
–V | Prints the version number of strip. |
–x | Keeps symbol table information, but may strip debugging and line number information. |
An archive library is a file that includes the contents of one or more object (.o) files. When the linker (ld) searches for a symbol in an archive library, it loads only the code from the object file where that symbol was defined (not the entire library) and links it with the calling program.
The archiver (ar) creates and maintains archive libraries and has the following main functions:
Copying new objects into the library
Replacing existing objects in the library
Moving objects around within the library
Extracting individual objects from the library
The following section explains the syntax of the ar command and lists some examples of how to use it. See the ar(1) reference page for details.
![]() | Note: ar simply strings together whatever object files you tell it to archive; thus, it can be used to build either non-shared or PIC libraries, depending on how the included .o files were built in the first place. If you do create a non-shared library with ar, remember to link it –non_shared with your other code. For information about building DSOs and converting libraries to DSOs, see Chapter 3. |
The syntax for ar is:
ar options [posObject] libName [object1... objectn] |
options | Specifies the action that the archiver is to take. Table 2-12, Table 2-13, and Table 2-14 list the available options. To specify more than one option, don't use a dash or put spaces between the options. For example, use ar ts, not ar –t –s. | |
posObject | Specifies the name of an object within an archive library. It specifies the relative placement (either before or after posObject) of an object that is to be copied into the library or moved within the library. This parameter is required when the a, b, or i suboptions are specified with the m or r option. The last example in "ar Examples," shows the use of a posObject parameter. | |
libName | Specifies the name of the archive library you are creating, updating, or extracting information from. | |
object | Specifies the name(s) of the object file(s) to manipulate. |
When running the archiver, specify exactly one of the options d, m, p, q, r, t, or x (listed in Table 2-12). In addition, you can optionally specify any of the modifiers in Table 2-13, as well as any of the archiver suboptions listed in Table 2-14.
Option | Purpose |
---|---|
d | Deletes the specified objects from the archive. |
m | Moves the specified files to the end of the archive. If you want to move the object to a specific position in the archive library, specify an a, b, or i suboption together with a posObject parameter. |
p | Prints the specified objects in the archive on the standard output device (usually the terminal screen). |
q | Adds the specified object files to the end of the archive. This option is similar to the r option (described below), but is faster and does not remove any older versions of the object files that may already be in the archive. Use the q option when creating a new library. |
r | Adds the specified object files to the end of the archive file. If an object file with the same name already exists in the archive, the new object file overwrites it. If you want to add an object at a specific position in the archive library, specify an a, b, or i suboption together with a posObject parameter. Use the r option when updating existing libraries. |
t | Prints a table of contents on the standard output (usually the screen) for the specified object or archive file. |
x | Copies the specified objects from the archive and places them in the current directory. Duplicate files are overwritten. The last modified date is the current date (unless you specify the o suboption, in which case the date stamp on the archive file is the last modified date). If no objects are specified, x copies all the library objects into the current directory. |
Table 2-13. Archiver Modifiers
Option | Purpose |
---|---|
c | Suppresses the warning message that the archiver issues when it discovers that the archive you specified does not already exist. |
C | Makes an archive compatible with pre-SVR4 IRIX. |
E | The default; creates an archive matching the specifications given by the SVR4 ABI. |
l | Puts the archiver's temporary files in the current working directory. Ordinarily, the archiver puts those files in /tmp (unless the STMDIR environment variable is set, in which case ar stores temporary files in the directory indicated by that variable). This option is useful when /tmp (or STMDIR) is full. |
s | Creates a symbol table in the archive. This modifier is rarely necessary since the archiver updates the symbol table of the archive library automatically. Optionsm, p, q, and r, in particular, create a symbol table by default and thus do not require s to be specified. |
v | Lists descriptive information during the process of creating or modifying the archive. When specified with the t option, produces a verbose table of contents. |
Table 2-14. Archiver Suboptions
Suboption | Use with Option | Purpose |
---|---|---|
a | m or r | Specifies that the object file being added should follow the already-archived object file specified by the posObject parameter on the command line. |
b | m or r | Specifies that the object file precede the object file specified by the posObject parameter. |
i | m or r | Same as b. |
o | x | Forces the last modified date of the extracted object file to match that of the archive file. |
u | r | Tells the archiver not to replace the existing object file in the archive if the last modified date indicates that the object file already in the archive is newer (more recently modified) than the one you're adding. |
![]() | Note: The a and b suboptions are only useful if the same symbol is defined in two or more of the object files in the archive (in which case, the symbol table shows the first definition listed in the archive). Under other circumstances, order of object files in an archive is irrelevant (and the a and b suboptions are useless), since ld uses the archive symbol table rather than searching linearly through the file. |
Create a new library, libtest.a, and add object files to it by entering:
ar cq libtest.a mcount.o mon1.o string.o |
The c option suppresses an archiver message during the creation process. The q option creates the library and puts mcount.o, mon1.o, and string.o into it.
An example of replacing an object file in an existing library:
ar r libtest.a mon1.o |
The r option replaces mon1.o in the library libtest.a. If mon1.o does not already exist in the library libtest.a, it is added.
![]() | Note: If you specify the same file twice in an argument list of files to be added to an archive, that file appears twice in the archive. |
To add a new file immediately before mcount.o in this library, enter:
ar rb mcount.o libtest.a new.o |
The r option adds new.o to the library libtest.a. The b option followed by mcount.o as the posObject causes the archiver to place new.o immediately before mcount.o in the archive.