Add linker support for PIE

Modify the dynamic linker so that executables can be loaded
at locations other than 0x00000000.

Modify crtbegin* so that non-PIC compilant "thumb interwork
veneers" are not created by the linker.

Bug: 5323301
Change-Id: Iece0272e2b708c79034f302c20160e1fe9029588
This commit is contained in:
Nick Kralevich 2011-10-20 14:57:56 -07:00
parent b0641d4a44
commit d9ad62343c
3 changed files with 33 additions and 32 deletions

View file

@ -43,21 +43,17 @@
# - address of an "onexit" function, not used on any # - address of an "onexit" function, not used on any
# platform supported by Bionic # platform supported by Bionic
# #
# - address of the "main" function of the program. We # - address of the "main" function of the program.
# can't hard-code it in the adr pseudo instruction
# so we use a tiny trampoline that will get relocated
# by the dynamic linker before this code runs
# #
# - address of the constructor list # - address of the constructor list
# #
_start: _start:
mov r0, sp mov r0, sp
mov r1, #0 mov r1, #0
adr r2, 0f ldr r2, =main
adr r3, 1f adr r3, 1f
b __libc_init ldr r4, =__libc_init
bx r4
0: b main
1: .long __PREINIT_ARRAY__ 1: .long __PREINIT_ARRAY__
.long __INIT_ARRAY__ .long __INIT_ARRAY__

View file

@ -43,21 +43,17 @@
# - address of an "onexit" function, not used on any # - address of an "onexit" function, not used on any
# platform supported by Bionic # platform supported by Bionic
# #
# - address of the "main" function of the program. We # - address of the "main" function of the program.
# can't hard-code it in the adr pseudo instruction
# so we use a tiny trampoline that will get relocated
# by the dynamic linker before this code runs
# #
# - address of the constructor list # - address of the constructor list
# #
_start: _start:
mov r0, sp mov r0, sp
mov r1, #0 mov r1, #0
adr r2, 0f ldr r2, =main
adr r3, 1f adr r3, 1f
b __libc_init ldr r4, =__libc_init
bx r4
0: b main
1: .long __PREINIT_ARRAY__ 1: .long __PREINIT_ARRAY__
.long __INIT_ARRAY__ .long __INIT_ARRAY__

View file

@ -1741,16 +1741,17 @@ static int link_image(soinfo *si, unsigned wr_offset)
if (phdr->p_type == PT_LOAD) { if (phdr->p_type == PT_LOAD) {
/* For the executable, we use the si->size field only in /* For the executable, we use the si->size field only in
dl_unwind_find_exidx(), so the meaning of si->size dl_unwind_find_exidx(), so the meaning of si->size
is not the size of the executable; it is the last is not the size of the executable; it is the distance
virtual address of the loadable part of the executable; between the load location of the executable and the last
since si->base == 0 for an executable, we use the address of the loadable part of the executable.
range [0, si->size) to determine whether a PC value We use the range [si->base, si->base + si->size) to
falls within the executable section. Of course, if determine whether a PC value falls within the executable
a value is below phdr->p_vaddr, it's not in the section. Of course, if a value is between si->base and
executable section, but a) we shouldn't be asking for (si->base + phdr->p_vaddr), it's not in the executable
such a value anyway, and b) if we have to provide section, but a) we shouldn't be asking for such a value
an EXIDX for such a value, then the executable's anyway, and b) if we have to provide an EXIDX for such a
EXIDX is probably the better choice. value, then the executable's EXIDX is probably the better
choice.
*/ */
DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid); DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid);
if (phdr->p_vaddr + phdr->p_memsz > si->size) if (phdr->p_vaddr + phdr->p_memsz > si->size)
@ -1760,12 +1761,20 @@ static int link_image(soinfo *si, unsigned wr_offset)
if (!(phdr->p_flags & PF_W)) { if (!(phdr->p_flags & PF_W)) {
unsigned _end; unsigned _end;
if (phdr->p_vaddr < si->wrprotect_start) if (si->base + phdr->p_vaddr < si->wrprotect_start)
si->wrprotect_start = phdr->p_vaddr; si->wrprotect_start = si->base + phdr->p_vaddr;
_end = (((phdr->p_vaddr + phdr->p_memsz + PAGE_SIZE - 1) & _end = (((si->base + phdr->p_vaddr + phdr->p_memsz + PAGE_SIZE - 1) &
(~PAGE_MASK))); (~PAGE_MASK)));
if (_end > si->wrprotect_end) if (_end > si->wrprotect_end)
si->wrprotect_end = _end; si->wrprotect_end = _end;
/* Make the section writable just in case we'll have to
* write to it during relocation (i.e. text segment).
* However, we will remember what range of addresses
* should be write protected.
*/
mprotect((void *) (si->base + phdr->p_vaddr),
phdr->p_memsz,
PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE);
} }
} else if (phdr->p_type == PT_DYNAMIC) { } else if (phdr->p_type == PT_DYNAMIC) {
if (si->dynamic != (unsigned *)-1) { if (si->dynamic != (unsigned *)-1) {
@ -2183,7 +2192,7 @@ unsigned __linker_init(unsigned **elfdata)
vecs += 2; vecs += 2;
} }
si->base = 0; si->base = (Elf32_Addr) si->phdr - si->phdr->p_vaddr;
si->dynamic = (unsigned *)-1; si->dynamic = (unsigned *)-1;
si->wrprotect_start = 0xffffffff; si->wrprotect_start = 0xffffffff;
si->wrprotect_end = 0; si->wrprotect_end = 0;