| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static size_t slbt_parse_comma_separated_flags( |
| const char * str, |
| int * argc) |
| { |
| const char * ch; |
| |
| for (ch=str; *ch; ch++) |
| if (*ch == ',') |
| (*argc)++; |
| |
| return ch - str; |
| } |
| |
| |
| static char * slbt_source_file(char ** argv) |
| { |
| char ** parg; |
| char * ch; |
| |
| for (parg=argv; *parg; parg++) |
| if ((ch = strrchr(*parg,'.'))) |
| if ((!(strcmp(++ch,"s"))) |
| || (!(strcmp(ch,"S"))) |
| || (!(strcmp(ch,"asm"))) |
| || (!(strcmp(ch,"c"))) |
| || (!(strcmp(ch,"cc"))) |
| || (!(strcmp(ch,"cpp"))) |
| || (!(strcmp(ch,"cxx")))) |
| return *parg; |
| return 0; |
| } |
| |
| |
| static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc( |
| const struct slbt_driver_ctx * dctx) |
| { |
| struct slbt_exec_ctx_impl * ictx; |
| size_t size; |
| size_t vsize; |
| int argc; |
| char * args; |
| char * shadow; |
| char * csrc; |
| char ** parg; |
| |
| argc = 0; |
| csrc = 0; |
| |
| |
| size = strlen(".lo") + 1; |
| size += 12 * (strlen(".libs/") + 1); |
| size += 36 * (strlen(".0000") + 1); |
| |
| |
| for (parg=dctx->cctx->cargv; *parg; parg++, argc++) |
| if (!(strncmp("-Wc,",*parg,4))) |
| size += slbt_parse_comma_separated_flags( |
| &(*parg)[4],&argc) + 1; |
| else |
| size += strlen(*parg) + 1; |
| |
| |
| if (dctx->cctx->output) |
| size += 9*strlen(dctx->cctx->output); |
| else if ((csrc = slbt_source_file(dctx->cctx->cargv))) |
| size += 9*strlen(csrc); |
| |
| |
| size += 9 * (16 + 16 + 16 + 16); |
| |
| |
| argc *= 2; |
| argc += SLBT_ARGV_SPARE_PTRS; |
| |
| |
| size += argc * strlen(".libs/-L-l"); |
| |
| |
| if (dctx->cctx->mode == SLBT_MODE_LINK) |
| size += strlen(dctx->cctx->settings.arprefix) + 1 |
| + strlen(dctx->cctx->settings.arsuffix) + 1 |
| + strlen(dctx->cctx->settings.dsoprefix) + 1 |
| + strlen(dctx->cctx->settings.dsoprefix) + 1 |
| + strlen(dctx->cctx->settings.dsoprefix) + 1 |
| + strlen(dctx->cctx->settings.exeprefix) + 1 |
| + strlen(dctx->cctx->settings.exeprefix) + 1 |
| + strlen(dctx->cctx->settings.impprefix) + 1 |
| + strlen(dctx->cctx->settings.impprefix) + 1; |
| |
| |
| if (!(args = malloc(size))) |
| return 0; |
| |
| if (!(shadow = malloc(size))) { |
| free(args); |
| return 0; |
| } |
| |
| |
| vsize = sizeof(*ictx); |
| vsize += sizeof(char *) * (argc + 1); |
| vsize += sizeof(char *) * (argc + 1); |
| |
| |
| vsize += sizeof(char *) * (argc + 1) * 3; |
| |
| if (!(ictx = calloc(1,vsize))) { |
| free(args); |
| free(shadow); |
| return 0; |
| } |
| |
| ictx->args = args; |
| ictx->argc = argc; |
| |
| ictx->size = size; |
| ictx->shadow = shadow; |
| |
| ictx->ctx.csrc = csrc; |
| ictx->fdwrapper = (-1); |
| |
| return ictx; |
| } |
| |
| |
| int slbt_get_exec_ctx( |
| const struct slbt_driver_ctx * dctx, |
| struct slbt_exec_ctx ** ectx) |
| { |
| struct slbt_exec_ctx_impl * ictx; |
| char ** parg; |
| char ** src; |
| char ** dst; |
| char * ch; |
| char * mark; |
| const char * dmark; |
| char * slash; |
| const char * arprefix; |
| const char * dsoprefix; |
| const char * impprefix; |
| const char * ref; |
| int i; |
| |
| |
| if (!(ictx = slbt_exec_ctx_alloc(dctx))) |
| return SLBT_NESTED_ERROR(dctx); |
| |
| |
| ch = ictx->args + strlen(".lo"); |
| ictx->ctx.argv = ictx->vbuffer; |
| ictx->ctx.xargv = &ictx->ctx.argv [ictx->argc + 1]; |
| ictx->ctx.altv = &ictx->ctx.xargv[ictx->argc + 1]; |
| |
| |
| ictx->ctx.compiler = dctx->cctx->cargv[0]; |
| ictx->ctx.cargv = ictx->ctx.argv; |
| |
| |
| ref = (dctx->cctx->output) |
| ? dctx->cctx->output |
| : ictx->ctx.csrc; |
| |
| if (ref && !ictx->ctx.csrc && (mark = strrchr(ref,'/'))) { |
| if (!(strncmp(ref,"../",3))) |
| dmark = 0; |
| else if (!(strncmp(ref,"./",2))) |
| dmark = &ref[1]; |
| else |
| dmark = strchr(ref,'/'); |
| |
| for (; dmark; ) { |
| if (!(strncmp(dmark,"/./",3))) { |
| dmark = strchr(&dmark[2],'/'); |
| } else if (!(strncmp(dmark,"/../",4))) { |
| ictx->ctx.ldirdepth = -1; |
| dmark = 0; |
| } else { |
| for (; *dmark=='/'; ) |
| dmark++; |
| |
| ictx->ctx.ldirdepth++; |
| dmark = strchr(dmark,'/'); |
| } |
| } |
| |
| ictx->ctx.ldirname = ch; |
| strcpy(ch,ref); |
| ch += mark - ref; |
| ch += sprintf(ch,"%s","/.libs/"); |
| ch++; |
| |
| ictx->ctx.lbasename = ch; |
| ch += sprintf(ch,"%s",++mark); |
| ch++; |
| } else if (ref) { |
| ictx->ctx.ldirname = ch; |
| ch += sprintf(ch,"%s",".libs/"); |
| ch++; |
| |
| ictx->ctx.lbasename = ch; |
| mark = strrchr(ref,'/'); |
| ch += sprintf(ch,"%s",mark ? ++mark : ref); |
| ch++; |
| } |
| |
| |
| if (ref && (dctx->cctx->mode == SLBT_MODE_COMPILE)) { |
| if ((ch[-4] == '.') && (ch[-3] == 'l') && (ch[-2] == 'o')) { |
| ch[-3] = 'o'; |
| ch[-2] = 0; |
| ch--; |
| } else if (ictx->ctx.csrc) { |
| if ((mark = strrchr(ictx->ctx.lbasename,'.'))) { |
| ch = mark; |
| *++ch = 'o'; |
| *++ch = 0; |
| ch++; |
| } |
| } |
| } |
| |
| |
| for (i=0, parg=dctx->cctx->cargv; *parg; parg++, ch++) { |
| if (!(strncmp("-Wc,",*parg,4))) { |
| strcpy(ch,&(*parg)[4]); |
| ictx->ctx.argv[i++] = ch; |
| |
| for (; *ch; ch++) |
| if (*ch == ',') { |
| *ch++ = 0; |
| ictx->ctx.argv[i++] = ch; |
| } |
| } else { |
| ictx->ctx.argv[i++] = ch; |
| ch += sprintf(ch,"%s",*parg); |
| ch += strlen(".libs/-L-l"); |
| } |
| } |
| |
| |
| ictx->ctx.dpic = &ictx->ctx.argv[i++]; |
| ictx->ctx.fpic = &ictx->ctx.argv[i++]; |
| ictx->ctx.cass = &ictx->ctx.argv[i++]; |
| |
| ictx->ctx.noundef = &ictx->ctx.argv[i++]; |
| ictx->ctx.soname = &ictx->ctx.argv[i++]; |
| ictx->ctx.lsoname = &ictx->ctx.argv[i++]; |
| ictx->ctx.symdefs = &ictx->ctx.argv[i++]; |
| ictx->ctx.symfile = &ictx->ctx.argv[i++]; |
| |
| ictx->ctx.lout[0] = &ictx->ctx.argv[i++]; |
| ictx->ctx.lout[1] = &ictx->ctx.argv[i++]; |
| |
| ictx->ctx.rpath[0] = &ictx->ctx.argv[i++]; |
| ictx->ctx.rpath[1] = &ictx->ctx.argv[i++]; |
| |
| ictx->ctx.sentinel= &ictx->ctx.argv[i++]; |
| |
| slbt_reset_placeholders(&ictx->ctx); |
| |
| |
| if (dctx->cctx->settings.dsoprefix) { |
| ictx->dsoprefix = ch; |
| strcpy(ch,dctx->cctx->settings.dsoprefix); |
| ch += strlen(ch) + 1; |
| } |
| |
| |
| if (ref && ((dctx->cctx->mode == SLBT_MODE_COMPILE))) { |
| *ictx->ctx.lout[0] = "-o"; |
| *ictx->ctx.lout[1] = ch; |
| ictx->ctx.lobjname = ch; |
| |
| ch += sprintf(ch,"%s%s", |
| ictx->ctx.ldirname, |
| ictx->ctx.lbasename) |
| + 1; |
| |
| ictx->ctx.aobjname = ch; |
| |
| ch += sprintf(ch,"%s",ictx->ctx.ldirname); |
| ch -= strlen(".libs/"); |
| ch += sprintf(ch,"%s", |
| ictx->ctx.lbasename) |
| + 1; |
| |
| ictx->ctx.ltobjname = ch; |
| strcpy(ch,ictx->ctx.aobjname); |
| |
| if ((mark = strrchr(ch,'.'))) |
| ch = mark + sprintf(mark,"%s",".lo") |
| + 1; |
| } |
| |
| |
| if (dctx->cctx->mode == SLBT_MODE_LINK && dctx->cctx->libname) { |
| |
| if (dctx->cctx->drvflags & SLBT_DRIVER_MODULE) { |
| ictx->ctx.sonameprefix = ""; |
| arprefix = ""; |
| dsoprefix = ""; |
| impprefix = ""; |
| } else { |
| ictx->ctx.sonameprefix = ictx->dsoprefix; |
| arprefix = dctx->cctx->settings.arprefix; |
| dsoprefix = dctx->cctx->settings.dsoprefix; |
| impprefix = dctx->cctx->settings.impprefix; |
| } |
| |
| |
| ictx->ctx.arfilename = ch; |
| ch += sprintf(ch,"%s%s%s%s", |
| ictx->ctx.ldirname, |
| arprefix, |
| dctx->cctx->libname, |
| dctx->cctx->settings.arsuffix); |
| ch++; |
| |
| |
| |
| |
| ictx->ctx.lafilename = ch; |
| ch += sprintf(ch,"%s%s%s.la", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname); |
| ch++; |
| |
| |
| |
| ictx->ctx.laifilename = ch; |
| ch += sprintf(ch,"%s%s%s.lai", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname); |
| ch++; |
| |
| |
| |
| ictx->ctx.dsobasename = ch; |
| ch += sprintf(ch,"%s%s%s", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname); |
| ch++; |
| |
| |
| ictx->ctx.dsofilename = ch; |
| ch += sprintf(ch,"%s%s%s%s", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->settings.dsosuffix); |
| ch++; |
| |
| |
| ictx->ctx.deffilename = ch; |
| ch += sprintf(ch,"%s%s%s%s.def", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->settings.dsosuffix); |
| ch++; |
| |
| |
| ictx->ctx.rpathfilename = ch; |
| ch += sprintf(ch,"%s%s%s%s.slibtool.rpath", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->settings.dsosuffix); |
| ch++; |
| |
| |
| ictx->ctx.dimpfilename = ch; |
| ch += sprintf(ch,"%s%s%s%s", |
| ictx->ctx.ldirname, |
| impprefix, |
| dctx->cctx->libname, |
| dctx->cctx->settings.impsuffix); |
| ch++; |
| |
| |
| |
| ictx->ctx.pimpfilename = ch; |
| ch += sprintf(ch,"%s%s%s.%d%s", |
| ictx->ctx.ldirname, |
| impprefix, |
| dctx->cctx->libname, |
| dctx->cctx->verinfo.major, |
| dctx->cctx->settings.impsuffix); |
| ch++; |
| |
| |
| ictx->ctx.vimpfilename = ch; |
| ch += sprintf(ch,"%s%s%s.%d.%d.%d%s", |
| ictx->ctx.ldirname, |
| impprefix, |
| dctx->cctx->libname, |
| dctx->cctx->verinfo.major, |
| dctx->cctx->verinfo.minor, |
| dctx->cctx->verinfo.revision, |
| dctx->cctx->settings.impsuffix); |
| ch++; |
| |
| |
| if (dctx->cctx->release) { |
| ictx->ctx.relfilename = ch; |
| ch += dctx->cctx->verinfo.verinfo |
| ? sprintf(ch,"%s%s%s-%s%s.%d.%d.%d%s", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->release, |
| dctx->cctx->settings.osdsuffix, |
| dctx->cctx->verinfo.major, |
| dctx->cctx->verinfo.minor, |
| dctx->cctx->verinfo.revision, |
| dctx->cctx->settings.osdfussix) |
| : sprintf(ch,"%s%s%s-%s%s", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->release, |
| dctx->cctx->settings.dsosuffix); |
| ch++; |
| } |
| |
| |
| if (dctx->cctx->release) { |
| ictx->ctx.dsorellnkname = ch; |
| ch += sprintf(ch,"%s%s%s-%s%s", |
| ictx->ctx.ldirname, |
| dsoprefix, |
| dctx->cctx->libname, |
| dctx->cctx->release, |
| dctx->cctx->settings.dsosuffix); |
| ch++; |
| } |
| } |
| |
| |
| if (dctx->cctx->mode == SLBT_MODE_LINK && !dctx->cctx->libname) { |
| ictx->ctx.exefilename = ch; |
| |
| if ((slash = strrchr(dctx->cctx->output,'/'))) { |
| strcpy(ch,dctx->cctx->output); |
| mark = ch + (slash - dctx->cctx->output); |
| sprintf(++mark,".libs/%s",++slash); |
| ch += strlen(ch) + 1; |
| } else |
| ch += sprintf(ch,".libs/%s",dctx->cctx->output) + 1; |
| } |
| |
| |
| memcpy(ictx->shadow,ictx->args,ictx->size); |
| |
| |
| if (dctx->cctx->mode == SLBT_MODE_COMPILE) |
| for (src=ictx->ctx.argv, dst=ictx->ctx.xargv; *src; src++, dst++) |
| *dst = *src; |
| |
| |
| ictx->lout[0] = ictx->ctx.lout[0]; |
| ictx->lout[1] = ictx->ctx.lout[1]; |
| |
| ictx->mout[0] = ictx->ctx.mout[0]; |
| ictx->mout[1] = ictx->ctx.mout[1]; |
| |
| |
| *ectx = &ictx->ctx; |
| return 0; |
| } |
| |
| |
| static int slbt_free_exec_ctx_impl( |
| struct slbt_exec_ctx_impl * ictx, |
| int status) |
| { |
| if (ictx->fdwrapper >= 0) |
| close(ictx->fdwrapper); |
| |
| free(ictx->args); |
| free(ictx->shadow); |
| free (ictx); |
| |
| return status; |
| } |
| |
| |
| void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx) |
| { |
| struct slbt_exec_ctx_impl * ictx; |
| uintptr_t addr; |
| |
| if (ctx) { |
| addr = (uintptr_t)ctx - offsetof(struct slbt_exec_ctx_impl,ctx); |
| ictx = (struct slbt_exec_ctx_impl *)addr; |
| slbt_free_exec_ctx_impl(ictx,0); |
| } |
| } |
| |
| |
| void slbt_reset_arguments(struct slbt_exec_ctx * ectx) |
| { |
| struct slbt_exec_ctx_impl * ictx; |
| uintptr_t addr; |
| |
| addr = (uintptr_t)ectx - offsetof(struct slbt_exec_ctx_impl,ctx); |
| ictx = (struct slbt_exec_ctx_impl *)addr; |
| memcpy(ictx->args,ictx->shadow,ictx->size); |
| } |
| |
| |
| void slbt_reset_argvector(struct slbt_exec_ctx * ectx) |
| { |
| struct slbt_exec_ctx_impl * ictx; |
| uintptr_t addr; |
| char ** src; |
| char ** dst; |
| |
| addr = (uintptr_t)ectx - offsetof(struct slbt_exec_ctx_impl,ctx); |
| ictx = (struct slbt_exec_ctx_impl *)addr; |
| |
| for (src=ectx->xargv, dst=ectx->argv; *src; src++, dst++) |
| *dst = *src; |
| |
| *dst = 0; |
| |
| ectx->lout[0] = ictx->lout[0]; |
| ectx->lout[1] = ictx->lout[1]; |
| |
| ectx->mout[0] = ictx->mout[0]; |
| ectx->mout[1] = ictx->mout[1]; |
| } |
| |
| |
| void slbt_reset_placeholders(struct slbt_exec_ctx * ectx) |
| { |
| *ectx->dpic = "-USLIBTOOL_PLACEHOLDER_DPIC"; |
| *ectx->fpic = "-USLIBTOOL_PLACEHOLDER_FPIC"; |
| *ectx->cass = "-USLIBTOOL_PLACEHOLDER_COMPILE_ASSEMBLE"; |
| |
| *ectx->noundef = "-USLIBTOOL_PLACEHOLDER_NO_UNDEFINED"; |
| *ectx->soname = "-USLIBTOOL_PLACEHOLDER_SONAME"; |
| *ectx->lsoname = "-USLIBTOOL_PLACEHOLDER_LSONAME"; |
| *ectx->symdefs = "-USLIBTOOL_PLACEHOLDER_SYMDEF_SWITCH"; |
| *ectx->symfile = "-USLIBTOOL_PLACEHOLDER_SYMDEF_FILE"; |
| |
| *ectx->lout[0] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_SWITCH"; |
| *ectx->lout[1] = "-USLIBTOOL_PLACEHOLDER_OUTPUT_FILE"; |
| |
| *ectx->rpath[0] = "-USLIBTOOL_PLACEHOLDER_RPATH_SWITCH"; |
| *ectx->rpath[1] = "-USLIBTOOL_PLACEHOLDER_RPATH_DIR"; |
| |
| ectx->mout[0] = 0; |
| ectx->mout[1] = 0; |
| |
| *ectx->sentinel= 0; |
| } |
| |
| void slbt_disable_placeholders(struct slbt_exec_ctx * ectx) |
| { |
| *ectx->dpic = 0; |
| *ectx->fpic = 0; |
| *ectx->cass = 0; |
| |
| *ectx->noundef = 0; |
| *ectx->soname = 0; |
| *ectx->lsoname = 0; |
| *ectx->symdefs = 0; |
| *ectx->symfile = 0; |
| |
| *ectx->lout[0] = 0; |
| *ectx->lout[1] = 0; |
| |
| *ectx->rpath[0] = 0; |
| *ectx->rpath[1] = 0; |
| |
| *ectx->sentinel= 0; |
| } |