diff --git a/project/common.mk b/project/common.mk index e8c60f4..1fa7ca9 100644 --- a/project/common.mk +++ b/project/common.mk @@ -11,6 +11,7 @@ API_SRCS = \ src/arbits/output/slbt_ar_output_members.c \ src/driver/slbt_amain.c \ src/driver/slbt_driver_ctx.c \ + src/driver/slbt_host_params.c \ src/fallback/slbt_archive_import_mri.c \ src/helper/slbt_archive_import.c \ src/helper/slbt_copy_file.c \ 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 "; + /* 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 "; -static const char cfglconf[] = "derived from "; -static const char cfgtarget[] = "derived from "; -static const char cfgcompiler[] = "derived from "; -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,"!\n"); - - arprobeargv[0] = drvhost->ar; - arprobeargv[1] = "-t"; - arprobeargv[2] = archivename; - arprobeargv[3] = 0; - - /* -ar */ - slbt_spawn_ar( - arprobeargv, - &ecode); - } - - /* --ar */ - if (ecode && !strchr(base,'-')) { - sprintf(drvhost->ar,"%s-%s-ar",host->host,base); - - slbt_spawn_ar( - arprobeargv, - &ecode); - } - - /* -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 +#include +#include +#include +#include +#include +#include +#include + +#include +#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 "; +static const char cfgtarget[] = "derived from "; +static const char cfgcompiler[] = "derived from "; +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,"!\n"); + + arprobeargv[0] = drvhost->ar; + arprobeargv[1] = "-t"; + arprobeargv[2] = archivename; + arprobeargv[3] = 0; + + /* -ar */ + slbt_spawn_ar( + arprobeargv, + &ecode); + } + + /* --ar */ + if (ecode && !strchr(base,'-')) { + sprintf(drvhost->ar,"%s-%s-ar",host->host,base); + + slbt_spawn_ar( + arprobeargv, + &ecode); + } + + /* -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; +} diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index c72f19e..32ae6c8 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -141,6 +141,12 @@ struct slbt_driver_ctx_impl { struct slbt_error_info erribuf[64]; }; +struct slbt_driver_ctx_alloc { + struct argv_meta * meta; + struct slbt_driver_ctx_impl ctx; + uint64_t guard; +}; + struct slbt_exec_ctx_impl { int argc; char * args; @@ -162,6 +168,31 @@ struct slbt_archive_ctx_impl { struct slbt_archive_ctx actx; }; + +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); + + +void slbt_free_host_params(struct slbt_host_strs * host); + + +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); + + static inline struct slbt_archive_ctx_impl * slbt_get_archive_ictx(const struct slbt_archive_ctx * actx) { uintptr_t addr;