为什么有些重定位是 .text + 加数而不是符号的名称 + 加数?
Why are some relocations .text + addend instead of symbol's name + addend?
为什么 ELF 文件中的某些重定位条目 symbol name + addend
而其他的 section + addend
?我希望消除一些困惑并加深对 ELF 的理解。下面是我的调查。
我有一个非常简单的 C 文件,test.c
:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
static void func1(void)
{
fprintf(stdout, "Inside func1\n");
}
// ... a couple other simple *static* functions
int main (void)
{
func1();
// ... call some other functions
exit(EXIT_SUCCESS);
}
然后我将其编译成目标文件:
clang -O0 -Wall -g -c test.c -o test.o
如果使用 readelf -r test.o
查看重定位,我会看到引用我的静态函数的条目如下(该条目选自 .rela.debug_info
部分):
Offset Info Type Symbol's Value Symbol's Name + Addend
...
000000000000006f 0000000400000001 R_X86_64_64 0000000000000000 .text + b0
...
为什么这些函数被称为 section + addend
而不是 symbol name + addend
?我使用 readelf -s test.o
:
在 .symtab
中看到函数条目
Num: Value Size Type Bind Vis Ndx Name
...
2: 00000000000000b0 31 FUNC LOCAL DEFAULT 2 func1
...
此外,当我反汇编目标文件时(通过 objdump -d
),我看到函数在那里并且没有优化成 main
或任何东西。
如果我 不使函数静态化 然后查看重定位,当类型为 R_X86_64_64
时,我看到的结果与以前相同,但我也查看使用符号名称加上类型为 R_X86_64_PC32
的加数的条目。例如 .rela.text
:
Offset Info Type Symbol's Value Symbol's Name + Addend
...
00000000000000fe 0000001200000002 R_X86_64_PC32 0000000000000000 func1 + 1c
...
如果更多 examples/readelf 输出有帮助,请告诉我。感谢您花时间阅读本文。
Why are these functions referred to as section + addend rather than symbol name + addend?
不保证静态函数的函数名称在 link 时出现。您可以使用例如删除它们objcopy --strip-unneeded
或 objcopy --strip-symbol
,结果仍然是 link。
I see entries for the functions in the .symtab
using readelf -s test.o
我相信保留它们的唯一原因是为了帮助调试,linker 根本不使用它们。但是我没有通过查看 linker 来源来验证这一点,所以没有回答这个 .
Eli Bendersky 的博客在 his blog post 中也提到了这一点。来自标题为“额外功劳:为什么需要调用重定位?”的部分:
In short, however, when ml_util_func is global, it may be overridden in the executable or another shared library, so when linking our shared library, the linker can't just assume the offset is known and hard-code it [12]. It makes all references to global symbols relocatable in order to allow the dynamic loader to decide how to resolve them. This is why declaring the function static makes a difference - since it's no longer global or exported, the linker can hard-code its offset in the code.
应该阅读完整的 post 以获得完整的上下文,但我想我会在这里分享它,因为它提供了比我的问题更好的例子,并强化了 Employed Russian 给出的解决方案。
为什么 ELF 文件中的某些重定位条目 symbol name + addend
而其他的 section + addend
?我希望消除一些困惑并加深对 ELF 的理解。下面是我的调查。
我有一个非常简单的 C 文件,test.c
:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
static void func1(void)
{
fprintf(stdout, "Inside func1\n");
}
// ... a couple other simple *static* functions
int main (void)
{
func1();
// ... call some other functions
exit(EXIT_SUCCESS);
}
然后我将其编译成目标文件:
clang -O0 -Wall -g -c test.c -o test.o
如果使用 readelf -r test.o
查看重定位,我会看到引用我的静态函数的条目如下(该条目选自 .rela.debug_info
部分):
Offset Info Type Symbol's Value Symbol's Name + Addend
...
000000000000006f 0000000400000001 R_X86_64_64 0000000000000000 .text + b0
...
为什么这些函数被称为 section + addend
而不是 symbol name + addend
?我使用 readelf -s test.o
:
.symtab
中看到函数条目
Num: Value Size Type Bind Vis Ndx Name
...
2: 00000000000000b0 31 FUNC LOCAL DEFAULT 2 func1
...
此外,当我反汇编目标文件时(通过 objdump -d
),我看到函数在那里并且没有优化成 main
或任何东西。
如果我 不使函数静态化 然后查看重定位,当类型为 R_X86_64_64
时,我看到的结果与以前相同,但我也查看使用符号名称加上类型为 R_X86_64_PC32
的加数的条目。例如 .rela.text
:
Offset Info Type Symbol's Value Symbol's Name + Addend
...
00000000000000fe 0000001200000002 R_X86_64_PC32 0000000000000000 func1 + 1c
...
如果更多 examples/readelf 输出有帮助,请告诉我。感谢您花时间阅读本文。
Why are these functions referred to as section + addend rather than symbol name + addend?
不保证静态函数的函数名称在 link 时出现。您可以使用例如删除它们objcopy --strip-unneeded
或 objcopy --strip-symbol
,结果仍然是 link。
I see entries for the functions in the
.symtab
usingreadelf -s test.o
我相信保留它们的唯一原因是为了帮助调试,linker 根本不使用它们。但是我没有通过查看 linker 来源来验证这一点,所以没有回答这个
Eli Bendersky 的博客在 his blog post 中也提到了这一点。来自标题为“额外功劳:为什么需要调用重定位?”的部分:
In short, however, when ml_util_func is global, it may be overridden in the executable or another shared library, so when linking our shared library, the linker can't just assume the offset is known and hard-code it [12]. It makes all references to global symbols relocatable in order to allow the dynamic loader to decide how to resolve them. This is why declaring the function static makes a difference - since it's no longer global or exported, the linker can hard-code its offset in the code.
应该阅读完整的 post 以获得完整的上下文,但我想我会在这里分享它,因为它提供了比我的问题更好的例子,并强化了 Employed Russian 给出的解决方案。