强制进入 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编译成一个可执行对象。为了确保 absdadd 函数将保留在 PLT 部分,我使用 -O0 编译 helper.omain.o 可以用更高的级别编译,比方说‘-O1’。

在可执行对象上,我希望看到所有 3 个函数的条目:strcmpabsdadd。然而,事实并非如此。

我是不是漏掉了什么? 有没有可能 linker 遗漏了一些东西,因为它发现它们从未被调用过?尽管使用 O0 作为助手,并使用 forceplt 函数的属性?

帮我好好庆祝一下……十岁。百万。问题!

干杯!

absstrcmp 被 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 条目。