Probing Shared Library Initialization
Aprobe can be used to probe program initialization in several ways.
Contents
Using Aprobe and RootCause Intercept
Probing program initialization, in general, is not a problem when using Aprobe from the command line or the RootCause intercept mechanism. In these cases the Aprobe runtime is loaded into the program address space and initialized before any part of the program runs. This allows Aprobe to instrument the program and create probes in any program initialization code including C++ global constructors or Ada program elaboration code. It is important to note that the Aprobe runtime library does depend on other shared libraries which will be initialized before the Aprobe runtime, and probes placed in those libraries will not be inserted until the Aprobe runtime library has a chance to execute. In practice this is not a problem.
If your program loads shared libraries dynamically (using dlopen
), you must have Aprobe pre-load the shared libraries using the -dll
option. This will make the shared libraries available to Aprobe to insert probes during initialization.
Using libdal.so
When linking your program with libdal.so
the situation gets a little trickier. The libdal.so
shared library is normally initialized as part of the dynamic loader dependency order. This will "just work" when libdal.so
is linked with a main executable (the usual way to do this).
If your program is linked with shared libraries and you want to insert probes in the initialization of those shared libraries, you must ensure that libdal.so
is initialized before the other shared libraries are initialized. To do this you need to insert a dependency on libdal.so
into each of the shared libraries. You can do this several ways:
- use the linker to force
libdal.so
to be initialized first; - use the linker to add dependencies from your shared libraries to
libdal.so
; or - explicitly call the
libdal.so
initialization function (ap_DalLibraryLoader()
) at the right time.
See below for examples of each approach.
For dynamically loaded shared libraries, you should pre-load them using the -dll
option in the APO
file.
Force libdal.so Initialization
On AIX, you can use the linker option -binitfini
to specify the priority of module initialization. By setting priorities for modules you can control the relative initialization order of the modules and ensure that libdal.so
is initialized early enough to probe your other shared libraries.
This is an example of the linker options used to specify a priority for the libdal.so
module initialization:
-Bi-binitfini\:ap_DalLibraryLoader\:\:-100000000
Note that you must specify the priority of the other shared libraries you want to probe so they will be initialized after libdal.so
.
See https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.cmds3/ld.htm#ld__xpudj83amy for more information.
On Linux you can use the GNU linker to add dependencies from one shared library to another. In this case you want to create a dependency on libdal.so
from your shared library.
This is an example of creating a dependency on libdal.so
while linking a shared library:
gcc -g -shared -L$APROBE/lib -ldal -o libmylib.so myobj1.o myobj2.so
This is generally the easiest and safest way to create the proper dependency order. The linker will take care of calling the initialization functions in the corrrect order based not eh inter-library dependencies.
Explicitly Call ap_DalLibraryLoader()
In more complex situations you might need to control when libdal.so
is initialized. You can do this by calling ap_DalLibraryLoader(void)
directly.
This is an example of this approach on AIX:
extern void ap_DalLibraryLoader(void);
void MyInit()
{
ap_DalLibraryLoader();
}
and on Linux:
extern void ap_DalLibraryLoader(int Arg, char **Argv);
void MyInit()
{
ap_DalLibraryLoader(1, "MyProgramName");
}
Be careful to initialize libdal.so
at the proper time. You cannot initialize it before the shared libraries upon which it depends, which generally will require you to initialize all those shared libraries yourself.