Chapter 2. Using the Compiler System

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:

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."

Object File Format and Dynamic Linking

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:

Executable and Linking Format

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.

Dynamic Shared Objects

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."

Position-Independent Code

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."

Source File Considerations

This section describes conventions for naming source files and including header files. Topics covered include:

Source File Naming Conventions

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

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.


Note: Do not put any code other than definitions in an include file, particularly if you intend to debug your program using dbx. The debugger recognizes an include file as only one line of source code, so source lines in an include file do not appear during debugging sessions.


Specifying a Header File

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.


Creating a Header File for Multiple Languages

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


Note: To indicate C++ definitions you must use _LANGUAGE_C_PLUS_PLUS, not _LANGUAGE_C++.

You can specify the various language definitions in any order, but you must specify _LANGUAGE_ before the language name.

Compiler Drivers

The driver commands, such as cc, f77, and pc, call subsystems that compile, optimize, assemble, and link your programs. This section describes:

Default Behavior for Compiler Drivers

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.


General Options for Compiler Drivers

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

Option

Purpose

–ansi

Strict ANSI/ISO C compilation mode. Preprocessing adds only standard predefined symbols to the name space, and standard include files declare only standard symbols.

–c

Prevents the linker from linking your program after assembly code generation. This option forces the driver to produce a .o file after the assembler phase, and prevents the driver from producing an executable file.

–C

(C driver only) Used with the –P or –E option. Prevents the macro preprocessor from stripping comments. Use this option when you suspect the preprocessor is not producing the intended code and you want to examine the code with its comments. Note that –C is an option to cfe; this option is passed along to cfe if you specify it with cc.

–C

(Pascal and Fortran drivers only) Generates code that invokes range checking for subscripts during program execution.

–cord

Runs the procedure rearranger, cord(1) on the resulting file after linking. Rearranging improves the paging and caching performance of the program's text. The output of cord is placed in a.out, by default, or a file specified by the –o option. If you don't specify –feedback, then outfile.fb is used as the default.

–cckr

K&R/Version7 C compatibility compilation mode. Preprocessing may add more predefined symbols to the name space than in –ansi mode. Compilation adheres to the K&R language semantics.

–Dname[ =def]

Defines a macro name as if you had specified a #define in your program. If you do not specify a definition with =def, name is set to 1.

–E

(C driver only) Runs only the macro preprocessor and sends results to the standard output. To retain comments, use the –C option as well. Use –E when you suspect the preprocessor is not producing the intended code.

–feedback

Use with the –cord option to specify feedback file(s). You can produce this file by using prof with its –feedback option from an execution of the instrumented program produced by pixie(1). Specify multiple feedback files with multiple –feedback options.

–g[ num]

Produces debugging information. The default is –g0: do not produce debugging information.

–Idirname

Adds dirname to the list of directories to be searched for specified header files. These directories are always searched before the default directory, /usr/include.

–KPIC

Generates position-independent code. This is the default and is required for programs linking with dynamic shared objects. Specify –non_shared if you don't want to generate PIC code.

–mips1

Generates code using the instruction set of the MIPS R2000/ R3000 RISC architecture. This is the default.

–mips2

Generates code using the MIPS II instruction set (MIPS I + R4000 specific extensions). Note that code compiled with – mips2 does not run on R2000/R3000 based machines.

–nocpp

Suppresses running of the macro preprocessor on the source files prior to processing.

–non_shared

Turns off the default option, –KPIC, to produce non-shared code. This code can be linked to only a few standard libraries (such as libc.a and libm.a) that are provided in non-shared format, in the directory /usr/lib/nonshared. You should use this option only when building device drivers.

–nostdinc

Suppresses searching of /usr/include for the specified header files.

–ofilename

Names the result of the compilation filename. If an executable is being generated, it is named filename rather than the default name, a.out. If a single source file is compiled with –c, the object is named filename (not, it should be noted, filename.o; if you want the object file name to end with .o, you should specify that in the argument to –o). Otherwise, this option is ignored.

–P

Runs only the macro preprocessor on the files and puts the result of each file in a .i file. Specify both –P and –C to retain comments.

–S

Similar to –c, except that it produces assembly code in a .s file instead of object code in a .o file.

–Uname

Overrides a definition of the macro name that you specified with the –D option, or that is defined automatically by the driver. Note that this option does not override a macro definition in a source file, only on the command line.

–v

Lists compiler phases as they are executed. Use this option to see the default options for each compiler phase along with the options you've specified.

–w

Suppresses warning messages.

–xansi

Compilation follows an extended ANSI/ISO C language semantics, which is more lenient in terms of the forms of expressions it allows. Preprocessing combines predefined macros. This is the default C compilation mode.



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__


Linking

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:

Invoking the Linker Manually

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.

Linker Syntax

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.

Table 2-3. Linker Options

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.


Linker Example

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.


Linking Assembly Language Programs

The assembler driver as1 does not run the linker. To link a program written in assembly language, use one of these procedures:

  • Assemble and link using one of the other driver commands (cc, for example). The .s suffix of the assembly language source file causes the driver to invoke the assembler.

  • Assemble the file using as; then link the resulting object file with the ld command.

Linking Libraries

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.

Specifying Libraries and DSOs

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.


Examples of Linking DSOs

To link a sample program foo.c with the math DSO, libm.so, enter:

cc foo.c -lm

To specify the appropriate DSOs for a graphics program foogl.c, enter:

cc foogl.c -lgl -lX11

Linking to Dynamic Shared Objects

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."


Note: DSOs replace the older static shared libraries, which were named with the extension _s.a. The _s.a libraries are no longer shipped with IRIX; however, the run-time versions of those libraries, named with _s at the end (and no .a), are still present under IRIX 5.0 for backward compatibility with older executables that used static shared libraries.

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.

Linking Multilanguage Programs

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):

  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.

  2. 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."

Figure 2-1. Compilation Control Flow for Multilanguage Programs

Figure 2-1 Compilation Control Flow for Multilanguage Programs

For specific details about compiling multilanguage programs, refer to the programming guides for the appropriate languages.

Finding an Unresolved Symbol With ld

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.

Debugging

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).


Getting Information About Object Files

The following tools provide information on object files:

  • dis disassembles an object file into machine instructions.

  • 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.

  • nm lists symbol table information.

  • odump lists the contents of a COFF-format object 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.

Disassembling Object Files with dis

The dis tool disassembles object files into machine instructions. You can disassemble an object, archive library, or executable file.

dis Syntax

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.

dis Options

Table 2-5 lists dis options. For more information, see the dis(1) reference page.

Table 2-5. dis Options

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).


Listing Selected Parts of Object Files and Libraries With elfdump

The elfdump tool lists headers, tables, and other selected parts of an ELF-format object file or archive file.

elfdump Syntax

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.

elfump Options

Table 2-6 lists elfdump options. For more information, see the elfdump(1) reference page.

Table 2-6. elfdump Options

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.

 


Determining File Type With file

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.

file Syntax

The syntax for file is:

file filename1 [filename2... filenamen]

Each filename is the name of a file to be examined.

file Example

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.

Listing Symbol Table Information: nm

The nm tool lists symbol table information for object files and archive files.

nm Syntax

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.

nm Options

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


nm Example

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

Finding a Symbol in an Unknown Library

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

Listing Selected Parts of COFF Files With odump

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.

odump Syntax

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.

Table 2-9. odump Options

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.


Determining Section Sizes With size

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.

size Syntax

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.

size options

Table 2-10 lists size options. For more information, see the size(1) reference page.

Table 2-10. size Options

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.


size Example

Below are examples of the size command and the listings they produce:

size -B -o test.o

       text  data bss   rdata sdata  sbss decimal hex
test.o 31250 2010 40470 550   210    50   31232   7a00

size -B -d test.o

       text  data bss   rdata sdata sbss decimal hex
test.o 12968 1032 16696 360   136   40   31232   7a00

Removing Symbol Table and Relocation Bits with strip

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.

strip Syntax

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.

strip Options

Table 2-11 lists strip options. For more information, see the strip(1) reference page.

Table 2-11. strip Options

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.


Using the Archiver to Create Libraries

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.


ar Syntax

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.

Archiver Options

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.

Table 2-12. Archiver Options

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.

Options

m, 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.


ar Examples

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.