调用函数(main()中)从在C的二进制文件(Invoking a function (main()

2019-09-22 09:57发布

我有一个像,my_bin.c简单的C程序:

#include <stdio.h>

int main()
{
    printf("Success!\n");
    return 0;
}

我用gcc编译,并得到执行:my_bin。

现在,我想用另一种C程序来调用主(或者运行my_bin)。 那我做了MMAP和函数指针这样的:

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
int main()
{
   void (*fun)();
   int fd;
   int *map;
   fd = open("./my_bin", O_RDONLY);
   map = mmap(0, 8378, PROT_READ, MAP_SHARED, fd, 0);
   fun = map;
   fun();
   return 0;
}

编辑1:添加PROT_EXEC制作它的响应更加清晰......我想打电话给第二个程序内的外部二进制程序。

我不知道如何初始化函数指针与主(其它程序)的地址。 任何想法?

编辑2:

为什么赛格故障,谷歌搜索后,想通了,它因为我的尺寸和偏移MMAP的说法。 它应该是多个页面大小的。 [参考:段错误,同时使用MMAP用C用于读取二进制文件

现在,代码如下:

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
int main()
{
   void (*fun)();
   int fd;
   int *map;
   int offset = 8378;
   int pageoffset = offset % getpagesize();
   fd = open("./my_bin", O_RDONLY);
   if(fd == -1) {
        printf("Err opening file\n");
        return -1;
   }
   map = mmap(0, 8378 + pageoffset, PROT_READ|PROT_EXEC,
                        MAP_SHARED, fd, offset - pageoffset);
   perror("Err\n"); //This is printing err and Success!
   //fun = map; // If I uncomment this and 
   //fun();     // this line then, still it 
                // print err and Success! from perror
                // but later it says Illegal instruction. 
   return 0;
}

仍与乐趣()或无其不打印...不知道如何给main()的地址。

编辑2 [解决]:

第一件事:我没看过定义从中我应该读二进制文件正确,我已经给定的地址。 第二:MMAP:大小和偏移量应该是多个页面大小的。

Answer 1:

main()通常不是在C程序的第一功能。 链接器会放一些设置/初始化代码,这之前,除其他事项外,将设立环境,得到了命令行参数,把它解析为一个字符串数组,这样的东西。

当新的它变得有问题main()基本上,这会毁了你所有的主要应用的重要的数据结构-功能开始设置内存分配程序。

如果要执行的功能(即无main()然后编译C代码到一个共享库,并加载与dlopen()或你的操作系统的等价物。

如果你真的需要main()使用fork()exec()



Answer 2:

一般来说,通过编译和链接生成的可执行文件是不是你可以加载到内存并执行一个简单的二进制图像。 (有一定的计算平台的目标在哪里。)通常情况下,一个特殊的程序调用装载机具有读取可执行文件,利用该文件中的内容,并说明准备内存,并使用特殊的系统调用来启动程序的执行作为一个新的进程。

例如,可执行文件通常包含一些数据,必须被复制到存储器中,然后标记为只读,即必须被复制到存储器中,然后一些数据标记可读和可写的,和一些数据(称为“文本”或程序指令),该必须复制到内存和显着的可执行文件。 可执行文件通常还包含关于准备存储器,诸如拨出最初清除存储器的一些量,留出一定量的对堆栈空间,以开始执行(这通常不是该地址的一些其他信息main ),等。

一个复杂的方面是可执行文件包含有关什么程序部分文字和数据必须根据使用什么内存地址变更信息。 其中,数据和文字被放在内存中的地址可能不是在编译时是已知的,所以编译器写一些原型代码,并装载有调整代码它决定于地址后。

另一个难题是一个可执行文件可能包含在动态库中的符号引用。 装载机具有检查这些引用,并加载必要的动态库。

正如你所看到的,负载是不是一个简单的过程。 你不能简单的内存映射的可执行文件,并跳转到它,即使你可以揣摩出它main启动。

某些系统提供对装载机的接口。 这些通常使用具有动态库。 而不是建立一个独立的可执行程序,你会生成一个动态库。 然后,你可以使用调用动态库接口加载库,找到程序的起始地址在里面,并调用这些例程。

一般来说,一个编程环境并没有提供一种方便的方式来加载一个可执行文件并调用它的main程序。 这可能是更容易地创建一个动态库,而不是创建一个可执行文件,然后加载动态库,并调用它内部的程序。 可替代地,有一些方法来调用的可执行文件作为单独的过程中,使得它基本上单独运行,如在命令行键入的命令,而不会与调用进程共享存储器。



Answer 3:

“正确”的解决方案恕我直言,如果在一个可执行的连接功能,是不调用的main()从另一个功能。 相反,创建一个包装了一下main()中做了功能和来自主()叫它。

int success()
{   
  printf("Success!\n");
  return 0;
}

int main()
{
  return success();
}

调用外部系统调用,使用系统



文章来源: Invoking a function (main()) from a binary file in C