Compare commits

...

9 Commits

8 changed files with 143 additions and 30 deletions

2
3rdparty/libfort vendored

@ -1 +1 @@
Subproject commit 41237162a9bd34a30a88069ee4e230584ae8d674 Subproject commit 5a8f9312bdbe05be484d2c07dd8c94a39e0ae196

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5...3.18)
project(patchelfcrc LANGUAGES C) project(patchelfcrc LANGUAGES C)

View File

@ -21,14 +21,25 @@
#include <stdbool.h> #include <stdbool.h>
#define print_err(fmt, ...) fprintf(stderr, "[ERR] " fmt, ## __VA_ARGS__) /**
* @brief Setting for reporting to console.
*/
enum reporting_color_mode {
COLOR_MODE_DETECT, /**< @brief Automatically detect if tty. If tty, color is used */
COLOR_MODE_COLOR, /**< @brief Force color mode on stderr */
COLOR_MODE_COLOR_OFF, /**< @brief Force no color on stderr */
};
#define print_warn(fmt, ...) fprintf(stderr, "[WARN] " fmt, ## __VA_ARGS__) void print_err(const char *fmt, ...);
void print_warn(const char *fmt, ...);
void print_debug(const char *fmt, ...); void print_debug(const char *fmt, ...);
void reporting_enable_verbose(void); void reporting_enable_verbose(bool state);
bool reporting_get_verbosity(void); bool reporting_get_verbosity(void);
void reporting_init(enum reporting_color_mode mode);
#endif /* _REPORTING_H_ */ #endif /* _REPORTING_H_ */

@ -1 +1 @@
Subproject commit c20b5c2528a46fe6a4aa74631ae3b628f73ac24f Subproject commit fdd99bad488bfd60cff152c0ec17bc927ed2e232

View File

@ -61,7 +61,7 @@
: Export the calculated files to an XML file *XMLFILE*. : Export the calculated files to an XML file *XMLFILE*.
**--import**=*XMLFILE* **--import**=*XMLFILE*
: Import the CRCs from an XML file *XMLFILE* and do not caclulate anything in the given *ELF* : Import the CRCs from an XML file *XMLFILE* and do not calculate anything in the given *ELF*
**--help**, **-h**, **-?** **--help**, **-h**, **-?**
: Print help. : Print help.
@ -84,6 +84,9 @@
**--usage** **--usage**
: Print usage hints on command line options. : Print usage hints on command line options.
**--no-color**
: Force output on stdout and stderr to be pure text without color codes.
# EXAMPLES # EXAMPLES
**patchelfcrc** --list-crcs **patchelfcrc** --list-crcs
@ -131,8 +134,8 @@
**patchelfcrc** -l -g word --start-magic=0x12345678 --end-magic=0x8754321 -p crc-32-mpeg -f bare -O .outputsection -S .text executable.elf **patchelfcrc** -l -g word --start-magic=0x12345678 --end-magic=0x8754321 -p crc-32-mpeg -f bare -O .outputsection -S .text executable.elf
: Calculate the CRC over *.text* section and place the result in the *.outputsection* section. : Calculate the CRC over *.text* section and place the result in the *.outputsection* section.
The output sections start and end are checked for the given magic numbers in order to assure correct memory layout. The output sections start and end are checked for the given magic numbers in order to ensure correct memory layout.
*CRC-32-MPEG* is used as CRC algorothm. *CRC-32-MPEG* is used as CRC algorithm.
The memory is interpreted as *little endian* and the CRC calculation granularity is a 32 bit *word*. The memory is interpreted as *little endian* and the CRC calculation granularity is a 32 bit *word*.
# BUGS # BUGS

View File

@ -470,12 +470,12 @@ elfpatch_handle_t *elf_patch_open(const char *path, bool readonly, bool expect_l
case 1: case 1:
print_debug("ELF Endianess: little\n"); print_debug("ELF Endianess: little\n");
if (!expect_little_endian) if (!expect_little_endian)
print_err("Big endian format expected. File is little endian. Double check settings!\n"); print_warn("Big endian format expected. File is little endian. Double check settings!\n");
break; break;
case 2: case 2:
print_debug("ELF Endianess: big\n"); print_debug("ELF Endianess: big\n");
if (expect_little_endian) if (expect_little_endian)
print_err("Little endian format expected. File is big endian. Double check settings!\n"); print_warn("Little endian format expected. File is big endian. Double check settings!\n");
break; break;
default: default:
print_err("Cannot determine endianess of ELF file. EI_DATA is: %d\n", ident[5]); print_err("Cannot determine endianess of ELF file. EI_DATA is: %d\n", ident[5]);
@ -561,25 +561,24 @@ int elf_patch_compute_crc_over_section(elfpatch_handle_t *ep, const char *sectio
/* Find section */ /* Find section */
sec = find_section_in_list(ep->sections, section); sec = find_section_in_list(ep->sections, section);
if (!sec) { if (!sec) {
print_err("Cannot find section %s\n", section); print_err("Cannot find section '%s'\n", section);
return -1; return -1;
} }
data = elf_getdata(sec->scn, NULL); data = elf_getdata(sec->scn, NULL);
if (!data) { if (!data) {
print_err("Error reading section data from %s: %s\n", section, elf_errmsg(-1)); print_err("Error reading section data from '%s': %s\n", section, elf_errmsg(-1));
return -1; return -1;
} }
print_debug("Section data length: %lu\n", data->d_size);
if (!data->d_size) { if (!data->d_size) {
print_err("Section %s contains no data.\n", section); print_err("Section '%s' contains no data.\n", section);
return -2; return -2;
} }
/* NOBIT sections have a length but no data in the file. Abort in this case */ /* NOBIT sections have a length but no data in the file. Abort in this case */
if (!data->d_buf) { if (!data->d_buf) {
print_err("Section %s does not contain loadable data.\n", section); print_err("Section '%s' does not contain loadable data.\n", section);
return -2; return -2;
} }
@ -593,7 +592,7 @@ int elf_patch_compute_crc_over_section(elfpatch_handle_t *ep, const char *sectio
/* Check granularity vs size of section */ /* Check granularity vs size of section */
padding_count = (gran_in_bytes - data->d_size % gran_in_bytes) % gran_in_bytes; padding_count = (gran_in_bytes - data->d_size % gran_in_bytes) % gran_in_bytes;
if (padding_count) { if (padding_count) {
print_err("Section '%s' is not a multiple size of the given granularity. %u zero padding bytes will be added.\n", print_warn("Section '%s' is not a multiple size of the given granularity. %u zero padding bytes will be added.\n",
section, padding_count); section, padding_count);
} }
@ -633,7 +632,7 @@ static size_t calculate_needed_space_for_crcs(enum crc_format format,
break; break;
default: default:
needed_space = 0; needed_space = 0;
print_err("Unsupported CRC output format\n"); print_err("Unsupported CRC output format.\n");
} }
/* Add existing magic numbers to required space */ /* Add existing magic numbers to required space */
if (check_start_magic) { if (check_start_magic) {

View File

@ -40,8 +40,10 @@ const char *argp_program_bug_address = "<mario [dot] huettel [at] linux [dot] co
#define ARG_KEY_IMPORT (6) #define ARG_KEY_IMPORT (6)
#define ARG_KEY_USE_VMA (7) #define ARG_KEY_USE_VMA (7)
#define ARG_KEY_XSD (8) #define ARG_KEY_XSD (8)
#define ARG_KEY_FORCE_NO_COLOR (9)
struct command_line_options { struct command_line_options {
bool force_nocolor;
bool little_endian; bool little_endian;
bool dry_run; bool dry_run;
bool verbose; bool verbose;
@ -104,6 +106,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case ARG_KEY_USE_VMA: case ARG_KEY_USE_VMA:
args->use_vma = true; args->use_vma = true;
break; break;
case ARG_KEY_FORCE_NO_COLOR:
args->force_nocolor = true;
break;
case 'p': case 'p':
/* Polyniomial */ /* Polyniomial */
args->crc.polynomial = strtoull(arg, &endptr, 0); args->crc.polynomial = strtoull(arg, &endptr, 0);
@ -195,6 +200,7 @@ static int parse_cmdline_options(int *argc, char ***argv, struct command_line_op
{"import", ARG_KEY_IMPORT, "XML", 0, "Do not caclulate CRCs but import them from file", 3}, {"import", ARG_KEY_IMPORT, "XML", 0, "Do not caclulate CRCs but import them from file", 3},
{"xsd", ARG_KEY_XSD, 0, 0, "Print XSD to stdout", 0}, {"xsd", ARG_KEY_XSD, 0, 0, "Print XSD to stdout", 0},
{"use-vma", ARG_KEY_USE_VMA, 0, 0, "Use the VMA instead of the LMA for struct output", 2}, {"use-vma", ARG_KEY_USE_VMA, 0, 0, "Use the VMA instead of the LMA for struct output", 2},
{"no-color", ARG_KEY_FORCE_NO_COLOR, 0, 0, "Force the output to be text only without colors", 0},
/* Sentinel */ /* Sentinel */
{NULL, 0, 0, 0, NULL, 0} {NULL, 0, 0, 0, NULL, 0}
}; };
@ -233,12 +239,11 @@ static void prepare_default_opts(struct command_line_options *opts)
opts->output_section = NULL; opts->output_section = NULL;
opts->export_xml = NULL; opts->export_xml = NULL;
opts->import_xml = NULL; opts->import_xml = NULL;
opts->force_nocolor = false;
} }
static void print_verbose_start_info(const struct command_line_options *cmd_opts) static void print_verbose_start_info(const struct command_line_options *cmd_opts)
{ {
int i;
SlList *list_iter;
const struct named_crc *predef_crc; const struct named_crc *predef_crc;
print_debug("Start CRC patching\n"); print_debug("Start CRC patching\n");
@ -272,11 +277,6 @@ static void print_verbose_start_info(const struct command_line_options *cmd_opts
if (cmd_opts->import_xml) if (cmd_opts->import_xml)
print_debug("Import CRCs from '%s'\n", cmd_opts->import_xml); print_debug("Import CRCs from '%s'\n", cmd_opts->import_xml);
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);
}
} }
static void free_cmd_args(struct command_line_options *opts) static void free_cmd_args(struct command_line_options *opts)
@ -425,8 +425,11 @@ int main(int argc, char **argv)
goto free_cmds; goto free_cmds;
} }
/* Initialize console output */
reporting_init(cmd_opts.force_nocolor ? COLOR_MODE_COLOR_OFF : COLOR_MODE_DETECT);
if (cmd_opts.verbose || cmd_opts.dry_run) if (cmd_opts.verbose || cmd_opts.dry_run)
reporting_enable_verbose(); reporting_enable_verbose(true);
print_verbose_start_info(&cmd_opts); print_verbose_start_info(&cmd_opts);
@ -450,7 +453,7 @@ int main(int argc, char **argv)
print_warn("--use-vma option only has an effect when exporting as struct output.\n"); print_warn("--use-vma option only has an effect when exporting as struct output.\n");
if (!cmd_opts.output_section && cmd_opts.export_xml == NULL) if (!cmd_opts.output_section && cmd_opts.export_xml == NULL)
print_err("No output section / XML export specified. Will continue but not create any output\n"); print_warn("No output section or XML export specified. Will continue but not create any output.\n");
/* Prepare libelf for use with the latest ELF version */ /* Prepare libelf for use with the latest ELF version */
elf_version(EV_CURRENT); elf_version(EV_CURRENT);
@ -492,7 +495,7 @@ int main(int argc, char **argv)
if (cmd_opts.export_xml) { if (cmd_opts.export_xml) {
if (xml_write_crcs_to_file(cmd_opts.export_xml, crc_data)) { if (xml_write_crcs_to_file(cmd_opts.export_xml, crc_data)) {
print_err("Error during XML generation\n"); print_err("Error during XML generation.\n");
ret = -3; ret = -3;
} }
} }

View File

@ -19,9 +19,66 @@
#include <patchelfcrc/reporting.h> #include <patchelfcrc/reporting.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <unistd.h>
static bool global_verbosity_state = false; static bool global_verbosity_state = false;
static bool reporting_use_color = false;
#define COLOR_RESET "\e[0m"
#define COLOR_BOLD_RED "\e[31;1m"
#define COLOR_RED "\e[31m"
#define COLOR_BOLD_YELLOW "\e[33;1m"
#define COLOR_YELLOW "\e[33m"
void print_err(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
/* Set color */
if (reporting_use_color)
fprintf(stderr, COLOR_BOLD_RED "[ERR]" COLOR_RESET " " COLOR_RED);
else
fprintf(stderr, "[ERR] ");
vfprintf(stderr, fmt, va);
/* Reset color */
if (reporting_use_color) {
fprintf(stderr, COLOR_RESET);
}
va_end(va);
}
void print_warn(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
/* Set color */
if (reporting_use_color)
fprintf(stderr, COLOR_BOLD_YELLOW "[WARN]" COLOR_RESET " " COLOR_YELLOW);
else
fprintf(stderr, "[WARN] ");
vfprintf(stderr, fmt, va);
/* Reset color */
if (reporting_use_color) {
fprintf(stderr, COLOR_RESET);
}
va_end(va);
}
void print_debug(const char *fmt, ...) void print_debug(const char *fmt, ...)
{ {
@ -34,12 +91,52 @@ void print_debug(const char *fmt, ...)
} }
} }
void reporting_enable_verbose(void) void reporting_enable_verbose(bool state)
{ {
global_verbosity_state = true; global_verbosity_state = state;
} }
bool reporting_get_verbosity(void) bool reporting_get_verbosity(void)
{ {
return global_verbosity_state; return global_verbosity_state;
} }
/**
* @brief Check whether stderr supports colors.
* @note This function checks for a tty and the TERM environment variable. It has to contain "xterm".
* @return true if colors are supported
* @return false if no colors should be used
*/
static bool stderr_supports_colors(void)
{
const char *env_var;
const char *tmp;
if (isatty(2) != 1)
return false;
env_var = getenv("TERM");
if (!env_var)
return false;
tmp = strstr(env_var, "xterm");
if (!tmp)
return false;
return true;
}
void reporting_init(enum reporting_color_mode mode)
{
switch (mode) {
case COLOR_MODE_COLOR:
reporting_use_color = true;
break;
case COLOR_MODE_COLOR_OFF:
reporting_use_color = false;
break;
default: /* Auto detect case and invalid settings */
reporting_use_color = stderr_supports_colors();
break;
}
}