From fb5f527f45f16ffc24aa53ae181ea3c22a6fda07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 16 Oct 2022 20:51:29 +0200 Subject: [PATCH] Implement ELF file opening --- CMakeLists.txt | 2 + elfpatch.c | 75 +++++++++++++++++++++++++++++++++ include/patchelfcrc/elfpatch.h | 17 ++++++++ include/patchelfcrc/reporting.h | 10 +++++ main.c | 54 +++++++++++++++++------- reporting.c | 22 ++++++++++ 6 files changed, 165 insertions(+), 15 deletions(-) create mode 100644 elfpatch.c create mode 100644 include/patchelfcrc/elfpatch.h create mode 100644 include/patchelfcrc/reporting.h create mode 100644 reporting.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c6e9b4..137be0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ set (CFILES version.c named_crcs.c crc.c + elfpatch.c + reporting.c ) set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated") diff --git a/elfpatch.c b/elfpatch.c new file mode 100644 index 0000000..8447257 --- /dev/null +++ b/elfpatch.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include + +#define print_err(fmt, ...) fprintf(stderr, (fmt), ## __VA_ARGS__); + +int elf_patch_open(struct elfpatch *ep, const char *path) +{ + int fd; + Elf *elf; + + if (!ep || !path) + return -1000; + + memset(ep, 0, sizeof(struct elfpatch)); + + fd = open(path, O_RDWR, 0); + if (fd < 0) { + print_err("Error opening file: %s\n", path); + return -1; + } + elf = elf_begin(fd, ELF_C_RDWR, NULL); + if (!elf) { + close(fd); + print_err("[LIBELF] %s\n", elf_errmsg(-1)); + return -1; + } + + ep->fd = fd; + ep->elf = elf; + + return 0; +} + +void elf_patch_print_stats(const struct elfpatch *ep) +{ + Elf_Kind ek; + const char *type_string = "unrecognized"; + + if (!ep || !ep->elf) + return; + + ek = elf_kind(ep->elf); + + switch (ek) { + case ELF_K_AR: + type_string = "archive"; + break; + case ELF_K_ELF: + type_string = "elf object"; + break; + default: + /* Unrecognized is the default. Do nothing */ + break; + } + print_debug("ELF File Type: %s\n", type_string); +} + +void elf_patch_close(struct elfpatch *ep) +{ + if (!ep) + return; + if (ep->elf) + elf_end(ep->elf); + + if (ep->fd > 0) + close(ep->fd); + + ep->elf = NULL; + ep->fd = 0; +} diff --git a/include/patchelfcrc/elfpatch.h b/include/patchelfcrc/elfpatch.h new file mode 100644 index 0000000..101511d --- /dev/null +++ b/include/patchelfcrc/elfpatch.h @@ -0,0 +1,17 @@ +#ifndef _ELFPATCH_H_ +#define _ELFPATCH_H_ + +#include + +struct elfpatch { + int fd; + Elf *elf; +}; + +int elf_patch_open(struct elfpatch *ep, const char *path); + +void elf_patch_print_stats(const struct elfpatch *ep); + +void elf_patch_close(struct elfpatch *ep); + +#endif /* _ELFPATCH_H_ */ diff --git a/include/patchelfcrc/reporting.h b/include/patchelfcrc/reporting.h new file mode 100644 index 0000000..d32ac58 --- /dev/null +++ b/include/patchelfcrc/reporting.h @@ -0,0 +1,10 @@ +#ifndef _REPORTING_H_ +#define _REPORTING_H_ + +#define print_err(fmt, ...) fprintf(stderr, (fmt), ## __VA_ARGS__); + +void print_debug(const char *fmt, ...); + +void reporting_enable_verbose(void); + +#endif /* _REPORTING_H_ */ diff --git a/main.c b/main.c index 0f03360..92904e3 100644 --- a/main.c +++ b/main.c @@ -25,13 +25,8 @@ #include #include #include - -#define print_err(fmt, ...) fprintf(stderr, (fmt), ## __VA_ARGS__); -#define print_debug(fmt, ...) do { \ - if (verbose) { \ - printf("[DBG] "fmt, ## __VA_ARGS__); \ - } \ - } while (0) +#include +#include const char *argp_program_bug_address = ""; @@ -64,6 +59,7 @@ struct command_line_options { uint32_t end_magic; bool list; SlList *section_list; + const char *elf_path; }; static error_t parse_opt(int key, char *arg, struct argp_state *state) @@ -117,6 +113,12 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) else if (!strcmp(arg, "word")) args->granularity = GRANULARITY_32BIT; break; + case ARGP_KEY_ARG: + if (state->arg_num >= 1) + argp_usage(state); + else + args->elf_path = arg; + break; default: return ARGP_ERR_UNKNOWN; } @@ -155,7 +157,7 @@ static int parse_cmdline_options(int *argc, char ***argv, struct command_line_op static struct argp arg_parser = { options, parse_opt, - NULL, + "ELF", NULL, 0, 0, 0 }; @@ -180,11 +182,11 @@ static void prepare_default_opts(struct command_line_options *opts) opts->has_start_magic = false; opts->list = false; opts->section_list = NULL; + opts->elf_path = NULL; } static void print_verbose_start_info(const struct command_line_options *cmd_opts) { - bool verbose = cmd_opts->verbose; int i; SlList *list_iter; const struct named_crc *predef_crc; @@ -209,6 +211,10 @@ static void print_verbose_start_info(const struct command_line_options *cmd_opts print_debug("CRC length: %d\n", crc_len_from_poly(cmd_opts->crc.polynomial)); } + if (cmd_opts->elf_path) { + print_debug("ELF file: %s\n", cmd_opts->elf_path); + } + if (cmd_opts->section_list) { for (list_iter = cmd_opts->section_list, i = 1; list_iter; list_iter = sl_list_next(list_iter), i++) { print_debug("Input section [%d]: \"%s\"\n", i, (const char *)list_iter->data); @@ -234,28 +240,46 @@ static void free_cmd_args(struct command_line_options *opts) int main(int argc, char **argv) { - bool verbose; struct crc_calc crc; struct command_line_options cmd_opts; + struct elfpatch ep; prepare_default_opts(&cmd_opts); parse_cmdline_options(&argc, &argv, &cmd_opts); - verbose = cmd_opts.verbose || cmd_opts.dry_run; + if (cmd_opts.verbose || cmd_opts.dry_run) + reporting_enable_verbose(); print_verbose_start_info(&cmd_opts); + /* Check if file has been supplied */ + if (!cmd_opts.elf_path) { + print_err("No ELF file specified. Exiting...\n"); + return -1; + } + if (cmd_opts.list) { list_predefined_crcs(); goto free_cmds; } + /* Do error printing if using a reversed polynomial. It is not implemented yet! */ + if (cmd_opts.crc.rev) { + print_err("Reversed polynomials are not supported yet\nExiting...\n"); + goto free_cmds; + } + /* Build the CRC */ crc_init(&crc, &cmd_opts.crc); - /* Perform the check test */ - crc_push_bytes(&crc, "123456789", 9u); - crc_finish_calc(&crc); - printf("CRC Check value: 0x%08x\n", crc_get_value(&crc)); + /* Prepare libelf for use with the latest ELF version */ + elf_version(EV_CURRENT); + + /* Open the ELF file */ + elf_patch_open(&ep, cmd_opts.elf_path); + + elf_patch_print_stats(&ep); + + elf_patch_close(&ep); crc_destroy(&crc); free_cmds: diff --git a/reporting.c b/reporting.c new file mode 100644 index 0000000..14fe2ad --- /dev/null +++ b/reporting.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +static bool global_verbosity_state = false; + +void print_debug(const char *fmt, ...) +{ + va_list va; + + if (global_verbosity_state) { + va_start(va, fmt); + (void)vprintf(fmt, va); + va_end(va); + } +} + +void reporting_enable_verbose(void) +{ + global_verbosity_state = true; +}