From c70c0a72abe470aa16aefd47f1fdde5c4aa0718f Mon Sep 17 00:00:00 2001 From: midipix Date: Sat, 11 Feb 2017 14:38:50 -0500 Subject: driver: utility api: added mdso_create_implib_archive(). --- include/mdso/mdso.h | 4 ++ project/common.mk | 1 + src/driver/mdso_amain.c | 3 ++ src/driver/mdso_driver_ctx.c | 27 +++++++++--- src/helper/mdso_create_output.c | 17 +++++-- src/internal/mdso_driver_impl.h | 2 + src/output/mdso_output_error.c | 1 + src/skin/mdso_skin_default.c | 3 ++ src/util/mdso_create_implib_archive.c | 83 +++++++++++++++++++++++++++++++++++ 9 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 src/util/mdso_create_implib_archive.c diff --git a/include/mdso/mdso.h b/include/mdso/mdso.h index 105a9c5..62ec354 100644 --- a/include/mdso/mdso.h +++ b/include/mdso/mdso.h @@ -51,6 +51,7 @@ enum mdso_custom_error { MDSO_ERR_FLEE_ERROR, MDSO_ERR_NULL_CONTEXT, MDSO_ERR_NULL_SOURCE, + MDSO_ERR_INVALID_NAME, MDSO_ERR_INVALID_DATA, MDSO_ERR_INVALID_DSTDIR, MDSO_ERR_INVALID_CONTEXT, @@ -99,6 +100,7 @@ struct mdso_common_ctx { uint64_t actflags; uint64_t fmtflags; uint32_t dsoflags; + const char * implib; const char * libname; const char * asmbase; const char * dstdir; @@ -136,11 +138,13 @@ mdso_api int mdso_map_input (const struct mdso_driver_ctx *, int fd, const cha mdso_api int mdso_unmap_input (struct mdso_input *); /* helper api */ +mdso_api FILE*mdso_create_archive (const struct mdso_driver_ctx *, const char * arname); mdso_api FILE*mdso_create_asm_source (const struct mdso_driver_ctx *, const char * asmname); mdso_api FILE*mdso_create_object (const struct mdso_driver_ctx *, const char * objname); /* utility api */ mdso_api int mdso_main (int, char **, char **); +mdso_api int mdso_create_implib_archive(const struct mdso_driver_ctx *); mdso_api int mdso_create_implib_sources(const struct mdso_driver_ctx *); mdso_api int mdso_create_implib_objects(const struct mdso_driver_ctx *); mdso_api int mdso_output_export_symbols(const struct mdso_driver_ctx *, const struct mdso_unit_ctx *, FILE *); diff --git a/project/common.mk b/project/common.mk index 5b1c676..8f693ff 100644 --- a/project/common.mk +++ b/project/common.mk @@ -16,6 +16,7 @@ API_SRCS = \ src/output/mdso_output_error.c \ src/output/mdso_output_export_symbols.c \ src/skin/mdso_skin_default.c \ + src/util/mdso_create_implib_archive.c \ src/util/mdso_create_implib_objects.c \ src/util/mdso_create_implib_sources.c \ diff --git a/src/driver/mdso_amain.c b/src/driver/mdso_amain.c index 629b606..70fb44a 100644 --- a/src/driver/mdso_amain.c +++ b/src/driver/mdso_amain.c @@ -78,6 +78,9 @@ int mdso_main(int argc, char ** argv, char ** envp) if ((mdso_version(dctx)) < 0) return mdso_exit(dctx,MDSO_ERROR); + if (dctx->cctx->implib) + mdso_create_implib_archive(dctx); + if (dctx->cctx->drvflags & MDSO_DRIVER_GENERATE_ASM) mdso_create_implib_sources(dctx); diff --git a/src/driver/mdso_driver_ctx.c b/src/driver/mdso_driver_ctx.c index 3decf70..5dd9449 100644 --- a/src/driver/mdso_driver_ctx.c +++ b/src/driver/mdso_driver_ctx.c @@ -131,12 +131,16 @@ static int mdso_dstdir_open(const struct mdso_common_ctx * cctx, const char * as static int mdso_get_driver_ctx_fail( struct argv_meta * meta, + char * implib, char * asmbase, int fddst) { if (fddst >= 0) close(fddst); + if (implib) + free(implib); + if (asmbase) free(asmbase); @@ -158,6 +162,7 @@ int mdso_get_driver_ctx( size_t nunits; const char * program; const char * pretty; + char * implib; char * asmbase; char * dot; int fddst; @@ -171,6 +176,7 @@ int mdso_get_driver_ctx( nunits = 0; pretty = 0; + implib = 0; asmbase = 0; fddst = -1; program = argv_program_name(argv[0]); @@ -207,6 +213,10 @@ int mdso_get_driver_ctx( cctx.drvflags &= ~(uint64_t)MDSO_DRIVER_QUAD_PTR; break; + case TAG_IMPLIB: + cctx.implib = entry->arg; + break; + case TAG_LIBPATH: if (!(strcmp(entry->arg,"loader"))) cctx.dsoflags |= MDSO_FLAG_LOADER_PATH; @@ -245,18 +255,22 @@ int mdso_get_driver_ctx( if (!cctx.libname) cctx.libname = "win32any"; + if (cctx.implib && !(implib = strdup(cctx.implib))) + return mdso_get_driver_ctx_fail(meta,0,0,fddst); + if (!(asmbase = strdup(cctx.libname))) - return mdso_get_driver_ctx_fail(meta,asmbase,fddst); + return mdso_get_driver_ctx_fail(meta,implib,0,fddst); if ((dot = strchr(asmbase,'.'))) *dot = '\0'; if (cctx.dstdir && (fddst = mdso_dstdir_open(&cctx,asmbase)) < 0) - return mdso_get_driver_ctx_fail(meta,asmbase,fddst); + return mdso_get_driver_ctx_fail(meta,implib,asmbase,fddst); if (!(ctx = mdso_driver_ctx_alloc(meta,&cctx,nunits))) - return mdso_get_driver_ctx_fail(meta,asmbase,fddst); + return mdso_get_driver_ctx_fail(meta,implib,asmbase,fddst); + ctx->implib = implib; ctx->asmbase = asmbase; ctx->cctx.asmbase = asmbase; @@ -284,10 +298,10 @@ int mdso_create_driver_ctx( return -1; if (cctx->dstdir && (fddst = mdso_dstdir_open(cctx,cctx->asmbase)) < 0) - return mdso_get_driver_ctx_fail(meta,0,fddst); + return mdso_get_driver_ctx_fail(meta,0,0,fddst); if (!(ctx = mdso_driver_ctx_alloc(meta,cctx,0))) - return mdso_get_driver_ctx_fail(meta,0,fddst); + return mdso_get_driver_ctx_fail(meta,0,0,fddst); ctx->ctx.cctx = &ctx->cctx; *pctx = &ctx->ctx; @@ -305,6 +319,9 @@ static void mdso_free_driver_ctx_impl(struct mdso_driver_ctx_alloc * ictx) if (ictx->ctx.asmbase) free(ictx->ctx.asmbase); + if (ictx->ctx.implib) + free(ictx->ctx.implib); + argv_free(ictx->meta); free(ictx); } diff --git a/src/helper/mdso_create_output.c b/src/helper/mdso_create_output.c index b152697..5f4a761 100644 --- a/src/helper/mdso_create_output.c +++ b/src/helper/mdso_create_output.c @@ -17,7 +17,8 @@ static FILE * mdso_create_output( const struct mdso_driver_ctx * dctx, - const char * name) + const char * name, + int fdat) { struct mdso_driver_ctx_impl * ictx; uintptr_t addr; @@ -26,8 +27,9 @@ static FILE * mdso_create_output( addr = (uintptr_t)dctx - offsetof(struct mdso_driver_ctx_impl,ctx); ictx = (struct mdso_driver_ctx_impl *)addr; + fdat = (fdat == AT_FDCWD) ? AT_FDCWD : ictx->fddst; - if ((fdout = openat(ictx->fddst,name, + if ((fdout = openat(fdat,name, O_CREAT|O_TRUNC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { MDSO_SYSTEM_ERROR(dctx); @@ -43,6 +45,13 @@ static FILE * mdso_create_output( return fout; } +FILE * mdso_create_archive( + const struct mdso_driver_ctx * dctx, + const char * arname) +{ + return mdso_create_output(dctx,arname,AT_FDCWD); +} + FILE * mdso_create_asm_source( const struct mdso_driver_ctx * dctx, const char * asmname) @@ -50,7 +59,7 @@ FILE * mdso_create_asm_source( if (!dctx->cctx->dstdir) return stdout; - return mdso_create_output(dctx,asmname); + return mdso_create_output(dctx,asmname,-1); } FILE * mdso_create_object( @@ -62,5 +71,5 @@ FILE * mdso_create_object( return 0; } - return mdso_create_output(dctx,objname); + return mdso_create_output(dctx,objname,-1); } diff --git a/src/internal/mdso_driver_impl.h b/src/internal/mdso_driver_impl.h index ffeae9d..6b092dc 100644 --- a/src/internal/mdso_driver_impl.h +++ b/src/internal/mdso_driver_impl.h @@ -18,6 +18,7 @@ enum app_tags { TAG_ASM, TAG_OBJ, TAG_QUAD_PTR, + TAG_IMPLIB, TAG_LIBPATH, TAG_LIBNAME, TAG_DSTDIR, @@ -34,6 +35,7 @@ struct mdso_driver_ctx_impl { struct mdso_common_ctx cctx; struct mdso_driver_ctx ctx; char * asmbase; + char * implib; int fddst; int fdtmpin; const struct mdso_unit_ctx * euctx; diff --git a/src/output/mdso_output_error.c b/src/output/mdso_output_error.c index 4793a35..d06d01e 100644 --- a/src/output/mdso_output_error.c +++ b/src/output/mdso_output_error.c @@ -23,6 +23,7 @@ static const char const * const mdso_error_strings[MDSO_ERR_CAP] = { [MDSO_ERR_FLEE_ERROR] = "flees and bugs and cats and mice", [MDSO_ERR_NULL_CONTEXT] = "null driver or unit context", [MDSO_ERR_NULL_SOURCE] = "source file does not define any symbols", + [MDSO_ERR_INVALID_NAME] = "invalid or missing import library archive name", [MDSO_ERR_INVALID_DATA] = "invalid data (symbol name too long)", [MDSO_ERR_INVALID_DSTDIR] = "invalid destination directory", [MDSO_ERR_INVALID_CONTEXT] = "invalid driver or unit context", diff --git a/src/skin/mdso_skin_default.c b/src/skin/mdso_skin_default.c index 1c0151e..fdff8ad 100644 --- a/src/skin/mdso_skin_default.c +++ b/src/skin/mdso_skin_default.c @@ -8,6 +8,9 @@ const struct argv_option mdso_default_options[] = { {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0, "show usage information [listing %s options only]"}, + {"implib", 'i',TAG_IMPLIB,ARGV_OPTARG_REQUIRED,0,0,"", + "create an import library archive"}, + {"asm", 'a',TAG_ASM,ARGV_OPTARG_NONE,0,0,0, "generate assembly sources"}, diff --git a/src/util/mdso_create_implib_archive.c b/src/util/mdso_create_implib_archive.c new file mode 100644 index 0000000..323b318 --- /dev/null +++ b/src/util/mdso_create_implib_archive.c @@ -0,0 +1,83 @@ +/****************************************************************/ +/* mdso: midipix dso scavenger */ +/* Copyright (C) 2015--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ +/****************************************************************/ + +#include +#include +#include +#include + +#include +#include "mdso_errinfo_impl.h" + +static void mdso_free_uctx_vector(struct mdso_unit_ctx ** uctxv) +{ + struct mdso_unit_ctx ** puctx; + + for (puctx=uctxv; *puctx; puctx++) + mdso_free_unit_ctx(*puctx); + + free(uctxv); +} + +int mdso_create_implib_archive(const struct mdso_driver_ctx * dctx) +{ + int ret; + FILE * fout; + size_t nsym; + struct mdso_unit_ctx ** uctxv; + struct mdso_unit_ctx ** puctx; + const char * const * dsym; + const char ** unit; + const char ** psym; + const char ** symv; + const char * asym[512]; + + if (!dctx->cctx->implib) + return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_NAME); + + if (!(fout = mdso_create_archive(dctx,dctx->cctx->implib))) + return MDSO_NESTED_ERROR(dctx); + + for (unit=dctx->units; *unit; unit++) + (void)0; + + if (!(uctxv = calloc(++unit - dctx->units,sizeof(*uctxv)))) + return MDSO_SYSTEM_ERROR(dctx); + + for (puctx=uctxv,unit=dctx->units; *unit; unit++) { + if (mdso_get_unit_ctx(dctx,*unit,puctx)) { + mdso_free_uctx_vector(uctxv); + return MDSO_NESTED_ERROR(dctx); + } + } + + for (nsym=0,puctx=uctxv; *puctx; puctx++) + for (dsym=puctx[0]->syms; *dsym; dsym++) + nsym++; + + if (nsym < 512) { + memset(asym,0,sizeof(asym)); + symv = asym; + + } else if (!(symv = calloc(nsym+1,sizeof(const char *)))) { + mdso_free_uctx_vector(uctxv); + return MDSO_SYSTEM_ERROR(dctx); + } + + for (psym=symv,puctx=uctxv; *puctx; puctx++) + for (dsym=puctx[0]->syms; *dsym; dsym++) + *psym++ = *dsym; + + ret = mdso_argen_common(dctx,symv,fout,0); + fclose(fout); + + if (symv != asym) + free(symv); + + mdso_free_uctx_vector(uctxv); + + return ret ? MDSO_NESTED_ERROR(dctx) : 0; +} -- cgit v1.2.3