Linux内核 - 为什么System.map中的函数地址是实时看到的地址之前的一个字节?

时间:2023-01-08 20:39:18

In linux kernel source code, added this lines in tasklet_action code:

在linux内核源代码中,在tasklet_action代码中添加了以下行:

printk("tasklet_action = %p\n" , *tasklet_action);
printk("tasklet_action = %p\n" , &tasklet_action);
printk("tasklet_action = %p\n" , tasklet_action);

In the output I get:

在输出中我得到:

tasklet_action = c03441a1
tasklet_action = c03441a1
tasklet_action = c03441a1

But when searching it in the system.map file the tasklet_action address is at c03441a0 so there is an offset of 1 byte.

但是当在system.map文件中搜索它时,tasklet_action地址位于c03441a0,因此存在1个字节的偏移量。

  • Why do I have this offset?
  • 为什么我有这个偏移?
  • Is it always an one byte offset?
  • 它总是一个字节的偏移量?

1 个解决方案

#1


18  

My guess is that you are running on ARM in Thumb mode, or on some other architecture that uses the bottom bit of the function pointer to indicate which mode to run in.

我的猜测是你在Thumb模式下运行ARM,或者在使用函数指针底部位的其他一些体系结构上运行,以指示运行哪种模式。

If so, the answer is that your function really is located at the address in the system.map.

如果是这样,答案是您的函数确实位于system.map中的地址。

The value you get at run time is the location and the mode.

运行时获得的值是位置和模式。

Instructions, on these kinds of architectures, always must be 2- or 4-byte aligned, which would leave the bottom bit always zero. When the architecture grew an extra mode the designers made use of the 'wasted' bit to encode the mode. It's clever, but confusing, and not just for you: a lot of software, like debuggers, broke in many nasty ways when this was first invented.

在这些类型的体系结构上的指令始终必须是2或4字节对齐,这将使底部位始终为零。当架构增长为额外模式时,设计人员利用“浪费”位对模式进行编码。它很聪明,但令人困惑,而且不只是为了你:很多软件,比如调试器,在最初发明时会以许多令人讨厌的方式破解。

The concept is particularly confusing for x86 programmers who are used to variable-length instructions with any random alignment.

对于习惯于任意随机对齐的可变长度指令的x86程序员来说,这个概念尤其令人困惑。

#1


18  

My guess is that you are running on ARM in Thumb mode, or on some other architecture that uses the bottom bit of the function pointer to indicate which mode to run in.

我的猜测是你在Thumb模式下运行ARM,或者在使用函数指针底部位的其他一些体系结构上运行,以指示运行哪种模式。

If so, the answer is that your function really is located at the address in the system.map.

如果是这样,答案是您的函数确实位于system.map中的地址。

The value you get at run time is the location and the mode.

运行时获得的值是位置和模式。

Instructions, on these kinds of architectures, always must be 2- or 4-byte aligned, which would leave the bottom bit always zero. When the architecture grew an extra mode the designers made use of the 'wasted' bit to encode the mode. It's clever, but confusing, and not just for you: a lot of software, like debuggers, broke in many nasty ways when this was first invented.

在这些类型的体系结构上的指令始终必须是2或4字节对齐,这将使底部位始终为零。当架构增长为额外模式时,设计人员利用“浪费”位对模式进行编码。它很聪明,但令人困惑,而且不只是为了你:很多软件,比如调试器,在最初发明时会以许多令人讨厌的方式破解。

The concept is particularly confusing for x86 programmers who are used to variable-length instructions with any random alignment.

对于习惯于任意随机对齐的可变长度指令的x86程序员来说,这个概念尤其令人困惑。