当前位置: 首页 > news >正文

_RET_IP_ 和_THIS_IP_ 作用

在Linux内核中,有两个罕见的宏定义_RET_IP_ 和_THIS_IP_。但是这两个宏在内核代码中又时不时的出现,那么它们到底是什么含义呢?

1、宏定义

我们先看它们的宏定义

include./linux/kernel.h#define _RET_IP_		(unsigned long)__builtin_return_address(0)#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })

我们先看_RET_IP_的含义:

#define _RET_IP_ (unsigned long)__builtin_return_address(0)

其中__builtin_return_address(0) 是gcc内建函数,返回函数的返回地址。所以_RET_IP_ 宏定义用于返回当前函数的返回地址(当前函数被调用处的地址)

在看看_THIS_IP_的含义:

#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })

__lable__ 是gcc对c语言的扩展,用于局部标签,__label__ __here; 声明了一个局部标签__here。

什么是局部标签?

GCC allows you to declare local labels(局部标签) in any nested block scope.A local label is just like an ordinary label, but you can only reference it (with a goto statement, or by taking its address) within the block in which it is declared.

一个局部标签只是一个标识符:可以使用通常的goto语句进行跳转或者获取其地址,但是只能在其所属的域内内。

A local label declaration looks like this:(局部标签定义如下:)

__label__ label;

or

__label__ label1, label2, /* … */;

You can get the address of a label defined in the current function (or a containing function) with the unary operator ‘&&’.The value has type void *.

我们可以通过'&&'符号来获取局部标签的地址(获取变量的地址是'&'),地址类型为void *.

#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })

先定义了一个局部标签 __here,后面是__here标签的内容,和我们使用goto语句时的标签的用法是一样的,  __here: (unsigned long)&&__here; 返回局部标签__here所在位置的地址。所以_THIS_IP_返回当前位置的地址(PC指针的值)

内核中有个专门返回当前代码段的地址的宏定义:

#define current_text_addr() ({ __label__ _l; _l: &&_l;})

和_THIS_IP_的宏定义是一样的。

2、测试

下面我们写个简单的程序测试下

#include <stdio.h>
#include <stdlib.h>#define _RET_IP_	(unsigned long)__builtin_return_address(0)#define _THIS_IP_  	({ __label__ __here; __here: (unsigned long)&&__here; })void bar(void)
{/*This is bar (400551,40052a) */printf("This is bar (%x,%x) \012",_RET_IP_,_THIS_IP_);return ;
}int main()
{bar();return 0;
}

上面程序输出结果是:This is bar (400551,40052a)

我们将上面程序反汇编结果如下:

0000000000400526 <bar>:

400526: 55 push %rbp

400527: 48 89 e5 mov %rsp,%rbp

40052a: ba 2a 05 40 00 mov $0x40052a,%edx

40052f: 48 8b 45 08 mov 0x8(%rbp),%rax

400533: 48 89 c6 mov %rax,%rsi

400536: bf e4 05 40 00 mov $0x4005e4,%edi

40053b: b8 00 00 00 00 mov $0x0,%eax

400540: e8 bb fe ff ff callq 400400 <printf@plt>

400545: 90 nop

400546: 5d pop %rbp

400547: c3 retq

0000000000400548 <main>:

400548: 55 push %rbp

400549: 48 89 e5 mov %rsp,%rbp

40054c: e8 d5 ff ff ff callq 400526 <bar>

400551: b8 00 00 00 00 mov $0x0,%eax

400556: 5d pop %rbp

400557: c3 retq

400558: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)

40055f: 00

_RET_IP_的打印结果是400551,但是调用bar函数的地址是40054c。由于流水线的原因,取指完成后PC=PC+4,所以_RET_IP_的值为400551.

_THIS_IP_的打印结果是40052a,该地址是printf打印中_THIS_IP_入栈时的地址值。

上面的打印结果和我们理解的结果是一致的。

http://www.lryc.cn/news/445823.html

相关文章:

  • Spring Boot 点餐系统:高效餐饮服务
  • RtspServer:轻量级RTSP服务器和推流器
  • 为什么结构化 Prompt 如此有效?
  • 无人机飞手培训校企合作特训技术详解
  • 从零开始的软件开发详解:数字药店系统源码与医保购药APP
  • 【记录】在返回值类型为BigDecimal情况下末尾小数位为0的会省略不显示
  • 通信工程高级职称评审条件详细解读
  • yolov8环境安装
  • C语言中易混淆概念的关键字
  • 网络资源模板--Android Studio 零食工坊(商城)
  • 百度高德坐标系相互转换
  • 免费下载6组简历模板,让HR一眼相中你!
  • 设计模式之模版方法模式
  • 解析!文档扫描 SDK 中的高级图像处理技术
  • 线性判别分析(LDA)中求协方差矩阵示例
  • Maven的详细解读和配置
  • 在vue2项目中使用dart-sass
  • 【机器学习】过拟合与欠拟合——如何优化模型性能
  • 二进制日志gtid模式
  • 华硕主板开启TPM 2.0
  • Linux 一键部署Mysql 8.0.37
  • Elasticsearch可视化工具ElasticHD
  • Chrome截取网页全屏
  • Why Is Prompt Tuning for Vision-Language Models Robust to Noisy Labels?
  • C++ 折叠表达式
  • 双控开关接入NVBoard
  • 聊一聊软件系统性能测试的重要性
  • 双十一有哪些好物值得入手?五款超值数码好物分享!
  • uniapp监听滚动实现顶部透明度变化
  • Humanoid 3D Charactor_P08_Federica