diff --git a/elfpatch.c b/elfpatch.c index 6936857..837f92d 100644 --- a/elfpatch.c +++ b/elfpatch.c @@ -20,6 +20,7 @@ struct elf_section { struct elfpatch { uint32_t magic; int fd; + bool readonly; Elf *elf; GElf_Ehdr ehdr; int class; @@ -218,7 +219,7 @@ static int elf_patch_update_info(elfpatch_handle_t *ep) return 0; } -elfpatch_handle_t *elf_patch_open(const char *path) +elfpatch_handle_t *elf_patch_open(const char *path, bool readonly) { struct elfpatch *ep; @@ -229,13 +230,14 @@ elfpatch_handle_t *elf_patch_open(const char *path) ep = (struct elfpatch *)calloc(1u, sizeof(struct elfpatch)); ep->magic = ELFPATCH_MAGIC; + ep->readonly = readonly; - ep->fd = open(path, O_RDWR, 0); + ep->fd = open(path, readonly ? O_RDONLY : O_RDWR, 0); if (ep->fd < 0) { print_err("Error opening file: %s\n", path); goto free_struct; } - ep->elf = elf_begin(ep->fd, ELF_C_RDWR, NULL); + ep->elf = elf_begin(ep->fd, readonly ? ELF_C_READ : ELF_C_RDWR, NULL); if (!ep->elf) { print_err("[LIBELF] %s\n", elf_errmsg(-1)); goto close_fd; diff --git a/include/patchelfcrc/elfpatch.h b/include/patchelfcrc/elfpatch.h index 1b16b0c..3101bdf 100644 --- a/include/patchelfcrc/elfpatch.h +++ b/include/patchelfcrc/elfpatch.h @@ -14,7 +14,7 @@ enum granularity { }; -elfpatch_handle_t *elf_patch_open(const char *path); +elfpatch_handle_t *elf_patch_open(const char *path, bool readonly); /** * @brief Check if a section is present in file diff --git a/main.c b/main.c index 96455c6..471b574 100644 --- a/main.c +++ b/main.c @@ -27,6 +27,7 @@ #include #include #include +#include const char *argp_program_bug_address = ""; @@ -232,11 +233,101 @@ static void free_cmd_args(struct command_line_options *opts) opts->section_list = NULL; } +/** + * @brief check_all_sections_present + * @param ep + * @param list + * @return -1 if no sections are provided. 0 if all sections are present. -2 if setions cannot be found + */ +static int check_all_sections_present(elfpatch_handle_t *ep, SlList *list) +{ + SlList *iter; + const char *sec_name; + int ret = 0; + + if (!ep) + return -1001; + if (!list) { + print_err("No input sections specified.\n") + return -1; + } + for (iter = list; iter; iter = sl_list_next(iter)) { + sec_name = (const char *)iter->data; + if (!sec_name) + continue; + if (elf_patch_check_for_section(ep, sec_name)) { + print_err("Cannot find section '%s'\n", sec_name); + ret = -2; + } else { + print_debug("Input section '%s': found\n", sec_name); + } + } + + return ret; +} + +/** + * @brief Compute CRCs over the sections in @p list + * @param ep Elf patch + * @param list List of section names to patch + * @param opts Command line options. Used for CRC generation + * @param[out] crcs Array of output CRCs. Must be large enough to hold all elements + * @return 0 if successful + */ +static int compute_crcs(elfpatch_handle_t *ep, SlList *list, const struct command_line_options *opts, uint32_t *crcs) +{ + SlList *iter; + const char *sec_name; + int ret = 0; + struct crc_calc _crc; + struct crc_calc * const crc = &_crc; + unsigned int idx; + + /* Construct the CRC */ + crc_init(crc, &opts->crc); + + for (iter = list, idx = 0; iter; iter = sl_list_next(iter), idx++) { + crc_reset(crc); + sec_name = (const char *)iter->data; + if (elf_patch_compute_crc_over_section(ep, sec_name, crc, opts->granularity, opts->little_endian)) { + print_err("Error during CRC calculation. Exiting.\n"); + ret = -1; + break; + } + crc_finish_calc(crc); + crcs[idx] = crc_get_value(crc); + } + + return ret; +} + +static void print_crcs(SlList *list, const uint32_t *crcs) +{ + SlList *iter; + unsigned int idx; + const char *sec_name; + ft_table_t *table; + + table = ft_create_table(); + + /* Write header */ + ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER); + ft_write_ln(table, "Section", "CRC"); + + for (iter = list, idx = 0; iter; iter = sl_list_next(iter), idx++) { + sec_name = (const char *)iter->data; + ft_printf_ln(table, "%s|0x%x", sec_name, crcs[idx]); + } + print_debug("Calculated CRCs:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); +} + int main(int argc, char **argv) { - struct crc_calc crc; struct command_line_options cmd_opts; elfpatch_handle_t *ep; + int ret = 0; + uint32_t *crcs; prepare_default_opts(&cmd_opts); parse_cmdline_options(&argc, &argv, &cmd_opts); @@ -262,26 +353,35 @@ int main(int argc, char **argv) goto free_cmds; } - /* Build the CRC */ - crc_init(&crc, &cmd_opts.crc); - /* Prepare libelf for use with the latest ELF version */ elf_version(EV_CURRENT); /* Open the ELF file */ - ep = elf_patch_open(cmd_opts.elf_path); + ep = elf_patch_open(cmd_opts.elf_path, cmd_opts.dry_run); + if (!ep) { + ret = -2; + goto free_cmds; + } - /* TODO: Implement this correctly! */ - elf_patch_compute_crc_over_section(ep, ".text", &crc, cmd_opts.granularity, cmd_opts.little_endian); + /* Check if all sections are present */ + if (check_all_sections_present(ep, cmd_opts.section_list)) { + ret = -2; + goto free_cmds; + } + + /* Compute CRCs over sections */ + crcs = (uint32_t *)malloc(sl_list_length(cmd_opts.section_list) * sizeof(uint32_t)); + compute_crcs(ep, cmd_opts.section_list, &cmd_opts, crcs); + + if (reporting_get_verbosity()) { + print_crcs(cmd_opts.section_list, crcs); + } elf_patch_close_and_free(ep); - printf("CRC is: 0x%08x\n", crc_get_value(&crc)); - - crc_destroy(&crc); free_cmds: free_cmd_args(&cmd_opts); - return 0; + return ret; }