首页
社区
课程
招聘
[原创] 较新的SO中根据 GNU_HASH字段 文件函数符号查询方法
发表于: 2017-6-16 17:20 3053

[原创] 较新的SO中根据 GNU_HASH字段 文件函数符号查询方法

2017-6-16 17:20
3053

由于比较新版本的编译生成的 SO 开始使用 .GNU_HASH 代替 .HASH 字段查询 符号表信息,特总结相关函数,希望对需要使用到的同学有所帮助:


static uint32_t gnuhash(const char* name_) {    // 根据 需要查询的 符号字符串信息  计算出gnuhash类似 elfhash

 uint32_t gnu_hash_ = 0;

 int has_gnu_hash_ = 0;

 if (!has_gnu_hash_) {

   uint32_t h = 5381;

   const uint8_t* name = reinterpret_cast<const uint8_t*>(name_);

   while (*name != 0) {

     h += (h << 5) + *name++; // h*33 + c = h + h * 32 + c = h + h << 5 + c

   }

   gnu_hash_ =  h;

   has_gnu_hash_ = true;

 }

     return gnu_hash_;

}


static Elf64_Sym* soinfo_gnu_lookup(soinfo* si, uint32_t gnu_hash, const char* name)   //使用 gnu_hash在GNU_HASH段中查询出符号偏移信息

{                                                // si为符号定义实现的so的soinfo信息, name为需要查找符号的字符串信息 

    Elf64_Sym* symtab_ = si->symtab;

    const char* strtab_ = si->strtab;

    size_t gnu_nbucket_ = si->gnu_nbucket_;

    uint32_t* gnu_bucket_ = si->gnu_bucket_;

    uint32_t* gnu_chain_ = si->gnu_chain_;

    uint32_t gnu_maskwords_ = si->gnu_maskwords_;

    uint32_t gnu_shift2_ = si->gnu_shift2_;

    Elf64_Addr* gnu_bloom_filter_ = si->gnu_bloom_filter_;

    uint32_t hash = gnu_hash;

    uint32_t h2 = hash >> gnu_shift2_;

    uint32_t bloom_mask_bits = sizeof(Elf64_Addr)*8;

    uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;

    Elf64_Addr bloom_word = gnu_bloom_filter_[word_num];

  // test against bloom filter

    if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {

      return NULL;

    }

  // bloom test says "probably yes"...

    uint32_t n = gnu_bucket_[hash % gnu_nbucket_];

    if (n == 0) {

      return NULL;

    }

    do {

      Elf64_Sym* s = symtab_ + n;

      // skip hidden versions when verneed == kVersymNotNeeded (0)

      if (((gnu_chain_[n] ^ hash) >> 1) == 0 &&

          strcmp(strtab_ + s->st_name, name) == 0) {

        return s;

      }

    } while ((gnu_chain_[n++] & 1) == 0);

    return NULL;

}



[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//