Plan for tomorrow's FESCo meeting (2011-06-21)

Adam Jackson ajax at redhat.com
Fri Jun 24 21:16:12 UTC 2011


On 6/24/11 3:31 AM, Richard W.M. Jones wrote:

> I don't think GHC generates C (it used to, a very long time ago).  GHC
> and OCaml contain code generators that generate machine code directly.
>
> So this could require changes to the code generator, but at least for
> RELRO it seems this is just a link-time change (is it?)

It's a link time change in that you have to ask the linker to create the 
GNU_RELRO segment put stuff in it, yes.  But it's also a code generation 
change if you want that segment to have anything in it besides the C 
runtime details.

Maybe an example will make this clear:

% cat test.c
#include <stdlib.h>
typedef void (*exit_type)(int);
maybeconst exit_type exit_type_array[] = { exit };
% gcc -Dmaybeconst= -c -o mutable.o test.c
% gcc -Dmaybeconst=const -c -o const.o test.c
% readelf -a mutable.o | grep -B2 -m1 exit
Relocation section '.rela.data' at offset 0x438 contains 1 entries:
   Offset          Info           Type           Sym. Value    Sym. Name 
+ Addend
000000000000  000800000001 R_X86_64_64       0000000000000000 exit + 0
% nm -a --defined mutable.o | grep exit
0000000000000000 D exit_type_array
% readelf -a const.o | grep -B2 -m1 exit
Relocation section '.rela.rodata' at offset 0x498 contains 1 entries:
   Offset          Info           Type           Sym. Value    Sym. Name 
+ Addend
000000000000  000900000001 R_X86_64_64       0000000000000000 exit + 0
% nm -a --defined const.o | grep exit
0000000000000000 R exit_type_array

We're not getting anywhere near the linker yet, but codegen has done 
different things.  When the array is expected to be const, the symbol 
and relocation info for the array are emitted into different sections.

Now, imagine tacking on to our test program something like:

#include <stdio.h>
int main(void) { printf("%p\n", exit_type_array[0]); return 0 }

and compiling it.  In this case, -z relro on its own will not help: the 
address of the 'exit' function isn't known until it's first called, 
because function resolution is normally done lazily, and because the 
'exit' symbol is not provided in the executable itself.  So the 
exit_type_array will end up in the final executable in a writeable 
section.  However, -z relro _will_ constify relocations that end up as 
part of the same linked object, eg, a function defined in one 
translation unit whose address is taken in another.

If instead you say both -z relro and -z now, then you are explicitly 
asking the runtime linker to resolve all symbols up front.  In this case 
the address of 'exit' _will_ be known before ctors are run, which means 
the array can be emitted in a .data.rel.ro section, which is initially 
writeable but made read-only after relocations.

- ajax


More information about the devel mailing list