4

I have simple c program like, my_bin.c:

#include <stdio.h>

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

I compile it with gcc and got executable: my_bin.

Now I want to invoke main (or run this my_bin) using another C program. That I did with mmap and function pointer like this:

#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;
}

EDIT 1: added PROT_EXEC Making it more clear from responses ... I want to call an external binary program within second program.

I don't know how to initialize function pointer with the address of main(other program's). any idea?

EDIT 2:

Why seg fault, after googling, figured out, its because of my size and offset argument of mmap. It should be multiple of pagesize. [Reference: Segfault while using mmap in C for reading binary files

Now the code looks like:

#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;
}

Still with fun() or without that its not printing ... not sure how to give main() address.

Edit 2[Solved]:

First thing: I didn't read definition properly, I have already given address from which I should read binary file. Second: mmap: size and offset should be multiple of pagesize.

Damian Yerrick
  • 4,602
  • 2
  • 26
  • 64
code muncher
  • 1,592
  • 2
  • 27
  • 46
  • For one, you not giving execute permissions. You'll need at least `PROT_EXEC`. – Mysticial Sep 13 '12 at 15:39
  • Your mmap call assumes that the function main() in my_bin executable begins at offset 0, which is not correct. I am not an expert but I think this is one of the reasons. – sandyiscool Sep 13 '12 at 15:44
  • Are you wanting to call an external program, or are you wanting to call the functionality of main() from within the second program? – Josh Petitt Sep 13 '12 at 15:53
  • @JoshPetitt I want to call an external binary program within second program. – code muncher Sep 13 '12 at 16:28
  • @sandyiscool ,... yeah neither do I ... as I don't know how to initialize function pointer with the address of main. any idea? – code muncher Sep 13 '12 at 16:30
  • @DharaDarji : You can have a look at http://www.thegeekstuff.com/2012/01/advanced-c-pointers/ . It shows an example demonstarting how to define and use a function pointer, among other things. – sandyiscool Sep 13 '12 at 17:08
  • @DharaDarji if you want to call a system command, then look at http://www.cplusplus.com/reference/clibrary/cstdlib/system/ – Josh Petitt Sep 13 '12 at 17:16
  • BTW, if you are executing another command, then you don't really care if there is a main() or not. It might not even be in C. You are just executing a command. – Josh Petitt Sep 13 '12 at 17:18
  • @JoshPetit "if you are executing another command .." here you mean system command right? I need to check that .. thanks but – code muncher Sep 13 '12 at 17:19
  • @DharaDarji, yes. In the context of your program, any other program you are invoking via the system call would be a system command. The results of this may vary depending on your OS. – Josh Petitt Sep 13 '12 at 17:20

3 Answers3

6

main() usually isn't the first function in a C program. The linker will put some setup/init code before that which, among other things, will set up the environment, get the command line arguments, parse them into a string array, stuff like that.

It gets problematic when the new main() function starts to set up the memory allocation routines - basically, this will ruin all the important data structures of your main application.

If you want to execute a function (i.e. without main()), then compile your C code into a shared library and load that with dlopen() or your OS's equivalent.

If you really need main(), use fork() and exec().

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • make sense. but I want to use function pointer .. and not with exec() ... like initializing function pointer with address of main. Is t possible? As this is something like, calling an extern function (but here what I've given is binary file) – code muncher Sep 13 '12 at 16:37
1

Generally, the executable file produced by compiling and linking is not a simple binary image that you can load into memory and execute. (There are certain computing platform targets where it is.) Usually, a special program called a loader has to read the executable file, prepare memory using the contents of and instructions in the file, and use special system calls to initiate execution of the program as a new process.

For example, executable files usually contain some data that must be copied to memory and then marked read-only, some data that must be copied to memory and then marked readable and writeable, and some data (called “text” or program instructions) that must be copied to memory and marked executable. The executable file usually also contains some other information about preparing memory, such as setting aside some amount of initially cleared memory, setting aside a certain amount for stack space, which address to start executing at (which is usually not main), and so on.

One complicated aspect is that the executable file contains information about what parts of the program text and the data have to be changed according to what memory addresses are used. The addresses where data and text are put in memory may not be known at compile time, so the compiler writes some prototype code, and the loader has to adjust the code after it decides upon the addresses.

Another complication is that an executable file may contain references to symbols in dynamic libraries. The loader has to examine those references and load the necessary dynamic libraries.

As you can see, loading is not a simple process. You cannot simply memory map an executable file and jump to it, even if you can figure out where in it main starts.

Some systems provide an interface to the loader. These are typically used with dynamic libraries. Instead of building a stand-alone executable program, you would build a dynamic library. Then you could use calls to the dynamic library interface to load the library, find the addresses of routines in it, and call those routines.

Generally, a programming environment does not provide a convenient way to load an executable file and call its main routine. It may be easier to create a dynamic library instead of creating an executable file and then to load the dynamic library and call a routine inside of it. Alternatively, there are ways to invoke an executable file as a separate process, so that it essentially runs separately, like a command typed at the command line, without sharing memory with the calling process.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

The "correct" solution IMHO if linking the functionality in one executable, is to not call main() from another function. Rather, create a function that wraps up what main() does and call it from both main()s.

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

int main()
{
  return success();
}

For calling external system call, use system

Josh Petitt
  • 9,371
  • 12
  • 56
  • 104