Chinaunix首页 | 论坛 | 博客
  • 博客访问: 263557
  • 博文数量: 52
  • 博客积分: 1379
  • 博客等级: 大尉
  • 技术积分: 525
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-18 17:34
文章分类

全部博文(52)

文章存档

2011年(48)

2010年(4)

分类: C/C++

2011-03-02 21:44:59

在遇到-lc这样的参数时, 如果可能,会尽量选择动态库
如下函数加载一个动态库,  文件已经打开

  1. /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
  2.    is referenced by the user (so it should be added as DT_NEEDED in
  3.    the generated ELF file) */
  4. ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
  5. {//
  6.     ElfW(Ehdr) ehdr;
  7.     ElfW(Shdr) *shdr, *sh, *sh1;
  8.     int i, j, nb_syms, nb_dts, sym_bind, ret;
  9.     ElfW(Sym) *sym, *dynsym;
  10.     ElfW(Dyn) *dt, *dynamic;
  11.     unsigned char *dynstr;
  12.     const char *name, *soname;
  13.     DLLReference *dllref;
  14.     
  15.     read(fd, &ehdr, sizeof(ehdr));

  16.     /* test CPU specific stuff */
  17.     if (ehdr.e_ident[5] != ELFDATA2LSB ||
  18.         ehdr.e_machine != EM_TCC_TARGET) {
  19.         error_noabort("bad architecture");
  20.         return -1;
  21.     }

  22.     /* read sections */
  23.     shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);

  24.     /* load dynamic section and dynamic symbols */
  25.     nb_syms = 0;
  26.     nb_dts = 0;
  27.     dynamic = NULL;
  28.     dynsym = NULL; /* avoid warning */
  29.     dynstr = NULL; /* avoid warning */
  30.     for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
  31.         switch(sh->sh_type) {
  32.         case SHT_DYNAMIC:
  33.             nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
  34.             dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
  35.             break;
  36.         case SHT_DYNSYM:
  37.             nb_syms = sh->sh_size / sizeof(ElfW(Sym));
  38.             dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
  39.             sh1 = &shdr[sh->sh_link];
  40.             dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
  41.             break;
  42.         default:
  43.             break;
  44.         }
  45.     }
  46.     soname通常和文件名一样,但是如果不一样,内部解决依赖会以内部名字为主
     比如把libm复制到当前目录, export LD_LIBRARY_PATH=.
     mv libm.so.6 liba.so

xcm@u32:~/study/tinycc$ tcc t.c -L. -la
xcm@u32:~/study/tinycc$ ldd a.out
    linux-gate.so.1 =>  (0xb77c6000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb778c000) 仍然找libm.so.6,因为liba的soname是它
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7632000)
    /lib/ld-linux.so.2 (0xb77c7000)
xcm@u32:~/study/tinycc$ mv liba.so libm.so
xcm@u32:~/study/tinycc$ ldd a.out
    linux-gate.so.1 =>  (0xb78a4000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb786a000) 同样
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7710000)
    /lib/ld-linux.so.2 (0xb78a5000)
xcm@u32:~/study/tinycc$ mv libm.so libm.so.6
xcm@u32:~/study/tinycc$ ldd a.out
    linux-gate.so.1 =>  (0xb7757000)
    libm.so.6 => ./libm.so.6 (0xb772f000) 这个时候就对了
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75c3000)
    /lib/ld-linux.so.2 (0xb7758000)
           
  1.     /* compute the real library name */
  2.     soname = tcc_basename(filename);
  3.         
  4.     for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
  5.         if (dt->d_tag == DT_SONAME) {
  6.             soname = dynstr + dt->d_un.d_val;
  7.         }
  8.     }

  9.     /* if the dll is already loaded, do not load it */
  10.     for(i = 0; i < s1->nb_loaded_dlls; i++) {
  11.         dllref = s1->loaded_dlls[i];
  12.         if (!strcmp(soname, dllref->name)) {
  13.             /* but update level if needed */
  14.             if (level < dllref->level)
  15.                 dllref->level = level;
  16.             ret = 0;
  17.             goto the_end;
  18.         }
  19.     }
  20.     
  21.     // printf("loading dll '%s'\n", soname);

  22.     /* add the dll and its level */
  23.     dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
  24.     dllref->level = level;
  25.     strcpy(dllref->name, soname);
  26.     dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);

  27.     /* add dynamic symbols in dynsym_section */
  28.     for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
  29.         sym_bind = ELFW(ST_BIND)(sym->st_info);
  30.         if (sym_bind == STB_LOCAL)
  31.             continue;
  32.         name = dynstr + sym->st_name;
  33.      ok, 该符号可用了
  34.         add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
  35.                     sym->st_info, sym->st_other, sym->st_shndx, name);
  36.     }
  37.    查找依赖
  38.     /* load all referenced DLLs */
  39.     for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
  40.         switch(dt->d_tag) {
  41.         case DT_NEEDED:
  42.             name = dynstr + dt->d_un.d_val;
  43.             for(j = 0; j < s1->nb_loaded_dlls; j++) {
  44.                 dllref = s1->loaded_dlls[j];
  45.                 if (!strcmp(name, dllref->name))
  46.                     goto already_loaded;
  47.             }
  48.             if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
  49.                 error_noabort("referenced dll '%s' not found", name);
  50.                 ret = -1;
  51.                 goto the_end;
  52.             }
  53.         already_loaded:
  54.             break;
  55.         }
  56.     }
  57.     ret = 0;
  58.  the_end:
  59.     tcc_free(dynstr);
  60.     tcc_free(dynsym);
  61.     tcc_free(dynamic);
  62.     tcc_free(shdr);
  63.     return ret;
  64. }


阅读(2307) | 评论(0) | 转发(0) |
0

上一篇:get_reg

下一篇:git add -u

给主人留下些什么吧!~~