HP-UX Linker and Libraries User's Guide Version (For PA32 and PA64 Systems) B.11.72 Version (For Integrity Systems) B.12.
© Copyright 2011 Hewlett-Packard Development Company L.P. Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor's standard commercial license. The information contained herein is subject to change without notice.
Contents About This Document...................................................................................13 Intended Audience..................................................................................................................13 Document conventions and symbols..........................................................................................13 Related Information.................................................................................................................
Changing the Default Shared Library Binding with -B..............................................................32 Example Using -B immediate..........................................................................................32 Nonfatal Shared Library Binding with -B nonfatal..............................................................32 Restricted Shared Library Binding with -B restricted.............................................................32 Direct Shared Library Binding with -B direct....
Linking in PA-64 Mode with +std..........................................................................................48 Linking in PA-32 Mode with +compat...................................................................................48 Changing Mapfiles with -k and +nodefaultmap......................................................................48 Selecting Verbose Output with +vtype...................................................................................
What are Shared Libraries?.....................................................................................................91 The Dynamic Loader ..........................................................................................................91 Default Behavior When Searching for Libraries at Run Time.....................................................91 Caution on Using Dynamic Library Searching........................................................................92 Running setuid Programs.
Version Control with Shared Libraries......................................................................................110 When to Use Shared Library Versioning..............................................................................110 Maintaining Old Versions of Library Modules......................................................................111 Library-Level Versioning.....................................................................................................
Using Shared Libraries with cc and ld Options.........................................................................138 Initializers for Shared Libraries................................................................................................138 Styles of Initializers ..........................................................................................................138 Init/Fini Style Initializers...............................................................................................
Return Values..............................................................................................................160 Description.................................................................................................................161 Using dlmodinfo to retrieve information about a load module............................................161 The dlgetname Routine.....................................................................................................161 Syntax..................
The shl_get and shl_get_r Routines.....................................................................................175 Syntax.......................................................................................................................175 Parameters.................................................................................................................175 Return Value...............................................................................................................
Segment Flags.................................................................................................................196 Mapfile Segment Declaration Examples..............................................................................197 Defining Mapfile Section Mapping Directives...........................................................................197 Internal Map Structure...........................................................................................................
Options to Improve TLB Hit Rates............................................................................................217 Profile-Based Optimization (Itanium)........................................................................................217 Incremental Linking...............................................................................................................217 Using Incremental Linking Options......................................................................................
About This Document This document discusses the most recent product information on HP-UX Linker and Libraries Version B.11.72 for HP 9000 systems and Version B.12.57 for Integrity systems that are running HP-UX 11i v1, HP-UX 11i v2, and HP-UX 11i v3. Intended Audience This document is intended for developers who want to compile, link, and build applications using the HP C/ANSI C Developer's Bundle on HP 9000 or HP Integrity systems.
HP Encourages Your Comments HP encourages your comments concerning this document. We are committed to providing documentation that meets your needs. Send any errors found, suggestions for improvement, or compliments to: feedback@fc.hp.com Include the document title, manufacturing part number, and any comment, error found, or suggestion for improvement you have concerning this document.
• “Using Mapfiles” (page 191) This chapter explains how to use mapfiles. The mapfile option, which is an advanced feature of the linker toolset, is intended for use in system programming. • “Improving Your Application Performance” (page 202) This chapter explains how you can use linker to improve the performance of your applications. This chapter discusses options to improve TLB hit rates, incremental linking, profile-based optimization, and other ways to improve application performance.
1 Compiling and Linking Programs on HP-UX This chapter describes the process of compiling and linking a program. Section Description “Compiling Programs on HP-UX: An Example” (page 16) Provides an overview of compiling on HP-UX. “Linking Programs on HP-UX” (page 21) Describes how ld creates an executable file from one or more object. “Linking with Libraries” (page 23) Describes conventions for using libraries with ld.
Notice that cc displays the name of each source file it compiles. This way, if errors occur, you know where they occur. Also, the diagnostics mention the name of the source file. #include
Figure 1 High-level View of the 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. (See also “What is an Object File?” (page 18)) 2.
or data definition can be either a local definition or global definition. Any reference to a symbol outside the object file is known as an external reference. To keep track of where all the symbols and external references occur, an object file has a symbol table. The linker uses the symbol tables of all input object files to match external references to global definitions.
-D__hpux -D__unix -D__ia64=1 -D_BIG_ENDIAN=1 -D_ILP32 -D__HP_cc=60200 \ -D__STDC_EXT__ -D_HPUX_SOURCE -D_INCLUDE_LONGLONG -D_INLINE_ASM \ -D_BIND_LIBCALLS -D_Math_errhandling=MATH_ERREXCEPT -D_FLT_EVAL_METHOD=O \ -ucode hdriver=optlevel%1% -plusolistoption -O106const! -plusolistoption \ -O113moderate! -plusooption -Oq01,al,ag,cn,sz,ic,vo,Mf,Po,es,rs,Rf,Pr,sp,\ in,cl,om,vc,pi,fa,pe,rr,pa,pv,nf,cp,1x,Pg,ug,1u,lb,uj,dn,sg,pt,kt,em,np,ar,\ rp,dl,fs,bp,wp,pc,mp,1r,cx,cr,pi,so,Rc,fa,ft,fe,ap,st,lc,Bl,sr,ib,pl,sd,
Linking Programs on HP-UX • “The crt0.o Startup File” (page 21) • “The a.out File” (page 22) • “Magic Numbers (PA-RISC ONLY)” (page 22) • “File Permissions” (page 23) The HP-UX linker (ld) creates an executable file, shared library, or combines the object files to create another relocatable object file. 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. This process is known as relocation.
The linker uses four startup files: • 32-bit PA is /opt/langtools/lib/crt0.o • 64-bit PA is /opt/langtools/lib/pa_64/crt0.o The linker uses this startup file when it is in compatibility mode (+compat) or it is in default standard mode (+std) with the -noshared option. • 32-bit IPF is /opt/langtools/lib/hpux32/crt0.o The linker uses this startup file when it is in default standard mode (+std) with the -noshared option. • 64-bit IPF is /opt/langtools/lib/hpux64/crt0.
program does not need to be loaded; however, it can degrade performance throughout execution. EXEC_MAGIC Neither the program's text nor data is shareable. In other words, the program is an unshared executable. Usually, it is not desirable to create such unshared executables because they place greater demands on memory resources. By default, the linker creates executables whose magic number is SHARE_MAGIC. Table 2 (page 23) shows which linker option to use to specifically set the magic number.
Library Naming Conventions By convention, library names have the form: libname. suffix name is a string of one or more characters that identifies the library. suffix is .a if the library is an archive library, .sl if the library is a PA-RISC shared library, or .so if the library is a shared library. (The suffix can be .sl for an IPF shared library. This naming convention is not recommended, but it is supported for backwards compatibility with PA-32 and PA-64.
library specified on the linker command line: because the other libraries preceding it in the link order often contain references to libc routines and so must precede it. NOTE: If multiple definitions of a symbol occur in the specified libraries, ld does not necessarily choose the first definition. It depends on whether the program is linked with archive libraries, shared libraries, or a combination of both.
Linker Thread-Safe Features The dynamic loader (dld) and its application interface library (libdl) are thread-safe. Also, the linker toolset provides thread local storage support in: • ld - the link editor • crt0.o - the program startup file Thread local storage (also called thread-specific data) is data specific to a thread. Each thread has its own copy of the data item.
2 Determining How to Link Programs or Libraries (Linker Tasks) You have a great deal of control over how the linker links your program or library by using ld command-line options. This chapter describes the tasks you can perform to determine how programs and libraries must link by using the Compiler commands and Linker commands.
◦ “Specifying Libraries with -l and -l:” (page 45) ◦ “Flagging Unsatisfied Symbols with +[no]allowunsats” (page 45) ◦ “Stripping Symbol Table Information from the Output File with -s and -x” (page 46) ◦ “Controlling Output from the Unwind Table with +strip unwind” (page 46) ◦ “Using the IPF Linker with +compat or +std” (page 46) ◦ “Linking in PA-64 Mode with +std” (page 48) ◦ “Linking in PA-32 Mode with +compat” (page 48) ◦ “Changing Mapfiles with -k and +nodefaultmap” (page 48) ◦ “Selectin
Getting Verbose Output with -v The -v option makes a compiler display the verbose information. This is useful for viewing how the compiler calls ld. For example, using the -v option with the C compiler shows that it automatically links with libc. $ cc -v himom.c /opt/ansic/lbin/ecom -ia64abi all -architecture 32 -ext on -lang c \ -exception off -sysdir /usr/include -inline_power 1 -link_type dynamic \ -fpeval float -tls_dyn on -target_os 11.
$ cc -Aa -v cursesprog.c -lcurses ... /usr/ccs/bin/ld /opt/langtools/lib/crt0.o cursesprog.o -lcurses \ -u main -lc cc: informational note 413: Entering Link editor. Linking with the crt0.o Startup File in 32-bit mode (PA-RISC) Notice also, in the above example, that the compiler linked cursesprog.o with the file /opt/langtools/lib/crt0.o.
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 prog.
NOTE: You can use $ORIGIN in SHLIB_PATH/LD_LIBRARY_PATH only for programs on PA32 systems. While the +origin option is available, the recommended way to specify $origin is in the embedded path with the +b option. For example, $ ld main.o -lc +b $ORIGIN If you use +b,\$ORIGIN; the $ORIGIN only affects libraries that are subject to dynamic path lookup; that is, the library shared_library_name is specified with -l or with no embedded / character.
When is -B restricted most useful? Consider a program that creates duplicate symbol definitions by either of these methods: • The program uses shl_load with the BIND_FIRST flag to load a library that contains symbol definitions that are already defined in a library that was loaded at program startup. • The program calls shl_definesym to define a symbol that is already defined in a library that was loaded at program startup.
Improving Shared Library Performance with -B symbolic The linker supports the -B symbolic option which optimizes call paths between procedures when building shared libraries. It does this by building direct internal call paths inside a shared library. In linker terms, import and export stubs are bypassed for calls within the library. The benefit of using -B symbolic option is that it helps improve application performance and the resulting shared library is slightly smaller.
Figure 4 Symbols Inside a Shared Library Visible with -B symbolic 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. However, only the exported symbols are visible outside of the shared library. For example, you can hide the gal_to_liter symbol, as shown: $ ld -b convert.o -h gal_to_liter volume.o -o libunits.
Choosing Archive or Shared Libraries with -a If both an archive and shared version of a particular library reside in the same directory, ld links with the shared version. Occasionally, you might want to override this behavior. As an example, suppose you write an application that runs on a system on which shared libraries may not be present.
Linking Archived Libraries with -noshared Use the -noshared option if you need to link with all archive libraries. The linker outputs an archive-bound executable. NOTE: You cannot link in shared libraries if you specify this option. In the following example, the linker only looks for: /usr/lib/hpux32/libfoo.a and /user/lib/hpux32/libc.a: $ ld /usr/ccs/hpux32/crt0.o main.o -noshared -L. -lfoo -lc If you specify a shared library libbar.
The linker command line gets lengthy and difficult to read if several such options are specified. In fact, you exceed the maximum HP-UX command line length if you specify too many options. To get around this, use ld linker option files, described under “Passing Linker Options in a file with -c” (page 44) . You can specify any number of -h or +e options in this file. You can use -h or +e options when building a shared library (with -b), combining .o files ( with -r), and when linking to create an a.out file.
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(). If you use +hideallsymbols, the linker cannot export the following routines in the a.out. $ ld main.o +hideallsymbols -L. -lfoo -lc $ elfdump -t a.out a.out: ... .symtab index 1 ...
Hiding and Exporting Symbols When Building a Shared Library When building a shared library, you may want to hide a symbol in the library for the following reasons: • When building a shared library, you may want to hide a symbol in the library for the following reasons: • Hiding a symbol ensures that the definition can only be accessed by other routines in the same library. When linking with other object modules or libraries, the definition is hidden from them.
if a definition exists outside the program file. In such cases, a shared library may update a global variable needed by the program, but the program would never see the change because it is referencing its own copy. One example of a data symbol that should almost always be exported from a program is errno. The errno data symbol is defined in every shared library and program; if this definition is hidden, the value of errno is not shared outside of the program in which it is hidden.
On PA32 systems, double colon (::) refers to the location in which the libraries were found at link time. For example, the following linker command instructs the dynamic loader to search for libfoo, libm, and libc first in the current working directory (.), then in the directory /app/lib, and lastly in the location in which the libraries were found at link time (::). $ ld /opt/langtools/lib/crt0.o +b .:/app/lib:: prog.o -lfoo -lm -lc NOTE: The double colon (::) feature is available only for PA32 systems.
/usr/local/lib/libfoo.sl, and the directory path list contains /apps/lib:xyz, the dynamic loader searches for /apps/lib/libfoo.sl, then ./xyz/libfoo.sl. The full library path name stored in the executable is referred to as the default library path. To cause the dynamic loader to search for the library in the default location, use a null directory path (). NOTE: The use of null directory path () is PA32 specific.
Controlling Archive Library Loading with +[no]forceload Use the +[no]forceload option to control how the linker loads object files from an archived library. The +forceload instructs the linker to load all object files from an archive library. The +noforceload option instructs the linker to only load those modules from an archive library that is needed. The mode you select, either by default or explicitly, remains active until you change it. The +noforceload option is the default.
Specifying Libraries with -l and -l: To direct the linker to search a particular library, use the -lname option. For example, to specify libc, use -lc; to specify libm, use -lm; to specify libXm, use -lXm. Specifying Libraries (-l) When writing programs that call routines not found in the default libraries linked at compile time, you must specify the libraries on the compiler command line with the -lx option. For example, if you write a C program that calls POSIX math functions, you must link with libm.
The +allowunsats option still causes the linker to emit a warning message and output a.out. If you do not specify the option and the linker finds an unsatisfied symbol, the linker displays an error message and a non-executable a.out. $ ld main.o -L. -lbar -lc ld: Unsatisfied symbol "foo". 1 error. Stripping Symbol Table Information from the Output File with -s and -x The a.
compatibility-mode libraries even if they are really created as standard mode dependent libraries. • Does not use embedded paths at link time to find dependent libraries. • Considers the order of ld, +b and +s. ◦ The +b option 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.
At runtime, the dynamic loader does a PA-64 load for all standard mode dependent shared libraries. The dynamic loader: • Does dynamic path searching only for standard-mode shared libraries in the DT_NEEDED entry of the dynamic table which do not contain a path. For those standard-mode dynamic libraries that contain paths, dld looks for the library as specified. • Looks for the shared library as specified in the DT_NEEDED dynamic table entry if it contains a path.
Table 3 values specify the type (continued) Parameter Description Loading Loading Loading Loading libraries ./libfile1.so: ./libfile2.so: /usr/lib/hpux32/libc.so: /usr/lib/hpux32/libdl.so.1: Dump information about libraries searched. $ ld main.o +vtype libraries -L. -lfile1 -lfile2 -lc Searching /usr/lib/hpux32/libc.a: Selecting /usr/lib/hpux32/libc.a sections Dump information about each input section added to the output file. $ ld main.o +vtype sections -L. -lfile1 -lfile2 -lc main.o: section .
Table 3 values specify the type (continued) Parameter Description procelim procelim Dump information about the sections that have been rejected by the +Oprocelim option. $ ld main.o +Oprocelim +vtype procelim -L. -lfile1 -lfile2 Deleting 236 bytes in section file.note Eliminated 0K of dead code and data, 0 global, 0 local and 0 hidden symbols Turning on the linkage table protection with +protect You can use the +protect option to turn on the linkage table protection mode.
Table 4 flags that are supported To Use the flag Enable trap on invalid floating-point operations. V Disable trap on invalid floating-point operations. v Enable trap on divide by zero. Z Disable trap on divide by zero. z Enable trap on floating-point overflow. O Disable trap on floating-point overflow. o Enable trap on floating-point underflow. U Disable trap on floating-point underflow. u Enable trap on floating-point operations that produce inexact results.
Turn Off Linker Warnings with -w In some build processes you might want to improve parsing of build output by ignoring linker warnings. You can turn off linker warnings with the -w option. Preserving Compiler Generated Relocation Sections with -emit_relocs The -emit_relocs option enables the linker to preserve compiler-generated relocation sections in the output binary. The input relocation information is stored in the executable, or the shared library.
3 Linker Tools for Itanium-Based Systems This chapter describes the linker toolset for Itanium-based system. This toolset provides several tools to help you find symbols, display and modify object files, and determine link order. These tools are specific to ELF (executable and linking format) object file type. The following lists Table 5 (page 53). Table 5 Linker toolset for Itanium-Based systems Tool Description chatr Displays or modifies the internal attributes of an object file.
Table 6 options to change various attributes (continued) To do this Use the option Enable run-time dereferencing of null pointers to produce a SIGSEGV signal. (This is the complement of the -Z option.) -z Use immediate binding for all libraries loaded at program start-up. -B immediate Use deferred binding for all libraries loaded at program start-up. -B deferred Disable run-time dereferencing of null pointers. (This is the complement of the -z option.
Table 6 options to change various attributes (continued) To do this Use the option Enable or disable the modification bit for the file's data segment(s). If this is enabled, it is denoted by the +m flag for the segment listing in the chatr output. +md flag Enable or disable the automatic preloading of librtc.so runtime library for the specified +mem_check executable to support runtime memory leak checking.
Viewing Symbols in an Object file with nm(1) The nm(1) command displays the symbol table of each specified object. The file can be a relocatable object file or an executable object file, or an archive of relocatable or executable object files. The nm command 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.
Prefix each output line with the name of the object file or archive file. Equivalent to -A. -r Print the section index instead of the section name (ELF only). -s Display each numeric value in the specified format. The format can be one of: -t format d Display the value and size of a symbol in decimal. This is the default for the default format or the -p format. Equivalent to -d. o Display the value and size of a symbol in octal. Equivalent to -o.
Example 2 Using the nm command • Display which object files have undefined references for the symbol leap: nm -rup *.o | grep leap • Display which object files have a definition for the text symbol leap: nm -rP *.o | awk '{ if ($3 == "T" && $2 == "leap" ) { print $0 } }' • To view the symbols defined in an object file, use the nm command. The following 32-bit mode example shows output from running nm -p on the func.o and main.o object files. $ nm -p func.o 0000000000 u 0000000000 r .HP.
To view this Use the option The .dynamic section in shared libraries and dynamically linked program files. -L The .linkmap section, which is only created when the incremental linker is used (with the ld+ild command). The .linkmap_bss section, which is only created when the incremental linker is used (with the ld +ild command). The .linkmap_file section, which is only created when the incremental linker is used (with the ld +ild command).
Option +T num2 Modifies -t Causes elfdump to Display the symbols in the range 0 to num2. • With-T, display the symbols in the range num to num2. -v -k Verify the CTTI section headers before printing. Viewing Library Dependencies with ldd(1) The ldd(1) command lists the dynamic dependencies of executable files or shared libraries. The ldd command displays verbose information about dynamic dependencies and symbol references: • Executable All shared libraries loaded as a result of executing the file.
Example 3 Using the ldd command • By default, ldd prints simple dynamic path information, including the dependencies recorded in the executable (or the shared library) followed by the physical location where the dynamic loader finds these libraries. $ ldd a.out ./libx.so => ./libx.so libc.so.1 => /usr/lib/hpux32/libc.so.1 libdl.so.1 => /usr/lib/hpux32/libdl.so.1 • The -v option causes ldd to print the dependency relationships along with the dynamic path information. $ ldd -v a.out find library=./libx.
directory and $PATH. The executable path can be specified along with the pid/corepath, separated by a colon (:) character. Use the -h option to print the usage menu. The following exit values are returned: 0: Successful operation non-zero: An error has occurred. Use the following options to view information for your specified files.
The -level n option can be used to print n levels of procedure calls. Without this option, pstack normally prints the complete procedure stack. With this option, pstack can be restricted to print 'n' levels in the procedure stack. With this option, pstack can be restricted to print only n levels of procedure calls in the procedure stack. The following example shows the result of running pstack for a process id 3975.
Example 7 Printing the default output for a sample threaded process -------------------------------- lwpid : 119942 ------------------------------- 0: 60000000c042fb70 : __pause_sys() + 0x30 (/usr/lib/hpux32/libc.so.1) 1: 60000000c0444de0 : pause() + 0xc0 (/usr/lib/hpux32/libc.so.1) 2: 0000000004000e80 : main() + 0x270 (./thread32) 3: 60000000c0030c90 : main_opd_entry() + 0x50 (/usr/lib/hpux32/dld.
Example 9 Calling pstack with special argument -1 3774: /usr/bin/bash -------------------------------- lwpid : 4520 ------------------------------- 0: 00000000040c47c1 : make_child() + 0x311 (/usr/bin/bash) 1: 000000000420bd60 : push_scope() + 0x3b0 (/usr/bin/bash) 2: 0000000004208e40 : coproc_closeall() + 0xfa0 (/usr/bin/bash) 3: 00000000040ba440 : execute_command_internal() + 0xf70 (/usr/bin/bash) 4: 000000000416c420 : execute_command() + 0x160 (/usr/bin/bash) 5: 00000000042206f0 : reader_loop() + 0x
Table 9 Options to control the amount of information stripped To Use the option Strip line number information only; do not strip any symbol table information. -l Same as the -x option. Obsolete. -r Strip the unwind information and annotations. -u Print the usage message. -U Print the version of the strip command to stderr. -V Strip the debug information and line number table. -x NOTE: The -l and -x options are synonymous because the symbol table contains only static and external symbols.
called, it is resolved from the explicitly-loaded library. But after running fastbind, the symbol foo() is resolved from the implicitly-loaded library. For more information about fastbind and how to improve program start-up time, see “Improving Shared Library Start-Up Time with fastbind” (page 222) . Example 10 Example • To run fastbind on the executable file a.out: $fastbind a.out • To later remove the fastbind information from the executable file a.out $fastbind -n a.
The output from each of the execution is appended to the log file. To generate a log when a program $ ./a.out arg1 arg2 arg3 .. argn is executed, use the following command syntax: $/usr/ccs/bin/ltrace ./a.out -a "arg1 arg2 arg3 .. argn" For example: $/usr/ccs/bin/ltrace /usr/bin/ls -a "-ltr" The above-mentioned command has the effect of tracing all inter-module procedure calls when /usr/bin/ls -ltr command is executed.
4 Linker Tools for PA-RISC Systems 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.
To Use the option Enable run-time use of the path list specified with the +b option at link time. +b enable If +b enable and +s enable are both specified, the order in which they appear determines which search path is used first. Disable run-time use of the path list specified with the +b option at link time. +b disable Enable the use of the SHLIB_PATH environment variable to perform run-time path list lookup of shared libraries.
Table 11 For the 64-bit only syntax To Use the option Set the code bit for a specified segment. +c Enables or disables lazy swap allocation for dynamically allocated segments (such as the stack or heap). +dz Set the modification bit for a specified segment. +m Set the page size for a specified segment. +p Identify a segment using a segment index number. +si Identify a segment using an address. +sa Use all segments in the file for a set of attribute modifications.
To Use the option Prefix each output line with the name of the object file or archive file. Equivalent to -A. -r Display each numeric value in the specified format. The format can be one of: d Display the value and size of a symbol in decimal. This is the default for the default format or the -p format. Equivalent to -d. o Display the value and size of a symbol in octal. Equivalent to -o. x Display the value and size of a symbol in hexadecimal. This is the default for the -P format. Equivalent to -x.
The elfdump 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 Use the option Symbol table entries. -t Archive headers from an archive library. -a String table(s). -c File header. -f Global symbols from an archive. -g Section headers. -h The .dynamic section in shared libraries and dynamically linked program files. -L Optional headers (program headers).
Viewing library dependencies with ldd(1) The ldd command lists the dynamic dependencies of executable files or shared libraries. The ldd command displays verbose information about dynamic dependencies and symbol references: Executable All shared libraries that are loaded as a result of executing the file. Shared library All shared libraries that are loaded as a result of loading the library. The ldd command uses the same algorithm as the dynamic loader (/usr/lib/dld.sl and /usr/lib/pa20_64/dld.
Example 13 Viewing library dependencies with ldd(1) • By default, ldd prints simple dynamic path information, including the dependencies recorded in the executable (or the shared library) followed by the physical location where the dynamic loader finds these libraries. $ 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 the dependency relationships along with the dynamic path information. $ ldd -v a.out find library=./libx.
the object file. If you specify an archive file, the information for all archive members is displayed. Use the following options to display information for your specified files: To display Use the option Sizes in decimal (default). -d Sizes in octal. -o Sizes in hexadecimal. -x Version information about the size command. -V Verbose list of the subspaces in the object files. Each subspace is listed on a separate line with its size, physical address, and virtual address.
The fastbind command performs analysis on the symbols used to bind an executable and all of its dependent shared libraries, and stores this information in the executable file. The next time the executable is run, the dynamic loader (/usr/lib/dld.sl for 32-bit mode or /usr/lib/pa20_64/dld.sl for 64-bit mode) detects that this information is available, and uses it to bind the executable instead of using the standard search method for binding the symbols.
The lorder command overlooks object files whose names do not end with .o, even when contained in library archives, and attributes their global symbols and references to some other file. Example 15 Finding Object Library Ordering Relationships with lorder(1) • Build a new library from existing .o files: $ ar cr library `lorder *.o | tsort` • When creating libraries with so many objects that the shell cannot properly handle the *.o expansion, the following method may prove useful: $ ls |grep '.
5 Linker Toolset Differences Between PA-RISC and Itanium-Based Systems This chapter describes some of the linker toolset differences between PA-RISC and Itanium-based systems.
release for PA-RISC 1.0 systems, so code generated by the HP-UX 10.20 release of HP compilers is not supported on PA-RISC 1.0 systems. NOTE: The +DA1.0 option will be obsolete in a future release. You can achieve better performance on PA-RISC 1.1 and 2.0 systems by not using this option. PA-RISC 2.0 Compatibility The instruction set on PA-RISC 2.0 is a superset of the instruction set on PA-RISC 1.1. As a result, code generated for PA-RISC 1.1 systems run on PA-RISC 2.0 systems.
Table 14 Differences in options between PA-32 and IPF/PA-64 bit modes Option Description -A name Specifies incremental loading. IPF 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. -T Save data and relocation information in temporary files to reduce virtual memory requirements during linking. This option is unsupported.
Run-time Differences Between SOM (PA32) and ELF (PA64 and Itanium) IPF applications (32-bit and 64-bit) and PA-64 applications use a run-time dynamic loading model similar to other SVR4 systems.
Table 19 Symbol names Symbol Definition __SYSTEM_ID Largest architecture revision level used by any compilation unit _FPU_STATUS Initial value of FPU status register. _end Address of first byte following the end of the main program's data segment; identifies the beginning of the heap segment. __TLS_SIZE Size of the Thread Local Storage segment required by the program. This symbol is not reserved in PA32 (SOM). __text_start Beginning of the text segment. _etext End of the text segment.
3. 4. 5. 6. 84 SHLIB_PATH (if set) RUNPATH the default location /usr/lib/hpux32 for 32-bit programs and /usr/lib/hpux64 for 64-bit programs.
Example 16 Specifying library paths in PA-32 mode and IPF/PA-64 mode The following are examples of specifying library paths in PA-32 mode and IPF/PA-64 mode (IPF (32-bit and 64-bit) and PA-64): • Linking to libraries by fully qualifying paths. The library does not contain SONAME specified by the linker +h option when building the shared library: In this example, the program is linked with /opt/myapp/mylib.sl: $ cc main.o /opt/myapp/mylib.sl Perform 32-bit link. $ cc +DD64 main.o /opt/myapp/mylib.
In PA-32 mode, the dynamic loader searches paths to resolve external references in the following order: 1. /var/tmp to find libme.sl found 2. /var/tmp to find libc.sl not found 3. /usr/lib/libc.sl found In IPF 32-bit mode, the dynamic loader searches paths to resolve external references in the following order: 1. LD_LIBRARY_PATH (if set) to find libme.sl not found ◦ 2. SHLIB_PATH (if set) to find libme.sl not found 3. /var/tmp to find libc.sl not found 4. LD_LIBRARY_PATH (if set) to find libc.
In PA-32 mode, the dynamic loader searches shared libraries using a depth-first search order. The diagram below illustrates a sample program with shared libraries and compares the two search methods: a.out | |-----------------| | | lib1 lib2 | lib3 Breadth-first search list: a.out -> lib1 -> lib2 -> lib3 Depth-first search list: a.out -> lib1 -> lib3 -> lib2 The commands to build the libraries and the executable in "Search Order of Dependent Libraries" are shown: $ $ $ $ ld -b lib2.o -o lib2.s ld -b lib3.
Statically-bound programs (archive-bound programs) Use the compiler -complete option or the linker -noshared option to create a statically-bound program. The default is -dynamic. Statically-bound programs are not supported on IPF. Most IPF (32-bit and 64-bit) system libraries, including libc, are only available as shared libraries.
6 Creating and Using Libraries Many libraries come with HP-UX. You can also create and use your own libraries on HP-UX.
Table 20 Differences between archive and shared libraries (continued) Comparing Archive Shared (or dll) address binding Addresses of library subroutines Addresses of library subroutines are bound at run time. and data are resolved at link 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.
Figure 6 Linking with an Archive Library 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.
it was when you linked the final application. Otherwise, when the users of your application run it, the dynamic loader looks for /users/hyperturbo/liblocal.so, fail to find it, and the program aborts. In default mode, the linker records ./liblocal.so. This is more of a concern with non-standard libraries-that is, libraries not found in /usr/lib/hpux32 or /usr/lib/hpux64. There is little chance of the standard libraries not being in these directories.
is shared by both processes. The total memory requirement for these two processes running simultaneously is 896Kb (256Kb + 128Kb + 512Kb). Figure 7 Two Processes Sharing libc Compare this with the memory requirements if prog1 and prog2 are linked with the archive version of libc. As shown in Figure 8 (page 93), 1428Kb of memory is required (768Kb + 640Kb). The numbers in this example are made up, but it is true in general that shared libraries reduce memory requirements.
Shared Libraries with Debuggers, Profilers, and Static Analysis Debugging of shared libraries is supported by the by the WDB Debugger. See the WDB documentation at: http://www.hp.com/go/wdb Profiling Shared Libraries with gprof(1) The gprof tool produces an execution profile about an executable for application programs and shared libraries. See gprof(1) for more information. Use the following steps to profile a shared library: • Set the environment variable LD_PROFILE to the shared library name.
• “Replacing, Adding, and Deleting an Object Module” (page 97) • “Summary of Keys to the ar(1) Command” (page 97) • “Archive Library Location (IPF) ” (page 98) Overview of Creating an Archive Library To create an archive library: 1. Create one or more object files containing relocatable object code. Typically, each object file contains one function, procedure, or data structure, but an object file can have multiple routines and data. 2.
acosh.o //Object modules are displayed. erf.o fabs.o . . . . This indicates that the library was built from object files named acosh.o, erf.o, fabs.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. The routines that do the conversions are contained in three C-language files.
Note that the whole library name was given, and the -l option was not specified. This is because the library was in the current directory. If you move libunits.a to /usr/lib/hpux32 (IPF 32-bit mode) or /usr/lib (PA32 mode) before compiling, the following command line works instead: $ cc -Aa convert.c -lunits Linking with archive libraries is covered in detail in “Determining How to Link Programs or Libraries (Linker Tasks)” (page 27).
$ ar tv libunits.a rw-rw-rw265/ rw-rw-rw265/ rw-rw-rw265/ 20 20 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 The crt0.o startup file is not needed for shared bound links because dld.so does some of the startup duties previously done by crt0.o. However, you still need to include crt0.
Following are the commands you can use to create a shared library called libunits.so: $ cc -Aa -c +z length.c volume.c mass.c $ ld -b -o libunits.so length.o volume.o mass.
$ cc -Aa -c +z length.c volume.c mass.c length.c: volume.c: mass.c: $ ld -b -o libunits.so length.o volume.o mass.o Once the library is created, ensure that it has read and execute permissions for all users who use the library. For example, the following chmod command allows read/execute permission for all users of the libunits.so library: $ chmod +r+x libunits.so This library can now be linked with other programs. For example, if you have a C program named convert.c that calls routines from libunits.
+-->libA.so | libP.so-->libD------+ | | | | v v +-->libQ.so-->libB.so For PA-32 compatibility mode The loader uses the following algorithm in PA-32 mode: 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. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
--> libP--> libA--> libD--> libQ--> libB The same behavior occurs for libraries that are explicitly loaded with shl_load, but without the BIND_FIRST modifier (see “BIND_FIRST Modifier” (page 171) for details). If BIND_FIRST is specified in the shl_load call, then the libraries in the load graph are inserted before the existing search list. For example, suppose libP is loaded with this call: lib_handle = shl_load("libP.
Loading Shared Libraries with the LD_PRELOAD Environment Variable NOTE: The LD_PRELOAD feature is disabled for seteuid/setegid programs, such as passwd. See ld(1) for more details. This feature is not available for fully-bound static executables. The LD_PRELOAD environment variable allows you to load additional shared libraries at program startup. The LD_PRELOAD environment variable provides a colon-separated or space-separated list of shared libraries that the dynamic loader can interpret.
$ $ $ $ cc ld ld cc -c ?.c -b -o libB.so b.o -b -o libA.so a.o foo.c -L. -lA -lB ldd(1) shows the order in which the shared libraries are loaded: $ ldd a.out libA.so => libB.so => libc.so.1 => libdl.so.1 => ./libA.so ./libB.so /usr/lib/hpux32/libc.so.1 /usr/lib/hpux32/libdl.so.1 The symbol resolution order for the user libraries is: a.out- ->libA.so --> libB.so If the LD_PRELOAD environment variable is set to "./libC.so", the symbol resolution order is: $ export LD_PRELOAD=./libC.so $ ldd a.out .
$ export LD_PRELOAD="./libB.sl" $ ldd a.out ./libB.sl => ./libB.sl ./libB.sl => ./libB.sl libA.sl => ./libA.sl libB.sl => ./libB.sl libc.2 => /usr/lib/pa20_64/libc.2 libC.sl => ./libC.sl libD.sl = ./libD.sl libdl.1 => /usr/lib/pa20_64/libdl.1 a.out --> libD.sl --> libA.sl --> libB.sl --> libC.sl Case (ii): LD_PRELOAD = "./libD.sl" In 64-bit mode, the symbol resolution order is: $ export LD_PRELOAD="./libD.sl" $ ldd a.out ./libD.sl => ./libD.sl ./libD.sl => ./libD.sl libA.sl => ./libA.sl libB.sl => ./libB.
The symbol resolution order is: a.out --> libA.sl--> libC.sl --> libD.sl --> libB.sl Loading Shared Libraries with the LD_PRELOAD_ONCE Environment Variable The LD_PRELOAD_ONCE feature is similar to LD_PRELOAD except that the dynamic loader, dld.sl, unsets LD_PRELOAD_ONCE after reading it, so that any applications invoked by the current application do not have LD_PRELOAD_ONCE set.
If you create a shared library using the following command line, the modules are inserted into the library in alphabetical order: $ ld -b -o libabc.so *.o The potential problem with this ordering is that the routines in a.o and c.o are spaced far apart in the library. Better virtual memory performance can be attained by positioning the modules a.o and c.o together in the shared library, followed by the module b.o. The following command does this: $ ld -b -o libabc.so a.o c.o b.
Normally, the C compiler places constant data in the data space. If such data is used in a shared library, each process receives its own copy of the data. This may result in some performance degradation. Use the +ESlit/+Olit=all option to place constant data in the .text text segment instead of in the data space. This results in one copy of the constant data being shared among all processes that use the library.
$ ld -b impl1.o -o libimpl1.sl $ ld -b impl2.o -o libimpl2.sl $ ld -b +filter libimpl1.sl +filter libimpl2.sl -o libfilt.sl This builds a filtered shared library libfilt.sl with two implementation libraries libimpl1.sl and libimpl2.sl. 3. To confirm which implementation libraries are in the filter set, use odump to list the contents of the filter library: $ odump -filtertable libfilt.sl Filtered Shared Library List Table for libfilt.
... } Dynamic Path Lookup If you specify an embedded path while building the filtered shared library using the +b linker option, the dynamic loader attempts to use this dynamic path when it searches for the implementation library to load. For example: $ $ $ $ $ $ ld -b impl1.o -o libimpl1.sl ld -b +b /path/to/implementation/libs +filter\ ./libimpl1.sl -o libfilt.sl chatr +b enable libfilt.sl cc prog.c libfilt.sl -o prog mv libimpl1.sl /path/to/implementation/libs .
side-effects in programs that call the old version of the routine. In such cases, it is desirable to retain the old version as well as the new. This way, old programs continue to run and new programs can use the new version of the routine. Here are some guidelines to keep in mind when making changes to a library: • When creating the first version of a shared library, carefully consider whether or not you need versioning. It is easier to use library-level versioning from the start.
Creating a New, Incompatible Version of the Library When you create a new version of the library with incompatible changes, repeat the above steps except increment the number in the suffix of the shared library file name. That is, create libA.1 rather than libA.0, and set the symbolic link libA.so to point to libA.1. Applications linked with libA.0 continue to run with that library while new applications link and run with libA.1.
To use library-level versioning in this situation, you must set up corresponding file system links to make sure older applications linked with the older libraries run with these libraries. Otherwise, older applications can end up running with newer shared libraries. In addition, you must include the absolute path name in the internal name of the new library.
is a date, specified with a compiler directive in the source file. The syntax of the version number directive depends on the language: C and C++: #pragma HP_SHLIB_VERSION "date" FORTRAN: $SHLIB_VERSION 'date' Pascal: $SHLIB_VERSION 'date'$ The date argument in all three directives is of the form month/year. The month must be 1 through 12, corresponding to January through December. The year can be specified as either the last two digits of the year (94 for 1994) or a full year specification (1994).
$ cc -Aa -c +z length.c $ ld -b -o libunits.sl oldlength.o \ volume.o mass.o length.o Make new length.o. Relink the library. Thereafter, any programs linked with libunits.sl use the new versions of length-conversion routines defined in length.o. Programs linked with the old version of the library still use those routines from oldlength.o. For details on linking with shared libraries, see“Determining How to Link Programs or Libraries (Linker Tasks)” (page 27).
wrapper routine and the corresponding routine from the C library are copied into the a.out file. If, on the other hand, a shared wrapper library and archive C library are specified, in that order, then all routines that can be referenced by any routine in the wrapper library are copied from the C library. To avoid this, link with archive or shared versions for both the wrapper library and C library, or use an archive version of the wrapper library and a shared version of the C library.
Using the chroot Command with Shared Libraries Some users may use the chroot super-user command while developing and using shared libraries. This affects the path name that the linker stores in the executable file. For example, if you chroot to the directory /users/hyperturbo and develop an application there that uses the shared library libhype.so in the same directory, ld records the path name of the library as /libhype.so.
(3E) These functions constitute the ELF access library (libelf) which lets a program manipulate ELF (Executable and Linking Format) object files, archive files, and archive members. The linker searches this library if the -lelf option is specified. The header file provides type and function declarations for all library services (described in elf(3E). (3S) These functions comprise the Standard input/output routines (see stdio(3S)). They are located in libc.
Figure 13 Example 1: Unsatisfied Symbols: Mixing Shared and Archive Libraries Now link the main with the libraries, and create the executable a.out: $ cc main.o lib12.a lib3.so Link the program . Figure 14 Example 1: Unsatisfied Symbols: Creating the Executable When you run a.out, it runs correctly. Now, suppose you need to modify f3() to call f2(): Figure 15 Example 1: Unsatisfied Symbols: Modifying a Function Compile the new f3() and rebuild the shared library lib3.so: $ cc -c +z f3.
Figure 17 Example 1: Unsatisfied Symbols: Problem of Unsatisfied Symbol $ a.out /usr/lib/dld.so: Unresolved symbol: f2 (code) from /users/steve/dev/lib3.so Abort(coredump) Example 2: Using shl_load(3X) This example (in PA-32 and PA-64/IPF +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.
Figure 19 Example 2: Using shl_load(3X): Mixing Shared and Archive Libraries Now link the main with the archive library, and create the executable a.out: $ cc main.o lib12.a -ldld Link the program. Figure 20 Example 2: Using shl_load(3X): Creating the Executable When you run a.out, it runs correctly. Now suppose you need to modify f3() to call f2(): Figure 21 Example 2: Using shl_load(3X): Modifying a Function Problem Here is where a problem can be introduced.
Figure 22 Example 2: Using shl_load(3X): Rebuilding the Shared Library 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.so, the program aborts since f2() is not available in the program's address space. The reference to f2() from f3() remains unsatisfied, generating the PA-32 error message: Figure 23 Example 2: Using shl_load(3X): Problem of Unsatisfied Symbol $ a.
$ cc -c main.c $ cc -c +z f1.c f2.c f3.c Compile to relocatable code. Compile to position-independent code. Figure 24 Example 3: Hidden Definitions: Compiling Next suppose you put f3.o into the shared library lib3.so and f1.o and f2.o into the archive library lib12.a. Also put f1.o and f2.o into the shared library lib12.so: $ ld -b -o lib3.so f3.o $ ld -b -o lib12.so 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 27 Example 3: Hidden Definitions: Modifying a Function Compile the new f3(), and rebuild the shared library lib3.so including the new dependency on f2() in lib12.so: $ cc -c +z f3.c Compile to PIC. $ ld -b -o lib3.so f3.o -L . -l12 Create library with dependency. Figure 28 Example 3: Hidden Definitions: Rebuilding the Shared Library Problem Here is where the problem can occur in PA-32 +compat modes. If you do not relink the application, main.o, and just run a.out with the new version of lib3.
differences exist between these toolsets. The IPF linker toolset introduces different types of shared libraries. (In SVR4 Unix, shared libraries are sometimes called dlls.) • Compatibility mode shared library: Using the IPF linker, a compatibility mode shared library is basically a library built with ld -b +compat that has dependent shared libraries. The +compat option affects the way the linker and loader search for dependent libraries of a shared library and records their names.
Dynamic Path Searching for Shared Libraries Any library whose name has no "/" character in it becomes a candidate for dynamic path searching. Also, the linker always uses the 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.
void afunc() { printf ("\tin ARCHIVE library procedure 'afunc'\n"); } main.c main() { bfunc(); } If these files are compiled and linked as: $ cc -c main.c unsat.c archive.c $ cc -c +z sharedlib.c $ ld -b sharedlib.o -o libA.so $ ar rv libB.a archive.o $ cc main.o libA.so unsat.o libB.a -o test1 The PA-32 linker toolset produces: $ test1 in ARCHIVE library procedure `afunc' At link time, there is an outstanding unsatisfied symbol for afunc() when libB is found.
main.c main() { a(); } 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.so main.o liba.so -o test2 Using the PA-32 linker, test2 executes without error. The module in liba.so created from lib2.o is determined to be unreachable during execution, so the global symbol for unsat (in lib2.o) is not bound.
$ test3 object is 1 The PA-32 linker toolset defines the object global variable in libA.so as a storage export symbol. The dynamic loader, when searching for a definition of object to satisfy the import request in libA.so, does not stop with the storage export in that library. It continues to see if there is a data export symbol for the same symbol definition.
Figure 30 Search Order of Dependent Libraries The commands to build the libraries and the executable in Figure 30 (page 130) are given below. Note the link order of libraries in steps 2 and 3: 1. First, the dependent shared libraries for libA are built. (Other libraries are also built.) $ ld -b libDK.o -o libDK.so $ ld -b libLH.o -o libLH.so $ ld -b libD.o -IDK -ILH -o libD.so libA dependent shared library $ ld -b libE.o -o libE.so libA dependent shared library $ ld -b libF.o -o libF.
algorithms. For any standard mode library, it uses the IPF/PA-64-style algorithms. Only the load order of the libraries themselves is fixed between depth-first or breadth-first. If you use mixed mode shared libraries, the behavior is 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.
... libfile2a.so: *** Dynamic Section *** Index 0 1 2 ... Tag Value HPNeeded 0:/home/knish/./libfile2.1 HPNeeded 0:./libfile4.so Rpath /var/tmp Library Example: Creating an IPF Standard Mode Shared Library The following example builds a standard mode library: $ ld -b file1.o -o libfile1.so +h libfile1.1 $ ld -b file2.o -o libfile2.so +h ./libfile2.1 $ ld -b file3.o -o libfile3.so +h /var/tmp/libfile3.1 $ ld -b file4.o -o libfile4.so $ ld -b file3a.o -o libfile3a.so -L. -lfile1 -lfile3 +h libfile3a.
$ a.out dld.so: Unable to find library 'libfile2.1' $ export SHLIB_PATH=/var/tmp $ a.out in file1 in file2 Library Example: IPF Compatibility Mode Link This example builds a compatibility mode library and does a compatibility mode link. The +s option is not specified at link time, so the dynamic loader does not look at any environment variables to do dynamic path searching. # build compatibility mode dlls # libfile1.so is a dependent of libfile2.so ld -b file1.o -o libfile1.so +h libfile1.1 ld -b file2.
lib3.so has dependents lib3a.so and lib3b.so lib3a.so has dependent lib3aa.so +-->lib2a.so | +-->lib2.so-->lib2b.so | lib1.so-->lib3.so.so-->lib3a.so-->lib3aa.so | | | +-->lib3b.so +-->lib4.so In breadth-first searching, the load order is siblings before children: lib1.so->lib2.so->lib3.so->lib4.so->lib2a.so->lib2b.so->lib3a.so->lib3b.so->lib3aa.so In depth-first searching, the load order is children before siblings: lib1.so->lib2.so->lib2a.so->lib2b.so->lib3.so->lib3a.so->lib3aa.so->lib3b.so->lib4.
In the above example, if you type: $ ld main.o -L. -lbar -lc $ mv libme.so /var/tmp instead of: $ mv libme.so /var/tmp $ ld main.o -L. -lbar -lc the linker finds libme.so in ./ at link time, and the dynamic loader finds libme.so in /var/tmp at run time. At run time, the dynamic loader searches paths to resolve external references made by main in the following order: 1. ./libc.so not found /usr/lib/hpux32/libc.so found 2. SHLIB_PATH to find libbar.so not found 3. ./libbar.so (./libbar.so) found 4.
7 Shared Library Management Routines You can explicitly load and use shared libraries from your program. The linker toolset provides two families of load routines, dlopen and shl_load. The dlopen routines (primarily for IPF/PA-64 mode ) use Unix SVR4 compatible mechanism for library management. The shl_load routines support the shared library mechanisms provided in previous versions of HP-UX. NOTE: Support for shl_load library management routines may be discontinued in a future IPF/PA-64 HP-UX release.
Table 22 dl* routines for shared library management (continued) Routine Action “The dlmodremove Routine” (page 166) Removes information registered using dlmodadd. “The dlgetmodinfo Routine” (page 166) Retrieves information about a loaded module (program or shared library). All the dlopen routines are thread-safe. These routines are described in the dl*(3C) manpages.
#include If an error occurs when calling shared library management routines, the system error variable errno is set to an appropriate error value. Constants are defined for these error values in /usr/include/errno.h (see errno(2)). Thus, if a program checks for these error values, it must include errno.h: #include Throughout this section, all examples are given in C.
Fini Finalizers (finis) are called after the user's code terminates by either calling the libc exit function, returning from the main or _start functions, or when the shared library which contains the fini is unloaded from memory. Like init functions, functions specified with this option must not take arguments and return nothing (void functions). The C compiler pragma "fini" can be used to create them. For example: #pragma fini "my_fini" void my_fini() { ... do some clean up ...
use linker options (+init and +fini) to specify the initializers and terminators, and lib3.so uses compiler pragmas. C source for lib1.so (file lib1.c): lib1() { printf("lib1\n"); } void lib1_init() { printf("lib1_init\n"); } void lib1_fini() { printf("lib1_fini\n"); } C source for lib2.so (file lib2.c): lib2() { printf("lib2\n"); } void lib2_init() { printf("lib2_init\n"); } void lib2_fini() { printf("lib2_fini\n"); } C source for lib3.so (file lib3.
$ ld -b lib3.o -o lib3.so $ ld -b +init lib2_init +fini lib2_fini lib2.o -o lib2.so $ ld -b +init lib1_init +fini lib1_fini lib1.o ./lib3.so -o \ lib1.so $ cc -L. main.o -l1 -l2 -lc Output from running a.out: lib2_init lib3_init lib1_init lib1 lib2 lib3 lib1_fini lib3_fini lib2_fini Ordering Within an Executable or Shared Library Multiple initializers/terminators within the same load module (an executable or shared library) are called in an order following these rules: • Inits in .o (object) files or .
initializers is based on the priorities that are specified in the source code, or at compile time. If no priority is specified, the default priority settings are applied. The following example illustrates the ordering of initializers based on the priority specified at compile-time: $ cat main.C #include struct A { A() {printf("Constructing A\n");} }; A a; // This will be 1st initializer entry in a.
Using HP-UX 10.X Style Initializers The initializer is called for libraries that are loaded implicitly at program startup, or explicitly with shl_load or dlopen. When calling initializers for implicitly loaded libraries, the dynamic loader waits until all libraries have been loaded before calling the initializers. It calls the initializers in depth-first order - that is, the initializers are called in the reverse order in which the libraries are searched for symbols.
Initializer Syntax initializer The name of the initializer as specified with the +I linker option. handle The initializer is called with this parameter set to the handle of the shared library for which it was invoked. loading The initializer is called with this parameter set to 1 (true) when the shared library is loaded and 0 (false) when the library is unloaded. The initializers cannot be defined as local definitions.
} float in_to_cm(float in) { return (in * 2.54); } /* convert inches to centimeters */ float gal_to_l(float gal) { return (gal * 3.79); } /* convert gallons to litres */ float oz_to_g(float oz) { return (oz * 28.35); } /* convert ounces to grams */ You can use the +I linker option to register a routine as an initializer. Following are the commands to create libfoo.so and to register init_foo as the initializer: $ cc -Aa -c libfoo.c $ ld -b -o libfoo.so +I init_foo libfoo.
$ cc -Aa testlib.c -o testlib -ldld $ testlib libfoo 1.0in 1.0gal 1.0oz libfoo loaded = 2.54cm = 3.79l = 28.35g unloaded Example: A Common Initializer for Multiple Libraries Rather than have a unique initializer for each library, libraries can have one initializer that calls the actual initialization code for each library. To use this technique, each library declares and references the same initializer (for example, _INITIALIZER), which calls the appropriate initialization code for each library.
} C Source for libtwo.c #include void load() /* called after libtwo.so loaded */ { printf("libtwo.so loaded\n"); } void unload() /* called after libtwo.so unloaded */ { printf("libtwo.so unloaded\n"); } extern void _INITIALIZER(); void (*init_ptr)() = _INITIALIZER; void foo() { printf("foo called\n"); } void bar() { printf("bar called\n"); } Following are the commands used to build these libraries: $ $ $ $ cc ld cc ld -Aa -c libunits.c -b -o libunits.so +I _INITIALIZER libunits.o -Aa -c libtwo.
*/ printf("1.0in = %5.2fcm\n", (*in_to_cm)(1.0)); printf("1.0gal = %5.2fl\n", (*gal_to_l)(1.0)); printf("1.0oz = %5.2fg\n", (*oz_to_g)(1.0)); /* * Call routines from libtwo.so: */ (*foo)(); (*bar)(); /* * Unload the libraries so we can see messages displayed by initializer: */ shl_unload(hndl_units); shl_unload(hndl_two); } Following is the command to create the executable testlib2: $ cc -Aa -Wl,-E -o testlib2 testlib2.c init.
Table 24 Parameters Parameter Definition file Used to construct a pathname to the shared library file. If files contain a slash character (/), dlopen uses the file argument itself as the pathname. If not, dlopen searches a series of directories for file. • Any directories specified by the dynamic search path, which is set by calling dlsetlibpath • Any directories specified by the environment variable LD_LIBRARY_PATH. • Any directories specified by the variable SHLIB_PATH.
• file is not a shared object. • An error occurs during the process of loading file or relocating its symbolic references. More detailed diagnostic information is available through dlerror. Description The dlopen routine is one of a family of routines that give the user direct access to the dynamic linking facilities. The dlopen routine 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.
The following flags do not affect relocation processing, but provide the following features: RTLD_NODELETE: Under this mode, the specified object and its dependencies behave as if they were built with -B nodelete . An explicit unload using dlclose or shl_load returns success silently without detaching the shared library for the process. Subsequently, the shared library handle is valid only for shl_findsym.
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. In PA-32 mode, for a.out files, only a subset of externally visible symbols are typically exported: specifically those referenced by the shared libraries with which the a.out is linked.
{ void* handle; handle = dlopen("./lib1.so", RTLD_GLOBAL | RTLD_LAZY); if (handle == NULL) { printf("Cannot load library\n"); } } The following example illustrates the use of dlopene to load a shared library with an explicit data segment address. For simplicity, error checking has been omitted: #include #include
4. 5. 6. The embedded path of the calling module (executable program or shared library) for libraries names in calls to dlopen ,dlopene, or dlgetfileinfo. For dependent libraries, the embedded path of the library that named it as a dependent is used. The standard library path. The current working directory. (This is only for libraries named in calls to dlopen, dlopene, and dlgetfileinfo, not their dependent libraries.) See dld.
Multithread Usage This routine is thread-safe. Calls to dlsetlibpath affect all subsequent calls to dlopen, dlopene, and dlgetfileinfo on any thread. See also dlopen(3C), dlopene(3C), dlgetfileinfo(3C), dlerror(3C), dlerrno(3C), dld.so(5). Return Value If successful, dlsetlibpath returns 0, otherwise a non-0 value is returned. More detailed diagnostic information is available through dlerror or dlerrno.
valid shared library, dlgetfileinfo returns information about the library through the info parameter. The info_size is the size in bytes of the info buffer. The info is a pointer to a buffer allocated by the user program. The dynamic loader fills this buffer with file information. A dlfileinfo structure has the following members: struct dlfileinfo { size_t text_size; size_t data_size; char *filename; } The text_size is the size in bytes of a shared library's text segment.
* allocate_data(). */ } } Multithread Usage The dlgetfileinfo routine is thread-safe. Return Value If successful, dlgetfileinfo returns 0, otherwise a non-0 value is returned. More detailed diagnostic information is available through dlerror or dlerrno. Errors If dlgetfileinfo fails, a subsequent call to dlerrno returns an error. For a complete listing of those values, see the dlgetfileinfo (3C) manpage. The dlerror Routine The dlerror routine gets diagnostic information.
Table 25 Parameters Parameter Definition handle Either the value returned by a call to dlopen or one of the special flags RTLD_NEXT, RTLD_SELF, and RTLD_DEFAULT. In the former case, the corresponding shared library must not have been closed using dlclose. name The symbol's name as a character string. Return Values If handle does not refer to a valid shared library opened by dlopen, or if the named symbol cannot be found within any of the shared libraries associated with handle, dlsym returns NULL.
The following example shows how to use dlsym with RTLD_NEXT to add functionality to an existing interface. (Error checking has been omitted.) extern void record_malloc(void *, size_t); void * malloc(size_t sz) { void *ptr; void *(*real_malloc)(size_t); real_malloc = (void * (*) (size_t)) dlsym(RTLD_NEXT, "malloc"); ptr = (*real_malloc)(sz); record_malloc(ptr, sz); return ptr; } The dlget Routine The dlget routine retrieves information about a loaded module (program or shared library).
Using dlget to retrieve information about loaded modules The following code sequence shows how to use dlget to retrieve information about loaded modules. The code sequence prints the text base of all loaded modules: void* int struct handle; index; load_module_desc desc; for (index = -2; ; i++) { handle = dlget(i, &desc, sizeof(struct load_module_desc)); if (handle = NULL) { printf("%s\n", dlerror()); break; } else { printf("library %d text base = %lx\n", index, desc.
Description The dlmodinfo routine is one of a family of routines that give the user direct access to the dynamic linking facilities. The dlmodinfo routine retrieves information about a load module from a given address value. The dlmodinfo routine 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.
Table 28 Parameters Parameter Description 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. If the value is NULL, the dynamic loader uses its own internal data structures to find the correct load module and ignore the ident_parm and load_map_parm parameters.
Table 29 Parameters Parameter Definition handle 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 cannot be closed or if the handle does not refer to an open shared library, the dlclose routine returns a non-0 value. For more detailed diagnostic information you can use the dlerror routine.
Return Values If the specified address does not fall within one of the load modules, 0 is returned; the contents of the D1_info structure are not modified. Otherwise, a non-zero value is returned and the fields of the D1_info structure are set.
Using dladdr to get the symbolic information for an address The following example shows how to use dladdr to: #include typedef int (*fptr_t) (); int func1() {return 11;} int main() { D1_info di; char* symname = (char*)strdup("func1"); if (dladdr(&func1, &di) == 0) { printf("dladdr() failed for %s\n", symname); return 1; } if (di.dli_sname) { fptr_t tmp = (fptr_t)dlsym(di.dli_fbase, symname); if (di.dli_saddr !=void *)&func1) puts("approx match"); if (tmp != (fptr_t)di.
Description The dlmodadd routine registers information about a dynamically-generated function, which can be retrieved through the dlmodinfo routine. The dlmodremove interface can be used to remove the registered information. When dlmodadd is invoked to register information about a dynamically-generated function, the dynamic loader creates an unwind header and a single-entry unwind table for the function. The unwind header is associated with the address range occupied by the dynamically-generated function.
void *(*read_tgt_mem) (void* buffer, uint64_t ptr, size_t bufsiz, int ident), int ident_parm, uint64_t load_map_parm); Table 33 Parameters Parameter Definition 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.
} else { printf("text base = 0x%x\n", desc.text_base); } } 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 PA-32 and IPF/PA-64 mode. Support for these routines may be discontinued in a future Itanium or PA-64 HP-UX release. If you use these routines in Itanium or PA-64 mode, consider converting your programs to the dl* family of shared library management routines.
Flag Definition BIND_TOGETHER Causes the library being loaded and all its dependent libraries to be bound together rather than each independently. Use this when you have interdependent libraries and you are using BIND_FIRST. BIND_BREADTH_FIRST Causes the dependent libraries to be loaded breadth first. By default, shl_load loads dependent libraries depth-first. These flags are discussed in detail in the “shl_load Example” (page 170) .
shl_load Usage Since the library was not specified at link time, the program must get the library name at run time. Here are some practical ways to do this: • Hard-code the library name into the program (the easiest method). • Get the library name from an environment variable using the getenv library routine (see getenv(3C)). • Get the library path name from the command line through argv. • Read the library name from a configuration file. • Prompt for the library path name at run time.
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. ORing BIND_NONFATAL with BIND_IMMEDIATE causes shl_load to allow the binding of unresolved symbols to be deferred if their later use can be detected - for example: shl_t libH; . . . libH = shl_load("libxyz.
When used with BIND_DEFERRED and the BIND_NONFATAL modifier, it has the same behavior, except that when a symbol definition cannot be found, the dynamic loader looks in the global symbol set. If a definition still cannot be found within the global set, a run-time symbol-binding error occurs. BIND_TOGETHER Modifier BIND_TOGETHER modifies the behavior of BIND_FIRST. When the library being loaded has dependencies, BIND_FIRST causes each dependent library to be loaded and bound separately.
Parameters Parameter handle Definition A pointer to a shared library handle of the library to search for the symbol name sym. This handle can be obtained from the shl_get routine (“The shl_get and shl_get_r Routines” (page 175)). The handle parameter can also point to: NULL If a pointer to NULL is specified, shl_findsym searches all loaded libraries for sym. If sym is found, shl_findsym sets handle to a pointer to the handle of the shared library containing sym.
1. 2. 3. Declare a pointer to a data structure of the same type as the data structure to access in the library 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 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. Each graphics device has its own library.
if (shl_findsym(&lib_handle, DRAW2D, TYPE_PROCEDURE, (void *) &draw2d)) perror("shl_findsym: error finding function draw2d"), exit(1); if (shl_findsym(&lib_handle, MAXX, TYPE_DATA, (void *) &maxX)) perror("shl_findsym: error finding data maxX"), exit(1); if (shl_findsym(&lib_handle, MAXY, TYPE_DATA, (void *) &maxY)) perror("shl_findsym: error finding data maxY"), exit(1); /* * Using the routines, draw a line from (0,0) to (maxX,maxY): */ (*gopen)(); /* open the graphics device */ (*move2d)(0,0); /* move to
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. initializer A pointer to the shared library's initializer routine (see Initializers for Shared Libraries. It is NULL if there is no initializer. This field is useful for calling the initializer if it was disabled by the BIND_NOSTART flag to shl_load. If the shared library has multiple initializers, this field is also set to NULL.
The shl_gethandle and shl_gethandle_r Routines The shl_gethandle and shl_gethandle_r routines return 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.
Syntax int shl_definesym( const char *sym, short type, long value, int flags ) Parameters sym A null-terminated string containing the name of the symbol to change or to add to the process's shared library symbol table. type The type of symbol - either TYPE_PROCEDURE or TYPE_DATA. value If value falls in the address range of a currently loaded library, an association is made and the symbol is undefined when the library is unloaded.
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
: flags TYPE_PROCEDURE Retrieve only function or procedure symbols. TYPE_DATA Retrieve only symbols from the data segment (for example, variables).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 or TYPE_DATA is a data symbol used for C uninitialized global variables or Fortran common blocks. value Contains the symbol's address. It is valid only if EXPORT_SYMBOLS is specified without the NO_VALUES modifier.
printf(" STORAGE "); } if ((flags & EXPORT_SYMBOLS) /* export symbols requested && (flags & NO_VALUES)==0) /* NO_VALUES was NOT specified printf(" 0x%8X", symbols->value); /* so display symbol's address printf("\n"); /* terminate output line symbols++; /* move to next symbol record } free(orig_symbols); /* free memory allocated by malloc return num_symbols; /* return the number of symbols */ */ */ */ */ */ */ } The following example shows the source for a program named show_all.
TOTAL SYMBOLS: 9 [/usr/lib/libc.1] Imports: _res_rmutex errno _regrpc_rmutex _yellowup_rmutex _FPU_MODEL _environ_rmutex _iop_rmutex _rpcnls_rmutex _switch_rmutex _mem_rmutex _dir_rmutex STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE STORAGE The shl_unload Routine The shl_unload routine unloads or frees up space for a shared library. Syntax int shl_unload(shl_t handle) Parameters handle The handle of the shared library you wish to unload.
The shl_unload Routine Returning ETXTBSY When shl_unload returns -1 and sets errno to ETXTBSY, it means the library cannot be unloaded because it is still being used by the program or other shared libraries. This error occurs when a shared library cannot be unloaded for the following reasons: • Another dll (dynamic loading library) loaded by the program has an explicit dependency on the library. • The program has bound a symbol reference to some symbol defined by the library.
• BIND_RESTRICTED • 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 IPF PA-64 mode linker does not support the TYPE_STORAGE flag.
8 Writing and 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. This chapter assumes you have a good understanding of virtual memory concepts and memory management.
What is a 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. In order for the object code in a shared library to be fully shareable, it must not depend on its position in the virtual address space of any particular process.
X': ADDIL LDW LDW LDSID MTSP BE STW L'ltoff,%r19 ; get procedure entry point R'ltoff(%r1),%r21 R'ltoff+4(%r1),%r19 ; get new r19 value (%r21),%r1 %r1,%sr0 0(%sr0,%r21) ; branch to target %rp,-24(%sp) ; save rp ;Export Stub (Shared libs and Incomplete Executables) X': BL,N X,%rp ; trap the return NOP LDW -24(%sp),%rp ; restore the original rp LDSID (%rp),%r1 MTSP %r1,%sr0 BE,N 0(%sr0,%rp) ; inter-space return For More Information: The remainder of this section describes how compilers generate PIC for the
Long Calls Normally, the compilers generate a single-instruction call sequence using the BL instruction. The compilers can be forced to generate a long call sequence when the module is so large that the BL is not guaranteed to reach the beginning of the subspace. In the latter case, the linker can insert a stub.
An opportunity for optimization in both cases is to share a single label (L) throughout a procedure, and let the result of BL become a common sub-expression. Thus, only the first literal reference within a procedure is expanded to three instructions. The rest remain two instructions.
LDIL LP'function,%r1 LDO RP'function(%r1), %r22 ; Now to call the routine BL $$dyncall, %r31 ; r22 is the input register for $$dyncall COPY %r31, %r2 This code sequence generates the necessary PLABEL fixups that the linker needs in order to generate the proper procedure label. The dyncall millicode routine in /usr/lib/milli.a must be used to call a procedure using this type of procedure label, (that is, a BL or BV does not work).
9 Using Mapfiles This chapter describes with examples how to use the mapfile option. • “Controlling Mapfiles with the -k Option” (page 191) • “Changing Mapfiles with -k filename and +nodefaultmap” (page 191) • “Mapfile Example: Using -k mapfile and +nodefaultmap ” (page 191) • “Default HP-UX 11.
data data data data data data data data note note : : : : : : : : = : .data; $PROGBITS ?AW!S; .sdata; $PROGBITS ?AWS; .sbss; $NOBITS ?AWS; .bss; $NOBITS ?AW!S; NOTE; $NOTE; # text text = text : text : text : text : text : text : text : text : text : text : text : text : text : text : text : segment LOAD ?RX V0x04000000; .dynamic; .dynsym; .dynstr; .hash; .rela.dlt; .rela.plt; .rela.opd; $RELA ?A; $REL ?A; .IA_64.unwind_hdr; $UNWIND ?A; .IA_64.unwind_info; $PROGBITS ?A!X!W; .IA_64.milli; .
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 UNWI PBIT HP_O PBIT PBIT PBIT PBIT PBIT PBIT PBIT PBIT PBIT PBIT PBIT PREI INIT FINI PBIT NOBI NOBI NOBI NOBI PBIT NOTE STRT SYMT STRT 040066d8 040088ec 0400eb08 04013000 04016c08 04016ca8 04017858 04017980 0407cde0 40000000 400018c8 400018d0 400018f0 40001f28 40001f28 40001f28 40001f28 40001f28 400021f8 400022e0 40007700 40007728 00000000 00000000 00000000 00000000 00000000 000066d8 000088ec 0000eb08 00013000 00016c08 00016
text text text text text text text text text text text text text : : : : : : : : : : : : : # data data = data : data : data : data : data : data : data : data : data : data : data : data : data : data : data : data : data : .rela.init_array; .rela.fini_array; $RELA ?A; $REL ?A; .IA_64.unwind_hdr; $UNWIND ?A; .IA_64.unwind_info; .HP.opt_annot; $PROGBITS ?A!X!W; .IA_64.milli; .text; $PROGBITS ?AX!W; $OVLBITS ?AX!W; segment LOAD ?RWm V0x40000000; .zeropage; .hdata; .data; $PROGBITS ?AW!S; .preinit_array; .
text text text text text text text text text text text : : : : : : : : : : : # data data = data : data : data : data : data : data : data : data : data : data : data : data : data : data : data : data : $RELA ?A; $REL ?A; .IA_64.unwind_hdr; $UNWIND ?A; .IA_64.unwind_info; .HP.opt_annot; $PROGBITS ?A!X!W; .IA_64.milli; .text; $PROGBITS ?AX!W; $OVLBITS ?AX!W; segment LOAD ?RWmo V0x6000000000000000; .zeropage; .hdata; .data; $PROGBITS ?AW!S; .preinit_array; .init_array; .fini_array; .opd; .plt; .dlt; .
• The section, segment, file, and symbol names are case-sensitive. • A string of characters following # and ending at a new-line is considered a comment. 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.
Flag Action c Sets the "code" hint for a segment. When this flag is set, it indicates that the segment mostly contains code that may be executed. When not set, it indicates that it is unlikely that the segment contains code. This flag is not set by default. The code hint is off by default. 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.
• At most one section_type can be specified in a mapping directive. • If a section flag is preceded by an exclamation mark (!), it indicates that the flag must 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 : ?X; The linker maps all executable sections onto segment S1. • The section_name attribute indicates that the linker must map the input sections with the specified name onto the named segment. text : .
in which they are specified in the mapfile. The linker maps out the input sections in the same order as their matching entrance criteria. Figure 31 Map Structure Figure 31 (page 199) 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.
5. It places the new output section descriptor after the last output section descriptor associated with that entrance criteria. If no entrance criteria match is found, the linker places the section at the end of the "nonsegment". It does not create a program header entry for the nonsegment.
Warnings The following conditions can produce a warning message: • A physical_address or a virtual_address value is specified for any segment other than a LOADable segment. The directive is ignored. • A second declaration for the same segment changes an attribute value. The second declaration overrides the original. • An attribute value for a built-in segment is changed.
10 Improving Your Application Performance The linker provides several ways to improve your application performance. This chapter discusses the following topics: Section Description “Linker Optimizations” (page 202) Describes how the linker -O option removes unnecessary ADDIL instructions and "dead" or unused procedures. “Options to Improve TLB Hit Rates” (page 217) Describes performance improvements in Translation Lookaside Buffer (TLB) hit rates.
If invoked with +O4, the compilers generate object code in such a way that code optimization is done at link time. Thus, the linker does a better job of optimizing code that was compiled with +O4. When the compile and link phases are invoked by separate commands, specify +O4 on both command lines. For example: $ cc -c +O4 prog.c $ cc -o prog +O4 prog.
candidates for removal. If the address of a procedure is taken, the subspace within which it resides is not removed. If a subspace is referenced in any way by a fixup representing a reference other than a PC-relative call or an absolute call it is not removed Incomplete Executables For incomplete executables, dead procedure elimination works in the same way as for complete executables except that no exported symbols or their dependencies are removed.
Using PBO • “How to Use PBO” (page 205) • “Instrumenting (+I/-I)” (page 206) • “Profiling” (page 208) • “Optimizing Based on Profile Data (+P/-P)” (page 210) • “Selecting an Optimization Level with PBO” (page 212) • “Using PBO to Optimize Shared Libraries” (page 212) • “Using PBO with ld -r” (page 213) NOTE: The compiler interface to PBO is currently supported only by the C, C++, and FORTRAN compilers.
Assume you have two representative input files to use for profiling, input.file1 and input.file2. Now execute the following three commands: $ sample.inst < input.file1 $ sample.inst < input.file2 $ mv flow.data sample.data The first invocation of sample.inst creates the flow.data file and places an entry for that executable file in the data file. The second invocation increments the counters for sample.inst in the flow.data file. The third command moves the flow.data file to a file named sample.data.
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. The atexit system call allows a fixed number of functions to be registered from a user application. Instrumented applications (those linked with -I) have one less atexit call available.
Building Portable Code with Linker Optimization To build executables on a PA-RISC 2.0 system that run on 1.1 and 2.0 systems, compiled for optimization with +O4, +P, or +I, explicitly compile those components with +DAportable or +DA1.1. This is due to the code generation that the linker invokes at link-time for optimization. When you compile with +O4, +P or +I, your compiler builds an I-SOM (Intermediate code-System Object Module) file instead of a SOM file at compile time.
There are also certain non-terminating processes (such as servers, daemons, and operating systems) which never call exit. For these processes, you must programmatically write the profile data to the flow.data file. In order to do so, a process must call a routine called _write_counters(). This routine is defined in the icrt0.o file. A stub routine with the same name is present in the crt0.o file so that the source does not have to change when instrumentation is not being done. If flow.
in a particular directory, a lock file called flow.lock is used. Instrumented programs that need to update the flow.data file and linker processes that need to read it must first obtain access to the lock file. Only one process can hold the lock at any time. As long as the flow.data file is being actively read and written, a process will wait for the lock to become available. A program that terminates abnormally can leave the flow.data file inactive but locked.
Notice how the program is now linked with /usr/ccs/lib/crt0.o instead of /opt/langtools/lib/icrt0.o because the profiling code is no longer needed. 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.
$ cc +P -o prog.opt prog.c //Optimize it, but name it prog.opt. The linker is unable to find the program name prog.opt in the flow.data file and issues the error message No profile data found for the program prog.opt in flow.data To get around this problem, the compilers and linker provide the +pgm name option, which allows you to specify a program name to look for in the flow.data file. For instance, to make the above example work properly, you would include +pgm prog.
To profile shared libraries, you must set the environment variable SHLIB_FLOW_DATA to the file that receives profile data. Unlike FLOW_DATA, SHLIB_FLOW_DATA has no default output file. If SHLIB_FLOW_DATA is not set, profile data is not collected. This allows you to activate or suspend the profiling of instrumented shared libraries. Note that you can set SHLIB_FLOW_DATA to flow.data which is the same file as the default setting for FLOW_DATA.
Restrictions and Limitations of PBO This section describes restrictions and limitations you must be aware of when using Profile-Based Optimization. This section discusses the folowing topics: • “Temporary Files” (page 214) • “Source Code Changes and PBO” (page 214) • “Profile-Based Optimization (PBO) and High-Level Optimization (HLO)” (page 214) • “I-SOM File Restrictions” (page 215) NOTE: PBO calls malloc() during the instrumentation (+I) phase.
When +I is specified along with +O3 or +O4, an I-SOM file is generated. However, HLO is not performed during I-SOM generation. When the I-SOM file is linked, using the +P option to do PBO, HLO is performed, taking advantage of the profile data. Example 18 The following example illustrates high-level optimization with PBO: $ cc +I +O3 -c file.c //Create I-SOM for instrumentation. $ cc +I +O3 file.o //Link with instrumentation. $ a.
$ size foo.o 0 + 0 + 0 = 0 strip Do not run strip on files compiled with +I or +P. Doing so results in an object file that is essentially empty. Compiler Options Except as noted below, all cc, CC, and f77 compiler options work as expected when specified with +I or +P: Compiler Options Description -g This option is incompatible with +I and +P.
Options to Improve TLB Hit Rates To improve Translation Lookaside Buffer (TLB) hit rates in an application running on an Itanium-based or 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.
debugger with incremental-linking support. The linker performs the following different modes of linking: • Normal link: the default operation mode in which the linker links all modules. • Initial incremental link: the mode entered when you request an incremental link, but the output module created by the incremental linker does not exist, or it exists but the incremental linker is unable to perform an incremental update.
• Modules have been modified by the ld -s or ld -x options or tools (for example, strip(1)). The incremental linking requires the parts of the output load module which are stripped out with these options. • Incompatible incremental linker version, when you run a new version of the incremental linker on an executable created by an older version. • New working directory, where the incremental linker performs an initial incremental link if current directory changes.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.
Generally, the linker needs to scan through all shared libraries on a link line in order to determine all the unsats, even in incremental links. This process may slow down incremental links. The incremental linker does not scan shared libraries and leaves detection of shared library unsats to the dynamic loader. It is not recommended that you use the incremental linker to create final production modules.