am 83362689: merge from open-source master

Merge commit '83362689f5b1f6393d376d242fe29541b63ead2d'

* commit '83362689f5b1f6393d376d242fe29541b63ead2d':
  added and modified linker to support SuperH architecture
  Add the BSD sys_signame array.
  added and modified bionic code to support SuperH architecture
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 1ada37e..67cb5fe 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -185,6 +185,14 @@
 extern pid_t tcgetpgrp(int fd);
 extern int   tcsetpgrp(int fd, pid_t _pid);
 
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+
 __END_DECLS
 
 #endif /* _UNISTD_H_ */
diff --git a/linker/linker.c b/linker/linker.c
index 9779290..1c2a28c 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008, 2009 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,6 @@
  *
  * open issues / todo:
  *
- * - should we do anything special for STB_WEAK symbols?
  * - are we doing everything we should for ARM_COPY relocations?
  * - cleaner error reporting
  * - after linking, set as much stuff as possible to READONLY
@@ -258,7 +257,7 @@
 
     if(strlen(name) >= SOINFO_NAME_LEN) {
         DL_ERR("%5d library name %s too long", pid, name);
-        return 0;
+        return NULL;
     }
 
     /* The freelist is populated when we call free_info(), which in turn is
@@ -406,20 +405,20 @@
         s = symtab + n;
         if(strcmp(strtab + s->st_name, name)) continue;
 
-            /* only concern ourselves with global symbols */
+            /* only concern ourselves with global and weak symbol definitions */
         switch(ELF32_ST_BIND(s->st_info)){
         case STB_GLOBAL:
+        case STB_WEAK:
                 /* no section == undefined */
             if(s->st_shndx == 0) continue;
 
-        case STB_WEAK:
             TRACE_TYPE(LOOKUP, "%5d FOUND %s in %s (%08x) %d\n", pid,
                        name, si->name, s->st_value, s->st_size);
             return s;
         }
     }
 
-    return 0;
+    return NULL;
 }
 
 static unsigned elfhash(const char *_name)
@@ -437,25 +436,23 @@
 }
 
 static Elf32_Sym *
-_do_lookup_in_so(soinfo *si, const char *name, unsigned *elf_hash)
-{
-    if (*elf_hash == 0)
-        *elf_hash = elfhash(name);
-    return _elf_lookup (si, *elf_hash, name);
-}
-
-static Elf32_Sym *
 _do_lookup(soinfo *si, const char *name, unsigned *base)
 {
-    unsigned elf_hash = 0;
+    unsigned elf_hash = elfhash(name);
     Elf32_Sym *s;
     unsigned *d;
     soinfo *lsi = si;
 
     /* Look for symbols in the local scope first (the object who is
      * searching). This happens with C++ templates on i386 for some
-     * reason. */
-    s = _do_lookup_in_so(si, name, &elf_hash);
+     * reason.
+     *
+     * Notes on weak symbols:
+     * The ELF specs are ambigious about treatment of weak definitions in
+     * 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;
 
@@ -465,12 +462,12 @@
             if (!validate_soinfo(lsi)) {
                 DL_ERR("%5d bad DT_NEEDED pointer in %s",
                        pid, si->name);
-                return 0;
+                return NULL;
             }
 
             DEBUG("%5d %s: looking up %s in %s\n",
                   pid, si->name, name, lsi->name);
-            s = _do_lookup_in_so(lsi, name, &elf_hash);
+            s = _elf_lookup(lsi, elf_hash, name);
             if(s != NULL)
                 goto done;
         }
@@ -485,7 +482,7 @@
         lsi = somain;
         DEBUG("%5d %s: looking up %s in executable %s\n",
               pid, si->name, name, lsi->name);
-        s = _do_lookup_in_so(lsi, name, &elf_hash);
+        s = _elf_lookup(lsi, elf_hash, name);
     }
 #endif
 
@@ -498,7 +495,7 @@
         return s;
     }
 
-    return 0;
+    return NULL;
 }
 
 /* This is used by dl_sym().  It performs symbol lookup only within the
@@ -506,15 +503,14 @@
  */
 Elf32_Sym *lookup_in_library(soinfo *si, const char *name)
 {
-    unsigned unused = 0;
-    return _do_lookup_in_so(si, name, &unused);
+    return _elf_lookup(si, elfhash(name), name);
 }
 
 /* This is used by dl_sym().  It performs a global symbol lookup.
  */
 Elf32_Sym *lookup(const char *name, soinfo **found)
 {
-    unsigned elf_hash = 0;
+    unsigned elf_hash = elfhash(name);
     Elf32_Sym *s = NULL;
     soinfo *si;
 
@@ -522,7 +518,7 @@
     {
         if(si->flags & FLAG_ERROR)
             continue;
-        s = _do_lookup_in_so(si, name, &elf_hash);
+        s = _elf_lookup(si, elf_hash, name);
         if (s != NULL) {
             *found = si;
             break;
@@ -535,7 +531,7 @@
         return s;
     }
 
-    return 0;
+    return NULL;
 }
 
 #if 0
@@ -1241,10 +1237,64 @@
         if(sym != 0) {
             sym_name = (char *)(strtab + symtab[sym].st_name);
             s = _do_lookup(si, sym_name, &base);
-            if(s == 0) {
-                DL_ERR("%5d cannot locate '%s'...", pid, sym_name);
-                return -1;
-            }
+            if(s == NULL) {
+                /* We only allow an undefined symbol if this is a weak
+                   reference..   */
+                s = &symtab[sym];
+                if (ELF32_ST_BIND(s->st_info) != STB_WEAK) {
+                    DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name);
+                    return -1;
+                }
+
+                /* IHI0044C AAELF 4.5.1.1:
+
+                   Libraries are not searched to resolve weak references.
+                   It is not an error for a weak reference to remain
+                   unsatisfied.
+
+                   During linking, the value of an undefined weak reference is:
+                   - Zero if the relocation type is absolute
+                   - The address of the place if the relocation is pc-relative
+                   - The address of nominial base address if the relocation
+                     type is base-relative.
+                  */
+
+                switch (type) {
+#if defined(ANDROID_ARM_LINKER)
+                case R_ARM_JUMP_SLOT:
+                case R_ARM_GLOB_DAT:
+                case R_ARM_ABS32:
+                case R_ARM_RELATIVE:    /* Don't care. */
+                case R_ARM_NONE:        /* Don't care. */
+#elif defined(ANDROID_X86_LINKER)
+                case R_386_JUMP_SLOT:
+                case R_386_GLOB_DAT:
+                case R_386_32:
+                case R_386_RELATIVE:    /* Dont' care. */
+#endif /* ANDROID_*_LINKER */
+                    /* sym_addr was initialized to be zero above or relocation
+                       code below does not care about value of sym_addr.
+                       No need to do anything.  */
+                    break;
+
+#if defined(ANDROID_X86_LINKER)
+                case R_386_PC32:
+                    sym_addr = reloc;
+                    break;
+#endif /* ANDROID_X86_LINKER */
+
+#if defined(ANDROID_ARM_LINKER)
+                case R_ARM_COPY:
+                    /* Fall through.  Can't really copy if weak symbol is
+                       not found in run-time.  */
+#endif /* ANDROID_ARM_LINKER */
+                default:
+                    DL_ERR("%5d unknown weak reloc type %d @ %p (%d)\n",
+                                 pid, type, rel, (int) (rel - start));
+                    return -1;
+                }
+            } else {
+                /* We got a definition.  */
 #if 0
             if((base == 0) && (si->base != 0)){
                     /* linking from libraries to main image is bad */
@@ -1253,20 +1303,11 @@
                 return -1;
             }
 #endif
-            // st_shndx==SHN_UNDEF means an undefined symbol.
-            // st_value should be 0 then, except that the low bit of st_value is
-            // used to indicate whether the symbol points to an ARM or thumb function,
-            // and should be ignored in the following check.
-            if ((s->st_shndx == SHN_UNDEF) && ((s->st_value & ~1) != 0)) {
-                DL_ERR("%5d In '%s', symbol=%s shndx=%d && value=0x%08x. We do not "
-                      "handle this yet", pid, si->name, sym_name, s->st_shndx,
-                      s->st_value);
-                return -1;
-            }
-            sym_addr = (unsigned)(s->st_value + base);
+                sym_addr = (unsigned)(s->st_value + base);
+	    }
             COUNT_RELOC(RELOC_SYMBOL);
         } else {
-            s = 0;
+            s = NULL;
         }
 
 /* TODO: This is ugly. Split up the relocations by arch into
@@ -1909,7 +1950,7 @@
     return 0;
 
 fail:
-    ERROR("failed to link %s\n", si->name);
+    DL_ERR("failed to link %s\n", si->name);
     si->flags |= FLAG_ERROR;
     return -1;
 }