ELF解析05 - hash表

这篇具有很好参考价值的文章主要介绍了ELF解析05 - hash表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ELF解析05 - hash表,ELF,前端,java,算法,开发语言

这个表叫 hash 表,它的作用是用于快速索引符号在符号表中的位置。

先看一张图:

ELF解析05 - hash表,ELF,前端,java,算法,开发语言

查找一个符号的位置步骤如下:

  • 首先,计算出符号字符串的 hash 值

  • 然后,根据 hash 值获取 bucket 索引 index

  • bucket[index] 里面储存的是符号表的 index,但是由于 hash 冲突问题,所以又建立了一个 chain 来当链表结构。

    chain 里面储存的是符号的 hash 值,但是只使用了前 31 位,后 1 位是用于表示该链表是否结束,奇数表示结束,偶数表示后面还有元素

  • 拿到 sym_tab[index] 后,可得 chain[index],然后根据 chain[index] 的值来与符号 hash 值比较,相等则找到,未相等则判断是否为链表结尾,开始循环遍历。

ELF解析05 - hash表,ELF,前端,java,算法,开发语言

结构分析

.gnu.hash节由4部分构成:

Header。

谨记:header的内容决定下面3部分内容的大小。header又分别由4个条目构成,每个条目大小是固定的4个字节,这4个条目分别是:

  • nbuckets。4个字节,决定了第3部分即Hash Buckets的条目数量,1个Hash Buckets占4个字节,如果nbuckets是2,则Hash Bucekts就占8个字节,依次类推,所以说nbuckets的值决定了Hash Bucekts的大小。如上图我的示例文件nbuckets是2。

  • symndx。4个字节,symndx是动态符号表中可通过哈希表访问的第一个符号的索引。symndx决定了第4部分即Hash Values的条目数量,1个Hash Values占4个字节,(dynsymcount – symndx)*4的结果就是Hash Values的实际大小,dynsymcount如果有人不清楚是什么,这里我明确告诉你们,dynsymcount表示的是动态符号表的条目数量。

  • maskwords。4个字节,决定了第2部分即Bloom Filter的条目数量,1个Bloom Filter在32位系统占4个字节,在64位系统占8个字节,我是64位系统所以是8个字节,maskwords如果是1,那么Bloom Filter就是8个字节,如果maskwords是2,那么Blooom Filter就是2*8=16,那么Bloom Filter的实际大小就是16个字节,以此类推,所以说maskwords的值决定了Bloom Filter的大小。

  • shift2。4个字节,Bloom Filter使用的移位计数。

Bloom Filter

32位系统单个条目占4个字节,64位系统占8个字节,条目数量由第一部分即header里的maskwords的值决定,我这儿是64位系统,Bloom Filter的大小是maskwords * 8。

Hash Buckets

单个条目占4个字节,条目数量由第一部分即header里的nbuckets的值决定,Hash Buckets的大小是nbuckets * 4。

Hash Values

单个条目占4个字节,条目数量由第一部分即header里的symndx的值决定(准确说是由dynsymcount和symndx的值决定)。Hash Values的大小是(dynsymcount – symndx) * 4。

例子分析

我们去到 d_ptr 的位置,即 3090:

ELF解析05 - hash表,ELF,前端,java,算法,开发语言

  • 第 1 个 4 字节,表示 bucket 的size,这里为3

  • 第 3 个 4 字节,值为 1,它用于计算 bucket 的起始位置。计算方式为0x3090 + 0x10 + 0x8

贴一段源码:

case DT_GNU_HASH:
        gnu_nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
        // skip symndx
        gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
        gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];

        gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
        gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
        // amend chain for symndx = header[1]
        gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -
            reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];

所以 bucket 起始位置在下图黄色位置:

ELF解析05 - hash表,ELF,前端,java,算法,开发语言

可以看到从黄色开始一共有 6 项,前面说过, bucket size 为 3,所以前 3 项是 bucket,由于 chain 的大小与 bucket 一样,所以后3项是 chain 。

bucket 的第一项是 00000159,这个就是 sym_tab 的索引,实际上我们看第二个 4 字节位置,它也是 00000159,这个值其实表示的是 chain 表的第一个有效索引,由于 sym_tab 与 chain 大小一致,所以这个索引的值也是一致的。

有一点需要注意,hash 表是用于linker快速索引符号的,而这些符号的合集是符号表的子表,所以只会使用到符号表的部分索引。这也是第一张图里面,在 sym_tab 与 chain 表中都留出了空白的原因。在我们的例子中,hash表里面就3个元素。

0x159 的符号是:

symtab[345] [U] _edata

0x15B 的符号是:

symtab[347] [U] __bss_start

由于 chain 的 0x159 位置储存的 hash 值是 ECD54542,是一个偶数。所以如果符号不是 _edata,还会去 chain 的 0x160 位置去寻找,其对应的符号是:文章来源地址https://www.toymoban.com/news/detail-797654.html

symtab[346] [U] _end

到了这里,关于ELF解析05 - hash表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023-05-20青少年软件编程(C语言)等级考试试卷(一级)解析

    2023-05-20青少年软件编程(C语言)等级考试试卷(一级)解析 T1、输出第二个整数 输入三个整数,把第二个输入的整数输出。 时间限制:1000 内存限制:65536 输入 只有一行,共三个整数,整数之间由一个空格分隔。整数是32位有符号整数。 输出 只有一行,一个整数,即输入

    2024年02月09日
    浏览(53)
  • 【HarmonyOS北向开发】-05 ArkTS开发语言-ArkTS开发实践

    飞书原文档:Docs 

    2024年02月11日
    浏览(54)
  • linux remoteproc驱动中elf解析函数实现分析

    在linux中存在的remoteproc的驱动中用到了很多elf解析的函数,比如 elf_size_of_phdr , elf_phdr_get_p_paddr 以及 elf_hdr_get_e_phnum 等等接口。当我们直接搜对应的函数时会发现无法找到其定义,其实这些函数的实现被定义在 drivers/remoteproc/remoteproc_elf_helpers.h 头文件中。 下面以ELF64为例 S

    2024年02月13日
    浏览(45)
  • 大型医院云HIS系统:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发 融合B/S版电子病历系统

    一套医院云his系统源码 采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发。融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。 文末卡片获取联系! 基于云计算技术的B/S架构的医院管理系统(简称云HIS),采用前后

    2024年02月03日
    浏览(50)
  • 前端项目-05-轮播图banner和Floor组件开发-全局轮播图组件抽取

    目录 1-轮播图模块数据开发 2-floor组件开发 3-抽取全局轮播图组件 轮播图需要用到swiper插件,先安装5.4.5版本的swiper: npm  install --save swiper@^5.4.5 --force 模拟从服务器获取数据; 1-编写mockRequests的js文件和之前编写的request的js文件类似,就修改一下baseURL,我们模拟的数据请求路

    2023年04月08日
    浏览(49)
  • Java【算法 05】通过时间获取8位验证码(每两个小时生成一个)源码分享

    要求是很简单的,每个验证码的有效时间是 2小时 ,这个并不是收到验证码开始计时的,而是每个两小时的时间段使用的是相同的验证码。 将 2个小时处理为相同的值 : 很简单的算法分享。优点: 不需要将生成的验证码缓存。 时间入参,能够重复获取相同的值。

    2024年02月05日
    浏览(35)
  • Java语言开发在线小说推荐网 小说推荐系统 基于用户、物品的协同过滤推荐算法 SSM(Spring+SpringMVC+Mybatis)开发框架 大数据、人工智能、机器学习开发

    1、开发工具和使用技术 MyEclipse10/Eclipse/IDEA,jdk1.8,mysql5.5/mysql8,navicat数据库管理工具,tomcat,SSM(spring+springmvc+mybatis)开发框架,jsp页面,javascript脚本,jquery脚本,bootstrap前端框架(用户端),layui前端框架(管理员端),layer弹窗组件等。 2、实现功能 前台用户包含:注

    2023年04月26日
    浏览(84)
  • EVM6678L 开发教程: IBL-TFTP 引导 elf 文件

    参考: \\\"C:timcsdk_2_01_02_06toolsboot_loaderexamplesi2ctftpdocsREADME.txt\\\" 此教程介绍如何在 EVM6678L 开发板上实现 IBL-TFTP 引导 elf 文件. 下载并安装 Tftpd64-#.#-setup.exe 运行 tftpd64.exe 设置 Current Directory(当前目录) (比如: D:/tftp ), 其他保持默认即可. 打开CCS. 导入工程: i2ctftpboot_evmc6678l (搜索

    2024年02月06日
    浏览(38)
  • 1+x web前端开发初级理论答案+解析(一)

    目录 一、单选题(每小题2分,共30小题,共60分) 二、多选题(每小题2分,共15小题,共30分) 三、判断题(每小题2分,共5小题,共10分。在每小题后对应括号内填入判断结果,正确的选项填写“√”,错误的选项填写“×”) 1、在HTML中,(  C  )用来表示特殊字符引号 A、

    2024年02月08日
    浏览(49)
  • Redis数据结构:Hash类型全面解析

    Redis,作为一个开源的、内存中的数据结构存储系统,以其出色的性能和灵活的数据类型,广泛应用于缓存、消息队列、发布订阅系统等多种场景。在 Redis 的五种基本数据类型中,Hash 类型是一种非常重要的数据类型。它可以存储键值对的集合,且能够用小于1毫秒的时间复杂

    2024年02月10日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包