How about this program, which compiles normally and does not crash.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
extern char __executable_start;
extern char __etext;
int
main (int argc, char **argv)
{
int pagesize = sysconf (_SC_PAGE_SIZE);
char *start =
(char *) (((uintptr_t) & __executable_start) & ~(pagesize - 1));
char *end =
(char *) (((uintptr_t) & __etext + pagesize - 1) & ~(pagesize - 1));
mprotect (start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
printf ("Hello world\n");
void *m = main;
*((char *) m) = 0;
exit (0);
}
I've used __executable_start
and __etext
, but you might be better seeing if you can get these to work, which are at least documented in man pages:
NAME
`etext`, `edata`, `end` - end of program segments
SYNOPSIS
extern etext;
extern edata;
extern end;
DESCRIPTION
The addresses of these symbols indicate the end of various program segments:
`etext` This is the first address past the end of the text segment (the program
code).
`edata` This is the first address past the end of the initialized data segment.
`end` This is the first address past the end of the uninitialized data
segment (also known as the BSS segment).
CONFORMING TO
Although these symbols have long been provided on most UNIX systems, they are
not standardized; use with caution.