由于原因,我想强制PLT部分中的一些条目。我已设法为某些条目执行此操作,但某些功能从未插入PLT。
所以,我们说main.c
:
int main(){
// some code
strcmp(a,b); //suppose a, b strings
// more code
// suppose that result of strcmp is used, so it won't be optimised away
}
和help.c
:
// declaration
void forceplt() __attribute__((__used__));
// definition
void forceplt(){
abs(-1);
__aeabi_dadd(0, 0);
}
然后,我将上述两个可重定位目标文件编译并链接到一个可执行对象中。为确保abs
和dadd
函数保留在PLT部分中,我使用helper.o
编译-O0
。 main.o
可以用更高级别编译,比如说'-O1'。
在可执行对象上,我希望看到所有3个函数的条目:strcmp
,abs
和dadd
。但事实并非如此。
我在这里遗漏了什么吗? 链接器是否有可能省略某些东西,因为它发现它们从未被调用过?尽管使用O0作为辅助函数,并使用了forceplt函数的属性?
帮我做一个正确的庆祝活动......十。百万。问题!
干杯!
答案 0 :(得分:2)
abs
和strcmp
由GCC特别识别,似乎编译器发现这些调用即使在-O0
中也没用。如果查看生成程序集(gcc foo.c -S -o-
),您会看到没有相应的调用指令。
PLT条目不是由编译器生成的:它们不存在于.o
文件中。当链接编辑器在其中一个输入.o
文件中找到相应的重定位时,它们将由链接编辑器生成。要生成PLT条目,您需要在其中一个输入.o
文件中生成合适的重定位条目。 .o
重定位始终适用于.o
文件的一部分:您需要在某些.o
部分中使用PLT重新定位的部分内存字节 - 意识到搬迁。它可以是(可能无用的)指令或其他一些(可能无用的)字节。
解决方案是创建(在汇编中)明确使用预期PLT条目的指令。使用x86_64,可以使用:
.text
.type forceplt2,@function
forceplt2:
callq abs@plt
我猜它在ARM中写得如此:
.text
.type forceplt2,%function
forceplt2:
bl abs@plt
或者您可以为重定位生成原始字节(再次在x86_64上):
.data
.align 8
.type forceplt3, @object
.size forceplt3, 8
forceplt3:
.quad socket@GOTPLT
On x_86_64,您应该能够使用@GOT
,@GOTPLT
,@GOTOFF
,@GOTPCREL
,@PLT
或{{1} }。我不确定如何编写for ARM。
这些解决方案中的任何一个都会发出一个合适的重定位条目,这将导致链接编辑器发出PLT条目和PLT GOT条目。