Novell Home

Understanding and Using the Linux Standard Base

Novell Cool Solutions: Feature
By Darren R. Davis

Digg This - Slashdot This

Posted: 21 Jun 2005
 

Darren R. Davis
Linux Developer Evangelist
Novell, Inc.

Introduction

It should be the goal of every developer to have their application target the widest possible platforms. If you are a commercial vendor and you are distributing your application in binary only form, you want to have your Linux application target all available Linux distributions. This way, you can get the best possible return on your investment in development and testing by being able to run on all the available Linux distributions. Sometimes, this has not always been achievable due to a difference in one of the Linux distributions. It is the goal of the Linux Standard Base to provide a specification and tools that allow for binary compatibility of applications and distributions. Now, not only the Linux distribution vendors, but also the application developers can take advantage of a broad range of compatibility. This means that a platform vendor could certify their Linux distribution as being compliant to the LSB specification, and an application vendor could certify their application and the two should operate together without issue.

So what was the problem?

The problem is binary portability and the Autopackage project has a good description of Binary Portability. When a developer builds their application, there are several things they are dependent upon for binary portability. If the developer is using any external library, which is in most cases, they depend on the version of the API (Application Programming Interface) of that library. A good example is the GNU C Library or glibc that all C applications generally use in Linux. Another major component is the ABI (Application Binary Interface) which represents such things as function calling conventions or how data structures are stored in memory. The ABI is the result of the binary output from GCC (GNU Compiler Collection). C++ has added another aspect to the ABI standard due to how C++ symbol names are handled and is referred to as name mangling or more properly called name decoration. GNU documents the C++ Standard Library ABI which is a product of the library API and the compiler ABI and gives the resulting library ABI. The problem has also come from using a non-standard ABI like was done in GCC Version 2.96. In order to solve all these ABI problems, a standard was needed and one was chosen that was based on the Itanium® ABI Standard.

So, in order to solve this problem, the LSB Organization formed to standardize the GNU Linux Platform using a standard API in the form of the necessary libraries to include in a Linux distribution, a standard ABI specification, and other standards such as the FHS (Filesystem Hierarchy Standard) to help preserve a systems name space and allow applications to coexist with the system and each other. The LSB Organization not only provides a specification, but they have a process to update the specification, and they provide tools to help Linux distribution vendors and application developers in their development efforts.

Building Applications with the Linux Standard Base

The core members of the Linux Standard Base Team wrote an excellent book that not only helps you understand using the LSB, but also covers general portability issues like 32 to 64 bit machines and dealing with various architectures. I give a review of the book in my article from last month titled "Linux Developer Bookshelf". Here is what the book looks like, and I have also linked the image to the on-line copy of the book.

Installing and Using the Linux Standard Base Tools

First, before installing the LSB RPMs available from the LSB Download site, a package needs to be installed from the original SUSE Linux installation. The package called lsb can be installed using YaST. This package provides a useful command called lsb_release that will tell us at what level our system is compliant with the LSB specification. With the lsb package installed, we can run it;

linux:~> lsb_release
LSB Version:   core-2.0-noarch:core-2.0-ia32:graphics-2.0-ia32:graphics-2.0-noarch
linux:~>
	

Now if the lsb_release command tells you that the system is at 1.3, you need to run YOU (YaST Online Update) to update the system. SLES 9 becomes LSB 2.0 compliant with Service Pack 1 (SP1) installed. You can verify the service pack level with another very useful command in SLES 9, SPident.

linux:~> SPident

CONCLUSION: ServicePack Level: SLES-9-i386 + "updates" =>
   superseded by SLES-9-i386-SP1
linux:~>

OK, we should now be ready to install the LSB Tools.

The Linux Standard Base provides packaged tools for development and testing.

LSB-Development

lsb-build-base
The LSB Build environment base package provides stub libraries and header files. These can be used to build LSB compliant applications. Note that the version number of the package refers to the version of the specification that the stub libraries and header files have been generated for.

lsb-build-c++
This package provides interim C++ building support for the lsb-build packages. It adds C++ headers and LSB-conforming builds of the static C++ libraries to the files installed by lsb-build-base.

lsb-build-cc
This package provides lsbcc, which is one of the approaches that can be used to build LSB conforming applications.

lsb-buildenv
The LSB Build environment is a tool to make it easier to generate LSB compliant binaries.

lsbdev-base
The LSB Build environment base package provides stub libraries and header files. These can be used to build LSB compliant applications. Note that the version number of the package refers to the version of the specification that the stub libraries and header files have been generated for.

lsbdev-c++
This package provides interim C++ building support for the lsbdev packages. It adds C++ headers and LSB-conforming builds of the static C++ libraries to the files installed by lsbdev-base.

lsbdev-cc
This package provides lsbcc, which is one of the approaches that can be used to build LSB conforming applications.

lsbdev-chroot
The LSB Build environment is a tool to make it easier to generate LSB compliant binaries.

LSB-Test Suites

lsb-appchk
lsbappchk is a program which forms part of a series of checks that a package is LSB compliant. It verifies that a supplied binary only uses dynamically linked symbols that are part of the LSB specification.

lsb-archk
lsbarchk is a development tool used to check a static archive for suitability for use in an LSB-compliant application. Use of non-LSB interfaces is flagged; the tool can be told about additional libraries which are to be linked as part of the final link-edit.

lsb-dynchk
lsbdynchk is a program which forms part of a series of checks that a application is LSB compliant. It is used during execution of the application to test the parameters that are passed to LSB interfaces.

lsb-pkgchk
lsbpkgchk is a program which forms part of a series of checks that a package is LSB compliant. It verifies that the package and its contents conform to the specified format.

To install the LSB tools on SUSE Linux Enterprise server, we need to download the corresponding packages from the LSB website, and install them. I will use the command line rpm command to install the packages I am going to use for this article, you can also use YaST to install the RPMs;

linux:~ # rpm -ihv lsb-build-base-2.1.1-1.i486.rpm
linux:~ # rpm -ihv lsb-appchk-2.1.0-1.i486.rpm
linux:~ # rpm -ihv lsb-build-cc-2.1.1-1.i486.rpm

Let's now run through an example of using the LSB tools from Chapter 2 of the LSB Book. In following the convention of the FHS, the LSB tools are installed in the directory /opt/lsb/ under a typical directory structure of bin for binaries, doc for documents, include for header files, lib for libraries, and man for manual pages. So, you will need to add the /opt/lsb/bin directory to your PATH environment variable, or specify the entire path when running the command.

First, we need the usual hello world sample application, so using your favorite editor, create this C program and save it as hwgood.c;

#include <stdio.h>
#include <unistd.h>

int main()
{
     printf("Hello from PID: %d\n", getpid());

     return 0;
}

Now from looking at this example we can see that it prints out a text string as well as making a call to getpid(). So, lets try and compile it with lsbcc;

linux:~> /opt/lsb/bin/lsbcc -o hwgood hwgood.c
linux:~>

We can see that lsbcc returned no errors telling us that it was successful in compiling our application. Lets make sure by using lsbappchk;

linux:~> /opt/lsb/bin/lsbappchk hwgood
/opt/lsb/bin/lsbappchk for LSB Specification 2.1.0
Checking binary hwgood
section .note.SUSE is not in the LSB
linux:~>

Other then the mention of a section in our ELF binary that is not in the LSB, everything passes. We will come back to the section .note.SUSE a little later. The tool lsbappchk also generates a report file journal.appchk.hwgood that we can examine later.

OK, we now need a bad hello world sample program, so lets replace the function call getpid() with __getpid() and save it as hwbad.c;
(Note: that is two underscore symbols before getpid())

#include <stdio.h>
#include <unistd.h>

int main()
{
	printf("Hello from PID: %d\n", __getpid());

	return 0;
}

Time to run lsbcc;

linux:~> /opt/lsb/bin/lsbcc -o hwbad hwbad.c
/tmp/cc8PTR2j.o(.text+0x23): In function `main':
: undefined reference to `__getpid'
collect2: ld returned 1 exit status
linux:~>

Notice that we get an error about __getpid() and no output binary is generated.

Now, if you are thinking this is just bad C code (well maybe it is), lets give gcc a try and see what it does;

linux:~> gcc -o hwbad hwbad.c
linux:~> ./hwbad
Hello from PID: 24193
linux:~> 

Well, it compiles just fine with gcc and runs fine too!

But is this a good LSB compliant application? Lets run lsbappchk;

linux:~> /opt/lsb/bin/lsbappchk hwbad
/opt/lsb/bin/lsbappchk for LSB Specification 2.1.0
Checking binary hwbad
Incorrect program interpreter: /lib/ld-linux.so.2
Header[ 1] PT_INTERP    Failed
Found wrong intepreter in .interp section: /lib/ld-linux.so.2 instead of: /lib/ld-lsb.so.2
section .note.SUSE is not in the LSB
Symbol __getpid used, but not part of LSB-Core
linux:~>

OK, it's looking like this program isn't LSB compliant. We can always check the journal.appchk.hwbad for details.

Now that we have a familiarity with some of the LSB tools like compiling and checking of applications, lets get back to that message "section .note.SUSE is not in the LSB". First, what is a section? Well in the ELF (Executable and Linkable Format) object format, the executable file is broken up into several sections. What this error is stating is there is a section called ".note.SUSE" found in our executable file that is not in the LSB. So, what is it and can we look at it? Well, the answer is yes and the tool for doing that is objdump which displays information from object files. So, let's use it to see what is going on;

linux:~> objdump -s -j .note.SUSE hwbad

hwbad:     file format elf32-i386

Contents of section .note.SUSE:
 8048168 05000000 02000000 01000000 53755345  ............SUSE
 8048178 00000000 09020000                    ........
linux:~>

Well, now that we take a look at this section, we can see there isn't much in it and only contains the string SUSE. So, even though this is not part of the LSB it will have no effect on the operation of our binary. So, everything looks good. While on the topic of the command objdump which you can use the man command to get more details, here is another interesting thing to be able to dump. There is a section in the ELF executable called the .comment section. Lets take a look at it;

linux:~> objdump -s -j .comment hwbad

hwbad:     file format elf32-i386

Contents of section .comment:
 0000 00474343 3a202847 4e552920 332e332e  .GCC: (GNU) 3.3.
 0010 34202870 72652033 2e332e35 20323030  4 (pre 3.3.5 200
 0020 34303830 39290000 4743433a 2028474e  40809)..GCC: (GN
 0030 55292033 2e332e34 20287072 6520332e  U) 3.3.4 (pre 3.
 0040 332e3520 32303034 30383039 29000047  3.5 20040809)..G
 0050 43433a20 28474e55 2920332e 332e3420  CC: (GNU) 3.3.4
 0060 28707265 20332e33 2e352032 30303430  (pre 3.3.5 20040
 0070 38303929 00004743 433a2028 474e5529  809)..GCC: (GNU)
 0080 20332e33 2e342028 70726520 332e332e   3.3.4 (pre 3.3.
 0090 35203230 30343038 30392900 00474343  5 20040809)..GCC
 00a0 3a202847 4e552920 332e332e 34202870  : (GNU) 3.3.4 (p
 00b0 72652033 2e332e35 20323030 34303830  re 3.3.5 2004080
 00c0 39290000 4743433a 2028474e 55292033  9)..GCC: (GNU) 3
 00d0 2e332e34 20287072 6520332e 332e3520  .3.4 (pre 3.3.5
 00e0 32303034 30383039 29000047 43433a20  20040809)..GCC:
 00f0 28474e55 2920332e 332e3420 28707265  (GNU) 3.3.4 (pre
 0100 20332e33 2e352032 30303430 38303929   3.3.5 20040809)
 0110 00                                   .
linux:~>

Well, we can see that there is some useful information here. The .comment section contains a note about what version of the GCC compiler was used to make this binary. This can come in handy if you ever run across a binary that you are trying to run on a Linux and want to know how it was built. This works for all GCC built Linux binaries. There is a couple more commands that I would like to cover here since we are on the topic of understanding what it takes from a system to make binaries run.

The next command is ldd and it prints the shared library dependencies. So, lets run it;

linux:~> ldd hwgood
	linux-gate.so.1 =>  (0xffffe000)
	libm.so.6 => /lib/tls/libm.so.6 (0x40034000)
	libc.so.6 => /lib/tls/libc.so.6 (0x40058000)
	/lib/ld-lsb.so.2 => /lib/ld-lsb.so.2 (0x40000000)
linux:~> 

So, after running ldd on hwgood, we can see what shared object libraries it depends on. This can come in handy when you have a binary and you need to know what system libraries it uses. OK, now for our last command. That command is nm and it lists symbols from object files. Lets see what it gets us;

linux:~> nm hwgood
080496fc A __bss_start
080483e4 t call_gmon_start
080496fc b completed.1
080495f4 d __CTOR_END__
080495f0 d __CTOR_LIST__
080496f0 D __data_start
080496f0 W data_start
08048590 t __do_global_ctors_aux
08048410 t __do_global_dtors_aux
080496f4 D __dso_handle
080495fc d __DTOR_END__
080495f8 d __DTOR_LIST__
08049604 A _DYNAMIC
080496fc A _edata
08049700 A _end
080485b4 T _fini
080495f0 A __fini_array_end
080495f0 A __fini_array_start
080485d0 R _fp_hw
08048450 t frame_dummy
080485ec r __FRAME_END__
         U getpid@@GLIBC_2.0
080496d8 A _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
08048588 T __i686.get_pc_thunk.bx
0804835c T _init
080495f0 A __init_array_end
080495f0 A __init_array_start
080485d4 R _IO_stdin_used
08049600 d __JCR_END__
08049600 d __JCR_LIST__
         w _Jv_RegisterClasses
080484c0 T __libc_csu_fini
08048530 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804847c T main
080496f8 d p.0
         U printf@@GLIBC_2.0
080483c0 T _start
linux:~> 

So, as the man page for the command describes, nm does dump out all the symbol information. This command is very useful in looking at symbol information, especially if working through name mangling issues with C++ since nm will also work on the system libraries. You can use the nm command on system libraries and find symbols and libraries that your program needs.

Summary

Well, we completed our first step in using the LSB tools. At this point, the developer should do a little studying to understand the LSB. I highly recommend the book "Building Applications with the Linux Standard Base" as I pointed out earlier with a link to my review of the book. As part of building an application to the LSB standard, the developer is going to need to be aware of where their application will reside in the file system as described by the FHS. The LSB standard also requires that the developer package their software with the RPM package manager. The RPM website has a great resource with the on-line book, Maximum RPM. I also recommend becoming familiar with the commands I described. It is not often that you may need to go looking at the binaries you built, but I suspect you will need to do it one day.

Resources:

Linux Standard Base
Building Applications with the Linux Standard Base
Free Standards Group
LANANA – The Linux Assigned Names and Numbers Authority
Filesystem Hierarchy Standard
RPM Package Manager
Maximum RPM
Wikipedia – Free On-line encyclopedia


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell