* [PATCH 2/2] add preinit_array support @ 2015-11-29 15:33 Szabolcs Nagy 2015-11-29 16:59 ` Szabolcs Nagy 0 siblings, 1 reply; 4+ messages in thread From: Szabolcs Nagy @ 2015-11-29 15:33 UTC (permalink / raw) To: musl handle DT_PREINIT_ARRAY{SZ} in case of dynamic linking and __preinit_array_{start,end} in case of static linking. redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. --- src/env/__libc_start_main.c | 5 +++++ src/ldso/dynlink.c | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index f9c7ca5..d4cc0ef 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -12,6 +12,9 @@ static void dummy(void) {} weak_alias(dummy, _init); __attribute__((__weak__, __visibility__("hidden"))) +extern void (*const __preinit_array_start[])(void), (*const __preinit_array_end[])(void); + +__attribute__((__weak__, __visibility__("hidden"))) extern void (*const __init_array_start[])(void), (*const __init_array_end[])(void); static void dummy1(void *p) {} @@ -57,6 +60,8 @@ static void libc_start_init(void) { void (*const *f)(void); _init(); + for (f=__preinit_array_start; f<__preinit_array_end; f++) + (*f)(); for (f=__init_array_start; f<__init_array_end; f++) (*f)(); } diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 93e7d67..623818a 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -135,11 +135,14 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap; struct debug *_dl_debug_addr = &debug; __attribute__((__visibility__("hidden"))) -void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; +void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0, +(*const __preinit_array_start)(void)=0; __attribute__((__visibility__("hidden"))) -extern void (*const __init_array_end)(void), (*const __fini_array_end)(void); +extern void (*const __init_array_end)(void), (*const __fini_array_end)(void), +(*const __preinit_array_end)(void); +weak_alias(__preinit_array_start, __preinit_array_end); weak_alias(__init_array_start, __init_array_end); weak_alias(__fini_array_start, __fini_array_end); @@ -1229,6 +1232,11 @@ static void do_init_fini(struct dso *p) if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT]) fpaddr(p, dyn[DT_INIT])(); #endif + if (dyn[0] & (1UL<<DT_PREINIT_ARRAY)) { + size_t n = dyn[DT_PREINIT_ARRAYSZ]/sizeof(size_t); + size_t *fn = laddr(p, dyn[DT_PREINIT_ARRAY]); + while (n--) ((void (*)(void))*fn++)(); + } if (dyn[0] & (1<<DT_INIT_ARRAY)) { size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t); size_t *fn = laddr(p, dyn[DT_INIT_ARRAY]); -- 2.4.1 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] add preinit_array support 2015-11-29 15:33 [PATCH 2/2] add preinit_array support Szabolcs Nagy @ 2015-11-29 16:59 ` Szabolcs Nagy 2015-11-29 23:43 ` Rich Felker 0 siblings, 1 reply; 4+ messages in thread From: Szabolcs Nagy @ 2015-11-29 16:59 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 414 bytes --] * Szabolcs Nagy <nsz@port70.net> [2015-11-29 16:33:22 +0100]: > redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. > --- > src/env/__libc_start_main.c | 5 +++++ > src/ldso/dynlink.c | 12 ++++++++++-- > 2 files changed, 15 insertions(+), 2 deletions(-) > src/internal change was missing and legacy _init vs preinit_array order was wrong. attached new version, array type is fixed too. [-- Attachment #2: 0002-add-preinit_array-support.patch --] [-- Type: text/x-diff, Size: 3087 bytes --] From 8820faea5a365387c8fe54c8ffa1f796c2084f83 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy <nsz@port70.net> Date: Sun, 29 Nov 2015 16:36:24 +0000 Subject: [PATCH 2/2] add preinit_array support handle DT_PREINIT_ARRAY{SZ} in case of dynamic linking and __preinit_array_{start,end} in case of static linking. redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. --- src/env/__libc_start_main.c | 5 +++++ src/internal/dynlink.h | 2 +- src/ldso/dynlink.c | 12 ++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index 14a2825..7502bc3 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -12,6 +12,9 @@ static void dummy(void) {} weak_alias(dummy, _init); __attribute__((__weak__, __visibility__("hidden"))) +extern void (*const __preinit_array_start)(void), (*const __preinit_array_end)(void); + +__attribute__((__weak__, __visibility__("hidden"))) extern void (*const __init_array_start)(void), (*const __init_array_end)(void); static void dummy1(void *p) {} @@ -56,6 +59,8 @@ void __init_libc(char **envp, char *pn) static void libc_start_init(void) { void (*const *f)(void); + for (f=&__preinit_array_start; f<&__preinit_array_end; f++) + (*f)(); _init(); for (f=&__init_array_start; f<&__init_array_end; f++) (*f)(); diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 9c494e4..fb706d3 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -84,7 +84,7 @@ struct fdpic_dummy_loadmap { #endif #define AUX_CNT 32 -#define DYN_CNT 32 +#define DYN_CNT DT_NUM typedef void (*stage2_func)(unsigned char *, size_t *); typedef _Noreturn void (*stage3_func)(size_t *); diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 93e7d67..51da820 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -135,11 +135,14 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap; struct debug *_dl_debug_addr = &debug; __attribute__((__visibility__("hidden"))) -void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; +void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0, +(*const __preinit_array_start)(void)=0; __attribute__((__visibility__("hidden"))) -extern void (*const __init_array_end)(void), (*const __fini_array_end)(void); +extern void (*const __init_array_end)(void), (*const __fini_array_end)(void), +(*const __preinit_array_end)(void); +weak_alias(__preinit_array_start, __preinit_array_end); weak_alias(__init_array_start, __init_array_end); weak_alias(__fini_array_start, __fini_array_end); @@ -1225,6 +1228,11 @@ static void do_init_fini(struct dso *p) p->fini_next = fini_head; fini_head = p; } + if (dyn[0] & (1UL<<DT_PREINIT_ARRAY)) { + size_t n = dyn[DT_PREINIT_ARRAYSZ]/sizeof(size_t); + size_t *fn = laddr(p, dyn[DT_PREINIT_ARRAY]); + while (n--) ((void (*)(void))*fn++)(); + } #ifndef NO_LEGACY_INITFINI if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT]) fpaddr(p, dyn[DT_INIT])(); -- 2.4.1 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] add preinit_array support 2015-11-29 16:59 ` Szabolcs Nagy @ 2015-11-29 23:43 ` Rich Felker 2016-05-17 21:52 ` Szabolcs Nagy 0 siblings, 1 reply; 4+ messages in thread From: Rich Felker @ 2015-11-29 23:43 UTC (permalink / raw) To: musl On Sun, Nov 29, 2015 at 05:59:25PM +0100, Szabolcs Nagy wrote: > * Szabolcs Nagy <nsz@port70.net> [2015-11-29 16:33:22 +0100]: > > redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. > > --- > > src/env/__libc_start_main.c | 5 +++++ > > src/ldso/dynlink.c | 12 ++++++++++-- > > 2 files changed, 15 insertions(+), 2 deletions(-) > > > > src/internal change was missing and legacy _init vs > preinit_array order was wrong. > > attached new version, array type is fixed too. > >From 8820faea5a365387c8fe54c8ffa1f796c2084f83 Mon Sep 17 00:00:00 2001 > From: Szabolcs Nagy <nsz@port70.net> > Date: Sun, 29 Nov 2015 16:36:24 +0000 > Subject: [PATCH 2/2] add preinit_array support > > handle DT_PREINIT_ARRAY{SZ} in case of dynamic linking and > __preinit_array_{start,end} in case of static linking. Omission of preinit array support was intentional since it's reserved for use by the [library] implementation and musl does not use it, and I've tried to keep mandatory-linked startup code as small as possible to keep the small-static-binaries people happy. However on IRC we discussed that ASan and VTV and perhaps other similar tools might use it, and such use makes sense, so we may need to add it. I just don't want to get in a habit of adding whatever random junk is in the ELF spec when there's no reasonable, well-defined way for application code to use or depend on it. > redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. This should be reviewed for possible problems; IIRC I reduced it to 32 to avoid having to worry about undefined bitshifts in some code that can't do 64-bit shifts (because libgcc functions might not yet be callable) but that code should really hard-code 32 rather than using DYN_CNT if it's still a problem. > --- > src/env/__libc_start_main.c | 5 +++++ > src/internal/dynlink.h | 2 +- > src/ldso/dynlink.c | 12 ++++++++++-- > 3 files changed, 16 insertions(+), 3 deletions(-) > > diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c > index 14a2825..7502bc3 100644 > --- a/src/env/__libc_start_main.c > +++ b/src/env/__libc_start_main.c > @@ -12,6 +12,9 @@ static void dummy(void) {} > weak_alias(dummy, _init); > > __attribute__((__weak__, __visibility__("hidden"))) > +extern void (*const __preinit_array_start)(void), (*const __preinit_array_end)(void); > + > +__attribute__((__weak__, __visibility__("hidden"))) > extern void (*const __init_array_start)(void), (*const __init_array_end)(void); > > static void dummy1(void *p) {} > @@ -56,6 +59,8 @@ void __init_libc(char **envp, char *pn) > static void libc_start_init(void) > { > void (*const *f)(void); > + for (f=&__preinit_array_start; f<&__preinit_array_end; f++) > + (*f)(); > _init(); > for (f=&__init_array_start; f<&__init_array_end; f++) > (*f)(); > diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h > index 9c494e4..fb706d3 100644 > --- a/src/internal/dynlink.h > +++ b/src/internal/dynlink.h > @@ -84,7 +84,7 @@ struct fdpic_dummy_loadmap { > #endif > > #define AUX_CNT 32 > -#define DYN_CNT 32 > +#define DYN_CNT DT_NUM DT_NUM is probably excessive and just increases stack usage with no benefit. > typedef void (*stage2_func)(unsigned char *, size_t *); > typedef _Noreturn void (*stage3_func)(size_t *); > diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c > index 93e7d67..51da820 100644 > --- a/src/ldso/dynlink.c > +++ b/src/ldso/dynlink.c > @@ -135,11 +135,14 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap; > struct debug *_dl_debug_addr = &debug; > > __attribute__((__visibility__("hidden"))) > -void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; > +void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0, > +(*const __preinit_array_start)(void)=0; > > __attribute__((__visibility__("hidden"))) > -extern void (*const __init_array_end)(void), (*const __fini_array_end)(void); > +extern void (*const __init_array_end)(void), (*const __fini_array_end)(void), > +(*const __preinit_array_end)(void); > > +weak_alias(__preinit_array_start, __preinit_array_end); > weak_alias(__init_array_start, __init_array_end); > weak_alias(__fini_array_start, __fini_array_end); > > @@ -1225,6 +1228,11 @@ static void do_init_fini(struct dso *p) > p->fini_next = fini_head; > fini_head = p; > } > + if (dyn[0] & (1UL<<DT_PREINIT_ARRAY)) { This invokes UB on 32-bit archs, and couldn't possibly work anyway since the bit simply doesn't exist. Probably the test just needs to be "if (dyn[DT_PREINIT_ARRAYSZ])" or similar. Alternatively, search_vec could be used. Further, I don't think having this code inside the do_init_fini loop makes sense -- that loop runs backwards starting from the last-loaded library, whereas preinit arrays are only valid in the main program (at least according to ld, IIRC) and must run before any normal init arrays or legacy _init functions (for any DSOs) are run. Rich ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] add preinit_array support 2015-11-29 23:43 ` Rich Felker @ 2016-05-17 21:52 ` Szabolcs Nagy 0 siblings, 0 replies; 4+ messages in thread From: Szabolcs Nagy @ 2016-05-17 21:52 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 1583 bytes --] * Rich Felker <dalias@libc.org> [2015-11-29 18:43:09 -0500]: > On Sun, Nov 29, 2015 at 05:59:25PM +0100, Szabolcs Nagy wrote: > > * Szabolcs Nagy <nsz@port70.net> [2015-11-29 16:33:22 +0100]: > > handle DT_PREINIT_ARRAY{SZ} in case of dynamic linking and > > __preinit_array_{start,end} in case of static linking. > > Omission of preinit array support was intentional since it's reserved > for use by the [library] implementation and musl does not use it, and > I've tried to keep mandatory-linked startup code as small as possible > to keep the small-static-binaries people happy. > > However on IRC we discussed that ASan and VTV and perhaps other > similar tools might use it, and such use makes sense, so we may need > to add it. I just don't want to get in a habit of adding whatever > random junk is in the ELF spec when there's no reasonable, > well-defined way for application code to use or depend on it. > > > redefined DYN_CNT because 32 is not enough for DT_PREINIT_ARRAY. > > This should be reviewed for possible problems; IIRC I reduced it to 32 > to avoid having to worry about undefined bitshifts in some code that > can't do 64-bit shifts (because libgcc functions might not yet be > callable) but that code should really hard-code 32 rather than using > DYN_CNT if it's still a problem. > attached another variant in case we will need it (handles DT_PREINIT* separately). i didn't handle the issue described in http://git.musl-libc.org/cgit/musl/commit/?id=19caa25d0a8e587bb89b79c3f629085548709dd4 i don't know if that may apply to the preinit* symbols too. [-- Attachment #2: 0001-add-preinit_array-support.patch --] [-- Type: text/x-diff, Size: 1975 bytes --] From 18cfe83a9f3afacb03f3cad8e8b9d78121179451 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy <nsz@port70.net> Date: Sun, 15 May 2016 20:11:42 +0000 Subject: [PATCH] add preinit_array support --- ldso/dynlink.c | 13 +++++++++++++ src/env/__libc_start_main.c | 8 +++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index e458f38..38709ec 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1207,6 +1207,18 @@ void __libc_exit_fini() } } +static void do_preinit(void) +{ + size_t *v, *fn, n=0; + + for (v = head->dynv; v[0]; v+=2) + if (v[0] == DT_PREINIT_ARRAY) + fn = laddr(head, v[1]); + else if (v[0] == DT_PREINIT_ARRAYSZ) + n = v[1]/sizeof(size_t); + while (n--) ((void(*)(void))*fn++)(); +} + static void do_init_fini(struct dso *p) { size_t dyn[DYN_CNT]; @@ -1242,6 +1254,7 @@ static void do_init_fini(struct dso *p) void __libc_start_init(void) { + do_preinit(); do_init_fini(tail); } diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index 5c79be2..1397ec4 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -12,6 +12,9 @@ static void dummy(void) {} weak_alias(dummy, _init); __attribute__((__weak__, __visibility__("hidden"))) +extern void (*const __preinit_array_start)(void), (*const __preinit_array_end)(void); + +__attribute__((__weak__, __visibility__("hidden"))) extern void (*const __init_array_start)(void), (*const __init_array_end)(void); static void dummy1(void *p) {} @@ -55,8 +58,11 @@ void __init_libc(char **envp, char *pn) static void libc_start_init(void) { + uintptr_t a = (uintptr_t)&__preinit_array_start; + for (; a<(uintptr_t)&__preinit_array_end; a+=sizeof(void(*)())) + (*(void (**)())a)(); _init(); - uintptr_t a = (uintptr_t)&__init_array_start; + a = (uintptr_t)&__init_array_start; for (; a<(uintptr_t)&__init_array_end; a+=sizeof(void(*)())) (*(void (**)())a)(); } -- 2.8.1 ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-05-17 21:52 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-11-29 15:33 [PATCH 2/2] add preinit_array support Szabolcs Nagy 2015-11-29 16:59 ` Szabolcs Nagy 2015-11-29 23:43 ` Rich Felker 2016-05-17 21:52 ` Szabolcs Nagy
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).