我不确定这个问题的主题是什么,但是我们走了......
为了强制代码的关键部分的代码局部性/紧凑性,我正在寻找一种方法在调用时R_X86_64_JUMP_SLOT直接通过"跳槽"(ELF 重定位)在外部(动态加载)库中调用函数site - 链接器通常放入PLT/GOT的内容,但是在调用站点上有这些内联.
如果我模仿这样的调用:
#include <stdio.h>
int main(int argc, char **argv)
{
asm ("push $1f\n\t"
"jmp *0f\n\t"
"0: .quad %P0\n"
"1:\n\t"
: : "i"(printf), "D"("Hello, World!\n"));
return 0;
}Run Code Online (Sandbox Code Playgroud)
为了得到一个64位字的空间,电话本身是有效的(拜托,没有评论这是幸运的巧合,因为这打破了某些ABI规则 - 所有这些都不是这个问题的主题......并且,对于我的情况,可以工作围绕/以其他方式解决,我试图保持这个例子简短).
它创建以下程序集:
0000000000000000 <main>:
0: bf 00 00 00 00 mov $0x0,%edi
1: R_X86_64_32 .rodata.str1.1
5: 68 00 00 00 00 pushq $0x0
6: R_X86_64_32 .text+0x19
a: ff 24 25 00 00 00 00 jmpq *0x0
d: R_X86_64_32S .text+0x11
...
11: R_X86_64_64 printf
19: 31 … 考虑以下功能:
extern void test1(void);
extern void test2(void) {
test1();
}
Run Code Online (Sandbox Code Playgroud)
这是gcc -fpic在amd64 Linux上生成的代码:
test2:
jmp test1
Run Code Online (Sandbox Code Playgroud)
当我编译时-fpic,gcc显式调用PLT来启用符号插入:
test2:
jmp test1@PLT
Run Code Online (Sandbox Code Playgroud)
然而,这对于与位置无关的代码并不是严格需要的,如果我不想支持,可能会被遗漏.如有必要,链接器仍然会将跳转目标重写为PLT符号.
如何在不更改源代码且不使编译代码不适合共享库的情况下,使函数调用直接转到其目标而不是通过PLT显式转换?
我对技术物流很感兴趣.是否有任何优势,例如保存的内存等,来实现处理类的某些功能?
特别是,将操作符重载实现为自由函数(假设您不需要访问任何私有成员,即使这样,您也可以让他们使用非成员的朋友)?
每次创建对象时,是否为类的每个函数提供了不同的内存地址?
我正在尝试通过编译简单的函数和查看输出来学习汇编.
我正在考虑调用其他库中的函数.这是一个玩具C函数,它调用其他地方定义的函数:
void give_me_a_ptr(void*);
void foo() {
give_me_a_ptr("foo");
}
Run Code Online (Sandbox Code Playgroud)
这是gcc生成的程序集:
$ gcc -Wall -Wextra -g -O0 -c call_func.c
$ objdump -d call_func.o
call_func.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <foo>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov $0x0,%edi
9: e8 00 00 00 00 callq e <foo+0xe>
e: 90 nop
f: 5d pop %rbp
10: c3 retq
Run Code Online (Sandbox Code Playgroud)
我期待着类似的东西call <give_me_a_ptr@plt>.为什么在它知道give_me_a_ptr定义的位置之前它会跳到相对位置?
我也很困惑mov $0, %edi.这看起来像是在传递一个空指针 …