diff options
Diffstat (limited to 'src/logic/slbt_exec_ctx.c')
-rw-r--r-- | src/logic/slbt_exec_ctx.c | 405 |
1 files changed, 342 insertions, 63 deletions
diff --git a/src/logic/slbt_exec_ctx.c b/src/logic/slbt_exec_ctx.c index 294641e..223be17 100644 --- a/src/logic/slbt_exec_ctx.c +++ b/src/logic/slbt_exec_ctx.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 SysDeer Technologies, LLC */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -11,9 +11,17 @@ #include <slibtool/slibtool.h> #include "slibtool_driver_impl.h" +#include "slibtool_mkdir_impl.h" +#include "slibtool_linkcmd_impl.h" #include "slibtool_errinfo_impl.h" +#include "slibtool_ar_impl.h" -#define SLBT_ARGV_SPARE_PTRS 16 +#define SLBT_ECTX_LIB_EXTRAS 26 +#define SLBT_ECTX_SPARE_PTRS 16 + +static int slbt_ectx_free_exec_ctx_impl( + struct slbt_exec_ctx_impl * ictx, + int status); static size_t slbt_parse_comma_separated_flags( const char * str, @@ -48,63 +56,82 @@ static char * slbt_source_file(char ** argv) } +static int slbt_exec_ctx_tool_argc(char ** argv) +{ + char ** parg; + + if (!(parg = argv)) + return 0; + + for (; *parg; ) + parg++; + + return parg - argv + 1; +} + + static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc( const struct slbt_driver_ctx * dctx) { + struct slbt_driver_ctx_impl * ctx; struct slbt_exec_ctx_impl * ictx; size_t size; - size_t vsize; + size_t slen; + size_t exts; int argc; char * args; char * shadow; char * csrc; char ** parg; + struct slbt_archive_ctx ** dlactxv; + size_t ndlopen; + /* internal driver context for host-specific tool arguments */ + ctx = slbt_get_driver_ictx(dctx); + + /* initial buffer size (cargv, -Wc), .libs/.exe.wrapper */ argc = 0; csrc = 0; + size = 0; + exts = 20; - /* clerical [worst-case] buffer size (guard, .libs, version) */ - size = strlen(".lo") + 1; - size += 12 * (strlen(".libs/") + 1); - size += 36 * (strlen(".0000") + 1); - - /* buffer size (cargv, -Wc) */ - for (parg=dctx->cctx->cargv; *parg; parg++, argc++) - if (!(strncmp("-Wc,",*parg,4))) + for (parg=dctx->cctx->cargv; *parg; parg++, argc++) { + if (!(strncmp("-Wc,",*parg,4))) { size += slbt_parse_comma_separated_flags( &(*parg)[4],&argc) + 1; - else + } else { size += strlen(*parg) + 1; + } + } - /* buffer size (ldirname, lbasename, lobjname, aobjname, etc.) */ - if (dctx->cctx->output) - size += 9*strlen(dctx->cctx->output); - else if ((csrc = slbt_source_file(dctx->cctx->cargv))) - size += 9*strlen(csrc); + /* argument transformation: assume for each argv member */ + if (dctx->cctx->shrext) { + exts += argc * (strlen(dctx->cctx->shrext)); + } - /* pessimistic: long dso suffix, long x.y.z version */ - size += 9 * (16 + 16 + 16 + 16); + if (dctx->cctx->settings.dsosuffix) { + exts += argc * (strlen(dctx->cctx->settings.dsosuffix)); + } - /* pessimistic argc: .libs/libfoo.so --> -L.libs -lfoo */ - argc *= 2; - argc += SLBT_ARGV_SPARE_PTRS; - - /* buffer size (.libs/%.o, pessimistic) */ - size += argc * strlen(".libs/-L-l"); - - /* buffer size (linking) */ - if (dctx->cctx->mode == SLBT_MODE_LINK) - size += strlen(dctx->cctx->settings.arprefix) + 1 - + strlen(dctx->cctx->settings.arsuffix) + 1 - + strlen(dctx->cctx->settings.dsoprefix) + 1 - + strlen(dctx->cctx->settings.dsoprefix) + 1 - + strlen(dctx->cctx->settings.dsoprefix) + 1 - + strlen(dctx->cctx->settings.exeprefix) + 1 - + strlen(dctx->cctx->settings.exeprefix) + 1 - + strlen(dctx->cctx->settings.impprefix) + 1 - + strlen(dctx->cctx->settings.impprefix) + 1; + size += argc * exts; - /* alloc */ + /* buffer size (csrc, ldirname, lbasename, lobjname, aobjname, etc.) */ + if (dctx->cctx->libname) { + slen = strlen(dctx->cctx->libname); + size += (strlen(".slibtool.expsyms.extension") + slen + exts + 1) * SLBT_ECTX_LIB_EXTRAS; + + } else if (dctx->cctx->output) { + slen = strlen(dctx->cctx->output); + size += (strlen(".slibtool.expsyms.extension") + slen + exts + 1) * SLBT_ECTX_LIB_EXTRAS; + + } else if ((csrc = slbt_source_file(dctx->cctx->cargv))) { + slen = strlen(csrc); + size += (strlen(".slibtool.expsyms.extension") + slen + exts + 1) * SLBT_ECTX_LIB_EXTRAS; + } else { + size += exts * SLBT_ECTX_LIB_EXTRAS; + } + + /* string buffers: args, shadow */ if (!(args = malloc(size))) return 0; @@ -113,24 +140,54 @@ static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc( return 0; } - /* ictx, argv, xargv */ - vsize = sizeof(*ictx); - vsize += sizeof(char *) * (argc + 1); - vsize += sizeof(char *) * (argc + 1); + /* tool-specific argv: to simplify matters, be additive */ + argc += slbt_exec_ctx_tool_argc(ctx->host.ar_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.as_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.nm_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.ranlib_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.windres_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.dlltool_argv); + argc += slbt_exec_ctx_tool_argc(ctx->host.mdso_argv); - /* altv: duplicate set, -Wl,--whole-archive, -Wl,--no-whole-archive */ - vsize += sizeof(char *) * (argc + 1) * 3; + /* argv transformation: .libs/libfoo.so --> -L.libs -lfoo */ + argc *= 2; - if (!(ictx = calloc(1,vsize))) { + /* argv ad-hoc extensions */ + argc += SLBT_ECTX_SPARE_PTRS; + + /* ctx alloc and vector alloc: argv, xargv, and altv, where we */ + /* assume -Wl,--whole-archive arg -Wl,--no-whole-archive; */ + /* and also dlargv for compiling dlunit.dlopen.c */ + if (!(ictx = calloc(1,sizeof(*ictx)))) { free(args); free(shadow); return 0; } + if (!(ictx->vbuffer = calloc(6*(argc+1),sizeof(char *)))) { + free(args); + free(shadow); + free(ictx); + } + + if ((ndlopen = (slbt_get_driver_ictx(dctx))->ndlopen)) { + if (!(dlactxv = calloc(ndlopen+1,sizeof(*dlactxv)))) { + free(ictx->vbuffer); + free(ictx); + free(args); + free(shadow); + } + + ictx->dlactxv = dlactxv; + } + + /* all ready */ + ictx->dctx = dctx; ictx->args = args; ictx->argc = argc; ictx->size = size; + ictx->exts = exts; ictx->shadow = shadow; ictx->ctx.csrc = csrc; @@ -142,24 +199,35 @@ static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc( } -int slbt_get_exec_ctx( +int slbt_ectx_get_exec_ctx( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx ** ectx) { struct slbt_exec_ctx_impl * ictx; + struct slbt_driver_ctx_impl * idctx; + struct slbt_error_info** errinfp; char ** parg; char ** src; char ** dst; char * ch; char * mark; const char * dmark; + const char * dsoext; char * slash; + char * arname; + struct slbt_archive_ctx ** dlactxv; + struct argv_entry * dlentry; + struct argv_entry ** dlopenv; + bool fpreopen; const char * arprefix; const char * dsoprefix; const char * impprefix; const char * ref; int i; + /* internal driver context */ + idctx = slbt_get_driver_ictx(dctx); + /* alloc */ if (!(ictx = slbt_exec_ctx_alloc(dctx))) return SLBT_NESTED_ERROR(dctx); @@ -169,6 +237,7 @@ int slbt_get_exec_ctx( ictx->ctx.argv = ictx->vbuffer; ictx->ctx.xargv = &ictx->ctx.argv [ictx->argc + 1]; ictx->ctx.altv = &ictx->ctx.xargv[ictx->argc + 1]; + ictx->dlargv = &ictx->ctx.altv [ictx->argc + 1]; /* <compiler> */ ictx->ctx.compiler = dctx->cctx->cargv[0]; @@ -252,7 +321,7 @@ int slbt_get_exec_ctx( } else { ictx->ctx.argv[i++] = ch; ch += sprintf(ch,"%s",*parg); - ch += strlen(".libs/-L-l"); + ch += ictx->exts; } } @@ -266,6 +335,8 @@ int slbt_get_exec_ctx( ictx->ctx.lsoname = &ictx->ctx.argv[i++]; ictx->ctx.symdefs = &ictx->ctx.argv[i++]; ictx->ctx.symfile = &ictx->ctx.argv[i++]; + ictx->ctx.explarg = &ictx->ctx.argv[i++]; + ictx->ctx.expsyms = &ictx->ctx.argv[i++]; ictx->ctx.lout[0] = &ictx->ctx.argv[i++]; ictx->ctx.lout[1] = &ictx->ctx.argv[i++]; @@ -311,8 +382,11 @@ int slbt_get_exec_ctx( + 1; } - /* linking: arfilename, lafilename, laifilename, dsobasename, dsofilename */ + /* linking: arfilename, lafilename, laifilename, dsobasename, dsofilename, mapfilename */ if (dctx->cctx->mode == SLBT_MODE_LINK && dctx->cctx->libname) { + if (!(dsoext = dctx->cctx->shrext)) + dsoext = dctx->cctx->settings.dsosuffix; + /* arprefix, dsoprefix */ if (dctx->cctx->drvflags & SLBT_DRIVER_MODULE) { ictx->ctx.sonameprefix = ""; @@ -369,7 +443,18 @@ int slbt_get_exec_ctx( ictx->ctx.ldirname, dsoprefix, dctx->cctx->libname, - dctx->cctx->settings.dsosuffix); + dsoext); + ch++; + + /* mapfilename */ + ictx->ctx.mapfilename = ch; + ch += sprintf(ch,"%s%s%s%s%s%s", + ictx->ctx.ldirname, + dsoprefix, + dctx->cctx->libname, + dctx->cctx->release ? "-" : "", + dctx->cctx->release ? dctx->cctx->release : "", + dctx->cctx->settings.mapsuffix); ch++; /* deffilename */ @@ -380,7 +465,7 @@ int slbt_get_exec_ctx( dctx->cctx->libname, dctx->cctx->release ? "-" : "", dctx->cctx->release ? dctx->cctx->release : "", - dctx->cctx->settings.dsosuffix); + dsoext); ch++; /* rpathfilename */ @@ -389,7 +474,7 @@ int slbt_get_exec_ctx( ictx->ctx.ldirname, dsoprefix, dctx->cctx->libname, - dctx->cctx->settings.dsosuffix); + dsoext); ch++; /* default implib file name */ @@ -447,7 +532,7 @@ int slbt_get_exec_ctx( dsoprefix, dctx->cctx->libname, dctx->cctx->release, - dctx->cctx->settings.dsosuffix); + dsoext); ch++; } @@ -459,13 +544,46 @@ int slbt_get_exec_ctx( dsoprefix, dctx->cctx->libname, dctx->cctx->release, - dctx->cctx->settings.dsosuffix); + dsoext); + ch++; + } + + /* dlopensrc, dlopenobj */ + if (idctx->dlopenv) { + ictx->ctx.dlopensrc = ch; + ch += sprintf(ch,"%s%s%s.dlopen.c", + ictx->ctx.ldirname, + dsoprefix, + dctx->cctx->libname); + + ch++; + + ictx->ctx.dlopenobj = ch; + ch += sprintf(ch,"%s%s%s.dlopen.o", + ictx->ctx.ldirname, + dsoprefix, + dctx->cctx->libname); + + 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, + dctx->cctx->libname); + ch++; } - } /* linking: exefilename */ - if (dctx->cctx->mode == SLBT_MODE_LINK && !dctx->cctx->libname) { + } else if (dctx->cctx->mode == SLBT_MODE_LINK) { ictx->ctx.exefilename = ch; if ((slash = strrchr(dctx->cctx->output,'/'))) { @@ -477,6 +595,141 @@ int slbt_get_exec_ctx( ch += sprintf(ch,".libs/%s",dctx->cctx->output) + 1; } + /* dlopensrc, dlopenobj: executable program */ + if (idctx->dlopenv && !dctx->cctx->libname) { + ictx->ctx.dlopensrc = ch; + ch += sprintf(ch,"%s.dlopen.c", + ictx->ctx.exefilename); + + ch++; + + ictx->ctx.dlopenobj = ch; + ch += sprintf(ch,"%s.dlopen.o", + ictx->ctx.exefilename); + + ch++; + + ictx->ctx.dlpreopen = ch; + ch += sprintf(ch,"%s.dlpreopen.a", + ictx->ctx.exefilename); + + ch++; + + ictx->ctx.dlunit = ch; + ch += sprintf(ch,"%s", + "@PROGRAM@"); + + ch++; + + ictx->ctx.mapfilename = ch; + ch += sprintf(ch,"%s%s", + ictx->ctx.exefilename, + dctx->cctx->settings.mapsuffix); + ch++; + + } + + /* dlopen, dlpreopen */ + if ((dlopenv = idctx->dlopenv), (dlactxv = ictx->dlactxv)) { + if (slbt_ar_get_varchive_ctx(dctx,dlactxv) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + if (slbt_ar_update_syminfo(*dlactxv) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + dlactxv++; + + for (; *dlopenv; ) { + dlentry = *dlopenv; + fpreopen = (dlentry->tag == TAG_DLPREOPEN); + + arname = ictx->sbuf; + strcpy(arname,dlentry->arg); + + slbt_adjust_wrapper_argument( + arname,true, + ".expsyms.a"); + + errinfp = idctx->errinfp; + + if (slbt_ar_get_archive_ctx(dctx,arname,dlactxv) < 0) { + 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, + dctx->cctx->settings.arsuffix); + + if (slbt_ar_get_archive_ctx(dctx,arname,dlactxv) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + idctx->errinfp = errinfp; + + for (; *errinfp; ) + *errinfp++ = 0; + + fpreopen = true; + } + + if (fpreopen) { + if (slbt_ar_update_syminfo(*dlactxv) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_NESTED_ERROR(dctx)); + + dlactxv++; + } else { + slbt_ar_free_archive_ctx(*dlactxv); + *dlactxv = 0; + } + + dlopenv++; + } + + if (slbt_mkdir(dctx,ictx->ctx.ldirname) < 0) + return slbt_ectx_free_exec_ctx_impl( + ictx, + SLBT_SYSTEM_ERROR( + dctx, + ictx->ctx.ldirname)); + + if (slbt_ar_create_dlsyms( + ictx->dlactxv, + ictx->ctx.dlunit, + ictx->ctx.dlopensrc, + 0644) < 0) + 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) */ + if (dctx->cctx->expsyms) + if (slbt_lib_get_symlist_ctx( + dctx,dctx->cctx->expsyms, + &ictx->sctx) < 0) + return SLBT_NESTED_ERROR(dctx); + /* argument strings shadow copy */ memcpy(ictx->shadow,ictx->args,ictx->size); @@ -498,22 +751,35 @@ int slbt_get_exec_ctx( } -static int slbt_free_exec_ctx_impl( +static int slbt_ectx_free_exec_ctx_impl( struct slbt_exec_ctx_impl * ictx, int status) { + struct slbt_archive_ctx ** dlactxv; + + if (ictx->sctx) + slbt_lib_free_symlist_ctx(ictx->sctx); + if (ictx->fdwrapper >= 0) close(ictx->fdwrapper); + if (ictx->dlactxv) { + for (dlactxv=ictx->dlactxv; *dlactxv; dlactxv++) + slbt_ar_free_archive_ctx(*dlactxv); + + free(ictx->dlactxv); + } + free(ictx->args); free(ictx->shadow); + free(ictx->vbuffer); free (ictx); return status; } -void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx) +void slbt_ectx_free_exec_ctx(struct slbt_exec_ctx * ctx) { struct slbt_exec_ctx_impl * ictx; uintptr_t addr; @@ -521,12 +787,12 @@ void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx) if (ctx) { addr = (uintptr_t)ctx - offsetof(struct slbt_exec_ctx_impl,ctx); ictx = (struct slbt_exec_ctx_impl *)addr; - slbt_free_exec_ctx_impl(ictx,0); + slbt_ectx_free_exec_ctx_impl(ictx,0); } } -void slbt_reset_arguments(struct slbt_exec_ctx * ectx) +void slbt_ectx_reset_arguments(struct slbt_exec_ctx * ectx) { struct slbt_exec_ctx_impl * ictx; uintptr_t addr; @@ -537,7 +803,7 @@ void slbt_reset_arguments(struct slbt_exec_ctx * ectx) } -void slbt_reset_argvector(struct slbt_exec_ctx * ectx) +void slbt_ectx_reset_argvector(struct slbt_exec_ctx * ectx) { struct slbt_exec_ctx_impl * ictx; uintptr_t addr; @@ -560,8 +826,17 @@ void slbt_reset_argvector(struct slbt_exec_ctx * ectx) } -void slbt_reset_placeholders(struct slbt_exec_ctx * ectx) +slbt_hidden void slbt_reset_placeholders(struct slbt_exec_ctx * ectx) { + struct slbt_exec_ctx_impl * ictx; + + ictx = slbt_get_exec_ictx(ectx); + + if (ictx->lout[0]) { + ectx->lout[0] = ictx->lout[0]; + ectx->lout[1] = ictx->lout[1]; + } + *ectx->dpic = "-USLIBTOOL_PLACEHOLDER_DPIC"; *ectx->fpic = "-USLIBTOOL_PLACEHOLDER_FPIC"; *ectx->cass = "-USLIBTOOL_PLACEHOLDER_COMPILE_ASSEMBLE"; @@ -571,6 +846,8 @@ void slbt_reset_placeholders(struct slbt_exec_ctx * ectx) *ectx->lsoname = "-USLIBTOOL_PLACEHOLDER_LSONAME"; *ectx->symdefs = "-USLIBTOOL_PLACEHOLDER_SYMDEF_SWITCH"; *ectx->symfile = "-USLIBTOOL_PLACEHOLDER_SYMDEF_FILE"; + *ectx->explarg = "-USLIBTOOL_PLACEHOLDER_EXPSYMS_SWITCH"; + *ectx->expsyms = "-USLIBTOOL_PLACEHOLDER_EXPSYMS_FILE"; *ectx->lout[0] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_SWITCH"; *ectx->lout[1] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_FILE"; @@ -584,7 +861,7 @@ void slbt_reset_placeholders(struct slbt_exec_ctx * ectx) *ectx->sentinel= 0; } -void slbt_disable_placeholders(struct slbt_exec_ctx * ectx) +slbt_hidden void slbt_disable_placeholders(struct slbt_exec_ctx * ectx) { *ectx->dpic = 0; *ectx->fpic = 0; @@ -595,6 +872,8 @@ void slbt_disable_placeholders(struct slbt_exec_ctx * ectx) *ectx->lsoname = 0; *ectx->symdefs = 0; *ectx->symfile = 0; + *ectx->explarg = 0; + *ectx->expsyms = 0; *ectx->lout[0] = 0; *ectx->lout[1] = 0; |