diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h index b081e57..0cbcad5 100644 --- a/include/slibtool/slibtool.h +++ b/include/slibtool/slibtool.h @@ -76,6 +76,7 @@ extern "C" { #define SLBT_DRIVER_MODE_AR SLBT_DRIVER_XFLAG(0x010000) #define SLBT_DRIVER_MODE_AR_CHECK SLBT_DRIVER_XFLAG(0x020000) +#define SLBT_DRIVER_MODE_AR_MERGE SLBT_DRIVER_XFLAG(0x040000) /* unit action flags */ #define SLBT_ACTION_MAP_READWRITE 0x0001 @@ -127,6 +128,8 @@ enum slbt_custom_error { SLBT_ERR_AR_INVALID_ARMAP_STRING_TABLE, SLBT_ERR_AR_INVALID_ARMAP_MEMBER_OFFSET, SLBT_ERR_AR_INVALID_ARMAP_NAME_OFFSET, + SLBT_ERR_AR_OUTPUT_NOT_SPECIFIED, + SLBT_ERR_AR_OUTPUT_NOT_APPLICABLE, }; /* execution modes */ diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index 631a1b6..17cb290 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -92,6 +92,8 @@ enum app_tags { TAG_AR_PRETTY, TAG_AR_POSIX, TAG_AR_YAML, + TAG_AR_MERGE, + TAG_AR_OUTPUT, TAG_AR_VERBOSE, }; diff --git a/src/logic/slbt_exec_ar.c b/src/logic/slbt_exec_ar.c index e3613fd..eab86ea 100644 --- a/src/logic/slbt_exec_ar.c +++ b/src/logic/slbt_exec_ar.c @@ -11,7 +11,8 @@ #include "slibtool_errinfo_impl.h" #include "argv/argv.h" -#define SLBT_DRIVER_MODE_AR_ACTIONS (SLBT_DRIVER_MODE_AR_CHECK) +#define SLBT_DRIVER_MODE_AR_ACTIONS (SLBT_DRIVER_MODE_AR_CHECK \ + | SLBT_DRIVER_MODE_AR_MERGE) #define SLBT_DRIVER_MODE_AR_OUTPUTS (SLBT_OUTPUT_ARCHIVE_MEMBERS \ | SLBT_OUTPUT_ARCHIVE_HEADERS \ @@ -77,6 +78,7 @@ static int slbt_exec_ar_perform_archive_actions( struct slbt_archive_ctx ** arctxv) { struct slbt_archive_ctx ** arctxp; + struct slbt_archive_ctx * arctx; for (arctxp=arctxv; *arctxp; arctxp++) { if (dctx->cctx->fmtflags & SLBT_DRIVER_MODE_AR_OUTPUTS) @@ -88,6 +90,15 @@ static int slbt_exec_ar_perform_archive_actions( return SLBT_NESTED_ERROR(dctx); } + if (dctx->cctx->drvflags & SLBT_DRIVER_MODE_AR_MERGE) { + if (slbt_merge_archives(arctxv,&arctx) < 0) + return SLBT_NESTED_ERROR(dctx); + + /* (defer mode to umask) */ + if (slbt_store_archive(arctx,dctx->cctx->output,0666) < 0) + return SLBT_NESTED_ERROR(dctx); + } + return 0; } @@ -183,6 +194,14 @@ int slbt_exec_ar( ictx->cctx.drvflags |= SLBT_DRIVER_MODE_AR_CHECK; break; + case TAG_AR_MERGE: + ictx->cctx.drvflags |= SLBT_DRIVER_MODE_AR_MERGE; + break; + + case TAG_AR_OUTPUT: + ictx->cctx.output = entry->arg; + break; + case TAG_AR_PRINT: if (!entry->arg) ictx->cctx.fmtflags |= SLBT_OUTPUT_ARCHIVE_MEMBERS; @@ -260,6 +279,37 @@ int slbt_exec_ar( SLBT_ERR_AR_NO_ACTION_SPECIFIED)); } + /* -Wmerge without -Woutput? */ + if ((cctx->drvflags & SLBT_DRIVER_MODE_AR_MERGE) && !cctx->output) { + if (cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS) + slbt_dprintf(fderr, + "%s: archive merging: output must be specified.\n", + dctx->program); + + return slbt_exec_ar_fail( + actx,meta, + SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_AR_OUTPUT_NOT_SPECIFIED)); + } + + + /* -Woutput without -Wmerge? */ + if (cctx->output && !(cctx->drvflags & SLBT_DRIVER_MODE_AR_MERGE)) { + if (cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS) + slbt_dprintf(fderr, + "%s: output may only be specified " + "when merging one or more archives.\n", + dctx->program); + + return slbt_exec_ar_fail( + actx,meta, + SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_AR_OUTPUT_NOT_APPLICABLE)); + } + + /* at least one unit must be specified */ if (!nunits) { if (cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS) diff --git a/src/skin/slbt_skin_ar.c b/src/skin/slbt_skin_ar.c index 5108554..d424abe 100644 --- a/src/skin/slbt_skin_ar.c +++ b/src/skin/slbt_skin_ar.c @@ -14,6 +14,22 @@ const struct argv_option slbt_ar_options[] = { "verify that each %s is a valid archive; " "supported variants are BSD, SysV, and PE/COFF"}, + {"Wmerge", 0,TAG_AR_MERGE,ARGV_OPTARG_NONE, + ARGV_OPTION_HYBRID_ONLY, + "[ARCHIVE-FILE]",0, + "merge one or more archive files; " + "the name of the new archive, which may be the same " + "as one of the input archives, shall be specified " + "via the -Woutput switch; order of archive members " + "shall be retained, and symbol maps shall be " + "merged as well as normalized."}, + + {"Woutput", 0,TAG_AR_OUTPUT,ARGV_OPTARG_REQUIRED, + ARGV_OPTION_HYBRID_ONLY|ARGV_OPTION_HYBRID_SPACE, + 0,0, + "specify the name of the archive to be created " + "(or replaced) as a result of a -Wmerge operation."}, + {"Wprint", 0,TAG_AR_PRINT,ARGV_OPTARG_OPTIONAL, ARGV_OPTION_HYBRID_EQUAL|ARGV_OPTION_HYBRID_COMMA, "members",0,