diff options
Diffstat (limited to 'src/driver')
-rw-r--r-- | src/driver/pe_amain.c | 102 | ||||
-rw-r--r-- | src/driver/pe_driver_ctx.c | 414 | ||||
-rw-r--r-- | src/driver/pe_unit_ctx.c | 159 |
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); } } |