Copyright 2007 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
The contents of this file are subject to the terms of the
Common Development and Distribution License (the "License").
You may not use this file except in compliance with the License.
You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
or http://www.opensolaris.org/os/licensing.
See the License for the specific language governing permissions
and limitations under the License.
When distributing Covered Code, include this CDDL HEADER in each
file and include the License file at usr/src/OPENSOLARIS.LICENSE.
If applicable, add the following below this CDDL HEADER, with the
fields enclosed by brackets "[]" replaced with your own identifying
information: Portions Copyright [yyyy] [name of copyright owner]
CDDL HEADER END
check_rtime attempts to check a number of ELF runtime attributes for consistency with common build rules. These checks involve running ldd(1) and elfdump(1) against a family of dynamic objects. A dynamic object can be defined explicitly as a file or multiple dynamic objects can be located under the directory dir.
check_rtime is typically called from nightly(1) when the -r option is in effect. In this case the dynamic objects under the associated proto area ($ROOT) are checked. check_rtime can also be run standalone against any set of dynamic objects.
check_rtime uses ldd(1) to verify dependencies. This implies that by default any object inspected will bind to its dependencies as they are found in the underlying system. Use of the -d option, or the existence of the environment variables $CODEMGR_WS/$ROOT instruct check_rtime to establish an alternative dependency mapping using runtime configuration files generated with crle(1).
check_rtime uses ldd(1) to completely relocate any dynamic object and thus detect missing dependencies, unsatisfied symbol relocations, unused and unreferenced dependencies. These checks are carried out for the following reasons:
4 An object that cannot find its dependencies may fail to load at runtime. This error condition often goes unnoticed because the existing use of the object is as a dependency itself, and the objects' dependencies are already satisfied by the caller. However, if the object itself is unable to satisfy its dependencies its use in new environments may be compromised. A missing or erroneous runpath is the typical reason why an object can not locate its dependencies. Use of the link-editors -zdefs option when building a shared object ensures required dependencies are established. This flag is inherited from $(DYNFLAGS) in lib/Makefile.lib. Missing dependencies are displayed as:
foo: bar.so.1 => (file not found) <no -zdefs?>
Unsatisfied symbol relocations indicate that some thread of execution through the object will fail when it is unable to locate a referenced symbol. A missing, or mismatched version of a dependency is the typical reason for unsatisfied symbol relocations (see missing dependency discussion above). Unsatisfied symbol relocations are displayed as:
foo: symbol not found: bar <no -zdefs?>
Unused dependencies are wasteful at runtime, as they take time to load and relocate, but will not be used by the calling object. They also result in unnecessary processing at link-edit time. Dependency lists (typically defined via $(LDLIBS)) that have been yanked-and-put between Makefiles without verifying their need, is a typical reason why unused dependencies exist. Unused dependencies are displayed as:
foo: unused object=bar.so.1 <remove lib or -zignore?>
Unreferenced dependencies are also wasteful at runtime, although not to the extent of unused dependencies. They also result in unnecessary processing at link-edit time. Unreferenced dependency removal guards against a dependency becoming unused when combined with different objects, or as the other object dependencies evolve. Unreferenced dependencies are displayed as:
See also the section ENVIRONMENT VARIABLES.check_rtime uses elfdump(1) to look for a concatenated relocation section in shared objects, the existence of text relocations, whether debugging or symbol table information exists, whether applications have a non-executable stack defined, and for duplicate entries in the symbol sorting sections. These checks are carried out for the following reasons:
4 A concatenated relocation section (.SUNW_reloc) provides optimal symbol table access as runtime, and thus reduces the overhead of relocating the shared object. The link-edit of a dynamic object with the -z combreloc option is required to generate a combined relocation section. Not inheriting $(DYNFLAGS) from lib/Makefile.lib is the typical reason for not having a concatenated relocation section. A missing concatenated relocation section is displayed as:
foo: SUNW_reloc section missing <no -zcombreloc?>
Text relocations result in impure text segments. As text segments are typically read-only, they can be shared between numerous processes. If they must be updated as part of the relocation then the updated pages become unshareable and swap space must be allocated to back these pages. These events consume unnecessary system resources and reduce overall system performance. Not inheriting the $(PICS) rules from lib/Makefile.lib is the typical reason for having non-pic code in shared objects. Text relocations are displayed as:
foo: TEXTREL .dynamic tag <no -Kpic?>
Debugging information is unnecessary in released objects. Although extensive when compiled -g, small quantities of debugging information are stored in .stabs sections under normal compilations. This debugging information is geared towards aiding debuggers locate relocatable objects associated with the dynamic objects being debugged. As relocatable objects aren't made available as part of a software release this information has no use. Not inheriting the correct $(LDFLAGS) from cmd/Makefile.cmd (which asserts -s), or $(POST_PROCESS_SO) (which asserts strip -x) are typical reasons for not removing debugging information. Note, removal of debugging information is only enabled for release builds. The existence of debugging information is displayed as:
foo: debugging sections should be deleted <no strip -x?>
All objects should retain their full .symtab symbol table. Although this consumes disk space, it provides for more extensive stack tracing when debugging user applications. Hard coding a -s flag with $(LDFLAGS) or $(DYNFLAGS) is the typical reason for symbol tables being removed. Objects that do not contain a symbol table are displayed as:
foo.so.1: symbol table should not be stripped <remove -s?>
Applications should have a non-executable stack defined to make them less vulnerable to buffer overflow attacks. Not inheriting the $(LDFLAGS) macro in cmd/Makefile.cmd is the typical reason for not having a non-executable stack definition. Applications without this definition are displayed as:
foo: application requires non-executable stack \\
<no -Mmapfile_noexstk?>
X86 applications should have a non-executable data segment defined to make them less vulnerable to buffer overflow attacks. Not inheriting the $(LDFLAGS) macro in cmd/Makefile.cmd is the typical reason for not having a non-executable data definition. Applications without this definition are displayed as:
foo: application requires non-executable data \\
<no -Mmapfile_noexdata?>
Solaris ELF files contain symbol sort sections used by DTrace to map addresses in memory to the related function or variable symbols. There are two such sections, .SUNW_dynsymsort for regular symbols, and .SUNW_dyntlssort for thread local symbols. To ensure that the best names are shown for each such address, and that the same name is given across Solaris releases, check_rtime enforces the rule that only one symbol can appear in the sort sections for any given address. There are two common ways in which multiple symbols or a given address occur in the ON distribution. The first is from code written in assembly language. The second is as a result of using #pragma weak in C to create weak symbols. The best solution to this situation is to modify the code to avoid symbol aliasing. Alternatively, the NODYNSORT mapfile attribute can be used to eliminate the unwanted symbol. Duplicate entries in a symbol sort section are displayed in one of the following ways, depending on whether the section is for regular, or thread local symbols:
foo: .SUNW_dynsymsort: duplicate ADDRESS: sym1, sym2
foo: .SUNW_dyntlssort: duplicate OFFSET: sym1, sym2
check_rtime also uses elfdump(1) to display useful dynamic entry information under the -i option. This doesn't necessarily indicate an error condition, but provides information that is often useful for gatekeepers to track changes in a release. Presently the information listed is:
Runpaths are printed for any dynamic object. This is a historic sanity check to insure compiler supplied runpaths (typically from CC) are not recorded in any objects. Runpaths are displayed as:
Needed dependencies are printed for any dynamic object. In the freeware world this often helps the introducer of a new shared object discover that an existing binary has become its consumer, and thus that binaries package dependencies may require updating. Dependencies are printed as:
foo: NEEDED=bar.so.1
check_rtime uses mcs(1) to inspect an objects .comment section. During development, this section contains numerous file identifiers marked with the tag "@(#)". For release builds these sections are deleted and rewritten under control of the $(POST_PROCESS) macro to produce a common release identifier. This identifier typically consists of three lines including a single comment starting with the string "@(#) SunOS". If this common identifier isn't found the following diagnostic is generated:
foo: non-conforming mcs(1) comment <no $(POST_PROCESS)?>
The following options are supported:
4 -a Process all dynamic objects found. As with all attempts to follow standard build rules, there are always exceptions. As check_rtime was primarily designed to process a nightly builds $ROOT hierarchy, and there exist numerous OSNet components that fail its tests, check_rtime maintains a list of directories and files (as they exist in a $ROOT directory hierarchy) that will be skipped during its processing. Use of -a prevents this component skipping. In addition there are a couple of optimizations within check_rtime directory traversal that improve the scripts performance. Use of -a ignores these optimizations.
-d depdir Use depdir to generate an alternative dependency mapping.
-i Provide dynamic entry information. Presently only dependencies and runpaths are printed. Note, any references to libintl.so.1 or libw.so.1 are flagged as being unnecessary as all the interfaces provided by these shared objects were folded into libc in Solaris 5.6.
-m Enable mcs(1) checking.
-o Produce a one-line output for each condition discovered, prefixed by the objects name. This output style is more terse, but is more appropriate for sorting and diffing with previous build results.
-s Determine whether .stabs sections exist.
To achieve this, check_rtime uses the directory specified with the -d option, or the existence of the environment variables $CODEMGR_WS and $ROOT to generate a list of available shared objects. This list is used to create runtime configuration files via crle(1), that establish the new shared objects as alternatives to their underlying system location. check_rtime passes these configuration files as LD_CONFIG environment variable settings to ldd(1) using its -e option.
The effect of these configuration files is that the execution of an object under ldd(1) will bind to the dependencies defined as alternatives. Simply put, an object inspected in the proto area will bind to its dependencies found in the proto area. Dependencies that have no alternative mapping will continue to bind to the underlying system.
When the -d option isn't in use check_rtime uses the following environment variables to establish an alternative dependency mapping:
CODEMGR_WS
The root of your Teamware workspace, which is the directory containing Codemgr_wsdata. Existence of this environment variable indicates that $ROOT should be investigated.
ROOT
Root of the proto area of your Teamware workspace. Any shared objects under this directory will be used to establish an alternative dependency mapping.
RELEASE
The release version number of the environment being built.
Use of an alternative dependency mapping requires ldd(1) -e. This option is relatively new (see 4390308 integrated in s81_30), thus check_rtime validates ldd(1) before attempting to create an alternative dependency mapping. An older version of ldd(1) will be caught as:
ldd: does not support -e, ....
Inspection of an object with ldd(1) assumes it is compatible with the machine on which check_rtime is being run. Incompatible objects such as a 64-bit object encountered on a 32-bit system, or an i386 object encountered on a sparc system, can not be fully inspected. These objects are displayed as:
foo: has wrong class or data encoding