From d47d9a50f2568927af51e21b2f2120409db1ab44 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 22 Sep 2015 22:48:21 +0000 Subject: fix dlsym lookup of function symbols on fdpic previously these resolved to the code address rather than the address of the function descriptor. the conditions for accepting or rejecting symbols are quite inconsistent between the different points in the dynamic linker code where such decisions are made. this commit attempts to be at least as correct as anything already there, but does not improve consistency. it has been tested to correctly avoid symbols that are merely references to functions defined in other modules, at least in simple usage, but at some point all symbol lookup logic should be reviewed and refactored/unified. --- src/ldso/dynlink.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index f144aa59..0c3b36ce 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1757,6 +1757,8 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra) if (!def.sym) goto failed; if ((def.sym->st_info&0xf) == STT_TLS) return __tls_get_addr((size_t []){def.dso->tls_id, def.sym->st_value}); + if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC) + return def.dso->funcdescs + (def.sym - def.dso->syms); return laddr(def.dso, def.sym->st_value); } if (invalid_dso_handle(p)) @@ -1770,6 +1772,8 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra) } if (sym && (sym->st_info&0xf) == STT_TLS) return __tls_get_addr((size_t []){p->tls_id, sym->st_value}); + if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC) + return p->funcdescs + (sym - p->syms); if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) return laddr(p, sym->st_value); if (p->deps) for (i=0; p->deps[i]; i++) { @@ -1782,6 +1786,8 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra) } if (sym && (sym->st_info&0xf) == STT_TLS) return __tls_get_addr((size_t []){p->deps[i]->tls_id, sym->st_value}); + if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC) + return p->deps[i]->funcdescs + (sym - p->deps[i]->syms); if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) return laddr(p->deps[i], sym->st_value); } -- cgit v1.2.1