summaryrefslogtreecommitdiffhomepage
path: root/src/driver
diff options
context:
space:
mode:
Diffstat (limited to 'src/driver')
-rw-r--r--src/driver/pe_amain.c102
-rw-r--r--src/driver/pe_driver_ctx.c414
-rw-r--r--src/driver/pe_unit_ctx.c159
3 files changed, 505 insertions, 170 deletions
diff --git a/src/driver/pe_amain.c b/src/driver/pe_amain.c
index 286e111..a766dba 100644
--- a/src/driver/pe_amain.c
+++ b/src/driver/pe_amain.c
@@ -10,13 +10,15 @@
#include <perk/perk_output.h>
#include "perk_driver_impl.h"
#include "perk_dprintf_impl.h"
+#include "perk_ar_impl.h"
#ifndef PERK_DRIVER_FLAGS
#define PERK_DRIVER_FLAGS PERK_DRIVER_VERBOSITY_ERRORS \
- | PERK_DRIVER_VERBOSITY_USAGE
+ | PERK_DRIVER_VERBOSITY_UTILITY \
+ | PERK_DRIVER_AR_OBJECT_VECTOR
#endif
-static const char vermsg[] = "%s%s%s (git://midipix.org/perk): "
+static const char vermsg[] = "%s%s%s (https://git.foss21.org/perk): "
"version %s%d.%d.%d%s.\n"
"[commit reference: %s%s%s]\n";
@@ -48,67 +50,10 @@ static ssize_t pe_version(struct pe_driver_ctx * dctx, int fdout)
verclr[4],verinfo->commit,verclr[5]);
}
-static void pe_perform_hdrdump_actions(
- const struct pe_driver_ctx * dctx,
- struct pe_unit_ctx * uctx)
-{
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_IMAGE_DOS_HEADER)
- pe_hdrdump_image_dos_hdr(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_IMAGE_HEADER)
- pe_hdrdump_coff_image_hdr(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_OBJECT_HEADER)
- pe_hdrdump_coff_object_hdr(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_OPT_HEADER)
- pe_hdrdump_coff_opt_hdr(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_SECTION_TABLE)
- pe_hdrdump_sec_tbl(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_EXPORT_HEADER)
- pe_hdrdump_export_hdr(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump & PERK_HDRDUMP_IMPORT_TABLE)
- pe_hdrdump_import_tbl(dctx,uctx->meta);
-}
-
-static void pe_perform_unit_actions(
- const struct pe_driver_ctx * dctx,
- struct pe_unit_ctx * uctx)
-{
- uint64_t flags = dctx->cctx->fmtflags;
-
- if (flags & PERK_OUTPUT_IMAGE_CATEGORY)
- pe_output_image_category(dctx,uctx->meta);
-
- if (flags & PERK_OUTPUT_IMAGE_SECTIONS)
- pe_output_image_sections(dctx,uctx->meta);
-
- if (flags & PERK_OUTPUT_IMAGE_SYMBOLS)
- pe_output_image_symbols(dctx,uctx->meta);
-
- if (flags & PERK_OUTPUT_IMAGE_STRINGS)
- pe_output_image_strings(dctx,uctx->meta);
-
- if (flags & PERK_OUTPUT_EXPORT_SYMS)
- pe_output_export_symbols(dctx,uctx->meta);
-
- if ((flags & PERK_OUTPUT_IMPORT_LIBS) || (flags & PERK_OUTPUT_IMPORT_SYMS))
- pe_output_import_libraries(dctx,uctx->meta);
-
- if ((flags & PERK_OUTPUT_MDSO_LIBS) || (flags & PERK_OUTPUT_MDSO_SYMS))
- pe_output_mdso_libraries(dctx,uctx->meta);
-
- if (dctx->cctx->hdrdump)
- pe_perform_hdrdump_actions(dctx,uctx);
-}
-
static int pe_exit(struct pe_driver_ctx * dctx, int ret)
{
pe_output_error_vector(dctx);
- pe_free_driver_ctx(dctx);
+ pe_lib_free_driver_ctx(dctx);
return ret;
}
@@ -118,13 +63,16 @@ int pe_main(char ** argv, char ** envp, const struct pe_fd_ctx * fdctx)
int fdout;
uint64_t flags;
struct pe_driver_ctx * dctx;
- struct pe_unit_ctx * uctx;
const char ** unit;
+ const char * posname;
+ const char * arname;
+ const char ** arfiles;
+ uint64_t arflags;
flags = PERK_DRIVER_FLAGS;
fdout = fdctx ? fdctx->fdout : STDOUT_FILENO;
- if ((ret = pe_get_driver_ctx(argv,envp,flags,fdctx,&dctx)))
+ if ((ret = pe_lib_get_driver_ctx(argv,envp,flags,fdctx,&dctx)))
return (ret == PERK_USAGE)
? !argv || !argv[0] || !argv[1]
: PERK_ERROR;
@@ -133,11 +81,31 @@ int pe_main(char ** argv, char ** envp, const struct pe_fd_ctx * fdctx)
if ((pe_version(dctx,fdout)) < 0)
return pe_exit(dctx,PERK_ERROR);
- for (unit=dctx->units; *unit; unit++) {
- if (!(pe_get_unit_ctx(dctx,*unit,&uctx))) {
- pe_perform_unit_actions(dctx,uctx);
- pe_free_unit_ctx(uctx);
- }
+ switch (dctx->cctx->cmd) {
+ case PERK_CMD_PERK:
+ for (unit=dctx->units; *unit; unit++)
+ pe_cmd_perk(dctx,*unit);
+ break;
+
+ case PERK_CMD_AR:
+ arflags = dctx->cctx->drvflags;
+
+ if (arflags & AR_POSNAME_MASK) {
+ posname = dctx->units[0];
+ arname = posname ? dctx->units[1] : 0;
+ arfiles = arname ? &dctx->units[2] : 0;
+ } else {
+ posname = 0;
+ arname = dctx->units[0];
+ arfiles = arname ? &dctx->units[1] : 0;
+ }
+
+ pe_cmd_ar(dctx,arflags,posname,arname,arfiles);
+
+ break;
+
+ default:
+ break;
}
return pe_exit(dctx,dctx->errv[0] ? PERK_ERROR : PERK_OK);
diff --git a/src/driver/pe_driver_ctx.c b/src/driver/pe_driver_ctx.c
index 9955548..11c2e27 100644
--- a/src/driver/pe_driver_ctx.c
+++ b/src/driver/pe_driver_ctx.c
@@ -14,6 +14,7 @@
#include <perk/perk_output.h>
#include "perk_version.h"
#include "perk_driver_impl.h"
+#include "perk_synopsis_impl.h"
#include "argv/argv.h"
/* package info */
@@ -24,6 +25,19 @@ static const struct pe_source_version pe_src_version = {
PERK_GIT_VERSION
};
+/* perk command names */
+static const char * const perk_cmd_name[PERK_CMD_CAP] = {
+ [PERK_CMD_PERK] = "perk",
+ [PERK_CMD_AR] = "ar",
+};
+
+/* perk command options */
+static const struct argv_option * perk_cmd_options[PERK_CMD_CAP] = {
+ [PERK_CMD_DEFAULT] = pe_default_options,
+ [PERK_CMD_PERK] = pe_perk_options,
+ [PERK_CMD_AR] = pe_ar_options,
+};
+
/* default fd context */
static const struct pe_fd_ctx pe_default_fdctx = {
.fdin = STDIN_FILENO,
@@ -62,13 +76,40 @@ static int pe_driver_usage(
const char * program,
const char * arg,
const struct argv_option ** optv,
- struct argv_meta * meta)
+ struct argv_meta * meta,
+ const char * cmdarg,
+ enum pe_cmd cmd)
{
- char header[512];
-
- snprintf(header,sizeof(header),
- "Usage: %s [options] <file>...\n" "Options:\n",
- program);
+ char header [2048];
+ char cmdname[128];
+
+ snprintf(cmdname,sizeof(cmdname),"%s%s%s",
+ program,
+ cmdarg ? " --cmd=" : "",
+ cmdarg ? perk_cmd_name[cmd] : "");
+
+ switch (cmd) {
+ case PERK_CMD_AR:
+ snprintf(header,sizeof(header),
+ PERK_AR_CMD_SYNOPSIS,
+ cmdname,cmdname,cmdname,cmdname,
+ cmdname,cmdname,cmdname,cmdname,
+ cmdname,cmdname,cmdname,cmdname,
+ cmdname,cmdname,cmdname);
+ break;
+
+ case PERK_CMD_PERK:
+ snprintf(header,sizeof(header),
+ PERK_PERK_CMD_SYNOPSIS,
+ cmdname,cmdname,cmdname);
+ break;
+
+ default:
+ snprintf(header,sizeof(header),
+ PERK_DEFAULT_CMD_SYNOPSIS,
+ program,program,program,program);
+ break;
+ }
argv_usage(fdout,header,optv,arg);
argv_free(meta);
@@ -113,157 +154,354 @@ static struct pe_driver_ctx_impl * pe_driver_ctx_alloc(
return &ictx->ctx;
}
-static int pe_get_driver_ctx_fail(struct argv_meta * meta)
+static int pe_cmd_from_program(const char * program)
{
- argv_free(meta);
- return -1;
-}
+ const char * dot;
+ const char * hyphen;
+ const char * mark;
-int pe_get_driver_ctx(
- char ** argv,
- char ** envp,
- uint32_t flags,
- const struct pe_fd_ctx * fdctx,
- struct pe_driver_ctx ** pctx)
-{
- struct pe_driver_ctx_impl * ctx;
- struct pe_common_ctx cctx;
- const struct argv_option * optv[PERK_OPTV_ELEMENTS];
- struct argv_meta * meta;
- struct argv_entry * entry;
- size_t nunits;
- const char * program;
- const char * pretty;
+ dot = strrchr(program,'.');
+ hyphen = strrchr(program,'-');
- (void)envp;
+ if (hyphen > dot)
+ mark = ++hyphen;
+ else if (dot > hyphen)
+ mark = ++dot;
+ else
+ mark = program;
- if (!fdctx)
- fdctx = &pe_default_fdctx;
+ if (!strcmp(mark,"perk")) {
+ return PERK_CMD_PERK;
- argv_optv_init(pe_default_options,optv);
+ } else if (!strcmp(mark,"ar")) {
+ return PERK_CMD_AR;
- if (!(meta = argv_get(
- argv,optv,
- pe_argv_flags(flags),
- fdctx->fderr)))
- return -1;
+ } else {
+ return PERK_CMD_DEFAULT;
+ }
+}
- pretty = 0;
- nunits = 0;
- program = argv_program_name(argv[0]);
- memset(&cctx,0,sizeof(cctx));
- cctx.drvflags = flags;
+static int pe_cctx_update(
+ const char * program,
+ const struct argv_option ** optv,
+ struct argv_meta * meta,
+ const struct pe_fd_ctx * fdctx,
+ struct pe_common_ctx * cctx,
+ size_t * nunits,
+ const char * cmdarg)
+{
+ struct argv_entry * entry;
+ const char * pretty;
- if (!argv[1] && (flags & PERK_DRIVER_VERBOSITY_USAGE))
- return pe_driver_usage(
- fdctx->fderr,
- program,
- 0,optv,meta);
+ pretty = 0;
/* get options, count units */
for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
if (entry->fopt) {
switch (entry->tag) {
case TAG_HELP:
- if (flags & PERK_DRIVER_VERBOSITY_USAGE)
+ return pe_driver_usage(
+ fdctx->fdout,
+ program,entry->arg,
+ optv,0,cmdarg,cctx->cmd);
+ break;
+
+ case TAG_CMD:
+ if (*nunits)
return pe_driver_usage(
- fdctx->fdout,
- program,entry->arg,
- optv,meta);
+ fdctx->fderr,
+ program,0,
+ optv,0,cmdarg,cctx->cmd);
+
+ cctx->cmd = pe_cmd_from_program(entry->arg);
+ cmdarg = entry->arg;
break;
case TAG_VERSION:
- cctx.drvflags |= PERK_DRIVER_VERSION;
+ cctx->drvflags |= PERK_DRIVER_VERSION;
break;
case TAG_PRETTY:
pretty = entry->arg;
break;
+ case TAG_VERBOSE:
+ cctx->fmtflags |= PERK_PRETTY_VERBOSE;
+ break;
+
case TAG_CATEGORY:
- cctx.fmtflags |= PERK_OUTPUT_IMAGE_CATEGORY;
+ cctx->fmtflags |= PERK_OUTPUT_IMAGE_CATEGORY;
break;
case TAG_SECTIONS:
- cctx.fmtflags |= PERK_OUTPUT_IMAGE_SECTIONS;
+ cctx->fmtflags |= PERK_OUTPUT_IMAGE_SECTIONS;
break;
case TAG_SYMBOLS:
- cctx.fmtflags |= PERK_OUTPUT_IMAGE_SYMBOLS;
+ cctx->fmtflags |= PERK_OUTPUT_IMAGE_SYMBOLS;
break;
case TAG_STRINGS:
- cctx.fmtflags |= PERK_OUTPUT_IMAGE_STRINGS;
+ cctx->fmtflags |= PERK_OUTPUT_IMAGE_STRINGS;
break;
case TAG_EXPSYMS:
- cctx.fmtflags |= PERK_OUTPUT_EXPORT_SYMS;
+ cctx->fmtflags |= PERK_OUTPUT_EXPORT_SYMS;
break;
case TAG_IMPLIBS:
- cctx.fmtflags |= PERK_OUTPUT_IMPORT_LIBS;
+ cctx->fmtflags |= PERK_OUTPUT_IMPORT_LIBS;
break;
case TAG_IMPSYMS:
- cctx.fmtflags |= PERK_OUTPUT_IMPORT_SYMS;
+ cctx->fmtflags |= PERK_OUTPUT_IMPORT_SYMS;
break;
case TAG_DSOLIBS:
- cctx.fmtflags |= PERK_OUTPUT_MDSO_LIBS;
+ cctx->fmtflags |= PERK_OUTPUT_MDSO_LIBS;
break;
case TAG_DSOSYMS:
- cctx.fmtflags |= PERK_OUTPUT_MDSO_SYMS;
+ cctx->fmtflags |= PERK_OUTPUT_MDSO_SYMS;
break;
case TAG_HDRDUMP:
if (!entry->arg) {
- cctx.hdrdump = 0;
- cctx.hdrdump = ~cctx.hdrdump;
+ cctx->hdrdump = 0;
+ cctx->hdrdump = ~cctx->hdrdump;
} else if (!strcmp(entry->arg,"dos")) {
- cctx.hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER;
} else if (!strcmp(entry->arg,"image.dos")) {
- cctx.hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER;
} else if (!strcmp(entry->arg,"coff")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER;
- cctx.hdrdump |= PERK_HDRDUMP_COFF_OBJECT_HEADER;
- cctx.hdrdump |= PERK_HDRDUMP_COFF_OPT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER;
+ cctx->hdrdump |= PERK_HDRDUMP_COFF_OBJECT_HEADER;
+ cctx->hdrdump |= PERK_HDRDUMP_COFF_OPT_HEADER;
} else if (!strcmp(entry->arg,"coff.image")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER;
} else if (!strcmp(entry->arg,"coff.obj")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER;
} else if (!strcmp(entry->arg,"coff.object")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER;
} else if (!strcmp(entry->arg,"coff.opt")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER;
} else if (!strcmp(entry->arg,"coff.optional")) {
- cctx.hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER;
} else if (!strcmp(entry->arg,"sectbl")) {
- cctx.hdrdump = PERK_HDRDUMP_SECTION_TABLE;
+ cctx->hdrdump = PERK_HDRDUMP_SECTION_TABLE;
} else if (!strcmp(entry->arg,"section.table")) {
- cctx.hdrdump = PERK_HDRDUMP_SECTION_TABLE;
+ cctx->hdrdump = PERK_HDRDUMP_SECTION_TABLE;
} else if (!strcmp(entry->arg,"exphdr")) {
- cctx.hdrdump = PERK_HDRDUMP_EXPORT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_EXPORT_HEADER;
} else if (!strcmp(entry->arg,"export.header")) {
- cctx.hdrdump = PERK_HDRDUMP_EXPORT_HEADER;
+ cctx->hdrdump = PERK_HDRDUMP_EXPORT_HEADER;
} else if (!strcmp(entry->arg,"imptbl")) {
- cctx.hdrdump = PERK_HDRDUMP_IMPORT_TABLE;
+ cctx->hdrdump = PERK_HDRDUMP_IMPORT_TABLE;
} else if (!strcmp(entry->arg,"import.table")) {
- cctx.hdrdump = PERK_HDRDUMP_IMPORT_TABLE;
+ cctx->hdrdump = PERK_HDRDUMP_IMPORT_TABLE;
}
break;
+
+ /*---ar---*/
+ case TAG_AR_LIST_MEMBERS:
+ cctx->drvflags |= PERK_DRIVER_AR_LIST_MEMBERS;
+ break;
+
+ case TAG_AR_PRINT_MEMBERS:
+ cctx->drvflags |= PERK_DRIVER_AR_PRINT_MEMBERS;
+ break;
+ }
+ } else {
+ (*nunits)++;
+ }
+ }
+
+ if (pretty && !strcmp(pretty,"yaml")) {
+ cctx->fmtflags |= PERK_PRETTY_YAML;
+
+ } else if (pretty && !strcmp(pretty,"posix")) {
+ cctx->fmtflags |= PERK_PRETTY_POSIX;
+
+ } else if (pretty && !strcmp(pretty,"hexdata")) {
+ cctx->fmtflags |= PERK_PRETTY_HEXDATA;
+
+ } else if (pretty && !strcmp(pretty,"dlltool")) {
+ cctx->fmtflags |= PERK_PRETTY_DLLTOOL;
+ }
+
+ return 0;
+}
+
+static int pe_lib_get_driver_ctx_fail(struct argv_meta * meta)
+{
+ argv_free(meta);
+ return -1;
+}
+
+int pe_lib_get_driver_ctx(
+ char ** argv,
+ char ** envp,
+ uint32_t flags,
+ const struct pe_fd_ctx * fdctx,
+ struct pe_driver_ctx ** pctx)
+{
+ struct pe_driver_ctx_impl * ctx;
+ struct pe_common_ctx cctx;
+ const struct argv_option * optv[PERK_OPTV_ELEMENTS];
+ struct argv_meta * meta;
+ size_t nunits;
+ const char * program;
+ const char * cmdarg;
+ char ** parg;
+ char ** pargcap;
+ char ** cmdargv;
+ char * cmdmark;
+ char stckarg[64];
+ struct argv_ctx actx = {ARGV_VERBOSITY_NONE,
+ ARGV_MODE_SCAN,
+ 0,0,0,0,0,0,0,0};
+
+
+ (void)envp;
+
+ /* fdctx */
+ if (!fdctx)
+ fdctx = &pe_default_fdctx;
+
+ /* cctx */
+ memset(&cctx,0,sizeof(cctx));
+
+ program = argv_program_name(argv[0]);\
+ cctx.cmd = pe_cmd_from_program(program);
+ cctx.drvflags = flags;
+ nunits = 0;
+ cmdarg = 0;
+
+ /* missing arguments? */
+ argv_optv_init(perk_cmd_options[cctx.cmd],optv);
+
+ if (!argv[1] && (flags & PERK_DRIVER_VERBOSITY_UTILITY))
+ return pe_driver_usage(
+ fdctx->fderr,
+ program,0,
+ optv,0,0,cctx.cmd);
+
+ /* historic ar usage (vector will be cloned, so stack var is fine) */
+ if (cctx.cmd == PERK_CMD_AR) {
+ if (argv && argv[0] && argv[1] && (argv[1][0] != '-')) {
+ if (strlen(argv[1]) < (sizeof(stckarg) - 1)) {
+ stckarg[0] = '-';
+ strcpy(&stckarg[1],argv[1]);
+ argv[1] = stckarg;
}
- } else
- nunits++;
+ }
+ }
+
+ /* initial argv scan: ... --cmd=xxx ... */
+ argv_scan(argv,optv,&actx,0);
+
+ /* position of last base perk argument */
+ if (actx.erridx && actx.unitidx)
+ pargcap = &argv[actx.unitidx];
+
+ else if (actx.erridx)
+ pargcap = &argv[actx.erridx];
+
+ else
+ for (pargcap=argv; *pargcap; pargcap++)
+ (void)0;
+
+ /* scan for --cmd */
+ for (parg=argv, cmdargv=0; (parg<pargcap) && !cmdargv; parg++) {
+ if (!strcmp(*parg,"--cmd") && parg[1]) {
+ cmdargv = &parg[2];
+ cmdmark = parg[2];
+ cmdarg = parg[1];
+ } else if (!strncmp(*parg,"--cmd=",6)) {
+ cmdargv = &parg[1];
+ cmdmark = parg[1];
+ cmdarg = &parg[0][6];
+ }
+ }
+
+ /* invalid perk arguments? */
+ if (!actx.erridx) {
+ (void)0;
+
+ } else if (&argv[actx.erridx] >= cmdargv) {
+ (void)0;
+
+ } else {
+ if (flags & PERK_DRIVER_VERBOSITY_ERRORS)
+ argv_get(
+ argv,optv,
+ ARGV_VERBOSITY_ERRORS,
+ fdctx->fderr);
+ return -1;
+ }
+
+ /* process argv entries preceding --cmd */
+ if (cmdargv) {
+ *cmdargv = 0;
+
+ if (!(meta = argv_get(
+ argv,optv,
+ pe_argv_flags(flags),
+ fdctx->fderr)))
+ return -1;
+
+ if (pe_cctx_update(
+ program,optv,meta,
+ fdctx,&cctx,&nunits,
+ cmdarg)) {
+ argv_free(meta);
+ return -1;
+ }
+
+ argv_free(meta);
+
+ *cmdargv-- = cmdmark;
+ *cmdargv = argv[0];
+ argv = cmdargv;
+ }
+
+ /* set option vector by command */
+ if (cctx.cmd == PERK_CMD_DEFAULT) {
+ argv_optv_init(pe_default_options,optv);
+
+ } else if (cctx.cmd == PERK_CMD_PERK) {
+ argv_optv_init(pe_perk_options,optv);
+
+ } else if (cctx.cmd == PERK_CMD_AR) {
+ argv_optv_init(pe_ar_options,optv);
+ }
+
+ /* process the selected tool's command-line arguments */
+ if (!(meta = argv_get(
+ argv,optv,
+ pe_argv_flags(flags),
+ fdctx->fderr)))
+ return -1;
+
+ if (pe_cctx_update(
+ program,optv,meta,
+ fdctx,&cctx,&nunits,
+ cmdarg)) {
+ argv_free(meta);
+ return -1;
}
- if (pretty && !strcmp(pretty,"yaml"))
- cctx.fmtflags |= PERK_PRETTY_YAML;
- else if (pretty && !strcmp(pretty,"dlltool"))
- cctx.fmtflags |= PERK_PRETTY_DLLTOOL;
+ /* utility mode and no action to take? */
+ if (cctx.drvflags & PERK_DRIVER_VERBOSITY_UTILITY)
+ if (!nunits && !(cctx.drvflags & PERK_DRIVER_VERSION))
+ return pe_driver_usage(
+ fdctx->fdout,
+ program,0,optv,meta,
+ cmdarg,cctx.cmd);
+ /* context allocation */
if (!(ctx = pe_driver_ctx_alloc(meta,fdctx,&cctx,nunits)))
- return pe_get_driver_ctx_fail(meta);
+ return pe_lib_get_driver_ctx_fail(meta);
ctx->ctx.program = program;
ctx->ctx.cctx = &ctx->cctx;
@@ -272,13 +510,13 @@ int pe_get_driver_ctx(
return PERK_OK;
}
-static void pe_free_driver_ctx_impl(struct pe_driver_ctx_alloc * ictx)
+static void pe_lib_free_driver_ctx_impl(struct pe_driver_ctx_alloc * ictx)
{
argv_free(ictx->meta);
free(ictx);
}
-void pe_free_driver_ctx(struct pe_driver_ctx * ctx)
+void pe_lib_free_driver_ctx(struct pe_driver_ctx * ctx)
{
struct pe_driver_ctx_alloc * ictx;
uintptr_t addr;
@@ -287,7 +525,7 @@ void pe_free_driver_ctx(struct pe_driver_ctx * ctx)
addr = (uintptr_t)ctx - offsetof(struct pe_driver_ctx_impl,ctx);
addr = addr - offsetof(struct pe_driver_ctx_alloc,ctx);
ictx = (struct pe_driver_ctx_alloc *)addr;
- pe_free_driver_ctx_impl(ictx);
+ pe_lib_free_driver_ctx_impl(ictx);
}
}
@@ -296,7 +534,7 @@ const struct pe_source_version * pe_source_version(void)
return &pe_src_version;
}
-int pe_get_driver_fdctx(
+int pe_lib_get_driver_fdctx(
const struct pe_driver_ctx * dctx,
struct pe_fd_ctx * fdctx)
{
@@ -314,7 +552,7 @@ int pe_get_driver_fdctx(
return 0;
}
-int pe_set_driver_fdctx(
+int pe_lib_set_driver_fdctx(
struct pe_driver_ctx * dctx,
const struct pe_fd_ctx * fdctx)
{
diff --git a/src/driver/pe_unit_ctx.c b/src/driver/pe_unit_ctx.c
index 5333a2d..b165226 100644
--- a/src/driver/pe_unit_ctx.c
+++ b/src/driver/pe_unit_ctx.c
@@ -11,27 +11,136 @@
#include <sys/mman.h>
#include <perk/perk.h>
+#include <perk/perk_arbits.h>
+#include "perk_ar_impl.h"
#include "perk_driver_impl.h"
#include "perk_errinfo_impl.h"
-static int pe_free_unit_ctx_impl(struct pe_unit_ctx_impl * ctx, int ret)
+static int pe_lib_free_unit_ctx_impl(struct pe_unit_ctx_impl * ctx, int ret)
{
+ struct pe_image_meta ** pmeta;
if (ctx) {
- pe_free_image_meta(ctx->meta);
- pe_unmap_raw_image(&ctx->map);
+ for (pmeta=ctx->objmeta; pmeta && *pmeta; pmeta++)
+ pe_meta_free_image_meta(*pmeta);
+
+ pe_ar_free_archive_meta(ctx->armeta);
+ pe_meta_free_image_meta(ctx->meta);
+ pe_raw_unmap_raw_image(&ctx->map);
+ free(ctx->usrobjmeta);
+ free(ctx->objmeta);
free(ctx);
}
return ret;
}
-int pe_get_unit_ctx(
+static int pe_lib_create_object_vector_or_verify_archive(
+ const struct pe_driver_ctx * dctx,
+ struct pe_unit_ctx_impl * ctx)
+{
+ struct pe_archive_meta * actx;
+ struct pe_archive_meta_impl * ictx;
+ struct pe_driver_ctx_impl * idctx;
+ bool fvector;
+ bool fstrict;
+ bool fpurearch;
+ struct pe_image_meta * meta;
+ struct pe_image_meta ** objmeta;
+ const struct pe_image_meta ** usrobjmeta;
+ size_t veclen;
+ struct pe_raw_image map;
+ struct ar_meta_member_info ** pmember;
+ struct pe_error_info ** errinfp;
+ enum pe_abi m_abi;
+ enum pe_subtype m_subtype;
+
+ fvector = (dctx->cctx->drvflags & PERK_DRIVER_AR_OBJECT_VECTOR);
+ fstrict = (dctx->cctx->drvflags & PERK_DRIVER_AR_STRICT_PE);
+ fpurearch = (dctx->cctx->drvflags & PERK_DRIVER_AR_STRICT_PE_ARCH);
+
+ if (!fvector && !fstrict && !fpurearch)
+ return 0;
+
+ actx = ctx->armeta;
+ ictx = pe_archive_meta_ictx(actx);
+ idctx = pe_get_driver_ictx(dctx);
+ veclen = ictx->nentries + 1;
+
+ if (fvector && !(ctx->objmeta = calloc(veclen,sizeof(meta))))
+ return PERK_BUFFER_ERROR(dctx);
+
+ if (fvector && !(ctx->usrobjmeta = calloc(veclen,sizeof(*usrobjmeta))))
+ return PERK_BUFFER_ERROR(dctx);
+
+ if (!actx->a_memberv)
+ return 0;
+
+ objmeta = ctx->objmeta;
+ usrobjmeta = ctx->usrobjmeta;
+
+ for (pmember=actx->a_memberv; *pmember; pmember++) {
+ errinfp = idctx->errinfp;
+
+ switch (pmember[0]->ar_member_attr) {
+ case AR_MEMBER_ATTR_ARCHIVE:
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_NESTED_ARCHIVE);
+
+ case AR_MEMBER_ATTR_ARMAP:
+ case AR_MEMBER_ATTR_NAMESTRS:
+ case AR_MEMBER_ATTR_LINKINFO:
+ break;
+
+ default:
+ map.map_addr = pmember[0]->ar_object_data;
+ map.map_size = pmember[0]->ar_object_size;
+
+ if (!pe_meta_get_image_meta(dctx,&map,&meta)) {
+ if (fpurearch && (objmeta == ctx->objmeta)) {
+ m_abi = meta->m_abi;
+ m_subtype = meta->m_subtype;
+
+ } else if (fpurearch) {
+ if ((meta->m_abi != m_abi) || (meta->m_subtype != m_subtype))
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_MIXED_PE_MEMBERS);
+ }
+
+ if (fvector) {
+ *objmeta++ = meta;
+ *usrobjmeta++ = meta;
+ } else {
+ pe_meta_free_image_meta(meta);
+ };
+
+
+ } else if (fstrict || fpurearch) {
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_NON_PE_MEMBERS);
+
+ } else {
+ idctx->errinfp = errinfp;
+
+ for (; *errinfp; )
+ *errinfp++ = 0;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int pe_lib_get_unit_ctx(
const struct pe_driver_ctx * dctx,
const char * path,
struct pe_unit_ctx ** pctx)
{
struct pe_unit_ctx_impl * ctx;
int prot;
+ char * mark;
+ size_t siglen;
if (!dctx)
return PERK_CUSTOM_ERROR(
@@ -43,28 +152,48 @@ int pe_get_unit_ctx(
pe_driver_set_ectx(
dctx,0,path);
- prot = (dctx->cctx->actflags & PERK_ACTION_MAP_READWRITE)
+ prot = (dctx->cctx->drvflags & PERK_DRIVER_MAP_WRITE_ACCESS)
? PROT_READ | PROT_WRITE
: PROT_READ;
- if (pe_map_raw_image(dctx,-1,path,prot,&ctx->map))
- return pe_free_unit_ctx_impl(ctx,
+ if (pe_raw_map_raw_image(dctx,-1,path,prot,&ctx->map))
+ return pe_lib_free_unit_ctx_impl(ctx,
PERK_NESTED_ERROR(dctx));
- if (pe_get_image_meta(dctx,&ctx->map,&ctx->meta))
- return pe_free_unit_ctx_impl(ctx,
+ if (ctx->map.map_size < (siglen = sizeof(struct ar_raw_signature)))
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_CUSTOM_ERROR(
+ dctx,
+ PERK_ERR_INVALID_IMAGE));
+
+ if (!strncmp((mark = ctx->map.map_addr),AR_SIGNATURE,siglen)) {
+ ctx->armap.map_addr = ctx->map.map_addr;
+ ctx->armap.map_size = ctx->map.map_size;
+
+ if (pe_ar_get_archive_meta(dctx,&ctx->armap,&ctx->armeta))
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_NESTED_ERROR(dctx));
+
+ if (pe_lib_create_object_vector_or_verify_archive(dctx,ctx) < 0)
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_NESTED_ERROR(dctx));
+
+ } else if (pe_meta_get_image_meta(dctx,&ctx->map,&ctx->meta)) {
+ return pe_lib_free_unit_ctx_impl(ctx,
PERK_NESTED_ERROR(dctx));
+ }
- ctx->path = path;
- ctx->uctx.path = &ctx->path;
- ctx->uctx.map = &ctx->map;
- ctx->uctx.meta = ctx->meta;
+ ctx->path = path;
+ ctx->uctx.path = &ctx->path;
+ ctx->uctx.meta = ctx->meta;
+ ctx->uctx.armeta = ctx->armeta;
+ ctx->uctx.objmeta = ctx->usrobjmeta;
*pctx = &ctx->uctx;
return 0;
}
-void pe_free_unit_ctx(struct pe_unit_ctx * ctx)
+void pe_lib_free_unit_ctx(struct pe_unit_ctx * ctx)
{
struct pe_unit_ctx_impl * ictx;
uintptr_t addr;
@@ -72,6 +201,6 @@ void pe_free_unit_ctx(struct pe_unit_ctx * ctx)
if (ctx) {
addr = (uintptr_t)ctx - offsetof(struct pe_unit_ctx_impl,uctx);
ictx = (struct pe_unit_ctx_impl *)addr;
- pe_free_unit_ctx_impl(ictx,0);
+ pe_lib_free_unit_ctx_impl(ictx,0);
}
}