Home > Back-end >  cast a function from mmap allocated address -- I can't figure out which address to use
cast a function from mmap allocated address -- I can't figure out which address to use

Time:04-22

First, apologies for the title, I don't really know how to explain it.

I'm allocating a private block of memeory with mmap like this :

char *err = mmap(
    (void*) ( alloc_size * (1 << 20)),          // Map from the start of the 2^20th page
    4 * alloc_size,                     // for one page length
    PROT_READ |  PROT_WRITE | PROT_EXEC,
    34,                         // to a private block of hardware memory
    0,
    0
    );

( The alloc_size is 1<<12 = 4096)

apparently I can cast to a function pointer [typedef int (*foo)()] like this:

foo f = (foo)0x10000000
f();

the system finds the address and thus calls the function. But the problem occures when I try something bigger than 4096, namely 1<<13 = 8192, it can no longer find the address valid. Please help me figure out what address to use and how all of these really work.

CodePudding user response:

Please help me figure out what address to use and how all of these really work.

Don't try to figure out an address to use. By far the easiest and most portable way to do it is to let mmap() choose by passing a null pointer as the first argument:

void *p = mmap(
    NULL,                        // mmap chooses the address
    4 * alloc_size,              // length
    PROT_READ |  PROT_WRITE | PROT_EXEC,
    MAP_PRIVATE | MAP_ANONYMOUS, // visible only to this process; not backed by a file
    0,                           // n/a for MAP_ANONYMOUS
    0                            // n/a for MAP_ANONYMOUS
    );

As far as

apparently I can cast to a function pointer [typedef int (*foo)()] like this:

foo f = (foo)0x10000000

, it is very poor form to hide pointer nature behind a typedef, and it is questionable to declare a function or function pointer type that does not provide a prototype. Otherwise, yes, you can do that, but the result of converting an integer to a pointer is implementation-defined, except in a couple of narrow cases that do not include that one. If you were writing for a freestanding implementation then that might nevertheless make sense to do, but otherwise not.

I suppose that you are trying to match the address of the function to the address of the mapped memory, but as long as you are relying on POSIX mmap, you might as well also rely on POSIX's provision that you may convert a void * to a function pointer:

int (*f)(void) = p;

Overall, the point appears to be to create a function dynamically, and then call it. Please do not take my answering your question as in any way condoning such activity. It is a terrible idea, and not supported by ISO C. That POSIX semantics provide a way to do it in no way makes it a good idea.

  • Related