diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h index 96e3738..bf0bf32 100644 --- a/include/slibtool/slibtool.h +++ b/include/slibtool/slibtool.h @@ -234,6 +234,7 @@ struct slbt_exec_ctx { char * dlunit; char * dlopensrc; char * dlopenobj; + char * dlpreopen; char * arfilename; char * lafilename; diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c index 8f4f2dc..fc242c0 100644 --- a/src/driver/slbt_driver_ctx.c +++ b/src/driver/slbt_driver_ctx.c @@ -247,7 +247,7 @@ static struct slbt_driver_ctx_impl * slbt_driver_ctx_alloc( } if (ndlopen) { - if (!(ictx->ctx.dlopenv = calloc(ndlopen+1,sizeof(char *)))) { + if (!(ictx->ctx.dlopenv = calloc(ndlopen+1,sizeof(*ictx->ctx.dlopenv)))) { free(ictx); slbt_free_argv_buffer(sargv,objlistv); return 0; @@ -406,7 +406,7 @@ int slbt_lib_get_driver_ctx( const char * lconf; uint64_t lflags; size_t ndlopen; - const char ** dlopenv; + struct argv_entry ** dlopenv; const char * cfgmeta_host; const char * cfgmeta_ar; const char * cfgmeta_as; @@ -1010,7 +1010,16 @@ int slbt_lib_get_driver_ctx( if (entry->fopt) { switch (entry->tag) { case TAG_DLOPEN: - ctx->cctx.drvflags |= SLBT_DRIVER_DLOPEN_FORCE; + if (!strcmp(entry->arg,"self")) { + ctx->cctx.drvflags |= SLBT_DRIVER_DLOPEN_FORCE; + + } else if (!strcmp(entry->arg,"force")) { + ctx->cctx.drvflags |= SLBT_DRIVER_DLOPEN_FORCE; + + } else { + *dlopenv++ = entry; + } + break; case TAG_DLPREOPEN: @@ -1021,9 +1030,11 @@ int slbt_lib_get_driver_ctx( ctx->cctx.drvflags |= SLBT_DRIVER_DLPREOPEN_FORCE; } else { - *dlopenv++ = entry->arg; + *dlopenv++ = entry; } + break; + default: break; } diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index e6e21ea..ef734fd 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -150,7 +150,7 @@ struct slbt_driver_ctx_impl { struct slbt_txtfile_ctx * lconfctx; struct slbt_obj_list * objlistv; - const char ** dlopenv; + struct argv_entry ** dlopenv; size_t ndlopen; const struct slbt_archive_ctx * arctx; @@ -179,6 +179,7 @@ struct slbt_exec_ctx_impl { struct slbt_symlist_ctx * sctx; struct slbt_exec_ctx ctx; struct slbt_archive_ctx ** dlactxv; + struct slbt_archive_ctx * dlpreopen; char ** dlargv; int argc; char * args; diff --git a/src/logic/linkcmd/slbt_linkcmd_argv.c b/src/logic/linkcmd/slbt_linkcmd_argv.c index 5cfbddb..a7c0777 100644 --- a/src/logic/linkcmd/slbt_linkcmd_argv.c +++ b/src/logic/linkcmd/slbt_linkcmd_argv.c @@ -23,6 +23,7 @@ #include "slibtool_symlink_impl.h" #include "slibtool_readlink_impl.h" #include "slibtool_visibility_impl.h" +#include "slibtool_ar_impl.h" static const char * slbt_ar_self_dlunit = "@PROGRAM@"; @@ -940,7 +941,7 @@ slbt_hidden int slbt_exec_link_finalize_argument_vector( /* add or repalce the archive context */ for (; !arctx && *arctxv; ) - if (!strcmp(*arctxv[0]->path,ectx->mapfilename)) + if (!strcmp(*arctxv[0]->path,slbt_ar_self_dlunit)) arctx = *arctxv; else arctxv++; @@ -955,7 +956,11 @@ slbt_hidden int slbt_exec_link_finalize_argument_vector( if (slbt_ar_get_archive_ctx(dctx,arname,arctxv) < 0) return SLBT_NESTED_ERROR(dctx); - arctxv[0]->path = &slbt_ar_self_dlunit; + arctx = *arctxv; + arctx->path = &slbt_ar_self_dlunit; + + if (slbt_ar_update_syminfo(arctx,ectx) < 0) + return SLBT_NESTED_ERROR(dctx); /* regenerate the dlsyms vtable source */ if (slbt_ar_create_dlsyms( @@ -981,6 +986,10 @@ slbt_hidden int slbt_exec_link_finalize_argument_vector( for (; srcdlpreopen) + *dst++ = ectx->dlpreopen; + /* join all other args, eliminate no-op linker path args */ src = aargv; cap = aarg; diff --git a/src/logic/slbt_exec_ctx.c b/src/logic/slbt_exec_ctx.c index b1177db..af45a93 100644 --- a/src/logic/slbt_exec_ctx.c +++ b/src/logic/slbt_exec_ctx.c @@ -16,7 +16,7 @@ #include "slibtool_errinfo_impl.h" #include "slibtool_ar_impl.h" -#define SLBT_ECTX_LIB_EXTRAS 24 +#define SLBT_ECTX_LIB_EXTRAS 26 #define SLBT_ECTX_SPARE_PTRS 16 static int slbt_ectx_free_exec_ctx_impl( @@ -217,7 +217,9 @@ int slbt_ectx_get_exec_ctx( char * slash; char * arname; struct slbt_archive_ctx ** dlactxv; - const char ** dlopenv; + struct argv_entry * dlentry; + struct argv_entry ** dlopenv; + bool fpreopen; const char * arprefix; const char * dsoprefix; const char * impprefix; @@ -548,7 +550,7 @@ int slbt_ectx_get_exec_ctx( } /* dlopensrc, dlopenobj */ - if (idctx->ndlopen) { + if (idctx->dlopenv) { ictx->ctx.dlopensrc = ch; ch += sprintf(ch,"%s%s%s.dlopen.c", ictx->ctx.ldirname, @@ -565,6 +567,14 @@ int slbt_ectx_get_exec_ctx( ch++; + ictx->ctx.dlpreopen = ch; + ch += sprintf(ch,"%s%s%s.dlpreopen.a", + ictx->ctx.ldirname, + dsoprefix, + dctx->cctx->libname); + + ch++; + ictx->ctx.dlunit = ch; ch += sprintf(ch,"%s%s", dsoprefix, @@ -600,6 +610,12 @@ int slbt_ectx_get_exec_ctx( ch++; + ictx->ctx.dlpreopen = ch; + ch += sprintf(ch,"%s.dlpreopen.a", + ictx->ctx.exefilename); + + ch++; + ictx->ctx.dlunit = ch; ch += sprintf(ch,"%s", "@PROGRAM@"); @@ -617,6 +633,7 @@ int slbt_ectx_get_exec_ctx( /* dlopen, dlpreopen */ if ((dlopenv = idctx->dlopenv), (dlactxv = ictx->dlactxv)) { fmask = SLBT_DRIVER_DLPREOPEN_FORCE; + fmask |= SLBT_DRIVER_DLPREOPEN_SELF; fmask |= SLBT_DRIVER_DLOPEN_FORCE; if (dctx->cctx->drvflags & fmask) { @@ -634,8 +651,11 @@ int slbt_ectx_get_exec_ctx( } for (; *dlopenv; ) { + dlentry = *dlopenv; + fpreopen = (dlentry->tag == TAG_DLPREOPEN); + arname = ictx->sbuf; - strcpy(arname,*dlopenv); + strcpy(arname,dlentry->arg); slbt_adjust_wrapper_argument( arname,true, @@ -644,7 +664,12 @@ int slbt_ectx_get_exec_ctx( errinfp = idctx->errinfp; if (slbt_ar_get_archive_ctx(dctx,arname,dlactxv) < 0) { - strcpy(arname,*dlopenv); + if ((*errinfp)->esyscode != ENOENT) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + strcpy(arname,dlentry->arg); slbt_adjust_wrapper_argument( arname,true, @@ -659,15 +684,23 @@ int slbt_ectx_get_exec_ctx( for (; *errinfp; ) *errinfp++ = 0; + + fpreopen = true; } - if (slbt_ar_update_syminfo(*dlactxv,&ictx->ctx) < 0) - return slbt_ectx_free_exec_ctx_impl( - ictx, - SLBT_NESTED_ERROR(dctx)); + if (fpreopen) { + if (slbt_ar_update_syminfo(*dlactxv,&ictx->ctx) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + dlactxv++; + } else { + slbt_ar_free_archive_ctx(*dlactxv); + *dlactxv = 0; + } dlopenv++; - dlactxv++; } if (slbt_mkdir(dctx,ictx->ctx.ldirname) < 0) @@ -685,6 +718,16 @@ int slbt_ectx_get_exec_ctx( return slbt_ectx_free_exec_ctx_impl( ictx, SLBT_NESTED_ERROR(dctx)); + + if (slbt_ar_merge_archives(ictx->dlactxv,&ictx->dlpreopen) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + if (slbt_ar_store_archive(ictx->dlpreopen,ictx->ctx.dlpreopen,0644) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); } /* vector of exported symbols (raw input via -export-symbols) */