Middleware, development tools, realtime operating system
software and services for superior embedded design


Home
QNX Community Resources
Technical Articles
View Article - Customizable Shared Libs
View Article - Customizable Shared Libs

View Article - Customizable Shared Libs

QNX Software Systems
Developer Resources
Blogs
Board support packages
Foundry27 projects
Forums
Hardware support listing
Online video tutorials
Product documentation
Technical Articles

 

Customizable Shared Libs

by Darrin Fry

We will look at shared libraries from two perspectives: that of the library provider, and that of the customer or the library user.

As the provider of a shared library, you want to ensure the functionality provided by that library meets the needs of as many potential customers as possible. This also means that virtually no one customer will use all of the functionality provided by that library. Wouldn't it be great if the unused functionality could be removed to reduce the overhead introduced by the library?

Ideally, the libraries/dlls provided to a customer would contain only what that customer actually needed. But this would be a support nightmare. The alternative? Let the customer build the custom shared libs/dlls themselves. An added bonus would be to do this without the vendor having to make the source public or require the customer to work with large numbers of object files. The answer is the creation of "static shared libraries."

A static shared library is a collection of objects compiled to be position-independent and added to an archive instead of being linked into an actual shared lib. How do you build a static shared library? Write the code the same as you would for a normal shared library, keeping in mind that the use of globals should be kept to a minimum. Compile the .cs with the -shared and -c options. The -shared option will cause position-independent code to be generated; the -c option prevents the link from occurring. This results in the creation of pic object files which can be used to create a shared library/DLL or a static shared library. To create the static shared lib simply add the pic .os to an archive.

To create a static shared library:

 

qcc -shared -c *.c

qcc -A libmyS *.o

NOTE: the above is Qcc NOT Gcc

Static shared libs are best suited as an object repository for building custom shared libraries or dlls. Using a simple script like the one provided below makes creating shared libraries a simple task. The resulting shared library contains only the functionality specified by the customer, imposing minimal impact on storage media and on memory footprint at runtime.

Static shared libs are indicated with a capital S just before the .a to make them more easily identifiable, for example, libcS.a, libphS.a, libmS.a. We will be releasing static shared versions of all of our standard shared libs in the very near future.

 

Generating a Custom Shared Library....

To generate custom libs from the static shared libs discussed above, it requires a little more information. For instance, how do you determine which portions of a library are needed? And, how do you use this information to create a custom shared library?

Determine which symbols are needed to run specific applications.

objdump -T executable |grep UND

 

Undefine the symbols found in step 1 while linking against the desired source static shared lib.

qcc -shared -L. -Wl,-h libph.so.1 -o libph.so.1 -Wl,-u myfunc -Wl,-u nextfunc ... -l phS

 

Below is a simple script that takes a source library, a file containing a list of executables, and a destination library. The script will look at all the executables and find all the unique undefined symbols that will be resolved by shared libs. It then creates a build command file and executes it to generate the target library, which contains only the code required by the applications indicated.

A file list may contain

 

[my_apps]

/usr/photon/bin/pwm

/usr/photon/bin/ped

/usr/photon/bin/voyager

/usr/photon/bin/voyager.server

/usr/photon/bin/phfontFA

/usr/photon/bin/io-graphics

 

To create a custom photon lib that can run the above apps...

customize_lib ph my_apps ph

This will take everything needed to run the apps in my_apps from libphS.a and put it into a shared lib called libph.so.1 which can simply replace the Photon® lib on the target device.

There is an extra bonus as well. The resultant library is fully supported as long as none of the functions in the static shared lib have been overridden in the destination shared lib. (topic for next article)

 

----- BEGIN SCRIPT customize_lib----

#! /bin/ksh

usage() {

echo Usage: customize_lib src_lib exec_list_file target_lib

echo \\ex.

echo \\$ customize_lib ph /project1/my_apps proj1_ph

echo \\takes from *libphS.a* all syms needed to run *my_apps* and

echo \\creates a lib called libproj1_ph.so.1

echo \\the command used to build the custom lib is stored in

echo \\build_proj1_ph_lib

echo \\the build_proj1_ph_lib file can be manually editted to

echo \\remove undefined syms that need not

echo \\be undefined in the target lib. ie. syms marked as

echo \\undefined which do not exist in the source lib.

echo

echo \\The exec_list_file should be a file containing the

echo \\fullpath of one executable per line that

echo \\uses the src_lib... \(objdump --private-headers executable

echo \\to see which libs an exe uses\)

echo \\If the applications in exec_list_file are not to be

echo \\relinked, the target_lib name should be the

echo \\same as the src_lib.

echo \\ex. customize_lib ph my_photon_apps ph

exit

}

find_lib() {

for i in $( echo $LD_LIBRARY_PATH |sed 's/:/ /g'); do

if [ -r $i/$lib ] ; then

libpath=$i/$lib

return 1

fi

done

return 0

}

if test $# -ne 3 ; then

usage

fi

echo Building lib$3.so.1 from lib$1S.a

# Start to construct our build command

echo qcc -shared -olib$3.so.1 -L$LD_LIBRARY_PATH \\ >build_$3_lib

rm -f symlist

found=0

# find all syms needed by our apps.

while read name ; do

objdump -T $name | awk '($3=="*UND*") || ($4==".bss") {print $NF}' >>symlist

objdump --private-headers $name | awk -v sl=lib$1.so.1 '($1=="NEEDED") && ($2!=sl)

{print $NF}' >>needed

done <$2

sort -u needed >neededlibs

rm needed

while read lib ; do

find_lib

if [ $? -eq 1 ] ; then

objdump -T $libpath | awk '($3=="*UND*") || ($4==".bss") {print $NF}' >>symlist

fi

done <neededlibs

rm neededlibs

sort -u symlist >usymlist

# find the source static shared library

lib=lib$1S.a

find_lib

if [ $? -eq 0 ] ; then

echo Could not find lib$1S.a in LD_LIBRARY_PATH

rm symlist

rm usymlist

exit

fi

nm $libpath |awk '$2=="T" || $2=="D" {print $3}' >symlist

sort -u symlist >>usymlist

sort usymlist >symlist

a=""

# only want syms that are needed by our apps and are in the source lib

while read b ; do

if [ "$a" = "$b" ] ; then

echo -Wl,-u$a \\ >>build_$3_lib

echo adding $a

read b

fi

a="$b"

done <symlist

rm symlist

rm usymlist

echo -l$1S \\ >>build_$3_lib

# ensure we include any needed libs (libs our lib depends on)

objdump --private-headers $i/lib$1.so |awk '$1 == "NEEDED" {print "-l"$2}' |sed "s/lib//"

|sed "s/\.so.*/ \\\\/g" >>build_$3_lib

echo >>build_$3_lib

echo strip lib$3.so.1 >>build_$3_lib

echo echo custom build of lib$3.so.1 complete >>build_$3_lib

 

sh build_$3_lib

if [ -r lib$3.so.1 ] ; then

echo Generated lib$3.so.1 from lib$1S.a \(see build_$3_lib file\)

else

echo Custom lib was NOT generated

fi

 

----- END SCRIPT ----

NOTE: This script assumes that there is a normal shared lib in the same directory as the static shared lib we are using as a source lib (for the purposes of pulling in needed slibs).

Put the above script into a file (customize_lib), make it executable, and you'll be building custom shared libs in no time. It's easy :-)

Hint, to make the script executable: chmod a+x customize_lib

Another hint: When an updated static shared lib is received just run the build again...

For example,

 

customize_lib ph my_apps ph

# we now have our own libph.so.1

mv build_ph_lib build_custom1_phlib

# time passes... got new libphS.a

sh build_custom1_phlib

# we now have an updated custom libph.so.1

Enjoy.