summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2014-09-30 16:40:25 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-09-30 16:40:27 +0000
commit9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6 (patch)
treec40ea1d3b72c1476745aa3a8b7506857eee24b29
parentb104be321f2538a6e0bbd566bc958537d1f65cef (diff)
parent96bc37f2e1093416a432135265fd7a4db6c3df17 (diff)
downloadbionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.zip
bionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.tar.gz
bionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.tar.bz2
Merge "Return has_DT_SYMBOLIC flag."
-rw-r--r--linker/linker.cpp68
-rw-r--r--linker/linker.h2
2 files changed, 47 insertions, 23 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 09ffa23..5b39668 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -485,14 +485,34 @@ static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi) {
unsigned elf_hash = elfhash(name);
ElfW(Sym)* s = nullptr;
- if (somain != nullptr) {
- DEBUG("%s: looking up %s in executable %s",
- si->name, name, somain->name);
-
- // 1. Look for it in the main executable
- s = soinfo_elf_lookup(somain, elf_hash, name);
+ /* "This element's presence in a shared object library alters the dynamic linker's
+ * symbol resolution algorithm for references within the library. Instead of starting
+ * a symbol search with the executable file, the dynamic linker starts from the shared
+ * object itself. If the shared object fails to supply the referenced symbol, the
+ * dynamic linker then searches the executable file and other shared objects as usual."
+ *
+ * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
+ *
+ * Note that this is unlikely since static linker avoids generating
+ * relocations for -Bsymbolic linked dynamic executables.
+ */
+ if (si->has_DT_SYMBOLIC) {
+ DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si->name, name);
+ s = soinfo_elf_lookup(si, elf_hash, name);
if (s != nullptr) {
- *lsi = somain;
+ *lsi = si;
+ }
+ }
+
+ if (s == nullptr && somain != nullptr) {
+ // 1. Look for it in the main executable unless we already did.
+ if (si != somain || !si->has_DT_SYMBOLIC) {
+ DEBUG("%s: looking up %s in executable %s",
+ si->name, name, somain->name);
+ s = soinfo_elf_lookup(somain, elf_hash, name);
+ if (s != nullptr) {
+ *lsi = somain;
+ }
}
// 2. Look for it in the ld_preloads
@@ -505,22 +525,23 @@ static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi) {
}
}
}
+ }
- /* Look for symbols in the local scope (the object who is
- * searching). This happens with C++ templates on x86 for some
- * reason.
- *
- * Notes on weak symbols:
- * The ELF specs are ambiguous 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. */
+ /* Look for symbols in the local scope (the object who is
+ * searching). This happens with C++ templates on x86 for some
+ * reason.
+ *
+ * Notes on weak symbols:
+ * The ELF specs are ambiguous 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. */
- if (s == nullptr) {
- s = soinfo_elf_lookup(si, elf_hash, name);
- if (s != nullptr) {
- *lsi = si;
- }
+ if (s == nullptr && !si->has_DT_SYMBOLIC) {
+ DEBUG("%s: looking up %s in local scope", si->name, name);
+ s = soinfo_elf_lookup(si, elf_hash, name);
+ if (s != nullptr) {
+ *lsi = si;
}
}
@@ -2009,7 +2030,7 @@ bool soinfo::PrelinkImage() {
break;
#endif
case DT_SYMBOLIC:
- // ignored
+ has_DT_SYMBOLIC = true;
break;
case DT_NEEDED:
++needed_count;
@@ -2023,6 +2044,9 @@ bool soinfo::PrelinkImage() {
has_text_relocations = true;
#endif
}
+ if (d->d_un.d_val & DF_SYMBOLIC) {
+ has_DT_SYMBOLIC = true;
+ }
break;
#if defined(__mips__)
case DT_STRSZ:
diff --git a/linker/linker.h b/linker/linker.h
index 68b5594..2896933 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -197,7 +197,7 @@ struct soinfo {
#if !defined(__LP64__)
bool has_text_relocations;
#endif
- bool unused4; // DO NOT USE, maintained for compatibility
+ bool has_DT_SYMBOLIC;
soinfo(const char* name, const struct stat* file_stat, int rtld_flags);