Hi there. The address space randomisation feature in 2.6.35 and above kernels breaks GCC's precompiled headers support. GCC works by compiling the header once, dumping the internal format out to disk, and then mmap()ing it back in at a fixed address. The solution for other architectures is for GCC to pick a spot in the virtual address space that is likely to be free and map the PCH in there. Most of them use 0x60000000 which from a bit of poking seems to be fine on ARM as well.
Can someone point me at the typical virtual address space for a ARM Linux process? How does 0x60000000 sound?
For reference, this is the code in kernel/arch/arm/mm/mmap.c that exposes the problem: /* 8 bits of randomness in 20 address space bits */ if (current->flags & PF_RANDOMIZE) addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
The GCC code with addresses for other architectures lives at: http://bazaar.launchpad.net/~linaro-toolchain-dev/gcc-linaro/4.5/view/head:/...
/proc/self/maps on a simple program gives:
00008000-00009000 r-xp 00000000 00:14 28747240 /home/michaelh/a.out 00010000-00011000 r--p 00000000 00:14 28747240 /home/michaelh/a.out 00011000-00012000 rw-p 00001000 00:14 28747240 /home/michaelh/a.out 00012000-00033000 rw-p 00000000 00:00 0 [heap] 2ab4c000-2ab4d000 rw-p 00000000 00:00 0 2ab5c000-2ab5e000 rw-p 00000000 00:00 0 2ab89000-2aba0000 r-xp 00000000 00:0d 26352847 /lib/ld-2.12.1.so 2aba8000-2aba9000 r--p 00017000 00:0d 26352847 /lib/ld-2.12.1.so 2aba9000-2abaa000 rw-p 00018000 00:0d 26352847 /lib/ld-2.12.1.so 2ac35000-2ac36000 rw-p 00000000 00:00 0 2ac93000-2aca0000 r-xp 00000000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca0000-2aca7000 ---p 0000d000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca7000-2aca8000 r--p 0000c000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca8000-2aca9000 rw-p 0000d000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca9000-2ad96000 r-xp 00000000 00:0d 26352832 /lib/libc-2.12.1.so 2ad96000-2ad9e000 ---p 000ed000 00:0d 26352832 /lib/libc-2.12.1.so 2ad9e000-2ada0000 r--p 000ed000 00:0d 26352832 /lib/libc-2.12.1.so 2ada0000-2ada1000 rw-p 000ef000 00:0d 26352832 /lib/libc-2.12.1.so 2ada1000-2ada4000 rw-p 00000000 00:00 0 7ed9c000-7edbd000 rw-p 00000000 00:00 0 [stack]
0x60000000 is well above the shared libraries and well below the stack.
-- Michael
On Thu, 14 Apr 2011, Michael Hope wrote:
Hi there. The address space randomisation feature in 2.6.35 and above kernels breaks GCC's precompiled headers support. GCC works by compiling the header once, dumping the internal format out to disk, and then mmap()ing it back in at a fixed address.
Oh my... This is really nasty.
The solution for other architectures is for GCC to pick a spot in the virtual address space that is likely to be free and map the PCH in there. Most of them use 0x60000000 which from a bit of poking seems to be fine on ARM as well.
Can someone point me at the typical virtual address space for a ARM Linux process? How does 0x60000000 sound?
The ARM user address space closely mimics the x86 32-bit user address space. So if 0x60000000 works fine there then it should be fine on ARM too.
Nicolas
On Wed, Apr 13, 2011 at 11:11 PM, Michael Hope michael.hope@linaro.org wrote:
Hi there. The address space randomisation feature in 2.6.35 and above kernels breaks GCC's precompiled headers support. GCC works by compiling the header once, dumping the internal format out to disk, and then mmap()ing it back in at a fixed address. The solution for other architectures is for GCC to pick a spot in the virtual address space that is likely to be free and map the PCH in there. Most of them use 0x60000000 which from a bit of poking seems to be fine on ARM as well.
This does sound rather an alarming design ... would it be hard to make the PCH blobs relocatable or position-independent?
How does GCC cope with multiple precompiled headers? Making them relocatable or position-independent might allow many to be mapped simultaneously, which might actually be a performance win (based on zero knowledge of the nature of this data or what GCC does with it...)
Cheers ---Dave
Can someone point me at the typical virtual address space for a ARM Linux process? How does 0x60000000 sound?
For reference, this is the code in kernel/arch/arm/mm/mmap.c that exposes the problem: /* 8 bits of randomness in 20 address space bits */ if (current->flags & PF_RANDOMIZE) addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
The GCC code with addresses for other architectures lives at: http://bazaar.launchpad.net/~linaro-toolchain-dev/gcc-linaro/4.5/view/head:/...
/proc/self/maps on a simple program gives:
00008000-00009000 r-xp 00000000 00:14 28747240 /home/michaelh/a.out 00010000-00011000 r--p 00000000 00:14 28747240 /home/michaelh/a.out 00011000-00012000 rw-p 00001000 00:14 28747240 /home/michaelh/a.out 00012000-00033000 rw-p 00000000 00:00 0 [heap] 2ab4c000-2ab4d000 rw-p 00000000 00:00 0 2ab5c000-2ab5e000 rw-p 00000000 00:00 0 2ab89000-2aba0000 r-xp 00000000 00:0d 26352847 /lib/ld-2.12.1.so 2aba8000-2aba9000 r--p 00017000 00:0d 26352847 /lib/ld-2.12.1.so 2aba9000-2abaa000 rw-p 00018000 00:0d 26352847 /lib/ld-2.12.1.so 2ac35000-2ac36000 rw-p 00000000 00:00 0 2ac93000-2aca0000 r-xp 00000000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca0000-2aca7000 ---p 0000d000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca7000-2aca8000 r--p 0000c000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca8000-2aca9000 rw-p 0000d000 00:0d 26352795 /lib/libbz2.so.1.0.4 2aca9000-2ad96000 r-xp 00000000 00:0d 26352832 /lib/libc-2.12.1.so 2ad96000-2ad9e000 ---p 000ed000 00:0d 26352832 /lib/libc-2.12.1.so 2ad9e000-2ada0000 r--p 000ed000 00:0d 26352832 /lib/libc-2.12.1.so 2ada0000-2ada1000 rw-p 000ef000 00:0d 26352832 /lib/libc-2.12.1.so 2ada1000-2ada4000 rw-p 00000000 00:00 0 7ed9c000-7edbd000 rw-p 00000000 00:00 0 [stack]
0x60000000 is well above the shared libraries and well below the stack.
-- Michael
linaro-dev mailing list linaro-dev@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-dev
Dave Martin dave.martin@linaro.org writes:
On Wed, Apr 13, 2011 at 11:11 PM, Michael Hope michael.hope@linaro.org wrote:
Hi there. The address space randomisation feature in 2.6.35 and above kernels breaks GCC's precompiled headers support. GCC works by compiling the header once, dumping the internal format out to disk, and then mmap()ing it back in at a fixed address. The solution for other architectures is for GCC to pick a spot in the virtual address space that is likely to be free and map the PCH in there. Most of them use 0x60000000 which from a bit of poking seems to be fine on ARM as well.
This does sound rather an alarming design ... would it be hard to make the PCH blobs relocatable or position-independent?
How does GCC cope with multiple precompiled headers? Making them relocatable or position-independent might allow many to be mapped simultaneously, which might actually be a performance win (based on zero knowledge of the nature of this data or what GCC does with it...)
The current PCH implementation is years old, and is really a hack that sits on top of the garbage collector. It basically dumps all of GCC's internal state out at a particular point, then reads it back in when the "precompiled header" is used. It's therefore only possible to have one precompiled header per compilation.
The model is that the package using PCH should have a common set of includes that every translation unit uses (or is at least prepared to accept). This common set can be put in the PCH, which must be included before anything else.
Like I said, a hack :-)
There is an ongoing project to use a streamed form of PCH. It's much more work than the current implementation was, but it should avoid the main drawbacks.
Richard
On Thu, Apr 14, 2011 at 12:09 PM, Richard Sandiford richard.sandiford@linaro.org wrote:
Dave Martin dave.martin@linaro.org writes:
On Wed, Apr 13, 2011 at 11:11 PM, Michael Hope michael.hope@linaro.org wrote:
Hi there. The address space randomisation feature in 2.6.35 and above kernels breaks GCC's precompiled headers support. GCC works by compiling the header once, dumping the internal format out to disk, and then mmap()ing it back in at a fixed address. The solution for other architectures is for GCC to pick a spot in the virtual address space that is likely to be free and map the PCH in there. Most of them use 0x60000000 which from a bit of poking seems to be fine on ARM as well.
This does sound rather an alarming design ... would it be hard to make the PCH blobs relocatable or position-independent?
How does GCC cope with multiple precompiled headers? Making them relocatable or position-independent might allow many to be mapped simultaneously, which might actually be a performance win (based on zero knowledge of the nature of this data or what GCC does with it...)
The current PCH implementation is years old, and is really a hack that sits on top of the garbage collector. It basically dumps all of GCC's internal state out at a particular point, then reads it back in when the "precompiled header" is used. It's therefore only possible to have one precompiled header per compilation.
The model is that the package using PCH should have a common set of includes that every translation unit uses (or is at least prepared to accept). This common set can be put in the PCH, which must be included before anything else.
Like I said, a hack :-)
eeaarrgh
There is an ongoing project to use a streamed form of PCH. It's much more work than the current implementation was, but it should avoid the main drawbacks.
Oh well, I will await developments with interest... ;)
---Dave