GNU/Linux Application Programming (Programming Series)

Now let s look at some of the other utilities that are useful when creating static, shared, or dynamic libraries.

file

The file utility tests the file argument for the purposes of identifying what it is. This utility is very useful in a number of different scenarios, but in this case it will provide us with a small amount of information about the shared object. Let s look at an interactive example:

$ file /usr/local/lib/libmyrand.so /usr/local/lib/libmyrand.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped $

So, using file , we see that our shared library is a 32-bit ELF object for the Intel 80386 processor family. It has been defined as not stripped, which simply means that debugging information is present.

size

The size command provides us with a very simple way to understand the text , data , and bss section sizes for an object. An example of the size command on our shared library is shown here:

$ size /usr/local/lib/libmyrand.so text data bss dec hex filename 2013 264 4 2281 8e9 /usr/local/lib/libmyrand.so $

nm

To dig into the object, we use the nm command. This commands permits us to look at the symbols that are available within a given object file. Let s look at a simple example using grep to filter our results:

$ nm -n /usr/local/lib/libmyrand.so grep " T " 00000608 T _init 0000074c T initRand 00000784 T getSRand 000007be T getRand 00000844 T _fini $

In this example, we use nm to print the symbols within the shared library, but then only emit those with the tag " T " to stdout (those symbols that are part of the .text section, or code segments). We also use the -n option to sort the output numerically by address, rather than the default, which is alphabetically by symbol name . This gives us relative address information within the library; if we wanted to know the specific sizes of these .text sections, we could use the -S option, as:

$ nm -n -S /usr/local/lib/libmyrand.so grep " T " 00000608 T _init 0000074c 00000036 T initRand 00000784 0000003a T getSRand 000007be 00000050 T getRand 00000844 T _fini $

From this example, we can see that the initRand is located at relative offset 0 74c in the library and its size is 0 36 (decimal 54) bytes. Many other options are available; the nm mainpage provides more detail on this.

objdump

The objdump utility is similar to nm in that it provides the ability to dig in and inspect the contents of an object. Let s now look at some of the specialized functions of objdump .

One of the most interesting features of objdump is its ability to disassemble the object into the native instruction set. Here s an excerpt of objdump performing this capability:

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ x11f8,%ebx 75f: 83 ec 0c sub

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ xc,%esp 762: 6a 00 push

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add

$ objdump -disassemble -S /usr/local/lib/libmyrand.so ... 0000074c <initRand>: 74c: 55 push %ebp 74d: 89 e5 mov %esp,%ebp 74f: 53 push %ebx 750: 83 ec 04 sub $0x4,%esp 753: e8 00 00 00 00 call 758 <initRand+0xc> 758: 5b pop %ebx 759: 81 c3 f8 11 00 00 add $0x11f8,%ebx 75f: 83 ec 0c sub $0xc,%esp 762: 6a 00 push $0x0 764: e8 c7 fe ff ff call 630 <_init+0x28> 769: 83 c4 10 add $0x10,%esp 76c: 89 45 f8 mov %eax,0xfffffff8(%ebp) 76f: 83 ec 0c sub $0xc,%esp 772: ff 75 f8 pushl 0xfffffff8(%ebp) 775: e8 d6 fe ff ff call 650 <_init+0x48> 77a: 83 c4 10 add $0x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $ x10,%esp 77d: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 780: c9 leave 781: c3 ret 782: 90 nop 783: 90 nop ... $

In addition to -disassemble (to disassemble to the native instruction set), we also specified -S to output interspersed source code. The problem is that we compiled our object to exclude this information. We can easily fix this as follows , by adding -g to the compilation process.

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ xc,%esp 7a6: 6a 00 push

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand( seed ); 7b3: 83 ec 0c sub

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add

$ gcc -c -g -fPIC initapi.c $ gcc -c -g -fPIC randapi.c $ gcc -shared initapi.o randapi.o -o libmyrand.so $ objdump -disassemble -S libmyrand.so ... 00000790 <initRand>: * */ void initRand() { 790: 55 push %ebp 791: 89 e5 mov %esp,%ebp 793: 53 push %ebx 794: 83 ec 04 sub $0x4,%esp 797: e8 00 00 00 00 call 79c <initRand+0xc> 79c: 5b pop %ebx 79d: 81 c3 fc 11 00 00 add $0x11fc,%ebx time_t seed; seed = time(NULL); 7a3: 83 ec 0c sub $0xc,%esp 7a6: 6a 00 push $0x0 7a8: e8 c7 fe ff ff call 674 <_init+0x28> 7ad: 83 c4 10 add $0x10,%esp 7b0: 89 45 f8 mov %eax,0xfffffff8(%ebp) srand ( seed ); 7b3: 83 ec 0c sub $0xc,%esp 7b6: ff 75 f8 pushl 0xfffffff8(%ebp) 7b9: e8 d6 fe ff ff call 694 <_init+0x48> 7be: 83 c4 10 add $0x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $ x10,%esp return; } 7c1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 7c4: c9 leave 7c5: c3 ret 7c6: 90 nop 7c7: 90 nop ... $

Having compiled our source code with -g , we now have the ability to understand the C source to machine code mapping.

Numerous other capabilities are provided with objdump . The GNU/Linux mainpage lists the plethora of other options.

ranlib

The ranlib utility is one of the most important utilities when creating static libraries. This utility creates an index of the contents of the library and stores it in the library file itself. When this index is present in the library, the linking stage of building an image can be sped up considerably. Therefore, the ranlib utility should be performed whenever a new static library is created. An example of using ranlib is shown here:

$ ranlib libmyrand.a $

Note that the same thing can be performed using the ar command with the -s option, as:

$ ar -s libmyrand.a $

Категории