diff options
author | Rich Felker <dalias@aerifal.cx> | 2013-07-20 18:26:17 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2013-07-20 18:26:17 -0400 |
commit | e69ae844dcc978f68761e4bc44fc5543717b9684 (patch) | |
tree | 2fcdc230795ede5df7e96568b75de04a8138508c /src/ldso | |
parent | ce8a99578254242a89adbde1cbbf0f34daeec79b (diff) | |
download | musl-e69ae844dcc978f68761e4bc44fc5543717b9684.tar.gz musl-e69ae844dcc978f68761e4bc44fc5543717b9684.tar.xz musl-e69ae844dcc978f68761e4bc44fc5543717b9684.zip |
add support for init_array/fini_array ctors/dtors to dynamic linker
Diffstat (limited to 'src/ldso')
-rw-r--r-- | src/ldso/dynlink.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 1d5e2977..dbf404ef 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -696,7 +696,13 @@ static void do_fini() for (p=fini_head; p; p=p->fini_next) { if (!p->constructed) continue; decode_vec(p->dynv, dyn, DYN_CNT); - ((void (*)(void))(p->base + dyn[DT_FINI]))(); + if (dyn[0] & (1<<DT_FINI_ARRAY)) { + size_t n = dyn[DT_FINI_ARRAYSZ]/sizeof(size_t); + size_t *fn = (void *)(p->base + dyn[DT_FINI_ARRAY]); + while (n--) ((void (*)(void))*fn++)(); + } + if (dyn[0] & (1<<DT_FINI)) + ((void (*)(void))(p->base + dyn[DT_FINI]))(); } } @@ -712,12 +718,17 @@ static void do_init_fini(struct dso *p) if (p->constructed) continue; p->constructed = 1; decode_vec(p->dynv, dyn, DYN_CNT); - if (dyn[0] & (1<<DT_FINI)) { + if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) { p->fini_next = fini_head; fini_head = p; } if (dyn[0] & (1<<DT_INIT)) ((void (*)(void))(p->base + dyn[DT_INIT]))(); + if (dyn[0] & (1<<DT_INIT_ARRAY)) { + size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t); + size_t *fn = (void *)(p->base + dyn[DT_INIT_ARRAY]); + while (n--) ((void (*)(void))*fn++)(); + } if (!need_locking && libc.threads_minus_1) { need_locking = 1; pthread_mutex_lock(&init_fini_lock); |