summaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/argv/argv.h97
-rw-r--r--src/internal/slibtool_ar_impl.h100
-rw-r--r--src/internal/slibtool_coff_impl.c46
-rw-r--r--src/internal/slibtool_coff_impl.h6
-rw-r--r--src/internal/slibtool_dprintf_impl.c7
-rw-r--r--src/internal/slibtool_driver_impl.h357
-rw-r--r--src/internal/slibtool_errinfo_impl.c7
-rw-r--r--src/internal/slibtool_errinfo_impl.h4
-rw-r--r--src/internal/slibtool_lconf_impl.c374
-rw-r--r--src/internal/slibtool_lconf_impl.h3
-rw-r--r--src/internal/slibtool_libmeta_impl.c57
-rw-r--r--src/internal/slibtool_linkcmd_impl.h89
-rw-r--r--src/internal/slibtool_m4fake_impl.c142
-rw-r--r--src/internal/slibtool_m4fake_impl.h12
-rw-r--r--src/internal/slibtool_mapfile_impl.c11
-rw-r--r--src/internal/slibtool_metafile_impl.h8
-rw-r--r--src/internal/slibtool_mkdir_impl.h4
-rw-r--r--src/internal/slibtool_mkvars_impl.c245
-rw-r--r--src/internal/slibtool_mkvars_impl.h13
-rw-r--r--src/internal/slibtool_objlist_impl.c83
-rw-r--r--src/internal/slibtool_objlist_impl.h10
-rw-r--r--src/internal/slibtool_objmeta_impl.c11
-rw-r--r--src/internal/slibtool_pecoff_impl.c16
-rw-r--r--src/internal/slibtool_pecoff_impl.h6
-rw-r--r--src/internal/slibtool_readlink_impl.h4
-rw-r--r--src/internal/slibtool_realpath_impl.c100
-rw-r--r--src/internal/slibtool_realpath_impl.h13
-rw-r--r--src/internal/slibtool_snprintf_impl.c40
-rw-r--r--src/internal/slibtool_snprintf_impl.h6
-rw-r--r--src/internal/slibtool_spawn_impl.h12
-rw-r--r--src/internal/slibtool_stoolie_impl.h15
-rw-r--r--src/internal/slibtool_symlink_impl.c89
-rw-r--r--src/internal/slibtool_symlink_impl.h10
-rw-r--r--src/internal/slibtool_tmpfile_impl.c89
-rw-r--r--src/internal/slibtool_tmpfile_impl.h6
-rw-r--r--src/internal/slibtool_txtline_impl.c67
-rw-r--r--src/internal/slibtool_txtline_impl.h8
-rw-r--r--src/internal/slibtool_visibility_impl.h26
38 files changed, 1964 insertions, 229 deletions
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h
index 20568e9..d17865b 100644
--- a/src/internal/argv/argv.h
+++ b/src/internal/argv/argv.h
@@ -1,6 +1,6 @@
/****************************************************************************/
/* argv.h: a thread-safe argument vector parser and usage screen generator */
-/* Copyright (C) 2015--2021 Z. Gilboa */
+/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
/****************************************************************************/
@@ -83,6 +83,7 @@ enum argv_error {
ARGV_ERROR_INTERNAL,
ARGV_ERROR_SHORT_OPTION,
ARGV_ERROR_LONG_OPTION,
+ ARGV_ERROR_VENDOR_OPTION,
ARGV_ERROR_OPTARG_NONE,
ARGV_ERROR_OPTARG_REQUIRED,
ARGV_ERROR_OPTARG_PARADIGM,
@@ -398,7 +399,11 @@ static void argv_scan(
fval = ch;
}
} else {
- ferr = ARGV_ERROR_SHORT_OPTION;
+ if ((ch == &parg[0][1]) && (ch[0] == 'W') && ch[1]) {
+ ferr = ARGV_ERROR_VENDOR_OPTION;
+ } else {
+ ferr = ARGV_ERROR_SHORT_OPTION;
+ }
}
} else if (!fnoscan && (fhybrid || is_long_option(ch))) {
@@ -413,49 +418,72 @@ static void argv_scan(
ch = *parg;
}
- if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH))
+ /* now verify the proper setting of option values */
+ if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH)) {
ferr = ARGV_ERROR_HYBRID_NONE;
- else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY))
+
+ } else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY)) {
ferr = ARGV_ERROR_HYBRID_ONLY;
- else if (option->optarg == ARGV_OPTARG_NONE) {
+
+ } else if (option->optarg == ARGV_OPTARG_NONE) {
if (val[0]) {
ferr = ARGV_ERROR_OPTARG_NONE;
ctx->errch = val + 1;
- } else
+ } else {
fval = false;
+ }
+
} else if (val[0] && (option->flags & ARGV_OPTION_HYBRID_JOINED)) {
fval = true;
ch = val;
- } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE))
- ferr = ARGV_ERROR_HYBRID_SPACE;
- else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL))
+
+ } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE)) {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL) {
+ fval = false;
+
+ } else {
+ ferr = ARGV_ERROR_HYBRID_SPACE;
+ }
+
+ } else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL)) {
ferr = ARGV_ERROR_HYBRID_EQUAL;
- else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA))
+
+ } else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA)) {
ferr = ARGV_ERROR_HYBRID_COMMA;
- else if (!fhybrid && (val[0]==','))
+
+ } else if (!fhybrid && (val[0]==',')) {
ferr = ARGV_ERROR_HYBRID_COMMA;
- else if (val[0] && !val[1])
+
+ } else if (val[0] && !val[1]) {
ferr = ARGV_ERROR_OPTARG_REQUIRED;
- else if (val[0] && val[1]) {
+
+ } else if (val[0] && val[1]) {
fval = true;
ch = ++val;
+
} else if (option->optarg == ARGV_OPTARG_REQUIRED) {
- if (!val[0] && !*parg)
+ if (!val[0] && !*parg) {
ferr = ARGV_ERROR_OPTARG_REQUIRED;
- else if (*parg && is_short_option(*parg))
+
+ } else if (*parg && is_short_option(*parg)) {
ferr = ARGV_ERROR_OPTARG_REQUIRED;
- else if (*parg && is_long_option(*parg))
+
+ } else if (*parg && is_long_option(*parg)) {
ferr = ARGV_ERROR_OPTARG_REQUIRED;
- else if (*parg && is_last_option(*parg))
+
+ } else if (*parg && is_last_option(*parg)) {
ferr = ARGV_ERROR_OPTARG_REQUIRED;
- else
+
+ } else {
fval = true;
+ }
} else {
/* ARGV_OPTARG_OPTIONAL */
fval = val[0];
}
- } else
+ } else {
ferr = ARGV_ERROR_LONG_OPTION;
+ }
}
if (ferr == ARGV_ERROR_OK)
@@ -531,7 +559,11 @@ static const char * argv_program_name(const char * program_path)
static void argv_show_error(int fd, struct argv_ctx * ctx)
{
- char opt_short_name[2] = {0,0};
+ const char * src;
+ char * dst;
+ char * cap;
+ char opt_vendor_buf[256];
+ char opt_short_name[2] = {0,0};
if (ctx->erropt && ctx->erropt->short_name)
opt_short_name[0] = ctx->erropt->short_name;
@@ -547,6 +579,27 @@ static void argv_show_error(int fd, struct argv_ctx * ctx)
argv_dprintf(fd,"'--%s' is not a valid long option\n",ctx->errch);
break;
+ case ARGV_ERROR_VENDOR_OPTION:
+ src = ctx->errch;
+ dst = opt_vendor_buf;
+ cap = &opt_vendor_buf[sizeof(opt_vendor_buf)];
+
+ for (; src && *src && dst<cap; ) {
+ if ((*src == '=') || (*src == ',') || (*src == ':')) {
+ src = 0;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+
+ if (dst == cap)
+ dst--;
+
+ *dst = '\0';
+
+ argv_dprintf(fd,"'-%s' is not a valid vendor option\n",opt_vendor_buf);
+ break;
+
case ARGV_ERROR_OPTARG_NONE:
argv_dprintf(fd,"'%s' is not a valid option value for [%s%s%s%s%s] "
"(option values may not be specified)\n",
@@ -563,7 +616,9 @@ static void argv_show_error(int fd, struct argv_ctx * ctx)
opt_short_name[0] ? "-" : "",
opt_short_name,
opt_short_name[0] ? "," : "",
- ctx->erropt->long_name ? "--" : "",
+ ctx->erropt->long_name
+ ? (ctx->erropt->flags & ARGV_OPTION_HYBRID_ONLY) ? "-" : "--"
+ : "",
ctx->erropt->long_name,
ctx->erropt->paradigm ? "one of the following values:" : "a value",
ctx->erropt->paradigm ? "{" : "",
diff --git a/src/internal/slibtool_ar_impl.h b/src/internal/slibtool_ar_impl.h
new file mode 100644
index 0000000..57ff1cc
--- /dev/null
+++ b/src/internal/slibtool_ar_impl.h
@@ -0,0 +1,100 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#ifndef SLIBTOOL_AR_IMPL_H
+#define SLIBTOOL_AR_IMPL_H
+
+#include "argv/argv.h"
+#include <slibtool/slibtool.h>
+#include <slibtool/slibtool_arbits.h>
+
+/* decimal values in archive header are right padded with ascii spaces */
+#define AR_DEC_PADDING (0x20)
+
+/* archive file members are right padded as needed with ascii newline */
+#define AR_OBJ_PADDING (0x0A)
+
+/* initial number of elements in the transient, on-stack vector */
+# define AR_STACK_VECTOR_ELEMENTS (0x200)
+
+extern const struct argv_option slbt_ar_options[];
+
+struct ar_armaps_impl {
+ struct ar_meta_armap_ref_32 * armap_symrefs_32;
+ struct ar_meta_armap_ref_64 * armap_symrefs_64;
+ struct ar_raw_armap_bsd_32 armap_bsd_32;
+ struct ar_raw_armap_bsd_64 armap_bsd_64;
+ struct ar_raw_armap_sysv_32 armap_sysv_32;
+ struct ar_raw_armap_sysv_64 armap_sysv_64;
+ struct ar_meta_armap_common_32 armap_common_32;
+ struct ar_meta_armap_common_64 armap_common_64;
+ uint64_t armap_nsyms;
+};
+
+struct slbt_archive_meta_impl {
+ const struct slbt_driver_ctx * dctx;
+ struct slbt_archive_ctx * actx;
+ size_t ofmtattr;
+ size_t nentries;
+ void * hdrinfov;
+ char * namestrs;
+ const char * symstrs;
+ const char ** symstrv;
+ const char ** mapstrv;
+ off_t * offsetv;
+ struct ar_meta_symbol_info * syminfo;
+ struct ar_meta_symbol_info ** syminfv;
+ struct ar_meta_member_info ** memberv;
+ struct ar_meta_member_info * members;
+ struct ar_armaps_impl armaps;
+ struct slbt_txtfile_ctx * nminfo;
+ struct slbt_archive_meta armeta;
+};
+
+struct ar_meta_member_info * slbt_archive_member_from_offset(
+ struct slbt_archive_meta_impl * meta,
+ off_t offset);
+
+int slbt_ar_parse_primary_armap_bsd_32(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_archive_meta_impl * m);
+
+int slbt_ar_parse_primary_armap_bsd_64(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_archive_meta_impl * m);
+
+int slbt_ar_parse_primary_armap_sysv_32(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_archive_meta_impl * m);
+
+int slbt_ar_parse_primary_armap_sysv_64(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_archive_meta_impl * m);
+
+int slbt_update_mapstrv(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_archive_meta_impl * m);
+
+int slbt_ar_update_syminfo(
+ struct slbt_archive_ctx * actx);
+
+int slbt_ar_update_syminfo_ex(
+ struct slbt_archive_ctx * actx,
+ int fdout);
+
+static inline struct slbt_archive_meta_impl * slbt_archive_meta_ictx(const struct slbt_archive_meta * meta)
+{
+ uintptr_t addr;
+
+ if (meta) {
+ addr = (uintptr_t)meta - offsetof(struct slbt_archive_meta_impl,armeta);
+ return (struct slbt_archive_meta_impl *)addr;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/internal/slibtool_coff_impl.c b/src/internal/slibtool_coff_impl.c
new file mode 100644
index 0000000..ac6a2fd
--- /dev/null
+++ b/src/internal/slibtool_coff_impl.c
@@ -0,0 +1,46 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <string.h>
+#include "slibtool_visibility_impl.h"
+
+slbt_hidden int slbt_coff_qsort_strcmp(const void * a, const void * b)
+{
+ const char * dot;
+ const char * mark;
+ const char * stra;
+ const char * strb;
+ const char ** pstra;
+ const char ** pstrb;
+ char strbufa[4096];
+ char strbufb[4096];
+
+ pstra = (const char **)a;
+ pstrb = (const char **)b;
+
+ stra = *pstra;
+ strb = *pstrb;
+
+ if (!strncmp(*pstra,".weak.",6)) {
+ stra = strbufa;
+ mark = &(*pstra)[6];
+ dot = strchr(mark,'.');
+
+ strncpy(strbufa,mark,dot-mark);
+ strbufa[dot-mark] = '\0';
+ }
+
+ if (!strncmp(*pstrb,".weak.",6)) {
+ strb = strbufb;
+ mark = &(*pstrb)[6];
+ dot = strchr(mark,'.');
+
+ strncpy(strbufb,mark,dot-mark);
+ strbufb[dot-mark] = '\0';
+ }
+
+ return strcmp(stra,strb);
+}
diff --git a/src/internal/slibtool_coff_impl.h b/src/internal/slibtool_coff_impl.h
new file mode 100644
index 0000000..b08c858
--- /dev/null
+++ b/src/internal/slibtool_coff_impl.h
@@ -0,0 +1,6 @@
+#ifndef SLIBTOOL_COFF_IMPL_H
+#define SLIBTOOL_COFF_IMPL_H
+
+int slbt_coff_qsort_strcmp(const void * a, const void * b);
+
+#endif
diff --git a/src/internal/slibtool_dprintf_impl.c b/src/internal/slibtool_dprintf_impl.c
index 434c96d..58c7eed 100644
--- a/src/internal/slibtool_dprintf_impl.c
+++ b/src/internal/slibtool_dprintf_impl.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,8 +11,9 @@
#include <errno.h>
#include "slibtool_dprintf_impl.h"
+#include "slibtool_visibility_impl.h"
-int slbt_dprintf(int fd, const char * fmt, ...)
+slbt_hidden int slbt_dprintf(int fd, const char * fmt, ...)
{
int ret;
int cnt;
diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h
index 270e9d6..429cdc4 100644
--- a/src/internal/slibtool_driver_impl.h
+++ b/src/internal/slibtool_driver_impl.h
@@ -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. */
/*******************************************************************/
@@ -9,13 +9,16 @@
#include <stdint.h>
#include <stdio.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <slibtool/slibtool.h>
#include "slibtool_dprintf_impl.h"
+#include "slibtool_mapfile_impl.h"
+#include "slibtool_visibility_impl.h"
#include "argv/argv.h"
-#define SLBT_OPTV_ELEMENTS 64
+#define SLBT_OPTV_ELEMENTS 128
extern const struct argv_option slbt_default_options[];
@@ -23,8 +26,12 @@ enum app_tags {
TAG_HELP,
TAG_HELP_ALL,
TAG_VERSION,
+ TAG_INFO,
TAG_CONFIG,
+ TAG_MKVARS,
TAG_DUMPMACHINE,
+ TAG_PRINT_AUX_DIR,
+ TAG_PRINT_M4_DIR,
TAG_DEBUG,
TAG_DRY_RUN,
TAG_FEATURES,
@@ -42,6 +49,8 @@ enum app_tags {
TAG_HOST,
TAG_FLAVOR,
TAG_AR,
+ TAG_AS,
+ TAG_NM,
TAG_RANLIB,
TAG_WINDRES,
TAG_DLLTOOL,
@@ -54,11 +63,12 @@ enum app_tags {
TAG_RPATH,
TAG_SYSROOT,
TAG_RELEASE,
+ TAG_OBJECTLIST,
TAG_DLOPEN,
TAG_DLPREOPEN,
TAG_EXPORT_DYNAMIC,
- TAG_EXPSYM_FILE,
- TAG_EXPSYM_REGEX,
+ TAG_EXPSYMS_FILE,
+ TAG_EXPSYMS_REGEX,
TAG_VERSION_INFO,
TAG_VERSION_NUMBER,
TAG_NO_SUPPRESS,
@@ -78,6 +88,36 @@ enum app_tags {
TAG_COMPILER_FLAG,
TAG_VERBATIM_FLAG,
TAG_THREAD_SAFE,
+ TAG_WEAK,
+ /* ar mode */
+ TAG_AR_HELP,
+ TAG_AR_VERSION,
+ TAG_AR_CHECK,
+ TAG_AR_PRINT,
+ TAG_AR_MAPFILE,
+ TAG_AR_DLUNIT,
+ TAG_AR_DLSYMS,
+ TAG_AR_NOSORT,
+ TAG_AR_REGEX,
+ TAG_AR_PRETTY,
+ TAG_AR_POSIX,
+ TAG_AR_YAML,
+ TAG_AR_MERGE,
+ TAG_AR_OUTPUT,
+ TAG_AR_VERBOSE,
+ /* slibtoolize (stoolie) mode */
+ TAG_STLE_VERSION,
+ TAG_STLE_HELP,
+ TAG_STLE_COPY,
+ TAG_STLE_FORCE,
+ TAG_STLE_INSTALL,
+ TAG_STLE_DEBUG,
+ TAG_STLE_DRY_RUN,
+ TAG_STLE_SILENT,
+ TAG_STLE_VERBOSE,
+ TAG_STLE_WARNINGS,
+ TAG_STLE_NO_WARNINGS,
+ TAG_STLE_LTDL,
};
struct slbt_split_vector {
@@ -92,43 +132,251 @@ struct slbt_host_strs {
char * host;
char * flavor;
char * ar;
+ char * as;
+ char * nm;
char * ranlib;
char * windres;
char * dlltool;
char * mdso;
+ char ** ar_argv;
+ char ** as_argv;
+ char ** nm_argv;
+ char ** ranlib_argv;
+ char ** windres_argv;
+ char ** dlltool_argv;
+ char ** mdso_argv;
+};
+
+struct slbt_obj_list {
+ const char * name;
+ void * addr;
+ size_t size;
+ int objc;
+ char ** objv;
};
struct slbt_driver_ctx_impl {
- struct slbt_common_ctx cctx;
- struct slbt_driver_ctx ctx;
- struct slbt_host_strs host;
- struct slbt_host_strs ahost;
- struct slbt_fd_ctx fdctx;
- char * libname;
- char * dargs;
- char ** dargv;
- char ** targv;
- char ** cargv;
- char ** envp;
- struct slbt_error_info**errinfp;
- struct slbt_error_info**erricap;
- struct slbt_error_info *erriptr[64];
- struct slbt_error_info erribuf[64];
+ struct argv_meta * meta;
+ struct slbt_common_ctx cctx;
+ struct slbt_driver_ctx ctx;
+ struct slbt_host_strs host;
+ struct slbt_host_strs ahost;
+ struct slbt_fd_ctx fdctx;
+ struct slbt_map_info lconf;
+ struct slbt_txtfile_ctx * lconfctx;
+ struct slbt_txtfile_ctx * mkvarsctx;
+ struct slbt_obj_list * objlistv;
+
+ struct argv_entry ** dlopenv;
+ size_t ndlopen;
+
+ const struct slbt_archive_ctx * arctx;
+ const char * arpath;
+
+ char * libname;
+ char * dargs;
+ char ** dargv;
+ char ** targv;
+ char ** cargv;
+ char ** envp;
+
+ struct slbt_error_info** errinfp;
+ struct slbt_error_info** erricap;
+ struct slbt_error_info * erriptr[64];
+ struct slbt_error_info erribuf[64];
+};
+
+struct slbt_driver_ctx_alloc {
+ struct slbt_driver_ctx_impl ctx;
+ uint64_t guard;
};
struct slbt_exec_ctx_impl {
- int argc;
- char * args;
- char * shadow;
- char * dsoprefix;
- size_t size;
- struct slbt_exec_ctx ctx;
- int fdwrapper;
- char ** lout[2];
- char ** mout[2];
- char * vbuffer[];
+ const struct slbt_driver_ctx * dctx;
+ 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;
+ char * shadow;
+ char * dsoprefix;
+ size_t size;
+ size_t exts;
+ int fdwrapper;
+ char sbuf[PATH_MAX];
+ char ** lout[2];
+ char ** mout[2];
+ char ** vbuffer;
};
+struct slbt_archive_ctx_impl {
+ const struct slbt_driver_ctx * dctx;
+ const char * path;
+ char * pathbuf;
+ struct slbt_raw_archive map;
+ struct slbt_archive_meta * meta;
+ struct slbt_archive_ctx actx;
+};
+
+struct slbt_symlist_ctx_impl {
+ const struct slbt_driver_ctx * dctx;
+ const char * path;
+ char * pathbuf;
+ char * symstrs;
+ const char ** symstrv;
+ struct slbt_symlist_ctx sctx;
+};
+
+
+struct slbt_txtfile_ctx_impl {
+ const struct slbt_driver_ctx * dctx;
+ const char * path;
+ char * pathbuf;
+ char * txtlines;
+ const char ** txtlinev;
+ struct slbt_txtfile_ctx tctx;
+};
+
+struct slbt_stoolie_ctx_impl {
+ const struct slbt_driver_ctx * dctx;
+ const char * path;
+ char * pathbuf;
+ int fdtgt;
+ int fdaux;
+ int fdm4;
+ const char * auxarg;
+ char * auxbuf;
+ const char * m4arg;
+ char * m4buf;
+ char ** m4argv;
+ struct slbt_txtfile_ctx * acinc;
+ struct slbt_txtfile_ctx * cfgac;
+ struct slbt_txtfile_ctx * makam;
+ struct slbt_stoolie_ctx zctx;
+};
+
+const char * slbt_program_name(const char *);
+
+
+int slbt_optv_init(
+ const struct argv_option[],
+ const struct argv_option **);
+
+
+uint64_t slbt_argv_flags(uint64_t flags);
+
+
+void slbt_argv_scan(
+ char ** argv,
+ const struct argv_option ** optv,
+ struct argv_ctx * ctx,
+ struct argv_meta * meta);
+
+
+struct argv_meta * slbt_argv_get(
+ char **,
+ const struct argv_option **,
+ int flags,
+ int fd);
+
+void slbt_argv_free(struct argv_meta *);
+
+
+void slbt_argv_usage(
+ int fd,
+ const char * header,
+ const struct argv_option **,
+ const char * mode);
+
+
+void slbt_argv_usage_plain(
+ int fd,
+ const char * header,
+ const struct argv_option **,
+ const char * mode);
+
+
+int slbt_driver_usage(
+ int fdout,
+ const char * program,
+ const char * arg,
+ const struct argv_option ** optv,
+ struct argv_meta * meta,
+ struct slbt_split_vector * sargv,
+ struct slbt_obj_list * objlistv,
+ int noclr);
+
+
+int slbt_split_argv(
+ char ** argv,
+ uint64_t flags,
+ struct slbt_split_vector * sargv,
+ struct slbt_obj_list ** aobjlistv,
+ int fderr,
+ int fdcwd);
+
+
+int slbt_init_version_info(
+ struct slbt_driver_ctx_impl * ictx,
+ struct slbt_version_info * verinfo);
+
+
+int slbt_init_host_params(
+ const struct slbt_driver_ctx * dctx,
+ const struct slbt_common_ctx * cctx,
+ struct slbt_host_strs * drvhost,
+ struct slbt_host_params * host,
+ struct slbt_host_params * cfgmeta,
+ const char * cfgmeta_host,
+ const char * cfgmeta_ar,
+ const char * cfgmeta_as,
+ const char * cfgmeta_nm,
+ const char * cfgmeta_ranlib,
+ const char * cfgmeta_dlltool);
+
+
+void slbt_free_host_params(struct slbt_host_strs * host);
+
+
+int slbt_init_link_params(struct slbt_driver_ctx_impl * ctx);
+
+
+void slbt_init_flavor_settings(
+ struct slbt_common_ctx * cctx,
+ const struct slbt_host_params * ahost,
+ struct slbt_flavor_settings * psettings);
+
+
+int slbt_init_ldrpath(
+ struct slbt_common_ctx * cctx,
+ struct slbt_host_params * host);
+
+
+void slbt_reset_placeholders (struct slbt_exec_ctx *);
+
+void slbt_disable_placeholders (struct slbt_exec_ctx *);
+
+int slbt_impl_get_txtfile_ctx(
+ const struct slbt_driver_ctx * dctx,
+ const char * path,
+ int fdsrc,
+ struct slbt_txtfile_ctx ** pctx);
+
+
+static inline struct slbt_archive_ctx_impl * slbt_get_archive_ictx(const struct slbt_archive_ctx * actx)
+{
+ uintptr_t addr;
+
+ if (actx) {
+ addr = (uintptr_t)actx - offsetof(struct slbt_archive_ctx_impl,actx);
+ return (struct slbt_archive_ctx_impl *)addr;
+ }
+
+ return 0;
+}
+
static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct slbt_driver_ctx * dctx)
{
uintptr_t addr;
@@ -141,6 +389,43 @@ static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct sl
return 0;
}
+static inline struct slbt_symlist_ctx_impl * slbt_get_symlist_ictx(const struct slbt_symlist_ctx * sctx)
+{
+ uintptr_t addr;
+
+ if (sctx) {
+ addr = (uintptr_t)sctx - offsetof(struct slbt_symlist_ctx_impl,sctx);
+ return (struct slbt_symlist_ctx_impl *)addr;
+ }
+
+ return 0;
+}
+
+static inline struct slbt_stoolie_ctx_impl * slbt_get_stoolie_ictx(const struct slbt_stoolie_ctx * stctx)
+{
+ uintptr_t addr;
+
+ if (stctx) {
+ addr = (uintptr_t)stctx - offsetof(struct slbt_stoolie_ctx_impl,zctx);
+ return (struct slbt_stoolie_ctx_impl *)addr;
+ }
+
+ return 0;
+}
+
+static inline void slbt_driver_set_arctx(
+ const struct slbt_driver_ctx * dctx,
+ const struct slbt_archive_ctx * arctx,
+ const char * arpath)
+{
+ struct slbt_driver_ctx_impl * ictx;
+
+
+ ictx = slbt_get_driver_ictx(dctx);
+ ictx->arctx = arctx;
+ ictx->arpath = arpath;
+}
+
static inline char ** slbt_driver_envp(const struct slbt_driver_ctx * dctx)
{
struct slbt_driver_ctx_impl * ictx;
@@ -151,42 +436,42 @@ static inline char ** slbt_driver_envp(const struct slbt_driver_ctx * dctx)
static inline int slbt_driver_fdin(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fdin;
}
static inline int slbt_driver_fdout(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fdout;
}
static inline int slbt_driver_fderr(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fderr;
}
static inline int slbt_driver_fdlog(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fdlog;
}
static inline int slbt_driver_fdcwd(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fdcwd;
}
static inline int slbt_driver_fddst(const struct slbt_driver_ctx * dctx)
{
struct slbt_fd_ctx fdctx;
- slbt_get_driver_fdctx(dctx,&fdctx);
+ slbt_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fddst;
}
diff --git a/src/internal/slibtool_errinfo_impl.c b/src/internal/slibtool_errinfo_impl.c
index 5b4291b..6501d84 100644
--- a/src/internal/slibtool_errinfo_impl.c
+++ b/src/internal/slibtool_errinfo_impl.c
@@ -1,14 +1,15 @@
/*******************************************************************/
-/* 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. */
/*******************************************************************/
#include <slibtool/slibtool.h>
#include "slibtool_driver_impl.h"
#include "slibtool_errinfo_impl.h"
+#include "slibtool_visibility_impl.h"
-int slbt_record_error(
+slbt_hidden int slbt_record_error(
const struct slbt_driver_ctx * dctx,
int esyscode,
int elibcode,
diff --git a/src/internal/slibtool_errinfo_impl.h b/src/internal/slibtool_errinfo_impl.h
index 366e067..fa185c8 100644
--- a/src/internal/slibtool_errinfo_impl.h
+++ b/src/internal/slibtool_errinfo_impl.h
@@ -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. */
/*******************************************************************/
diff --git a/src/internal/slibtool_lconf_impl.c b/src/internal/slibtool_lconf_impl.c
index 2b893bb..ffe92b0 100644
--- a/src/internal/slibtool_lconf_impl.c
+++ b/src/internal/slibtool_lconf_impl.c
@@ -1,10 +1,10 @@
-
/*******************************************************************/
-/* 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. */
/*******************************************************************/
+#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
@@ -18,6 +18,8 @@
#include "slibtool_errinfo_impl.h"
#include "slibtool_symlink_impl.h"
#include "slibtool_readlink_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_visibility_impl.h"
enum slbt_lconf_opt {
SLBT_LCONF_OPT_UNKNOWN,
@@ -364,13 +366,21 @@ static int slbt_lconf_trace_result_silent(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
(void)dctx;
(void)fd;
(void)fdat;
(void)lconf;
- return err ? (-1) : fd;
+
+ if (err)
+ return -1;
+
+ if (slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)) <0)
+ return -1;
+
+ return fd;
}
static int slbt_lconf_trace_result_plain(
@@ -378,16 +388,16 @@ static int slbt_lconf_trace_result_plain(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
int fderr;
const char * cpath;
- char path[PATH_MAX];
fderr = slbt_driver_fderr(dctx);
- cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
- ? path : lconf;
+ cpath = !(slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)))
+ ? *pathbuf : lconf;
switch (err) {
case 0:
@@ -426,16 +436,16 @@ static int slbt_lconf_trace_result_annotated(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
int fderr;
const char * cpath;
- char path[PATH_MAX];
fderr = slbt_driver_fderr(dctx);
- cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
- ? path : lconf;
+ cpath = !(slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)))
+ ? *pathbuf : lconf;
switch (err) {
case 0:
@@ -504,7 +514,9 @@ static int slbt_lconf_trace_result_annotated(
static int slbt_lconf_open(
struct slbt_driver_ctx * dctx,
- const char * lconf)
+ const char * lconf,
+ bool fsilent,
+ char (*lconfpath)[PATH_MAX])
{
int fderr;
int fdcwd;
@@ -514,6 +526,7 @@ static int slbt_lconf_open(
struct stat stcwd;
struct stat stparent;
ino_t stinode;
+ const char * mconf;
int (*trace_lconf)(struct slbt_driver_ctx *,
const char *);
@@ -525,14 +538,22 @@ static int slbt_lconf_open(
int,const char *,int,int);
int (*trace_result)(struct slbt_driver_ctx *,
- int,int,const char *,int);
+ int,int,const char *,int,
+ char (*)[PATH_MAX]);
- lconf = lconf ? lconf : "libtool";
fderr = slbt_driver_fderr(dctx);
fdcwd = slbt_driver_fdcwd(dctx);
fdlconfdir = fdcwd;
+ fsilent |= (dctx->cctx->drvflags & SLBT_DRIVER_SILENT);
- if (dctx->cctx->drvflags & SLBT_DRIVER_SILENT) {
+ if (lconf) {
+ mconf = 0;
+ } else {
+ mconf = "slibtool.cfg";
+ lconf = "libtool";
+ }
+
+ if (fsilent) {
trace_lconf = 0;
trace_fstat = slbt_lconf_trace_fstat_silent;
trace_openat = slbt_lconf_trace_openat_silent;
@@ -563,21 +584,35 @@ static int slbt_lconf_open(
trace_result = slbt_lconf_trace_result_plain;
}
- if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
- trace_lconf(dctx,lconf);
+ if (!(dctx->cctx->drvflags & SLBT_DRIVER_DEBUG)) {
+ trace_fstat = slbt_lconf_trace_fstat_silent;
+ trace_openat = slbt_lconf_trace_openat_silent;
+ }
+
+ if (!fsilent) {
+ if (!mconf)
+ trace_lconf(dctx,lconf);
+
slbt_output_fdcwd(dctx);
}
if (lconf && strchr(lconf,'/'))
return ((fdlconf = trace_openat(dctx,fdcwd,lconf,O_RDONLY,0)) < 0)
? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_LCONF_OPEN)
- : trace_result(dctx,fdlconf,fdcwd,lconf,0);
+ : trace_result(dctx,fdlconf,fdcwd,lconf,0,lconfpath);
if (trace_fstat(dctx,fdlconfdir,".",&stcwd) < 0)
return SLBT_SYSTEM_ERROR(dctx,0);
stinode = stcwd.st_ino;
- fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
+ fdlconf = -1;
+
+ if (mconf)
+ if ((fdlconf = trace_openat(dctx,fdlconfdir,mconf,O_RDONLY,0)) >= 0)
+ lconf = mconf;
+
+ if (fdlconf < 0)
+ fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
while (fdlconf < 0) {
fdparent = trace_openat(dctx,fdlconfdir,"../",O_DIRECTORY,0);
@@ -592,52 +627,153 @@ static int slbt_lconf_open(
}
if (stparent.st_dev != stcwd.st_dev) {
- trace_result(dctx,fdparent,fdparent,".",EXDEV);
+ trace_result(dctx,fdparent,fdparent,".",EXDEV,lconfpath);
close(fdparent);
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_OPEN);
}
if (stparent.st_ino == stinode) {
- trace_result(dctx,fdparent,fdparent,".",ELOOP);
+ trace_result(dctx,fdparent,fdparent,".",ELOOP,lconfpath);
close(fdparent);
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_OPEN);
}
fdlconfdir = fdparent;
- fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
stinode = stparent.st_ino;
+
+ if (mconf)
+ if ((fdlconf = trace_openat(dctx,fdlconfdir,mconf,O_RDONLY,0)) >= 0)
+ lconf = mconf;
+
+ if (fdlconf < 0)
+ fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
}
- trace_result(dctx,fdlconf,fdlconfdir,lconf,0);
+ trace_result(dctx,fdlconf,fdlconfdir,lconf,0,lconfpath);
slbt_lconf_close(fdcwd,fdlconfdir);
return fdlconf;
}
-int slbt_get_lconf_flags(
+static int slbt_get_lconf_var(
+ const struct slbt_txtfile_ctx * tctx,
+ const char * var,
+ const char space,
+ char (*val)[PATH_MAX])
+{
+ const char ** pline;
+ const char * mark;
+ const char * match;
+ const char * cap;
+ ssize_t len;
+ int cint;
+
+ /* init */
+ match = 0;
+ pline = tctx->txtlinev;
+ len = strlen(var);
+
+ /* search for ^var= */
+ for (; *pline && !match; ) {
+ if (!strncmp(*pline,var,len)) {
+ match = *pline;
+ } else {
+ pline++;
+ }
+ }
+
+ /* not found? */
+ if (!match) {
+ (*val)[0] = '\0';
+ return 0;
+ }
+
+ /* support a single pair of double quotes */
+ match = &match[len];
+ mark = match;
+
+ if (match[0] == '"') {
+ match++;
+ mark++;
+
+ for (; *mark && (*mark != '"'); )
+ mark++;
+
+ /* unpaired quote? */
+ if (*mark != '"')
+ return -1;
+ } else {
+ for (; *mark && !isspace((cint=*mark)); )
+ mark++;
+ }
+
+ cap = mark;
+
+ /* validate */
+ for (mark=match; mark<cap; mark++) {
+ if ((*mark >= 'a') && (*mark <= 'z'))
+ (void)0;
+
+ else if ((*mark >= 'A') && (*mark <= 'Z'))
+ (void)0;
+
+ else if ((*mark >= '0') && (*mark <= '9'))
+ (void)0;
+
+ else if ((*mark == '+') || (*mark == '-'))
+ (void)0;
+
+ else if ((*mark == '/') || (*mark == '@'))
+ (void)0;
+
+ else if ((*mark == '.') || (*mark == '_'))
+ (void)0;
+
+ else if ((*mark == ':') || (*mark == space))
+ (void)0;
+
+ else
+ return -1;
+ }
+
+ /* all done */
+ memcpy(*val,match,cap-match);
+ (*val)[cap-match] = '\0';
+
+ return 0;
+}
+
+slbt_hidden int slbt_get_lconf_flags(
struct slbt_driver_ctx * dctx,
const char * lconf,
- uint64_t * flags)
+ uint64_t * flags,
+ bool fsilent)
{
+ struct slbt_driver_ctx_impl * ctx;
+ struct slbt_txtfile_ctx * confctx;
int fdlconf;
struct stat st;
void * addr;
- const char * mark;
- const char * cap;
uint64_t optshared;
uint64_t optstatic;
- int optsharedlen;
- int optstaticlen;
- const char * optsharedstr;
- const char * optstaticstr;
+ char val[PATH_MAX];
+
+ /* driver context (ar, ranlib, cc) */
+ ctx = slbt_get_driver_ictx(dctx);
/* open relative libtool script */
- if ((fdlconf = slbt_lconf_open(dctx,lconf)) < 0)
+ if ((fdlconf = slbt_lconf_open(dctx,lconf,fsilent,&val)) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ /* cache the configuration in library friendly form) */
+ if (slbt_lib_get_txtfile_ctx(dctx,val,&ctx->lconfctx) < 0)
return SLBT_NESTED_ERROR(dctx);
+ confctx = ctx->lconfctx;
+
/* map relative libtool script */
if (fstat(fdlconf,&st) < 0)
return SLBT_SYSTEM_ERROR(dctx,0);
@@ -653,78 +789,34 @@ int slbt_get_lconf_flags(
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_MAP);
- mark = addr;
- cap = &mark[st.st_size];
-
/* scan */
optshared = 0;
optstatic = 0;
- optsharedstr = "build_libtool_libs=";
- optstaticstr = "build_old_libs=";
-
- optsharedlen = strlen(optsharedstr);
- optstaticlen = strlen(optstaticstr);
-
- for (; mark && mark<cap; ) {
- if (!optshared && (cap - mark < optsharedlen)) {
- mark = 0;
-
- } else if (!optstatic && (cap - mark < optstaticlen)) {
- mark = 0;
-
- } else if (!optshared && !strncmp(mark,optsharedstr,optsharedlen)) {
- mark += optsharedlen;
-
- if ((cap - mark >= 3)
- && (mark[0]=='n')
- && (mark[1]=='o')
- && (mark[2]=='\n')
- && (mark = &mark[3]))
- optshared = SLBT_DRIVER_DISABLE_SHARED;
-
- else if ((cap - mark >= 4)
- && (mark[0]=='y')
- && (mark[1]=='e')
- && (mark[2]=='s')
- && (mark[3]=='\n')
- && (mark = &mark[4]))
- optshared = SLBT_DRIVER_SHARED;
-
- if (!optshared)
- mark--;
-
- } else if (!optstatic && !strncmp(mark,optstaticstr,optstaticlen)) {
- mark += optstaticlen;
-
- if ((cap - mark >= 3)
- && (mark[0]=='n')
- && (mark[1]=='o')
- && (mark[2]=='\n')
- && (mark = &mark[3]))
- optstatic = SLBT_DRIVER_DISABLE_STATIC;
-
- else if ((cap - mark >= 4)
- && (mark[0]=='y')
- && (mark[1]=='e')
- && (mark[2]=='s')
- && (mark[3]=='\n')
- && (mark = &mark[4]))
- optstatic = SLBT_DRIVER_STATIC;
-
- if (!optstatic)
- mark--;
- } else {
- for (; (mark<cap) && (*mark!='\n'); )
- mark++;
- mark++;
- }
+ /* shared libraries option */
+ if (slbt_get_lconf_var(confctx,"build_libtool_libs=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
- if (optshared && optstatic)
- mark = 0;
+ if (!strcmp(val,"yes")) {
+ optshared = SLBT_DRIVER_SHARED;
+
+ } else if (!strcmp(val,"no")) {
+ optshared = SLBT_DRIVER_DISABLE_SHARED;
}
- munmap(addr,st.st_size);
+
+ /* static libraries option */
+ if (slbt_get_lconf_var(confctx,"build_old_libs=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (!strcmp(val,"yes")) {
+ optstatic = SLBT_DRIVER_STATIC;
+
+ } else if (!strcmp(val,"no")) {
+ optstatic = SLBT_DRIVER_DISABLE_STATIC;
+ }
if (!optshared || !optstatic)
return SLBT_CUSTOM_ERROR(
@@ -732,5 +824,89 @@ int slbt_get_lconf_flags(
*flags = optshared | optstatic;
+
+ /* host */
+ if (!ctx->cctx.host.host) {
+ if (slbt_get_lconf_var(confctx,"host=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.host = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.host = ctx->host.host;
+ }
+
+
+ /* ar tool */
+ if (!ctx->cctx.host.ar) {
+ if (slbt_get_lconf_var(confctx,"AR=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.ar = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ar = ctx->host.ar;
+ }
+
+
+ /* nm tool */
+ if (!ctx->cctx.host.nm) {
+ if (slbt_get_lconf_var(confctx,"NM=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.nm = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.nm = ctx->host.nm;
+ }
+
+
+ /* ranlib tool */
+ if (!ctx->cctx.host.ranlib) {
+ if (slbt_get_lconf_var(confctx,"RANLIB=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.ranlib = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ranlib = ctx->host.ranlib;
+ }
+
+
+ /* as tool (optional) */
+ if (!ctx->cctx.host.as) {
+ if (slbt_get_lconf_var(confctx,"AS=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.as = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+
+ ctx->cctx.host.as = ctx->host.as;
+ }
+
+
+ /* dlltool tool (optional) */
+ if (!ctx->cctx.host.dlltool) {
+ if (slbt_get_lconf_var(confctx,"DLLTOOL=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.dlltool = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.dlltool = ctx->host.dlltool;
+ }
+
+
+ /* all done */
+ ctx->lconf.addr = addr;
+ ctx->lconf.size = st.st_size;
+
return 0;
}
diff --git a/src/internal/slibtool_lconf_impl.h b/src/internal/slibtool_lconf_impl.h
index d2bd44c..05c7537 100644
--- a/src/internal/slibtool_lconf_impl.h
+++ b/src/internal/slibtool_lconf_impl.h
@@ -8,6 +8,7 @@ struct slbt_driver_ctx;
int slbt_get_lconf_flags(
struct slbt_driver_ctx * dctx,
const char * lconf,
- uint64_t * flags);
+ uint64_t * flags,
+ bool fsilent);
#endif
diff --git a/src/internal/slibtool_libmeta_impl.c b/src/internal/slibtool_libmeta_impl.c
index 58f582f..17e090c 100644
--- a/src/internal/slibtool_libmeta_impl.c
+++ b/src/internal/slibtool_libmeta_impl.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. */
/*******************************************************************/
@@ -13,14 +13,15 @@
#include "slibtool_dprintf_impl.h"
#include "slibtool_errinfo_impl.h"
#include "slibtool_metafile_impl.h"
+#include "slibtool_visibility_impl.h"
static int slbt_create_default_library_wrapper(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
- char * arname,
- char * soname,
- char * soxyz,
- char * solnk)
+ const char * arname,
+ const char * soname,
+ const char * soxyz,
+ const char * solnk)
{
int ret;
int fdout;
@@ -28,6 +29,7 @@ static int slbt_create_default_library_wrapper(
const char * base;
bool fnover;
bool fvernum;
+ bool fspace;
int current;
int revision;
int age;
@@ -54,7 +56,8 @@ static int slbt_create_default_library_wrapper(
fnover = !!(dctx->cctx->drvflags & SLBT_DRIVER_AVOID_VERSION);
fvernum = !!(dctx->cctx->verinfo.vernumber);
- verinfo = slbt_source_version();
+ fspace = !!soname[0];
+ verinfo = slbt_api_source_version();
/* wrapper header */
header = "libtool compatible library wrapper\n";
@@ -67,7 +70,7 @@ static int slbt_create_default_library_wrapper(
"# [commit reference: %s]\n\n"
"dlname='%s'\n"
- "library_names='%s %s %s'\n"
+ "library_names='%s%s%s%s%s'\n"
"old_library='%s'\n\n"
"inherited_linker_flags='%s'\n"
@@ -99,7 +102,9 @@ static int slbt_create_default_library_wrapper(
/* library_names */
fnover ? solnk : soxyz,
+ fspace ? " " : "",
fnover ? solnk : soname,
+ fspace ? " " : "",
solnk,
/* old_library */
@@ -130,16 +135,17 @@ static int slbt_create_default_library_wrapper(
static int slbt_create_compatible_library_wrapper(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
- char * arname,
- char * soname,
- char * soxyz,
- char * solnk)
+ const char * arname,
+ const char * soname,
+ const char * soxyz,
+ const char * solnk)
{
int ret;
int fdout;
const char * base;
bool fnover;
bool fvernum;
+ bool fspace;
int current;
int revision;
int age;
@@ -173,7 +179,8 @@ static int slbt_create_compatible_library_wrapper(
fnover = !!(dctx->cctx->drvflags & SLBT_DRIVER_AVOID_VERSION);
fvernum = !!(dctx->cctx->verinfo.vernumber);
- verinfo = slbt_source_version();
+ fspace = !!soname[0];
+ verinfo = slbt_api_source_version();
/* wrapper content */
ret = slbt_dprintf(fdout,
@@ -188,7 +195,7 @@ static int slbt_create_compatible_library_wrapper(
"dlname='%s'\n\n"
"# Names of this library.\n"
- "library_names='%s %s %s'\n\n"
+ "library_names='%s%s%s%s%s'\n\n"
"# The name of the static archive.\n"
"old_library='%s'\n\n"
@@ -233,7 +240,9 @@ static int slbt_create_compatible_library_wrapper(
/* library_names */
fnover ? solnk : soxyz,
+ fspace ? " " : "",
fnover ? solnk : soname,
+ fspace ? " " : "",
solnk,
/* old_library */
@@ -266,14 +275,24 @@ static int slbt_create_compatible_library_wrapper(
return (ret < 0) ? SLBT_SYSTEM_ERROR(dctx,0) : 0;
}
-int slbt_create_library_wrapper(
+slbt_hidden int slbt_create_library_wrapper(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
- char * arname,
- char * soname,
- char * soxyz,
- char * solnk)
+ const char * arname,
+ const char * soname,
+ const char * soxyz,
+ const char * solnk)
{
+ if (!arname) {
+ arname = "";
+ }
+
+ if (!soname) {
+ soname = "";
+ soxyz = "";
+ solnk = "";
+ }
+
if (dctx->cctx->drvflags & SLBT_DRIVER_LEGABITS)
return slbt_create_compatible_library_wrapper(
dctx,ectx,arname,soxyz,soname,solnk);
diff --git a/src/internal/slibtool_linkcmd_impl.h b/src/internal/slibtool_linkcmd_impl.h
new file mode 100644
index 0000000..e1b384e
--- /dev/null
+++ b/src/internal/slibtool_linkcmd_impl.h
@@ -0,0 +1,89 @@
+#ifndef SLIBTOOL_LINKCMD_IMPL_H
+#define SLIBTOOL_LINKCMD_IMPL_H
+
+struct slbt_deps_meta {
+ char ** altv;
+ char * args;
+ int depscnt;
+ int infolen;
+};
+
+int slbt_get_deps_meta(
+ const struct slbt_driver_ctx * dctx,
+ char * libfilename,
+ int fexternal,
+ struct slbt_deps_meta * depsmeta);
+
+int slbt_exec_link_create_dep_file(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ char ** altv,
+ const char * libfilename,
+ bool farchive);
+
+bool slbt_adjust_object_argument(
+ char * arg,
+ bool fpic,
+ bool fany,
+ int fdcwd);
+
+bool slbt_adjust_wrapper_argument(
+ char * arg,
+ bool fpic,
+ const char * suffix);
+
+int slbt_adjust_linker_argument(
+ const struct slbt_driver_ctx * dctx,
+ char * arg,
+ char ** xarg,
+ bool fpic,
+ const char * dsosuffix,
+ const char * arsuffix,
+ struct slbt_deps_meta * depsmeta);
+
+int slbt_exec_link_adjust_argument_vector(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ struct slbt_deps_meta * depsmeta,
+ const char * cwd,
+ bool flibrary);
+
+int slbt_exec_link_finalize_argument_vector(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx);
+
+int slbt_exec_link_create_host_tag(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ char * deffilename);
+
+int slbt_exec_link_create_import_library(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ char * impfilename,
+ char * deffilename,
+ char * soname);
+
+int slbt_exec_link_create_archive(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ const char * arfilename,
+ bool fpic,
+ bool fdep);
+
+int slbt_exec_link_create_library(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ const char * dsobasename,
+ const char * dsofilename,
+ const char * relfilename,
+ bool fardlopen,
+ bool fpic);
+
+
+int slbt_exec_link_create_executable(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ const char * exefilename);
+
+#endif
diff --git a/src/internal/slibtool_m4fake_impl.c b/src/internal/slibtool_m4fake_impl.c
new file mode 100644
index 0000000..3bab8c8
--- /dev/null
+++ b/src/internal/slibtool_m4fake_impl.c
@@ -0,0 +1,142 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <string.h>
+#include <limits.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+#include "slibtool_snprintf_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "slibtool_visibility_impl.h"
+#include "slibtool_m4fake_impl.h"
+
+slbt_hidden int slbt_m4fake_expand_cmdarg(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_txtfile_ctx * sctx,
+ const char * cmdname,
+ char (*argbuf)[PATH_MAX])
+{
+ const char ** pline;
+ size_t slen;
+ const char * mark;
+ const char * match;
+ const char * cap;
+ int fquote;
+ char varbuf[PATH_MAX];
+ char strbuf[PATH_MAX];
+
+ memset(*argbuf,0,sizeof(*argbuf));
+
+ slen = strlen(cmdname);
+ pline = sctx->txtlinev;
+ match = 0;
+
+ for (; !match && *pline; ) {
+ if (!strncmp(*pline,cmdname,slen)) {
+ if ((*pline)[slen] == '(') {
+ mark = &(*pline)[slen];
+ cap = ++mark;
+
+ for (fquote=0; !match && *cap; ) {
+ if (*cap == '[')
+ fquote++;
+
+ else if ((*cap == ']') && fquote)
+ fquote--;
+
+ else if ((*cap == ')') && !fquote)
+ match = cap;
+
+ if (!match)
+ cap++;
+ }
+
+ if (!match)
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_FLOW_ERROR);
+ }
+ }
+
+ if (!match)
+ pline++;
+ }
+
+ if (!match)
+ return 0;
+
+ strncpy(strbuf,mark,cap-mark);
+ strbuf[cap-mark] = '\0';
+
+ mark = strbuf;
+ slen = strlen(mark);
+
+ if ((mark[0] == '[') && (mark[--slen] == ']')) {
+ strcpy(*argbuf,++mark);
+ (*argbuf)[--slen] = '\0';
+ return 0;
+ }
+
+ if (slbt_snprintf(
+ varbuf,sizeof(varbuf),
+ "AC_DEFUN([%s],",
+ strbuf) < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ slen = strlen(varbuf);
+
+ for (--pline; pline >= sctx->txtlinev; pline--) {
+ if (!strncmp(*pline,varbuf,slen)) {
+ mark = &(*pline)[slen];
+ cap = mark;
+ match = 0;
+
+ for (fquote=0; !match && *cap; ) {
+ if (*cap == '[')
+ fquote++;
+
+ else if ((*cap == ']') && fquote)
+ fquote--;
+
+ else if ((*cap == ')') && !fquote)
+ match = cap;
+
+ if (!match)
+ cap++;
+ }
+
+ if (!match)
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_FLOW_ERROR);
+
+ strncpy(strbuf,mark,cap-mark);
+ strbuf[cap-mark] = '\0';
+
+ mark = strbuf;
+ slen = strlen(mark);
+
+ if ((mark[0] == '[') && (mark[--slen] == ']')) {
+ strcpy(*argbuf,++mark);
+ (*argbuf)[--slen] = '\0';
+ return 0;
+ }
+
+ if (slbt_snprintf(
+ varbuf,sizeof(varbuf),
+ "AC_DEFUN([%s],",
+ strbuf) < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ slen = strlen(varbuf);
+ }
+ }
+
+ strcpy(*argbuf,strbuf);
+
+ return 0;
+}
diff --git a/src/internal/slibtool_m4fake_impl.h b/src/internal/slibtool_m4fake_impl.h
new file mode 100644
index 0000000..8bb2b5f
--- /dev/null
+++ b/src/internal/slibtool_m4fake_impl.h
@@ -0,0 +1,12 @@
+#ifndef SLIBTOOL_M4FAKE_IMPL_H
+#define SLIBTOOL_M4FAKE_IMPL_H
+
+#include <slibtool/slibtool.h>
+
+int slbt_m4fake_expand_cmdarg(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_txtfile_ctx * sctx,
+ const char * cmdname,
+ char (*argbuf)[PATH_MAX]);
+
+#endif
diff --git a/src/internal/slibtool_mapfile_impl.c b/src/internal/slibtool_mapfile_impl.c
index 5df006b..5a4fcff 100644
--- a/src/internal/slibtool_mapfile_impl.c
+++ b/src/internal/slibtool_mapfile_impl.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. */
/*******************************************************************/
@@ -15,6 +15,7 @@
#include "slibtool_errinfo_impl.h"
#include "slibtool_mapfile_impl.h"
+#include "slibtool_visibility_impl.h"
static void slbt_munmap(void * addr, size_t size)
{
@@ -23,7 +24,7 @@ static void slbt_munmap(void * addr, size_t size)
}
}
-struct slbt_map_info * slbt_map_file(
+slbt_hidden struct slbt_map_info * slbt_map_file(
int fdat,
const char * path,
uint32_t flags)
@@ -82,13 +83,13 @@ struct slbt_map_info * slbt_map_file(
return mapinfo;
}
-void slbt_unmap_file(struct slbt_map_info * mapinfo)
+slbt_hidden void slbt_unmap_file(struct slbt_map_info * mapinfo)
{
slbt_munmap(mapinfo->addr,mapinfo->size);
free(mapinfo);
}
-int slbt_mapped_readline(
+slbt_hidden int slbt_mapped_readline(
const struct slbt_driver_ctx * dctx,
struct slbt_map_info * mapinfo,
char * buf,
diff --git a/src/internal/slibtool_metafile_impl.h b/src/internal/slibtool_metafile_impl.h
index bd78b09..b415c05 100644
--- a/src/internal/slibtool_metafile_impl.h
+++ b/src/internal/slibtool_metafile_impl.h
@@ -10,9 +10,9 @@ int slbt_create_object_wrapper(
int slbt_create_library_wrapper(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
- char * arname,
- char * soname,
- char * soxyz,
- char * solnk);
+ const char * arname,
+ const char * soname,
+ const char * soxyz,
+ const char * solnk);
#endif
diff --git a/src/internal/slibtool_mkdir_impl.h b/src/internal/slibtool_mkdir_impl.h
index 018f5c3..41943f1 100644
--- a/src/internal/slibtool_mkdir_impl.h
+++ b/src/internal/slibtool_mkdir_impl.h
@@ -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. */
/*******************************************************************/
diff --git a/src/internal/slibtool_mkvars_impl.c b/src/internal/slibtool_mkvars_impl.c
new file mode 100644
index 0000000..155036a
--- /dev/null
+++ b/src/internal/slibtool_mkvars_impl.c
@@ -0,0 +1,245 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "slibtool_mkvars_impl.h"
+#include "slibtool_driver_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "slibtool_symlink_impl.h"
+#include "slibtool_readlink_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_visibility_impl.h"
+
+static int slbt_get_mkvars_var(
+ const struct slbt_driver_ctx * dctx,
+ const struct slbt_txtfile_ctx * tctx,
+ const char * var,
+ const char space,
+ char (*val)[PATH_MAX])
+{
+ const char ** pline;
+ const char * mark;
+ const char * match;
+ char * ch;
+ ssize_t len;
+ int cint;
+
+ /* init */
+ match = 0;
+ len = strlen(var);
+
+ /* search for ^var= */
+ for (pline=tctx->txtlinev; !match && *pline; pline++) {
+ if (!strncmp(*pline,var,len)) {
+ if (isspace((*pline)[len]) || ((*pline)[len] == '=')) {
+ mark = &(*pline)[len];
+
+ for (; isspace(cint = *mark); )
+ mark++;
+
+ if (mark[0] != '=')
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_MKVARS_PARSE);
+
+ mark++;
+
+ for (; isspace(cint = *mark); )
+ mark++;
+
+ match = mark;
+ }
+ }
+ }
+
+ /* not found? */
+ if (!match) {
+ (*val)[0] = '\0';
+ return 0;
+ }
+
+ /* special case the SLIBTOOL make variable */
+ if (!strcmp(var,"SLIBTOOL")) {
+ mark = match;
+ ch = *val;
+
+ for (; *mark; ) {
+ if (isspace(cint = *mark)) {
+ *ch = '\0';
+ return 0;
+ }
+
+ *ch++ = *mark++;
+ }
+ }
+
+ /* validate */
+ for (mark=match; *mark; mark++) {
+ if ((*mark >= 'a') && (*mark <= 'z'))
+ (void)0;
+
+ else if ((*mark >= 'A') && (*mark <= 'Z'))
+ (void)0;
+
+ else if ((*mark >= '0') && (*mark <= '9'))
+ (void)0;
+
+ else if ((*mark == '+') || (*mark == '-'))
+ (void)0;
+
+ else if ((*mark == '/') || (*mark == '@'))
+ (void)0;
+
+ else if ((*mark == '.') || (*mark == '_'))
+ (void)0;
+
+ else if ((*mark == ':') || (*mark == space))
+ (void)0;
+
+ else
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_MKVARS_PARSE);
+ }
+
+ /* all done */
+ strcpy(*val,match);
+
+ return 0;
+}
+
+slbt_hidden int slbt_get_mkvars_flags(
+ struct slbt_driver_ctx * dctx,
+ const char * mkvars,
+ uint64_t * flags)
+{
+ struct slbt_driver_ctx_impl * ctx;
+ struct slbt_txtfile_ctx * confctx;
+ char * dash;
+ uint64_t optshared;
+ uint64_t optstatic;
+ char val[PATH_MAX];
+
+ /* driver context (ar, ranlib, cc) */
+ ctx = slbt_get_driver_ictx(dctx);
+
+ /* cache the makefile in library friendly form) */
+ if (slbt_lib_get_txtfile_ctx(dctx,mkvars,&ctx->mkvarsctx) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ confctx = ctx->mkvarsctx;
+
+ /* scan */
+ optshared = 0;
+ optstatic = 0;
+
+ /* slibtool */
+ if (slbt_get_mkvars_var(dctx,confctx,"SLIBTOOL",0,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if ((dash = strrchr(val,'-'))) {
+ if (!strcmp(dash,"-shared")) {
+ optshared = SLBT_DRIVER_SHARED;
+ optstatic = SLBT_DRIVER_DISABLE_STATIC;
+
+ } else if (!strcmp(dash,"-static")) {
+ optshared = SLBT_DRIVER_DISABLE_SHARED;
+ optstatic = SLBT_DRIVER_STATIC;
+ } else {
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_MKVARS_PARSE);
+ }
+ } else if (!strcmp(val,"false")) {
+ optshared = SLBT_DRIVER_DISABLE_SHARED;
+ optstatic = SLBT_DRIVER_DISABLE_STATIC;
+ } else {
+ optshared = SLBT_DRIVER_SHARED;
+ optstatic = SLBT_DRIVER_STATIC;
+ }
+
+ *flags = optshared | optstatic;
+
+ /* host */
+ if (!ctx->cctx.host.host) {
+ if (slbt_get_mkvars_var(dctx,confctx,"host",0,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.host = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.host = ctx->host.host;
+ }
+
+
+ /* ar tool */
+ if (!ctx->cctx.host.ar) {
+ if (slbt_get_mkvars_var(dctx,confctx,"AR",0x20,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.ar = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ar = ctx->host.ar;
+ }
+
+
+ /* nm tool */
+ if (!ctx->cctx.host.nm) {
+ if (slbt_get_mkvars_var(dctx,confctx,"NM",0x20,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.nm = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.nm = ctx->host.nm;
+ }
+
+
+ /* ranlib tool */
+ if (!ctx->cctx.host.ranlib) {
+ if (slbt_get_mkvars_var(dctx,confctx,"RANLIB",0x20,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.ranlib = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ranlib = ctx->host.ranlib;
+ }
+
+
+ /* as tool (optional) */
+ if (!ctx->cctx.host.as) {
+ if (slbt_get_mkvars_var(dctx,confctx,"AS",0x20,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.as = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+
+ ctx->cctx.host.as = ctx->host.as;
+ }
+
+
+ /* dlltool tool (optional) */
+ if (!ctx->cctx.host.dlltool) {
+ if (slbt_get_mkvars_var(dctx,confctx,"DLLTOOL",0x20,&val) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (val[0] && !(ctx->host.dlltool = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.dlltool = ctx->host.dlltool;
+ }
+
+
+ /* all done */
+ return 0;
+}
diff --git a/src/internal/slibtool_mkvars_impl.h b/src/internal/slibtool_mkvars_impl.h
new file mode 100644
index 0000000..00ebd99
--- /dev/null
+++ b/src/internal/slibtool_mkvars_impl.h
@@ -0,0 +1,13 @@
+#ifndef SLIBTOOL_MKVARS_IMPL_H
+#define SLIBTOOL_MKVARS_IMPL_H
+
+#include <stdint.h>
+
+struct slbt_driver_ctx;
+
+int slbt_get_mkvars_flags(
+ struct slbt_driver_ctx * dctx,
+ const char * mkvars,
+ uint64_t * flags);
+
+#endif
diff --git a/src/internal/slibtool_objlist_impl.c b/src/internal/slibtool_objlist_impl.c
new file mode 100644
index 0000000..9f25529
--- /dev/null
+++ b/src/internal/slibtool_objlist_impl.c
@@ -0,0 +1,83 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "slibtool_driver_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "slibtool_mapfile_impl.h"
+#include "slibtool_objlist_impl.h"
+#include "slibtool_visibility_impl.h"
+
+slbt_hidden int slbt_objlist_read(
+ int fdcwd,
+ struct slbt_obj_list * objlist)
+{
+ struct slbt_map_info * mapinfo;
+ int objc;
+ char ** objv;
+ char * src;
+ char * dst;
+ char * mark;
+ int skip;
+
+ /* temporarily map the object list */
+ if (!(mapinfo = slbt_map_file(fdcwd,objlist->name,SLBT_MAP_INPUT)))
+ return -1;
+
+ /* object list, cautionary null termination, vector null termination */
+ objlist->size = mapinfo->size;
+ objlist->size++;
+ objlist->size++;
+
+ if (!(objlist->addr = calloc(1,objlist->size))) {
+ slbt_unmap_file(mapinfo);
+ return -1;
+ }
+
+ /* object list file to normalized object strings */
+ objc = 0;
+ skip = true;
+
+ for (src=mapinfo->addr,dst=objlist->addr; src<mapinfo->cap; src++) {
+ if (!*src || (*src==' ') || (*src=='\n') || (*src=='\r')) {
+ if (!skip)
+ *dst++ = 0;
+
+ skip = true;
+ } else {
+ *dst++ = *src;
+
+ objc += !!skip;
+ skip = false;
+ }
+ }
+
+ /* object vector */
+ objlist->objc = objc;
+
+ if (!(objlist->objv = calloc(++objc,sizeof(char *)))) {
+ free(objlist->addr);
+ slbt_unmap_file(mapinfo);
+ return -1;
+ }
+
+ for (objv=objlist->objv,mark=objlist->addr; *mark; objv++) {
+ *objv = mark;
+ mark += strlen(mark) + 1;
+ }
+
+ slbt_unmap_file(mapinfo);
+
+ return 0;
+}
diff --git a/src/internal/slibtool_objlist_impl.h b/src/internal/slibtool_objlist_impl.h
new file mode 100644
index 0000000..cb11d07
--- /dev/null
+++ b/src/internal/slibtool_objlist_impl.h
@@ -0,0 +1,10 @@
+#ifndef SLIBTOOL_OBJLIST_IMPL_H
+#define SLIBTOOL_OBJLIST_IMPL_H
+
+#include "slibtool_driver_impl.h"
+
+int slbt_objlist_read(
+ int fdcwd,
+ struct slbt_obj_list * objlist);
+
+#endif
diff --git a/src/internal/slibtool_objmeta_impl.c b/src/internal/slibtool_objmeta_impl.c
index 9d4902c..768cc96 100644
--- a/src/internal/slibtool_objmeta_impl.c
+++ b/src/internal/slibtool_objmeta_impl.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,6 +11,7 @@
#include "slibtool_dprintf_impl.h"
#include "slibtool_errinfo_impl.h"
#include "slibtool_metafile_impl.h"
+#include "slibtool_visibility_impl.h"
static int slbt_create_default_object_wrapper(
const struct slbt_driver_ctx * dctx,
@@ -27,7 +28,7 @@ static int slbt_create_default_object_wrapper(
0644)) < 0)
return SLBT_SYSTEM_ERROR(dctx,ectx->ltobjname);
- verinfo = slbt_source_version();
+ verinfo = slbt_api_source_version();
ret = slbt_dprintf(fdout,
"# libtool compatible object wrapper\n"
@@ -68,7 +69,7 @@ static int slbt_create_compatible_object_wrapper(
0644)) < 0)
return SLBT_SYSTEM_ERROR(dctx, ectx->ltobjname);
- verinfo = slbt_source_version();
+ verinfo = slbt_api_source_version();
ret = slbt_dprintf(fdout,
"# %s - a libtool object file\n"
@@ -101,7 +102,7 @@ static int slbt_create_compatible_object_wrapper(
return (ret < 0) ? SLBT_SYSTEM_ERROR(dctx,0) : 0;
}
-int slbt_create_object_wrapper(
+slbt_hidden int slbt_create_object_wrapper(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx)
{
diff --git a/src/internal/slibtool_pecoff_impl.c b/src/internal/slibtool_pecoff_impl.c
new file mode 100644
index 0000000..590fafc
--- /dev/null
+++ b/src/internal/slibtool_pecoff_impl.c
@@ -0,0 +1,16 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <string.h>
+
+#include "slibtool_visibility_impl.h"
+
+slbt_hidden int slbt_is_strong_coff_symbol(const char * sym)
+{
+ return strncmp(sym,"__imp_",6)
+ && strncmp(sym,".weak.",6)
+ && strncmp(sym,".refptr.",8);
+}
diff --git a/src/internal/slibtool_pecoff_impl.h b/src/internal/slibtool_pecoff_impl.h
new file mode 100644
index 0000000..e18b5af
--- /dev/null
+++ b/src/internal/slibtool_pecoff_impl.h
@@ -0,0 +1,6 @@
+#ifndef SLIBTOOL_PECOFF_IMPL_H
+#define SLIBTOOL_PECOFF_IMPL_H
+
+int slbt_is_strong_coff_symbol(const char *);
+
+#endif
diff --git a/src/internal/slibtool_readlink_impl.h b/src/internal/slibtool_readlink_impl.h
index 19aafa2..378ed5c 100644
--- a/src/internal/slibtool_readlink_impl.h
+++ b/src/internal/slibtool_readlink_impl.h
@@ -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. */
/*******************************************************************/
diff --git a/src/internal/slibtool_realpath_impl.c b/src/internal/slibtool_realpath_impl.c
new file mode 100644
index 0000000..63fc3c4
--- /dev/null
+++ b/src/internal/slibtool_realpath_impl.c
@@ -0,0 +1,100 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <slibtool/slibtool.h>
+
+#include "slibtool_driver_impl.h"
+#include "slibtool_readlink_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_visibility_impl.h"
+
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
+#ifdef _MIDIPIX_ABI
+#include <sys/fs.h>
+#endif
+
+#ifndef ENOTSUP
+#define ENOTSUP EOPNOTSUPP
+#endif
+
+slbt_hidden int slbt_realpath(
+ int fdat,
+ const char * path,
+ int options,
+ char * buf,
+ size_t buflen)
+{
+ int ret;
+ int fd;
+ int fdproc;
+ struct stat st;
+ struct stat stproc;
+ char procfspath[36];
+
+ /* common validation */
+ if (!buf || (options & O_CREAT)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* framework-based wrapper */
+#ifdef _MIDIPIX_ABI
+ return __fs_rpath(fdat,path,options,buf,buflen);
+#endif
+
+#ifdef SYS___realpathat
+ return syscall(SYS___realpathat,fdat,path,buf,buflen,0);
+#endif
+
+ /* buflen */
+ if (buflen < PATH_MAX) {
+ errno = ENOBUFS;
+ return -1;
+ }
+
+ /* AT_FDCWD */
+ if (fdat == AT_FDCWD) {
+ return realpath(path,buf) ? 0 : -1;
+ }
+
+ /* /proc/self/fd */
+ if ((fd = openat(fdat,path,options,0)) < 0)
+ return -1;
+
+ sprintf(procfspath,"/proc/self/fd/%d",fd);
+
+ if (slbt_readlinkat(fdat,procfspath,buf,buflen)) {
+ close(fd);
+ return -1;
+ }
+
+ if ((fdproc = openat(AT_FDCWD,buf,options|O_NOFOLLOW,0)) < 0) {
+ close(fd);
+ errno = ELOOP;
+ return -1;
+ }
+
+ ret = fstat(fd,&st) || fstat(fdproc,&stproc);
+
+ close(fd);
+ close(fdproc);
+
+ if (ret || (st.st_dev != stproc.st_dev) || (st.st_ino != stproc.st_ino)) {
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/internal/slibtool_realpath_impl.h b/src/internal/slibtool_realpath_impl.h
new file mode 100644
index 0000000..01df1c1
--- /dev/null
+++ b/src/internal/slibtool_realpath_impl.h
@@ -0,0 +1,13 @@
+#ifndef SLIBTOOL_REALPATH_IMPL_H
+#define SLIBTOOL_REALPATH_IMPL_H
+
+#include <stdlib.h>
+
+int slbt_realpath(
+ int fdat,
+ const char * path,
+ int options,
+ char * buf,
+ size_t buflen);
+
+#endif
diff --git a/src/internal/slibtool_snprintf_impl.c b/src/internal/slibtool_snprintf_impl.c
new file mode 100644
index 0000000..84e01f0
--- /dev/null
+++ b/src/internal/slibtool_snprintf_impl.c
@@ -0,0 +1,40 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "slibtool_snprintf_impl.h"
+#include "slibtool_visibility_impl.h"
+
+
+/*****************************************************************/
+/* snprintf() wrapper that simplifies usage via the following: */
+/* */
+/* (1) fail (return a negative result) in case the buffer is */
+/* not sufficiently large for the formatted string plus */
+/* the terminating null character. */
+/* */
+/**********************************************************/
+
+
+slbt_hidden int slbt_snprintf(char * buf, size_t buflen, const char * fmt, ...)
+{
+ va_list ap;
+ size_t nbytes;
+
+ va_start(ap,fmt);
+ nbytes = vsnprintf(buf,buflen,fmt,ap);
+ va_end(ap);
+
+ if (nbytes >= buflen)
+ return -1;
+
+ return nbytes;
+}
diff --git a/src/internal/slibtool_snprintf_impl.h b/src/internal/slibtool_snprintf_impl.h
new file mode 100644
index 0000000..87fa65a
--- /dev/null
+++ b/src/internal/slibtool_snprintf_impl.h
@@ -0,0 +1,6 @@
+#ifndef SLIBTOOL_SNPRINTF_IMPL_H
+#define SLIBTOOL_SNPRINTF_IMPL_H
+
+int slbt_snprintf(char * buf, size_t buflen, const char * fmt, ...);
+
+#endif
diff --git a/src/internal/slibtool_spawn_impl.h b/src/internal/slibtool_spawn_impl.h
index d6b18cb..aa4ea35 100644
--- a/src/internal/slibtool_spawn_impl.h
+++ b/src/internal/slibtool_spawn_impl.h
@@ -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. */
/*******************************************************************/
@@ -30,6 +30,12 @@
#include <spawn.h>
#endif
+#ifdef __midipix__
+static pid_t slbt_fork(void) {return vfork();}
+#else
+static pid_t slbt_fork(void) {return fork();}
+#endif
+
static inline int slbt_spawn(
struct slbt_exec_ctx * ectx,
bool fwait)
@@ -56,6 +62,8 @@ static inline int slbt_spawn(
#endif
+ (void)slbt_fork;
+
if (pid < 0) {
ectx->pid = pid;
ectx->exitcode = errno;
diff --git a/src/internal/slibtool_stoolie_impl.h b/src/internal/slibtool_stoolie_impl.h
new file mode 100644
index 0000000..43d70a5
--- /dev/null
+++ b/src/internal/slibtool_stoolie_impl.h
@@ -0,0 +1,15 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#ifndef SLIBTOOL_STOOLIE_IMPL_H
+#define SLIBTOOL_STOOLIE_IMPL_H
+
+#include "argv/argv.h"
+#include <slibtool/slibtool.h>
+
+extern const struct argv_option slbt_stoolie_options[];
+
+#endif
diff --git a/src/internal/slibtool_symlink_impl.c b/src/internal/slibtool_symlink_impl.c
index bb38333..bb117e2 100644
--- a/src/internal/slibtool_symlink_impl.c
+++ b/src/internal/slibtool_symlink_impl.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. */
/*******************************************************************/
@@ -13,26 +13,32 @@
#include "slibtool_errinfo_impl.h"
#include "slibtool_symlink_impl.h"
#include "slibtool_readlink_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_snprintf_impl.h"
+#include "slibtool_visibility_impl.h"
#define SLBT_DEV_NULL_FLAGS (SLBT_DRIVER_ALL_STATIC \
| SLBT_DRIVER_DISABLE_SHARED \
| SLBT_DRIVER_DISABLE_STATIC)
-int slbt_create_symlink(
+slbt_hidden int slbt_create_symlink_ex(
const struct slbt_driver_ctx * dctx,
struct slbt_exec_ctx * ectx,
+ int fddst,
const char * target,
const char * lnkname,
uint32_t options)
{
- int fdcwd;
int fliteral;
int fwrapper;
int fdevnull;
+ size_t slen;
char ** oargv;
const char * slash;
char * ln[5];
+ char * dot;
char * dotdot;
+ char * mark;
char tmplnk [PATH_MAX];
char lnkarg [PATH_MAX];
char alnkarg[PATH_MAX];
@@ -45,18 +51,14 @@ int slbt_create_symlink(
fdevnull = (options & SLBT_SYMLINK_DEVNULL);
/* symlink is a placeholder? */
- if (fliteral && fdevnull) {
+ if (fliteral) {
slash = target;
- } else if ((dctx->cctx->drvflags & SLBT_DEV_NULL_FLAGS)
- && !strcmp(target,"/dev/null")) {
+ /* .disabled .so or .a file */
+ } else if (fdevnull) {
slash = target;
suffix = ".disabled";
- /* target is an absolute path? */
- } else if (fliteral) {
- slash = target;
-
/* symlink target contains a dirname? */
} else if ((slash = strrchr(target,'/'))) {
slash++;
@@ -70,23 +72,52 @@ int slbt_create_symlink(
dotdot = fwrapper ? "../" : "";
/* atarget */
- if ((size_t)snprintf(atarget,sizeof(atarget),"%s%s",
- dotdot,slash) >= sizeof(atarget))
+ if (slbt_snprintf(atarget,sizeof(atarget),
+ "%s%s",dotdot,slash) < 0)
return SLBT_BUFFER_ERROR(dctx);
/* tmplnk */
- if ((size_t)snprintf(tmplnk,sizeof(tmplnk),"%s.symlink.tmp",
- lnkname) >= sizeof(tmplnk))
+ if (slbt_snprintf(tmplnk,sizeof(tmplnk),
+ "%s.symlink.tmp",
+ lnkname) <0)
return SLBT_BUFFER_ERROR(dctx);
/* placeholder? */
+ if (fdevnull) {
+ if (unlinkat(fddst,lnkname,0) && (errno != ENOENT))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ if ((dot = strrchr(lnkname,'.'))) {
+ if (!strcmp(dot,dctx->cctx->settings.dsosuffix)) {
+ strcpy(dot,".expsyms.a");
+
+ if (unlinkat(fddst,lnkname,0) && (errno != ENOENT))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ strcpy(dot,dctx->cctx->settings.dsosuffix);
+ }
+ }
+ }
+
if (suffix) {
sprintf(alnkarg,"%s%s",lnkname,suffix);
lnkname = alnkarg;
}
/* lnkarg */
- strcpy(lnkarg,lnkname);
+ if (fddst == slbt_driver_fdcwd(dctx)) {
+ strcpy(lnkarg,lnkname);
+ } else {
+ if (slbt_realpath(fddst,".",0,lnkarg,sizeof(lnkarg)) < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ if ((slen = strlen(lnkarg)) + strlen(lnkname) + 1 >= PATH_MAX)
+ return SLBT_BUFFER_ERROR(dctx);
+
+ mark = &lnkarg[slen];
+ mark[0] = '/';
+ strcpy(++mark,lnkname);
+ }
/* ln argv (fake) */
ln[0] = "ln";
@@ -101,12 +132,12 @@ int slbt_create_symlink(
/* step output */
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
if (dctx->cctx->mode == SLBT_MODE_LINK) {
- if (slbt_output_link(dctx,ectx)) {
+ if (slbt_output_link(ectx)) {
ectx->argv = oargv;
return SLBT_NESTED_ERROR(dctx);
}
} else {
- if (slbt_output_install(dctx,ectx)) {
+ if (slbt_output_install(ectx)) {
ectx->argv = oargv;
return SLBT_NESTED_ERROR(dctx);
}
@@ -116,19 +147,29 @@ int slbt_create_symlink(
/* restore execution context */
ectx->argv = oargv;
- /* fdcwd */
- fdcwd = slbt_driver_fdcwd(dctx);
-
/* create symlink */
- if (symlinkat(atarget,fdcwd,tmplnk))
+ if (symlinkat(atarget,fddst,tmplnk))
return SLBT_SYSTEM_ERROR(dctx,tmplnk);
- return renameat(fdcwd,tmplnk,fdcwd,lnkname)
+ return renameat(fddst,tmplnk,fddst,lnkname)
? SLBT_SYSTEM_ERROR(dctx,lnkname)
: 0;
}
-int slbt_symlink_is_a_placeholder(int fdcwd, char * lnkpath)
+slbt_hidden int slbt_create_symlink(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ const char * target,
+ const char * lnkname,
+ uint32_t options)
+{
+ return slbt_create_symlink_ex(
+ dctx,ectx,
+ slbt_driver_fdcwd(dctx),
+ target,lnkname,options);
+}
+
+slbt_hidden int slbt_symlink_is_a_placeholder(int fdcwd, const char * lnkpath)
{
size_t len;
char slink [PATH_MAX];
diff --git a/src/internal/slibtool_symlink_impl.h b/src/internal/slibtool_symlink_impl.h
index fc4c708..9f968de 100644
--- a/src/internal/slibtool_symlink_impl.h
+++ b/src/internal/slibtool_symlink_impl.h
@@ -16,6 +16,14 @@ int slbt_create_symlink(
const char * lnkname,
uint32_t options);
-int slbt_symlink_is_a_placeholder(int fdcwd, char * lnkpath);
+int slbt_create_symlink_ex(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ int fddst,
+ const char * target,
+ const char * lnkname,
+ uint32_t options);
+
+int slbt_symlink_is_a_placeholder(int fdcwd, const char * lnkpath);
#endif
diff --git a/src/internal/slibtool_tmpfile_impl.c b/src/internal/slibtool_tmpfile_impl.c
new file mode 100644
index 0000000..52c7317
--- /dev/null
+++ b/src/internal/slibtool_tmpfile_impl.c
@@ -0,0 +1,89 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#define _GNU_SOURCE
+#include <time.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "slibtool_visibility_impl.h"
+
+#define PPRIX64 "%"PRIx64
+
+/* mkostemp might be guarded by non-standard macros */
+/* unless HAVE_NO_MKOSTEMP, assume it is available */
+extern int mkstemp(char *);
+extern int mkostemp(char *, int);
+
+/* __fs_tmpfile() atomically provides a private tmpfile */
+static int slbt_tmpfile_by_framework(void)
+{
+#ifdef _MIDIPIX_ABI
+ extern int __fs_tmpfile(int);
+ return __fs_tmpfile(O_CLOEXEC);
+#else
+ return (-1);
+#endif
+}
+
+/* O_TMPFILE atomically provides a private tmpfile */
+static int slbt_tmpfile_by_kernel(void)
+{
+#ifdef O_TMPFILE
+ return openat(AT_FDCWD,"/tmp",O_RDWR|O_TMPFILE|O_CLOEXEC,0);
+#else
+ return (-1);
+#endif
+}
+
+/* mk{o}stemp() provides a non-private tmpfile */
+static int slbt_mkostemp(char * tmplate)
+{
+ int fd;
+#ifdef HAVE_NO_MKOSTEMP
+ if ((fd = mkstemp(tmplate)) >= 0)
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+#else
+ fd = mkostemp(tmplate,O_CLOEXEC);
+#endif
+ return fd;
+}
+
+slbt_hidden int slbt_tmpfile(void)
+{
+ int fd;
+ void * addr;
+ char tmplate[128];
+
+ /* try with __fs_tmpfile() */
+ if ((fd = slbt_tmpfile_by_framework()) >= 0)
+ return fd;
+
+ /* try with O_TMPFILE */
+ if ((fd = slbt_tmpfile_by_kernel()) >= 0)
+ return fd;
+
+ /* fallback to mk{o}stemp */
+ addr = tmplate;
+ memset(tmplate,0,sizeof(tmplate));
+ snprintf(tmplate,sizeof(tmplate),
+ "/tmp/"
+ ".slibtool.tmpfile"
+ ".time."PPRIX64
+ ".salt.%p"
+ ".pid.%d"
+ ".XXXXXXXXXXXX",
+ time(0),
+ addr,
+ getpid());
+
+ return slbt_mkostemp(tmplate);
+}
diff --git a/src/internal/slibtool_tmpfile_impl.h b/src/internal/slibtool_tmpfile_impl.h
new file mode 100644
index 0000000..cd6a02b
--- /dev/null
+++ b/src/internal/slibtool_tmpfile_impl.h
@@ -0,0 +1,6 @@
+#ifndef SLIBTOOL_TMPFILE_IMPL_H
+#define SLIBTOOL_TMPFILE_IMPL_H
+
+int slbt_tmpfile(void);
+
+#endif
diff --git a/src/internal/slibtool_txtline_impl.c b/src/internal/slibtool_txtline_impl.c
new file mode 100644
index 0000000..4c8f2ad
--- /dev/null
+++ b/src/internal/slibtool_txtline_impl.c
@@ -0,0 +1,67 @@
+/*******************************************************************/
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_visibility_impl.h"
+
+slbt_hidden int slbt_txtline_to_string_vector(const char * txtline, char *** pargv)
+{
+ int argc;
+ char ** argv;
+ const char * ch;
+ const char * mark;
+
+ if (!(ch = txtline))
+ return 0;
+
+ argc = 1;
+
+ for (; *ch == ' '; )
+ ch++;
+
+ for (; *ch; ) {
+ if (*ch++ == ' ') {
+ argc++;
+
+ for (; (*ch == ' '); )
+ ch++;
+ }
+ }
+
+ if (argc == 1)
+ return 0;
+
+ if (!(*pargv = calloc(++argc,sizeof(char *))))
+ return -1;
+
+ for (ch=txtline; (*ch == ' '); ch++)
+ (void)0;
+
+ argv = *pargv;
+ mark = ch;
+
+ for (; *ch; ) {
+ if (*ch == ' ') {
+ if (!(*argv++ = strndup(mark,ch-mark)))
+ return -1;
+
+ for (; (*ch == ' '); )
+ ch++;
+
+ mark = ch;
+ } else {
+ ch++;
+ }
+ }
+
+ if (!(*argv++ = strndup(mark,ch-mark)))
+ return -1;
+
+ return 0;
+}
diff --git a/src/internal/slibtool_txtline_impl.h b/src/internal/slibtool_txtline_impl.h
new file mode 100644
index 0000000..2a647b1
--- /dev/null
+++ b/src/internal/slibtool_txtline_impl.h
@@ -0,0 +1,8 @@
+#ifndef SLIBTOOL_TXTLINE_IMPL_H
+#define SLIBTOOL_TXTLINE_IMPL_H
+
+#include <slibtool/slibtool.h>
+
+int slbt_txtline_to_string_vector(const char *, char ***);
+
+#endif
diff --git a/src/internal/slibtool_visibility_impl.h b/src/internal/slibtool_visibility_impl.h
new file mode 100644
index 0000000..2bdded0
--- /dev/null
+++ b/src/internal/slibtool_visibility_impl.h
@@ -0,0 +1,26 @@
+#ifndef SLIBTOOL_VISIBILITY_IMPL_H
+#define SLIBTOOL_VISIBILITY_IMPL_H
+
+/**********************************************************************/
+/* PE targets: __dllexport suffices for the purpose of exporting only */
+/* the desired subset of global symbols; this makes the visibility */
+/* attribute not only redundant, but also tricky if not properly */
+/* supported by the toolchain. */
+/* */
+/* When targeting Midipix, __PE__, __dllexport and __dllimport are */
+/* always defined by the toolchain. Otherwise, the absnece of these */
+/* macros has been detected by sofort's ccenv.sh during ./configure, */
+/* and they have accordingly been added to CFLAGS_OS. */
+/**********************************************************************/
+
+#ifdef __PE__
+#define slbt_hidden
+#else
+#ifdef _ATTR_VISIBILITY_HIDDEN
+#define slbt_hidden _ATTR_VISIBILITY_HIDDEN
+#else
+#define slbt_hidden
+#endif
+#endif
+
+#endif