我有一个简单的c文件,它在main中打印一条消息而不执行任何其他操作 使用gcc编译它来生成.out文件。使用elf解析器获取entry_address 启动函数和使用此addressas函数指针我试图执行c文件中的main函数,但它给出了seg错误。
e.g
test.c
void main()
{
print("something");
}
通过gcc生成的test.out elf文件
我通过nm test.out
得到以下内容0000000000601020 A _edata
0000000000601030 A _end
00000000004005e8 T _fini
00000000004003c8 T _init
0000000000400410 T _start
000000000040043c t call_gmon_start
0000000000601020 b completed.6531
0000000000601010 W data_start
0000000000601028 b dtor_idx.6533
00000000004004d0 t frame_dummy
00000000004004f4 T main
起始地址为0x0400410 T _start
。
现在我写下面的另一个c代码来执行test.c中的main函数。
execute.c
void main()
{
typedef int func(void);
f = (func*)0x00400410;
f();
}
gcc execute.c -o execute.out
编译excute.c会在调用f()
时给出分段错误。
所需的输出是打印something
。
是否可以从地址执行elf文件功能,我错了。
答案 0 :(得分:1)
您的问题表明了一些基本的错误理解。让我们一个接一个。
首先,正如hcs指出的那样,test.out
和execute.out
彼此之间没有没有。当一个正在运行时,另一个不加载到您的进程空间中。你期望能够从test.out
execute.out
调用一个函数与我右前裤口袋中的钱数(就像你在那里找到一个25c硬币)一样,然后伸入你自己的右前裤口袋里,并希望在那里找到相同的25c硬币。
与此相关,你也期望甚至拥有合适的裤子口袋,因为我有一个(希望在_start
0x00400410
找到execute.out
仅因为_start
}在test.out
)的那个地址。实际上,您可能会在同一地址找到_start
,或者您可能找不到。也许你今天穿着短裙,而且根本没有前右裤袋。
最后,考虑一下程序的执行情况。谁叫你main
例程? (那是对的,_start
确实如此)。现在,您已安排main
再次致电_start
。你有什么期望呢?它会再次调用main
。这将再次呼叫_start
。这称为无限递归,并且会导致二进制文件因堆栈耗尽而崩溃。
注意:崩溃的实际原因是不同的,并且与_start
在同一进程中不期望被调用两次的事实有关。