Revert "Make the linker relocatable."
This reverts commit 994e9a5ed1c4e9f23a8bed79caea684eaa270027.
Broke x86 build.
diff --git a/linker/Android.mk b/linker/Android.mk
index 717e9c4..60f291c 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -10,9 +10,27 @@
dlfcn.c \
debugger.c
-LOCAL_LDFLAGS := -shared
+ifeq ($(TARGET_ARCH),sh)
+# SH-4A series virtual address range from 0x00000000 to 0x7FFFFFFF.
+LINKER_TEXT_BASE := 0x70000100
+else
+# This is aligned to 4K page boundary so that both GNU ld and gold work. Gold
+# actually produces a correct binary with starting address 0xB0000100 but the
+# extra objcopy step to rename symbols causes the resulting binary to be misaligned
+# and unloadable. Increasing the alignment adds an extra 3840 bytes in padding
+# but switching to gold saves about 1M of space.
+LINKER_TEXT_BASE := 0xB0001000
+endif
-LOCAL_CFLAGS += -fno-stack-protector
+# The maximum size set aside for the linker, from
+# LINKER_TEXT_BASE rounded down to a megabyte.
+LINKER_AREA_SIZE := 0x01000000
+
+LOCAL_LDFLAGS := -Wl,-Ttext,$(LINKER_TEXT_BASE)
+
+LOCAL_CFLAGS += -DPRELINK
+LOCAL_CFLAGS += -DLINKER_TEXT_BASE=$(LINKER_TEXT_BASE)
+LOCAL_CFLAGS += -DLINKER_AREA_SIZE=$(LINKER_AREA_SIZE)
# Set LINKER_DEBUG to either 1 or 0
#
diff --git a/linker/linker.c b/linker/linker.c
index cf66211..504fb93 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -313,6 +313,15 @@
freelist = si;
}
+#ifndef LINKER_TEXT_BASE
+#error "linker's makefile must define LINKER_TEXT_BASE"
+#endif
+#ifndef LINKER_AREA_SIZE
+#error "linker's makefile must define LINKER_AREA_SIZE"
+#endif
+#define LINKER_BASE ((LINKER_TEXT_BASE) & 0xfff00000)
+#define LINKER_TOP (LINKER_BASE + (LINKER_AREA_SIZE))
+
const char *addr_to_name(unsigned addr)
{
soinfo *si;
@@ -323,6 +332,10 @@
}
}
+ if((addr >= LINKER_BASE) && (addr < LINKER_TOP)){
+ return "linker";
+ }
+
return "";
}
@@ -341,10 +354,12 @@
soinfo *si;
unsigned addr = (unsigned)pc;
- for (si = solist; si != 0; si = si->next){
- if ((addr >= si->base) && (addr < (si->base + si->size))) {
- *pcount = si->ARM_exidx_count;
- return (_Unwind_Ptr)(si->base + (unsigned long)si->ARM_exidx);
+ if ((addr < LINKER_BASE) || (addr >= LINKER_TOP)) {
+ for (si = solist; si != 0; si = si->next){
+ if ((addr >= si->base) && (addr < (si->base + si->size))) {
+ *pcount = si->ARM_exidx_count;
+ return (_Unwind_Ptr)(si->base + (unsigned long)si->ARM_exidx);
+ }
}
}
*pcount = 0;
@@ -405,33 +420,6 @@
return NULL;
}
-/*
- * Essentially the same method as _elf_lookup() above, but only
- * searches for LOCAL symbols
- */
-static Elf32_Sym *_elf_lookup_local(soinfo *si, unsigned hash, const char *name)
-{
- Elf32_Sym *symtab = si->symtab;
- const char *strtab = si->strtab;
- unsigned n = hash % si->nbucket;;
-
- TRACE_TYPE(LOOKUP, "%5d LOCAL SEARCH %s in %s@0x%08x %08x %d\n", pid,
- name, si->name, si->base, hash, hash % si->nbucket);
- for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){
- Elf32_Sym *s = symtab + n;
- if (strcmp(strtab + s->st_name, name)) continue;
- if (ELF32_ST_BIND(s->st_info) != STB_LOCAL) continue;
- /* no section == undefined */
- if(s->st_shndx == 0) continue;
-
- TRACE_TYPE(LOOKUP, "%5d FOUND LOCAL %s in %s (%08x) %d\n", pid,
- name, si->name, s->st_value, s->st_size);
- return s;
- }
-
- return NULL;
-}
-
static unsigned elfhash(const char *_name)
{
const unsigned char *name = (const unsigned char *) _name;
@@ -455,17 +443,7 @@
soinfo *lsi = si;
int i;
- /* If we are trying to find a symbol for the linker itself, look
- * for LOCAL symbols first. Avoid using LOCAL symbols for other
- * shared libraries until we have a better understanding of what
- * might break by doing so. */
- if (si->flags & FLAG_LINKER) {
- s = _elf_lookup_local(si, elf_hash, name);
- if(s != NULL)
- goto done;
- }
-
- /* Look for symbols in the local scope (the object who is
+ /* Look for symbols in the local scope first (the object who is
* searching). This happens with C++ templates on i386 for some
* reason.
*
@@ -474,7 +452,6 @@
* dynamic linking. Some systems return the first definition found
* and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity. */
-
s = _elf_lookup(si, elf_hash, name);
if(s != NULL)
goto done;
@@ -2107,12 +2084,7 @@
static void * __tls_area[ANDROID_TLS_SLOTS];
-/*
- * This code is called after the linker has linked itself and
- * fixed it's own GOT. It is safe to make references to externs
- * and other non-local data at this point.
- */
-static unsigned __linker_init_post_relocation(unsigned **elfdata)
+unsigned __linker_init(unsigned **elfdata)
{
static soinfo linker_soinfo;
@@ -2289,80 +2261,3 @@
si->entry);
return si->entry;
}
-
-/*
- * Find the value of AT_BASE passed to us by the kernel. This is the load
- * location of the linker.
- */
-static unsigned find_linker_base(unsigned **elfdata) {
- int argc = (int) *elfdata;
- char **argv = (char**) (elfdata + 1);
- unsigned *vecs = (unsigned*) (argv + argc + 1);
- while (vecs[0] != 0) {
- vecs++;
- }
-
- /* The end of the environment block is marked by two NULL pointers */
- vecs++;
-
- while(vecs[0]) {
- if (vecs[0] == AT_BASE) {
- return vecs[1];
- }
- vecs += 2;
- }
-
- return 0; // should never happen
-}
-
-/*
- * This is the entry point for the linker, called from begin.S. This
- * method is responsible for fixing the linker's own relocations, and
- * then calling __linker_init_post_relocation().
- *
- * Because this method is called before the linker has fixed it's own
- * relocations, any attempt to reference an extern variable, extern
- * function, or other GOT reference will generate a segfault.
- */
-unsigned __linker_init(unsigned **elfdata) {
- unsigned linker_addr = find_linker_base(elfdata);
- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr;
- Elf32_Phdr *phdr =
- (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff);
-
- soinfo linker_so;
- memset(&linker_so, 0, sizeof(soinfo));
-
- linker_so.base = linker_addr;
- linker_so.dynamic = (unsigned *) -1;
- linker_so.phdr = phdr;
- linker_so.phnum = elf_hdr->e_phnum;
- linker_so.flags |= FLAG_LINKER;
-
- /*
- * Find the DYNAMIC section of the linker itself, so we can
- * fix our own relocations.
- */
- int i;
- for (i = 0; i < linker_so.phnum; i++) {
- if (phdr[i].p_type == PT_DYNAMIC) {
- linker_so.dynamic = (unsigned *)(linker_so.base + phdr[i].p_vaddr);
- break;
- }
- }
-
- if ((linker_so.dynamic != (unsigned char*) -1)
- && link_image(&linker_so, 0)) {
- // It would be nice to print an error message, but if the linker
- // can't link itself, there's no guarantee that we'll be able to
- // call write() (because it involves a GOT reference).
- //
- // This situation should never occur unless the linker itself
- // is corrupt.
- exit(-1);
- }
-
- // We have successfully fixed our own relocations. It's safe to run
- // the main part of the linker now.
- return __linker_init_post_relocation(elfdata);
-}
diff --git a/linker/linker.h b/linker/linker.h
index aa1e5e7..7b1ba51 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -83,7 +83,6 @@
#define FLAG_LINKED 0x00000001
#define FLAG_ERROR 0x00000002
#define FLAG_EXE 0x00000004 // The main executable
-#define FLAG_LINKER 0x00000010 // The linker itself
#define SOINFO_NAME_LEN 128