summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/slibtool/slibtool.h5
-rw-r--r--src/logic/linkcmd/slbt_linkcmd_argv.c51
2 files changed, 53 insertions, 3 deletions
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h
index d89e184..96e3738 100644
--- a/include/slibtool/slibtool.h
+++ b/include/slibtool/slibtool.h
@@ -78,6 +78,11 @@ extern "C" {
#define SLBT_DRIVER_MODE_AR_CHECK SLBT_DRIVER_XFLAG(0x020000)
#define SLBT_DRIVER_MODE_AR_MERGE SLBT_DRIVER_XFLAG(0x040000)
+#define SLBT_DRIVER_DLOPEN_SELF SLBT_DRIVER_XFLAG(0x10000000)
+#define SLBT_DRIVER_DLOPEN_FORCE SLBT_DRIVER_XFLAG(0x20000000)
+#define SLBT_DRIVER_DLPREOPEN_SELF SLBT_DRIVER_XFLAG(0x40000000)
+#define SLBT_DRIVER_DLPREOPEN_FORCE SLBT_DRIVER_XFLAG(0x80000000)
+
/* unit action flags */
#define SLBT_ACTION_MAP_READWRITE 0x0001
diff --git a/src/logic/linkcmd/slbt_linkcmd_argv.c b/src/logic/linkcmd/slbt_linkcmd_argv.c
index 5782952..9197734 100644
--- a/src/logic/linkcmd/slbt_linkcmd_argv.c
+++ b/src/logic/linkcmd/slbt_linkcmd_argv.c
@@ -25,6 +25,8 @@
#include "slibtool_visibility_impl.h"
+static const char * slbt_ar_self_dlunit = "@PROGRAM@";
+
static int slbt_linkcmd_exit(
struct slbt_deps_meta * depsmeta,
int ret)
@@ -592,7 +594,8 @@ static int slbt_exec_link_create_expsyms_archive(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
char ** lobjv,
- char ** cnvlv)
+ char ** cnvlv,
+ char (*arname)[PATH_MAX])
{
int ret;
char * dot;
@@ -602,8 +605,8 @@ static int slbt_exec_link_create_expsyms_archive(
struct slbt_archive_ctx * arctx;
char ** ectx_argv;
char * ectx_program;
- char program[PATH_MAX];
char output [PATH_MAX];
+ char program[PATH_MAX];
/* output */
if (slbt_snprintf(output,sizeof(output),
@@ -619,6 +622,9 @@ static int slbt_exec_link_create_expsyms_archive(
dot[1] = 'a';
dot[2] = '\0';
+ if (arname)
+ strcpy(*arname,output);
+
/* tool-specific argument vector */
argv = (slbt_get_driver_ictx(dctx))->host.ar_argv;
@@ -930,9 +936,48 @@ slbt_hidden int slbt_exec_link_finalize_argument_vector(
/* export-symbols-regex, proper dlpreopen support */
if (dctx->cctx->libname)
if (slbt_exec_link_create_expsyms_archive(
- dctx,ectx,lobjv,cnvlv) < 0)
+ dctx,ectx,lobjv,cnvlv,0) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ /* -dlpreopen self */
+ if (dctx->cctx->drvflags & SLBT_DRIVER_DLPREOPEN_SELF) {
+ struct slbt_archive_ctx * arctx;
+ struct slbt_archive_ctx ** arctxv;
+ struct slbt_exec_ctx_impl * ictx;
+ char arname[PATH_MAX];
+
+ ictx = slbt_get_exec_ictx(ectx);
+ arctxv = ictx->dlactxv;
+ arctx = 0;
+
+ /* add or repalce the archive context */
+ for (; !arctx && *arctxv; )
+ if (!strcmp(*arctxv[0]->path,ectx->mapfilename))
+ arctx = *arctxv;
+ else
+ arctxv++;
+
+ if (arctx)
+ slbt_ar_free_archive_ctx(arctx);
+
+ if (slbt_exec_link_create_expsyms_archive(
+ dctx,ectx,lobjv,cnvlv,&arname) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (slbt_ar_get_archive_ctx(dctx,arname,arctxv) < 0)
return SLBT_NESTED_ERROR(dctx);
+ arctxv[0]->path = &slbt_ar_self_dlunit;
+
+ /* regenerate the dlsyms vtable source */
+ if (slbt_ar_create_dlsyms(
+ ictx->dlactxv,
+ ectx->dlunit,
+ ectx->dlopensrc,
+ 0644) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+ }
+
/* program name, ccwrap */
if ((ccwrap = (char *)dctx->cctx->ccwrap)) {
base[1] = base[0];