Chinaunix首页 | 论坛 | 博客
  • 博客访问: 665518
  • 博文数量: 156
  • 博客积分: 4833
  • 博客等级: 上校
  • 技术积分: 1554
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-21 19:36
文章分类

全部博文(156)

文章存档

2016年(2)

2013年(1)

2012年(13)

2011年(30)

2010年(46)

2009年(29)

2008年(23)

2007年(12)

分类: LINUX

2011-12-27 20:48:40

glibc 扩展函数

dladdr==dladdr1

int
dladdr1 (const void *address, Dl_info *info, void **extra, int flags)
=>_dl_addr
=>determine_info

static void
__attribute ((always_inline))
determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
        struct link_map **mapp, const ElfW(Sym) **symbolp)
{
  /* Now we know what object the address lies in.  */
  info->dli_fname = match->l_name;
  info->dli_fbase = (void *) match->l_map_start;

  /* If this is the main program the information is incomplete.  */
  if (__builtin_expect (match->l_name[0], 'a') == '\0'
      && match->l_type == lt_executable)
    info->dli_fname = _dl_argv[0];

  const ElfW(Sym) *symtab
    = (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
  const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);

  ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;

  const ElfW(Sym) *matchsym = NULL;
  if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
            + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
    {
      /* We look at all symbol table entries referenced by the hash
     table.  */
      for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
    {
      Elf32_Word symndx = match->l_gnu_buckets[bucket];
      if (symndx != 0)
        {
          const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];

          do
        {
          /* The hash table never references local symbols so
             we can omit that test here.  */
          if ((symtab[symndx].st_shndx != SHN_UNDEF
               || symtab[symndx].st_value != 0)
              && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
              && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
                        matchsym, addr)
              && symtab[symndx].st_name < strtabsize)
            matchsym = (ElfW(Sym) *) &symtab[symndx];

          ++symndx;
        }
          while ((*hasharr++ & 1u) == 0);
        }
    }
    }
  else
    {
      const ElfW(Sym) *symtabend;
      if (match->l_info[DT_HASH] != NULL)
    symtabend = (symtab
             + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
      else
    /* There is no direct way to determine the number of symbols in the
       dynamic symbol table and no hash table is present.  The ELF
       binary is ill-formed but what shall we do?  Use the beginning of
       the string table which generally follows the symbol table.  */
    symtabend = (const ElfW(Sym) *) strtab;

      for (; (void *) symtab < (void *) symtabend; ++symtab)
    if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
         || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
        && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
        && (symtab->st_shndx != SHN_UNDEF
        || symtab->st_value != 0)
        && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
        && symtab->st_name < strtabsize)
      matchsym = (ElfW(Sym) *) symtab;
    }

  if (mapp)
    *mapp = match;
  if (symbolp)
    *symbolp = matchsym;

  if (matchsym)
    {
      /* We found a symbol close by.  Fill in its name and exact
     address.  */
      lookup_t matchl = LOOKUP_VALUE (match);

      info->dli_sname = strtab + matchsym->st_name;
      info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
    }
  else
    {
      /* No symbol matches.  We return only the containing object.  */
      info->dli_sname = NULL;
      info->dli_saddr = NULL;
    }
}

阅读(8988) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~