浅析从DWARF到BTF @龙蜥社区eBPF SIG

news2024/12/28 9:12:07

一、背景

一个程序会经历编码、编译、运行的过程,但所有的开发几乎都不可能是一帆风顺的,总会有些意想不到的错误,这时便需要调试。那么调试器使用的调试信息是从哪里来的呢?答案就是从编译后的文件中来的(依赖编译的时候使用特定的编译选项,如GCC使用“-g”)。

在BPF程序开发过程中,我们也需要这类调试信息,首先LLVM 能够将调试信息附加到生成的 BPF 目标文件中。默认情况下,这是 DWARF 格式。但BPF 使用的是高度简化的版本称为 BTF。我们首先需要将DWARF 转换为 BTF。BPF程序加载到内核后,内核验证器将验证 BTF 数据的正确性并跟踪 BTF 数据包含的数据类型。

DWARF的全称是"Debugging With Attributed Record Formats",遵从GNU FDL授权。由以上述描述可知,DWARF是一种调试文件格式,许多编译器和调试器均使用DWARF来支持源代码级调试。简单来说,DWARF记录了源代码、二进制程序以及它们之间存在的联系。

本文主要从三个方面介绍DWARF:

  1. DWARF在elf文件存在哪些段,以及每个段的含义;
  2. 采用具体的实例,介绍了.deubg_str所包含的内容;
  3. 重点介绍了.debug_info段,其是理解BTF的关键;

二、elf中包含的DWARF段

DWARF在elf文件中共存在12个段。就本文而言,12个段重要的段是:.debug_info段和.deubg_str段,后面也是着重讲解这两个段。这两个段也是libbpf BTF最感兴趣的两个段。

三、.debug_str解析

.debug_str段主要包含了源代码中的各种可读文本。以下面的C代码为例:

struct test_struct{
    int testa;
    char testb;
}test_s;
int main()
{
    return 0;
}
  • 首先将该C代码编译成二进制,即gcc -g -o test test.c;
  • 运行命令:readelf -ws test,可以得到如下的文本。核心文本包括了test_s(结构体变量)、test_struct(结构体)、testa(结构体成员)、testb(结构体成员)、char(结构体成员类型)等。但是如果变量的名字是单个字符,则不会单独存储。
  0x00000000 74657374 5f73006d 61696e00 2f686f6d test_s.main./hom
  0x00000010 652f6368 656e6773 68757969 2e637379 e/chengshuyi.csy
  0x00000020 2f706168 6f6c6500 74657374 5f737472 /pahole.test_str
  0x00000030 75637400 474e5520 4320342e 382e3520 uct.GNU C 4.8.5 
  0x00000040 32303135 30363233 20285265 64204861 20150623 (Red Ha
  0x00000050 7420342e 382e352d 32382920 2d6d7475 t 4.8.5-28) -mtu
  0x00000060 6e653d67 656e6572 6963202d 6d617263 ne=generic -marc
  0x00000070 683d7838 362d3634 202d6700 74657374 h=x86-64 -g.test
  0x00000080 2e630074 65737461 00746573 74620063 .c.testa.testb.c
  0x00000090 68617200                            har.

四、.debug_info解析

.debug_info包含了DWARF的DIEs,DIE则重在描述数据类型。DIE包含一个tag,指定了DIE所描述的类型。DIE还包含属性列表,用于描述该类型的具体信息。

本节主要详细介绍了两种不同tag的DIE,分别是结构体类型(对应的tag是DW_TAG_structure_type)和引用类型(只介绍DW_TAG_const_type)。理解这两种DIE,非常有助于理解libbpf BTF的去重算法。

结构体类型
下面是一段简单的C语言代码。

struct test{
    int a;
    char b;
}test;
int main()
{
    return 0;
}
  • 首先将该C代码编译成二进制,即gcc -g -o test test.c;
  • 运行命令:readelf -wi test,可以得到如下文本:
<1><2d>: Abbrev Number: 2 (DW_TAG_structure_type)
    <2e>   DW_AT_name        : (indirect string, offset: 0x1c): test
    <32>   DW_AT_byte_size   : 8
    <33>   DW_AT_decl_file   : 1
    <34>   DW_AT_decl_line   : 1
    <35>   DW_AT_sibling     : <0x4e>
 <2><39>: Abbrev Number: 3 (DW_TAG_member)
    <3a>   DW_AT_name        : a
    <3c>   DW_AT_decl_file   : 1
    <3d>   DW_AT_decl_line   : 2
    <3e>   DW_AT_type        : <0x4e>
    <42>   DW_AT_data_member_location: 0
 <2><43>: Abbrev Number: 3 (DW_TAG_member)
    <44>   DW_AT_name        : b
    <46>   DW_AT_decl_file   : 1
    <47>   DW_AT_decl_line   : 3
    <48>   DW_AT_type        : <0x55>
    <4c>   DW_AT_data_member_location: 4
 <2><4d>: Abbrev Number: 0
 <1><4e>: Abbrev Number: 4 (DW_TAG_base_type)
    <4f>   DW_AT_byte_size   : 4
    <50>   DW_AT_encoding    : 5        (signed)
    <51>   DW_AT_name        : int
 <1><55>: Abbrev Number: 5 (DW_TAG_base_type)
    <56>   DW_AT_byte_size   : 1
    <57>   DW_AT_encoding    : 6        (signed char)
    <58>   DW_AT_name        : (indirect string, offset: 0x75): char
 <1><79>: Abbrev Number: 7 (DW_TAG_variable)
    <7a>   DW_AT_name        : (indirect string, offset: 0x1c): test
    <7e>   DW_AT_decl_file   : 1
    <7f>   DW_AT_decl_line   : 4
    <80>   DW_AT_type        : <0x2d>
    <84>   DW_AT_external    : 1
    <84>   DW_AT_location    : 9 byte block: 3 20 10 60 0 0 0 0 0       (DW_OP_addr: 601020)
 <1><8e>: Abbrev Number: 0

上述的文字可以转换成如下图所示的图形。可以理解以下几点:

  • DW_TAG_structure_type的结构体成员组织方式(通过DW_TAG_member字段);
  • 如何确定DW_TAG_variable的具体类型(通过DW_AT_type字段);


引用类型

const int a;
int main()
{
    return 0;
}

转换之后,得到如下内容:

 <1><4a>: Abbrev Number: 3 (DW_TAG_base_type)
    <4b>   DW_AT_byte_size   : 4
    <4c>   DW_AT_encoding    : 5        (signed)
    <4d>   DW_AT_name        : int
 <1><51>: Abbrev Number: 4 (DW_TAG_variable)
    <52>   DW_AT_name        : a
    <54>   DW_AT_decl_file   : 1
    <55>   DW_AT_decl_line   : 1
    <56>   DW_AT_type        : <0x64>
    <5a>   DW_AT_external    : 1
    <5a>   DW_AT_location    : 9 byte block: 3 20 10 60 0 0 0 0 0       (DW_OP_addr: 601020)
 <1><64>: Abbrev Number: 5 (DW_TAG_const_type)
    <65>   DW_AT_type        : <0x4a>

上述的文字可以转换成如下图所示的图形。可以理解DW_TAG_const_type存在的形式,
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubernetes使用Ingress Nginx流量代理

理论了解 1、ingress简介 kubernetes官方文档 Ingress 是 kubernetes API 中的标准资源类型之一&#xff0c;ingress 实现的功能是在应用层对客户端请求的 host 名称或请求的 URL 路径把请求转发到指定的 service 资源的规则&#xff0c;即用于将 kubernetes 集群外部的请求…

数字孪生水电站:发电流程三维可视化优化

从大禹治水到三峡大坝的建造&#xff0c;人类为控制和调配自然界的地表水和地下水&#xff0c;修建了许多的水利工程。对水资源进行了广泛的开发利用&#xff0c;诸如农业灌溉、工业和生活用水、水力发电、航运、港口运输、淡水养殖、旅游等。 将图扑软件与 GIS、粒子仿真、虚拟…

动作捕捉系统用于微创手术

微创手术是医生通过病人体表的微小切口&#xff0c;将细长的手术工具探入病人体内进行手术操作。与传统的开口手术相比&#xff0c;这种方式可减少手术对病人造成的创伤&#xff0c;缩短恢复时间。但是&#xff0c;微创手术也给医生的操作带来了一系列困难&#xff1a;比如受小…

Autoform R10中文版安装说明教程

1、安装R8的服务RLM_v12.0BL2 2、拷贝文件到相关目录&#xff08;1、许可证&#xff0c;C:\Program Files安装许可的位置。。。直接停止服务后替换R10 BIN文件 然后改环境变量&#xff08;这里可以直接改&#xff0c;也可以删掉然后重新输入&#xff0c;建议删掉后输入&#x…

上海亚商投顾:创业板缩量跌近1% 血氧仪概念逆市大涨

上海亚商投顾前言&#xff1a;无惧大盘大跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪沪指早间低开高走&#xff0c;盘中一度拉升翻红&#xff0c;午后又再度下挫&#xff0c;深成指、创业板指均跌近1%。…

5G网络的关键技术及特点,面临的挑战!

01 5G关键技术 超密集组网&#xff1a;5G需要满足热点高容量场景&#xff08;高流量密度、高速率&#xff09; 超密集组网&#xff1a;大量增加小基站&#xff0c;以空间换性能 基站一般包括&#xff1a;宏基站和小基站 宏基站:即“铁塔站”&#xff0c;一般覆盖范围数千米…

Linux课程笔记

Linux基础命令 Linux的目录结构 /&#xff0c;根目录是最顶级的目录了Linux只有一个顶级目录&#xff1a;/路径描述的层次关系同样适用/来表示/home/itheima/a.txt&#xff0c;表示根目录下的home文件夹内有itheima文件夹&#xff0c;内有a.txt ls命令 功能&#xff1a;列出…

【北邮】计算机组成原理实验:实验一 运算器组成实验

实验一 运算器组成实验 实验目的 ⑴熟悉逻辑测试笔的使用方法。 ⑵熟悉 TEC-8 模型计算机的节拍脉冲 T1、T2、T3&#xff1b; ⑶熟悉双端口通用寄存器组的读写操作&#xff1b; ⑷熟悉运算器的数据传送通路&#xff1b; ⑸验证 74LS181 的加、减、与、或功能&#xff1…

Python数据容器(五)

python学习之旅&#xff08;五&#xff09; &#x1f44d;基础语法部分笔记(一) &#x1f44d;条件判断部分笔记(二) &#x1f44d;循环语句部分笔记(三) &#x1f44d;函数使用部分笔记(四) &#x1f44d;数据容器部分笔记(五) 一.数据容器 一种可以容纳多份数据的数据类型&am…

kail - 扫描与爆破

数据来源 扫描技术 背景 在渗透测试过程中&#xff0c;为了节省人力和时间&#xff0c;通常采用手工和工具相结合的方式。使用工具&#xff0c;就是将一些机械性的操作自动化实现&#xff0c;用来提高渗透测试的效率。例如&#xff0c;寻找内网网段[10.10.10,20/24]所有在线主…

MySQL窗口函数 和 阿里云日志15日留存率仪表盘统计脚本实现

窗口函数的官方描述&#xff1a;窗口函数对一组查询行执行类似聚合的操作。但是&#xff0c;虽然聚合操作将查询行分组为单个结果行&#xff0c;但窗口函数会为每个查询行生成一个结果&#xff0c;发生函数评估的行称为当前行&#xff0c;与发生函数评估的当前行相关的查询行构…

Kubernetes证书热更新期限至100年【HA高可用集群】

一、问题与环境 1.为什么更新证书&#xff1f;局域网如何保障服务稳定性&#xff1f;   众所周知k8s&#xff08;Kubernetes&#xff09;有一个默认证书期限为一年不成文的规定&#xff0c;官方的解释是“最佳的做法是经常升级集群以确保安全。&#xff08;升级后集群证书自…

MySQL表的增删查改

目录 1、表的插入 <1> 全列插入 <2> 指定列插入 <3> 插入否则更新 <4> 替换 2、表的查找 <1>全列查询 <2>指定列查询 <3> where条件 <4> 筛选分页结果 3、表的修改 4、表的数据删除 5、查看表结构 6、插入查询结…

SpringCloud微服务项目实战 - 2.App登录及网关

如果你追求一个局部的更好甚至完美,你有可能花费巨大的资源和时间&#xff1b; 从总体上看&#xff0c;这往往意味着总体的浪费和失败&#xff0c;这是传说中的“打赢了战役打输了战争”。 系列文章目录 项目搭建App登录及网关 文章目录系列文章目录一、App登录1. 需求分析2. …

2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest K. The Robot

翻译&#xff1a; 有一个机器人在一个没有尽头的方格场上。最初&#xff0c;机器人位于坐标为(0,0)的单元中。他将执行由一串大写拉丁字母“L”、“R”、“D”、“U”所描述的命令。当一个命令被执行时&#xff0c;机器人只是朝着相应的方向移动: “L”:向左一个单元格(当前单…

【聆思CSK6 视觉AI开发套件试用】AI控制直流电机转速接口打通

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;oxlm 背景 在访问极术社区时&#xff0c;偶然发现聆思科技的CSK6开发板的评估活动&#xff0c;看CSK6的硬件配置和技术规格&#xff0c;300M…

JavaScript奇淫技巧:变速齿轮

JavaScript奇淫技巧&#xff1a;变速齿轮 在PC时代&#xff0c;曾有个名为“变速齿轮”的神奇软件&#xff0c;可以加快或减慢系统时间。 当时常用来修改游戏速度&#xff0c;可实现外挂一般的效果&#xff0c;很不可思议。 本文&#xff0c;将用JavaScript复刻这一功能&…

maven在无互联网(内网)环境下打包

Maven在内网环境打包 首先需要准备好项目所需的所有依赖包 我们可以在外网环境下&#xff0c;更改idea中Maven的local repository目录&#xff0c;然后刷新一下项目&#xff0c;将项目所需的依赖下载到更换的目录下 将新建的依赖目录和项目一起拷贝到内网环境下将依赖文件拷贝…

带你学懂数据结构中的八大排序(下)

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; 数据结构 | C语言 &#x1f38a;每篇一句&#xff1a; 图片来源 You can avoid reality, but you cannot avoid the consequences of avoiding reality. 你可以逃避现实&#xff0c;但你无法逃避其带来的后果…

《图解TCP/IP》阅读笔记(第八章 8.1~8.4)—— 概要,TELNET、FTP、SMTP、POP、IMAP协议介绍

前言 本篇篇幅较长&#xff0c;请耐心或者选择性阅读。 第八章 应用协议 从本篇开始&#xff0c;将介绍一些应用层协议&#xff0c;一般情况下&#xff0c;人们不太会在意网络应用程序实际上是按照何种机制正常运行的。本章旨在介绍TCP/IP中所使用的几个主要应用协议&#x…