From: norly Date: Sat, 15 Jun 2013 23:47:23 +0000 (+0100) Subject: mv main.c -> elfucli.c, make it scriptable via args X-Git-Url: https://git.enpas.org/?p=centaur.git;a=commitdiff_plain;h=150d0c42d423fe49304d648e2c19ff08f6c2e0ad mv main.c -> elfucli.c, make it scriptable via args --- diff --git a/include/options.h b/include/options.h deleted file mode 100644 index 2210c85..0000000 --- a/include/options.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __OPTIONS_H__ -#define __OPTIONS_H__ - - -typedef struct { - char *fnInput; - char *fnOutput; - int printHeader; - int printSegments; - int printSections; - unsigned insertBeforeOffs; - unsigned insertBeforeSz; - unsigned insertAfterOffs; - unsigned insertAfterSz; - unsigned expandNobitsOffs; - char *fnReladd; -} CLIOpts; - - -void parseOptions(CLIOpts *opts, int argc, char **argv); - -#endif diff --git a/include/printing.h b/include/printing.h deleted file mode 100644 index bda2fc1..0000000 --- a/include/printing.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __PRINTING_H__ -#define __PRINTING_H__ - -#include - - -void printHeader(Elf *e); - -void printSegmentsWithSection(Elf *e, Elf_Scn *scn); -void printSection(Elf *e, Elf_Scn *scn); -void printSections(Elf *e); - -char* segmentTypeStr(size_t pt); -void printSectionsInSegment(Elf *e, GElf_Phdr *phdr); -void printSegments(Elf *e); - - -#endif diff --git a/src/elfucli.c b/src/elfucli.c new file mode 100644 index 0000000..0fd5a2d --- /dev/null +++ b/src/elfucli.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#include "elfhandle.h" + + + +static void printUsage(char *progname) +{ + printf("Usage: %s -i [OPTIONS]\n", progname); + printf("\n" + "Options, executed in order given:\n" + " -h, --help Print this help message\n" + "\n" + " -i, --input infile Load new ELF file (must be first command)\n" + "\n" + " -c, --check Do a few sanity checks and print any errors\n" + " -d, --dump Dump current model state (debug only)\n" + " --reladd obj.o Insert object file contents\n" + " -o, --output outfile Where to write the modified ELF file to\n" + "\n"); +} + + + + +int main(int argc, char **argv) +{ + ELFHandles hIn = { 0 }; + int exitval = EXIT_SUCCESS; + char *progname = argv[0]; + int c; + int option_index = 0; + ElfuElf *me = NULL; + + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"check", 0, 0, 'c'}, + {"dump", 0, 0, 'd'}, + {"input", 1, 0, 'i'}, + {"output", 1, 0, 'o'}, + {"reladd", 1, 0, 10001}, + {NULL, 0, NULL, 0} + }; + + + if (argc < 3) { + printUsage(progname); + goto EXIT; + } + + + /* Is libelf alive and well? */ + if (elf_version(EV_CURRENT) == EV_NONE) { + fprintf(stderr, "libelf init error: %s\n", elf_errmsg(-1)); + } + + + /* Parse and and execute user commands */ + while ((c = getopt_long(argc, argv, "hcdi:o:", + long_options, &option_index)) != -1) { + switch (c) { + case 'h': + printUsage(progname); + goto EXIT; + case 'c': + if (!me) { + goto ERR_NO_INPUT; + } else { + printf("Checking model validity...\n"); + elfu_mCheck(me); + } + break; + case 'd': + if (!me) { + goto ERR_NO_INPUT; + } else { + elfu_mDumpElf(me); + } + break; + case 'i': + printf("Opening input file %s.\n", optarg); + openElf(&hIn, optarg, ELF_C_READ); + if (!hIn.e) { + printf("Error: Failed to open input file. Aborting.\n"); + exitval = EXIT_FAILURE; + goto EXIT; + } + + me = elfu_mFromElf(hIn.e); + closeElf(&hIn); + + if (!me) { + printf("Error: Failed to load model, aborting.\n"); + goto EXIT; + } + break; + case 'o': + if (!me) { + goto ERR_NO_INPUT; + } else { + ELFHandles hOut = { 0 }; + + printf("Writing modified file to %s.\n", optarg); + + openElf(&hOut, optarg, ELF_C_WRITE); + if (!hOut.e) { + printf("Failed to open output file. Aborting.\n"); + closeElf(&hOut); + exitval = EXIT_FAILURE; + goto EXIT; + } + + elfu_mToElf(me, hOut.e); + + if (elf_update(hOut.e, ELF_C_WRITE) < 0) { + fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1)); + } + closeElf(&hOut); + } + break; + case 10001: + if (!me) { + goto ERR_NO_INPUT; + } else { + ELFHandles hRel = { 0 }; + ElfuElf *mrel = NULL; + + openElf(&hRel, optarg, ELF_C_READ); + if (!hRel.e) { + printf("--reladd: Failed to open file for --reladd, aborting.\n"); + closeElf(&hRel); + goto ERR; + } + + mrel = elfu_mFromElf(hRel.e); + closeElf(&hRel); + if (!mrel) { + printf("--reladd: Failed to load model for --reladd, aborting.\n"); + goto ERR; + } else { + printf("--reladd: Injecting %s...\n", optarg); + elfu_mCheck(mrel); + elfu_mReladd(me, mrel); + printf("--reladd: Injected %s.\n", optarg); + } + } + break; + case '?': + default: + printUsage(progname); + goto EXIT; + } + } + + while (optind < argc) { + optind++; + } + + + +EXIT: + if (hIn.e) { + closeElf(&hIn); + } + + return (exitval); + + +ERR_NO_INPUT: + printf("Error: No input file opened. Aborting.\n"); + +ERR: + exitval = EXIT_FAILURE; + goto EXIT; +} diff --git a/src/main.c b/src/main.c deleted file mode 100644 index eda76e5..0000000 --- a/src/main.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include - -#include "elfhandle.h" -#include "options.h" -#include "printing.h" - - -int main(int argc, char **argv) -{ - CLIOpts opts = { 0 }; - ELFHandles hIn = { 0 }; - ELFHandles hOut = { 0 }; - int exitval = EXIT_SUCCESS; - ElfuElf *me; - - /* Is libelf alive and well? */ - if (elf_version(EV_CURRENT) == EV_NONE) { - fprintf(stderr, "libelf init error: %s\n", elf_errmsg(-1)); - } - - - /* Parse and validate user input */ - parseOptions(&opts, argc, argv); - - - /* Open input/output files */ - openElf(&hIn, opts.fnInput, ELF_C_READ); - if (!hIn.e) { - exitval = EXIT_FAILURE; - goto EXIT; - } - - /* Now that we have a (hopefully) sane environment, execute commands. */ - me = elfu_mFromElf(hIn.e); - closeElf(&hIn); - if (!me) { - printf("Failed to load model, aborting.\n"); - goto EXIT; - } - - elfu_mCheck(me); - - //elfu_mDumpElf(me); - - /* Perform requested transformations on the memory model on-the-fly. */ - if (opts.fnReladd) { - ELFHandles hRel = { 0 }; - ElfuElf *mrel = NULL; - - openElf(&hRel, opts.fnReladd, ELF_C_READ); - if (!hRel.e) { - printf("--reladd: Failed to open file for --reladd, skipping operation.\n"); - } else { - mrel = elfu_mFromElf(hRel.e); - closeElf(&hRel); - if (!mrel) { - printf("--reladd: Failed to load model for --reladd, skipping operation.\n"); - } else { - elfu_mCheck(mrel); - elfu_mReladd(me, mrel); - printf("--reladd: Injected %s.\n", opts.fnReladd); - } - } - } - - //elfu_mDumpElf(me); - - /* Copy the input ELF to the output file if one is specified. */ - if (opts.fnOutput) { - printf("Writing modified file to %s.\n", opts.fnOutput); - elfu_mCheck(me); - - - openElf(&hOut, opts.fnOutput, ELF_C_WRITE); - if (!hOut.e) { - printf("Failed to open output file. Aborting.\n"); - exitval = EXIT_FAILURE; - goto EXIT; - } - - elfu_mToElf(me, hOut.e); - - if (elf_update(hOut.e, ELF_C_WRITE) < 0) { - fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1)); - } - closeElf(&hOut); - } - - - -EXIT: - if (hIn.e) { - closeElf(&hIn); - } - - return (exitval); -} diff --git a/src/options.c b/src/options.c deleted file mode 100644 index b5018d3..0000000 --- a/src/options.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include -#include -#include - -#include "options.h" - - -static void printUsage(char *progname) -{ - printf("Usage: %s [OPTIONS] \n", progname); - printf("\n" - "Options:\n" - " -h, --help Print this help message\n" - " -o, --output Where to write the modified ELF file to\n" - "\n" -// "ELF dump:\n" -// " --print-header Print ELF header\n" -// " --print-segments Print program headers\n" -// " --print-sections Print sections\n" -// "\n" -// "Space insertion:\n" -// " off: File offset, not within any structure (headers or sections).\n" -// " sz: A multiple of the maximum alignment of all PHDRs.\n" -// "\n" -// " --expand-nobits off Expand virtual areas (NOBITS sections and similar PHDRs).\n" -// " --insert-before off,sz Insert spacing at given offset,\n" -// " mapping everything before it to lower mem addresses.\n" -// " --insert-after off,sz Insert spacing at given offset,\n" -// " mapping everything after it to higher mem addresses.\n" -// "\n" - "High-level insertion:\n" - " --reladd obj.o Automatically insert object file contents\n" - "\n"); -} - - - -void parseOptions(CLIOpts *opts, int argc, char **argv) -{ - char *progname = argv[0]; - int c; - int option_index = 0; - char *endptr; - - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"output", 1, 0, 'o'}, - {"print-header", 0, 0, 10001}, - {"print-segments", 0, 0, 10002}, - {"print-sections", 0, 0, 10003}, - {"insert-before", 1, 0, 10004}, - {"insert-after", 1, 0, 10005}, - {"expand-nobits", 1, 0, 10006}, - {"reladd", 1, 0, 10007}, - {NULL, 0, NULL, 0} - }; - - while ((c = getopt_long(argc, argv, "e:ho:", - long_options, &option_index)) != -1) { - switch (c) { - case 'h': - printUsage(progname); - exit(EXIT_SUCCESS); - case 'o': - opts->fnOutput = optarg; - break; - case 10001: - opts->printHeader = 1; - break; - case 10002: - opts->printSegments = 1; - break; - case 10003: - opts->printSections = 1; - break; - case 10004: - opts->insertBeforeOffs = strtoul(optarg, &endptr, 0); - if (endptr[0] != ',') { - goto USAGE; - } - opts->insertBeforeSz = strtoul(endptr + 1, &endptr, 0); - if (endptr[0] != '\0' || opts->insertBeforeSz == 0) { - goto USAGE; - } - break; - case 10005: - opts->insertAfterOffs = strtoul(optarg, &endptr, 0); - if (endptr[0] != ',') { - goto USAGE; - } - opts->insertAfterSz = strtoul(endptr + 1, &endptr, 0); - if (endptr[0] != '\0' || opts->insertAfterSz == 0) { - goto USAGE; - } - break; - case 10006: - opts->expandNobitsOffs = strtoul(optarg, &endptr, 0); - if (endptr[0] != '\0' || opts->expandNobitsOffs < 1) { - goto USAGE; - } - break; - case 10007: - opts->fnReladd = optarg; - break; - case '?': - default: - goto USAGE; - } - } - - while (optind < argc) { - if (!opts->fnInput) { - opts->fnInput = argv[optind]; - } - optind++; - } - - if (!opts->fnInput) { - fprintf(stderr, "Error: No input file specified.\n\n"); - goto USAGE; - } - - return; - -USAGE: - printUsage(progname); - exit(1); -}