summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-10-06 01:36:11 -0400
committerRich Felker <dalias@aerifal.cx>2012-10-06 01:36:11 -0400
commitbd17431a2cba8aafd1e4f95f9b70e5800ee51d24 (patch)
tree7dbe1f313dbdcb2275452b921b02ec58085be94a
parentcf3fd3d002c728ed0ef5d3aef856ff3e1d418da0 (diff)
downloadmusl-bd17431a2cba8aafd1e4f95f9b70e5800ee51d24.tar.gz
fix symbol acceptance/rejection rules for TLS
symbol value of 0 is not "undefined" for TLS; it's the address of the first symbol in the TLS segment. however, non-definition TLS references also have values of 0, so check the section. hopefully the new logic is more clear, too.
-rw-r--r--src/ldso/dynlink.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 21c3ebad..db7770b9 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -209,14 +209,20 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
if (!h) h = sysv_hash(s);
sym = sysv_lookup(s, h, dso);
}
- if (sym && (!need_def || sym->st_shndx) && sym->st_value
- && (1<<(sym->st_info&0xf) & OK_TYPES)
- && (1<<(sym->st_info>>4) & OK_BINDS)) {
- if (def.sym && sym->st_info>>4 == STB_WEAK) continue;
- def.sym = sym;
- def.dso = dso;
- if (sym->st_info>>4 == STB_GLOBAL) break;
- }
+ if (!sym) continue;
+ if (!sym->st_shndx)
+ if (need_def || (sym->st_info&0xf) == STT_TLS)
+ continue;
+ if (!sym->st_value)
+ if ((sym->st_info&0xf) != STT_TLS)
+ continue;
+ if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
+ if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;
+
+ if (def.sym && sym->st_info>>4 == STB_WEAK) continue;
+ def.sym = sym;
+ def.dso = dso;
+ if (sym->st_info>>4 == STB_GLOBAL) break;
}
return def;
}