diff options
author | Dmitriy Ivanov <dimitry@google.com> | 2014-09-30 16:40:25 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-09-30 16:40:27 +0000 |
commit | 9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6 (patch) | |
tree | c40ea1d3b72c1476745aa3a8b7506857eee24b29 | |
parent | b104be321f2538a6e0bbd566bc958537d1f65cef (diff) | |
parent | 96bc37f2e1093416a432135265fd7a4db6c3df17 (diff) | |
download | bionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.zip bionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.tar.gz bionic-9997daa0ff8f630bee5d3b8eb0ab15a0ba1e5cf6.tar.bz2 |
Merge "Return has_DT_SYMBOLIC flag."
-rw-r--r-- | linker/linker.cpp | 68 | ||||
-rw-r--r-- | linker/linker.h | 2 |
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); |