Debugging with strace

For some reason, the native test program for the library runs in version 1.0 R2 of the SDK, but fails to load in 1.5 R2. The output gives a clue: the file bionic/linker/linker.c:1581 fails to load the library. There is a simple Linux tool called strace that can help in this situation.

The strace tool runs the specified command until it exits. It intercepts and records the system calls that are called by a process and the signals that are received by a process. The name of each system call, its arguments, and its return value are printed. This is a useful diagnostic and debugging tool for solving problems with programs for which the source is not readily available. You will find that a great deal can be learned about a system and its system calls by tracing even ordinary programs.

The book source provides an Android version of strace. (strace is now a built into versions 1.5 and later of the Android SDK.) Let's push it and see what is going on, as shown in Listing 2-9.

Listing 2-9. strace Tool Output

$ adb push strace /data $ adb shell

# ./strace ./testlib execve("./testlib", ["./testlib"], [/* 10 vars */]) = 0 getpid() = 835

sigaction(SIGILL, {0xb0001a99, [], SA_RESTART}, {SIG_DFL}, 0) = 0 sigaction(SIGABRT, {0xb0001a99, [], SA_RESTART}, {SIG_DFl}, 0) = 0 sigaction(SIGBUS, {0xb0001a99, [], SA_RESTART}, {SIG_DFL}, 0) = 0 stat64("/system/lib/libch02.so", 0xbef9ea58) = -1 ENOENT (No such file or directory) stat64("/lib/libch02.so", 0xbef9ea58) = -1 ENOENT (No such file or directory) mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000 mprotect(0x40000000, 4096, PROT_READ) = 0

fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 1), ...}) = 0 brk(0) = 0x11000

brk(0x11000) = 0x11000

brk(0x12000) = 0x12000

mprotect(0x40000000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x40000000, 4096, PROT_READ) = 0

ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 write(1, "bionic/linker/linker.c:1581| ERR"..., 70bionic/linker/linker.c:1581| ERROR: 835 could not load 'libch02.so' ) = 70

write(1, "bionic/linker/linker.c:1641| ERR"..., 61bionic/linker/linker.c:1641| ERROR: failed to link ./testlib ) = 61

write(1, "bionic/linker/linker.c:1741| ERR"..., 71bionic/linker/linker.c:1741| ERROR: CANNOT LINK EXECUTABLE './testlib' ) = 71

Process 835 detached

The following lines give a clue to the source of the problem:

stat64("/system/lib/libch02.so", 0xbef9ea58) = -1 ENOENT (No such file or directory) stat64("/lib/libch02.so", 0xbef9ea58) = -1 ENOENT (No such file or directory)

The linker first tries to open the library from the device /system/lib folder. This is a read-only file system, and user-defined libraries cannot be saved there. Next, the linker searches the /lib folder, which doesn't exist, thus the link fails. The linker is not searching in the current directory—that is the problem!

The good news is that this will not prevent the library from loading within the Java application, as long as there are no missing symbols.

If you run the same sequence in a version 1.0 R2 of the SDK, you will see that the second line becomes the following:

stat64("./libch02.so", 0xbef9ea58) = 0 OK Thus, the program runs successfully.

■ Note It is hard to say what has changed from version 1.0 to 1.5 in the file bionic/linker/linker.c, as Google provides no support in this matter. I can only speculate, but my guess is that either the developers forgot to search in the current folder or some new compilation option can be used to tell the linker where to search.

Was this article helpful?

0 0

Post a comment