由于产品设计的需要,我要在Davinci6446平台移植thttpd-2.25b,在此过程中也出现一些问题,则在此记录之。 我们知道,当 rootfs缺少必要的library时,会导致应用程序无法正确运行,严重的话可能导致系统无法正常启动,解决库依赖(library dependency)问题可参考如下三个要点: 1、先使用交叉编译器的objdump观察目标项目,加入library。 2、检查这些library是不是依赖其他的library。 3、最后检查应用程序是否用到特定的library的service。 thttpd 使用到 NSS (Name Service Switch),因此若沒有将 libnss_SERVICE.so 加到 root filesystem,thttpd 在执行时可能会遇到一些奇怪的问题。例如,当 thttpd 依据 /etc/passwd 去寻找 linux user 時,会用到 libnss_files.so (不读 /etc/shadow),因此会看到以下错误信息: unknown user - root 出现这个错误的原因是 thttpd 读不到 'root' 使用者,要深入探讨这个问题的原理,必须从以下的程序源代码中了解: 403 /* If we're root and we're going to become another user, get the uid /gid 404 ** now. 405 */ 406 if ( getuid() == 0 ) 407 { 408 pwd = getpwnam( user ); 409 if ( pwd == (struct passwd*) 0 ) 410 { 411 syslog( LOG_CRIT, "unknown user - '%.80s'", user ); 412 (void) fprintf( stderr, "%s: unknown user - '%s'\n", argv0, user ); 413 exit( 1 ); 414 } 415 uid = pwd->pw_uid; 416 gid = pwd->pw_gid; 417 } 以上代码是 thttpd 2.25b 的程序源代码,位于 thttpd.c 的 main() 函数。 由系统构建的角度来看这个问题。我们已经习惯用 objdump 来观察程序library依赖,所以当 objdump 的输出跟我们預期的不同时,还比较惊奇。例如: root@microtiger:/home/microtiger/task/thttpd/thttpd-2.25b# arm_v5t_le-objdump -x thttpd|more thttpd: file format elf32-littlearm thttpd architecture: armv5t, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x00008180 Program Header: 0x70000001 off 0x00082d4c vaddr 0x0008ad4c paddr 0x0008ad4c align 2**2 filesz 0x000006e8 memsz 0x000006e8 flags r-- LOAD off 0x00000000 vaddr 0x00008000 paddr 0x00008000 align 2**15 filesz 0x000834b0 memsz 0x000834b0 flags r-x LOAD off 0x000834b0 vaddr 0x000934b0 paddr 0x000934b0 align 2**15 filesz 0x00001ef8 memsz 0x0002a99c flags rw- NOTE off 0x000000d4 vaddr 0x000080d4 paddr 0x000080d4 align 2**2 filesz 0x00000020 memsz 0x00000020 flags r-- NOTE off 0x000000f4 vaddr 0x000080f4 paddr 0x000080f4 align 2**2 filesz 0x00000074 memsz 0x00000074 flags r-- private flags = 4000002: [Version4 EABI] [has entry point] Sections: Idx Name Size VMA LMA File off Algn 0 .note.ABI-tag 00000020 000080d4 000080d4 000000d4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_CONTENTS 1 .note.numapolicy 00000074 000080f4 000080f4 000000f4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_CONTENTS 2 .init 00000018 00008168 00008168 00000168 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 3 .text 0006a3c4 00008180 00008180 00000180 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 4 __libc_freeres_fn 000009bc 00072544 00072544 0006a544 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 5 __libc_thread_freeres_fn 00000050 00072f00 00072f00 0006af00 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 6 .fini 00000018 00072f50 00072f50 0006af50 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 7 .rodata 00017cc4 00072f68 00072f68 0006af68 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 __libc_subfreeres 00000040 0008ac2c 0008ac2c 00082c2c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 __libc_atexit 00000004 0008ac6c 0008ac6c 00082c6c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 __libc_thread_subfreeres 00000004 0008ac70 0008ac70 00082c70 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 11 .ARM.extab 000000d8 0008ac74 0008ac74 00082c74 2**2 是相当的长,只要了这么一段。 追溯这个问题:thttpd 调用 getpwnam() 函数,此函数由 libnss_compat 提供,因此解決方案是把 libnss_files.so 加到 root filesystem 里面即可。 前面提到 libnss_compat,怎么后面是把 libnss_files 加到 root filesystem?原因在于libnss_compat 用來读 /etc/shadow,但是現在我们只需要由 /etc/passwd 读 linux user,所以使用 libnss_files.so 就行了。 执行 thttpd 的话,再加上指定 username 的参数即可: # thttpd -p 80 -d www -u root libnss_SERVICE.so 是包含在 glibc 里的程序库,因此可以直接由 cross toolchain 取得,不必再另行建置。 附带一提,如果要读 shadow passwd 的话,是使用 libnss_compat.so。 |
|