views:

76

answers:

1

Hi all,

I am generating x86-64 code at runtime in a C program on a linux system (centos 5.4 to be exact).

I generate my bytecodes into a global array as shown below

char program[1024 * 1024] __attribute__((aligned (16)));

and then call into it via a function pointer.

My issue is, when I compile the program like this

gcc -std=gnu99 parse.c -o parse -lm

I get a SIGSEGV, which I am surmising is due to the bss section not being set as executable, as shown by pmap

0000000000601000      4K rw---  /data/work/tmp/parse
0000000000602000   1024K rw---    [ anon ]

when I compile it like this, (empty.s is a zero-length file)

gcc -std=gnu99 parse.c empty.s -o parse -lm

during runtime, the bss sections magically have the execute bit set, and everything works just great.

0000000000601000      4K rwx--  /data/work/tmp/parse
0000000000602000   1024K rwx--    [ anon ]

So, how do these flags get set up in the ELF? And is there a reliable, correct way to get a bss section with rwx permissions?

More details - software versions

gcc version 4.1.2 20080704 (Red Hat 4.1.2-48)
Linux 2.6.18-164.15.1.el5 x86_64 GNU/Linux

Thankyou

update - at first I thought I could not use mmap to solve this problem as caf suggested, because mmap was giving me back pages that were too far away (I wanted to jump into nearby code with relative adressing). It turns out that you can ask mmap to take care of this for you, like so - the MAP_32BIT will give you back a page in the first 2GB.

char* program = mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+1  A: 

You should probably just directly request a writeable, executable anonymous mapping with mmap() to store your generated machine code.

caf