General QuestionsQ: Appcert is a Perl script; which version of Perl does it work with?
How can I get a copy of Perl?
A:
The appcert script works with either version 4 or 5 of Perl.
Perl 5 is included in Solaris 8. Binaries for previous release of
Solaris can be found at www.sunfreeware.com. You can also download
the source for Perl, and the pre-compiled binaries for some
platforms, from any site in the Comprehensive Perl Archive Network
(CPAN). See The Perl Institute (www.perl.org) or the Perl Language
Home Page (www.perl.com).
Q: When trying to install appcert I get errors "Invalid character (0x0)",
"tar: directory checksum error", etc. What is happening?
A:
Most likely this indicates a failed or partial download of the
installation script (e.g. "appcert_install.sparc.sh"). The 2nd line
of that file should contain checksum information that will allow you
to perform a sum(1) checksum of the whole installation script. If
the checksums do not match you will need to try downloading the file
again. If the installation script checksum matches correctly,
another possibility is that you do not have enough disk space in
/tmp or in the destination directory to install the tool.
Q: What OS releases does appcert support? Are there any plans to support
SunOS 4.x (Solaris 1)?
A:
Appcert can examine applications written for Solaris 2.3 to Solaris 9
and beyond. There are no plans to support SunOS 4.x or releases of
Solaris prior to 2.3.
Q: What languages does appcert support?
A:
As long as the resulting binary objects constituting the application rely
on dynamic linking (i.e., access Solaris services via dynamic bindings to
C-language interfaces in Solaris shared libraries), it doesn't matter what
source code they were derived from -- appcert will work on them. Binaries
produced from FORTRAN, Mainsail and other languages have already been
checked.Appcert doesn't work on Java programs, because they rely on a different
runtime interface -- the Java virtual machine (this might be called the
Java ABI). For Java applications please refer to
http://developer.java.sun.com/
for information on developing stable
applications. Appcert currently does not check usage of symbols in the C++ runtime
interfaces (libC.so.3 or libC.so.5) because there is no defined C++ ABI
to be part of the current Solaris system ABI definition. We expect such
a C++ ABI to be defined eventually and will then include it in the
Solaris ABI.Finally, appcert also doesn't check interpreted code such as shell
scripts, Perl scripts, or Tcl scripts.
Q: What programming interfaces are covered by appcert?
A:
The components currently covered are: all of the C programming interfaces
included (bundled) in the Solaris product. That is, all of the interfaces
in the base system and networking areas (/usr/man/man{2,3}), OpenWindows
(/usr/openwin/man), and CDE (Motif) (/usr/dt/man).
Q: How long will it take to check my application?
A:
Appcert takes about 1-10 seconds to examine each binary object in an
application. Very large application binaries will take longer, as
will work done over NFS or on slower processors. See the "-1" option
for a faster mode of checking.
Q: Can I use appcert to examine just a .so file?
A:
Yes, but make sure that the library's dependencies are recorded in
the shared object (by using the compiler's "-l" "-R" and "-z defs"
options. Also, in Solaris 2.6 and earlier, the compiler will not record
a dependency on libc unless "-lc" is explicitly used on the command line.
Q: How do I get started analyzing the output of appcert?
A:
Here is a three-step to procedure to follow:
Step 1. See if appcert was able to check all of your binaries completely.
If not, determine if incomplete checking was due to an inherent
limitation in appcert (e.g., appcert can't check calls to the
C++ library libC), or to the runtime environment (e.g.,
LD_LIBRARY_PATH) not being properly set up. If necessary,
rerun appcert.Step 2. Check for unbound symbols in shared object binaries. These may
be due to your application's using dlopen() to access the
shared object; appcert has difficulty resolving the symbol
bindings in that case (see the appcert man page for more
information).Step 3. Check for private symbol usage. If appcert reports that your
application uses a private symbol, but you can't find any
occurrence of it in your source code, then the reference is
probably coming from a statically linked library; these cases can
be ignored (though you should use dynamically linked libraries
whenever possible). If you are actually using a private interface
in a library, check the documentation to find the appropriate
public interface to use instead.
Q: Appcert claims my application calls private interfaces such as
_mutex_unlock() and _dgettext(). My source code contains no references
to these symbols, or anything even vaguely related to them. Is appcert
confused?
A:
This is a problem with statically linking libraries into
applications: the archives linked in may themselves make calls to
private symbols in Solaris shared objects. Because the archive is
statically linked in, to appcert it appears your application is
making these private calls itself (which, in a sense, it is).For historical reasons, releases prior to Solaris 7 provided only
static archives for the libraries in /usr/ccs/lib (e.g., libcurses.a,
libtermcap.a, libgen.a, and libmalloc.a). Unfortunately a small
number of calls to private symbols occur in these static archives:
for example, _mutex_unlock() is called from libmalloc.a and
_dgettext() is called from libcurses.a. If your build environment
includes linking command-line flags such as "-lmalloc" or "-lcurses",
then there is a good chance you will statically link in the archives
along with the private symbol calls--even if you have not explicitly
used the "-Bstatic" option (this is because the linker will use an
archive version of the library if it cannot find a shared version of it).Some build environments (e.g., imake) will automatically add linking
flags like "-lmalloc". Developers may not always want this,
preferring instead the malloc() family of functions in libc.so.1 to
the ones in /usr/ccs/lib/libmalloc.a.To increase binary stability, we encourage developers to move away from
linking Solaris static archives when building their applications; as of
Solaris 7, shared object versions of the static archives in /usr/ccs/lib
are now available. We understand this may be difficult because it
requires you to provide two sets of binaries: one for Solaris 2.6 and
earlier and a second for Solaris 7 and later. If you are porting some
or all of your product to 64 bits, that may be a good time to remove all
of the Solaris static archive linking in your application.To be on the safe side, appcert will flag as errors private symbol
calls resulting from static linking.Here is a table created by correlating the private symbols in
libc.so.1 (found via pvs(1)) with the UNDEF symbols (found via
elfdump(1)) in the Solaris archive libraries:
Solaris library archive: private symbol in libc.so the archive calls:
/usr/ccs/lib/libcurses.a: _dgettext
/usr/ccs/lib/libcurses.a: _doscan
/usr/ccs/lib/libgen.a: _thr_getspecific
/usr/ccs/lib/libgen.a: _thr_keycreate
/usr/ccs/lib/libgen.a: _thr_setspecific
/usr/ccs/lib/libgen.a: _thr_main
/usr/ccs/lib/libgen.a: _mutex_unlock
/usr/ccs/lib/libmalloc.a: _mutex_unlock
/usr/ccs/lib/libtermcap.a: _dgettext
/usr/ccs/lib/libtermcap.a: _doscan
/usr/ccs/lib/libtermlib.a: _dgettext
/usr/ccs/lib/libtermlib.a: _doscan
/usr/openwin/lib/libxview.a: _doscan
/usr/lib/libbsm.a: _mutex_unlock
/usr/lib/libcrypt.a: _mutex_unlock
/usr/lib/libcrypt.a: _thr_getspecific
/usr/lib/libcrypt.a: _thr_keycreate
/usr/lib/libcrypt.a: _thr_setspecific
/usr/lib/libelf.a: _dgettext
/usr/lib/libelf.a: __threaded
/usr/lib/libmapmalloc.a: _mutex_unlock
/usr/ucblib/libcurses.a: gtty
/usr/ucblib/libcurses.a: stty
/usr/ucblib/libcurses.a: _doscan
/usr/ucblib/libucb.a: _getsp
/usr/ucblib/libucb.a: __getcontext
/usr/ucblib/libucb.a: _cerror
/usr/ucblib/libucb.a: _memcmp
/usr/ucblib/libucb.a: _memmove
/usr/ucblib/libucb.a: _memset
/usr/ucblib/libucb.a: _psignal
/usr/ucblib/libucb.a: _smbuf
/usr/ucblib/libucb.a: _setbufend
/usr/ucblib/libucb.a: _siguhandler
/usr/ucblib/libucb.a: __sigaction
/usr/ucblib/libucb.a: _findiop
/usr/ucblib/libucb.a: _doprnt
/usr/ucblib/libucb.a: _realbufend
/usr/ucblib/libucb.a: _bufsync
/usr/ucblib/libucb.a: _findbuf
/usr/ucblib/libucb.a: _xflsbuf
/usr/ucblib/libucb.a: _ecvt
/usr/ucblib/libucb.a: _fcvt
One can use this table to try to find any false positives of this
sort that appcert warns about. Find the occurrences of the private
symbol in the right hand column, then if you know the application
statically links any of the corresponding archives in the left hand
column that is most likely the reason for the appcert warning.
Q: Why can't I statically link with archives like libc.a and libsocket.a?
After all, Sun provides many of them to me in /usr/lib.
A:
Sun provides the archives because in some circumstances static linking
cannot be avoided, for example if security is an issue or if one is
constructing a boot-time or other administrative tool that has to run
when dynamic linking is not operational. In general, it is an unsafe
practice because the older code you statically link into your application
may have private interfaces that do not cooperate properly with newer
Solaris system components. From the intro(4) manpage:For many shared objects, an archive library is provided for
backward compatibility. Use of these libraries may restrict
an applications ability to migrate between different Solaris
releases. As dynamic linking is the preferred compilation
method on Solaris, the use of these libraries is
discouraged.As a specific example of this sort of binary breakage, one can
create a small TCP/IP client program that calls socket(3N) and
connect(3N) to connect to a network service. When you build that
program on Solaris 2.5 and statically link libsocket.a, the program
will run fine on Solaris 2.5 and 2.5.1. However, if you take
that binary to Solaris 2.6 or later and attempt to run it, the
socket(3N) call will fail with an error. This is because in release
2.6 Solaris moved from STREAMS-based sockets to in-kernel sockets.
Older network applications *dynamically* linked with libsocket.so.1
continue to run properly on 2.6 and above; it is only the ones
statically linked with libsocket.a that have problems.
Q: Why does appcert complain about applications which statically link only
libc, libnsl, libsocket, etc, but not ones which statically link
some other libraries like libXm?
A:
Generally speaking, statically linking libraries is a bad idea, and is
discouraged as a default practice in developing with Solaris. Statically
linking libc, libnsl, or libsocket is a very bad idea, and is a major
source of the stability problems we see with applications, hence appcert
looks specifically for static linking of those libraries. In the future,
appcert may check for others as well.
Q: Appcert complains that I'm using __rpc_createerr(), but it isn't in
my code and I'm not statically linking any libraries. What is going on?
A:
Note, however, under certain build conditions the header file
/usr/include/rpc/clnt.h will replace rpc_createerr by a macro that
expands to involve __rpc_createerr(). This occurs when _REENTRANT is
defined, and makes your application depend directly on the private
symbol __rpc_createerr.If your application was compiled in this environment it causes
static analysis tools like appcert to give a "false positive"
(there is not much a binary analysis tool can easily do to see that
the source code did not directly reference the private symbol).
If your source code does not directly reference __rpc_createerr() you
should be OK.
Q: Appcert reports a number of unbound symbols in one of my application's
shared objects, but they are symbols in Solaris libraries that the
shared object calls. Why doesn't appcert recognize them?
A:
This situation arises when the shared object does not record its
dependencies and is dlopen'ed by the application rather than linked.
Since the shared object is never linked, and appcert uses the linker to
resolve symbols, appcert cannot figure out what is going on unless the
shared object records its dependencies. Since the default compiler
behavior is to NOT record dependencies in shared objects, this situation
frequently happens with dlopen'ed shared objects.
To avoid this problem, make sure that when a shared object is built,
its dependencies on Solaris libraries are explicitly recorded by using the
the "-l" and "-R" compiler options, and force symbol resolution at compile
time with the "-z defs" options. See the man pages for cc and ld.
Q: Appcert claims that a documented public interface is private.
Isn't this a bug?
A:
Sometimes. Examples are "mkstemp" in libc, and "gethostname" in
libnsl, which were misclassified in those libraries' definitions
prior to Solaris 7. Remember, however, that by "public" appcert
means "stable"; there are a number of experimental or evolving
interfaces that are available for use, but which are unsuitable for
building applications that are intended to be binary compatible with
future releases of Solaris. Appcert classifies such interfaces as
"private" so that you will know about their potential instability.
Q: What does it mean when appcert complains about an application because
it couldn't find a library?
A:
Appcert looks in the list of directories specified by the current
LD_LIBRARY_PATH (and finally in /usr/lib) for libraries containing
the symbols used by an application. If a non-Solaris library is used
by the application, but is not on LD_LIBRARY_PATH, then appcert cannot
find those symbols unless the "-R" option was used at build time to
specify where the libraries were located. The presence of unbound symbols
and/or failure to find a library will cause appcert to fail an application.
Q: When I run appcert on the dynamic libraries in /usr/lib I get results
that don't make sense. Why?
A:
Appcert is a tool for testing YOUR application's dependencies on the
Solaris system libraries (i.e the shared objects in /usr/lib,
/usr/dt/lib, /usr/openwin/lib, ...). It examines your application to
see what interfaces it depends on in the Solaris system libraries,
and then checks to see that only stable, public interfaces are used.
If you run appcert on the very shared libraries that it checks
against, the outcome may be unpredictable. Please note that since the
Solaris system libraries are a bundled product, it is all right for
one of the those libraries to call private symbols in another because
Sun makes sure the bundled shared objects cooperate correctly.
Q: Why can't I use symbols like "_select", the way I can use "_read"?
A:
The "strong" symbols (e.g. _socket) associated with "weak" symbols
(e.g. socket) are reserved as private (their behavior could change in
the future). Your application should only directly reference the weak
symbol (usually the strong symbols begin with "_"). Note that the
weak symbol is typically an alias for the strong symbol, not a
wrapper, so there is no performance penalty in using it.Unless your application is trying to do something very special (e.g.
intercepting system library calls from code that is not under your
control) use the corresponding public symbols.Note: under certain build environments it may happen that the
strong/private symbol dependency gets recorded into your binary instead
of the weak/public one, even though the source code doesn't appear to
reference the private symbol. Nevertheless, steps should be taken
to trace down why this is occurring and fix the dependency.
Q: Why can't I use getdomainname in libnsl? What should I use instead?
A:
In Solaris, libnsl's getdomainname() is a private interface, unlike in
some other UNIX implementations. In some cases there is an ambiguity
about DNS domain vs. NIS domain.A replacement for getdomainname() depends on what it is being used
for. In the case of DNS, the traditional way of doing this is to
call res_init(3N) and look in a deprecated data structure. This is
not supported. To obtain the NIS domain the documented way is to
use "sysinfo(SI_SRPC_DOMAIN)".
Q: What's so bad about using sys_errlist and sys_nerr?
A:
Briefly, there are two reasons:
Q: Can appcert tell me if my application will run on Solaris version "N"?
A:
Not directly. Appcert will only tell you if your application is at
risk of not running because it uses unstable library interfaces. If
those interfaces have not changed (yet) in Solaris "N", then your
application may still run without failure. Conversely, since
appcert only checks library interfaces, it cannot warn about other
unstable practices such as relying on private non-library interfaces
in Solaris (for example, the format of various files in /etc). In
those cases, appcert may not find any binary stability problems, yet
your application may not run on Solaris "N".
Q: What can appcert tell me about backwards compatibility? For example,
if I build my application on Solaris 8, will it run on 7, 2.6, etc?
A:
You can test your Solaris 8 application on a Solaris 8 machine against
an earlier model such as Solaris 7 or 2.6. See the "-c" option.
Q: I have an application which is OK on Solaris Sparc 2.6.
Do I have to run appcert on the software on Solaris 8 and 9 as well?
A:
You do not need to run appcert, but, depending on the risks involved,
to ensure that your application has no unstable behavioral or
environmental dependencies (which appcert does not check for: e.g.
an application that opens a private system file or parses
human-readable output from a command), one should do some testing of
the application on later releases as well.
Q: I have an application which is OK on Solaris Sparc 7,
and have ported the software to Solaris X86. Do I need a separate
run of appcert for this?
A:
Yes, those X86 binaries need to be separately exercised on their
platforms and run through appcert.
Note that in this case, appcert must be run again - because you are
checking a different binary object (an x86 binary rather than a SPARC
one). Since there are some minor differences between the Solaris SPARC
and x86 ABI's with regard to some of the compiler-emitted intrinsics for
low-level use of the processor's instruction set, there is a slim
possibility that an x86 binary compiled from the same source code as a
SPARC binary could have had unstable binary interfaces in the emitted
x86 code.
Q: What's an ABI (vs. an API)?
A:
The API is the source level interface which is used when source code is
compiled to produce a binary object. The ABI is the resulting set of
binary level interfaces that the compiled application relies on at runtime.
We're concerned with the ABI since we want a given binary object already
out in the field to continue to run on subsequent OS releases.
Q: So how do I find out which interfaces are public? Conversely, which ones
should I stay away from?
A:
The public programming interface to Solaris at the source level (the
Solaris API) is represented by what's in the Solaris man pages (most
notably sections 2 and 3 of /usr/man, /usr/openwin/man, /usr/dt/man, and
so on for unbundled products). If you compile a program which uses only
these interfaces it is virtually certain that you'll have a Solaris
ABI-conforming binary object. See also the library specific man pages in
section 4 to find lists of public symbols (Solaris 2.6 and above).Do not assume, however, that any interface you find in a Solaris header
file is public (i.e. part of the API). Some interfaces present in Solaris
header files are private, and are there only because the Solaris system
implementation is built using these same header files.
So: * Write code using only the Solaris API (those source-level interfaces specified in the man pages for the OS release you are targeting) and then * Run appcert to verify that your resulting binary depends only on public binary interfaces (the Solaris ABI). Q: What is the difference between the "unbundled" and "bundled" versions
of appcert?
A:
Starting with Solaris 8 (4/01) a version of appcert was bundled
with Solaris in the developer cluster. It is based on the unbundled tool
that has been available at
http://www.sun.com/software/solaris/programs/abi/appcert.html
The primary differences between the two tools is that the bundled
one is specific to the Solaris release it is shipped with (i.e. it
does not carry along with it model file definitions for all previous
versions of Solaris). It also does not contain tutorial information
such as html output, etc.Model files for Solaris 9 have been included in the unbundled
appcert version 2.4. (Please note that these model files are not
required to test for stability: if an application uses only public
interfaces on a release, it will be stable on all later Solaris
releases).
Q: Is there any effort being done for I18N/L10N (Internationalization/
Localization) for appcert?
A:
The unbundled tool (see the previous question) is not internationalized,
but the bundled appcert (Solaris 8 4/01) is.
Q: Our product is running on a number of other platforms (IBM, HP, and
others). Is there a possibility to use appcert for these platforms
as well?
A:
Appcert is specific to the Solaris ABI. It requires definitions specific
to each platform and we have not seen similar definitions other
vendors. We have made a simplified port of appcert to Linux-based
systems (particularly straight forward due to the similarities
between the Solaris and GLIBC dynamic linkers. This opensource tool
is called abicheck and is located at
http://abicheck.sourceforge.net/
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||