summaryrefslogtreecommitdiff
path: root/src/logic/slbt_exec_ctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic/slbt_exec_ctx.c')
-rw-r--r--src/logic/slbt_exec_ctx.c405
1 files changed, 342 insertions, 63 deletions
diff --git a/src/logic/slbt_exec_ctx.c b/src/logic/slbt_exec_ctx.c
index a170b45..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 Z. Gilboa */
+/* 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;