强制进入 PLT 部分
Force entries in PLT section
由于某些原因,我想在 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);
}
然后,我将上面的两个可重定位对象link编译成一个可执行对象。为了确保 abs
和 dadd
函数将保留在 PLT 部分,我使用 -O0
编译 helper.o
。 main.o
可以用更高的级别编译,比方说‘-O1’。
在可执行对象上,我希望看到所有 3 个函数的条目:strcmp
、abs
和 dadd
。然而,事实并非如此。
我是不是漏掉了什么?
有没有可能 linker 遗漏了一些东西,因为它发现它们从未被调用过?尽管使用 O0 作为助手,并使用 forceplt 函数的属性?
帮我好好庆祝一下……十岁。百万。问题!
干杯!
abs
和 strcmp
被 GCC 特别识别,编译器似乎认为这些调用即使在 -O0
中也是无用的。如果查看生成程序集(gcc foo.c -S -o-
),您会发现没有相应的调用指令。
PLT 条目不是由编译器生成的:它们不存在于 .o
文件中。当他们在其中一个输入 .o
文件中找到相应的重定位时,它们由 link 编辑器生成。为了生成 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, you should be able to use either @GOT
, @GOTPLT
, @GOTOFF
, @GOTPCREL
, @PLT
or @PLTOFF
. I'm not so sure how this is supposed to be written for ARM.
这些解决方案中的任何一个都会发出一个合适的重定位条目,这将导致 link 编辑器发出一个 PLT 条目和一个 PLT GOT 条目。
由于某些原因,我想在 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);
}
然后,我将上面的两个可重定位对象link编译成一个可执行对象。为了确保 abs
和 dadd
函数将保留在 PLT 部分,我使用 -O0
编译 helper.o
。 main.o
可以用更高的级别编译,比方说‘-O1’。
在可执行对象上,我希望看到所有 3 个函数的条目:strcmp
、abs
和 dadd
。然而,事实并非如此。
我是不是漏掉了什么? 有没有可能 linker 遗漏了一些东西,因为它发现它们从未被调用过?尽管使用 O0 作为助手,并使用 forceplt 函数的属性?
帮我好好庆祝一下……十岁。百万。问题!
干杯!
abs
和 strcmp
被 GCC 特别识别,编译器似乎认为这些调用即使在 -O0
中也是无用的。如果查看生成程序集(gcc foo.c -S -o-
),您会发现没有相应的调用指令。
PLT 条目不是由编译器生成的:它们不存在于 .o
文件中。当他们在其中一个输入 .o
文件中找到相应的重定位时,它们由 link 编辑器生成。为了生成 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, you should be able to use either @GOT
, @GOTPLT
, @GOTOFF
, @GOTPCREL
, @PLT
or @PLTOFF
. I'm not so sure how this is supposed to be written for ARM.
这些解决方案中的任何一个都会发出一个合适的重定位条目,这将导致 link 编辑器发出一个 PLT 条目和一个 PLT GOT 条目。