Sym *syms;
uint32_t *hashtab;
uint32_t *ghashtab;
+ int16_t *versym;
char *strings;
unsigned char *map;
size_t map_len;
uint32_t *hashtab = dso->hashtab;
char *strings = dso->strings;
for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
- if (!strcmp(s, strings+syms[i].st_name))
+ if ((!dso->versym || dso->versym[i] >= 0)
+ && (!strcmp(s, strings+syms[i].st_name)))
return syms+i;
}
return 0;
static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso)
{
- Sym *sym;
- char *strings;
+ Sym *syms = dso->syms;
+ char *strings = dso->strings;
uint32_t *hashtab = dso->ghashtab;
uint32_t nbuckets = hashtab[0];
uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
uint32_t h2;
uint32_t *hashval;
- uint32_t n = buckets[h1 % nbuckets];
+ uint32_t i = buckets[h1 % nbuckets];
- if (!n) return 0;
+ if (!i) return 0;
- strings = dso->strings;
- sym = dso->syms + n;
- hashval = buckets + nbuckets + (n - hashtab[1]);
+ hashval = buckets + nbuckets + (i - hashtab[1]);
- for (h1 |= 1; ; sym++) {
+ for (h1 |= 1; ; i++) {
h2 = *hashval++;
- if ((h1 == (h2|1)) && !strcmp(s, strings + sym->st_name))
- return sym;
+ if ((!dso->versym || dso->versym[i] >= 0)
+ && (h1 == (h2|1)) && !strcmp(s, strings + syms[i].st_name))
+ return syms+i;
if (h2 & 1) break;
}
p->hashtab = (void *)(p->base + dyn[DT_HASH]);
if (search_vec(p->dynv, dyn, DT_GNU_HASH))
p->ghashtab = (void *)(p->base + *dyn);
+ if (search_vec(p->dynv, dyn, DT_VERSYM))
+ p->versym = (void *)(p->base + *dyn);
}
static struct dso *load_library(const char *name)
}
if (strlen(name) > NAME_MAX) return 0;
fd = -1;
- if (r_path) fd = path_open(name, r_path, buf, sizeof buf);
- if (fd < 0 && env_path) fd = path_open(name, env_path, buf, sizeof buf);
+ if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
+ if (fd < 0 && r_path) fd = path_open(name, r_path, buf, sizeof buf);
if (fd < 0) {
if (!sys_path) {
char *prefix = 0;
{
}
+void __reset_tls()
+{
+ pthread_t self = __pthread_self();
+ struct dso *p;
+ for (p=head; p; p=p->next) {
+ if (!p->tls_id || !self->dtv[p->tls_id]) continue;
+ memcpy(self->dtv[p->tls_id], p->tls_image, p->tls_len);
+ memset((char *)self->dtv[p->tls_id]+p->tls_len, 0,
+ p->tls_size - p->tls_len);
+ if (p->tls_id == (size_t)self->dtv[0]) break;
+ }
+}
+
void *__copy_tls(unsigned char *mem)
{
pthread_t td;