HP-UX Linker and Libraries User's Guide HP 9000 Computers B2355-90655 November 1997 © Copyright 1997 Hewlett-Packard Company. All rights reserved.
Legal Notices The information contained in this document is subject to change without notice. Hewlett-Packard makes no warranty of any kind with regard to this manual, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. Hewlett-Packard shall not be liable for errors contained herein or direct, indirect, special, incidental or consequential damages in connection with the furnishing, performance, or use of this material.
UNIX is a registered trademark in the United States and other countries, licensed exclusively through X/Open Company Limited. © Copyright 1979, 1980, 1983, 1985-1990 Regents of the University of California. This software is based in part on the Fourth Berkeley Software Distribution under license from the Regents of the University of California.
Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Printing History. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15 1. What's New in Recent Releases PA-RISC Changes in Hardware Compatibility . . . . . . . . . . . . . . . . . . . .21 PA-RISC 2.0 Compatibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21 PA-RISC Architectures and Their System Models . . . . . . . . . . . .
Contents Global Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 External References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Compiler-Linker Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Linking Programs on HP-UX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The crt0.o Startup File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The a.
Contents Changing the Default Shared Library Binding with -B. . . . . . . . . . . .58 Improving Shared Library Performance with -B symbolic . . . . . . . . .60 Choosing Archive or Shared Libraries with -a . . . . . . . . . . . . . . . . . . .63 Dynamic Linking with -A and -R. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .65 Exporting Symbols with +e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79 Exporting Symbols with +ee . . . . . . . . . . . . . . . . . . . . . . . . . .
Contents 4. Linker Tools Changing a Program's Attributes with chatr(1) . . . . . . . . . . . . . . . . . . 104 Using chatr for 32-bit Program Attributes . . . . . . . . . . . . . . . . . . . . 104 Using chatr for 64-bit Program Attributes . . . . . . . . . . . . . . . . . . . . 105 Viewing Symbols in an Object file with nm(1) . . . . . . . . . . . . . . . . . . . 107 Viewing the Contents of an Object File with elfdump(1) . . . . . . . . . . . 111 Viewing library dependencies with ldd(1). . . . . . . . . .
Contents Summary of Keys to the ar(1) Command . . . . . . . . . . . . . . . . . . . . . .135 crt0.o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .136 Archive Library Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .136 Creating Shared Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .138 Creating Position-Independent Code (PIC). . . . . . . . . . . . . . . . . . . . .
Contents Using Shared Libraries in 64-bit mode. . . . . . . . . . . . . . . . . . . . . . . . . Internal Name Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic Path Searching for Shared Libraries . . . . . . . . . . . . . . . . . Shared Library Symbol Binding Semantics . . . . . . . . . . . . . . . . . . . Mixed Mode Shared Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64-bit Mode Library Examples. . . . . . . . . . . . . . . . . . . . . . . . . .
Contents The dlsym Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .245 The dlget Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .248 The dlmodinfo Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .249 The dlgetname Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .252 The dlclose Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Contents Profile-Based Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . General Information about PBO . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using PBO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . When to Use PBO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How to Use PBO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Instrumenting (+I/-I). . .
Contents Defining Syntax for Mapfile Directives . . . . . . . . . . . . . . . . . . . . . . . . .303 Defining Mapfile Segment Declarations. . . . . . . . . . . . . . . . . . . . . . . . .304 Segment Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .304 Mapfile Segment Declaration Examples . . . . . . . . . . . . . . . . . . . . . . .306 Defining Mapfile Section Mapping Directives . . . . . . . . . . . . . . . . . . . .307 Internal Map Structure . . . . . . . . . . .
Contents 14
Preface This Guide covers the following topics: • Chapter 1, “What's New in Recent Releases,” lists new features added in recent releases. • Chapter 2, “What Happens When You Compile and Link a Program,” provides details on compiling and linking programs. • Chapter 3, “Linker Tasks,” lists many ways you can specify how you want your program linked. • Chapter 4, “Linker Tools,” list the tools available in the linker toolset.
• Add the +ee linker option to export symbols. • Add 64-bit linker toolset support for linker options. • Add 64-bit mode linker tools and describe the enhancements to the 32-bit mode toolset. • Describe 32-bit and 64-bit mode behavior differences. • Add 64-bit mode dynamic path searching mechanisms. • Add 64-bit mode symbol binding semantics. • Add the dl* shared library management routines for 64-bit mode support and describe enhancement to the shl_load routines for shared libraries.
• July 1996, Edition 1, part number B2355-90653. This manual supersedes Programming on HP-UX part number B2355-90652. The main reason for this new edition is to document new functionality for the HP-UX 10.20 release and to describe what's ahead in a future release of the linker toolset: • Add a -B symbolic option to help improve shared library performance. • Introduce the fastbind tool to improve the start up time of programs that use shared libraries. • Introduce the Linker and Libraries Online User Guide.
• Describe thread-safe interfaces shl_get_r and shl_gethandle_r. • Add a new BIND_TOGETHER flag to the shl_load routine. • Add a new chapter "Porting Applications to HP-UX.
What's New in Recent Releases 1 What's New in Recent Releases This section contains information about recent releases of the HP-UX linker toolset: For This Release The HP-UX 11.00 linker toolset contains new features: If you use the 32-bit mode linker toolset, see the following items: • “PA-RISC Changes in Hardware Compatibility” updated in this chapter. • “Exporting Symbols with +ee” on page 81. • “Changes in Future Releases” updated in this chapter.
What's New in Recent Releases • “The dlopen Shared Library Management Routines” on page 240 describes the dl* family of shared library management routines for 64-bit mode. • “BIND_BREADTH_FIRST Modifier” on page 222 describes the flag added to the shl_load routine to modify search behavior. • “Changes in Future Releases” updated in this chapter. For Previous Releases The following items were added in the HP-UX 10.30 release: • “Linker Thread-Safe Features” on page 50.
What's New in Recent Releases PA-RISC Changes in Hardware Compatibility PA-RISC Changes in Hardware Compatibility The HP-UX 10.20 release introduced HP 9000 systems based on the PA-RISC 2.0 architecture. Also, beginning with that release, HP compilers by default generate executable code for the PA-RISC architecture of the machine on which you are compiling. In previous releases, the compilers generated PA-RISC 1.0 code on all HP 9000 Series 800 servers and PA-RISC 1.1 code on Series 700 workstations.
What's New in Recent Releases PA-RISC Changes in Hardware Compatibility In this example, the +DAportable compiler option can be used to create code compatible for PA-RISC 1.1 and 2.0 systems. PA-RISC Architectures and Their System Models The HP 9000 PA-RISC (Precision Architecture Reduced Instruction Set Computing) Series 700/800 family of workstations and servers has evolved from three versions of PA-RISC: PA-RISC 1.0 The original version of PA-RISC first introduced on Series 800 servers.
What's New in Recent Releases 64-bit Mode Linker Toolset Compatibility with De Facto Industry Standards 64-bit Mode Linker Toolset Compatibility with De Facto Industry Standards The 64-bit mode linker and dynamic loader provide linking and loading behaviors found widely across the Unix industry, considered, with the SVR4 standards, to define the de facto industry standards.
What's New in Recent Releases 64-bit Mode ELF Object File Format 64-bit Mode ELF Object File Format Starting with HP-UX release 11.00, the 64-bit linker toolset supports the ELF (executable and linking format) object file format. The 64-bit linker toolset provides new tools to display and manipulate ELF files. The libelf(3x) library routines provide access to ELF files. The command elfdump(1) displays contents of an ELF file. The following options instruct the compiler to generate 64-bit ELF object code.
What's New in Recent Releases New Features for 64-bit Mode Linking New Features for 64-bit Mode Linking This section introduces new features of the 64-bit linker for HP-UX release 11.00. 64-bit Mode Linker Options The ld(1) command supports the following new options in 64-bit mode: Option Action -dynamic Forces the linker to create a shared executable. The linker looks for shared libraries first and then archived libraries. This option is on by default when you compile in 64-bit mode.
What's New in Recent Releases New Features for 64-bit Mode Linking Option Action +noenvvar Instructs the dynamic loader not to look at the LD_LIBRARY_PATH and SHLIB_PATH environment variables at runtime.a +std Instructs the linker to use SVR4 compatible linking and loading behaviors. Default for 64-bit mode.a +stripunwind Instructs the linker not to output the unwind table. +vtype type Produces verbose output about selected link operations.a a.
What's New in Recent Releases New Features for 64-bit Mode Linking Symbol NOTE Definition _edata End of initialized data __gp Global pointer value __init_start Beginning of the .init section __init_end End of the .init section __fini_start Beginning of the .fini section __fini_end End of the .fini section __unwind_start Beginning of the unwind table __unwind_end End of the unwind table The linker generates an error if a user application also defines these symbols.
What's New in Recent Releases 64-bit Mode Link-time Differences 64-bit Mode Link-time Differences The 64-bit mode linker toolset does not support the following 32-bit mode features. Option or Behavior Description -A name Specifies incremental loading. 64-bit applications must use shared libraries instead. -C n Does parameter type checking. This option is unsupported. -S Generates an initial program loader header file. This option is unsupported.
What's New in Recent Releases 64-bit Mode Link-time Differences Option or Behavior Description +dpv Displays verbose messages regarding procedures which have been removed due to dead procedure elimination. Use the -v linker option instead. Intra-library versioning Specified by using the HP_SHLIB_VERSION pragma (C and aC++) or SHLIB_VERSION directive (Fortran90). In 32-bit mode, the linker lets you version your library by object files. 64-bit applications must use SVR4 library-level versioning instead.
What's New in Recent Releases 64-bit Mode Run Time Differences 64-bit Mode Run Time Differences Applications compiled and linked in 64-bit mode use a run-time dynamic loading model similar to other SVR4 systems. There are two main areas where program startup changes in 64-bit mode: • Dynamic path searching for shared libraries. • Symbol searching in dependent libraries. It is recommended that you use the standard SVR4 linking option (+std), which is on by default when linking 64-bit applications.
What's New in Recent Releases 64-bit Mode Run Time Differences Linker and Loader Functions 32-bit Mode Behavior Symbol searching in dependent libraries Depth-first search order. Run time path environment variables No run time environment variables by default. Breadth-first search order. Use +compat to enforce depth first ordering. If +s is specified, then SHLIB_PATH is available.
What's New in Recent Releases Changes in Future Releases Changes in Future Releases The following changes are planned in future releases. • Support of ELF 32 object file format A future release will support the ELF 32 object file format. • Future of ld +compat option The +compat linker option and support of compatibility mode may be discontinued in a future release.
What's New in Recent Releases Online Help for Linker and Libraries Online Help for Linker and Libraries The Linker and Libraries Online User Guide is available for HP 9000 Series 700 and 800 systems. The online help comes with HP C, HP C++, HP aC++, HP Fortran, HP Pascal, and HP Micro Focus COBOL/UX. Online help can be accessed from any X Window display device, or from the charhelp(1) character-mode help browser.
What's New in Recent Releases Online Help for Linker and Libraries /opt/langtools/bin/charhelp ld See charhelp(1) for details.
What Happens When You Compile and Link a Program 2 What Happens When You Compile and Link a Program This chapter describes the process of compiling and linking a program. • “Compiling Programs on HP-UX: An Example” provides an overview of compiling on HP-UX. • “Looking “inside” a Compiler” describes the process of creating an executable file in more detail. • “Linking Programs on HP-UX” describes how ld creates an executable file from one or more object files.
What Happens When You Compile and Link a Program Compiling Programs on HP-UX: An Example Compiling Programs on HP-UX: An Example To create an executable program, you compile a source file containing a main program. For example, to compile an ANSI C program named sumnum.c, shown below, use this command (-Aa says to compile in ANSI mode): $ cc -Aa sumnum.c The compiler displays status, warning, and error messages to standard error output (stderr).
What Happens When You Compile and Link a Program Compiling Programs on HP-UX: An Example sum += n; return sum; /* add n to sum /* return the value of sum */ */ } main() /* begin main program */ { int n; /* number to input from user */ printf("Enter a number: "); /* prompt for number */ scanf("%d", &n); /* read the number into n */ printf("Sum 1 to %d: %d\\n", n, sum_n(n)); /* display the sum */ } Generally speaking, the compiler reads one or more source files, one of which contains a main program, and o
What Happens When You Compile and Link a Program Looking “inside” a Compiler Looking “inside” a Compiler On the surface, it appears as though an HP-UX compiler generates an a.out file by itself. Actually, an HP-UX compiler is a driver that calls other commands to create the a.out file. The driver performs different tasks (or phases) for different languages, but two phases are common to all languages: 1. For each source file, the driver calls the language compiler to create an object file.
What Happens When You Compile and Link a Program Looking “inside” a Compiler -D__unix -D_PA_RISC1_1 cc: Entering Preprocessor. /opt/ansic/lbin/ccom /var/tmp/ctmAAAa10102 func.o -O0 -Aa cc: LPATH is /usr/lib/pa1.1:/usr/lib:/opt/langtools/lib: /usr/ccs/bin/ld /opt/langtools/lib/crt0.o -u main main.o func.o \\ -lm -lc cc: Entering Link editor. This example shows that the cc driver calls the C preprocessor (/opt/langtools/lbin/cpp.
What Happens When You Compile and Link a Program What is an Object File? What is an Object File? An object file is basically a file containing machine language instructions and data in a form that the linker can use to create an executable program. Each routine or data item defined in an object file has a corresponding symbol name by which it is referenced. A symbol generated for a routine or data definition can be either a local definition or global definition.
What Happens When You Compile and Link a Program Compiler-Linker Interaction Compiler-Linker Interaction As described in “Looking “inside” a Compiler”, the compilers automatically call ld to create an executable file. To see how the compilers call ld, run the compiler with the -v (verbose) option. For example, compiling a C program in 32-bit mode produces the output below: $ cc -Aa -v main.c func.c -lm cc: CCOPTS is not set. main.c: /opt/langtools/lbin/cpp.ansi main.
What Happens When You Compile and Link a Program Linking Programs on HP-UX Linking Programs on HP-UX The HP-UX linker, ld, produces a single executable file from one or more input object files and libraries. In doing so, it matches external references to global definitions contained in other object files or libraries. It revises code and data to reflect new addresses, a process known as relocation. If the input files contain debugger information, ld updates this information appropriately.
What Happens When You Compile and Link a Program Linking Programs on HP-UX The crt0.o Startup File Notice in the example in “Compiler-Linker Interaction” that the first object file on the linker command line is /opt/langtools/lib/crt0.o, even though this file was not specified on the compiler command line. This file, known as a startup file, contains the program's entry point that is, the location at which the program starts running after HP-UX loads it into memory to begin execution.
What Happens When You Compile and Link a Program Linking Programs on HP-UX In 64-bit mode for dynamically bound executables, the entry point, defined by the symbol $START$ in the dynamic loader (dld.sl). The a.out File The information contained in the resulting a.out file depends on which architecture the file was created on and what options were used to link the program. In any case, an executable a.
What Happens When You Compile and Link a Program Linking Programs on HP-UX Table 2-1 32-bit Mode Magic Number Linker Options To set the magic number to: Use this option: SHARE_MAGIC -n DEMAND_MAGIC -q EXEC_MAGIC -N An executable file's magic number can also be changed using the chatr command (see “Changing a Program's Attributes with chatr(1)” on page 104). However, chatr can only toggle between SHARE_MAGIC and DEMAND_MAGIC; it cannot be used to change from or to EXEC_MAGIC.
What Happens When You Compile and Link a Program Linking with Libraries Linking with Libraries In addition to matching external references to global definitions in object files, ld matches external references to global definitions in libraries. A library is a file containing object code for subroutines and data that can be used by other programs.
What Happens When You Compile and Link a Program Linking with Libraries $ f77 -v sumnum.f ... /usr/ccs/bin/ld -x /opt/langtools/lib/crt0.o \ sumnum.o -lcl -lisamstub -lc The Default Library Search Path By default, ld searches for libraries in the directory /usr/lib. (If the -p or -G compiler profiling option is specified on the command line, the compiler directs the linker to also search /usr/lib/libp.) The default order can be overridden with the LPATH environment variable or the -L linker option.
What Happens When You Compile and Link a Program Running the Program Running the Program An executable file is created after the program has been compiled and linked. The next step is to run or load the program. Loading Programs: exec When you run an executable file created by ld, the program is loaded into memory by the HP-UX program loader, exec. This routine is actually a system call and can be called by other programs to load a new program into the current process space.
What Happens When You Compile and Link a Program Running the Program Deferred Binding is the Default To accelerate program startup time, routines in a shared library are not bound until referenced. (Data items are always bound at program startup.) This deferred binding of shared library routines distributes the overhead of binding across the execution time of the program and is especially expedient for programs that contain many references that are not likely to be executed.
What Happens When You Compile and Link a Program Linker Thread-Safe Features Linker Thread-Safe Features Beginning with the HP-UX 10.30 release, the dynamic loader (dld.sl) and its application interface library (libdld.sl) are thread-safe. Also, beginning with the HP-UX 10.30 release, the linker toolset provides thread local storage support in: • ld — the link editor • dld.sl — the shared library dynamic loader • crt0.
Linker Tasks 3 Linker Tasks You have a great deal of control over how the linker links your program or library by using ld command-line options. • Using the Compiler Command • “Changing the Default Library Search Path with -Wl, -L” • “Getting Verbose Output with -v” • “Passing Linker Options from the Compiler Command with -Wl” • “Renaming the Output File with -o” • “Specifying Libraries with -l” • “Suppressing the Link-Edit Phase with -c” • Using the Linker Command • “Linking with the 32-bit crt0.
Linker Tasks • “Specifying Libraries with -l and l:” • “Stripping Symbol Table Information from the Output File with -s and -x” • Using the 64-bit mode linker command • “Using the 64-bit Mode Linker with +compat or +std” • “Linking Shared Libraries with -dynamic” • “Linking Archived Libraries with -noshared” • “Controlling Archive Library Loading with +[no]forceload” • “Flagging Unsatisfied Symbols with +[no]allowunsats” • “Hiding Symbols from export with +hideallsymbols” • “Changing Mapfiles with -k and +
Linker Tasks Using the Compiler to Link Using the Compiler to Link In many cases, you use your compiler command to compile and link programs. Your compiler uses options that directly affect the linker. Changing the Default Library Search Path with -Wl, -L By default, the linker searches the directory /usr/lib and /usr/ccs/lib for libraries specified with the -l compiler option. (If the -p or -G compiler option is specified, then the linker also searches the profiling library directory /usr/lib/libp.
Linker Tasks Using the Compiler to Link The LPATH environment variable provides another way to override the default search path. For details, see “Changing the Default Library Search Path with -L and LPATH”. Getting Verbose Output with -v The -v option makes a compiler display verbose information. This is useful for seeing how the compiler calls ld. For example, using the -v option with the Pascal compiler shows that it automatically links with libcl, libm, and libc. $ pc -v prog.
Linker Tasks Using the Compiler to Link Renaming the Output File with -o The -o name option causes ld to name the output file name instead of a.out. For example, to compile a C program prog.c and name the resulting file sum_num: $ cc -Aa -o sum_num prog.c $ sum_num Enter a number to sum: 5 The sum of 1 to 5: 15 Compile using -o option. Run the program. Specifying Libraries with -l Sometimes programs call routines not contained in the default libraries.
Linker Tasks Using the Compiler to Link $ f77 -c func.f $ ls func.o func.o $ f77 main.f func.o $ a.out 56 Produce .o for func.f. Verify that func.o was created. Compile main.f with func.o Run it to verify it worked.
Linker Tasks Using Linker commands Using Linker commands This section describes linker commands for the 32-bit and 64-bit linker. NOTE Unless otherwise noted, all examples show 32-bit behavior. Linking with the 32-bit crt0.o Startup File In 32-bit mode, you must always include crt0.o on the link line. In 64-bit mode, you must include crt0.o on the link line for all fully archive links (ld -noshared) and in compatibility mode (+compat). You do not need to include the crt0.
Linker Tasks Using Linker commands Augmenting the Default Linker Search Path with -L The -L option to ld also allows you to add additional directories to the search path. If -L libpath is specified, ld searches the libpath directory before the default places. For example, suppose you have a locally developed version of libc, which resides in the directory /usr/local/lib. To make ld find this version of libc before the default libc, use the -L option as follows: $ ld /opt/langtools/lib/crt0.o prog.
Linker Tasks Using Linker commands Nonfatal Shared Library Binding with -B nonfatal The linker also supports nonfatal binding, which is useful with the -B immediate option. Like immediate binding, nonfatal immediate binding causes all required symbols to be bound at program startup. The main difference from immediate binding is that program execution continues even if the dynamic loader cannot resolve symbols. Compare this with immediate binding, where unresolved symbols cause the program to abort.
Linker Tasks Using Linker commands • The program calls shl_definesym to define a symbol that is already defined in a library that was loaded at program startup. If such a program is linked with -B immediate, references to symbols will be bound at program startup, regardless of whether duplicate symbols are created later by shl_load or shl_definesym.
Linker Tasks Using Linker commands NOTE The +e option overrides the -B symbolic option. For example, you use +e symbol, only symbol is exported and all other symbols are hidden. Similarly, if you use +ee symbol, only symbol is exported, but other symbols exported by default remain visible. Since all internal calls inside the shared library are resolved inside the shared library, user-supplied modules with the same name are not seen by routines inside the library.
Linker Tasks Using Linker commands Figure 3-1 Symbols inside a Shared Library Visible with -B symbolic main1 libunits.sl main () { convert_rtn(); } main2 main () { gal_to_liter(); } convert_rtn() { gal_to_liter(); } gal_to_liter() { } Direct call path Both convert_rtn and gal_to_liter symbols are visible. Case 2: Building a Shared Library with -h or +e. The -h (hide symbol) and +e (export symbol) options can also optimize the call path in a shared library for symbols that are explicitly hidden.
Linker Tasks Using Linker commands In both cases, main2 will not be able to resolve its reference to gal_to_liter() because only the convert_rtn() symbol is exported as shown below: libunits.sl main1 main () { convert_rtn (); } main2 main () { gal_to_liter(); } convert_rtn() { gal_to_liter(); } Only convert_rtn symbol is visible.
Linker Tasks Using Linker commands -a archive Select archive libraries. If the archive library does not exist, ld generates an error message and does not generate the output file. -a shared Select shared libraries. If the shared library does not exist, ld generates an error message and does not generate the output file. -a default This is the same as -a shared_archive. -a archive_shared Select the archive library if it exists; otherwise, select the shared library.
Linker Tasks Using Linker commands Dynamic Linking with -A and -R This section describes how to do dynamic linking — that is, how to add an object module to a running program. Conceptually, it is very similar to loading a shared library and accessing its symbols (routines and data). In fact, if you require such functionality, you should probably use shared library management routines (see Chapter 6, “Shared Library Management Routines,” on page 195).
Linker Tasks Using Linker commands 8. Get the addresses of routines and data that are referenced in the module. Step 1: Determine how much space is required to load the module. There must be enough contiguous memory to hold the module's text, data, and bss segments. You can make a liberal guess as to how much memory is needed, and hope that you've guessed correctly. Or you can be more precise by pre-linking the module and getting size information from its header.
Linker Tasks Using Linker commands The useful members of the som_exec_auxhdr structure are: .exec_tsize Size of text (code) segment. .exec_tmem Address at which to load the text (already adjusted for offset specified by the -R linker option). .exec_tfile Offset into file (location) where text segment starts. .exec_dsize Size of data segment. .exec_dmem Address at which to load the data (already adjusted). .exec_dfile Offset into file (location) where data segment starts. .
Linker Tasks Using Linker commands Use an assembly language routine named flush_cache (see “The flush_cache Function” in this chapter). You must assemble this routine separately (with the as command) and link it with the main program. Step 8: Get the addresses of routines and data that are referenced in the module. If the -e linker option was used, the module's header will contain the address of the entry point. The entry point's address is stored in the .exec_entry member of the som_exec_auxhdr structure.
Linker Tasks Using Linker commands The Build Environment. Before seeing the program's source code, it may help to see how the program and the various object files were built. The following shows the makefile used to generate the various files. Makefile Used to Create Dynamic Link Files CFLAGS = -Aa -D_POSIX_SOURCE dynprog: dynprog.o dynload.o flush_cache.o # Compile line: cc -o dynprog dynprog.o dynload.o flush_cache.o -Wl,-a,archive file1.o: file2.o: file1.c dynprog.c file2.c # Create flush_cache.
Linker Tasks Using Linker commands Note that the line CFLAGS =… causes any C files to be compiled in ANSI mode (-Aa) and causes the compiler to search for routines that are defined in the Posix standard (-D_POSIX_SOURCE). For details on using make refer to make(1). Source for dynprog. Here is the source file for the dynprog program. dynprog.c — Example Dynamic Link and Load Program #include #include
Linker Tasks Using Linker commands foo_ptr = (void (*)()) dyn_load(base_prog, addr, obj_files, dest_file, entry_pt); /* STEP 3: Get the addresses of all desired routines using nlist(3C): */ nl[0].n_name = “bar”; nl[1].n_name = “counter”; nl[2].n_name = NULL; if (nlist(dest_file, nl)) { fprintf(stderr, “error obtaining namelist for %s\n”, dest_file); exit(1); } /* * Assign the addresses to meaningful variable names: */ bar_ptr = (void (*)()) nl[0].n_value; counter_ptr = (int *) nl[1].
Linker Tasks Using Linker commands glorp(“foo”); (*counter_ptr) ++; /* update counter indirectly with global pointer */ } void bar() { glorp(“bar”); counter ++; } /* update counter directly */ /**************************************************************** * file2.c - Global counter variable referenced by dynprog.c * and file1.c. ****************************************************************/ int counter = 0; Output of dynprog .
Linker Tasks Using Linker commands obj_files The name of the object file or files that will be linked together to create dest_file. dest_file The name of the resulting object module that will by dynamically linked and loaded by base_prog. As described in Step 1 in “Overview of Dynamic Linking” at the start of this section, you can either guess at how much space will be required to load a module, or you can try to be more accurate.
Linker Tasks Using Linker commands fprintf(stderr, “link failed: %s\n”, cmd_buf); exit(ret_val); } /* * * * */ --------------------------------------------------------------STEP 2: Get the size of the module’s text, data, and bss segments from the auxiliary header for dest_file; add them together to determine size: if ((destfp = fopen(dest_file, “r”)) == NULL) { fprintf(stderr, “error opening %s\n”, dest_file); exit(1); } /* * Must seek past SOM “header” to get to the desired * “som_exec_auxhdr”: */ if (fs
Linker Tasks Using Linker commands The base_prog, obj_files, and dest_file parameters are the same parameters supplied to alloc_load_space. The addr parameter is the address returned by alloc_load_space, and the entry_pt parameter specifies a symbol name that you want to act as the entry point in the module. To dynamically link and load dest_file into base_prog, the dyn_load function performs these steps: 1. Dynamically link base_prog with obj_files, producing dest_file.
Linker Tasks Using Linker commands */ struct som_exec_auxhdr aux_hdr; /* som file auxiliary header */ unsigned int tdb_size; /* size of text, data, and bss combined*/ /* ----------------------------------------------------------------* STEP 1: Dynamically link the module to be loaded: */ sprintf(cmd_buf, “/bin/ld -a archive -A %s -R %x -N %s -o %s -lc -e %s”, base_prog, addr, obj_files, dest_file, entry_pt); if (ret_val = system(cmd_buf)) { fprintf(stderr, “link command failed: %s\n”, cmd_buf); exit(ret_val
Linker Tasks Using Linker commands if (fseek(destfp, aux_hdr.exec_tfile, 0)) { fprintf(stderr, “error seeking start of text in %s\n”, dest_file); exit(1); } if ((fread(aux_hdr.exec_tmem, aux_hdr.exec_tsize, 1, destfp)) <= 0) { fprintf(stderr, “error reading text from %s\n”, dest_file); exit(1); } /* * Now load the data, if any: */ if (aux_hdr.exec_dsize) { if (fseek(destfp, aux_hdr.exec_dfile, 0)) { fprintf(stderr, “error seeking start of data in %s\n”, dest_file); exit(1); } if ((fread(aux_hdr.
Linker Tasks Using Linker commands /* ----------------------------------------------------------------* STEP 6: Return a pointer to the entry point specified by -e: */ entry_pt_addr = (unsigned int) aux_hdr.exec_entry; return ((void *) entry_pt_addr); } The flush_cache Function . Since there is no existing routine to flush text from the data cache before execution, you must create one. Below is the assembly language source for such a function.
Linker Tasks Using Linker commands copy %arg1,%arg3 ; Copy offset from GR25 to GR23 fdc %arg1(0,%arg0) ; Flush data cache @SID.address+offset loop1 addib,>,n -16,%arg1,loop1 ; Decrement offset by cache line size fdc %arg1(0,%arg0) ; Flush data cache @SID.address+offset ; flush first word at addr, to handle arbitrary cache line boundary fdc 0(0,%arg0) sync fic %arg3(%sr0,%arg2) @SID.address+offset loop2 addib,>,n -16,%arg3,loop2 size fic %arg3(%sr0,%arg2) @SID.
Linker Tasks Using Linker commands $ nm -p sem.o 0000000000 U 1073741824 d 1073741864 b 0000000004 cS 0000000000 T 0000000036 T 0000000000 U 0000000088 T 0000000140 T $global$ $THIS_DATA$ $THIS_BSS$ sem_val check_sem_val foo printf bar sem In this example, check_sem_val, foo, bar, and sem are all global definitions. To create a shared library where check_sem_val is a hidden, local definition, you could use either of the following commands: $ ld -b -h check_sem_val sem.o $ ld -b +e foo +e bar +e sem sem.
Linker Tasks Using Linker commands Exporting Symbols with +ee Like the +e option, the +ee option allows you to export symbols. Unlike the +e option, the option does not alter the visibility of any other symbols in the file. It exports the specified symbol, and does not hide any of the symbols exported by default. Exporting Symbols from main with -E By default, the linker exports from a program only those symbols that were imported by a shared library.
Linker Tasks Using Linker commands $ nm -p sem.o 0000000000 U 1073741824 d 1073741864 b 0000000004 cS 0000000000 T 0000000036 T 0000000000 U 0000000088 T 0000000140 T $global$ $THIS_DATA$ $THIS_BSS$ sem_val check_sem_val foo printf bar sem In this example, check_sem_val, foo, bar, and sem are all global definitions. To create a shared library where check_sem_val is a hidden, local definition, you could do the following: $ ld -b -h check_sem_val sem.
Linker Tasks Using Linker commands • When linking with other libraries (to create an executable), it ensures that the library will use the local definition of a routine rather than a definition that occurs earlier in the link order. Exporting a symbol is necessary if the symbol must be accessible outside the shared library. But remember that, by default, most symbols are global definitions anyway, so it is seldom necessary to explicitly export symbols.
Linker Tasks Using Linker commands As mentioned previously in the section “Exporting Symbols from main with -E”, the -E option forces the export of all symbols from the program, regardless of whether they are referenced by shared libraries on the linker command line. The +e option allows you to be more selective in what symbols are exported. You can use +e to limit the exported symbols to only those symbols you want to be visible. For example, the following ld command exports the symbols main and foo.
Linker Tasks Using Linker commands Specifying a Path List with +b The syntax of the +b option is +b path_list where path_list is the list of directories you want the dynamic loader to search at run time. For example, the following linker command causes the path .:/app/lib:: to be stored in the executable. At run time, the dynamic loader would search for libfoo.sl, libm.sl, and libc.sl in the current working directory (.
Linker Tasks Using Linker commands the previous example were /apps/lib::xyz, the dynamic loader would search for /apps/lib/libfoo.sl, /usr/local/lib/libfoo.sl, then ./xyz/libfoo.sl. If the dynamic loader cannot find a required library in any of the directories specified in the path list, it searches for the library in the default location () recorded by the linker. Moving Libraries After Linking with +s and SHLIB_PATH A library can be moved even after an application has been linked with it.
Linker Tasks Using Linker commands +e reverse_tree +e preorder_traversal +e shift_reduce_parse . . . Note that the linker ignores lines in that option file that begin with a pound sign (#). You can use such lines as comment lines or to temporarily disable certain linker options in the file.
Linker Tasks Using Linker commands The x argument corresponds to the identifying portion of the library path name — the part following lib and preceding the suffix .a or .sl. For example, for the libm.sl or libm.a library, x is the letter m: $ cc -Aa mathprog.c -lm The linker searches libraries in the order in which they are specified on the command line (that is, the link order). In addition, libraries specified with -l are searched before the libraries that the compiler links by default.
Linker Tasks Using Linker commands Stripping Symbol Table Information from the Output File with -s and -x The a.out file created by the linker contains symbol table, relocation, and (if debug options were specified) information used by the debugger. Such information can be used by other commands that work on a.out files, but is not actually necessary to make the file run.
Linker Tasks Using 64-bit Mode Linker Options Using 64-bit Mode Linker Options This section introduces 64-bit-only linker options. Using the 64-bit Mode Linker with +compat or +std In the HP-UX 11.0 release, the linker toolset supports extended features for linking in 64-bit mode. Since compatibility with the previous linker toolset is a high priority, the 64-bit linker uses much of the old behavior in the new toolset.
Linker Tasks Using 64-bit Mode Linker Options • +b first means dld looks at the RPATH first when searching for dependent shared libraries. To get the default RPATH, you must specify ld +b. This instructs the linker to construct a default RPATH consisting of the -L directories and LPATH. • +s first means the dynamic loader looks at the SHLIB_PATH environment variable first when searching for dependent shared libraries.
Linker Tasks Using 64-bit Mode Linker Options This default may change in future releases. When you use +std, the linker: • Assumes -dynamic was passed to ld. The linker looks for shared libraries first. The output executable is a shared executable. • All dependent shared libraries are output in the dynamic table in a DT_NEEDED entry. These dependent shared libraries are recorded as standard mode shared libraries. • ld +b and +s ordering is ignored. ld +s is on by default.
Linker Tasks Using 64-bit Mode Linker Options • Looks at the environment variables first, followed by RPATH, and the default directories by default when doing dynamic path searching for standard-mode dependentshared libraries. Linking Shared Libraries with -dynamic Use the -dynamic option to instruct the linker to look for shared libraries first and then archive libraries. The linker outputs a dynamically linked executable. This option is on by default in standard mode.
Linker Tasks Using 64-bit Mode Linker Options only load those modules from an archive library that is needed. The mode you select, either by default or explicitly, remains on until you change it. +noforceload is the default on both 32-bit and 64-bit modes. In the following example, main() references foo(), which is a module in mylib.a. foo() doesn’t reference any other module in mylib.a and libc.a. If mylib.a contains foo.o and bar.o, then only foo.o is linked in. ld crt0.o main.o +vtype libraries mylib.
Linker Tasks Using 64-bit Mode Linker Options Hiding Symbols from export with +hideallsymbols Use the +hideallsymbols option to hide all symbols to prevent the linker from exporting them in a shared link. In the following example, main() exports func() and test(). Using +hideallsymbols, the linker does not export these two routines in the a.out. ld main.o +hideallsymbols -L. -lfoo -lc elfdump -t a.out a.out: ... .symtab index Type Bind Other SectValueSizeName 1 FUNC LOCL 00xb 0x4000000000001104 0test ...
Linker Tasks Using 64-bit Mode Linker Options Ignoring Dynamic Path Environment Variables with +noenvvar Use the +noenvvar to instruct the dynamic loader not to look at the environment variables relating to dynamic path searching at runtime. It ignores LD_LIBRARY_PATH and SHLIB_PATH environment variables. This option is on by default in with ld +compat. It is off by default with ld +std. For example, if libbar.sl has dependent library libfee.sl that is i .
Linker Tasks Using 64-bit Mode Linker Options Selecting Verbose Output with +vtype Use the +vtype option to get verbose output about specified elements of the link operation. The following values specify the type: Parameter Description files Dump information about each object file loaded. ld main.o +vtype files -L. -lfile1 -lfile2 -lc Loading main.o: Loading ./libfile1.sl: Loading ./libfile2.sl: Loading /usr/lib/pa20_64/libc.2: Loading /usr/lib/pa20_64/libdl.
Linker Tasks Using 64-bit Mode Linker Options ld main.o +vtype all -L. -lfile1 -lfile2 -lc Loading main.o: main.o: main is DEFINED GLOBAL FUNC printf is UNDEF GLOBAL FUNC lib1_func is UNDEF GLOBAL FUNC lib2_func is UNDEF GLOBAL FUNC main.o: section .text PROG_BITS AX 116 8 added to text segment section .PARISC.unwind UNWIND 16 4 added to text segment section .data PROG_BITS AW 96 8 added to data segment Loading ./libfile1.sl: ./libfile1.sl: ... Linking with the 64-bit crt0.
Linker Tasks Linker Compatibility Warnings Linker Compatibility Warnings Beginning with the HP-UX 10.20 release, the linker generates compatibility warnings. These warnings include HP 9000 architecture issues, as well as linker features that may change over time. Compatibility warnings can be turned off with the +vnocompatwarnings linker option. Also, detailed warnings can be turned on with the +vallcompatwarnings linker option. See the ld(1) man page for a description of these options.
Linker Tasks Linker Compatibility Warnings • Unsatisfied symbols found when linking to archive libraries — If you specify the -v option with the +vallcompatwarnings option and link to archive libraries, you may see new warnings. For an example, see “Linking to Archive Libraries with Unsatisfied Symbols” in this chapter.
Linker Tasks Linker Compatibility Warnings printf ("\tfoo = %d\n", foo); } If these files are compiled and linked as: cc cc ar ld -c main.c -c archive.c rv liba.a archive.o /opt/langtools/lib/crt0.o -v \ +vallcompatwarnings main.o liba.a -lc -o test The linker issues the following warning: ld: (Warning) The file liba.a(archive.o) has not been fully checked for unsatisfied symbols. This behavior may change in future releases. due to an unresolved symbol for unsat(). In the HP-UX 11.
Linker Tasks Linker Compatibility Warnings 102 Chapter 3
4 Linker Tools This chapter describes the linker toolset, which provides several tools to help you find symbols, display and modify object files, and determine link order. Some of these tools are specific to a particular object file type; others are available in both 32-bit and 64-bit mode. The following table lists the linker toolset. Tool Mode Description chatr 32-bit/ 64-bit Displays or modifies the internal attributes of an object file. See “Changing a Program's Attributes with chatr(1)”.
Linker Tools Changing a Program's Attributes with chatr(1) Changing a Program's Attributes with chatr(1) The chatr command (see chatr(1)) allows you to change various program attributes that were determined at link time. When run without any options, chatr displays the attributes of the specified file.
Linker Tools Changing a Program's Attributes with chatr(1) To do this: Use this option: Enable the use of the SHLIB_PATH environment variable to perform run-time path list lookup of shared libraries. +s enablea Disable the use of the SHLIB_PATH environment variable to perform run-time path list lookup of shared libraries. +s disable 32-bit mode only: Do not subject a library to path list lookup, even if path lists are provided. That is, use default library path stored in the executable.
Linker Tools Changing a Program's Attributes with chatr(1) To do this: Use this option: Set the modification bit for the file’s data segment(s). +md Set the modification bit for the file’s text segment(s). +mi Set the code bit for the file’s data segment(s). +cd Set the code bit for the file’s text segment(s). +ci Enable lazy swap on all data segments. Do not use with non-data segments. +z For the 64-bit only syntax: To do this: Use this option: Set the code bit for a specified segment.
Linker Tools Viewing Symbols in an Object file with nm(1) Viewing Symbols in an Object file with nm(1) The nm(1) command displays the symbol table of each specified object. file can be a relocatable object file or an executable object file, or an archive of relocatable or executable object files. nm provides three general output formats: the default (neither –p nor –P specified), –p, and –P. See the nm(1) man page for a detailed description of the output formats.
Linker Tools Viewing Symbols in an Object file with nm(1) To Display information in a blank-separated output format. Each symbol name is preceded by its value (blanks if undefined) and one of the letters A absolute B bss symbol C common symbol D data symbol R section region S tstorage symbol (32-bit mode SOM files only) If the symbol is local (nonexternal), the type letter is in lowercase. If the symbol is a secondary definition, the type letter is followed by the letter S.
Linker Tools Viewing Symbols in an Object file with nm(1) Use This Option To 32-bit mode SOM files only: Truncate every name that would otherwise overflow its column and place an asterisk as the last character in the displayed name to mark it as truncated. If –A or –r is also specified, the file prefix is truncated first. –T By default, nm prints the entire name of the symbols listed.
Linker Tools Viewing Symbols in an Object file with nm(1) 0000000000 compiling. 1073741824 1073741872 1073741872 1073741872 0000000000 0000000000 0000000000 0000000000 U $global$ d d b d T U U U $THIS_DATA$ $THIS_SHORTDATA$ $THIS_BSS$ $THIS_SHORTBSS$ main printf scanf sum_n Other symbols created from Global definition of main. The first column shows the address of each symbol or reference. The last column shows the symbol name.
Linker Tools Viewing the Contents of an Object File with elfdump(1) Viewing the Contents of an Object File with elfdump(1) NOTE The elfdump command works on 64-bit executables or shared libraries. The elfdump(1) command displays information contained in ELF format object files, archives, and shared libraries. Use the following options to select the information you want to display: To view the contents. Use this option Symbol table entries. -t Archive headers from an archive library.
Linker Tools Viewing the Contents of an Object File with elfdump(1) Option Modifies Causes elfdump to -H all Select output format in hexadecimal, octal, or decimal. -p all Suppress title printing. -S -h,-o Display headers in short format. -C -c, -r, -s, -t Demangle C++ symbol names before displaying them. • With -H, ignored. • With -n name, display the symbol whose unmangled name matches name, and prints its symbol name as a demangled name.
Linker Tools Viewing library dependencies with ldd(1) Viewing library dependencies with ldd(1) NOTE The ldd command works on 64-bit executables or shared libraries. The ldd(1) command lists the dynamic dependencies of executable files or shared libraries. ldd displays verbose information about dynamic dependencies and symbol references: Executable All shared libraries that would be loaded as a result of executing the file.
Linker Tools Viewing library dependencies with ldd(1) $ldd a.out ./libx.sl =>./libx.sl libc.2 =>/lib/pa20_64/libc.2 libdl.1 =>/lib/pa20_64/libdl.1 • The -v option causes ldd to print dependency relationship along with the dynamic path information. $ldd -v a.out find library=./libx.sl; required by a.out ./libx.sl =>./libx.sl find library=libc.2; required by a.out libc.2 =>/lib/pa20_64/libc.2 find library=libdl.1; required by /lib/pa20_64/libc.2 libdl.1 =>/lib/pa20_64/libdl.
Linker Tools Viewing the Size of Object File Elements with size(1) Viewing the Size of Object File Elements with size(1) The size(1) command produces section size information for each section in your specified object files. It displays the size of the text, data and bss (uninitialized data) sections with the total size of the object file. If you specify an archive file, the information for all archive members is displayed.
Linker Tools Reducing Storage Space with strip(1) Reducing Storage Space with strip(1) The strip(1) command removes the symbol table and line number information from object files, including archives. Thereafter, no symbolic debugging access is available for that file. The purpose of this command is to reduce file storage overhead consumed by the object file. Use this command on production modules that have been debugged and tested. The effect is nearly identical to using the -s option of ld.
Linker Tools Reducing Storage Space with strip(1) If you execute strip on an archive file (see ar(4)), it removes the archive symbol table. The archive symbol table must be restored by executing ar with its s operator (see ar(1)) before the ld command (see ld (1)) can use the archive. strip issues appropriate warning messages when this situation occurs.
Linker Tools Improving Program Start-up with fastbind(1) Improving Program Start-up with fastbind(1) The fastbind(1) command prepare an incomplete executable for faster program start-up. It can improve the start-up time of programs that use shared libraries (incomplete executables) by storing information about needed shared library symbols in the executable file.
Linker Tools Improving Program Start-up with fastbind(1) The 32-bit mode fastbind command does not work with EXEC_MAGIC executables. fastbind effectively enforces the binding modes bind-restricted and bind-immediate. For example, consider an executable linked bind-deferred, which calls a function foo() defined in an implicitly loaded library.
Linker Tools Finding Object Library Ordering Relationships with lorder(1) Finding Object Library Ordering Relationships with lorder(1) The lorder command finds the ordering relation for an object library. You can specify one or more object or archive library files (see ar(1)) on the command line or read those files from standard input. The standard output is a list of pairs of object file names, meaning that the first file of the pair refers to external identifiers defined in the second.
Creating and Using Libraries 5 Creating and Using Libraries Many libraries come with HP-UX. You can also create and use your own libraries on HP-UX.
Creating and Using Libraries Overview of Shared and Archive Libraries Overview of Shared and Archive Libraries HP-UX supports two kinds of libraries: archive and shared. A shared library is also called a dll (dynamically linked library), particularly in the context of the 64-bit mode linker. Archive libraries are the more traditional of the two. The following table summarizes differences between archive and shared libraries. Comparing Archive Shared (or dll) file name suffix Suffix is .a. Suffix is .
Creating and Using Libraries Overview of Shared and Archive Libraries Comparing Archive Shared (or dll) address binding Addresses of library subroutines and data are resolved at link time. Addresses of library subroutines are bound at run time. Addresses of data in a.out are bound at link time; addresses of data in shared libraries are bound at run time. a.out files Contains all library routines or data (external references) referenced in the program. An a.
Creating and Using Libraries Overview of Shared and Archive Libraries (/usr/lib/libc.a or /usr/lib/pa20_64/libc.a). You can, however, override this behavior and select the archive version of a library with the -a option or the -l: option. These are described in “Choosing Archive or Shared Libraries with -a” on page 63 and “Specifying Libraries with -l and l:” on page 87. In addition to the system libraries provided on HP-UX, you can create your own archive and shared libraries.
Creating and Using Libraries What are Archive Libraries? What are Archive Libraries? An archive library contains one or more object files and is created with the ar command. When linking an object file with an archive library, ld searches the library for global definitions that match up with external references in the object file. If a match is found, ld copies the object file containing the global definition from the library into the a.out file.
Creating and Using Libraries What are Shared Libraries? What are Shared Libraries? Like an archive library, a shared library contains object code. However, ld treats shared libraries quite differently from archive libraries. When linking an object file with a shared library, ld does not copy object code from the library into the a.out file; instead, the linker simply notes in the a.out file that the code calls a routine in the shared library. An a.
Creating and Using Libraries What are Shared Libraries? Default Behavior When Searching for Libraries at Run Time By default, if the dynamic loader cannot find a shared library from the list, it generates a run-time error and the program aborts. For example, in 32-bit mode, suppose that during development, a program is linked with the shared library liblocal.sl in your current working directory (say, /users/hyperturbo): $ ld /opt/langtools/lib/crt0.o prog.o -lc liblocal.
Creating and Using Libraries Example Program Comparing Shared and Archive Libraries Example Program Comparing Shared and Archive Libraries As an example, suppose two separate programs, prog1 and prog2, use shared libc routines heavily. Suppose that the a.out portion of prog1 is 256Kb in size, while the prog2 a.out portion is 128Kb. Assume also that the shared libc is 512Kb in size. Figure 5-2 shows how physical memory might look when both processes run simultaneously.
Creating and Using Libraries Example Program Comparing Shared and Archive Libraries Figure 5-3 Two Processes with Their Own Copies of libc Chapter 5 129
Creating and Using Libraries Shared Libraries with Debuggers, Profilers, and Static Analysis Shared Libraries with Debuggers, Profilers, and Static Analysis As of the HP-UX 10.0 release, debugging of shared libraries is supported by the HP/DDE debugger. For details on how to debug shared libraries, refer to the HP/DDE Debugger User's Guide. Profiling with prof and gprof and static analysis are not allowed on shared libraries.
Creating and Using Libraries Creating Archive Libraries Creating Archive Libraries Two steps are required to create an archive library: 1. Compile one or more source files to create object files containing relocatable object code. 2. Combine these object files into a single archive library file with the ar command. Shown below are the commands you would use to create an archive library called libunits.a: cc -Aa -c length.c volume.c mass.c ar r libunits.a length.o volume.o mass.
Creating and Using Libraries Creating Archive Libraries Figure 5-4 summarizes the procedure for creating archive libraries from three C source files (file1.c, file2.c, and file3.c). The process is identical for other languages, except that you would use a different compiler. Figure 5-4 Creating an Archive Library Contents of an Archive File An archive library file consists of four main pieces: 1.
Creating and Using Libraries Creating Archive Libraries cosh.o Object modules are displayed. erf.o fabs.o floor.o . . . . This indicates that the library was built from object files named cosh.o, erf.o, fabs.o, floor.o, and so forth. In other words, module names are the same as the names of the object files from which they were created. Example of Creating an Archive Library Suppose you are working on a program that does several conversions between English and Metric units.
Creating and Using Libraries Creating Archive Libraries Then combine the .o files by running ar with the r key, followed by the library name (say libunits.a), followed by the names of the object files to place in the library: $ ar r libunits.a length.o volume.o mass.o ar: creating libunits.a To verify that ar created the library correctly, view its contents: $ ar t libunits.a length.o volume.o mass.o Use ar with the t key. All the .o modules are included; it worked.
Creating and Using Libraries Creating Archive Libraries Deleting an Object Module To delete an object module from a library, use the d key. For example, to delete volume.o from libunits.a: $ ar d libunits.a volume.o $ ar t libunits.a length.o mass.o Delete volume.o. List the contents. volume.o is gone. Summary of Keys to the ar(1) Command When used to create and manage archive libraries, ar's syntax is: ar [-] keys archive [modules] ... archive is the name of the archive library.
Creating and Using Libraries Creating Archive Libraries $ ar tv rw-rr rw-rr rw-rr libunits.a 265/ 20 265/ 20 265/ 20 230 Feb 228 Feb 230 Feb 2 17:19 1990 length.o 2 16:25 1990 mass.o 2 16:24 1990 volume.o The next example replaces length.o in libunits.a, only if length.o is more recent than the one already contained in libunits.a: $ ar ru libunits.a length.o crt0.o In 64-bit mode, the crt0.o startup file is not needed for shared bound links because dld.
Creating and Using Libraries Creating Archive Libraries Check with your system administrator before attempting to use /usr/lib or /usr/lib/pa20_64. Using /usr/local/lib or /usr/contrib/lib The /usr/local/lib and /usr/local/lib/pa20_64 library typically contain libraries created locally — by programmers on the system; /usr/contrib/lib and /usr/contrib/lib/pa20_64 contain libraries supplied with HP-UX but not supported by Hewlett-Packard.
Creating and Using Libraries Creating Shared Libraries Creating Shared Libraries Two steps are required to create a shared library: 1. “Creating Position-Independent Code (PIC)” by compiling with +z. 2. “Creating the Shared Library with ld” by linking with -b. Shown below are the commands you would use to create a shared library called libunits.sl: $ cc -Aa -c +z length.c volume.c mass.c $ ld -b -o libunits.sl length.o volume.o mass.
Creating and Using Libraries Creating Shared Libraries Example Using +z Suppose you have some C functions, stored in length.c, that convert between English and Metric length units. To compile these routines and create PIC object files with the C compiler, you could use this command: $ cc -Aa -c +z length.c The +z option creates PIC. You could then link it with other PIC object files to create a shared library, as discussed in “Creating the Shared Library with ld”.
Creating and Using Libraries Creating Shared Libraries $ cc -Aa -c +z length.c volume.c mass.c length.c: volume.c: mass.c: $ ld -b -o libunits.sl length.o volume.o mass.o Once the library is created, be sure it has read and execute permissions for all users who will use the library. For example, the following chmod command allows read/execute permission for all users of the libunits.sl library: $ chmod +r+x libunits.sl This library can now be linked with other programs.
Creating and Using Libraries Creating Shared Libraries Thereafter, any programs that load libdep.sl — either explicitly with shl_load or implicitly with the dynamic loader when the program begins execution — also automatically load the dependent libraries libcurses.sl and libcustom.sl.
Creating and Using Libraries Creating Shared Libraries if the library has not been visited then mark the library as visited. if the library has a dependency list then traverse the list in reverse order. Place the library at the head of the load list. Shown below are the steps taken to form the load graph when libP is loaded: 1. mark P, traverse Q 2. mark Q, traverse B 3. mark B, load B 4. load Q 5. traverse D 6. mark D, traverse B 7. B is already marked, so skip B, traverse Q 8.
Creating and Using Libraries Creating Shared Libraries 3. mark A, load A 4. mark D, load D 5. mark Q, load Q 6. traverse D 7. D is already marked, so skip D 8. traverse Q 9. Q is already marked, so skip Q 10. traverse Q 11. Q is already marked, so skip Q 12. traverse B 13. mark B, load B 14. traverse B 15.
Creating and Using Libraries Creating Shared Libraries libP → libA → libD → libQ → libB → Updating a Shared Library The ld command cannot replace or delete object modules in a shared library. Therefore, to update a shared library, you must relink the library with all the object files you want the library to include. For example, suppose you fix some routines in length.c (from the previous section) that were giving incorrect results. To update the libunits.
Creating and Using Libraries Creating Shared Libraries Prior to the HP-UX 9.0 release, moving a shared library caused any programs that were linked with the library to fail when they tried to load the library. Prior to 9.0, you were required to relink all applications that used the library if the library was moved to a different directory. Beginning with the HP-UX 9.0 release, a program can search a list of directories at run time for any required libraries.
Creating and Using Libraries Creating Shared Libraries You may be surprised to find that a shared library exports many more symbols than necessary for code that uses the library. These extra symbols add to the size of the library's symbol table and can even degrade performance (since the dynamic loader has to search a larger-than-necessary number of symbols). One possible way to improve shared library performance is to export only those symbols that need exporting from a library.
Creating and Using Libraries Creating Shared Libraries b.o A huge module, but contains only error routines that are seldom called. c.o Contains routines that are called frequently by a.o, and calls routines in a.o frequently. If you create a shared library using the following command line, the modules will be inserted into the library in alphabetical order: $ ld -b -o libabc.sl *.o The potential problem with this ordering is that the routines in a.o and c.o are spaced far apart in the library.
Creating and Using Libraries Creating Shared Libraries y.o d.o Notice that d.o is now closer to x.o and y.o, which call it. However, this is still not the best information to use because a.o and b.o are separated from x.o and y.o by the module e.o, which is not called by any modules. The actual optimal order might be more like this: a.o b.o x.o y.o d.o e.o Again, the use of lorder and tsort is not perfect, but it may give you leads on how to best order the modules.
Creating and Using Libraries Version Control with Shared Libraries Version Control with Shared Libraries HP-UX provides two ways to support incompatible versions of shared library routines. “Library-Level Versioning” describes how you create multiple versions of a shared library. “Intra-Library Versioning” describes how a single shared library can have multiple versions of an object module. Library-level versioning is recommended over intra-library versioning. NOTE Beginning with HP-UX Release 11.
Creating and Using Libraries Version Control with Shared Libraries • As a general rule, when an exported function is changed such that calls to the function from previously compiled object files should not resolve to the new version, the change is incompatible. If the new version can be used as a wholesale replacement for the old version, the change is compatible. • For exported data, any change in either the initial value or the size represents an incompatible change.
Creating and Using Libraries Version Control with Shared Libraries 1. Name the first version of your shared library with an extension of .0 (that's the number zero), for example libA.0. Use the +h option to designate the internal name of the library, for example, libA.0: ld -b *.o -o libA.0 +h libA.0 Creates the shared library libA.0. 2. Since the linker still looks for libraries ending in .sl with the -l option, create a symbolic link from the usual name of the library ending in .
Creating and Using Libraries Version Control with Shared Libraries When you run a program that uses shared libraries and was linked before HP-UX 10.0, the dynamic loader first attempts to open the shared library ending in .0. If it cannot find that library, it attempts to open the library ending in .sl. The +h Option and Internal Names The +h option gives a library an internal name for library-level versioning.
Creating and Using Libraries Version Control with Shared Libraries Figure 5-5 During a link, the linker records the file name of the opened library in the shared library list of the output file. However, if the shared library is a file system link to the actual library, the linker does not record the name of the library the file system link points to. Rather it records the name of the file system link. For example, if /tmp/libmine.sl is a file system link to /X/libapp.
Creating and Using Libraries Version Control with Shared Libraries Figure 5-6 With these links in place, the loader will load /X/libapp.0 when running the a.out file created above. New applications will link and run with /X/libapp.1. NOTE Renaming the old version of the .0 version library only works for 32-bit mode. For 64-bit mode programs, the dynamic loader only loads the library recorded in the dynamic load table.
Creating and Using Libraries Version Control with Shared Libraries • “Shared Library Dependencies and Version Control” • “Adding New Versions to a Shared Library” • “Specifying a Version Date” The Version Number Compiler Directive With intra-library versioning, you assign a version number to any module in a shared library. The version number applies to all global symbols defined in the module's source file. The version number is a date, specified with a compiler directive in the source file.
Creating and Using Libraries Version Control with Shared Libraries If a shared library lists a second shared library as a dependency, dld.sl will generate an error if the second shared library has a version number which is older than the version number recorded with the dependency. This means that the first library was built using a more recent version of the second library than the version that dld.sl currently finds.
Creating and Using Libraries Version Control with Shared Libraries Specifying a Version Date When adding modules to a library for a particular release of the library, it is best to give all modules the same version date. For example, if you complete file1.o on 04/93, file2.o on 05/93, and file3.o on 07/93, it would be best to give all the modules the same version date, say 07/93. The reason for doing this is best illustrated with an example.
Creating and Using Libraries Switching from Archive to Shared Libraries Switching from Archive to Shared Libraries There are cases where a program may behave differently when linked with shared libraries than when linked with archive libraries. These are the result of subtle differences in the algorithms the linker uses to resolve symbols and combine object modules. This section covers these considerations. (See also “Caution When Mixing Shared and Archive Libraries”.
Creating and Using Libraries Switching from Archive to Shared Libraries More commonly, programmers may take advantage of undocumented linker behavior to minimize the size of routines copied into the a.out files from archive libraries. This is no longer necessary if all libraries are shared.
Creating and Using Libraries Switching from Archive to Shared Libraries rearrange data in shared libraries, this is no longer guaranteed. Another example is a function that assumes variables it declares statically (for example, C static variables) reside below the reserved symbol _end in memory (see end(3)). In general, it is a bad idea to depend on the relative addresses of global variables, because the linker may move them around.
Creating and Using Libraries Switching from Archive to Shared Libraries Debugger Limitations Shared libraries can be debugged just like archive libraries with few exceptions. For details on debugging shared libraries, refer to the HP/DDE Debugger User's Guide or the HP-UX Symbolic Debugger User's Guide. Using the chroot Command with Shared Libraries Some users may use the chroot super-user command when developing and using shared libraries.
Creating and Using Libraries Summary of HP-UX Libraries Summary of HP-UX Libraries What libraries your system has depends on what components were purchased. For example, if you didn't purchase Starbase Display List, you won't have the Starbase Display List library on your system. HP-UX library routines are described in detail in sections 2 and 3 of the HP-UX Reference. Routines in section 2 are known as system calls, because they provide low-level system services; they are found in libc.
Creating and Using Libraries Summary of HP-UX Libraries (2) These functions are known as system calls. They provide low-level access to operating system services, such as opening files, setting up signal handlers, and process control. These routines are located in libc. (3C) These are standard C library routines located in libc. (3S) These functions comprise the Standard input/output routines (see stdio(3S)). They are located in libc. (3M) These functions comprise the Math library.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Caution When Mixing Shared and Archive Libraries Mixing shared and archive libraries in an application is not recommended and should be avoided. That is, an application should use only shared libraries or only archive libraries. Mixing shared and archive libraries can lead to unsatisfied symbols, hidden definitions, and duplicate definitions and cause an application to abort or exhibit incorrect behavior at run time.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-8 Now link the main with the libraries and create the executable a.out: $ cc main.o lib12.a lib3.sl . Link the program Figure 5-9 When you run a.out, it runs correctly.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-10 Compile the new f3() and rebuild the shared library lib3.sl: $ cc -c +z f3.c .$ ld -b -o lib3.sl f3.o Compile to relocatable code Create a new shared library. Figure 5-11 Problem Here's where the problem can occur. If you do not relink the application, main.o, and just run a.out with the new version of lib3.sl, the program will abort since f2() is not available in the application.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-12 $ a.out /usr/lib/dld.sl: Unresolved symbol: f2 (code) from /users/steve/dev/lib3.sl Abort(coredump) Example 2: Using shl_load(3X) This example (in 32-bit and 64-bit +compat mode shows how mixing archive libraries and shared libraries using shl_load(3X) can lead to unsatisfied symbols and cause a program to abort.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-13 Next suppose you put f3.o into the shared library lib3.sl and f1.o and f2.o into the archive library lib12.a: $ ld -b -o lib3.sl f3.o $ ar qvc lib12.a f1.o f2.o Create a shared library. Create an archive library. Figure 5-14 Now link the main with the archive library and create the executable a.out: $ cc main.o lib12.a -ldld 168 Link the program.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-15 When you run a.out, it runs correctly. Now suppose you need to modify f3() to call f2(): Figure 5-16 Problem Here is where a problem can be introduced. If you compile the new f3() and rebuild the shared library lib3.sl without specifying the dependency on a shared library containing f2(), calls to f3() will abort. $ cc -c +z f3.c $ ld -b -o lib3.sl f3.o Chapter 5 Compile to position-independent code.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-17 Here's where the problem shows up. If you do not relink the application, main.o, and just run a.out with the new version of lib3.sl, the program will abort since f2() is not available in the program's address space. The reference to f2() from f3() remains unsatisfied, generating the 32-bit error message: Figure 5-18 $ a.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Example 3: Hidden Definitions This example shows how mixing archive libraries and shared libraries can lead to multiple definitions in the application and unexpected results. If one of the definitions happens to be a data symbol, the results can be catastrophic. If any of the definitions are code symbols, different versions of the same routine could end up being used in the application. This could lead to incompatibilities.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-19 Next suppose you put f3.o into the shared library lib3.sl and f1.o and f2.o into the archive library lib12.a. Also put f1.o and f2.o into the shared library lib12.sl: $ ld -b -o lib3.sl f3.o $ ld -b -o lib12.sl f1.o f2.o $ ar qvc lib12.a f1.o f2.o Create a shared library. Create a shared library. Create an archive library. Figure 5-20 Now link the main with the archive library lib12.a and the shared library lib3.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-21 When you run a.out, it runs correctly. Now suppose you need to modify f3() to call f2(): Figure 5-22 Compile the new f3() and rebuild the shared library lib3.sl, including the new dependency on f2() in lib12.sl: $ cc -c +z f3.c Compile to PIC. $ ld -b -o lib3.sl f3.o -L . -l12 Create library with dependency.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-23 Problem Here's where the problem can occur in 32-bit and 64-bit +compat modes. If you do not relink the application, main.o, and just run a.out with the new version of lib3.sl, the program will execute successfully, but it will execute two different versions of f2(). main() calls f2() in the program file a.out and f3() calls f2() in lib12.sl.
Creating and Using Libraries Caution When Mixing Shared and Archive Libraries Figure 5-24 Summary of Mixing Shared and Archive Libraries Applications that depend on shared libraries should not use archive libraries to satisfy symbol imports in a shared library. This suggests that only a shared version of libc should be used in applications using shared libraries.
Creating and Using Libraries Using Shared Libraries in 64-bit mode Using Shared Libraries in 64-bit mode In the HP-UX 11.00 release, HP provides an industry-standard linker toolset for programs linked in 64-bit mode. The new toolset consists of a linker, dynamic loader, object file class library, and an object file tool collection. Although compatibility between the current and previous toolset is an important goal, some differences exist between these toolsets.
Creating and Using Libraries Using Shared Libraries in 64-bit mode • If the dependent library’s internal name contains a relative path, the internal name is inserted at the end of the path where the shared library is found at link time, replacing the library’s filename in the DT_HP_NEEDED entry. If the library is specified with -l, the dynamic path bit is set to TRUE.
Creating and Using Libraries Using Shared Libraries in 64-bit mode LD_LIBRARY_PATH and the SHLIB_PATH environment variable to add directories to the run time search path for shared libraries, unless the ld +noenvvar option is set. In the 32-bit mode of the linker toolset (selected by the +compat option), the linker enables run-time dynamic path searching when you link a program with the -llibrary and +b path_name options. Or, you can use the -llibrary option with the +s path_name option.
Creating and Using Libraries Using Shared Libraries in 64-bit mode The 32-bit mode linker does not remember the definition of a procedure in a shared library unless it was referenced in previously scanned object files. If you have function names that are duplicated in a shared and archive library, the 64-bit mode linker may reference a different version of a procedure than is referenced by the 32-bit mode linker. This change can lead to unexpected results. For example, given these source files: sharedlib.
Creating and Using Libraries Using Shared Libraries in 64-bit mode At link time, there is an outstanding unsatisfied symbol for afunc() when libB is found. The exported symbol for afunc() is not remembered after libA.sl is scanned. At run time, the afunc() symbol that is called is the one that came from the archive library, which resides in test1. The 64-bit mode linker toolset produces: $ test1 in SHARED library procedure `afunc' The 64-bit mode linker remembers the symbol for afunc(), and archive.
Creating and Using Libraries Using Shared Libraries in 64-bit mode If these files are compiled and linked as: cc cc ld cc -c main.c -c +z lib1.c lib2.c -b lib1.o lib2.o -o liba.sl main.o liba.sl -o test2 Using the 32-bit mode linker, test2 executes without error. The module in liba.sl created from lib2.o is determined to be unreachable during execution, so the global symbol for unsat (in lib2.o) is not bound.
Creating and Using Libraries Using Shared Libraries in 64-bit mode cc cc ld ld cc -c main.c -c +z a.c b.c -b a.o -o libA.sl -b b.o -o libB.sl main.o libA.sl libB.sl -o test3 The 32-bit mode linker toolset produces: $ test3 object is 1 The 32-bit mode linker toolset defines the object global variable in libA.sl as a storage export symbol. The dynamic loader, when searching for a definition of object to satisfy the import request in libA.sl, does not stop with the storage export in that library.
Creating and Using Libraries Using Shared Libraries in 64-bit mode If you have data or function names that are duplicated in different shared libraries, the 64-bit mode linker may link in a different version of a procedure than the current release. This can lead to unexpected results. NOTE Figure 5-25 shows an example program with shared libraries (the shaded boxes are libA.
Creating and Using Libraries Using Shared Libraries in 64-bit mode 1. First, the dependent shared libraries for libA are built. (Other libraries are also built.) ld ld ld ld ld -b -b -b -b -b libD.o libE.o libF.o libB.o libC.o -o -o -o -o -o libD.sl libE.sl libF.sl libB.sl libC.sl libA dependent shared library libA dependent shared library libA dependent shared library 2. Next, libA.o is linked to its dependent libraries and libA.sl is built. ld -b libA.o -lD -lE -lF -o libA.sl 3. Finally, main.
Creating and Using Libraries Using Shared Libraries in 64-bit mode If you use mixed mode shared libraries, you get behavior based on the first mode encountered. At runtime, the dynamic loader does a depth-first search if the dependent libraries at the highest level are compatibility mode libraries. Otherwise, it does breadth-first searching. This applies to all dependent libraries of the incomplete executable file.
Creating and Using Libraries Using Shared Libraries in 64-bit mode mode library. The loader uses 64-bit mode search techniques on all libraries except for libfile3.sl, in which case it uses 32-mode search techniques. NOTE Embedded path inheritance is not applied to any mixed mode shared library and its descendents. It is only applied to libraries in an a.out linked with +compat. Embedded path inheritance does not apply to a breadth-first search mechanism.
Creating and Using Libraries Using Shared Libraries in 64-bit mode Library Example: Creating a 64-bit Standard Mode Shared Library The following example builds a standard mode library. ld -b file1.o -o libfile1.sl +h libfile1.1 ld -b file2.o -o libfile2.sl +h ./libfile2.1 ld -b file3.o -o libfile3.sl +h /var/tmp/libfile3.1 ld -b file4.o -o libfile4.sl ld -b file3a.o -o libfile3a.sl -L. -lfile1 -lfile3 +h libfile3a.1 ld -b file2a.o -o libfile2a.sl libfile2.sl ./libfile4.sl +b /var/tmp elfdump -L libfile3a.
Creating and Using Libraries Using Shared Libraries in 64-bit mode ld -b file1.o -o libfile1.sl +h libfile1.1 ld -b file2.o -o libfile2.sl +h libfile2.1 -L. -lfile1 ld main.o -L. -lfile2 -lc # # # # # # # move dependent lib so dld can’t find it dld won’t find library because we didn’t set the environment variable LD_LIBRARY_PATH and SHLIB_PATH By default, dld will look at the environment variables LD_LIBRARY_PATH and SHLIB_PATH when doing dynamic path searching unless +noenvvar is specified mv libfile2.
Creating and Using Libraries Using Shared Libraries in 64-bit mode Library Example: Using 64-bit Mode Compatibility and Standard Shared Libraries This example mixes compatibility and standard mode shared libraries. It uses 32-it-style linking and loading for the compatibility mode libraries and 64-bit-style linking and loading for standard mode libraries. # build standard mode dlls # libfile1.sl is a dependent of libfile2 ld -b file1.o -o libfile1.sl +h libfile1.1 mkdir TMP ld -b +b $pwd/TMP file2.
Creating and Using Libraries Using Shared Libraries in 64-bit mode +-->lib2a.sl | +-->lib2.sl-->lib2b.sl | lib1.sl-->lib3.sl-->lib3a.sl-->lib3aa.sl | | | +-->lib3b.sl +-->lib4.sl In breadth-first searching, the load order is siblings before children: lib1.sl->lib2.sl->lib3.sl->lib4.sl->lib2a.sl->lib2b.sl->lib3a.sl>lib3b.sl->lib3aa.sl In depth-first searching, the load order is children before siblings: lib1.sl->lib2.sl->lib2a.sl->lib2b.sl->lib3.sl->lib3a.sl->lib3aa.s l->lib3b.sl->lib4.
Creating and Using Libraries Using Shared Libraries in 64-bit mode Library Example: Linking to Libraries with +b path_list in 64-bit Mode. In this example, the program main calls a shared library routine in libbar.sl. The routine in libbar.sl in turn calls a routine in the shared library libme.sl. The +b linker option indicates the search path for libme.sl when linking libbar.sl. (You use +b path_list with libraries specified with the -l library or -l:library options.) cc ld ld mv ld -c +DD64 me.c -b me.
Creating and Using Libraries Using Shared Libraries in 64-bit mode 3. ./libbar.sl (./libbar.sl) found 4. LD_LIBRARY_PATH to find libme.sl not found 5. SHLIB_PATH to find libme.sl not found 6. /var/tmp/libme.sl found 7. LD_LIBRARY_PATH to find libc.sl not found 8. SHLIB_PATH to find libc.sl not found 9. ./libc.sl not found 10. /usr/lib/pa20_64/libc.sl found Library Example: Linking to Libraries with +b path_list in 32-bit Mode.
Creating and Using Libraries Using Shared Libraries in 64-bit mode The linker does not look in /var/tmp to find shared libraries because in 32-bit mode the directories specified by +b pathname are only searched at run time. Because libme.sl is specified with the -l option, it is subject to dynamic path searching. At run time, the dynamic loader looks for shared libraries used by main in the following order: 1. ./libbar.sl found 2. /var/tmp/libme.sl found 3. ./libc.sl not found 4. /usr/lib/libc.
Creating and Using Libraries Using Shared Libraries in 64-bit mode 194 Chapter 5
Shared Library Management Routines 6 Shared Library Management Routines You can explicitly load and use shared libraries from your program. The linker toolset provides two families of load routines, shl_load and dlopen. The shl_load routines support the shared library mechanisms provided in previous version of HP-UX. The dlopen routines (available for 64-bit mode only) use Unix SVR4 compatible mechanism for library management. NOTE Both families of routines support initializer and terminator routines.
Shared Library Management Routines Shared Library Management Routine Summaries Shared Library Management Routine Summaries The following sections introduce the shared library management routines available for the HP-UX 11.00 release. The shl_load Routine Summary The shl_load family of shared library management routines are available for both the 32-bit and 64-bit mode linker. All of the shl_load family routines use the same user interface in 32-bit and 64-bit mode linking.
Shared Library Management Routines Shared Library Management Routine Summaries Routine Action shl_definesym Adds a new symbol to the global shared library symbol table. shl_getsymbols Returns a list of symbols in a shared library. shl_unload and cxxshl_load Unload a shared library and a C++ shared library, respectively. They have the same syntax. Except for shl_get and shl_gethandle, all these routines are thread safe. These routines are described in the shl_load(3x) man page.
Shared Library Management Routines Shared Library Management Routine Summaries All the dlopen routines are thread-safe. These routines are described in the dl*(3C) man pages. Related Files and Commands These commands and files provide more information about using shared library management routines. Command/File Action a.out(4) Executable file from assembler, compiler, and linker output. cc(1) Command to invoke the HP-UX C compiler. exec(2) System loader. ld(1) Command to invoke the linker.
Shared Library Management Routines Shared Library Header Files Shared Library Header Files The shl_load family of shared library management routines use some special data types (structures) and constants defined in the C-language header file /usr/include/dl.h. When using these functions from C programs, be sure to include dl.h: #include
If you are using HP C++, also include /opt/CC/include/CC/cxxdl.h. Similarly, if you are using the dlopen family of routines, include /usr/include/dlfcn.h.Shared Library Management Routines Using Shared Libraries with cc and ld Options Using Shared Libraries with cc and ld Options In 32-bit mode, you can access the shl_load family of routines specifying the -ldld option on the cc(1) or ld(1) command line. In 64-bit mode, you can access the shl_load and dlopen routines by specifying either -ldld or -ldl on the command line.
Shared Library Management Routines Initializers for Shared Libraries Initializers for Shared Libraries A shared library can have an initialization routine—known as an initializer—that is called when the load module (a shared library or executable) is loaded (initializer) or explicitly unloaded (terminator). Typically, an initializer is used to initialize a shared library's data when the library is loaded. When a program begins execution its initializers are called before any other user code is executed.
Shared Library Management Routines Initializers for Shared Libraries $ ld -b foo.o +I my_10x_init -o libfoo.sl #include
void my_10x_init(shl_t handle, int loading) { /* handle is the shl_load API handle for the shared library being initialized. */ /* loading is non-zero at startup and zero at termination. */ if (loading) { ... do some initializations ... } else { ... do some clean up ... } } NOTE Unlike 32-bit mode, the 64-bit HP-UX 10.Shared Library Management Routines Initializers for Shared Libraries The ld command supports the +fini option to specify theterminator. 32-bit Mode Initializers The 32-bit mode linker supports HP-UX 10.X style initializers. This section contains the following topics: • Using HP-UX 10.X Style Initializers • “Declaring the Initializer with the +I Option” • “Initializer Syntax” • “Example: An Initializer for Each Library” • “Example: A Common Initializer for Multiple Libraries” Using HP-UX 10.
Shared Library Management Routines Initializers for Shared Libraries For example, to create a shared library named libfoo.sl that uses an initializer named init_foo, use this linker command line: $ ld -b -o libfoo.sl libfoo.o +I init_foo Order of Execution of Multiple Initializers . Multiple initializers are executed in the same order that they appear on the command line; they are unloaded in reverse order.
Shared Library Management Routines Initializers for Shared Libraries Accessing Initializers' Addresses . Prior to the HP-UX 10.0 release, initializer's addresses could be accessed through the initializer field of the shared library descriptor which is returned from a call to shl_get(). To support multiple initializers, the shl_getsymbols() routine has been enhanced to support the return of the initializer's address.
Shared Library Management Routines Initializers for Shared Libraries C Source for libfoo.sl #include #include /* * This is the local initializer that is called when the libfoo.sl * is loaded and unloaded: */ void init_foo(shl_t hndl, int loading) { if (loading) printf(“libfoo loaded\n”); else printf(“libfoo unloaded\n”); } float in_to_cm(float in) centimeters */ { return (in * 2.54); } float gal_to_l(float gal) */ { return (gal * 3.79); } float oz_to_g(float oz) { return (oz * 28.
Shared Library Management Routines Initializers for Shared Libraries if (shl_findsym(&hndl_foo, “in_to_cm”, TYPE_PROCEDURE, (void *) &in_to_cm)) perror(“shl_findsym: error finding in_to_cm”), exit(1); if (shl_findsym(&hndl_foo, “gal_to_l”, TYPE_PROCEDURE, (void *) &gal_to_l)) perror(“shl_findsym: error finding gal_to_l”), exit(1); if (shl_findsym(&hndl_foo, “oz_to_g”, TYPE_PROCEDURE, (void *) &oz_to_g)) perror(“shl_findsym: errror finding oz_to_g”), exit(1); /* * Call routines from libfoo.sl: */ printf(“1.
Shared Library Management Routines Initializers for Shared Libraries C Source for _INITIALIZER (file init.c) #include
Shared Library Management Routines Initializers for Shared Libraries C Source for libtwo.sl #include void load() /* called after libtwo.sl loaded */ { printf(“libtwo.sl loaded\n”); } void unload() /* called after libtwo.sl unloaded */ { printf(“libtwo.
Shared Library Management Routines Initializers for Shared Libraries TYPE_PROCEDURE, (void *) &oz_to_g)) perror(“shl_findsym: errror finding oz_to_g”), exit(1); /* * Load libtwo.sl and find the required symbols: */ if ((hndl_two = shl_load(“libtwo.sl”, BIND_IMMEDIATE, 0)) == NULL) perror(“shl_load: error loading libtwo.
Shared Library Management Routines Initializers for Shared Libraries • Init/Fini style: see “Init/Fini Style Initializers” and the topics described in this section: • “Init and Fini Usage Example” • “Ordering Within an Executable or Shared Library” • “Ordering Among Executables and Shared Libraries” Init and Fini Usage Example This example consists of three shared libraries lib1.sl, lib2.sl and lib3.sl. The lib1.sl depends on lib3.sl. The main program (a.out) depends on lib1.sl and lib2.sl.
Shared Library Management Routines Initializers for Shared Libraries C source for lib3.sl (file lib3.c): lib3() { printf(“lib3\n”); } #pragma init “lib3_init” void lib3_init() { printf(“lib3_init\n”); } #pragma fini “lib3_fini” void lib3_fini() { printf(“lib3_fini\n”); } Commands used to build these libraries: $ cc +DD64 lib1.c lib2.c lib3.c main.c -c; $ ld -b lib3.o -o lib3.sl; $ ld -b +init lib2_init +fini lib2_fini lib2.o -o lib2.sl; $ ld -b +init lib1_init +fini lib1_fini lib1.o ./lib3.sl -o \ lib1.
Shared Library Management Routines Initializers for Shared Libraries • HP-UX 10.X style initializers are called in forward order of the +I options specified on the link line when loading a shared library. They are then called in reverse order when unloading the library. • HP-UX 10.X style initializers are called after inits and before finis. • Any inits or finis in archive (.a) files are called only if the .o which contains it is used during the link. Use the linker -v option to determine which .
Shared Library Management Routines Initializers for Shared Libraries • When loading, the inits and HP-UX 10.X initializers of any dependent libraries are called before the ones in the current library. • When unloading, the finis and HP-UX 10.X initializers of any dependent libraries are called after the finis of the current library. • If a shared library is itself a dependent of one of its dependents (a “circular” dependency), no ordering between them is guaranteed. For example, given three libraries: libA.
Shared Library Management Routines The shl_load Shared Library Management Routines The shl_load Shared Library Management Routines This section describes the shl_load family of shared library management routines. NOTE You can use these routines in both 32-bit and 64-bit mode. Support for these routines may be discontinues in a future 64-bit HP-UX release. If you use these routines in 64-bit mode, consider converting your programs to the dl* family of shared library management routines.
Shared Library Management Routines The shl_load Shared Library Management Routines In addition to the above values, the flags parameter can be ORed with the following values: BIND_NONFATAL Allow binding of unresolved symbols. BIND_VERBOSE Make dynamic loader display verbose messages when binding symbols. BIND_FIRST Insert the loaded library before all others in the current link order. DYNAMIC_PATH Causes the dynamic loader to perform dynamic library searching when loading the library.
Shared Library Management Routines The shl_load Shared Library Management Routines Causes the dependent libraries to be loaded breadth first. By default, the 64-bit mode shl_load loads dependent libraries depth-first. These flags are discussed in detail in“shl_load Example”. address Specifies the virtual address at which to attach the library. Set this parameter to 0 (zero) to tell the system to choose the best location.
Shared Library Management Routines The shl_load Shared Library Management Routines However, programs are not restricted to using shared libraries only in that situation. For example, rather than linking with any required libraries, a program could explicitly load libraries as they are needed. One possible reason for doing this is to minimize virtual memory overhead.
Shared Library Management Routines The shl_load Shared Library Management Routines Once a library is explicitly loaded, use the shl_findsym routine to get pointers to functions or data contained in the library; then call or reference them through the pointers. This is described in detail in“The shl_findsym Routine”. shl_load Example The following example shows the source for a function named load_lib that explicitly loads a library specified by the user.
Shared Library Management Routines The shl_load Shared Library Management Routines } /* * Dynamically load the shared library using BIND_IMMEDIATE binding: */ lib_handle = shl_load( lib_path, BIND_IMMEDIATE, 0); if (lib_handle == NULL) perror(“shl_load: error loading library”), exit(1); return lib_handle; } BIND_NONFATAL Modifier If you load a shared library with the BIND_IMMEDIATE flag and the library contains unresolved symbols, the load fails and sets errno to ENOSYM.
Shared Library Management Routines The shl_load Shared Library Management Routines BIND_FIRST is typically used when you want to make the symbols in a particular library more visible than the symbols of the same name in other libraries. Compare this with the default behavior, which is to append loaded libraries to the link order.
Shared Library Management Routines The shl_load Shared Library Management Routines BIND_FIRST | BIND_TOGETHER causes the library being loaded and its dependent libraries to be bound all at the same time, thereby resolving interdependencies. If you are not using BIND_FIRST, libraries are bound together by default so this option has no effect. BIND_BREADTH_FIRST Modifier 64-bit mode only: This flag causes the dependent libraries to be loaded breadth first.
Shared Library Management Routines The shl_load Shared Library Management Routines Syntax int shl_findsym( shl_t * handle, const char * sym, short type, void * value ) Parameters handle A pointer to a shared library handle of the library to search for the symbol name sym. This handle could be obtained from the shl_get routine (described in the “The shl_get and shl_get_r Routines”). handle can also point to: NULL If a pointer to NULL is specified, shl_findsym searches all loaded libraries for sym.
Shared Library Management Routines The shl_load Shared Library Management Routines Look for a symbol in the data segment (for example, variables). TYPE_UNDEFINED Look for any symbol. TYPE_STORAGE 32-bit mode only. TYPE_TSTORAGE 32-bit mode only. value A pointer in which shl_findsym stores the address of sym, if found. Return Value If successful, shl_findsym returns an integer (int) value zero. If shl_findsym cannot find sym, it returns −1 and sets errno to zero.
Shared Library Management Routines The shl_load Shared Library Management Routines 1. declare a pointer to a data structure of the same type as the data structure to access in the library 2. using shl_findsym with the type parameter set to TYPE_DATA, find the symbol in the shared library and assign its address to the pointer declared in Step 1 3. access the data through the pointer obtained in Step 2 shl_findsym Example Suppose you have a set of libraries that output to various graphics devices.
Shared Library Management Routines The shl_load Shared Library Management Routines shl_t load_lib(int argc, char * argv[]); main(int argc, char * argv[]) { shl_t lib_handle; /* handle of shared library */ int (*gopen)(void); /* opens the graphics device */ int (*gclose)(void); /* closes the graphics device */ int (*move2d)(int, int); /* moves to specified x,y location */ int (*draw2d)(int, int); /* draw line to specified x,y location*/ int *maxX; /* maximum X pixel on device */ int *maxY; /* maximum Y pixe
Shared Library Management Routines The shl_load Shared Library Management Routines Syntax int shl_get( int index, struct shl_descriptor **desc ) Parameters index Specifies an ordinal number of the shared library in the process. For libraries loaded implicitly (at startup time), index is the ordinal number of the library as it appeared on the command line. For example, if libc was the first library specified on the ld command line, then libc has an index of 1.
Shared Library Management Routines The shl_load Shared Library Management Routines dend The end address (unsigned long) of the shared library bss segment. The data and bss segments together form a contiguous memory block starting at dstart and ending at dend. handle The shared library's handle (type shl_t). filename A character array containing the library's path name as specified at link time or at explicit load time.
Shared Library Management Routines The shl_load Shared Library Management Routines Description To obtain information on currently loaded libraries, use the shl_get function. If you are programming in a threaded environment, use the thread-safe version shl_get_r which is the same as shl_get in all other respects. (See Programming with Threads on HP-UX for more information about threads.) Other than obtaining interesting information, this routine is of little use to most programmers.
Shared Library Management Routines The shl_load Shared Library Management Routines The shl_gethandle and shl_gethandle_r Routines Returns descriptor information about a loaded shared library. Syntax int shl_gethandle( shl_t handle, struct shl_descriptor **desc ) Parameters handle The handle of the shared library you want information about. This handle is the same as that returned by shl_load. desc Points to shared library descriptor information — the same information returned by the shl_get routine.
Shared Library Management Routines The shl_load Shared Library Management Routines int show_lib_info(shl_t libH) { struct shl_descriptor *desc; if (shl_gethandle(libH, &desc) == -1) { fprintf(stderr, "Invalid library handle.
Shared Library Management Routines The shl_load Shared Library Management Routines Return Value If successful, shl_definesym returns 0. Otherwise, it returns −1 and sets errno accordingly. See shl_definesym(3X) for details. Description The shl_definesym function allows you to add a new symbol to the global shared library symbol table. Use of this routine will be unnecessary for most programmers.
Shared Library Management Routines The shl_load Shared Library Management Routines Parameters handle The handle of the shared library whose symbols you want to retrieve. If handle is NULL, shl_getsymbols returns symbols that were defined with the shl_definesym routine. type Defines the type of symbol to retrieve. It must be one of the following values, which are defined as constants in
: TYPE_PROCEDURE Retrieve only function or procedure symbols.Shared Library Management Routines The shl_load Shared Library Management Routines One of the following modifiers can be ORed with both the EXPORT_SYMBOLS and the INITIALIZERS flags: NO_VALUES Do not calculate the value field of the shl_symbol structure for symbols. The value field has an undefined value.
Shared Library Management Routines The shl_load Shared Library Management Routines ENOSYM Some symbol required by the shared library could not be found. EINVAL The specified handle is invalid. ENOMEM memfunc failed to allocate the requested memory. The shl_symbol Structure The members of the shl_symbol structure are defined as follows: name Contains the name of a symbol. type Contains the symbol's type: TYPE_PROCEDURE, TYPE_DATA, or TYPE_STORAGE.
Shared Library Management Routines The shl_load Shared Library Management Routines type The type of symbol you want to display. This is the same as the type parameter to shl_getsymbols and can have these values: TYPE_PROCEDURE, TYPE_DATA, or TYPE_UNDEFINED. If it is TYPE_UNDEFINED, show_symbols displays the type of each symbol. flags This is the same as the flags parameter. It can have the value EXPORT_SYMBOLS or IMPORT_SYMBOLS. In addition, it can be ORed with NO_VALUES or GLOBAL_VALUES.
Shared Library Management Routines The shl_load Shared Library Management Routines */ } free(orig_symbols); malloc */ return num_symbols; */ } /* free memory allocated by /* return the number of symbols The following example shows the source for a program named show_all.c that calls show_symbols to show all imported and exported symbols for every loaded shared library. It uses shl_get to get the library handles of all loaded libraries. show_all — Use show_symbols to Show All Symbols #include
Shared Library Management Routines The shl_load Shared Library Management Routines printf shl_get shl_getsymbols __d_trap TOTAL SYMBOLS: 9 Exports: environ errno _SYSTEM_ID __dld_loc _FPU_MODEL _end _environ __d_trap main TOTAL SYMBOLS: 9 [/usr/lib/libc.
Shared Library Management Routines The shl_load Shared Library Management Routines Description To unload a shared library, use the shl_unload function. One reason to do this is to free up the private copy of shared library data and swap space allocated when the library was loaded with shl_load. (This is done automatically when a process exits.) Another reason for doing this occurs if a program needs to replace a shared library.
Shared Library Management Routines The dlopen Shared Library Management Routines The dlopen Shared Library Management Routines This section describes the dl* family of shared library management routines. NOTE Use these routines in 64-bit mode only The dlopen Routine Opens a shared library. Syntax void *dlopen(const char *file, int mode); Parameters Parm file Definition Used to construct a pathname to the shared library file.
Shared Library Management Routines The dlopen Shared Library Management Routines Parm flags Definition Mode Definition RTLD_LAZY Under this mode, only references to data symbols are relocated when the library t is loaded. References to functions are not relocated until a given function is invoked for the first time. This mode should result in better performance, since a process may not reference all of the functions in any given shared object.
Shared Library Management Routines The dlopen Shared Library Management Routines More detailed diagnostic information is available through dlerror. Description dlopen is one of a family of routines that give the user direct access to the dynamic linking facilities. dlopen makes a shared library specified by a file available to a running process. A shared library may specify other objects that it “needs” in order to execute properly. These dependencies are specified by DT_NEEDED entries in the.
Shared Library Management Routines The dlopen Shared Library Management Routines To determine the scope of visibility for the symbols loaded with a dlopen invocation, bitwise OR the mode parameter with one of the following values: RTLD_GLOBAL or RTLD_LOCAL. If neither RTLD_GLOBAL nor RTLD_LOCAL are specified, the default is RTLD_LOCAL. If a file is specified in multiple dlopen invocations, mode is interpreted at each invocation.
Shared Library Management Routines The dlopen Shared Library Management Routines The symbols introduced by dlopen operations and available through dlsym are those which are “exported” as symbols of global scope by the shared library. For shared libraries, such symbols are typically those that were specified in (for example) C source code as having extern linkage. For a.
Shared Library Management Routines The dlopen Shared Library Management Routines Description dlerror returns a null-terminated character string (with no trailing newline character) that describes the last error that occurred during dynamic linking processing. If no dynamic linking errors have occurred since the last invocation of dlerror, it returns NULL. Thus, invoking dlerror a second time, immediately following a prior invocation, results in NULL being returned.
Shared Library Management Routines The dlopen Shared Library Management Routines Parameters Parameter Definition handle Either the value returned by a call to dlopen or the special flag RTLD_NEXT. In the former case, the corresponding shared library must not have been closed using dlclose. name The symbol's name as a character string.
Shared Library Management Routines The dlopen Shared Library Management Routines necessary information, and use dlsym with RTLD_NEXT to find the “real” malloc, which would perform the actual memory allocation. Of course, this “real” malloc could be another user-defined interface that added its own value and then used RTLD_NEXT to find the system malloc. Examples The following example shows how to use dlopen and dlsym to access either function or data objects.
Shared Library Management Routines The dlopen Shared Library Management Routines The dlget Routine Retrieves information about a loaded module (program or shared library). Syntax void *dlget(unsigned int index, struct load_module_desc *desc, size_t desc_size); Parameters Parameter Definition index Specifies the requested shared library by its placement on the dynamic loader's search list. An index of zero requests information about the program file itself.
Shared Library Management Routines The dlopen Shared Library Management Routines struct load_module_desc { unsigned long text_base; unsigned long text_size; unsigned long data_base; unsigned long data_size; unsigned long unwind_base; unsigned long linkage_ptr; unsigned long phdr_base; unsigned long tls_size; unsigned long tls_start_addr; } Example The following code sequence shows how to use dlget to retrieve information about loaded modules.
Shared Library Management Routines The dlopen Shared Library Management Routines int ident_parm, uint64_t load_map_parm); Parameters Parameter Description ip_value An address. The instruction pointer value of the requested library. desc A buffer of memory allocated by the user program. The dynamic loader fills this in with module information. desc_size Size in bytes of the desc buffer. read_tgm_mem A pointer to a function used by dlmodinfo to retrieve needed information.
Shared Library Management Routines The dlopen Shared Library Management Routines searches all currently loaded load modules looking for a load module whose address range (address range of all loaded segments) holds the given address value. The dlmodinfo routine fills the load_module_desc with information from the matching load module. read_tgm_mem allows dlmodinfo to find a load module in one process on behalf of another.
Shared Library Management Routines The dlopen Shared Library Management Routines The dlgetname Routine Retrieves the name of a load module given a load module descriptor. Syntax char *dlgetname(struct load_module_desc *desc, size_t desc_size, void *(*read_tgt_mem)(void* buffer, unsigned long long ptr, size_t bufsiz, int ident), int ident_parm, unsigned long long load_map_parm); Parameters Parameter Description desc A buffer of memory allocated by the user program.
Shared Library Management Routines The dlopen Shared Library Management Routines Return Values dlgetname returns the pathname of a load module represented by desc. If desc does not describe a loaded module, dlgetname returns NULL. Description dlgetname is one of a family of routines that give the user direct access to the dynamic linking facilities. The read_tgt_mem, ident_parm, and load_map_parm parameters are identical to those for dlmodinfo.
Shared Library Management Routines The dlopen Shared Library Management Routines Parameters Parm handle Definition Value returned by a previous invocation of dlopen. Return Values If the referenced shared library was successfully closed, dlclose returns 0. If the shared library could not be closed, or if handle does not refer to an open shared library, dlclose returns a non-0 value. More detailed diagnostic information is available through dlerror.
Shared Library Management Routines The dlopen Shared Library Management Routines if (handle == NULL) { printf(“%s\n”, dlerror()); } ret_value = dlclose(handle); if (ret_value != 0) { printf(“%s\n”, dlerror()); } Chapter 6 255
Shared Library Management Routines Dynamic Loader Compatibility Warnings Dynamic Loader Compatibility Warnings Starting with the HP-UX 10.20 release, the dynamic loader generates compatibility warnings. These warnings include linker toolset features that may change over time.
Shared Library Management Routines Dynamic Loader Compatibility Warnings • BIND_TOGETHER • BIND_NONFATAL • BIND_VERBOSE • DYNAMIC_PATH The following shl_findsym() flags may become unsupported in a future release: • TYPE_PROCEDURE • TYPE_DATA • TYPE_STORAGE NOTE The for HP-UX Release 11.
Shared Library Management Routines Dynamic Loader Compatibility Warnings 258 Chapter 6
Position-Independent Code 7 Position-Independent Code This chapter discusses • “What Is Relocatable Object Code?” • “What is Absolute Object Code?” • “What Is Position-Independent Code?” • “Generating Position-Independent Code” This chapter is useful mainly to programmers who want to write position-independent assembly language code, or who want to convert existing assembly language programs to be position-independent. It is also of interest to compiler developers.
Position-Independent Code What Is Relocatable Object Code? What Is Relocatable Object Code? Relocatable object code is machine code that is generated by compilers and assemblers and stored in relocatable object files, or .o files. A relocatable object file contains symbolic references to locations defined within the compilation unit as well as symbolic references to locations defined outside the compilation unit. The object file also contains relocation information.
Position-Independent Code What is Absolute Object Code? What is Absolute Object Code? Absolute object code is machine code that contains references to actual addresses within the program's address space. When the linker combines relocatable object files to build a program file, or a.out file, it writes absolute object code into the file. Thus, when the program is executed, its routines and data must reside at the addresses determined by the linker.
Position-Independent Code What Is Position-Independent Code? What Is Position-Independent Code? Position-independent code (PIC) is a form of absolute object code that does not contain any absolute addresses and therefore does not depend on where it is loaded in the process's virtual address space. This is an important property for building shared libraries.
Position-Independent Code Generating Position-Independent Code Generating Position-Independent Code To be position-independent, object code must restrict all references to code and data to either PC-relative or indirect references, where all indirect references are collected in a single linkage table that can be initialized on a per-process basis by dld.sl. Register 19 (%r19) is the designated pointer to the linkage table.
Position-Independent Code Generating Position-Independent Code NOP LDW LDSID MTSP BE,N -24(%sp),%rp ; restore the original rp (%rp),%r1 %r1,%sr0 0(%sr0,%rp) ; inter-space return For More Information: The remainder of this section describes how compilers generate PIC for the following addressing situations: • “PIC Requirements for Compilers and Assembly Code” • “Long Calls” • “Long Branches and Switch Tables” • “Assigned GOTO Statements” • “Literal References” • “Global and Static Variable References” • “P
Position-Independent Code Generating Position-Independent Code NOTE Any code which is PIC or which makes calls to PIC must follow the standard procedure call mechanism. When linking files produced by the assembler, the linker exports only those assembly language routines that have been explicitly exported as entry (that is, symbols of type ST_ENTRY).
Position-Independent Code Generating Position-Independent Code LDIL BE L'target,%r1 R'target(%sr4,%r1) For PIC, these two instructions must be transformed into four instructions, similar to the long call sequence: L: BL ADDIL LDO BV,N .+8,%r1 L'target-L,%r1 R'target-L,%r1 0(%r1) ; ; ; ; get add add and pc into r1 pc-relative offset pc-relative offset branch The only problem with this sequence occurs when the long branch is in a switch table, where each switch table entry is restricted to two words.
Position-Independent Code Generating Position-Independent Code Global and Static Variable References References to global or static variables currently require two instructions either to form the address of a variable, or to load or store the contents of the variable: ; to form the address of a variable ADDIL L'var-$global$+x,%dp LDO R'var-$global$+x(%r1),tmp ; to load the contents of a variable ADDIL L'var-$global$+x,%dp LDW R'var-$global$+x(%r1),tmp These sequences must be converted to equivalent sequen
Position-Independent Code Generating Position-Independent Code When building shared libraries and incomplete executables, the linker modifies the plabel calculation (produced by the compilers in both shared libraries and incomplete executables) to load the contents of a DLT entry, which is built for each symbol associated with a CODE_PLABEL fixup.
Ways to Improve Performance 8 Ways to Improve Performance The linker provides several ways you can improve your application performance. • “Linker Optimizations” describes how the linker -O option removes unnecessary ADDIL instructions and “dead” or unused procedures. • “Options to Improve TLB Hit Rates”describes performance improvements in Translation Lookaside Buffer (TLB) hit rates.
Ways to Improve Performance Linker Optimizations Linker Optimizations The linker supports the -O option which performs the following optimizations at link time: • optimizes references to data by removing unnecessary ADDIL instructions from the object code. • removes procedures that can never be reached. These optimizations can be separately enabled or disabled with the +O[no]fastaccess and +O[no]procelim options respectively. The -O linker option simply combines enabling of these into one option.
Ways to Improve Performance Linker Optimizations NOTE With the HP-UX 10.0 release, you can also invoke linker optimizations at levels 2 and 3 by using the +Ofastaccess or +Oprocelim option. See Also: For a brief description of compiler optimization options see “Selecting an Optimization Level with PBO”. For a complete description, see your compiler manuals or online help.
Ways to Improve Performance Linker Optimizations subspaces. Merged subspaces can prevent the removal of dead procedures. Therefore, it is optimal to have each procedure in its own subspace. Complete Executables For complete executables, dead procedure elimination removes any text subspaces that are not referenced from another subspace.
Ways to Improve Performance Options to Improve TLB Hit Rates Options to Improve TLB Hit Rates To improve Translation Lookaside Buffer (TLB) hit rates in an application running on a PA 8000-based system, use the following linker or chatr virtual memory page setting options: • +pd size — requests a specified data page size of 4K bytes, 16K, 64K, 256K, 1M, 4M, 16M, 64M, 256M, or L. Use L to specify the largest page size available. The actual page size may vary if the requested size can not be fulfilled.
Ways to Improve Performance Profile-Based Optimization Profile-Based Optimization In profile-based optimization (PBO), the compiler and linker work together to optimize an application based on profile data obtained from running the application on a typical input data set. For instance, if certain procedures call each other frequently, the linker can place them close together in the a.out file, resulting in fewer instruction cache misses, TLB misses, and memory page faults when the program runs.
Ways to Improve Performance Profile-Based Optimization When to Use PBO PBO should be the last level of optimization you use when building an application. As with other optimizations, it should be performed after an application has been completely debugged. Most applications will benefit from PBO. The two types of applications that will benefit the most from PBO are: • Applications that exhibit poor instruction memory locality.
Ways to Improve Performance Profile-Based Optimization A Simple Example Suppose you want to apply PBO to an application called sample. The application is built from a C source file sample.c. Discussed below are the steps involved in optimizing the application. Step 1 Instrumentation First, compile the application for instrumentation and level 2 optimization: $ cc -v -c +I -O sample.c /opt/langtools/lbin/cpp sample.c /var/tmp/ctm123 /opt/ansic/lbin/ccom /var/tmp/ctm123 sample.o -O2 -I $ cc -v -o sample.
Ways to Improve Performance Profile-Based Optimization Instrumenting (+I/-I) Although you can use the linker alone to perform PBO, the best optimizations result if you use the compiler as well; this section describes this approach. To instrument an application (with C, C++, and FORTRAN), compile the source with the +I compiler command line option. This causes the compiler to generate a .o file containing intermediate code, rather than the usual object code.
Ways to Improve Performance Profile-Based Optimization The Startup File icrt0.o The icrt0.o startup file uses the atexit system call to register the function that writes out profile data. (For 64-bit mode, the initialization code is in /usr/ccs/lib/pa20_64/fdp_init.0.) That function is called when the application exits. atexit allows a fixed number of functions to be registered from a user application. Instrumented applications (those linked with -I) will have one less atexit call available.
Ways to Improve Performance Profile-Based Optimization A simpler approach would be to compile foo.c and bar.c with a single cc command: $ cc -v +I -O -o foobar bar.c foo.c /opt/langtools/lbin/cpp bar.c /var/tmp/ctm352 /opt/ansic/lbin/ccom /var/tmp/ctm352 bar.o -O2 -I /opt/langtools/lbin/cpp foo.c /var/tmp/ctm456 /opt/ansic/lbin/ccom /var/tmp/ctm456 foo.o -O2 -I /usr/ccs/bin/ld /opt/langtools/lib/icrt0.o -u main -o foobar \ bar.o foo.
Ways to Improve Performance Profile-Based Optimization user's environment. Then, the optimizer will focus its efforts on the parts of the program that are critical to performance in the user's environment. You should not have to do a large number of profiling runs before the optimization phase. Usually it is adequate to select a small number of representative input data sets. The flow.data File When an instrumented program terminates with the exit(2) system call, special code in the 32-bit icrt0.
Ways to Improve Performance Profile-Based Optimization Storing Profile Information for Multiple Programs A single flow.data file can store information for multiple programs. This allows an instrumented program to spawn other instrumented programs, all of which share the same flow.data file. To allow multiple programs to save their data in the same flow.
Ways to Improve Performance Profile-Based Optimization Sharing the flow.data File Among Multiple Processes A flow.data file can potentially be accessed by several processes at the same time. For example, this could happen when you run more than one instrumented program at the same time in the same directory, or when profiling one program while linking another with -P. Such asynchronous access to the file could potentially corrupt the data. To prevent simultaneous access to the flow.
Ways to Improve Performance Profile-Based Optimization The function _clear_counters is defined in icrt0.o. It is also defined as a stub (an empty function that does nothing) in crt0.o. This allows you to use the same source code without modification in the instrumented and un-instrumented versions of the program. Optimizing Based on Profile Data (+P/-P) The final step in PBO is optimizing a program using profile data created in the profiling phase.
Ways to Improve Performance Profile-Based Optimization Using The flow.data File By default, the code generator and linker look for the flow.data file in the current working directory. In other words, the flow.data file created during the profiling phase should be located in the directory where you relink the program. Specifying a Different flow.data File with +df What if you want to use a flow.data file from a different directory than where you are linking? Or what if you have renamed the flow.
Ways to Improve Performance Profile-Based Optimization Specifying a Different Program Name (+pgm) When retrieving a program's profile data from the flow.data file, the linker uses the program's basename as a lookup key. For instance, if a program were compiled as follows, the linker would look for the profile data under the name foobar: $ cc -v -o foobar +P foo.o bar.o /usr/ccs/bin/ld /usr/ccs/lib/crt0.o -u main -o foobar \ foo.o bar.
Ways to Improve Performance Profile-Based Optimization NOTE +O2 Full optimization within each procedure in a file. (Can also be invoked as -O.) +O3 Full optimization across all procedures in an object file. Includes subprogram inlining. +O4 Full optimization across entire application, performed at link time. (Invokes ld +Ofastaccess +Oprocelim.) Includes inlining across multiple files. Be aware that +O3 and +O4 are incompatible with symbolic debugging.
Ways to Improve Performance Profile-Based Optimization Note that you could set SHLIB_FLOW_DATA to flow.data which is the same file as the default setting for FLOW_DATA. But, again, profile data will not be collected from shared libraries unless you explicitly set SHLIB_FLOW_DATA to some output file. The following is a simple example for instrumenting, profiling, and optimizing a shared library: $ $ $ $ cc +z +I -c -O libcode.c ld -b -I libcode.o -o mylib.inst.sl cc main.c mylib.inst.
Ways to Improve Performance Profile-Based Optimization Notice in the example above, that the +pgm option was necessary because the output file name differs from the instrumented program file name. NOTE If you are using -r and C++ templates, check "Known Limitations" in the HP C++ Release Notes for possible limitations. Restrictions and Limitations of PBO This section describes restrictions and limitations you should be aware of when using Profile-Based Optimization.
Ways to Improve Performance Profile-Based Optimization What happens if you attempt to optimize a program using profile data that is older than the source files? For example, this could occur if you change source code and recompile with +P, but don't gather new profile data by re-instrumenting the code. In that sequence of events, optimizations will still be performed.
Ways to Improve Performance Profile-Based Optimization $ cc +I +O3 -c file.c $ cc +I +O3 file.o $ a.out < input_file data. $ cc +P +O3 file.o Create I-SOM for instrumentation. Link with instrumentation. Run instrumented executable with representative input Perform PBO and HLO. Replace +O3 with +O4 in the above example to get HLO over the entire program and ADDIL elimination. (You may see a warning when using +O4 at instrumentation indicating that the +O4 option is being ignored.
Ways to Improve Performance Profile-Based Optimization nm . The nm command works on I-SOM files. However, since code generation has not yet been performed, some of the imported symbols that might appear in an ordinary relocatable object file will not appear in an I-SOM file. ar . I-SOM files can be manipulated with ar in exactly the same way that ordinary relocatable files can be. strip . Do not run strip on files compiled with +I or +P. Doing so results in an object file that is essentially empty.
Ways to Improve Performance Profile-Based Optimization I-SOM files created under 9.0 are completely acceptable in the 10.0 environment. However, it is advantageous to re-profile programs under 10.0 in order to achieve improved optimization. Although you can use profile data in flow.data files created under 9.0, the resulting optimization will not take advantage of 10.0 enhancements. In addition, a warning is generated stating that the profile data is from a previous release.
Ways to Improve Performance Improving Shared Library Start-Up Time with fastbind Improving Shared Library Start-Up Time with fastbind The fastbind tool improves the start-up time of programs that use shared libraries. When fastbind is invoked, it caches relocation information inside the executable file. The next time the executable file runs, the dynamic loader uses this cached information to bind the executable instead of searching for symbols.
Ways to Improve Performance Improving Shared Library Start-Up Time with fastbind Invoking fastbind from the Linker To invoke fastbind from ld, pass the request to the linker from your compiler by using the -Wl,+fb options. For example: $ ld -b convert.o volume.o -o libunits.sl $ cc -Aa -Wl,+fb main.c -o main \ libunits.sl -lc Build the shared library. Link main to the shared library. Perform fastbind. The linker performs fastbind after it creates the executable file.
A Using Mapfiles The ld command automatically maps sections from input object files onto output segments in executable files. The mapfile option allows you to change the default mapping provided by the linker. NOTE The mapfile option is supported only in 64-bit mode linking. NOTE In most cases, the linker produces a correct executable without the use of the mapfile option.
Using Mapfiles Controlling Mapfiles with the -k Option Controlling Mapfiles with the -k Option The -k option to ld specifies a text file containing mapfile directives: ld -k mapfile [flags] files ... The ld command automatically maps sections from input object files onto output segments in executable files. The mapfile option allows you to change the default mapping provided by the linker. Use the -k filename option to specify a text file that contains mapfile directives.
Using Mapfiles Controlling Mapfiles with the -k Option 1 1 2 3 4 5 6 10 15 16 17 18 19 20 21 22 23 24 25 26 27 DYNM DYNM DYNS STRT HASH PBIT PBIT RELA PBIT PBIT PBIT PBIT PBIT PBIT PBIT PBIT NOBI NOBI STRT SYMT STRT 00000000000012a8 00000000000011c8 00000000000012e8 0000000000001558 0000000000001670 0000000000001718 000000000000175c 0000000000001778 4000000040001020 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040001038 00000
Using Mapfiles Changing Mapfiles with -k filename and +nodefaultmap Changing Mapfiles with -k filename and +nodefaultmap The +nodefaultmap option used with -k option prevents the linker from concatenating the default memory map to the map provided by filename. If you specify +nodefaultmap, the linker does not append the default mapfile to your mapfile. If you do not specify +nodefaultmap with -k, the linker appends the default to the output file.
Using Mapfiles Changing Mapfiles with -k filename and +nodefaultmap 5 PBIT 6 PBIT 7 RELA 8 RELA 9 RELA 10RELA 11RELA 12RELA 13UNWI 14PBIT 15PBIT 16PBIT 17PBIT 18PBIT 19PBIT 20PBIT 21PBIT 22PBIT 23NOBI 24NOBI 25STRT 26SYMT 27STRT 0000000000001718 000000000000175c 0000000000001778 0000000000001778 0000000000001778 0000000000001778 0000000000001778 0000000000001790 0000000000001790 4000000040001000 4000000040001020 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040001030 4000000040
Using Mapfiles Simple Mapfile Simple Mapfile The following directives show how a simple mapfile would appear: # text segment text = LOAD ?RX; text : .
Using Mapfiles Default HP-UX Release 11.0 Mapfile Default HP-UX Release 11.0 Mapfile The HP-UX Release 11.0 64-bit linker uses the following default mapfile: # text segment text = LOAD ?RXc V0x4000000000001000; text : .dynamic; text : .dynsym; text : .dynstr; text : .hash; text : $REL ?A; text : $RELA ?A; text : $UNWIND ?A; text : $PROGBITS ?A!X!W; text : .PARISC.milli; text : .text; text : $PROGBITS ?AX!W; # data segment data : .hdata; data =LOAD ?RWmo V0x8000000000001000; data : .
Using Mapfiles Default HP-UX Release 11.0 Mapfile thread_specific : $NOBITS ?AWT; # Note segment note = NOTE; note : $NOTE; # non-segment nonsegment = NONSEGMENT; nonsegment : .debug_header; nonsegment : .debug_gntt; nonsegment : .debug_ntt; nonsegment : .debug_slt; nonsegment : .
Using Mapfiles Defining Syntax for Mapfile Directives Defining Syntax for Mapfile Directives A mapfile can have zero or more mapfile directives. There are two types of mapfile directives: segment declarations and section mapping directives. The directives can span across lines and are terminated by a semicolon. The following syntax conventions are used to describe the directives: • [...]* means zero or more • [...]+ means one or more • [...
Using Mapfiles Defining Mapfile Segment Declarations Defining Mapfile Segment Declarations A segment declaration can create a new segment with a set of attributes or change the attributes of an existing segment.
Using Mapfiles Defining Mapfile Segment Declarations Flag Action R Readable W Writable X Executable The default segment_flags for a LOADable segment is ?RWX. Segment declarations support the following special flags: Flag Action s Enables static branch prediction on a segment. This flag is not set by default. (Dynamic branch prediction is the default.) l Enables lazy swap allocation for a segment. This flag is not set by default. (The lazy swap is disabled by default.
Using Mapfiles Defining Mapfile Segment Declarations Flag Action k Locks a particular segment into memory when loaded. This flag is set off for all segments. g Groups segments together. A segment declared with g flag is grouped with a segment preceding it in the mapfile. Any number of segments can be grouped together. The grouping affects the way in which addresses are assigned to segments. The segments in one group are assigned consecutive virtual addresses.
Using Mapfiles Defining Mapfile Section Mapping Directives Defining Mapfile Section Mapping Directives A section mapping directive specifies how the linker should map the input section onto output segments. This directive tells the linker what attributes of a section must be matched in order to map that section into the named segment. The set of attribute values that a section must have to map into a specific segment is called the entrance criteria.
Using Mapfiles Defining Mapfile Section Mapping Directives • If a section flag is preceded by an exclamation mark (!), it indicates that the flag should not be set to meet the entrance criteria. If you do not specify section_flags, the flag can have any value to meet the entrance criteria. S1 : ?XR; The linker maps all executable sections with static branch prediction enabled onto segment S1.
Using Mapfiles Internal Map Structure Internal Map Structure The linker use a default map structure corresponding to the default mapfile. When you use the mapfile option with the ld command, the linker appends the default mapfile to the end of your user-specified mapfile. (You can override the default mapfile by using the +nodefaultmap option.
Using Mapfiles Internal Map Structure Figure A-1 310 Appendix A
Using Mapfiles Internal Map Structure Figure A-1 shows the map structure. The entrance criteria boxes correspond to the information from the section mapping directives and the segment attribute descriptors correspond to the information from the segment declarations. The output section descriptors boxes group the sections that fall under each segment based on their section attributes. The linker associates each entrance criteria with a list of “output section descriptors”.
Using Mapfiles Internal Map Structure • If an entrance criteria selects both S (short data) and !S (non-short data) sections, the layout of the sections depends on section_type and S flag status.The linker maintains the following order: $PROGBITS and !S $PROGBITS and S $NOBITS and S $NOBITS and !S • The linker always tries to group all $NOBITS sections at the end of the data segment.
Using Mapfiles Mapfile Option Error Messages Mapfile Option Error Messages Fatal Errors The following conditions can result in a fatal error: • Specifying more than one -k option on the command line • Mapfile cannot be opened or read • The linker finds a syntax error in the mapfile • More than one segment_type, segment_flags, virtual_address, physical_address or alignment value appears on a single declaration line • More than one section_name, section_type, or section_flags value appears on a single direct
Using Mapfiles Mapfile Option Error Messages 314 Appendix A
Glossary absolute object code Machine code that contains absolute virtual addresses. Created by the linker when it combines relocatable object files. archive library A library, created by the ar command, which contains one or more object modules. By convention, archive library file names end with .a. Compare with "shared library.
Glossary code is contained within it. Compare with "incomplete executable." -b…), other libraries were specified on the command line. See also "dependent library." crt0.o file See startup file. dependent library A library that was specified on the command line when building a shared library (with ld -b…). See "dependency." data export symbol An initialized global variable that may be referenced outside of the library. data linkage table A linkage table that stores the addresses of data items.
Glossary dynamic loading library An SVR4 term for a shared library. dynamic search path The process that allows the location of shared libraries to be specified at runtime. entry point The location at which a program starts running after HP-UX loads it into memory. The entry point is defined by the symbol $START$ in crt0.o. explicit loading The process of using the shl_load(3X) function to load a shared library into a running program.
Glossary header string A string, "!\n", which identifies a file as an archive created by ar (\n represents the newline character). hiding a symbol Making a symbol invisible to code outside the module in which the symbol was defined. Accomplished with the -h linker option. immediate binding By default, the dynamic loader attempts to bind all symbols in a shared library when a program starts up — known as "immediate binding." Compare with "deferred binding.
Glossary link order The order in which object files and libraries are specified on the linker command line. link-edit phase The compilation phase in which the compiler calls the linker to create an executable (a.out) file from object modules and libraries. linkage table A table containing the addresses of shared library routines and data. A process calls shared library routines and accesses shared library data indirectly through the linkage table.
Glossary is that program execution continues even if the dynamic loader cannot resolve symbols. object code See relocatable object code. object file A file containing machine language instructions and data in a form that the linker can use to create an executable program. object module A file containing machine language code and data in a form that the linker can use to create an executable program or shared library. parent process The process that spawned a particular process. See also "process ID.
Glossary profile data obtained from running the application on a typical input data set. relocatable object code Machine code that is generated by compilers and assemblers. It is relocatable in the sense that it does not contain actual addresses; instead, it contains symbols corresponding to actual addresses. The linker decides where to place these symbols in virtual memory, and changes the symbols to absolute virtual addresses.
Glossary standard input/output library A collection of routines that provide efficient and portable input/output services for most C programs. standard output The default stream for sending character output data — usually connected to the screen. startup file Also known as crt0.o, this is the first object file that is linked with an executable program. It contains the program's entry point.
Glossary typically stored. Compare with "bss segment" and "data segment." For details, refer to a.out(4). umask A field of bits (set by the umask(1) command) that turns off certain file permissions for newly created files. version number A number that differentiates different versions of routines in a shared library. wrapper library A library that contains alternate versions of library functions, each of which performs some bookkeeping and then calls the actual function.
Glossary 324 Glossary
Index Symbols $LIT$ text space and performance, 148 $START$ symbol, 43 $TEXT$ space and performance, 148 +b linker option, 176, 178 +b path_list linker option, 84, 104, 145 +cg linker option, 28 +compat linker option, 25, 90 +DA compiler option, 21 +df compiler and linker option, 282, 284 +df option, 276 +dpv linker option, 28 +e linker option, 79, 84, 146 +ee linker option, 81 +ESlit option to cc, 148 +fb linker option, 294 +fini linker option, 202 +h linker option, 152 +hideallsymbols linker option, 25,
Index linking, 93 loading, 93 location, 136 migrating to shared library, 158, 161 mixing with shared libraries, 164 naming, 122 replacing object modules, 134 selecting at link time, 63 symbol table, 132, 322 assembler internal pseudo-op, 160 position-independent code, 264 atexit function, 278 attaching a shared library, 48, 126, 315 B -B bind linker option, 49, 58, 60 -b linker option, 82, 139, 271 basic block, 274, 315 BIND_BREADTH_FIRST flag to shl_load, 222 BIND_DEFERRED flag to shl_load, 215 BIND_FIRST
Index cxxshl_load function for C++, 215 cxxshl_unload function for C++, 238 D -D linker option, 271 data copy elimination in shared libraries, 126 data export symbol, 316 data linkage table, 262, 316 data references, optimizing, 270 data segment, 316 data symbol, 28 dead procedure elimination, 270, 271 debugging optimized code, 286 debugging shared libraries, 130, 161 default libraries, 46 default mapfile, 298, 301 deferred binding, 49, 104, 126, 316 DEMAND_MAGIC, 28, 44 demand-loaded executable, 316 depen
Index cxxdl.h, 199 dl.h, 199, 215, 223, 233 errno.h, 199, 217, 224 filehdr.h, 67 header string, 132, 318 header structure, 67 hiding shared library symbols (h), 81, 82, 84, 146, 318 high-level optimization, 289 HP_SHLIB_VERSION pragma, 28, 99, 155 HP-UX 10.X initializers, 201 HP-UX Reference, 162 I -I linker option, 277, 278 icrt0.
Index data segment, placing after text (-N), 66 data space offset, setting (-D), 271 DEMAND_MAGIC magic number (-q), 45 duplicate symbol definitions, 47 dynamic library search of SHLIB_PATH, enabling (+s), 86, 104, 145 dynamic library search path, specifying (+b), 84, 104, 145 dynamic linking (-A), 65, 271, 290 dynamic linking (-R), 65, 316 -dynamic option, 93 -E option, 81, 84 -e option, 66 entry point, specifying (-e), 66 EXEC_MAGIC magic number (-N), 45 exporting main program symbols (-E), 81, 84 export
Index suppressing, 55 linker compatibility features, 23 options 64-bit mode, 25, 90 SVR4-compliant features, 23 linker tool summary, 103 linker toolset unsupported features, 28 linking C++ programs, 41, 140 links with ln(1) to shared libraries, 152 link-time behavior changes, 28 load graph, shared library, 141 loading a shared library, 126, 215, 240 local definition, 40, 319 lock file, 282, 319 lorder command, 147 LPATH environment variable, 47, 57 M magic number, 44 malloc() and PBO, 288 man page, 162, 31
Index HP_SHLIB_VERSION pragma, 28 SHLIB_VERSION pragma, 28 procedure labels and PIC, 268 procedure linkage table, 262, 320 process ID, 320 prof profiler, 130 profile-based optimization, 274, 292, 321 +df option, 282, 284 +I and -I options, 277, 278 +P and -P options, 283 _clear_counters function, 282 -A linker option, 290 ar command, 291 atexit function, 278 -b linker option, 286 basic block, 274, 315 code generation, 279 compatibility with 9.0, 291 compiler incompatibilities, 291 crt0.
Index dynamic library search, 144, 145 dynamic loader, 48, 126, 262, 316 dynamic loader stack usage problems, 160 explicit loading, 215, 240, 317 explicit unloading, 238 exporting symbols, 79, 82, 84, 146, 317 file system links, 152 handle, 217, 321 hiding symbols, 81, 82, 84, 146, 318 immediate binding, 58, 104, 126 importing main program symbols, 81, 84 incomplete executable, 126, 318 initializer, 201, 210 ordering, 212, 213 initializer style HP-UX 10.
Index suffix for shared and archive libraries, 46 supporting library, 140, 322 SVID math library (libm), 163 symbol code, duplicate, 28 data, duplicate, 28 hiding, 95 linker-defined, 26 searching dependent libraries, 182 unsatisfied, 94 symbol binding semantics, 178 symbol name, 40, 99, 322 symbol searching of dependent libraries, 30 symbol table, 116 archive library, 132, 322 object file, 40, 322 stripping from a.