|
|
528799 |
/*******************************************************************/
|
|
|
528799 |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
528799 |
/* Copyright (C) 2016 Z. Gilboa */
|
|
|
528799 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
528799 |
/*******************************************************************/
|
|
|
528799 |
|
|
|
528799 |
#include <stdint.h>
|
|
|
528799 |
#include <unistd.h>
|
|
|
528799 |
#include <stdlib.h>
|
|
|
528799 |
#include <string.h>
|
|
|
528799 |
|
|
|
528799 |
#include <slibtool/slibtool.h>
|
|
|
528799 |
|
|
|
528799 |
#define SLBT_ARGV_SPARE_PTRS 16
|
|
|
528799 |
|
|
|
528799 |
struct slbt_exec_ctx_impl {
|
|
|
528799 |
int argc;
|
|
|
528799 |
char * args;
|
|
|
e7ddb2 |
char * shadow;
|
|
|
e7ddb2 |
size_t size;
|
|
|
528799 |
struct slbt_exec_ctx ctx;
|
|
|
54d0a5 |
char * vbuffer[];
|
|
|
528799 |
};
|
|
|
528799 |
|
|
|
528799 |
|
|
|
528799 |
static size_t slbt_parse_comma_separated_flags(
|
|
|
528799 |
const char * str,
|
|
|
528799 |
int * argc)
|
|
|
528799 |
{
|
|
|
528799 |
const char * ch;
|
|
|
528799 |
|
|
|
528799 |
for (ch=str; *ch; ch++)
|
|
|
528799 |
if (*ch == ',')
|
|
|
528799 |
(*argc)++;
|
|
|
528799 |
|
|
|
528799 |
return ch - str;
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
528799 |
|
|
|
df088e |
static char * slbt_source_file(char ** argv)
|
|
|
df088e |
{
|
|
|
df088e |
char ** parg;
|
|
|
df088e |
char * ch;
|
|
|
df088e |
|
|
|
df088e |
for (parg=argv; *parg; parg++)
|
|
|
df088e |
if ((ch = strrchr(*parg,'.')))
|
|
|
df088e |
if ((!(strcmp(++ch,"s")))
|
|
|
df088e |
|| (!(strcmp(ch,"S")))
|
|
|
533d94 |
|| (!(strcmp(ch,"asm")))
|
|
|
df088e |
|| (!(strcmp(ch,"c")))
|
|
|
df088e |
|| (!(strcmp(ch,"cc")))
|
|
|
df088e |
|| (!(strcmp(ch,"cxx"))))
|
|
|
df088e |
return *parg;
|
|
|
df088e |
return 0;
|
|
|
df088e |
}
|
|
|
df088e |
|
|
|
df088e |
|
|
|
528799 |
static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc(
|
|
|
528799 |
const struct slbt_driver_ctx * dctx)
|
|
|
528799 |
{
|
|
|
528799 |
struct slbt_exec_ctx_impl * ictx;
|
|
|
528799 |
size_t size;
|
|
|
e7ddb2 |
size_t vsize;
|
|
|
528799 |
int argc;
|
|
|
528799 |
char * args;
|
|
|
e7ddb2 |
char * shadow;
|
|
|
df088e |
char * csrc;
|
|
|
528799 |
char ** parg;
|
|
|
528799 |
|
|
|
df088e |
argc = 0;
|
|
|
df088e |
csrc = 0;
|
|
|
df088e |
|
|
|
ef1e6e |
/* clerical [worst-case] buffer size (guard, .libs, version) */
|
|
|
ef1e6e |
size = strlen(".lo") + sizeof('\0');
|
|
|
f0c096 |
size += 8 * (strlen(".libs/") + sizeof('\0'));
|
|
|
ef1e6e |
size += 36 * (strlen(".0000") + sizeof('\0'));
|
|
|
528799 |
|
|
|
528799 |
/* buffer size (cargv, -Wc) */
|
|
|
528799 |
for (parg=dctx->cctx->cargv; *parg; parg++, argc++)
|
|
|
528799 |
if (!(strncmp("-Wc,",*parg,4)))
|
|
|
528799 |
size += sizeof('\0') + slbt_parse_comma_separated_flags(
|
|
|
4c2181 |
&(*parg)[4],&argc);
|
|
|
528799 |
else
|
|
|
528799 |
size += sizeof('\0') + strlen(*parg);
|
|
|
528799 |
|
|
|
e88a39 |
/* buffer size (ldirname, lbasename, lobjname, aobjname, ltobjname) */
|
|
|
df088e |
if (dctx->cctx->output)
|
|
|
e02305 |
size += 4*strlen(dctx->cctx->output);
|
|
|
df088e |
else if ((csrc = slbt_source_file(dctx->cctx->cargv)))
|
|
|
e02305 |
size += 4*strlen(csrc);
|
|
|
df088e |
|
|
|
0919b0 |
/* buffer size (.libs/%.o, pessimistic) */
|
|
|
0919b0 |
size += argc * strlen(".libs/");
|
|
|
0919b0 |
|
|
|
f0c096 |
/* buffer size (linking) */
|
|
|
f0c096 |
if (dctx->cctx->mode == SLBT_MODE_LINK)
|
|
|
f0c096 |
size += strlen(dctx->cctx->settings.arprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.arsuffix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.dsoprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.dsoprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.exeprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.exeprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.impprefix) + sizeof('\0')
|
|
|
f0c096 |
+ strlen(dctx->cctx->settings.impprefix) + sizeof('\0');
|
|
|
f0c096 |
|
|
|
528799 |
/* alloc */
|
|
|
df088e |
if (!(args = malloc(size)))
|
|
|
528799 |
return 0;
|
|
|
528799 |
|
|
|
e7ddb2 |
if (!(shadow = malloc(size))) {
|
|
|
e7ddb2 |
free(args);
|
|
|
e7ddb2 |
return 0;
|
|
|
e7ddb2 |
}
|
|
|
e7ddb2 |
|
|
|
e7ddb2 |
vsize = sizeof(*ictx) + (2*(argc+1)+SLBT_ARGV_SPARE_PTRS)*sizeof(char *);
|
|
|
528799 |
|
|
|
e7ddb2 |
if (!(ictx = calloc(1,vsize))) {
|
|
|
528799 |
free(args);
|
|
|
e7ddb2 |
free(shadow);
|
|
|
528799 |
return 0;
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
528799 |
ictx->args = args;
|
|
|
528799 |
ictx->argc = argc;
|
|
|
528799 |
|
|
|
e7ddb2 |
ictx->size = size;
|
|
|
e7ddb2 |
ictx->shadow = shadow;
|
|
|
e7ddb2 |
|
|
|
df088e |
ictx->ctx.csrc = csrc;
|
|
|
df088e |
|
|
|
528799 |
return ictx;
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
528799 |
|
|
|
528799 |
int slbt_get_exec_ctx(
|
|
|
528799 |
const struct slbt_driver_ctx * dctx,
|
|
|
528799 |
struct slbt_exec_ctx ** ectx)
|
|
|
528799 |
{
|
|
|
528799 |
struct slbt_exec_ctx_impl * ictx;
|
|
|
528799 |
char ** parg;
|
|
|
528799 |
char * ch;
|
|
|
014f4c |
char * mark;
|
|
|
f47761 |
char * slash;
|
|
|
df088e |
const char * ref;
|
|
|
528799 |
int i;
|
|
|
528799 |
|
|
|
528799 |
/* alloc */
|
|
|
528799 |
if (!(ictx = slbt_exec_ctx_alloc(dctx)))
|
|
|
528799 |
return -1;
|
|
|
528799 |
|
|
|
528799 |
/* init with guard for later .lo check */
|
|
|
528799 |
ch = ictx->args + strlen(".lo");
|
|
|
54d0a5 |
ictx->ctx.argv = ictx->vbuffer;
|
|
|
54d0a5 |
ictx->ctx.altv = &ictx->vbuffer[ictx->argc + 1];
|
|
|
528799 |
|
|
|
528799 |
/* <compiler> */
|
|
|
27a8e1 |
ictx->ctx.compiler = dctx->cctx->cargv[0];
|
|
|
27a8e1 |
ictx->ctx.cargv = ictx->ctx.argv;
|
|
|
528799 |
|
|
|
df088e |
/* ldirname, lbasename */
|
|
|
df088e |
ref = (dctx->cctx->output)
|
|
|
df088e |
? dctx->cctx->output
|
|
|
df088e |
: ictx->ctx.csrc;
|
|
|
df088e |
|
|
|
014f4c |
if (ref && !ictx->ctx.csrc && (mark = strrchr(ref,'/'))) {
|
|
|
df088e |
ictx->ctx.ldirname = ch;
|
|
|
df088e |
strcpy(ch,ref);
|
|
|
014f4c |
ch += mark - ref;
|
|
|
df088e |
ch += sprintf(ch,"%s","/.libs/");
|
|
|
df088e |
ch++;
|
|
|
df088e |
|
|
|
df088e |
ictx->ctx.lbasename = ch;
|
|
|
014f4c |
ch += sprintf(ch,"%s",++mark);
|
|
|
df088e |
ch++;
|
|
|
df088e |
} else if (ref) {
|
|
|
df088e |
ictx->ctx.ldirname = ch;
|
|
|
df088e |
ch += sprintf(ch,"%s",".libs/");
|
|
|
df088e |
ch++;
|
|
|
df088e |
|
|
|
df088e |
ictx->ctx.lbasename = ch;
|
|
|
014f4c |
mark = strrchr(ref,'/');
|
|
|
014f4c |
ch += sprintf(ch,"%s",mark ? ++mark : ref);
|
|
|
df088e |
ch++;
|
|
|
df088e |
}
|
|
|
df088e |
|
|
|
df088e |
/* lbasename suffix */
|
|
|
df088e |
if (ref && (dctx->cctx->mode == SLBT_MODE_COMPILE)) {
|
|
|
df088e |
if ((ch[-4] == '.') && (ch[-3] == 'l') && (ch[-2] == 'o')) {
|
|
|
df088e |
ch[-3] = 'o';
|
|
|
df088e |
ch[-2] = '\0';
|
|
|
df088e |
ch--;
|
|
|
df088e |
} else if (ictx->ctx.csrc) {
|
|
|
cae4bb |
if ((mark = strrchr(ictx->ctx.lbasename,'.'))) {
|
|
|
cae4bb |
ch = mark;
|
|
|
df088e |
*++ch = 'o';
|
|
|
df088e |
*++ch = '\0';
|
|
|
df088e |
ch++;
|
|
|
df088e |
}
|
|
|
df088e |
}
|
|
|
df088e |
}
|
|
|
df088e |
|
|
|
528799 |
/* cargv, -Wc */
|
|
|
528799 |
for (i=0, parg=dctx->cctx->cargv; *parg; parg++, ch++) {
|
|
|
528799 |
if (!(strncmp("-Wc,",*parg,4))) {
|
|
|
4c2181 |
strcpy(ch,&(*parg)[4]);
|
|
|
528799 |
ictx->ctx.argv[i++] = ch;
|
|
|
528799 |
|
|
|
528799 |
for (; *ch; ch++)
|
|
|
528799 |
if (*ch == ',') {
|
|
|
869626 |
*ch++ = '\0';
|
|
|
869626 |
ictx->ctx.argv[i++] = ch;
|
|
|
528799 |
}
|
|
|
528799 |
} else {
|
|
|
528799 |
ictx->ctx.argv[i++] = ch;
|
|
|
528799 |
ch += sprintf(ch,"%s",*parg);
|
|
|
df1a81 |
ch += strlen(".libs/");
|
|
|
528799 |
}
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
5aae4b |
/* placeholders for -DPIC, -fPIC, -c, -o, <output> */
|
|
|
5aae4b |
ictx->ctx.dpic = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.fpic = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.cass = &ictx->ctx.argv[i++];
|
|
|
528799 |
|
|
|
93b62c |
|
|
|
93b62c |
ictx->ctx.noundef = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.lout[0] = &ictx->ctx.argv[i++];
|
|
|
5aae4b |
ictx->ctx.lout[1] = &ictx->ctx.argv[i++];
|
|
|
b1f977 |
ictx->ctx.sentinel= &ictx->ctx.argv[i++];
|
|
|
df088e |
|
|
|
62a7c9 |
slbt_reset_placeholders(&ictx->ctx);
|
|
|
62a7c9 |
|
|
|
df088e |
/* output file name */
|
|
|
2691fe |
if (ref && ((dctx->cctx->mode == SLBT_MODE_COMPILE))) {
|
|
|
5aae4b |
*ictx->ctx.lout[0] = "-o";
|
|
|
5aae4b |
*ictx->ctx.lout[1] = ch;
|
|
|
5aae4b |
ictx->ctx.lobjname = ch;
|
|
|
528799 |
|
|
|
e02305 |
ch += sprintf(ch,"%s%s",
|
|
|
df088e |
ictx->ctx.ldirname,
|
|
|
e02305 |
ictx->ctx.lbasename)
|
|
|
e02305 |
+ sizeof('\0');
|
|
|
e02305 |
|
|
|
e02305 |
ictx->ctx.aobjname = ch;
|
|
|
e02305 |
|
|
|
e02305 |
ch += sprintf(ch,"%s",ictx->ctx.ldirname);
|
|
|
e02305 |
ch -= strlen(".libs/");
|
|
|
e88a39 |
ch += sprintf(ch,"%s",
|
|
|
e88a39 |
ictx->ctx.lbasename)
|
|
|
e88a39 |
+ sizeof('\0');
|
|
|
e88a39 |
|
|
|
e88a39 |
ictx->ctx.ltobjname = ch;
|
|
|
e88a39 |
strcpy(ch,ictx->ctx.aobjname);
|
|
|
e88a39 |
|
|
|
cae4bb |
if ((mark = strrchr(ch,'.')))
|
|
|
cae4bb |
ch = mark + sprintf(mark,"%s",".lo")
|
|
|
e88a39 |
+ sizeof('\0');
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
731e44 |
/* linking: arfilename, lafilename, dsofilename */
|
|
|
731e44 |
if (dctx->cctx->mode == SLBT_MODE_LINK && dctx->cctx->libname) {
|
|
|
731e44 |
/* arfilename */
|
|
|
731e44 |
ictx->ctx.arfilename = ch;
|
|
|
731e44 |
ch += sprintf(ch,"%s%s%s%s",
|
|
|
731e44 |
ictx->ctx.ldirname,
|
|
|
731e44 |
dctx->cctx->settings.arprefix,
|
|
|
731e44 |
dctx->cctx->libname,
|
|
|
731e44 |
dctx->cctx->settings.arsuffix)
|
|
|
731e44 |
+ sizeof('\0');
|
|
|
731e44 |
|
|
|
731e44 |
|
|
|
731e44 |
|
|
|
731e44 |
/* lafilename */
|
|
|
731e44 |
ictx->ctx.lafilename = ch;
|
|
|
731e44 |
ch += sprintf(ch,"%s%s%s.la",
|
|
|
731e44 |
ictx->ctx.ldirname,
|
|
|
731e44 |
dctx->cctx->settings.dsoprefix,
|
|
|
731e44 |
dctx->cctx->libname)
|
|
|
731e44 |
+ sizeof('\0');
|
|
|
731e44 |
|
|
|
731e44 |
|
|
|
731e44 |
/* dsofilename */
|
|
|
731e44 |
ictx->ctx.dsofilename = ch;
|
|
|
731e44 |
ch += sprintf(ch,"%s%s%s%s",
|
|
|
731e44 |
ictx->ctx.ldirname,
|
|
|
731e44 |
dctx->cctx->settings.dsoprefix,
|
|
|
731e44 |
dctx->cctx->libname,
|
|
|
731e44 |
dctx->cctx->settings.dsosuffix)
|
|
|
731e44 |
+ sizeof('\0');
|
|
|
731e44 |
}
|
|
|
731e44 |
|
|
|
f47761 |
/* linking: exefilename */
|
|
|
f47761 |
if (dctx->cctx->mode == SLBT_MODE_LINK && !dctx->cctx->libname) {
|
|
|
f47761 |
ictx->ctx.exefilename = ch;
|
|
|
f47761 |
|
|
|
f47761 |
if ((slash = strrchr(dctx->cctx->output,'/'))) {
|
|
|
f47761 |
strcpy(ch,dctx->cctx->output);
|
|
|
f47761 |
mark = ch + (slash - dctx->cctx->output);
|
|
|
f47761 |
sprintf(++mark,".libs/%s",++slash);
|
|
|
f47761 |
ch += strlen(ch) + sizeof('\0');
|
|
|
f47761 |
} else
|
|
|
f47761 |
ch += sprintf(ch,".libs/%s",dctx->cctx->output)
|
|
|
f47761 |
+ sizeof('\0');
|
|
|
f47761 |
}
|
|
|
f47761 |
|
|
|
e7ddb2 |
/* argument strings shadow copy */
|
|
|
e7ddb2 |
memcpy(ictx->shadow,ictx->args,ictx->size);
|
|
|
e7ddb2 |
|
|
|
528799 |
*ectx = &ictx->ctx;
|
|
|
528799 |
return 0;
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
528799 |
|
|
|
528799 |
static int slbt_free_exec_ctx_impl(
|
|
|
528799 |
struct slbt_exec_ctx_impl * ictx,
|
|
|
528799 |
int status)
|
|
|
528799 |
{
|
|
|
528799 |
free(ictx->args);
|
|
|
e7ddb2 |
free(ictx->shadow);
|
|
|
528799 |
free (ictx);
|
|
|
528799 |
return status;
|
|
|
528799 |
}
|
|
|
528799 |
|
|
|
528799 |
|
|
|
528799 |
void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx)
|
|
|
528799 |
{
|
|
|
528799 |
struct slbt_exec_ctx_impl * ictx;
|
|
|
528799 |
uintptr_t addr;
|
|
|
528799 |
|
|
|
528799 |
if (ctx) {
|
|
|
528799 |
addr = (uintptr_t)ctx - offsetof(struct slbt_exec_ctx_impl,ctx);
|
|
|
528799 |
ictx = (struct slbt_exec_ctx_impl *)addr;
|
|
|
528799 |
slbt_free_exec_ctx_impl(ictx,0);
|
|
|
528799 |
}
|
|
|
528799 |
}
|
|
|
5aae4b |
|
|
|
5aae4b |
|
|
|
e7ddb2 |
void slbt_reset_arguments(struct slbt_exec_ctx * ectx)
|
|
|
e7ddb2 |
{
|
|
|
e7ddb2 |
struct slbt_exec_ctx_impl * ictx;
|
|
|
e7ddb2 |
uintptr_t addr;
|
|
|
e7ddb2 |
|
|
|
e7ddb2 |
addr = (uintptr_t)ectx - offsetof(struct slbt_exec_ctx_impl,ctx);
|
|
|
e7ddb2 |
ictx = (struct slbt_exec_ctx_impl *)addr;
|
|
|
e7ddb2 |
memcpy(ictx->args,ictx->shadow,ictx->size);
|
|
|
e7ddb2 |
}
|
|
|
e7ddb2 |
|
|
|
e7ddb2 |
|
|
|
5aae4b |
void slbt_reset_placeholders(struct slbt_exec_ctx * ectx)
|
|
|
5aae4b |
{
|
|
|
a40c9a |
*ectx->dpic = "-USLIBTOOL_PLACEHOLDER_DPIC";
|
|
|
a40c9a |
*ectx->fpic = "-USLIBTOOL_PLACEHOLDER_FPIC";
|
|
|
a40c9a |
*ectx->cass = "-USLIBTOOL_PLACEHOLDER_COMPILE_ASSEMBLE";
|
|
|
5aae4b |
|
|
|
93b62c |
*ectx->noundef = "-USLIBTOOL_PLACEHOLDER_NO_UNDEFINED";
|
|
|
a40c9a |
*ectx->lout[0] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_SWITCH";
|
|
|
a40c9a |
*ectx->lout[1] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_FILE";
|
|
|
b1f977 |
*ectx->sentinel= 0;
|
|
|
5aae4b |
}
|