分享

移植thttpd出错所涉及到的库依赖问题分析

 北漂之邬 2014-03-11
    由于产品设计的需要,我要在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。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多