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:
parent
b0641d4a44
commit
d9ad62343c
3 changed files with 33 additions and 32 deletions
|
@ -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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue