我正在编写将被编译的代码(使用gcc,定位到Android x86),然后由另一个程序处理。该程序对其输入有限制,例如代码不能进行间接调用或引用全局变量。要在PIC / PIE代码中强制执行此操作,调用get_pc_thunk(或任何只读取堆栈顶部并返回的函数)的工具错误
我的代码处于满足这些要求的状态。所有函数都链接在一起,并且可以在链接后通过偏移调用。但是GCC在我的函数中调用了get_pc_thunk,即使它没有被使用。
我的代码是(test.c):
unsigned long long API test(unsigned long long a, unsigned long long b)
{
return a / b;
}
构建这个我使用:
gcc.exe -o test.o -fno-stack-protector test.c -c -O0
gcc.exe -o libtest.so -m32 -static -static-libgcc -nostartfiles -shared test.o
我出去了:
000001d8 <test>:
1d8: 55 push ebp
1d9: 89 e5 mov ebp,esp
1db: 53 push ebx
1dc: 8d 64 24 dc lea esp,[esp-0x24]
1e0: e8 45 00 00 00 call 22a <__x86.get_pc_thunk.bx>
1e5: 81 c3 0f 1e 00 00 add ebx,0x1e0f
1eb: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
1ee: 89 45 f0 mov DWORD PTR [ebp-0x10],eax
1f1: 8b 45 0c mov eax,DWORD PTR [ebp+0xc]
1f4: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
1f7: 8b 45 10 mov eax,DWORD PTR [ebp+0x10]
1fa: 89 45 e8 mov DWORD PTR [ebp-0x18],eax
1fd: 8b 45 14 mov eax,DWORD PTR [ebp+0x14]
200: 89 45 ec mov DWORD PTR [ebp-0x14],eax
203: 8b 45 e8 mov eax,DWORD PTR [ebp-0x18]
206: 8b 55 ec mov edx,DWORD PTR [ebp-0x14]
209: 89 44 24 08 mov DWORD PTR [esp+0x8],eax
20d: 89 54 24 0c mov DWORD PTR [esp+0xc],edx
211: 8b 45 f0 mov eax,DWORD PTR [ebp-0x10]
214: 8b 55 f4 mov edx,DWORD PTR [ebp-0xc]
217: 89 04 24 mov DWORD PTR [esp],eax
21a: 89 54 24 04 mov DWORD PTR [esp+0x4],edx
21e: e8 0b 00 00 00 call 22e <__udivdi3>
223: 8d 64 24 24 lea esp,[esp+0x24]
227: 5b pop ebx
228: 5d pop ebp
229: c3 ret
0000022a <__x86.get_pc_thunk.bx>:
22a: 8b 1c 24 mov ebx,DWORD PTR [esp]
22d: c3 ret
0000022e <__udivdi3>:
...
通过了解正在发生的事情我明白在编译时gcc为get_pc_thunk和__udivdi3调用添加占位符,因为它不知道__udivdi3将在哪一点,并且可能需要通过查找表调用。但是在链接之后不再需要get_pc_thunk。我查看了链接器选项,但找不到可以优化此调用的选项。
在这种情况下是否可以选择删除此不需要的电话?
答案 0 :(得分:1)
对于Android NDK版本的gcc,有一个-fno-pic选项,允许在这种特殊情况下禁用PIC。