aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Chupin <pavel.v.chupin@intel.com>2012-10-31 13:55:51 +0400
committerPavel Chupin <pavel.v.chupin@intel.com>2012-11-02 18:34:22 +0400
commitc77c434149959e135ba21d1dd8a78a408fef2489 (patch)
tree416bcd464428bc39d772e636e2898eb46da07533
parent084be591923d3d509cea0a0f4b11b073e362d730 (diff)
downloadandroid_bionic-c77c434149959e135ba21d1dd8a78a408fef2489.tar.gz
android_bionic-c77c434149959e135ba21d1dd8a78a408fef2489.tar.bz2
android_bionic-c77c434149959e135ba21d1dd8a78a408fef2489.zip
Adjust symbol lookup for DT_SYMBOLIC case
According ELF spec re. DT_SYMBOLIC: 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. This change implements the last part. Change-Id: Iae95d53d455313a4306f11733941bcd3596ac85f Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
-rwxr-xr-x[-rw-r--r--]linker/linker.cpp76
1 files changed, 53 insertions, 23 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 9e4138e15..8bb989a4b 100644..100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -425,38 +425,68 @@ soinfo_do_lookup(soinfo *si, const char *name, soinfo **lsi,
Elf32_Sym *s = NULL;
int i;
- if (si != NULL) {
+ if (si != NULL && somain != NULL) {
/*
- * If this object was built with symbolic relocations disabled, the
- * first place to look to resolve external references is the main
- * executable.
+ * Local scope is executable scope. Just start looking into it right away
+ * for the shortcut.
*/
- if (!si->has_DT_SYMBOLIC) {
- DEBUG("%5d %s: looking up %s in executable %s\n",
- pid, si->name, name, somain->name);
- s = soinfo_elf_lookup(somain, elf_hash, name);
+ if (si == somain) {
+ s = soinfo_elf_lookup(si, elf_hash, name);
if (s != NULL) {
- *lsi = somain;
+ *lsi = si;
goto done;
}
- }
+ } else {
+ /* Order of symbol lookup is controlled by DT_SYMBOLIC flag */
- /* Look for symbols in the local scope (the object who is
- * searching). This happens with C++ templates on i386 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 this object was built with symbolic relocations disabled, the
+ * first place to look to resolve external references is the main
+ * executable.
+ */
- s = soinfo_elf_lookup(si, elf_hash, name);
- if (s != NULL) {
- *lsi = si;
- goto done;
+ if (!si->has_DT_SYMBOLIC) {
+ DEBUG("%5d %s: looking up %s in executable %s\n",
+ pid, si->name, name, somain->name);
+ s = soinfo_elf_lookup(somain, elf_hash, name);
+ if (s != NULL) {
+ *lsi = somain;
+ goto done;
+ }
+ }
+
+ /* Look for symbols in the local scope (the object who is
+ * searching). This happens with C++ templates on i386 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. */
+
+ s = soinfo_elf_lookup(si, elf_hash, name);
+ if (s != NULL) {
+ *lsi = si;
+ goto done;
+ }
+
+ /*
+ * If this object was built with -Bsymbolic and symbol is not found
+ * in the local scope, try to find the symbol in the main executable.
+ */
+
+ if (si->has_DT_SYMBOLIC) {
+ DEBUG("%5d %s: looking up %s in executable %s after local scope\n",
+ pid, si->name, name, somain->name);
+ s = soinfo_elf_lookup(somain, elf_hash, name);
+ if (s != NULL) {
+ *lsi = somain;
+ goto done;
+ }
+ }
}
}