$ gcc -m32 -fPIE -O -S foo.c $ cat foo.s # edited for brevity foo: # 25 bytes; about 15 cycles (incl. 3*3 cycles data cache fetch latency) call __x86.get_pc_thunk.cx addl $_GLOBAL_OFFSET_TABLE_, %ecx movl 4(%esp), %eax movl a@GOT(%ecx), %edx movl %eax, (%edx,%eax,4) ret
Yes, but... Am I right in thinking that a page containing the above can be shared, ...
Yes. '_GLOBAL_OFFSET_TABLE_' and 'a@GOT' both are constants whose value is established by the static linker /bin/ld and unchanged for every subsequent execve(). The final relocation of _GLOBAL_OFFSET_TABLE_ is performed during execution by the 'addl' using the execution-time base address returned by __x86.get_pc_thunk.cx. The final relocation for the address of "a[]" is performed at the start of execution by ld-linux changing the value contained in the GOT.
$ gcc -m32 -O -S foo.c $ cat foo.s # edited for brevity foo: # 12 bytes; about 6 cycles (incl. 1*3 cycles data cache fetch latency) movl 4(%esp), %eax movl %eax, a(,%eax,4) ret $
... but a page containing this cannot because it must be relocated prior to execution?
For a main program in normal usage where 'a' must be defined in the target of execve [else static linking fails], then that page _can_ be shared, and is shared. The relocation occurs at static link time. If 'a' remains undefined at the end of static linking, or if 'a' is known to reside in some shared library, then yes, the address must be relocated at the time of execution, and therefore the page cannot be shared.
For a shared library, that code is not even -fPIC, so it won't work on many platforms, although i686 allows it.