Merge "We should use load_bias. This patch fixes MIPS NDK device exception test failures."
diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c
index a73bb71..ba7f008 100644
--- a/libc/bionic/libc_init_static.c
+++ b/libc/bionic/libc_init_static.c
@@ -48,6 +48,14 @@
#include <bionic_tls.h>
#include <errno.h>
+#include <sys/mman.h>
+
+// Returns the address of the page containing address 'x'.
+#define PAGE_START(x) ((x) & PAGE_MASK)
+
+// Returns the address of the next page after address 'x', unless 'x' is
+// itself at the start of a page.
+#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
static void call_array(void(**list)())
{
@@ -57,6 +65,42 @@
}
}
+/*
+ * Find the value of the AT_* variable passed to us by the kernel.
+ */
+static unsigned find_aux(unsigned *vecs, unsigned type) {
+ while (vecs[0]) {
+ if (vecs[0] == type) {
+ return vecs[1];
+ }
+ vecs += 2;
+ }
+
+ return 0; // should never happen
+}
+
+static void apply_gnu_relro(unsigned *vecs) {
+ Elf32_Phdr *phdr_start;
+ unsigned phdr_ct;
+ Elf32_Phdr *phdr;
+
+ phdr_start = (Elf32_Phdr *) find_aux(vecs, AT_PHDR);
+ phdr_ct = find_aux(vecs, AT_PHNUM);
+
+ for (phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO)
+ continue;
+
+ Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr);
+ Elf32_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz);
+
+ // Check return value here? What do we do if we fail?
+ mprotect((void *) seg_page_start,
+ seg_page_end - seg_page_start,
+ PROT_READ);
+ }
+}
+
__noreturn void __libc_init(uintptr_t *elfdata,
void (*onexit)(void),
int (*slingshot)(int, char**, char**),
@@ -64,6 +108,7 @@
{
int argc;
char **argv, **envp;
+ unsigned *vecs;
__libc_init_tls(NULL);
@@ -84,6 +129,14 @@
argv = (char**)(elfdata + 1);
envp = argv + argc + 1;
+ // The auxiliary vector is at the end of the environment block
+ vecs = (unsigned *) envp;
+ while (vecs[0] != 0) {
+ vecs++;
+ }
+ /* The end of the environment block is marked by two NULL pointers */
+ vecs++;
+
/* The executable may have its own destructors listed in its .fini_array
* so we need to ensure that these are called when the program exits
* normally.
@@ -91,5 +144,6 @@
if (structors->fini_array)
__cxa_atexit(__libc_fini,structors->fini_array,NULL);
+ apply_gnu_relro(vecs);
exit(slingshot(argc, argv, envp));
}
diff --git a/linker/linker_format.cpp b/linker/linker_format.cpp
index 60b759b..65c6264 100644
--- a/linker/linker_format.cpp
+++ b/linker/linker_format.cpp
@@ -26,6 +26,10 @@
* SUCH DAMAGE.
*/
+// Temporarily disable _FORTIFY_SOURCE to get this code to
+// compile under GCC 4.7
+#undef _FORTIFY_SOURCE
+
#include <assert.h>
#include <stdarg.h>
#include <string.h>