|
|
3d5567 |
/*******************************************************************/
|
|
|
eac61a |
/* slibtool: a strong libtool implementation, written in C */
|
|
|
49181b |
/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
|
|
|
3d5567 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
3d5567 |
/*******************************************************************/
|
|
|
3d5567 |
|
|
|
3d5567 |
#include <stdarg.h>
|
|
|
3d5567 |
#include <stdlib.h>
|
|
|
3d5567 |
#include <stdio.h>
|
|
|
3d5567 |
#include <string.h>
|
|
|
3d5567 |
#include <fcntl.h>
|
|
|
3d5567 |
#include <errno.h>
|
|
|
3d5567 |
#include <sys/stat.h>
|
|
|
3d5567 |
|
|
|
3d5567 |
#include <slibtool/slibtool.h>
|
|
|
3d5567 |
#include "slibtool_driver_impl.h"
|
|
|
3d5567 |
#include "slibtool_errinfo_impl.h"
|
|
|
752c02 |
#include "slibtool_spawn_impl.h"
|
|
|
3d5567 |
#include "slibtool_linkcmd_impl.h"
|
|
|
3d5567 |
#include "slibtool_mapfile_impl.h"
|
|
|
3d5567 |
#include "slibtool_metafile_impl.h"
|
|
|
3d5567 |
#include "slibtool_snprintf_impl.h"
|
|
|
3d5567 |
#include "slibtool_symlink_impl.h"
|
|
|
3d5567 |
#include "slibtool_readlink_impl.h"
|
|
|
4b56de |
#include "slibtool_visibility_impl.h"
|
|
|
a07095 |
#include "slibtool_ar_impl.h"
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
ec3617 |
static const char * slbt_ar_self_dlunit = "@PROGRAM@";
|
|
|
ec3617 |
|
|
|
3d5567 |
static int slbt_linkcmd_exit(
|
|
|
3d5567 |
struct slbt_deps_meta * depsmeta,
|
|
|
3d5567 |
int ret)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
if (depsmeta->altv)
|
|
|
3d5567 |
free(depsmeta->altv);
|
|
|
3d5567 |
|
|
|
3d5567 |
if (depsmeta->args)
|
|
|
3d5567 |
free(depsmeta->args);
|
|
|
3d5567 |
|
|
|
3d5567 |
return ret;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
3d5567 |
static int slbt_emit_fdwrap_amend_dl_path(
|
|
|
3d5567 |
const struct slbt_driver_ctx * dctx,
|
|
|
3d5567 |
struct slbt_exec_ctx * ectx,
|
|
|
3d5567 |
struct slbt_deps_meta * depsmeta,
|
|
|
3d5567 |
const char * fmt,
|
|
|
3d5567 |
...)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
va_list ap;
|
|
|
3d5567 |
char * buf;
|
|
|
3d5567 |
int cnt;
|
|
|
3d5567 |
char dlpathbuf[2048];
|
|
|
3d5567 |
int fdwrap;
|
|
|
3d5567 |
const char * fdwrap_fmt;
|
|
|
3d5567 |
int size;
|
|
|
3d5567 |
|
|
|
3d5567 |
va_start(ap,fmt);
|
|
|
3d5567 |
|
|
|
3d5567 |
size = sizeof(dlpathbuf);
|
|
|
3d5567 |
|
|
|
3d5567 |
buf = ((cnt = vsnprintf(dlpathbuf,size,fmt,ap)) < size)
|
|
|
3d5567 |
? dlpathbuf : malloc((size = cnt + 1));
|
|
|
3d5567 |
|
|
|
3d5567 |
va_end(ap);
|
|
|
3d5567 |
|
|
|
3d5567 |
if (buf == dlpathbuf) {
|
|
|
3d5567 |
(void)0;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (buf) {
|
|
|
3d5567 |
va_start(ap,fmt);
|
|
|
3d5567 |
vsprintf(buf,fmt,ap);
|
|
|
3d5567 |
va_end(ap);
|
|
|
3d5567 |
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((fdwrap = slbt_exec_get_fdwrapper(ectx)) >= 0) {
|
|
|
3d5567 |
if (buf[0] == '/') {
|
|
|
3d5567 |
fdwrap_fmt =
|
|
|
3d5567 |
"DL_PATH=\"${DL_PATH}${COLON}%s\"\n"
|
|
|
3d5567 |
"COLON=':'\n\n";
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
fdwrap_fmt =
|
|
|
3d5567 |
"DL_PATH=\"${DL_PATH}${COLON}${DL_PATH_FIXUP}%s\"\n"
|
|
|
3d5567 |
"COLON=':'\n\n";
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if (slbt_dprintf(fdwrap,fdwrap_fmt,buf) < 0) {
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
4b56de |
slbt_hidden bool slbt_adjust_object_argument(
|
|
|
3d5567 |
char * arg,
|
|
|
3d5567 |
bool fpic,
|
|
|
3d5567 |
bool fany,
|
|
|
3d5567 |
int fdcwd)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
char * slash;
|
|
|
3d5567 |
char * dot;
|
|
|
3d5567 |
char base[PATH_MAX];
|
|
|
3d5567 |
|
|
|
3d5567 |
if (*arg == '-')
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* object argument: foo.lo or foo.o */
|
|
|
3d5567 |
if (!(dot = strrchr(arg,'.')))
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((dot[1]=='l') && (dot[2]=='o') && !dot[3]) {
|
|
|
3d5567 |
dot[1] = 'o';
|
|
|
3d5567 |
dot[2] = 0;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if ((dot[1]=='o') && !dot[2]) {
|
|
|
3d5567 |
(void)0;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* foo.o requested and is present? */
|
|
|
3d5567 |
if (!fpic && !faccessat(fdcwd,arg,0,0))
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* .libs/foo.o */
|
|
|
3d5567 |
if ((slash = strrchr(arg,'/')))
|
|
|
3d5567 |
slash++;
|
|
|
3d5567 |
else
|
|
|
3d5567 |
slash = arg;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (slbt_snprintf(base,sizeof(base),
|
|
|
3d5567 |
"%s",slash) < 0)
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
sprintf(slash,".libs/%s",base);
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!faccessat(fdcwd,arg,0,0))
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* foo.o requested and neither is present? */
|
|
|
3d5567 |
if (!fpic) {
|
|
|
3d5567 |
strcpy(slash,base);
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* .libs/foo.o explicitly requested and is not present? */
|
|
|
3d5567 |
if (!fany)
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* use foo.o in place of .libs/foo.o */
|
|
|
3d5567 |
strcpy(slash,base);
|
|
|
3d5567 |
|
|
|
3d5567 |
if (faccessat(fdcwd,arg,0,0))
|
|
|
3d5567 |
sprintf(slash,".libs/%s",base);
|
|
|
3d5567 |
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
4b56de |
slbt_hidden bool slbt_adjust_wrapper_argument(
|
|
|
3d5567 |
char * arg,
|
|
|
d054ee |
bool fpic,
|
|
|
d054ee |
const char * suffix)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
char * slash;
|
|
|
3d5567 |
char * dot;
|
|
|
3d5567 |
char base[PATH_MAX];
|
|
|
3d5567 |
|
|
|
3d5567 |
if (*arg == '-')
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!(dot = strrchr(arg,'.')))
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (strcmp(dot,".la"))
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (fpic) {
|
|
|
3d5567 |
if ((slash = strrchr(arg,'/')))
|
|
|
3d5567 |
slash++;
|
|
|
3d5567 |
else
|
|
|
3d5567 |
slash = arg;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (slbt_snprintf(base,sizeof(base),
|
|
|
3d5567 |
"%s",slash) < 0)
|
|
|
3d5567 |
return false;
|
|
|
3d5567 |
|
|
|
3d5567 |
sprintf(slash,".libs/%s",base);
|
|
|
3d5567 |
dot = strrchr(arg,'.');
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
d054ee |
strcpy(dot,suffix);
|
|
|
3d5567 |
return true;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
4b56de |
slbt_hidden int slbt_adjust_linker_argument(
|
|
|
3d5567 |
const struct slbt_driver_ctx * dctx,
|
|
|
3d5567 |
char * arg,
|
|
|
3d5567 |
char ** xarg,
|
|
|
3d5567 |
bool fpic,
|
|
|
3d5567 |
const char * dsosuffix,
|
|
|
3d5567 |
const char * arsuffix,
|
|
|
3d5567 |
struct slbt_deps_meta * depsmeta)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
int fdcwd;
|
|
|
3d5567 |
int fdlib;
|
|
|
3d5567 |
char * slash;
|
|
|
3d5567 |
char * dot;
|
|
|
3d5567 |
char base[PATH_MAX];
|
|
|
3d5567 |
|
|
|
4ffae7 |
/* argv switch or non-library input argument? */
|
|
|
3d5567 |
if (*arg == '-')
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!(dot = strrchr(arg,'.')))
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
|
|
|
4ffae7 |
/* explicit .a input argument? */
|
|
|
3d5567 |
if (!(strcmp(dot,arsuffix))) {
|
|
|
3d5567 |
*xarg = arg;
|
|
|
3d5567 |
return slbt_get_deps_meta(dctx,arg,1,depsmeta);
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
4ffae7 |
/* explicit .so input argument? */
|
|
|
3d5567 |
if (!(strcmp(dot,dsosuffix)))
|
|
|
3d5567 |
return slbt_get_deps_meta(dctx,arg,1,depsmeta);
|
|
|
3d5567 |
|
|
|
4ffae7 |
/* not an .la library? */
|
|
|
3d5567 |
if (strcmp(dot,".la"))
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
|
|
|
4ffae7 |
/* .la file, associated .deps located under .libs */
|
|
|
4ffae7 |
if ((slash = strrchr(arg,'/'))) {
|
|
|
4ffae7 |
slash++;
|
|
|
4ffae7 |
} else {
|
|
|
4ffae7 |
slash = arg;
|
|
|
4ffae7 |
}
|
|
|
3d5567 |
|
|
|
4ffae7 |
if (slbt_snprintf(base,sizeof(base),
|
|
|
4ffae7 |
"%s",slash) < 0)
|
|
|
4ffae7 |
return 0;
|
|
|
3d5567 |
|
|
|
4ffae7 |
sprintf(slash,".libs/%s",base);
|
|
|
4ffae7 |
dot = strrchr(arg,'.');
|
|
|
3d5567 |
|
|
|
3d5567 |
/* fdcwd */
|
|
|
3d5567 |
fdcwd = slbt_driver_fdcwd(dctx);
|
|
|
3d5567 |
|
|
|
5cfb11 |
/* .a preferred but a.disabled present? */
|
|
|
5cfb11 |
sprintf(dot,"%s",arsuffix);
|
|
|
5cfb11 |
|
|
|
5cfb11 |
if (slbt_symlink_is_a_placeholder(fdcwd,arg))
|
|
|
5cfb11 |
fpic = true;
|
|
|
5cfb11 |
|
|
|
3d5567 |
/* shared library dependency? */
|
|
|
3d5567 |
if (fpic) {
|
|
|
3d5567 |
sprintf(dot,"%s",dsosuffix);
|
|
|
3d5567 |
|
|
|
4ffae7 |
if (slbt_symlink_is_a_placeholder(fdcwd,arg)) {
|
|
|
3d5567 |
sprintf(dot,"%s",arsuffix);
|
|
|
4ffae7 |
|
|
|
4ffae7 |
} else if ((fdlib = openat(fdcwd,arg,O_RDONLY)) >= 0) {
|
|
|
3d5567 |
close(fdlib);
|
|
|
4ffae7 |
|
|
|
4ffae7 |
} else {
|
|
|
3d5567 |
sprintf(dot,"%s",arsuffix);
|
|
|
4ffae7 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
return slbt_get_deps_meta(dctx,arg,0,depsmeta);
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* input archive */
|
|
|
3d5567 |
sprintf(dot,"%s",arsuffix);
|
|
|
3d5567 |
return slbt_get_deps_meta(dctx,arg,0,depsmeta);
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
4b56de |
slbt_hidden int slbt_exec_link_adjust_argument_vector(
|
|
|
3d5567 |
const struct slbt_driver_ctx * dctx,
|
|
|
3d5567 |
struct slbt_exec_ctx * ectx,
|
|
|
3d5567 |
struct slbt_deps_meta * depsmeta,
|
|
|
3d5567 |
const char * cwd,
|
|
|
3d5567 |
bool flibrary)
|
|
|
3d5567 |
{
|
|
|
3d5567 |
int fd;
|
|
|
3d5567 |
int fdcwd;
|
|
|
3d5567 |
char ** carg;
|
|
|
3d5567 |
char ** aarg;
|
|
|
3d5567 |
char * slash;
|
|
|
3d5567 |
char * mark;
|
|
|
3d5567 |
char * darg;
|
|
|
3d5567 |
char * dot;
|
|
|
3d5567 |
char * base;
|
|
|
3d5567 |
char * dpath;
|
|
|
3d5567 |
int argc;
|
|
|
3d5567 |
char arg[PATH_MAX];
|
|
|
3d5567 |
char lib[PATH_MAX];
|
|
|
3d5567 |
char depdir [PATH_MAX];
|
|
|
3d5567 |
char rpathdir[PATH_MAX];
|
|
|
3d5567 |
char rpathlnk[PATH_MAX];
|
|
|
3d5567 |
struct stat st;
|
|
|
3d5567 |
size_t size;
|
|
|
3d5567 |
size_t dlen;
|
|
|
9c528f |
struct slbt_map_info * mapinfo = 0;
|
|
|
3d5567 |
bool fwholearchive = false;
|
|
|
3d5567 |
int ret;
|
|
|
3d5567 |
|
|
|
3d5567 |
for (argc=0,carg=ectx->cargv; *carg; carg++)
|
|
|
3d5567 |
argc++;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!(depsmeta->args = calloc(1,depsmeta->infolen)))
|
|
|
3d5567 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
3d5567 |
|
|
|
3d5567 |
argc *= 3;
|
|
|
3d5567 |
argc += depsmeta->depscnt;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!(depsmeta->altv = calloc(argc,sizeof(char *))))
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
3d5567 |
|
|
|
3d5567 |
fdcwd = slbt_driver_fdcwd(dctx);
|
|
|
3d5567 |
|
|
|
3d5567 |
carg = ectx->cargv;
|
|
|
3d5567 |
aarg = depsmeta->altv;
|
|
|
3d5567 |
darg = depsmeta->args;
|
|
|
3d5567 |
size = depsmeta->infolen;
|
|
|
3d5567 |
|
|
|
3d5567 |
for (; *carg; ) {
|
|
|
3d5567 |
dpath = 0;
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!strcmp(*carg,"-Wl,--whole-archive"))
|
|
|
3d5567 |
fwholearchive = true;
|
|
|
3d5567 |
else if (!strcmp(*carg,"-Wl,--no-whole-archive"))
|
|
|
3d5567 |
fwholearchive = false;
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
3d5567 |
/* output annotation */
|
|
|
3d5567 |
if (carg == ectx->lout[0]) {
|
|
|
3d5567 |
ectx->mout[0] = &aarg[0];
|
|
|
3d5567 |
ectx->mout[1] = &aarg[1];
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* argument translation */
|
|
|
3d5567 |
mark = *carg;
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((mark[0] == '-') && (mark[1] == 'L')) {
|
|
|
b5f778 |
if ((ret = slbt_emit_fdwrap_amend_dl_path(
|
|
|
b5f778 |
dctx,ectx,depsmeta,
|
|
|
b5f778 |
"%s",&mark[2])) < 0)
|
|
|
b5f778 |
return ret;
|
|
|
3d5567 |
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (**carg == '-') {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (!(dot = strrchr(*carg,'.'))) {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (ectx->xargv[carg - ectx->cargv]) {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (!(strcmp(dot,".a"))) {
|
|
|
270b46 |
if (flibrary && !fwholearchive) {
|
|
|
270b46 |
strcpy(lib,*carg);
|
|
|
270b46 |
dot = strrchr(lib,'.');
|
|
|
270b46 |
strcpy(dot,".lai");
|
|
|
270b46 |
|
|
|
270b46 |
if ((fd = openat(fdcwd,lib,O_RDONLY,0)) < 0)
|
|
|
270b46 |
*aarg++ = "-Wl,--whole-archive";
|
|
|
270b46 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
dpath = lib;
|
|
|
3d5567 |
sprintf(lib,"%s.slibtool.deps",*carg);
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
270b46 |
if (flibrary && !fwholearchive) {
|
|
|
270b46 |
if (fd < 0) {
|
|
|
270b46 |
*aarg++ = "-Wl,--no-whole-archive";
|
|
|
270b46 |
} else {
|
|
|
270b46 |
close(fd);
|
|
|
270b46 |
}
|
|
|
270b46 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (strcmp(dot,dctx->cctx->settings.dsosuffix)) {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (carg == ectx->lout[1]) {
|
|
|
3d5567 |
/* ^^^hoppla^^^ */
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
/* -rpath */
|
|
|
3d5567 |
sprintf(rpathlnk,"%s.slibtool.rpath",*carg);
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!fstatat(fdcwd,rpathlnk,&st,AT_SYMLINK_NOFOLLOW)) {
|
|
|
3d5567 |
if (slbt_readlinkat(
|
|
|
3d5567 |
fdcwd,
|
|
|
3d5567 |
rpathlnk,
|
|
|
3d5567 |
rpathdir,
|
|
|
3d5567 |
sizeof(rpathdir)))
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_SYSTEM_ERROR(dctx,rpathlnk));
|
|
|
3d5567 |
|
|
|
3d5567 |
sprintf(darg,"-Wl,%s",rpathdir);
|
|
|
3d5567 |
*aarg++ = "-Wl,-rpath";
|
|
|
3d5567 |
*aarg++ = darg;
|
|
|
3d5567 |
darg += strlen(darg);
|
|
|
3d5567 |
darg++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
dpath = lib;
|
|
|
3d5567 |
sprintf(lib,"%s.slibtool.deps",*carg);
|
|
|
3d5567 |
|
|
|
3d5567 |
/* account for {'-','L','-','l'} */
|
|
|
3d5567 |
if (slbt_snprintf(arg,
|
|
|
3d5567 |
sizeof(arg) - 4,
|
|
|
3d5567 |
"%s",*carg) < 0)
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_BUFFER_ERROR(dctx));
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((slash = strrchr(arg,'/'))) {
|
|
|
3d5567 |
sprintf(*carg,"-L%s",arg);
|
|
|
3d5567 |
|
|
|
3d5567 |
mark = strrchr(*carg,'/');
|
|
|
3d5567 |
*mark = 0;
|
|
|
3d5567 |
*slash = 0;
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((ret = slbt_emit_fdwrap_amend_dl_path(
|
|
|
3d5567 |
dctx,ectx,depsmeta,
|
|
|
3d5567 |
"%s%s%s",
|
|
|
3d5567 |
((arg[0] == '/') ? "" : cwd),
|
|
|
3d5567 |
((arg[0] == '/') ? "" : "/"),
|
|
|
3d5567 |
arg)) < 0) {
|
|
|
3d5567 |
return ret;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
dlen = strlen(dctx->cctx->settings.dsoprefix);
|
|
|
3d5567 |
|
|
|
3d5567 |
/* -module? (todo: non-portable usage, display warning) */
|
|
|
3d5567 |
if (strncmp(++slash,dctx->cctx->settings.dsoprefix,dlen)) {
|
|
|
3d5567 |
*--slash = '/';
|
|
|
3d5567 |
strcpy(*carg,arg);
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
*aarg++ = ++mark;
|
|
|
3d5567 |
|
|
|
3d5567 |
slash += dlen;
|
|
|
3d5567 |
|
|
|
3d5567 |
sprintf(mark,"-l%s",slash);
|
|
|
3d5567 |
dot = strrchr(mark,'.');
|
|
|
3d5567 |
*dot = 0;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
*aarg++ = *carg++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if (dpath && !fstatat(fdcwd,dpath,&st,0)) {
|
|
|
3d5567 |
if (!(mapinfo = slbt_map_file(
|
|
|
3d5567 |
fdcwd,dpath,
|
|
|
3d5567 |
SLBT_MAP_INPUT)))
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_SYSTEM_ERROR(dctx,dpath));
|
|
|
3d5567 |
|
|
|
3d5567 |
if (!(strncmp(lib,".libs/",6))) {
|
|
|
3d5567 |
*aarg++ = "-L.libs";
|
|
|
3d5567 |
lib[1] = 0;
|
|
|
3d5567 |
} else if ((base = strrchr(lib,'/'))) {
|
|
|
3d5567 |
if (base - lib == 5) {
|
|
|
3d5567 |
if (!(strncmp(&base[-5],".libs/",6)))
|
|
|
3d5567 |
base -= 4;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else if (base - lib >= 6) {
|
|
|
3d5567 |
if (!(strncmp(&base[-6],"/.libs/",7)))
|
|
|
3d5567 |
base -= 6;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
*base = 0;
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
lib[0] = '.';
|
|
|
3d5567 |
lib[1] = 0;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
while (mapinfo->mark < mapinfo->cap) {
|
|
|
3d5567 |
if (slbt_mapped_readline(dctx,mapinfo,darg,size))
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_NESTED_ERROR(dctx));
|
|
|
3d5567 |
|
|
|
7a6d89 |
if (darg[0] != '#') {
|
|
|
7a6d89 |
*aarg++ = darg;
|
|
|
7a6d89 |
}
|
|
|
3d5567 |
|
|
|
7a6d89 |
mark = darg;
|
|
|
3d5567 |
dlen = strlen(darg);
|
|
|
3d5567 |
size -= dlen;
|
|
|
3d5567 |
darg += dlen;
|
|
|
3d5567 |
darg[-1] = 0;
|
|
|
3d5567 |
|
|
|
198205 |
/* handle -L... and ::... as needed */
|
|
|
3d5567 |
if ((mark[0] == '-')
|
|
|
3d5567 |
&& (mark[1] == 'L')
|
|
|
3d5567 |
&& (mark[2] != '/')) {
|
|
|
3d5567 |
if (strlen(mark) >= sizeof(depdir) - 1)
|
|
|
3d5567 |
return slbt_linkcmd_exit(
|
|
|
3d5567 |
depsmeta,
|
|
|
3d5567 |
SLBT_BUFFER_ERROR(dctx));
|
|
|
3d5567 |
|
|
|
3d5567 |
darg = mark;
|
|
|
3d5567 |
strcpy(depdir,&mark[2]);
|
|
|
3d5567 |
sprintf(darg,"-L%s/%s",lib,depdir);
|
|
|
3d5567 |
|
|
|
3d5567 |
darg += strlen(darg);
|
|
|
3d5567 |
darg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
if ((ret = slbt_emit_fdwrap_amend_dl_path(
|
|
|
3d5567 |
dctx,ectx,depsmeta,
|
|
|
3d5567 |
"%s/%s",lib,depdir)) < 0)
|
|
|
3d5567 |
return ret;
|
|
|
3d5567 |
|
|
|
198205 |
} else if ((mark[0] == ':') && (mark[1] == ':')) {
|
|
|
198205 |
if (strlen(mark) >= sizeof(depdir) - 1)
|
|
|
198205 |
return slbt_linkcmd_exit(
|
|
|
198205 |
depsmeta,
|
|
|
198205 |
SLBT_BUFFER_ERROR(dctx));
|
|
|
198205 |
|
|
|
198205 |
darg = mark;
|
|
|
198205 |
strcpy(depdir,&mark[2]);
|
|
|
198205 |
|
|
|
198205 |
sprintf(darg,"%s/%s",
|
|
|
198205 |
mark[2] == '/' ? "" : lib,
|
|
|
198205 |
depdir);
|
|
|
198205 |
|
|
|
198205 |
darg += strlen(darg);
|
|
|
198205 |
darg++;
|
|
|
198205 |
|
|
|
3d5567 |
} else if ((mark[0] == '-') && (mark[1] == 'L')) {
|
|
|
3d5567 |
if ((ret = slbt_emit_fdwrap_amend_dl_path(
|
|
|
3d5567 |
dctx,ectx,depsmeta,
|
|
|
3d5567 |
"%s",&mark[2])) < 0)
|
|
|
3d5567 |
return ret;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
9c528f |
|
|
|
9c528f |
if (mapinfo) {
|
|
|
9c528f |
slbt_unmap_file(mapinfo);
|
|
|
9c528f |
mapinfo = 0;
|
|
|
9c528f |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if (dctx->cctx->drvflags & SLBT_DRIVER_EXPORT_DYNAMIC)
|
|
|
d68d02 |
if (!slbt_host_objfmt_is_coff(dctx))
|
|
|
d68d02 |
*aarg++ = "-Wl,--export-dynamic";
|
|
|
3d5567 |
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
|
|
|
752c02 |
static int slbt_exec_link_remove_file(
|
|
|
752c02 |
const struct slbt_driver_ctx * dctx,
|
|
|
752c02 |
struct slbt_exec_ctx * ectx,
|
|
|
752c02 |
const char * target)
|
|
|
752c02 |
{
|
|
|
752c02 |
int fdcwd;
|
|
|
752c02 |
|
|
|
752c02 |
(void)ectx;
|
|
|
752c02 |
|
|
|
752c02 |
/* fdcwd */
|
|
|
752c02 |
fdcwd = slbt_driver_fdcwd(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
/* remove target (if any) */
|
|
|
752c02 |
if (!unlinkat(fdcwd,target,0) || (errno == ENOENT))
|
|
|
752c02 |
return 0;
|
|
|
752c02 |
|
|
|
752c02 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
752c02 |
}
|
|
|
752c02 |
|
|
|
752c02 |
|
|
|
752c02 |
static int slbt_exec_link_create_expsyms_archive(
|
|
|
752c02 |
const struct slbt_driver_ctx * dctx,
|
|
|
752c02 |
struct slbt_exec_ctx * ectx,
|
|
|
752c02 |
char ** lobjv,
|
|
|
ec3617 |
char ** cnvlv,
|
|
|
ec3617 |
char (*arname)[PATH_MAX])
|
|
|
752c02 |
{
|
|
|
752c02 |
int ret;
|
|
|
752c02 |
char * dot;
|
|
|
752c02 |
char ** argv;
|
|
|
752c02 |
char ** aarg;
|
|
|
752c02 |
char ** parg;
|
|
|
752c02 |
struct slbt_archive_ctx * arctx;
|
|
|
752c02 |
char ** ectx_argv;
|
|
|
752c02 |
char * ectx_program;
|
|
|
752c02 |
char output [PATH_MAX];
|
|
|
ec3617 |
char program[PATH_MAX];
|
|
|
752c02 |
|
|
|
752c02 |
/* output */
|
|
|
752c02 |
if (slbt_snprintf(output,sizeof(output),
|
|
|
752c02 |
"%s",ectx->mapfilename) < 0)
|
|
|
752c02 |
return SLBT_BUFFER_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
if (!(dot = strrchr(output,'.')))
|
|
|
752c02 |
return SLBT_CUSTOM_ERROR(
|
|
|
752c02 |
dctx,
|
|
|
752c02 |
SLBT_ERR_FLOW_ERROR);
|
|
|
752c02 |
|
|
|
5b42a8 |
/* .expsyms.xxx --> .expsyms.a */
|
|
|
752c02 |
dot[1] = 'a';
|
|
|
752c02 |
dot[2] = '\0';
|
|
|
752c02 |
|
|
|
ec3617 |
if (arname)
|
|
|
ec3617 |
strcpy(*arname,output);
|
|
|
ec3617 |
|
|
|
752c02 |
/* tool-specific argument vector */
|
|
|
752c02 |
argv = (slbt_get_driver_ictx(dctx))->host.ar_argv;
|
|
|
752c02 |
|
|
|
752c02 |
/* ar alternate argument vector */
|
|
|
752c02 |
if (!argv)
|
|
|
752c02 |
if (slbt_snprintf(program,sizeof(program),
|
|
|
752c02 |
"%s",dctx->cctx->host.ar) < 0)
|
|
|
752c02 |
return SLBT_BUFFER_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
/* ar command argument vector */
|
|
|
752c02 |
aarg = lobjv;
|
|
|
752c02 |
|
|
|
752c02 |
if ((parg = argv)) {
|
|
|
752c02 |
for (; *parg; )
|
|
|
752c02 |
*aarg++ = *parg++;
|
|
|
752c02 |
} else {
|
|
|
752c02 |
*aarg++ = program;
|
|
|
752c02 |
}
|
|
|
752c02 |
|
|
|
752c02 |
*aarg++ = "-crs";
|
|
|
752c02 |
*aarg++ = output;
|
|
|
752c02 |
|
|
|
752c02 |
ectx_argv = ectx->argv;
|
|
|
752c02 |
ectx_program = ectx->program;
|
|
|
752c02 |
|
|
|
752c02 |
ectx->argv = lobjv;
|
|
|
752c02 |
ectx->program = ectx->argv[0];
|
|
|
752c02 |
|
|
|
752c02 |
/* step output */
|
|
|
752c02 |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
|
|
|
752c02 |
if (slbt_output_link(ectx))
|
|
|
752c02 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
/* remove old archive as needed */
|
|
|
752c02 |
if (slbt_exec_link_remove_file(dctx,ectx,output))
|
|
|
752c02 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
/* ar spawn */
|
|
|
752c02 |
if ((slbt_spawn(ectx,true) < 0) && (ectx->pid < 0)) {
|
|
|
752c02 |
return SLBT_SPAWN_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
} else if (ectx->exitcode) {
|
|
|
752c02 |
return SLBT_CUSTOM_ERROR(
|
|
|
752c02 |
dctx,
|
|
|
752c02 |
SLBT_ERR_AR_ERROR);
|
|
|
752c02 |
}
|
|
|
752c02 |
|
|
|
752c02 |
/* restore link command ectx */
|
|
|
752c02 |
ectx->argv = ectx_argv;
|
|
|
752c02 |
ectx->program = ectx_program;
|
|
|
752c02 |
|
|
|
752c02 |
/* input objects associated with .la archives */
|
|
|
752c02 |
for (parg=cnvlv; *parg; parg++)
|
|
|
752c02 |
if (slbt_util_import_archive(ectx,output,*parg))
|
|
|
752c02 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
752c02 |
|
|
|
752c02 |
/* do the thing */
|
|
|
752c02 |
if (slbt_ar_get_archive_ctx(dctx,output,&arctx) < 0)
|
|
|
752c02 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
752c02 |
|
|
|
5b42a8 |
/* .expsyms.a --> .exp */
|
|
|
ac4a1b |
if ((*dot = '\0'), !(dot = strrchr(output,'.'))) {
|
|
|
ac4a1b |
slbt_ar_free_archive_ctx(arctx);
|
|
|
ac4a1b |
return SLBT_CUSTOM_ERROR(
|
|
|
ac4a1b |
dctx,
|
|
|
ac4a1b |
SLBT_ERR_FLOW_ERROR);
|
|
|
ac4a1b |
}
|
|
|
ac4a1b |
|
|
|
ac4a1b |
dot[1] = 'e';
|
|
|
ac4a1b |
dot[2] = 'x';
|
|
|
ac4a1b |
dot[3] = 'p';
|
|
|
ac4a1b |
dot[4] = '\0';
|
|
|
ac4a1b |
|
|
|
ac4a1b |
/* symfile */
|
|
|
ac4a1b |
if (dctx->cctx->expsyms) {
|
|
|
ac4a1b |
struct slbt_symlist_ctx * sctx;
|
|
|
ac4a1b |
sctx = (slbt_get_exec_ictx(ectx))->sctx;
|
|
|
ac4a1b |
|
|
|
ac4a1b |
ret = slbt_util_create_symfile(
|
|
|
ac4a1b |
sctx,output,0644);
|
|
|
ac4a1b |
} else {
|
|
|
ac4a1b |
ret = slbt_ar_create_symfile(
|
|
|
ac4a1b |
arctx->meta,
|
|
|
ac4a1b |
output,
|
|
|
ac4a1b |
0644);
|
|
|
ac4a1b |
}
|
|
|
ac4a1b |
|
|
|
ac4a1b |
/* mapfile */
|
|
|
ac4a1b |
if ((ret == 0) && (dctx->cctx->regex)) {
|
|
|
ac4a1b |
ret = slbt_ar_create_mapfile(
|
|
|
ac4a1b |
arctx->meta,
|
|
|
ac4a1b |
ectx->mapfilename,
|
|
|
ac4a1b |
0644);
|
|
|
5b42a8 |
}
|
|
|
5b42a8 |
|
|
|
752c02 |
slbt_ar_free_archive_ctx(arctx);
|
|
|
752c02 |
|
|
|
ac4a1b |
return (ret < 0) ? SLBT_NESTED_ERROR(dctx) : 0;
|
|
|
752c02 |
}
|
|
|
752c02 |
|
|
|
752c02 |
|
|
|
4b56de |
slbt_hidden int slbt_exec_link_finalize_argument_vector(
|
|
|
3d5567 |
const struct slbt_driver_ctx * dctx,
|
|
|
3d5567 |
struct slbt_exec_ctx * ectx)
|
|
|
3d5567 |
{
|
|
|
30e15b |
size_t nargs;
|
|
|
3d5567 |
char * sargv[1024];
|
|
|
3d5567 |
char ** sargvbuf;
|
|
|
3d5567 |
char ** base;
|
|
|
3d5567 |
char ** parg;
|
|
|
752c02 |
char ** pcap;
|
|
|
752c02 |
char ** argv;
|
|
|
752c02 |
char ** mark;
|
|
|
3d5567 |
char ** aarg;
|
|
|
3d5567 |
char ** oarg;
|
|
|
752c02 |
char ** lobj;
|
|
|
752c02 |
char ** cnvl;
|
|
|
3d5567 |
char ** larg;
|
|
|
3d5567 |
char ** darg;
|
|
|
3d5567 |
char ** earg;
|
|
|
3d5567 |
char ** rarg;
|
|
|
3d5567 |
char ** aargv;
|
|
|
3d5567 |
char ** oargv;
|
|
|
752c02 |
char ** lobjv;
|
|
|
752c02 |
char ** cnvlv;
|
|
|
42187c |
char ** dlargv;
|
|
|
3d5567 |
char ** cap;
|
|
|
3d5567 |
char ** src;
|
|
|
3d5567 |
char ** dst;
|
|
|
3d5567 |
char * arg;
|
|
|
3d5567 |
char * dot;
|
|
|
3d5567 |
char * ccwrap;
|
|
|
abb1bf |
char * program;
|
|
|
3d5567 |
const char * arsuffix;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* vector size */
|
|
|
3d5567 |
base = ectx->argv;
|
|
|
3d5567 |
arsuffix = dctx->cctx->settings.arsuffix;
|
|
|
3d5567 |
|
|
|
3d5567 |
for (parg=base; *parg; parg++)
|
|
|
3d5567 |
(void)0;
|
|
|
3d5567 |
|
|
|
752c02 |
if (dctx->cctx->regex) {
|
|
|
752c02 |
argv = (slbt_get_driver_ictx(dctx))->host.ar_argv;
|
|
|
752c02 |
|
|
|
752c02 |
for (mark=argv; mark && *mark; mark++)
|
|
|
752c02 |
(void)0;
|
|
|
752c02 |
} else {
|
|
|
752c02 |
argv = 0;
|
|
|
752c02 |
mark = 0;
|
|
|
752c02 |
}
|
|
|
752c02 |
|
|
|
3d5567 |
/* buffer */
|
|
|
30e15b |
if ((nargs = ((parg - base) + (mark - argv))) < 256) {
|
|
|
3d5567 |
aargv = &sargv[0];
|
|
|
752c02 |
oargv = &sargv[1*256];
|
|
|
752c02 |
lobjv = &sargv[2*256];
|
|
|
752c02 |
cnvlv = &sargv[3*256];
|
|
|
3d5567 |
sargvbuf = 0;
|
|
|
3d5567 |
|
|
|
752c02 |
parg = &sargv[0];
|
|
|
752c02 |
pcap = &sargv[1024];
|
|
|
752c02 |
|
|
|
752c02 |
for (; parg
|
|
|
752c02 |
*parg++ = 0;
|
|
|
752c02 |
|
|
|
30e15b |
} else if (!(sargvbuf = calloc(4*(nargs+1),sizeof(char *)))) {
|
|
|
3d5567 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
3d5567 |
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
aargv = &sargvbuf[0];
|
|
|
30e15b |
oargv = &sargvbuf[1*(nargs+1)];
|
|
|
30e15b |
lobjv = &sargvbuf[2*(nargs+1)];
|
|
|
30e15b |
cnvlv = &sargvbuf[3*(nargs+1)];
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
752c02 |
aarg = aargv;
|
|
|
752c02 |
oarg = oargv;
|
|
|
752c02 |
cnvl = cnvlv;
|
|
|
752c02 |
lobj = lobjv;
|
|
|
752c02 |
|
|
|
752c02 |
/* -export-symbols-regex: lobjv in place: ar [arg] [arg] -crs <output> */
|
|
|
752c02 |
if (dctx->cctx->regex && argv)
|
|
|
752c02 |
lobj += mark - argv + 2;
|
|
|
752c02 |
else
|
|
|
752c02 |
lobj += 3;
|
|
|
752c02 |
|
|
|
3d5567 |
/* (program name) */
|
|
|
3d5567 |
parg = &base[1];
|
|
|
3d5567 |
|
|
|
3d5567 |
/* split object args from all other args, record output */
|
|
|
752c02 |
/* annotation, and remove redundant -l arguments; and */
|
|
|
752c02 |
/* create additional vectors of all input objects as */
|
|
|
752c02 |
/* convenience libraries for -export-symbols-regex. */
|
|
|
3d5567 |
for (; *parg; ) {
|
|
|
3d5567 |
if (ectx->lout[0] == parg) {
|
|
|
3d5567 |
ectx->lout[0] = &aarg[0];
|
|
|
3d5567 |
ectx->lout[1] = &aarg[1];
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if (ectx->mout[0] == parg) {
|
|
|
3d5567 |
ectx->mout[0] = &aarg[0];
|
|
|
3d5567 |
ectx->mout[1] = &aarg[1];
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
arg = *parg;
|
|
|
3d5567 |
dot = strrchr(arg,'.');
|
|
|
3d5567 |
|
|
|
3d5567 |
/* object input argument? */
|
|
|
3d5567 |
if (dot && (!strcmp(dot,".o") || !strcmp(dot,".lo"))) {
|
|
|
752c02 |
*lobj++ = *parg;
|
|
|
3d5567 |
*oarg++ = *parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* --whole-archive input argument? */
|
|
|
3d5567 |
} else if ((arg[0] == '-')
|
|
|
3d5567 |
&& (arg[1] == 'W')
|
|
|
3d5567 |
&& (arg[2] == 'l')
|
|
|
3d5567 |
&& (arg[3] == ',')
|
|
|
3d5567 |
&& !strcmp(&arg[4],"--whole-archive")
|
|
|
3d5567 |
&& parg[1] && parg[2]
|
|
|
3d5567 |
&& !strcmp(parg[2],"-Wl,--no-whole-archive")
|
|
|
3d5567 |
&& (dot = strrchr(parg[1],'.'))
|
|
|
3d5567 |
&& !strcmp(dot,arsuffix)) {
|
|
|
752c02 |
*cnvl++ = parg[1];
|
|
|
3d5567 |
*oarg++ = *parg++;
|
|
|
3d5567 |
*oarg++ = *parg++;
|
|
|
3d5567 |
*oarg++ = *parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* local archive input argument? */
|
|
|
3d5567 |
} else if (dot && !strcmp(dot,arsuffix)) {
|
|
|
35000f |
*aarg++ = *parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* -l argument? */
|
|
|
3d5567 |
} else if ((parg[0][0] == '-') && (parg[0][1] == 'l')) {
|
|
|
3d5567 |
/* find the previous occurence of this -l argument */
|
|
|
3d5567 |
for (rarg=0, larg=&aarg[-1]; !rarg && (larg>=aargv); larg--)
|
|
|
3d5567 |
if (!strcmp(*larg,*parg))
|
|
|
3d5567 |
rarg = larg;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* first occurence of this specific -l argument? */
|
|
|
3d5567 |
if (!rarg) {
|
|
|
3d5567 |
*aarg++ = *parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
larg = rarg;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* if all -l arguments following the previous */
|
|
|
3d5567 |
/* occurence had already appeared before the */
|
|
|
3d5567 |
/* previous argument, then the current */
|
|
|
3d4e32 |
/* occurence is (possibly) redundant. */
|
|
|
3d5567 |
|
|
|
3d5567 |
for (darg=&larg[1]; rarg && darg
|
|
|
3d5567 |
/* only test -l arguments */
|
|
|
3d5567 |
if ((darg[0][0] == '-') && (darg[0][1] == 'l')) {
|
|
|
3d5567 |
for (rarg=0, earg=aargv; !rarg && earg
|
|
|
3d5567 |
if (!strcmp(*earg,*darg))
|
|
|
3d5567 |
rarg = darg;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d4e32 |
/* any archive (.a) input arguments between the */
|
|
|
3d4e32 |
/* current occurrence and the previous one? */
|
|
|
3d4e32 |
for (darg=&larg[1]; rarg && darg
|
|
|
3d4e32 |
if ((dot = strrchr(*darg,'.')))
|
|
|
3d4e32 |
if (!(strcmp(dot,arsuffix)))
|
|
|
3d4e32 |
rarg = 0;
|
|
|
3d4e32 |
|
|
|
3d5567 |
/* final verdict: repeated -l argument? */
|
|
|
3d5567 |
if (rarg) {
|
|
|
3d5567 |
parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
*aarg++ = *parg++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* -L argument? */
|
|
|
3d5567 |
} else if ((parg[0][0] == '-') && (parg[0][1] == 'L')) {
|
|
|
3d5567 |
/* find a previous occurence of this -L argument */
|
|
|
3d5567 |
for (rarg=0, larg=aargv; !rarg && (larg
|
|
|
3d5567 |
if (!strcmp(*larg,*parg))
|
|
|
3d5567 |
rarg = larg;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* repeated -L argument? */
|
|
|
3d5567 |
if (rarg) {
|
|
|
3d5567 |
parg++;
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
*aarg++ = *parg++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
42187c |
/* dlsyms vtable object must only be added once (see below) */
|
|
|
42187c |
} else if (!strcmp(*parg,"-dlpreopen")) {
|
|
|
42187c |
parg++;
|
|
|
42187c |
|
|
|
3d5567 |
/* placeholder argument? */
|
|
|
3d5567 |
} else if (!strncmp(*parg,"-USLIBTOOL_PLACEHOLDER_",23)) {
|
|
|
3d5567 |
parg++;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* all other arguments */
|
|
|
3d5567 |
} else {
|
|
|
3d5567 |
*aarg++ = *parg++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
42187c |
/* dlsyms vtable object inclusion */
|
|
|
42187c |
if (ectx->dlopenobj)
|
|
|
42187c |
*oarg++ = ectx->dlopenobj;
|
|
|
42187c |
|
|
|
ac4a1b |
/* export-symbols-regex, proper dlpreopen support */
|
|
|
ac4a1b |
if (dctx->cctx->libname)
|
|
|
752c02 |
if (slbt_exec_link_create_expsyms_archive(
|
|
|
ec3617 |
dctx,ectx,lobjv,cnvlv,0) < 0)
|
|
|
ec3617 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
ec3617 |
|
|
|
ec3617 |
/* -dlpreopen self */
|
|
|
ec3617 |
if (dctx->cctx->drvflags & SLBT_DRIVER_DLPREOPEN_SELF) {
|
|
|
ec3617 |
struct slbt_archive_ctx * arctx;
|
|
|
ec3617 |
struct slbt_archive_ctx ** arctxv;
|
|
|
ec3617 |
struct slbt_exec_ctx_impl * ictx;
|
|
|
ec3617 |
char arname[PATH_MAX];
|
|
|
ec3617 |
|
|
|
ec3617 |
ictx = slbt_get_exec_ictx(ectx);
|
|
|
ec3617 |
arctxv = ictx->dlactxv;
|
|
|
ec3617 |
arctx = 0;
|
|
|
ec3617 |
|
|
|
ec3617 |
/* add or repalce the archive context */
|
|
|
ec3617 |
for (; !arctx && *arctxv; )
|
|
|
a07095 |
if (!strcmp(*arctxv[0]->path,slbt_ar_self_dlunit))
|
|
|
ec3617 |
arctx = *arctxv;
|
|
|
ec3617 |
else
|
|
|
ec3617 |
arctxv++;
|
|
|
ec3617 |
|
|
|
ec3617 |
if (arctx)
|
|
|
ec3617 |
slbt_ar_free_archive_ctx(arctx);
|
|
|
ec3617 |
|
|
|
ec3617 |
if (slbt_exec_link_create_expsyms_archive(
|
|
|
ec3617 |
dctx,ectx,lobjv,cnvlv,&arname) < 0)
|
|
|
ec3617 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
ec3617 |
|
|
|
ec3617 |
if (slbt_ar_get_archive_ctx(dctx,arname,arctxv) < 0)
|
|
|
752c02 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
752c02 |
|
|
|
a07095 |
arctx = *arctxv;
|
|
|
a07095 |
arctx->path = &slbt_ar_self_dlunit;
|
|
|
a07095 |
|
|
|
3077bb |
if (slbt_ar_update_syminfo(arctx) < 0)
|
|
|
a07095 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
ec3617 |
|
|
|
ec3617 |
/* regenerate the dlsyms vtable source */
|
|
|
ec3617 |
if (slbt_ar_create_dlsyms(
|
|
|
ec3617 |
ictx->dlactxv,
|
|
|
ec3617 |
ectx->dlunit,
|
|
|
ec3617 |
ectx->dlopensrc,
|
|
|
ec3617 |
0644) < 0)
|
|
|
ec3617 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
ec3617 |
}
|
|
|
ec3617 |
|
|
|
3d5567 |
/* program name, ccwrap */
|
|
|
3d5567 |
if ((ccwrap = (char *)dctx->cctx->ccwrap)) {
|
|
|
3d5567 |
base[1] = base[0];
|
|
|
3d5567 |
base[0] = ccwrap;
|
|
|
3d5567 |
base++;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* join object args */
|
|
|
3d5567 |
src = oargv;
|
|
|
3d5567 |
cap = oarg;
|
|
|
3d5567 |
dst = &base[1];
|
|
|
3d5567 |
|
|
|
3d5567 |
for (; src
|
|
|
3d5567 |
*dst++ = *src++;
|
|
|
3d5567 |
|
|
|
a07095 |
/* dlpreopen */
|
|
|
a07095 |
if (ectx->dlpreopen)
|
|
|
a07095 |
*dst++ = ectx->dlpreopen;
|
|
|
a07095 |
|
|
|
c5c351 |
/* join all other args, eliminate no-op linker path args */
|
|
|
3d5567 |
src = aargv;
|
|
|
3d5567 |
cap = aarg;
|
|
|
3d5567 |
|
|
|
c5c351 |
for (; src
|
|
|
c5c351 |
if ((src[0][0] == '-') && (src[0][1] == 'L')) {
|
|
|
c5c351 |
for (larg=0,rarg=src; *rarg && !larg; rarg++)
|
|
|
c5c351 |
if ((rarg[0][0] == '-') && (rarg[0][1] == 'l'))
|
|
|
c5c351 |
larg = rarg;
|
|
|
c5c351 |
|
|
|
c5c351 |
if (larg) {
|
|
|
c5c351 |
*dst++ = *src++;
|
|
|
c5c351 |
} else {
|
|
|
c5c351 |
src++;
|
|
|
c5c351 |
}
|
|
|
c5c351 |
} else {
|
|
|
c5c351 |
*dst++ = *src++;
|
|
|
c5c351 |
}
|
|
|
c5c351 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
/* properly null-terminate argv, accounting for redundant -l arguments */
|
|
|
3d5567 |
*dst = 0;
|
|
|
3d5567 |
|
|
|
3d5567 |
/* output annotation */
|
|
|
3d5567 |
if (ectx->lout[0]) {
|
|
|
3d5567 |
ectx->lout[0] = &base[1] + (oarg - oargv) + (ectx->lout[0] - aargv);
|
|
|
3d5567 |
ectx->lout[1] = ectx->lout[0] + 1;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
3d5567 |
if (ectx->mout[0]) {
|
|
|
3d5567 |
ectx->mout[0] = &base[1] + (oarg - oargv) + (ectx->mout[0] - aargv);
|
|
|
3d5567 |
ectx->mout[1] = ectx->mout[0] + 1;
|
|
|
3d5567 |
}
|
|
|
3d5567 |
|
|
|
42187c |
/* dlsyms vtable object compilation */
|
|
|
42187c |
if (ectx->dlopenobj) {
|
|
|
42187c |
dlargv = (slbt_get_exec_ictx(ectx))->dlargv;
|
|
|
42187c |
*dlargv = base[0];
|
|
|
42187c |
|
|
|
42187c |
src = aargv;
|
|
|
42187c |
cap = aarg;
|
|
|
42187c |
dst = &dlargv[1];
|
|
|
42187c |
|
|
|
42187c |
/* compile argv, based on the linkcmd argv */
|
|
|
42187c |
for (; src
|
|
|
42187c |
if ((src[0][0] == '-') && (src[0][1] == '-')) {
|
|
|
42187c |
*dst++ = *src;
|
|
|
42187c |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'L')) {
|
|
|
42187c |
(void)0;
|
|
|
42187c |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'l')) {
|
|
|
42187c |
(void)0;
|
|
|
42187c |
|
|
|
99fb66 |
} else if ((dot = strrchr(*src,'.')) && (dot[1] == 'a') && !dot[2]) {
|
|
|
99fb66 |
(void)0;
|
|
|
99fb66 |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'o')) {
|
|
|
42187c |
src++;
|
|
|
42187c |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'D')) {
|
|
|
42187c |
if (!src[0][2])
|
|
|
42187c |
src++;
|
|
|
42187c |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'U')) {
|
|
|
42187c |
if (!src[0][2])
|
|
|
42187c |
src++;
|
|
|
42187c |
|
|
|
42187c |
} else if ((src[0][0] == '-') && (src[0][1] == 'W')) {
|
|
|
42187c |
if ((src[0][2] == 'a') && (src[0][3] == ','))
|
|
|
42187c |
*dst++ = *src;
|
|
|
99fb66 |
|
|
|
42187c |
} else {
|
|
|
42187c |
*dst++ = *src;
|
|
|
42187c |
}
|
|
|
42187c |
|
|
|
42187c |
src++;
|
|
|
42187c |
}
|
|
|
42187c |
|
|
|
42187c |
*dst++ = dctx->cctx->settings.picswitch
|
|
|
42187c |
? dctx->cctx->settings.picswitch
|
|
|
42187c |
: *ectx->fpic;
|
|
|
42187c |
|
|
|
42187c |
*dst++ = "-c";
|
|
|
42187c |
*dst++ = ectx->dlopensrc;
|
|
|
42187c |
|
|
|
42187c |
*dst++ = "-o";
|
|
|
42187c |
*dst++ = ectx->dlopenobj;
|
|
|
42187c |
|
|
|
abb1bf |
*dst++ = 0;
|
|
|
abb1bf |
|
|
|
42187c |
/* nested compile step */
|
|
|
abb1bf |
program = ectx->program;
|
|
|
abb1bf |
ectx->argv = dlargv;
|
|
|
abb1bf |
ectx->program = dlargv[0];
|
|
|
42187c |
|
|
|
42187c |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
|
|
|
42187c |
if (slbt_output_compile(ectx))
|
|
|
42187c |
return SLBT_NESTED_ERROR(dctx);
|
|
|
42187c |
|
|
|
42187c |
if ((slbt_spawn(ectx,true) < 0) && (ectx->pid < 0))
|
|
|
42187c |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
42187c |
|
|
|
42187c |
if (ectx->exitcode)
|
|
|
42187c |
return SLBT_CUSTOM_ERROR(
|
|
|
42187c |
dctx,
|
|
|
42187c |
SLBT_ERR_COMPILE_ERROR);
|
|
|
42187c |
|
|
|
abb1bf |
ectx->argv = base;
|
|
|
abb1bf |
ectx->program = program;
|
|
|
42187c |
}
|
|
|
42187c |
|
|
|
3d5567 |
/* all done */
|
|
|
3d5567 |
if (sargvbuf)
|
|
|
3d5567 |
free(sargvbuf);
|
|
|
3d5567 |
|
|
|
3d5567 |
return 0;
|
|
|
3d5567 |
}
|