summaryrefslogtreecommitdiffhomepage
path: root/src/driver
diff options
context:
space:
mode:
Diffstat (limited to 'src/driver')
-rw-r--r--src/driver/slbt_driver_ctx.c650
-rw-r--r--src/driver/slbt_host_params.c663
2 files changed, 671 insertions, 642 deletions
diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c
index 126dc85..ec468a2 100644
--- a/src/driver/slbt_driver_ctx.c
+++ b/src/driver/slbt_driver_ctx.c
@@ -26,6 +26,10 @@
extern char ** environ;
+/* annotation strings */
+static const char cfgexplicit[] = "command-line argument";
+static const char cfglconf[] = "derived from <libtool>";
+
/* package info */
static const struct slbt_source_version slbt_src_version = {
SLBT_TAG_VER_MAJOR,
@@ -44,72 +48,9 @@ static const struct slbt_fd_ctx slbt_default_fdctx = {
.fdlog = (-1),
};
-/* flavor settings */
-#define SLBT_FLAVOR_SETTINGS(flavor, \
- bfmt,pic, \
- arp,ars,dsop,dsos,osds,osdf, \
- exep,exes,impp,imps, \
- ldenv) \
- static const struct slbt_flavor_settings flavor = { \
- bfmt,arp,ars,dsop,dsos,osds,osdf, \
- exep,exes,impp,imps, \
- ldenv,pic}
-
-SLBT_FLAVOR_SETTINGS(host_flavor_default, \
- "elf","-fPIC", \
- "lib",".a","lib",".so",".so","", \
- "","","","", \
- "LD_LIBRARY_PATH");
-
-SLBT_FLAVOR_SETTINGS(host_flavor_midipix, \
- "pe","-fPIC", \
- "lib",".a","lib",".so",".so","", \
- "","","lib",".lib.a", \
- "LD_LIBRARY_PATH");
-
-SLBT_FLAVOR_SETTINGS(host_flavor_mingw, \
- "pe",0, \
- "lib",".a","lib",".dll","",".dll", \
- "",".exe","lib",".dll.a", \
- "PATH");
-
-SLBT_FLAVOR_SETTINGS(host_flavor_cygwin, \
- "pe",0, \
- "lib",".a","lib",".dll","",".dll", \
- "",".exe","lib",".dll.a", \
- "PATH");
-
-SLBT_FLAVOR_SETTINGS(host_flavor_darwin, \
- "macho","-fPIC", \
- "lib",".a","lib",".dylib","",".dylib", \
- "","","","", \
- "DYLD_LIBRARY_PATH");
-
-
-/* annotation strings */
-static const char cfgexplicit[] = "command-line argument";
-static const char cfghost[] = "derived from <host>";
-static const char cfglconf[] = "derived from <libtool>";
-static const char cfgtarget[] = "derived from <target>";
-static const char cfgcompiler[] = "derived from <compiler>";
-static const char cfgnmachine[] = "native (cached in ccenv/host.mk)";
-static const char cfgxmachine[] = "foreign (derived from -dumpmachine)";
-static const char cfgnative[] = "native";
-
-
/* default compiler argv */
static char * slbt_default_cargv[] = {"cc",0};
-/* elf rpath */
-static const char*ldrpath_elf[] = {
- "/lib",
- "/lib/64",
- "/usr/lib",
- "/usr/lib64",
- "/usr/local/lib",
- "/usr/local/lib64",
- 0};
-
static const char aclr_reset [] = "\x1b[0m";
static const char aclr_bold [] = "\x1b[1m";
static const char aclr_red [] = "\x1b[31m";
@@ -119,11 +60,6 @@ static const char aclr_blue [] = "\x1b[34m";
static const char aclr_cyan [] = "\x1b[36m";
static const char aclr_white [] = "\x1b[37m";
-struct slbt_driver_ctx_alloc {
- struct argv_meta * meta;
- struct slbt_driver_ctx_impl ctx;
- uint64_t guard;
-};
static void slbt_output_raw_vector(int fderr, char ** argv, char ** envp, bool fcolor)
{
@@ -774,499 +710,6 @@ static int slbt_split_argv(
return 0;
}
-static void slbt_get_host_quad(
- char * hostbuf,
- char ** hostquad)
-{
- char * mark;
- char * ch;
- int i;
-
- for (i=0, ch=hostbuf, mark=hostbuf; *ch && i<4; ch++) {
- if (*ch == '-') {
- *ch = 0;
- hostquad[i++] = mark;
- mark = &ch[1];
- }
- }
-
- if (i<4)
- hostquad[i] = mark;
-
- if (i==3) {
- hostquad[1] = hostquad[2];
- hostquad[2] = hostquad[3];
- hostquad[3] = 0;
- }
-}
-
-static void slbt_spawn_ar(char ** argv, int * ecode)
-{
- int estatus;
- pid_t pid;
-
- *ecode = 127;
-
- if ((pid = fork()) < 0) {
- return;
-
- } else if (pid == 0) {
- execvp(argv[0],argv);
- _exit(errno);
-
- } else {
- waitpid(pid,&estatus,0);
-
- if (WIFEXITED(estatus))
- *ecode = WEXITSTATUS(estatus);
- }
-}
-
-static 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_ar,
- const char * cfgmeta_ranlib)
-{
- int fdcwd;
- int arprobe;
- int arfd;
- int ecode;
- size_t toollen;
- char * dash;
- char * base;
- char * mark;
- const char * machine;
- bool ftarget = false;
- bool fhost = false;
- bool fcompiler = false;
- bool fnative = false;
- bool fdumpmachine = false;
- char buf [256];
- char hostbuf [256];
- char machinebuf [256];
- char * hostquad [4];
- char * machinequad[4];
- char * arprobeargv[4];
- char archivename[] = "/tmp/slibtool.ar.probe.XXXXXXXXXXXXXXXX";
-
- /* base */
- if ((base = strrchr(cctx->cargv[0],'/')))
- base++;
- else
- base = cctx->cargv[0];
-
- fdumpmachine = (cctx->mode == SLBT_MODE_COMPILE)
- || (cctx->mode == SLBT_MODE_LINK)
- || (cctx->mode == SLBT_MODE_INFO);
-
- fdumpmachine &= (!strcmp(base,"xgcc")
- || !strcmp(base,"xg++"));
-
- /* support the portbld <--> unknown synonym */
- if (!(drvhost->machine = strdup(SLBT_MACHINE)))
- return -1;
-
- if ((mark = strstr(drvhost->machine,"-portbld-")))
- memcpy(mark,"-unknown",8);
-
- /* host */
- if (host->host) {
- cfgmeta->host = cfgexplicit;
- fhost = true;
-
- } else if (cctx->target) {
- host->host = cctx->target;
- cfgmeta->host = cfgtarget;
- ftarget = true;
-
- } else if (strrchr(base,'-')) {
- if (!(drvhost->host = strdup(cctx->cargv[0])))
- return -1;
-
- dash = strrchr(drvhost->host,'-');
- *dash = 0;
- host->host = drvhost->host;
- cfgmeta->host = cfgcompiler;
- fcompiler = true;
-
- } else if (!fdumpmachine) {
- host->host = drvhost->machine;
- cfgmeta->host = cfgnmachine;
-
- } else if (slbt_dump_machine(cctx->cargv[0],buf,sizeof(buf)) < 0) {
- if (dctx)
- slbt_dprintf(
- slbt_driver_fderr(dctx),
- "%s: could not determine host "
- "via -dumpmachine\n",
- dctx->program);
- return -1;
-
- } else {
- if (!(drvhost->host = strdup(buf)))
- return -1;
-
- host->host = drvhost->host;
- fcompiler = true;
- fnative = !strcmp(host->host,drvhost->machine);
- cfgmeta->host = fnative ? cfgnmachine : cfgxmachine;
-
- if (!fnative) {
- strcpy(hostbuf,host->host);
- strcpy(machinebuf,drvhost->machine);
-
- slbt_get_host_quad(hostbuf,hostquad);
- slbt_get_host_quad(machinebuf,machinequad);
-
- if (hostquad[2] && machinequad[2])
- fnative = !strcmp(hostquad[0],machinequad[0])
- && !strcmp(hostquad[1],machinequad[1])
- && !strcmp(hostquad[2],machinequad[2]);
- }
- }
-
- /* flavor */
- if (host->flavor) {
- cfgmeta->flavor = cfgexplicit;
- } else {
- if (fhost) {
- machine = host->host;
- cfgmeta->flavor = cfghost;
- } else if (ftarget) {
- machine = cctx->target;
- cfgmeta->flavor = cfgtarget;
- } else if (fcompiler) {
- machine = drvhost->host;
- cfgmeta->flavor = cfgcompiler;
- } else {
- machine = drvhost->machine;
- cfgmeta->flavor = cfgnmachine;
- }
-
- dash = strrchr(machine,'-');
- cfgmeta->flavor = cfghost;
-
- if ((dash && !strcmp(dash,"-bsd")) || strstr(machine,"-bsd-"))
- host->flavor = "bsd";
- else if ((dash && !strcmp(dash,"-cygwin")) || strstr(machine,"-cygwin-"))
- host->flavor = "cygwin";
- else if ((dash && !strcmp(dash,"-darwin")) || strstr(machine,"-darwin"))
- host->flavor = "darwin";
- else if ((dash && !strcmp(dash,"-linux")) || strstr(machine,"-linux-"))
- host->flavor = "linux";
- else if ((dash && !strcmp(dash,"-midipix")) || strstr(machine,"-midipix-"))
- host->flavor = "midipix";
- else if ((dash && !strcmp(dash,"-mingw")) || strstr(machine,"-mingw-"))
- host->flavor = "mingw";
- else if ((dash && !strcmp(dash,"-mingw32")) || strstr(machine,"-mingw32-"))
- host->flavor = "mingw";
- else if ((dash && !strcmp(dash,"-mingw64")) || strstr(machine,"-mingw64-"))
- host->flavor = "mingw";
- else if ((dash && !strcmp(dash,"-windows")) || strstr(machine,"-windows-"))
- host->flavor = "mingw";
- else {
- host->flavor = "default";
- cfgmeta->flavor = "fallback, unverified";
- }
-
- if (fcompiler && !fnative)
- if ((mark = strstr(drvhost->machine,host->flavor)))
- if (mark > drvhost->machine)
- fnative = (*--mark == '-');
- }
-
- /* toollen */
- toollen = fnative ? 0 : strlen(host->host);
- toollen += strlen("-utility-name");
-
- /* ar */
- if (host->ar)
- cfgmeta->ar = cfgmeta_ar ? cfgmeta_ar : cfgexplicit;
- else {
- if (!(drvhost->ar = calloc(1,toollen)))
- return -1;
-
- if (fnative) {
- strcpy(drvhost->ar,"ar");
- cfgmeta->ar = cfgnative;
- arprobe = 0;
- } else if (cctx->mode == SLBT_MODE_LINK) {
- arprobe = true;
- } else if (cctx->mode == SLBT_MODE_INFO) {
- arprobe = true;
- } else {
- arprobe = false;
- }
-
- /* arprobe */
- if (arprobe) {
- sprintf(drvhost->ar,"%s-ar",host->host);
- cfgmeta->ar = cfghost;
- ecode = 127;
-
- /* empty archive */
- if ((arfd = mkstemp(archivename)) >= 0) {
- slbt_dprintf(arfd,"!<arch>\n");
-
- arprobeargv[0] = drvhost->ar;
- arprobeargv[1] = "-t";
- arprobeargv[2] = archivename;
- arprobeargv[3] = 0;
-
- /* <target>-ar */
- slbt_spawn_ar(
- arprobeargv,
- &ecode);
- }
-
- /* <target>-<compiler>-ar */
- if (ecode && !strchr(base,'-')) {
- sprintf(drvhost->ar,"%s-%s-ar",host->host,base);
-
- slbt_spawn_ar(
- arprobeargv,
- &ecode);
- }
-
- /* <compiler>-ar */
- if (ecode && !strchr(base,'-')) {
- sprintf(drvhost->ar,"%s-ar",base);
-
- slbt_spawn_ar(
- arprobeargv,
- &ecode);
- }
-
- /* if target is the native target, fallback to native ar */
- if (ecode && !strcmp(host->host,SLBT_MACHINE)) {
- strcpy(drvhost->ar,"ar");
- cfgmeta->ar = cfgnative;
- }
-
- /* fdcwd */
- fdcwd = slbt_driver_fdcwd(dctx);
-
- /* clean up */
- if (arfd >= 0) {
- unlinkat(fdcwd,archivename,0);
- close(arfd);
- }
- }
-
- host->ar = drvhost->ar;
- }
-
- /* ranlib */
- if (host->ranlib)
- cfgmeta->ranlib = cfgmeta_ranlib ? cfgmeta_ranlib : cfgexplicit;
- else {
- if (!(drvhost->ranlib = calloc(1,toollen)))
- return -1;
-
- if (fnative) {
- strcpy(drvhost->ranlib,"ranlib");
- cfgmeta->ranlib = cfgnative;
- } else {
- sprintf(drvhost->ranlib,"%s-ranlib",host->host);
- cfgmeta->ranlib = cfghost;
- }
-
- host->ranlib = drvhost->ranlib;
- }
-
- /* windres */
- if (host->windres)
- cfgmeta->windres = cfgexplicit;
-
- else if (strcmp(host->flavor,"cygwin")
- && strcmp(host->flavor,"midipix")
- && strcmp(host->flavor,"mingw")) {
- host->windres = "";
- cfgmeta->windres = "not applicable";
-
- } else {
- if (!(drvhost->windres = calloc(1,toollen)))
- return -1;
-
- if (fnative) {
- strcpy(drvhost->windres,"windres");
- cfgmeta->windres = cfgnative;
- } else {
- sprintf(drvhost->windres,"%s-windres",host->host);
- cfgmeta->windres = cfghost;
- }
-
- host->windres = drvhost->windres;
- }
-
- /* dlltool */
- if (host->dlltool)
- cfgmeta->dlltool = cfgexplicit;
-
- else if (strcmp(host->flavor,"cygwin")
- && strcmp(host->flavor,"midipix")
- && strcmp(host->flavor,"mingw")) {
- host->dlltool = "";
- cfgmeta->dlltool = "not applicable";
-
- } else {
- if (!(drvhost->dlltool = calloc(1,toollen)))
- return -1;
-
- if (fnative) {
- strcpy(drvhost->dlltool,"dlltool");
- cfgmeta->dlltool = cfgnative;
- } else {
- sprintf(drvhost->dlltool,"%s-dlltool",host->host);
- cfgmeta->dlltool = cfghost;
- }
-
- host->dlltool = drvhost->dlltool;
- }
-
- /* mdso */
- if (host->mdso)
- cfgmeta->mdso = cfgexplicit;
-
- else if (strcmp(host->flavor,"cygwin")
- && strcmp(host->flavor,"midipix")
- && strcmp(host->flavor,"mingw")) {
- host->mdso = "";
- cfgmeta->mdso = "not applicable";
-
- } else {
- if (!(drvhost->mdso = calloc(1,toollen)))
- return -1;
-
- if (fnative) {
- strcpy(drvhost->mdso,"mdso");
- cfgmeta->mdso = cfgnative;
- } else {
- sprintf(drvhost->mdso,"%s-mdso",host->host);
- cfgmeta->mdso = cfghost;
- }
-
- host->mdso = drvhost->mdso;
- }
-
- return 0;
-}
-
-static void slbt_free_host_params(struct slbt_host_strs * host)
-{
- if (host->machine)
- free(host->machine);
-
- if (host->host)
- free(host->host);
-
- if (host->flavor)
- free(host->flavor);
-
- if (host->ar)
- free(host->ar);
-
- if (host->ranlib)
- free(host->ranlib);
-
- if (host->windres)
- free(host->windres);
-
- if (host->dlltool)
- free(host->dlltool);
-
- if (host->mdso)
- free(host->mdso);
-
- memset(host,0,sizeof(*host));
-}
-
-static void slbt_init_flavor_settings(
- struct slbt_common_ctx * cctx,
- const struct slbt_host_params * ahost,
- struct slbt_flavor_settings * psettings)
-{
- const struct slbt_host_params * host;
- const struct slbt_flavor_settings * settings;
-
- host = ahost ? ahost : &cctx->host;
-
- if (!strcmp(host->flavor,"midipix"))
- settings = &host_flavor_midipix;
- else if (!strcmp(host->flavor,"mingw"))
- settings = &host_flavor_mingw;
- else if (!strcmp(host->flavor,"cygwin"))
- settings = &host_flavor_cygwin;
- else if (!strcmp(host->flavor,"darwin"))
- settings = &host_flavor_darwin;
- else
- settings = &host_flavor_default;
-
- if (!ahost) {
- if (!strcmp(settings->imagefmt,"elf"))
- cctx->drvflags |= SLBT_DRIVER_IMAGE_ELF;
- else if (!strcmp(settings->imagefmt,"pe"))
- cctx->drvflags |= SLBT_DRIVER_IMAGE_PE;
- else if (!strcmp(settings->imagefmt,"macho"))
- cctx->drvflags |= SLBT_DRIVER_IMAGE_MACHO;
- }
-
- memcpy(psettings,settings,sizeof(*settings));
-
- if (cctx->shrext)
- psettings->dsosuffix = cctx->shrext;
-}
-
-static int slbt_init_ldrpath(
- struct slbt_common_ctx * cctx,
- struct slbt_host_params * host)
-{
- char * buf;
- const char ** ldrpath;
-
- if (!cctx->rpath || !(cctx->drvflags & SLBT_DRIVER_IMAGE_ELF)) {
- host->ldrpath = 0;
- return 0;
- }
-
- /* common? */
- for (ldrpath=ldrpath_elf; *ldrpath; ldrpath ++)
- if (!(strcmp(cctx->rpath,*ldrpath))) {
- host->ldrpath = 0;
- return 0;
- }
-
- /* buf */
- if (!(buf = malloc(12 + strlen(cctx->host.host))))
- return -1;
-
- /* /usr/{host}/lib */
- sprintf(buf,"/usr/%s/lib",cctx->host.host);
-
- if (!(strcmp(cctx->rpath,buf))) {
- host->ldrpath = 0;
- free(buf);
- return 0;
- }
-
- /* /usr/{host}/lib64 */
- sprintf(buf,"/usr/%s/lib64",cctx->host.host);
-
- if (!(strcmp(cctx->rpath,buf))) {
- host->ldrpath = 0;
- free(buf);
- return 0;
- }
-
- host->ldrpath = cctx->rpath;
-
- free(buf);
- return 0;
-}
static int slbt_init_version_info(
struct slbt_driver_ctx_impl * ictx,
@@ -2023,6 +1466,7 @@ int slbt_get_driver_ctx(
return 0;
}
+
static void slbt_free_driver_ctx_impl(struct slbt_driver_ctx_alloc * ictx)
{
struct slbt_error_info ** perr;
@@ -2057,6 +1501,7 @@ static void slbt_free_driver_ctx_impl(struct slbt_driver_ctx_alloc * ictx)
free(ictx);
}
+
void slbt_free_driver_ctx(struct slbt_driver_ctx * ctx)
{
struct slbt_driver_ctx_alloc * ictx;
@@ -2070,93 +1515,13 @@ void slbt_free_driver_ctx(struct slbt_driver_ctx * ctx)
}
}
-void slbt_reset_alternate_host(const struct slbt_driver_ctx * ctx)
-{
- struct slbt_driver_ctx_alloc * ictx;
- uintptr_t addr;
-
- addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
- addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
- ictx = (struct slbt_driver_ctx_alloc *)addr;
-
- slbt_free_host_params(&ictx->ctx.ahost);
-}
-
-int slbt_set_alternate_host(
- const struct slbt_driver_ctx * ctx,
- const char * host,
- const char * flavor)
-{
- struct slbt_driver_ctx_alloc * ictx;
- uintptr_t addr;
-
- addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
- addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
- ictx = (struct slbt_driver_ctx_alloc *)addr;
- slbt_free_host_params(&ictx->ctx.ahost);
-
- if (!(ictx->ctx.ahost.host = strdup(host)))
- return SLBT_SYSTEM_ERROR(ctx,0);
-
- if (!(ictx->ctx.ahost.flavor = strdup(flavor))) {
- slbt_free_host_params(&ictx->ctx.ahost);
- return SLBT_SYSTEM_ERROR(ctx,0);
- }
-
- ictx->ctx.cctx.ahost.host = ictx->ctx.ahost.host;
- ictx->ctx.cctx.ahost.flavor = ictx->ctx.ahost.flavor;
-
- if (slbt_init_host_params(
- 0,
- ctx->cctx,
- &ictx->ctx.ahost,
- &ictx->ctx.cctx.ahost,
- &ictx->ctx.cctx.acfgmeta,
- 0,0)) {
- slbt_free_host_params(&ictx->ctx.ahost);
- return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_HOST_INIT);
- }
-
- slbt_init_flavor_settings(
- &ictx->ctx.cctx,
- &ictx->ctx.cctx.ahost,
- &ictx->ctx.cctx.asettings);
-
- if (slbt_init_ldrpath(
- &ictx->ctx.cctx,
- &ictx->ctx.cctx.ahost)) {
- slbt_free_host_params(&ictx->ctx.ahost);
- return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_LDRPATH_INIT);
- }
-
- return 0;
-}
-
-int slbt_get_flavor_settings(
- const char * flavor,
- const struct slbt_flavor_settings ** settings)
-{
- if (!strcmp(flavor,"midipix"))
- *settings = &host_flavor_midipix;
- else if (!strcmp(flavor,"mingw"))
- *settings = &host_flavor_mingw;
- else if (!strcmp(flavor,"cygwin"))
- *settings = &host_flavor_cygwin;
- else if (!strcmp(flavor,"darwin"))
- *settings = &host_flavor_darwin;
- else if (!strcmp(flavor,"default"))
- *settings = &host_flavor_default;
- else
- *settings = 0;
-
- return *settings ? 0 : -1;
-}
const struct slbt_source_version * slbt_source_version(void)
{
return &slbt_src_version;
}
+
int slbt_get_driver_fdctx(
const struct slbt_driver_ctx * dctx,
struct slbt_fd_ctx * fdctx)
@@ -2175,6 +1540,7 @@ int slbt_get_driver_fdctx(
return 0;
}
+
int slbt_set_driver_fdctx(
struct slbt_driver_ctx * dctx,
const struct slbt_fd_ctx * fdctx)
diff --git a/src/driver/slbt_host_params.c b/src/driver/slbt_host_params.c
new file mode 100644
index 0000000..b83fa8a
--- /dev/null
+++ b/src/driver/slbt_host_params.c
@@ -0,0 +1,663 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016--2021 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <sys/wait.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+#include "slibtool_errinfo_impl.h"
+#include "slibtool_ar_impl.h"
+
+
+/* annotation strings */
+static const char cfgexplicit[] = "command-line argument";
+static const char cfghost[] = "derived from <host>";
+static const char cfgtarget[] = "derived from <target>";
+static const char cfgcompiler[] = "derived from <compiler>";
+static const char cfgnmachine[] = "native (cached in ccenv/host.mk)";
+static const char cfgxmachine[] = "foreign (derived from -dumpmachine)";
+static const char cfgnative[] = "native";
+
+/* elf rpath */
+static const char*ldrpath_elf[] = {
+ "/lib",
+ "/lib/64",
+ "/usr/lib",
+ "/usr/lib64",
+ "/usr/local/lib",
+ "/usr/local/lib64",
+ 0};
+
+/* flavor settings */
+#define SLBT_FLAVOR_SETTINGS(flavor, \
+ bfmt,pic, \
+ arp,ars,dsop,dsos,osds,osdf, \
+ exep,exes,impp,imps, \
+ ldenv) \
+ static const struct slbt_flavor_settings flavor = { \
+ bfmt,arp,ars,dsop,dsos,osds,osdf, \
+ exep,exes,impp,imps, \
+ ldenv,pic}
+
+SLBT_FLAVOR_SETTINGS(host_flavor_default, \
+ "elf","-fPIC", \
+ "lib",".a","lib",".so",".so","", \
+ "","","","", \
+ "LD_LIBRARY_PATH");
+
+SLBT_FLAVOR_SETTINGS(host_flavor_midipix, \
+ "pe","-fPIC", \
+ "lib",".a","lib",".so",".so","", \
+ "","","lib",".lib.a", \
+ "LD_LIBRARY_PATH");
+
+SLBT_FLAVOR_SETTINGS(host_flavor_mingw, \
+ "pe",0, \
+ "lib",".a","lib",".dll","",".dll", \
+ "",".exe","lib",".dll.a", \
+ "PATH");
+
+SLBT_FLAVOR_SETTINGS(host_flavor_cygwin, \
+ "pe",0, \
+ "lib",".a","lib",".dll","",".dll", \
+ "",".exe","lib",".dll.a", \
+ "PATH");
+
+SLBT_FLAVOR_SETTINGS(host_flavor_darwin, \
+ "macho","-fPIC", \
+ "lib",".a","lib",".dylib","",".dylib", \
+ "","","","", \
+ "DYLD_LIBRARY_PATH");
+
+
+static void slbt_get_host_quad(
+ char * hostbuf,
+ char ** hostquad)
+{
+ char * mark;
+ char * ch;
+ int i;
+
+ for (i=0, ch=hostbuf, mark=hostbuf; *ch && i<4; ch++) {
+ if (*ch == '-') {
+ *ch = 0;
+ hostquad[i++] = mark;
+ mark = &ch[1];
+ }
+ }
+
+ if (i<4)
+ hostquad[i] = mark;
+
+ if (i==3) {
+ hostquad[1] = hostquad[2];
+ hostquad[2] = hostquad[3];
+ hostquad[3] = 0;
+ }
+}
+
+
+static void slbt_spawn_ar(char ** argv, int * ecode)
+{
+ int estatus;
+ pid_t pid;
+
+ *ecode = 127;
+
+ if ((pid = fork()) < 0) {
+ return;
+
+ } else if (pid == 0) {
+ execvp(argv[0],argv);
+ _exit(errno);
+
+ } else {
+ waitpid(pid,&estatus,0);
+
+ if (WIFEXITED(estatus))
+ *ecode = WEXITSTATUS(estatus);
+ }
+}
+
+
+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_ar,
+ const char * cfgmeta_ranlib)
+{
+ int fdcwd;
+ int arprobe;
+ int arfd;
+ int ecode;
+ size_t toollen;
+ char * dash;
+ char * base;
+ char * mark;
+ const char * machine;
+ bool ftarget = false;
+ bool fhost = false;
+ bool fcompiler = false;
+ bool fnative = false;
+ bool fdumpmachine = false;
+ char buf [256];
+ char hostbuf [256];
+ char machinebuf [256];
+ char * hostquad [4];
+ char * machinequad[4];
+ char * arprobeargv[4];
+ char archivename[] = "/tmp/slibtool.ar.probe.XXXXXXXXXXXXXXXX";
+
+ /* base */
+ if ((base = strrchr(cctx->cargv[0],'/')))
+ base++;
+ else
+ base = cctx->cargv[0];
+
+ fdumpmachine = (cctx->mode == SLBT_MODE_COMPILE)
+ || (cctx->mode == SLBT_MODE_LINK)
+ || (cctx->mode == SLBT_MODE_INFO);
+
+ fdumpmachine &= (!strcmp(base,"xgcc")
+ || !strcmp(base,"xg++"));
+
+ /* support the portbld <--> unknown synonym */
+ if (!(drvhost->machine = strdup(SLBT_MACHINE)))
+ return -1;
+
+ if ((mark = strstr(drvhost->machine,"-portbld-")))
+ memcpy(mark,"-unknown",8);
+
+ /* host */
+ if (host->host) {
+ cfgmeta->host = cfgexplicit;
+ fhost = true;
+
+ } else if (cctx->target) {
+ host->host = cctx->target;
+ cfgmeta->host = cfgtarget;
+ ftarget = true;
+
+ } else if (strrchr(base,'-')) {
+ if (!(drvhost->host = strdup(cctx->cargv[0])))
+ return -1;
+
+ dash = strrchr(drvhost->host,'-');
+ *dash = 0;
+ host->host = drvhost->host;
+ cfgmeta->host = cfgcompiler;
+ fcompiler = true;
+
+ } else if (!fdumpmachine) {
+ host->host = drvhost->machine;
+ cfgmeta->host = cfgnmachine;
+
+ } else if (slbt_dump_machine(cctx->cargv[0],buf,sizeof(buf)) < 0) {
+ if (dctx)
+ slbt_dprintf(
+ slbt_driver_fderr(dctx),
+ "%s: could not determine host "
+ "via -dumpmachine\n",
+ dctx->program);
+ return -1;
+
+ } else {
+ if (!(drvhost->host = strdup(buf)))
+ return -1;
+
+ host->host = drvhost->host;
+ fcompiler = true;
+ fnative = !strcmp(host->host,drvhost->machine);
+ cfgmeta->host = fnative ? cfgnmachine : cfgxmachine;
+
+ if (!fnative) {
+ strcpy(hostbuf,host->host);
+ strcpy(machinebuf,drvhost->machine);
+
+ slbt_get_host_quad(hostbuf,hostquad);
+ slbt_get_host_quad(machinebuf,machinequad);
+
+ if (hostquad[2] && machinequad[2])
+ fnative = !strcmp(hostquad[0],machinequad[0])
+ && !strcmp(hostquad[1],machinequad[1])
+ && !strcmp(hostquad[2],machinequad[2]);
+ }
+ }
+
+ /* flavor */
+ if (host->flavor) {
+ cfgmeta->flavor = cfgexplicit;
+ } else {
+ if (fhost) {
+ machine = host->host;
+ cfgmeta->flavor = cfghost;
+ } else if (ftarget) {
+ machine = cctx->target;
+ cfgmeta->flavor = cfgtarget;
+ } else if (fcompiler) {
+ machine = drvhost->host;
+ cfgmeta->flavor = cfgcompiler;
+ } else {
+ machine = drvhost->machine;
+ cfgmeta->flavor = cfgnmachine;
+ }
+
+ dash = strrchr(machine,'-');
+ cfgmeta->flavor = cfghost;
+
+ if ((dash && !strcmp(dash,"-bsd")) || strstr(machine,"-bsd-"))
+ host->flavor = "bsd";
+ else if ((dash && !strcmp(dash,"-cygwin")) || strstr(machine,"-cygwin-"))
+ host->flavor = "cygwin";
+ else if ((dash && !strcmp(dash,"-darwin")) || strstr(machine,"-darwin"))
+ host->flavor = "darwin";
+ else if ((dash && !strcmp(dash,"-linux")) || strstr(machine,"-linux-"))
+ host->flavor = "linux";
+ else if ((dash && !strcmp(dash,"-midipix")) || strstr(machine,"-midipix-"))
+ host->flavor = "midipix";
+ else if ((dash && !strcmp(dash,"-mingw")) || strstr(machine,"-mingw-"))
+ host->flavor = "mingw";
+ else if ((dash && !strcmp(dash,"-mingw32")) || strstr(machine,"-mingw32-"))
+ host->flavor = "mingw";
+ else if ((dash && !strcmp(dash,"-mingw64")) || strstr(machine,"-mingw64-"))
+ host->flavor = "mingw";
+ else if ((dash && !strcmp(dash,"-windows")) || strstr(machine,"-windows-"))
+ host->flavor = "mingw";
+ else {
+ host->flavor = "default";
+ cfgmeta->flavor = "fallback, unverified";
+ }
+
+ if (fcompiler && !fnative)
+ if ((mark = strstr(drvhost->machine,host->flavor)))
+ if (mark > drvhost->machine)
+ fnative = (*--mark == '-');
+ }
+
+ /* toollen */
+ toollen = fnative ? 0 : strlen(host->host);
+ toollen += strlen("-utility-name");
+
+ /* ar */
+ if (host->ar)
+ cfgmeta->ar = cfgmeta_ar ? cfgmeta_ar : cfgexplicit;
+ else {
+ if (!(drvhost->ar = calloc(1,toollen)))
+ return -1;
+
+ if (fnative) {
+ strcpy(drvhost->ar,"ar");
+ cfgmeta->ar = cfgnative;
+ arprobe = 0;
+ } else if (cctx->mode == SLBT_MODE_LINK) {
+ arprobe = true;
+ } else if (cctx->mode == SLBT_MODE_INFO) {
+ arprobe = true;
+ } else {
+ arprobe = false;
+ }
+
+ /* arprobe */
+ if (arprobe) {
+ sprintf(drvhost->ar,"%s-ar",host->host);
+ cfgmeta->ar = cfghost;
+ ecode = 127;
+
+ /* empty archive */
+ if ((arfd = mkstemp(archivename)) >= 0) {
+ slbt_dprintf(arfd,"!<arch>\n");
+
+ arprobeargv[0] = drvhost->ar;
+ arprobeargv[1] = "-t";
+ arprobeargv[2] = archivename;
+ arprobeargv[3] = 0;
+
+ /* <target>-ar */
+ slbt_spawn_ar(
+ arprobeargv,
+ &ecode);
+ }
+
+ /* <target>-<compiler>-ar */
+ if (ecode && !strchr(base,'-')) {
+ sprintf(drvhost->ar,"%s-%s-ar",host->host,base);
+
+ slbt_spawn_ar(
+ arprobeargv,
+ &ecode);
+ }
+
+ /* <compiler>-ar */
+ if (ecode && !strchr(base,'-')) {
+ sprintf(drvhost->ar,"%s-ar",base);
+
+ slbt_spawn_ar(
+ arprobeargv,
+ &ecode);
+ }
+
+ /* if target is the native target, fallback to native ar */
+ if (ecode && !strcmp(host->host,SLBT_MACHINE)) {
+ strcpy(drvhost->ar,"ar");
+ cfgmeta->ar = cfgnative;
+ }
+
+ /* fdcwd */
+ fdcwd = slbt_driver_fdcwd(dctx);
+
+ /* clean up */
+ if (arfd >= 0) {
+ unlinkat(fdcwd,archivename,0);
+ close(arfd);
+ }
+ }
+
+ host->ar = drvhost->ar;
+ }
+
+ /* ranlib */
+ if (host->ranlib)
+ cfgmeta->ranlib = cfgmeta_ranlib ? cfgmeta_ranlib : cfgexplicit;
+ else {
+ if (!(drvhost->ranlib = calloc(1,toollen)))
+ return -1;
+
+ if (fnative) {
+ strcpy(drvhost->ranlib,"ranlib");
+ cfgmeta->ranlib = cfgnative;
+ } else {
+ sprintf(drvhost->ranlib,"%s-ranlib",host->host);
+ cfgmeta->ranlib = cfghost;
+ }
+
+ host->ranlib = drvhost->ranlib;
+ }
+
+ /* windres */
+ if (host->windres)
+ cfgmeta->windres = cfgexplicit;
+
+ else if (strcmp(host->flavor,"cygwin")
+ && strcmp(host->flavor,"midipix")
+ && strcmp(host->flavor,"mingw")) {
+ host->windres = "";
+ cfgmeta->windres = "not applicable";
+
+ } else {
+ if (!(drvhost->windres = calloc(1,toollen)))
+ return -1;
+
+ if (fnative) {
+ strcpy(drvhost->windres,"windres");
+ cfgmeta->windres = cfgnative;
+ } else {
+ sprintf(drvhost->windres,"%s-windres",host->host);
+ cfgmeta->windres = cfghost;
+ }
+
+ host->windres = drvhost->windres;
+ }
+
+ /* dlltool */
+ if (host->dlltool)
+ cfgmeta->dlltool = cfgexplicit;
+
+ else if (strcmp(host->flavor,"cygwin")
+ && strcmp(host->flavor,"midipix")
+ && strcmp(host->flavor,"mingw")) {
+ host->dlltool = "";
+ cfgmeta->dlltool = "not applicable";
+
+ } else {
+ if (!(drvhost->dlltool = calloc(1,toollen)))
+ return -1;
+
+ if (fnative) {
+ strcpy(drvhost->dlltool,"dlltool");
+ cfgmeta->dlltool = cfgnative;
+ } else {
+ sprintf(drvhost->dlltool,"%s-dlltool",host->host);
+ cfgmeta->dlltool = cfghost;
+ }
+
+ host->dlltool = drvhost->dlltool;
+ }
+
+ /* mdso */
+ if (host->mdso)
+ cfgmeta->mdso = cfgexplicit;
+
+ else if (strcmp(host->flavor,"cygwin")
+ && strcmp(host->flavor,"midipix")
+ && strcmp(host->flavor,"mingw")) {
+ host->mdso = "";
+ cfgmeta->mdso = "not applicable";
+
+ } else {
+ if (!(drvhost->mdso = calloc(1,toollen)))
+ return -1;
+
+ if (fnative) {
+ strcpy(drvhost->mdso,"mdso");
+ cfgmeta->mdso = cfgnative;
+ } else {
+ sprintf(drvhost->mdso,"%s-mdso",host->host);
+ cfgmeta->mdso = cfghost;
+ }
+
+ host->mdso = drvhost->mdso;
+ }
+
+ return 0;
+}
+
+
+void slbt_free_host_params(struct slbt_host_strs * host)
+{
+ if (host->machine)
+ free(host->machine);
+
+ if (host->host)
+ free(host->host);
+
+ if (host->flavor)
+ free(host->flavor);
+
+ if (host->ar)
+ free(host->ar);
+
+ if (host->ranlib)
+ free(host->ranlib);
+
+ if (host->windres)
+ free(host->windres);
+
+ if (host->dlltool)
+ free(host->dlltool);
+
+ if (host->mdso)
+ free(host->mdso);
+
+ memset(host,0,sizeof(*host));
+}
+
+
+void slbt_init_flavor_settings(
+ struct slbt_common_ctx * cctx,
+ const struct slbt_host_params * ahost,
+ struct slbt_flavor_settings * psettings)
+{
+ const struct slbt_host_params * host;
+ const struct slbt_flavor_settings * settings;
+
+ host = ahost ? ahost : &cctx->host;
+
+ if (!strcmp(host->flavor,"midipix"))
+ settings = &host_flavor_midipix;
+ else if (!strcmp(host->flavor,"mingw"))
+ settings = &host_flavor_mingw;
+ else if (!strcmp(host->flavor,"cygwin"))
+ settings = &host_flavor_cygwin;
+ else if (!strcmp(host->flavor,"darwin"))
+ settings = &host_flavor_darwin;
+ else
+ settings = &host_flavor_default;
+
+ if (!ahost) {
+ if (!strcmp(settings->imagefmt,"elf"))
+ cctx->drvflags |= SLBT_DRIVER_IMAGE_ELF;
+ else if (!strcmp(settings->imagefmt,"pe"))
+ cctx->drvflags |= SLBT_DRIVER_IMAGE_PE;
+ else if (!strcmp(settings->imagefmt,"macho"))
+ cctx->drvflags |= SLBT_DRIVER_IMAGE_MACHO;
+ }
+
+ memcpy(psettings,settings,sizeof(*settings));
+
+ if (cctx->shrext)
+ psettings->dsosuffix = cctx->shrext;
+}
+
+
+int slbt_init_ldrpath(
+ struct slbt_common_ctx * cctx,
+ struct slbt_host_params * host)
+{
+ char * buf;
+ const char ** ldrpath;
+
+ if (!cctx->rpath || !(cctx->drvflags & SLBT_DRIVER_IMAGE_ELF)) {
+ host->ldrpath = 0;
+ return 0;
+ }
+
+ /* common? */
+ for (ldrpath=ldrpath_elf; *ldrpath; ldrpath ++)
+ if (!(strcmp(cctx->rpath,*ldrpath))) {
+ host->ldrpath = 0;
+ return 0;
+ }
+
+ /* buf */
+ if (!(buf = malloc(12 + strlen(cctx->host.host))))
+ return -1;
+
+ /* /usr/{host}/lib */
+ sprintf(buf,"/usr/%s/lib",cctx->host.host);
+
+ if (!(strcmp(cctx->rpath,buf))) {
+ host->ldrpath = 0;
+ free(buf);
+ return 0;
+ }
+
+ /* /usr/{host}/lib64 */
+ sprintf(buf,"/usr/%s/lib64",cctx->host.host);
+
+ if (!(strcmp(cctx->rpath,buf))) {
+ host->ldrpath = 0;
+ free(buf);
+ return 0;
+ }
+
+ host->ldrpath = cctx->rpath;
+
+ free(buf);
+ return 0;
+}
+
+
+void slbt_reset_alternate_host(const struct slbt_driver_ctx * ctx)
+{
+ struct slbt_driver_ctx_alloc * ictx;
+ uintptr_t addr;
+
+ addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
+ addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
+ ictx = (struct slbt_driver_ctx_alloc *)addr;
+
+ slbt_free_host_params(&ictx->ctx.ahost);
+}
+
+int slbt_set_alternate_host(
+ const struct slbt_driver_ctx * ctx,
+ const char * host,
+ const char * flavor)
+{
+ struct slbt_driver_ctx_alloc * ictx;
+ uintptr_t addr;
+
+ addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
+ addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
+ ictx = (struct slbt_driver_ctx_alloc *)addr;
+ slbt_free_host_params(&ictx->ctx.ahost);
+
+ if (!(ictx->ctx.ahost.host = strdup(host)))
+ return SLBT_SYSTEM_ERROR(ctx,0);
+
+ if (!(ictx->ctx.ahost.flavor = strdup(flavor))) {
+ slbt_free_host_params(&ictx->ctx.ahost);
+ return SLBT_SYSTEM_ERROR(ctx,0);
+ }
+
+ ictx->ctx.cctx.ahost.host = ictx->ctx.ahost.host;
+ ictx->ctx.cctx.ahost.flavor = ictx->ctx.ahost.flavor;
+
+ if (slbt_init_host_params(
+ 0,
+ ctx->cctx,
+ &ictx->ctx.ahost,
+ &ictx->ctx.cctx.ahost,
+ &ictx->ctx.cctx.acfgmeta,
+ 0,0)) {
+ slbt_free_host_params(&ictx->ctx.ahost);
+ return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_HOST_INIT);
+ }
+
+ slbt_init_flavor_settings(
+ &ictx->ctx.cctx,
+ &ictx->ctx.cctx.ahost,
+ &ictx->ctx.cctx.asettings);
+
+ if (slbt_init_ldrpath(
+ &ictx->ctx.cctx,
+ &ictx->ctx.cctx.ahost)) {
+ slbt_free_host_params(&ictx->ctx.ahost);
+ return SLBT_CUSTOM_ERROR(ctx,SLBT_ERR_LDRPATH_INIT);
+ }
+
+ return 0;
+}
+
+int slbt_get_flavor_settings(
+ const char * flavor,
+ const struct slbt_flavor_settings ** settings)
+{
+ if (!strcmp(flavor,"midipix"))
+ *settings = &host_flavor_midipix;
+ else if (!strcmp(flavor,"mingw"))
+ *settings = &host_flavor_mingw;
+ else if (!strcmp(flavor,"cygwin"))
+ *settings = &host_flavor_cygwin;
+ else if (!strcmp(flavor,"darwin"))
+ *settings = &host_flavor_darwin;
+ else if (!strcmp(flavor,"default"))
+ *settings = &host_flavor_default;
+ else
+ *settings = 0;
+
+ return *settings ? 0 : -1;
+}