From badfb6c462599e0e4db450048c5c6b17e9192a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Sun, 25 Sep 2016 22:51:10 +0200 Subject: [PATCH 01/23] Harden check for file size value. The st_size member of struct stat is of signed type off_t, so check for negative values in addition to zero. Also explicitly cast the value when assigning to a size_t variable. --- src/image_raw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/image_raw.c b/src/image_raw.c index b5f4537..5eb75d5 100644 --- a/src/image_raw.c +++ b/src/image_raw.c @@ -174,13 +174,13 @@ image_raw_merge_file(const char *filename, return -2; } - if (st.st_size == 0) { + if (st.st_size <= 0) { fprintf(stderr, _("Image file \"%s\" is empty\n"), filename); } else { if (blob_size > (size_t) st.st_size) { fprintf(stderr, _("Image file \"%s\" is too small, %zu of %zu bytes missing\n"), filename, blob_size - (size_t) st.st_size, blob_size); - blob_size = st.st_size; + blob_size = (size_t) st.st_size; } #if HAVE_MMAP From 5c1ae7aa25d09b0ae969324576ff15d03e4d5d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Sun, 25 Sep 2016 21:54:53 +0200 Subject: [PATCH 02/23] Correct error message for failed allocation. Distinguish between failure to allocate memory and errors in ihex_byte_copy() and use a separate error message. --- src/image_ihex_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index 1a99977..ed84ff2 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -96,8 +96,8 @@ image_ihex_merge_file(const char *filename, // Allocate and initialize memory for needed ihex content blob = calloc(1, blob_size); if (! blob) { - fprintf(stderr, _("Could not copy data from Intel Hex file \"%s\" (%s)\n"), - filename, strerror(errno)); + fprintf(stderr, _("Could not allocate memory for image data: %s\n"), + strerror(errno)); symbols = -3; } else { if (0 != ihex_byte_copy(rs, (void*) blob, blob_size, 0)) { From f8b5fc75e4a2d4011328d59af873bfb0afa6ea9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Sun, 25 Sep 2016 19:53:48 +0200 Subject: [PATCH 03/23] Minor formatting corrections. --- src/image_formats.h | 6 +++--- src/image_ihex.h | 4 ++-- src/image_ihex_input.c | 3 ++- src/image_raw.h | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/image_formats.h b/src/image_formats.h index 082a002..e96b33b 100644 --- a/src/image_formats.h +++ b/src/image_formats.h @@ -1,6 +1,6 @@ ///@file ///@brief Handling of different binary image formats -///@copyright Copyright (C) 2014 Andre Colomb +///@copyright Copyright (C) 2014, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -47,7 +47,7 @@ int image_merge_file( int list_size, ///< [in] Number of symbols in list size_t blob_size, ///< [in] Expected data size in the image enum image_format format ///< [in] Expected input format - ); +); ///@brief Write blob data to raw binary image file void image_write_file( @@ -55,6 +55,6 @@ void image_write_file( const char* blob, ///< [in] Binary data to write size_t blob_size, ///< [in] Data size in bytes enum image_format format ///< [in] Desired output format - ); +); #endif //IMAGE_FORMATS_H_ diff --git a/src/image_ihex.h b/src/image_ihex.h index 3785438..a6e218d 100644 --- a/src/image_ihex.h +++ b/src/image_ihex.h @@ -1,6 +1,6 @@ ///@file ///@brief Handle input and output of blob data to Intel Hex files -///@copyright Copyright (C) 2014 Andre Colomb +///@copyright Copyright (C) 2014, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -38,7 +38,7 @@ int image_ihex_merge_file( const nvm_symbol *list, ///< [in] Symbol list start address int list_size, ///< [in] Number of symbols in list size_t blob_size ///< [in] Expected data size in the image - ); +); ///@brief Write blob data to Intel Hex image file void image_ihex_write_file( diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index ed84ff2..522a054 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -1,6 +1,6 @@ ///@file ///@brief Handle input of blob data from Intel Hex files -///@copyright Copyright (C) 2014, 2015 Andre Colomb +///@copyright Copyright (C) 2014, 2015, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -111,5 +111,6 @@ image_ihex_merge_file(const char *filename, } } ihex_rs_free(rs); + return symbols; } diff --git a/src/image_raw.h b/src/image_raw.h index b756600..8070eee 100644 --- a/src/image_raw.h +++ b/src/image_raw.h @@ -1,6 +1,6 @@ ///@file ///@brief Handle input and output of blob data to raw binary files -///@copyright Copyright (C) 2014 Andre Colomb +///@copyright Copyright (C) 2014, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -38,7 +38,7 @@ int image_raw_merge_mem( const nvm_symbol *list, ///< [in] Symbol list start address int list_size, ///< [in] Number of symbols in list size_t blob_size ///< [in] Data size in the memory image - ); +); ///@brief Update each listed symbol's content from open binary file ///@return Number of symbols successfully read or negative error code @@ -47,7 +47,7 @@ int image_raw_merge_filedes( const nvm_symbol *list, ///< [in] Symbol list start address int list_size, ///< [in] Number of symbols in list size_t blob_size ///< [in] Data size in the memory image - ); +); ///@brief Open raw binary image file and update each listed symbol's content ///@return Number of symbols successfully read or negative error code @@ -56,7 +56,7 @@ int image_raw_merge_file( const nvm_symbol *list, ///< [in] Symbol list start address int list_size, ///< [in] Number of symbols in list size_t blob_size ///< [in] Expected data size in the image - ); +); ///@brief Write blob data to raw binary image file void image_raw_write_file( From 5e3225b0046c9b6dee9e9683c1baec27cbe360fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Sun, 25 Sep 2016 20:30:40 +0200 Subject: [PATCH 04/23] Factor out functions to open binary image files. Introduce image_*_open_file() with modified code from the image_*_merge_file() functions. --- src/image_ihex_input.c | 61 ++++++++++++++++++++++++++++++++++++++++++ src/image_raw.c | 35 +++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index 522a054..54112dc 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -38,6 +38,67 @@ +///@brief Open Intel Hex file and determine content size +///@return 1 on success, 0 for unsupported format or negative error code +static int +image_ihex_open_file( + const char *filename, ///< [in] Input file path to open + size_t *file_size, ///< [out] Data address at end of content + ihex_recordset_t **rs) ///< [out] File access handle (open on success) +{ + uint32_t start, end; + int status = 0; + + if (! filename || ! rs) return -1; //invalid parameters + + *rs = ihex_rs_from_file(filename); + if (! *rs) { + switch (ihex_errno()) { + case IHEX_ERR_INCORRECT_CHECKSUM: + case IHEX_ERR_NO_EOF: + case IHEX_ERR_PARSE_ERROR: + case IHEX_ERR_WRONG_RECORD_LENGTH: + case IHEX_ERR_UNKNOWN_RECORD_TYPE: + // Parse error, not a well-formed Intel Hex file + return 0; + + case IHEX_ERR_NO_INPUT: + case IHEX_ERR_MMAP_FAILED: + case IHEX_ERR_READ_FAILED: + // File not accessible + status = -2; + break; + + case IHEX_ERR_MALLOC_FAILED: + default: + // System error + status = -3; + break; + } + fprintf(stderr, _("Cannot open image \"%s\" (%s)\n"), filename, ihex_error()); + return status; + } + + if (0 != ihex_rs_get_address_range(*rs, &start, &end)) { + fprintf(stderr, _("Could not determine data range in Intel Hex file \"%s\" (%s)\n"), + filename, ihex_error()); + status = -4; + } else if ((*rs)->ihrs_count == 0 || start >= end) { + fprintf(stderr, _("Image file \"%s\" is empty\n"), filename); + status = -4; + } else { + if (DEBUG) printf(_("%s: %s contains range 0x%04" PRIx32 " to 0x%04" PRIx32 "\n"), + __func__, filename, start, end > 0 ? end - 1 : 0); + if (file_size) *file_size = end; + return 1; + } + ihex_rs_free(*rs); + + return status; +} + + + int image_ihex_merge_file(const char *filename, const nvm_symbol *list, int list_size, diff --git a/src/image_raw.c b/src/image_raw.c index 5eb75d5..3e1ca4b 100644 --- a/src/image_raw.c +++ b/src/image_raw.c @@ -1,6 +1,6 @@ ///@file ///@brief Handle input and output of blob data to raw binary files -///@copyright Copyright (C) 2014, 2015 Andre Colomb +///@copyright Copyright (C) 2014, 2015, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -157,6 +157,39 @@ image_raw_merge_filedes(int fd, +///@brief Open file in raw binary format and determine content size +///@return 1 on success or negative error code +static int +image_raw_open_file( + const char *filename, ///< [in] Input file path to open + size_t *file_size, ///< [out] Data address at end of content + int *fd) ///< [out] File access handle (open on success) +{ + int status = 0; + struct stat st; + + if (! filename || ! fd) return -1; //invalid parameters + + *fd = open(filename, O_RDONLY | O_BINARY); + if (*fd == -1 || 0 != fstat(*fd, &st)) { //file not accessible + fprintf(stderr, _("Cannot open image \"%s\" (%s)\n"), filename, strerror(errno)); + return -2; + } + + if (st.st_size <= 0) { + fprintf(stderr, _("Image file \"%s\" is empty\n"), filename); + status = -4; + } else { + if (file_size) *file_size = (size_t) st.st_size; + return 1; + } + close(*fd); + + return status; +} + + + int image_raw_merge_file(const char *filename, const nvm_symbol list[], int list_size, From 0a931c5624489486579b602d34fbd0cfda221d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 11:17:38 +0200 Subject: [PATCH 05/23] Use new file open functions in image merging functions. Switch to using the factored out code in image_ihex_merge_file() and image_raw_merge_file(). --- src/image_ihex_input.c | 73 +++++++++++------------------------------- src/image_raw.c | 43 +++++++++++-------------- 2 files changed, 37 insertions(+), 79 deletions(-) diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index 54112dc..a63a42b 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -105,71 +105,36 @@ image_ihex_merge_file(const char *filename, size_t blob_size) { ihex_recordset_t *rs; - uint32_t start, end; char *blob; int symbols = 0; + size_t file_size = 0; if (! filename || ! blob_size) return -1; //invalid parameters - rs = ihex_rs_from_file(filename); - if (! rs) { - switch (ihex_errno()) { - case IHEX_ERR_INCORRECT_CHECKSUM: - case IHEX_ERR_NO_EOF: - case IHEX_ERR_PARSE_ERROR: - case IHEX_ERR_WRONG_RECORD_LENGTH: - case IHEX_ERR_UNKNOWN_RECORD_TYPE: - // Parse error, not a well-formed Intel Hex file - return 0; - - case IHEX_ERR_NO_INPUT: - case IHEX_ERR_MMAP_FAILED: - case IHEX_ERR_READ_FAILED: - // File not accessible - symbols = -2; - break; + symbols = image_ihex_open_file(filename, &file_size, &rs); + if (symbols <= 0) return symbols; //file not accessible - case IHEX_ERR_MALLOC_FAILED: - default: - // System error - symbols = -3; - break; - } - fprintf(stderr, _("Cannot open image \"%s\" (%s)\n"), filename, ihex_error()); - return symbols; + if (blob_size > file_size) { + fprintf(stderr, _("Image file \"%s\" is too small, %zu of %zu bytes missing\n"), + filename, blob_size - file_size, blob_size); + blob_size = file_size; } - if (0 != ihex_rs_get_address_range(rs, &start, &end)) { - fprintf(stderr, _("Could not determine data range in Intel Hex file \"%s\" (%s)\n"), - filename, ihex_error()); - symbols = -4; - } else if (rs->ihrs_count == 0 || start >= end) { - fprintf(stderr, _("Image file \"%s\" is empty\n"), filename); + // Allocate and initialize memory for needed ihex content + blob = calloc(1, blob_size); + if (! blob) { + fprintf(stderr, _("Could not allocate memory for image data: %s\n"), + strerror(errno)); + symbols = -3; } else { - if (DEBUG) printf(_("%s: %s contains range 0x%04" PRIx32 " to 0x%04" PRIx32 "\n"), - __func__, filename, start, end > 0 ? end - 1 : 0); - if (blob_size > end) { - fprintf(stderr, _("Image file \"%s\" is too small, %zu of %zu bytes missing\n"), - filename, blob_size - end, blob_size); - blob_size = end; - } - - // Allocate and initialize memory for needed ihex content - blob = calloc(1, blob_size); - if (! blob) { - fprintf(stderr, _("Could not allocate memory for image data: %s\n"), - strerror(errno)); - symbols = -3; + if (0 != ihex_byte_copy(rs, (void*) blob, blob_size, 0)) { + fprintf(stderr, _("Could not copy data from Intel Hex file \"%s\" (%s)\n"), + filename, ihex_error()); + symbols = -4; } else { - if (0 != ihex_byte_copy(rs, (void*) blob, blob_size, 0)) { - fprintf(stderr, _("Could not copy data from Intel Hex file \"%s\" (%s)\n"), - filename, ihex_error()); - symbols = -4; - } else { - symbols = image_raw_merge_mem(blob, list, list_size, blob_size); - } - free(blob); + symbols = image_raw_merge_mem(blob, list, list_size, blob_size); } + free(blob); } ihex_rs_free(rs); diff --git a/src/image_raw.c b/src/image_raw.c index 3e1ca4b..2fb4600 100644 --- a/src/image_raw.c +++ b/src/image_raw.c @@ -197,40 +197,33 @@ image_raw_merge_file(const char *filename, { char *mapped = NULL; int fd, symbols = 0; - struct stat st; + size_t file_size = 0; if (! filename || ! blob_size) return -1; //invalid parameters - fd = open(filename, O_RDONLY | O_BINARY); - if (fd == -1 || 0 != fstat(fd, &st)) { //file not accessible - fprintf(stderr, _("Cannot open image \"%s\" (%s)\n"), filename, strerror(errno)); - return -2; - } + symbols = image_raw_open_file(filename, &file_size, &fd); + if (symbols <= 0) return symbols; //file not accessible - if (st.st_size <= 0) { - fprintf(stderr, _("Image file \"%s\" is empty\n"), filename); - } else { - if (blob_size > (size_t) st.st_size) { - fprintf(stderr, _("Image file \"%s\" is too small, %zu of %zu bytes missing\n"), - filename, blob_size - (size_t) st.st_size, blob_size); - blob_size = (size_t) st.st_size; - } + if (blob_size > file_size) { + fprintf(stderr, _("Image file \"%s\" is too small, %zu of %zu bytes missing\n"), + filename, blob_size - file_size, blob_size); + blob_size = file_size; + } #if HAVE_MMAP - mapped = mmap(NULL, blob_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (mapped == MAP_FAILED) { - mapped = NULL; - fprintf(stderr, _("%s: mmap() failed (%s)\n"), __func__, strerror(errno)); - } + mapped = mmap(NULL, blob_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) { + mapped = NULL; + fprintf(stderr, _("%s: mmap() failed (%s)\n"), __func__, strerror(errno)); + } #endif - if (mapped) { - symbols = image_raw_merge_mem(mapped, list, list_size, blob_size); + if (mapped) { + symbols = image_raw_merge_mem(mapped, list, list_size, blob_size); #if HAVE_MMAP - munmap(mapped, blob_size); + munmap(mapped, blob_size); #endif - } else { - symbols = image_raw_merge_filedes(fd, list, list_size, blob_size); - } + } else { + symbols = image_raw_merge_filedes(fd, list, list_size, blob_size); } close(fd); From f48a75a1609cef48d7a8aac4b0f5ff8715650bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 12:34:15 +0200 Subject: [PATCH 06/23] Implement functions to cache image file data in memory. Add image_ihex_memorize_file() and image_raw_memorize_file(), utilizing the common image_*_open_file() functions. The allocated blob address and size are returned in the referenced parameters. --- src/image_ihex.h | 8 ++++++++ src/image_ihex_input.c | 34 ++++++++++++++++++++++++++++++++++ src/image_raw.c | 39 +++++++++++++++++++++++++++++++++++++++ src/image_raw.h | 8 ++++++++ 4 files changed, 89 insertions(+) diff --git a/src/image_ihex.h b/src/image_ihex.h index a6e218d..12ac04f 100644 --- a/src/image_ihex.h +++ b/src/image_ihex.h @@ -31,6 +31,14 @@ typedef struct nvm_symbol nvm_symbol; +///@brief Open Intel Hex image file and store contents in memory +///@return 1 on success or negative error code +int image_ihex_memorize_file( + const char *filename, ///< [in] Input file path to open + const char **blob, ///< [out] Binary data content + size_t *blob_size ///< [out] Data address at end of content +); + ///@brief Open Intel Hex image file and update each listed symbol's content ///@return Number of symbols successfully read or negative error code int image_ihex_merge_file( diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index a63a42b..8b98871 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -99,6 +99,40 @@ image_ihex_open_file( +int +image_ihex_memorize_file(const char *filename, + const char **blob, size_t *blob_size) +{ + ihex_recordset_t *rs = NULL; + int status; + char *contents = NULL; + + if (! filename || ! blob || ! blob_size) return -1; //invalid parameters + + status = image_ihex_open_file(filename, blob_size, &rs); + if (status <= 0) return status; //file not accessible + + // Allocate and initialize memory for needed ihex content + contents = calloc(1, *blob_size); + if (! contents) { + fprintf(stderr, _("Could not allocate memory for image data: %s\n"), + strerror(errno)); + status = -3; + } else { + if (0 != ihex_byte_copy(rs, (void*) blob, *blob_size, 0)) { + fprintf(stderr, _("Could not copy data from Intel Hex file \"%s\" (%s)\n"), + filename, ihex_error()); + status = -4; + } + *blob = contents; + } + ihex_rs_free(rs); + + return status; +} + + + int image_ihex_merge_file(const char *filename, const nvm_symbol *list, int list_size, diff --git a/src/image_raw.c b/src/image_raw.c index 2fb4600..3b90d86 100644 --- a/src/image_raw.c +++ b/src/image_raw.c @@ -190,6 +190,45 @@ image_raw_open_file( +int +image_raw_memorize_file(const char *filename, + const char **blob, size_t *blob_size) +{ + int fd = -1, status; + char *contents = NULL; + ssize_t bytes_read = 0; + size_t rest; + + if (! filename || ! blob || ! blob_size) return -1; //invalid parameters + + status = image_raw_open_file(filename, blob_size, &fd); + if (status <= 0) return status; //file not accessible + + // Allocate and initialize memory for needed content + contents = calloc(1, *blob_size); + if (! contents) { + fprintf(stderr, _("Could not allocate memory for image data: %s\n"), + strerror(errno)); + status = -3; + } else { + for (rest = *blob_size; rest > 0; rest -= bytes_read) { + bytes_read = read(fd, contents + (*blob_size - rest), rest); + if (bytes_read <= 0) { + fprintf(stderr, _("Failed to read %zu bytes from file \"%s\"" + " at offset %zu (%s)\n"), + rest, filename, *blob_size - rest, strerror(errno)); + break; //error or end of file + } + } + *blob = contents; + } + close(fd); + + return status; +} + + + int image_raw_merge_file(const char *filename, const nvm_symbol list[], int list_size, diff --git a/src/image_raw.h b/src/image_raw.h index 8070eee..83c2c03 100644 --- a/src/image_raw.h +++ b/src/image_raw.h @@ -31,6 +31,14 @@ typedef struct nvm_symbol nvm_symbol; +///@brief Open raw binary image file and store contents in memory +///@return 1 on success or negative error code +int image_raw_memorize_file( + const char *filename, ///< [in] Input file path to open + const char **blob, ///< [out] Binary data content + size_t *blob_size ///< [out] Data address at end of content +); + ///@brief Update each listed symbol's content from memory region ///@return Number of symbols successfully read or negative error code int image_raw_merge_mem( From 52bedb1cee688f7fb207b0c4064772a4e5ea3a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 12:38:26 +0200 Subject: [PATCH 07/23] Add wrapper function image_memorize_file(). Implement the image file format detection and failover logic just as in image_merge_file(). The blob address and size are returned by reference via the respective parameters. --- src/image_formats.c | 39 ++++++++++++++++++++++++++++++++++++++- src/image_formats.h | 9 +++++++++ src/image_ihex_input.c | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/image_formats.c b/src/image_formats.c index bea6b45..3b6b4b6 100644 --- a/src/image_formats.c +++ b/src/image_formats.c @@ -1,6 +1,6 @@ ///@file ///@brief Handling of different binary image formats -///@copyright Copyright (C) 2014, 2015 Andre Colomb +///@copyright Copyright (C) 2014, 2015, 2016 Andre Colomb /// /// This file is part of elf-mangle. /// @@ -35,6 +35,43 @@ +int +image_memorize_file(const char *filename, + const char **blob, size_t *blob_size, + enum image_format format) +{ + int status = 0; + + if (! filename || ! blob || ! blob_size) return -1; + + if (format == formatNone || + format == formatIntelHex) { +#if HAVE_INTELHEX + status = image_ihex_memorize_file(filename, blob, blob_size); + if (status != 0) return status; + // Retry with raw binary on failure + else if (format == formatNone) { + fprintf(stderr, + _("Image file \"%s\" is not in Intel Hex format, trying raw binary.\n"), + filename); + format = formatRawBinary; + } +#else // !HAVE_INTELHEX + format = formatRawBinary; +#endif + } + + if (format == formatRawBinary) { + status = image_raw_memorize_file(filename, blob, blob_size); + return status; + } + + fprintf(stderr, _("Invalid input image file format.\n")); + return -2; +} + + + int image_merge_file(const char *filename, const nvm_symbol *list, int list_size, diff --git a/src/image_formats.h b/src/image_formats.h index e96b33b..011f89d 100644 --- a/src/image_formats.h +++ b/src/image_formats.h @@ -39,6 +39,15 @@ enum image_format { }; +///@brief Open image file and store contents in memory +///@return 1 on success or negative error code +int image_memorize_file( + const char *filename, ///< [in] Input file path to open + const char **blob, ///< [out] Binary data content + size_t *blob_size, ///< [out] Data address at end of content + enum image_format format ///< [in] Expected input format +); + ///@brief Open image file and update each listed symbol's content ///@return Number of symbols successfully read or negative error code int image_merge_file( diff --git a/src/image_ihex_input.c b/src/image_ihex_input.c index 8b98871..d090bed 100644 --- a/src/image_ihex_input.c +++ b/src/image_ihex_input.c @@ -119,7 +119,7 @@ image_ihex_memorize_file(const char *filename, strerror(errno)); status = -3; } else { - if (0 != ihex_byte_copy(rs, (void*) blob, *blob_size, 0)) { + if (0 != ihex_byte_copy(rs, (void*) contents, *blob_size, 0)) { fprintf(stderr, _("Could not copy data from Intel Hex file \"%s\" (%s)\n"), filename, ihex_error()); status = -4; From 292fb6a2b7e7911f143413c75b14d1bdada3f674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 19:15:12 +0200 Subject: [PATCH 08/23] Fix offset output in nvm_string_list(). Don't overwrite the original blob address while iterating, it is needed for the offset address output. Also fix missing argument in the test code. --- src/find_string.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/find_string.c b/src/find_string.c index 0193269..1a29b45 100644 --- a/src/find_string.c +++ b/src/find_string.c @@ -86,10 +86,10 @@ nvm_string_find(const char* blob, size_t size, uint8_t min_length) void nvm_string_list(const char* blob, size_t size, uint8_t min_length, int parseable) { - const char *next; + const char *next, *start = blob; while (size) { - next = nvm_string_find(blob, size, min_length); + next = nvm_string_find(start, size, min_length); if (! next) break; printf(parseable ? ("lpstring [%04zx] (%zu bytes + NUL):\n\t" @@ -98,8 +98,8 @@ nvm_string_list(const char* blob, size_t size, uint8_t min_length, int parseable "\"%s\"\n"), next - 1 - blob, strlen(next), next); next += strlen(next) + 1; - size -= next - blob; - blob = next; + size -= next - start; + start = next; } } @@ -142,7 +142,7 @@ main(void) "\0" //0xff ; - nvm_string_list(data, sizeof(data), 0); + nvm_string_list(data, sizeof(data), 0, 0); return 0; } From fd212eee5c859968082fa0583228591d175a3d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 16:18:25 +0200 Subject: [PATCH 09/23] Rename options.c to specific to elf-mangle utility. --- src/Makefile.am | 2 +- src/Makefile.simple | 2 +- src/{options.c => options_elf-mangle.c} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/{options.c => options_elf-mangle.c} (99%) diff --git a/src/Makefile.am b/src/Makefile.am index 52ce7d1..a38cc7d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ libfallback_la_SOURCES = \ elf_mangle_SOURCES = \ elf-mangle.c \ - options.c \ + options_elf-mangle.c \ options.h \ override.c \ override.h \ diff --git a/src/Makefile.simple b/src/Makefile.simple index 3170f05..300abe3 100644 --- a/src/Makefile.simple +++ b/src/Makefile.simple @@ -21,7 +21,7 @@ elf_mangle_SRC = \ elf-mangle.c \ - options.c \ + options_elf-mangle.c \ override.c \ print_symbols.c \ transform.c \ diff --git a/src/options.c b/src/options_elf-mangle.c similarity index 99% rename from src/options.c rename to src/options_elf-mangle.c index 3bde9fa..5dcc416 100644 --- a/src/options.c +++ b/src/options_elf-mangle.c @@ -1,5 +1,5 @@ ///@file -///@brief Command line parsing +///@brief Command line parsing for elf-mangle utility ///@copyright Copyright (C) 2014, 2015 Andre Colomb /// /// This file is part of elf-mangle. From 9be79933ac3901a4dd6be6b66b28e17f40e3c635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 17:14:26 +0200 Subject: [PATCH 10/23] Factor out internal library libelf-mangle. Make it easier to reuse some of elf-mangle's internal functions by compiling to an internal library everything except the main program logic and command line handling. --- src/Makefile.am | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index a38cc7d..edc024b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,7 +32,9 @@ GNULIB_LIBS = $(top_builddir)/gnulib/libgnu.la endif -noinst_LTLIBRARIES = libfallback.la +noinst_LTLIBRARIES = \ + libfallback.la \ + libelf-mangle.la bin_PROGRAMS = elf-mangle EXTRA_DIST = include_order.txt @@ -41,10 +43,7 @@ libfallback_la_SOURCES = \ fallback_options.c \ fallback_known_fields.c -elf_mangle_SOURCES = \ - elf-mangle.c \ - options_elf-mangle.c \ - options.h \ +libelf_mangle_la_SOURCES = \ override.c \ override.h \ print_symbols.c \ @@ -73,13 +72,20 @@ elf_mangle_SOURCES = \ find_string.h \ intl.h \ gettext.h +libelf_mangle_la_LIBADD = $(CINTELHEX_LIBS) $(GNULIB_LIBS) $(LTLIBINTL) if HAVE_INTELHEX -IMAGE_IHEX_INPUT = \ +IMAGE_IHEX_INPUT = \ image_ihex_input.c endif + +elf_mangle_SOURCES = \ + elf-mangle.c \ + options_elf-mangle.c \ + options.h + if CUSTOM_OPTIONS elf_mangle_SOURCES += \ custom_options.c @@ -89,5 +95,5 @@ elf_mangle_SOURCES += \ custom_known_fields.c endif -elf_mangle_LDADD = $(CINTELHEX_LIBS) $(GNULIB_LIBS) $(LTLIBINTL) +elf_mangle_LDADD = libelf-mangle.la elf_mangle_LDADD += libfallback.la From 40c64e1e1f14e92d86433d90cbf83a5ef5e96880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 17:58:51 +0200 Subject: [PATCH 11/23] Add lpstrings utility. Provide a separate binary to only look for length-prefixed strings, simliar to the well-known UNIX strings utility. Reuse the flexible image format handling from elf-mangle. --- src/.gitignore | 1 + src/Makefile.am | 10 ++- src/lpstrings.c | 83 +++++++++++++++++++++ src/options_lpstrings.c | 155 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 src/lpstrings.c create mode 100644 src/options_lpstrings.c diff --git a/src/.gitignore b/src/.gitignore index 423699e..b8e4ccb 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -2,5 +2,6 @@ *.bin *.eep /elf-mangle +/lpstrings /.deps /.libs diff --git a/src/Makefile.am b/src/Makefile.am index edc024b..3259251 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,7 +35,7 @@ endif noinst_LTLIBRARIES = \ libfallback.la \ libelf-mangle.la -bin_PROGRAMS = elf-mangle +bin_PROGRAMS = elf-mangle lpstrings EXTRA_DIST = include_order.txt @@ -97,3 +97,11 @@ endif elf_mangle_LDADD = libelf-mangle.la elf_mangle_LDADD += libfallback.la + + +lpstrings_SOURCES = \ + lpstrings.c \ + options_lpstrings.c \ + options.h + +lpstrings_LDADD = libelf-mangle.la diff --git a/src/lpstrings.c b/src/lpstrings.c new file mode 100644 index 0000000..3adfd69 --- /dev/null +++ b/src/lpstrings.c @@ -0,0 +1,83 @@ +///@file +///@brief Main program logic for lpstrings utility +///@copyright Copyright (C) 2016 Andre Colomb +/// +/// This file is part of elf-mangle. +/// +/// This file is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Lesser General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// elf-mangle is distributed in the hope that it will be useful, but +/// WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +/// Lesser General Public License for more details. +/// +/// You should have received a copy of the GNU Lesser General Public +/// License along with this program. If not, see +/// . +/// +///@author Andre Colomb + + +#include "config.h" + +#include "options.h" +#include "gettext.h" + +#include + + + +///@brief Process binary data according to application arguments +///@return Zero for success, negative on error +static int +process_image(const tool_config *config) +{ + int status, ret_code = 0; + const char *blob_address; + size_t blob_size; + + // Read input symbol layout and associated image data + status = image_memorize_file( //input image loaded + config->image_in, &blob_address, &blob_size, config->format_in); + if (0 < status) { + // Scan for strings + nvm_string_list( + blob_address, blob_size, + config->locate_strings, 0); + } else { + ret_code = status; //propagate error code + } + + return ret_code; +} + + + +int +main(int argc, char **argv) +{ + int ret_code; + tool_config config = { + .locate_strings = 0, + .show_size = 0, + .show_fields = showNone, + .print_content = printNone, + }; + + // Initialize message translation + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + // Parse command line options + ret_code = check_opts(argc, argv, &config) != 0; + if (ret_code != 0) return ret_code; + + // Process specified actions + ret_code = -process_image(&config); + + return ret_code; +} diff --git a/src/options_lpstrings.c b/src/options_lpstrings.c new file mode 100644 index 0000000..4f58143 --- /dev/null +++ b/src/options_lpstrings.c @@ -0,0 +1,155 @@ +///@file +///@brief Command line parsing for lpstrings utility +///@copyright Copyright (C) 2016 Andre Colomb +/// +/// This file is part of elf-mangle. +/// +/// This file is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Lesser General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// elf-mangle is distributed in the hope that it will be useful, but +/// WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +/// Lesser General Public License for more details. +/// +/// You should have received a copy of the GNU Lesser General Public +/// License along with this program. If not, see +/// . +/// +///@author Andre Colomb + + +#include "config.h" + +#include "options.h" +#include "find_string.h" +#include "intl.h" + +#include +#include +#include + + + +///@name Option keys +///@{ +#define OPT_IN_FORMAT 'I' +#define OPT_BYTES 'n' +///@} + +/// Helper macro to show number literals in option help +#define _STR_MACRO(x) _STR(x) +#define _STR(x) #x + + + +/// Supported command-line arguments definition +static const struct argp_option options[] = { + { NULL, 0, NULL, 0, + N_("Input / output options:"), 0 }, + { "input-format", OPT_IN_FORMAT, N_("FORMAT"), 0, + N_("Format of input image file. FORMAT can be either" + " \"raw\"" +#if HAVE_INTELHEX + ", \"ihex\"" +#endif + " or \"auto\" (default)"), 0 }, + { "bytes", OPT_BYTES, N_("MIN-LEN"), 0, + N_("Locate strings of at least MIN-LEN bytes in input" + " (argument defaults to " _STR_MACRO(FIND_STRING_DEFAULT_LENGTH) + " if omitted)"), 0 }, + { 0 } +}; + + + +/// Non-option arguments shown in help texts +static const char args_doc[] = N_("FILE"); + +/// Program short description +static const char doc[] = + N_("Locate length-prefixed strings of printable characters plus NUL terminator."); + +/// Version information for Argp +const char *argp_program_version = "lpstrings " PACKAGE_VERSION; + + + +///@brief Argp Parser Function for command line options +///@return Zero or error code specifying how to continue +static error_t +parse_opt( + const int key, ///< [in] Key field from the options vector + char *arg, ///< [in,out] Value given as option argument + struct argp_state *state) ///< [in,out] Parsing state for use by parser +{ + // Retreive the input argument from argp_parse + struct tool_config *tool = state->input; + const struct argp_child *child; + + switch (key) { + case ARGP_KEY_INIT: + if (! state->child_inputs) break; + // Copy tool config address to be used by parser children + for (child = state->root_argp->children; child && child->argp; ++child) { + state->child_inputs[child - state->root_argp->children] = state->input; + } + break; + + case OPT_IN_FORMAT: + if (arg == NULL) return EINVAL; + else if (strcmp(arg, "auto") == 0) tool->format_in = formatNone; + else if (strcmp(arg, "raw") == 0) tool->format_in = formatRawBinary; +#if HAVE_INTELHEX + else if (strcmp(arg, "ihex") == 0) tool->format_in = formatIntelHex; +#endif + else argp_error(state, _("Invalid binary image format `%s' specified."), arg); + break; + + case OPT_BYTES: + if (arg == NULL) return EINVAL; + else tool->locate_strings = atoi(arg); + if (tool->locate_strings < 0 || tool->locate_strings > UINT8_MAX) { + argp_error(state, _("Minimum string length %d out of range."), + tool->locate_strings); + tool->locate_strings = -1; + } + break; + + case ARGP_KEY_ARG: /* non-option -> input / output file name */ + // Check number of non-option arguments + if (state->arg_num >= 1) argp_error(state, _("Too many input file arguments.")); + else tool->image_in = arg; + break; + + case ARGP_KEY_NO_ARGS: + argp_error(state, _("Missing file name.")); + // Fall through + case ARGP_KEY_FINI: + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + + + +int +check_opts(int argc, char **argv, tool_config *config) +{ + struct argp argp = { //top-level parser for command line + .options = options, + .parser = parse_opt, + .args_doc = args_doc, + .doc = doc, + }; + int ret_code; + + ret_code = argp_parse(&argp, argc, argv, 0, 0, config); + + return ret_code; +} From 2dda7bc3728f15750a1e8b6975f2c853d1e601b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 6 Oct 2016 22:32:23 +0200 Subject: [PATCH 12/23] Implement additional options for nvm_string_list(). Make the output format rather configurable, supporting some features of the strings utility. --- src/elf-mangle.c | 3 ++- src/find_string.c | 41 ++++++++++++++++++++++++++++++++--------- src/find_string.h | 7 ++++--- src/lpstrings.c | 2 +- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/elf-mangle.c b/src/elf-mangle.c index 071b780..5d074ef 100644 --- a/src/elf-mangle.c +++ b/src/elf-mangle.c @@ -62,7 +62,8 @@ process_maps(const tool_config *config) // Scan for strings if requested if (config->locate_strings >= 0) nvm_string_list( symbol_map_blob_address(map_in), symbol_map_blob_size(map_in), - config->locate_strings, config->show_fields & showSymbol); + config->locate_strings, config->show_fields & showSymbol, + NULL); // Translate data from input to output layout if supplied map_out = symbol_map_open_file(config->map_files[1]); diff --git a/src/find_string.c b/src/find_string.c index 1a29b45..fddfa46 100644 --- a/src/find_string.c +++ b/src/find_string.c @@ -83,20 +83,43 @@ nvm_string_find(const char* blob, size_t size, uint8_t min_length) /// Strings are located by repeatedly calling nvm_string_find(), /// skipping over any previous match. +/// +/// If non-NULL, the delim parameter is used to separate the located +/// strings for output. In that case, the offset may be printed in +/// octal=8, decimal=10 or hex=16 as specified in the radix parameter. +/// If negative, the string length is also included. If no delimiter +/// is specified, a human-readable, verbose efault format is used. A +/// nonzero output_format then avoids translation of the message. void -nvm_string_list(const char* blob, size_t size, uint8_t min_length, int parseable) +nvm_string_list(const char* blob, size_t size, + uint8_t min_length, + int output_format, const char *delim) { - const char *next, *start = blob; + const char *next, *start = blob, *fmt = NULL; while (size) { next = nvm_string_find(start, size, min_length); if (! next) break; - printf(parseable - ? ("lpstring [%04zx] (%zu bytes + NUL):\n\t" - "\"%s\"\n") - : _("Length prefixed string at offset [%04zx] (%zu bytes + NUL):\n\t" - "\"%s\"\n"), - next - 1 - blob, strlen(next), next); + if (delim) { //output compatibility mode + switch (output_format) { + case 8: fmt = "%7zo "; break; + case 10: fmt = "%7zu "; break; + case 16: fmt = "%7zx "; break; + case -8: fmt = "%7zo+%03zo "; break; + case -10: fmt = "%7zu+%03zu "; break; + case -16: fmt = "%7zx+%03zx "; break; + default: break; + } + if (fmt) printf(fmt, next - 1 - blob, strlen(next)); + printf("%s%s", next, delim); + } else { + printf(output_format + ? ("lpstring [%04zx] (%zu bytes + NUL):\n\t" + "\"%s\"\n") + : _("Length prefixed string at offset [%04zx] (%zu bytes + NUL):\n\t" + "\"%s\"\n"), + next - 1 - blob, strlen(next), next); + } next += strlen(next) + 1; size -= next - start; start = next; @@ -142,7 +165,7 @@ main(void) "\0" //0xff ; - nvm_string_list(data, sizeof(data), 0, 0); + nvm_string_list(data, sizeof(data), 0, -16, " EOS\n\n"); return 0; } diff --git a/src/find_string.h b/src/find_string.h index 12a4d89..bdca1ec 100644 --- a/src/find_string.h +++ b/src/find_string.h @@ -38,14 +38,15 @@ const char* nvm_string_find( const char* blob, ///< [in] Binary data to search in size_t size, ///< [in] Size of binary data uint8_t min_length ///< [in] Minimum length of string to find (zero for default=4) - ); +); ///@brief Find and print all suitable strings in given binary data void nvm_string_list( const char* blob, ///< [in] Binary data to search in size_t size, ///< [in] Size of binary data uint8_t min_length, ///< [in] Minimum string length passed to nvm_string_find() - int parseable ///< [in] Avoid localized output - ); + int output_format, ///< [in] Output format configuration: + const char *delim ///< [in] Delimiter for string output, forces simple format if set +); #endif //FIND_STRING_H_ diff --git a/src/lpstrings.c b/src/lpstrings.c index 3adfd69..6e5a693 100644 --- a/src/lpstrings.c +++ b/src/lpstrings.c @@ -46,7 +46,7 @@ process_image(const tool_config *config) // Scan for strings nvm_string_list( blob_address, blob_size, - config->locate_strings, 0); + config->locate_strings, 0, NULL); } else { ret_code = status; //propagate error code } From f3141d2eab35a2d6059f30a1514ff7d40adcd065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 10 Oct 2016 22:29:25 +0200 Subject: [PATCH 13/23] Rename locate_strings option member. More descriptive name for the option is lpstring_min (the minimum length of length-prefixed strings). --- src/elf-mangle.c | 6 +++--- src/lpstrings.c | 4 ++-- src/options.h | 2 +- src/options_elf-mangle.c | 10 +++++----- src/options_lpstrings.c | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/elf-mangle.c b/src/elf-mangle.c index 5d074ef..86f4fd1 100644 --- a/src/elf-mangle.c +++ b/src/elf-mangle.c @@ -60,9 +60,9 @@ process_maps(const tool_config *config) config->image_in, symbols_in, num_in, symbol_map_blob_size(map_in), config->format_in))) { // Scan for strings if requested - if (config->locate_strings >= 0) nvm_string_list( + if (config->lpstring_min >= 0) nvm_string_list( symbol_map_blob_address(map_in), symbol_map_blob_size(map_in), - config->locate_strings, config->show_fields & showSymbol, + config->lpstring_min, config->show_fields & showSymbol, NULL); // Translate data from input to output layout if supplied @@ -107,7 +107,7 @@ main(int argc, char **argv) int ret_code; tool_config config = { .section = DEFAULT_SECTION, - .locate_strings = -1, + .lpstring_min = -1, .show_size = 0, .show_fields = showNone, .print_content = printNone, diff --git a/src/lpstrings.c b/src/lpstrings.c index 6e5a693..c1700a3 100644 --- a/src/lpstrings.c +++ b/src/lpstrings.c @@ -46,7 +46,7 @@ process_image(const tool_config *config) // Scan for strings nvm_string_list( blob_address, blob_size, - config->locate_strings, 0, NULL); + config->lpstring_min, 0, NULL); } else { ret_code = status; //propagate error code } @@ -61,7 +61,7 @@ main(int argc, char **argv) { int ret_code; tool_config config = { - .locate_strings = 0, + .lpstring_min = 0, .show_size = 0, .show_fields = showNone, .print_content = printNone, diff --git a/src/options.h b/src/options.h index 96e8aeb..ce7eeba 100644 --- a/src/options.h +++ b/src/options.h @@ -48,7 +48,7 @@ typedef struct tool_config { /// Format of the output image file enum image_format format_out; /// Locate strings of this minimum length within image - int locate_strings; + int lpstring_min; /// Print out the total section image size in bytes char show_size; /// Configuration flags for dumping symbol descriptions diff --git a/src/options_elf-mangle.c b/src/options_elf-mangle.c index 5dcc416..b5a69d0 100644 --- a/src/options_elf-mangle.c +++ b/src/options_elf-mangle.c @@ -176,12 +176,12 @@ parse_opt( break; case OPT_STRINGS: - if (arg == NULL) tool->locate_strings = 0; - else tool->locate_strings = atoi(arg); - if (tool->locate_strings < 0 || tool->locate_strings > UINT8_MAX) { + if (arg == NULL) tool->lpstring_min = 0; + else tool->lpstring_min = atoi(arg); + if (tool->lpstring_min < 0 || tool->lpstring_min > UINT8_MAX) { argp_error(state, _("Minimum string length %d out of range."), - tool->locate_strings); - tool->locate_strings = -1; + tool->lpstring_min); + tool->lpstring_min = -1; } break; diff --git a/src/options_lpstrings.c b/src/options_lpstrings.c index 4f58143..382ea67 100644 --- a/src/options_lpstrings.c +++ b/src/options_lpstrings.c @@ -110,11 +110,11 @@ parse_opt( case OPT_BYTES: if (arg == NULL) return EINVAL; - else tool->locate_strings = atoi(arg); - if (tool->locate_strings < 0 || tool->locate_strings > UINT8_MAX) { + else tool->lpstring_min = atoi(arg); + if (tool->lpstring_min < 0 || tool->lpstring_min > UINT8_MAX) { argp_error(state, _("Minimum string length %d out of range."), - tool->locate_strings); - tool->locate_strings = -1; + tool->lpstring_min); + tool->lpstring_min = -1; } break; From ae8f53cb0ea86c205e6e5c9f7c354644e0ea10ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 10 Oct 2016 22:47:15 +0200 Subject: [PATCH 14/23] Avoid overwriting custom CPPFLAGS / LDFLAGS. When testing for libcintelhex with given prefix, do not permanently alter the CPPFLAGS and LDFLAGS variables. They might be overridden after configuration, via command line arguments to make. In that case, extra flags added during configuration are overwritten. Store the respective configuration in $CINTELHEX_CPPFLAGS and $CINTELHEX_LDFLAGS instead and use those in the automake recipe. --- configure.ac | 16 +++++++++------- src/Makefile.am | 7 ++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index a5b3abc..04f977d 100644 --- a/configure.ac +++ b/configure.ac @@ -71,15 +71,17 @@ AC_ARG_WITH([cintelhex], [cintelhex=1], [cintelhex_internal=1])], [cintelhex_internal=1])], [internal], [cintelhex_internal=1], - [saved_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="-I$with_cintelhex/include $CPPFLAGS" + [AC_SUBST([CINTELHEX_CPPFLAGS], [-I$with_cintelhex/include]) + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CINTELHEX_CPPFLAGS $CPPFLAGS" AC_CHECK_HEADERS([cintelhex.h], - [saved_LDFLAGS="$LDFLAGS" - LDFLAGS="-L$with_cintelhex/lib $LDFLAGS" + [AC_SUBST([CINTELHEX_LDFLAGS], [-L$with_cintelhex/lib]) + saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$CINTELHEX_LDFLAGS $LDFLAGS" AC_CHECK_LIB([cintelhex], [ihex_byte_copy], - [cintelhex=1], - [LDFLAGS="$saved_LDFLAGS"])], - [CPPFLAGS="$saved_CPPFLAGS"]) + [cintelhex=1]) + LDFLAGS="$saved_LDFLAGS"]) + CPPFLAGS="$saved_CPPFLAGS" ]) ], [AC_MSG_RESULT([--with-cintelhex not specified]) diff --git a/src/Makefile.am b/src/Makefile.am index 52ce7d1..7c60cce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,12 +17,13 @@ # . -AM_CPPFLAGS = -D_POSIX $(CINTELHEX_INTERNAL_CPPFLAGS) $(GNULIB_CPPFLAGS) +AM_CPPFLAGS = -D_POSIX $(CINTELHEX_CPPFLAGS) $(GNULIB_CPPFLAGS) AM_CFLAGS = -Wall -Wstrict-prototypes -Wextra -fgnu89-inline +AM_LDFLAGS = $(CINTELHEX_LDFLAGS) DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ if HAVE_INTELHEX_INTERNAL -CINTELHEX_INTERNAL_CPPFLAGS = -I$(top_srcdir)/libcintelhex/include +CINTELHEX_CPPFLAGS += -I$(top_srcdir)/libcintelhex/include CINTELHEX_LIBS += $(top_builddir)/libcintelhex/src/libcintelhex.la endif @@ -76,7 +77,7 @@ elf_mangle_SOURCES = \ if HAVE_INTELHEX -IMAGE_IHEX_INPUT = \ +IMAGE_IHEX_INPUT = \ image_ihex_input.c endif From 470a585475a83391a59e4017f0dfb943ef46124b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 10 Oct 2016 22:56:36 +0200 Subject: [PATCH 15/23] Add additional lpstrings command line options. If either --output-separator (-s) or --radix (-t) is given, switch to the simpler output format from the POSIX specification for strings(1). As an extension, print the string length in bytes without NUL terminator for each string if the --length option is given in addition to --radix. It is appended after the offset with a plus sign and uses the same radix. --- src/lpstrings.c | 6 +++--- src/options.h | 4 ++++ src/options_lpstrings.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/lpstrings.c b/src/lpstrings.c index c1700a3..faa82e9 100644 --- a/src/lpstrings.c +++ b/src/lpstrings.c @@ -46,7 +46,9 @@ process_image(const tool_config *config) // Scan for strings nvm_string_list( blob_address, blob_size, - config->lpstring_min, 0, NULL); + config->lpstring_min, + config->offset_radix * (config->show_fields & showByteSize ? -1 : 1), + config->lpstring_delim); } else { ret_code = status; //propagate error code } @@ -61,8 +63,6 @@ main(int argc, char **argv) { int ret_code; tool_config config = { - .lpstring_min = 0, - .show_size = 0, .show_fields = showNone, .print_content = printNone, }; diff --git a/src/options.h b/src/options.h index ce7eeba..a8f4855 100644 --- a/src/options.h +++ b/src/options.h @@ -49,8 +49,12 @@ typedef struct tool_config { enum image_format format_out; /// Locate strings of this minimum length within image int lpstring_min; + /// Output separator between located strings + char* lpstring_delim; /// Print out the total section image size in bytes char show_size; + /// Number base for displaying address offsets and sizes + signed char offset_radix; /// Configuration flags for dumping symbol descriptions enum show_field show_fields; /// Configuration flags for dumping symbol content diff --git a/src/options_lpstrings.c b/src/options_lpstrings.c index 382ea67..200232f 100644 --- a/src/options_lpstrings.c +++ b/src/options_lpstrings.c @@ -37,6 +37,9 @@ ///@{ #define OPT_IN_FORMAT 'I' #define OPT_BYTES 'n' +#define OPT_LENGTH 'l' +#define OPT_SEPARATOR 's' +#define OPT_RADIX 't' ///@} /// Helper macro to show number literals in option help @@ -60,6 +63,16 @@ static const struct argp_option options[] = { N_("Locate strings of at least MIN-LEN bytes in input" " (argument defaults to " _STR_MACRO(FIND_STRING_DEFAULT_LENGTH) " if omitted)"), 0 }, + + { NULL, 0, NULL, 0, + N_("Display information from parsed files:"), 0 }, + { "length", OPT_LENGTH, NULL, 0, + N_("Print length in bytes for each string"), 0 }, + { "output-separator",OPT_SEPARATOR, N_("SEP"), 0, + N_("Separator between strings in output."), 0 }, + { "radix", OPT_RADIX, "{o,d,x}", OPTION_ARG_OPTIONAL, + N_("Print the location of the string" + " in base 8, 10 or 16 (default)"), 0 }, { 0 } }; @@ -118,6 +131,24 @@ parse_opt( } break; + case OPT_LENGTH: + tool->show_fields |= showByteSize; + break; + + case OPT_SEPARATOR: + // Switch to strings(1) like output + tool->lpstring_delim = arg; + break; + + case OPT_RADIX: + // Switch to strings(1) like output + if (! tool->lpstring_delim) tool->lpstring_delim = "\n"; + if (arg == NULL || strcmp(arg, "x") == 0) tool->offset_radix = 16; + else if (strcmp(arg, "d") == 0) tool->offset_radix = 10; + else if (strcmp(arg, "o") == 0) tool->offset_radix = 8; + else argp_error(state, _("Invalid offset radix `%s' specified."), arg); + break; + case ARGP_KEY_ARG: /* non-option -> input / output file name */ // Check number of non-option arguments if (state->arg_num >= 1) argp_error(state, _("Too many input file arguments.")); From ed30761222d068b86a50e1485eec4d1f89a97c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 10 Oct 2016 23:51:22 +0200 Subject: [PATCH 16/23] Document lpstrings utility in README. Remove the TODO item and include a subsection in README.md. --- README.md | 26 ++++++++++++++++++++++++++ TODO.md | 8 -------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8abc434..885e07a 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,32 @@ format with a length prefix byte, and usually operates on all initialized and loaded sections of the object file. +#### Length-Prefixed Strings in Binary Image Files #### + +Similar to the standard POSIX `strings(1)` utility, *elf-mangle* +includes a separate binary called `lpstrings` that applies the search +algorithm described above to a given binary data image. In contrast to +`elf-mangle`, it works without an ELF file as input, but directly +scans a binary file in any supported format, as documented for the +`--input-format` option. + +The default output format used by *elf-mangle* can be switched to a +simpler format if either the `--output-separator` or `--radix` options +are given. The former allows specifying a custom delimiter between +located strings, which is a newline by default. If given, the +`--radix` option causes the start offset to be prepended to each +string, as an octal (`o`), decimal (`d`) or hexadecimal (`x`) number. + +As an extension to the POSIX options, `lpstrings` may print the +string length in bytes without NUL terminator for each string if the +`--length` option is given in addition to `--radix`. It is appended +after the offset with a plus sign and uses the same radix. + +In contrast to POSIX `strings(1)`, processing the standard input or +more than one file given on the command line is not possible. + + + Application Extensions ---------------------- diff --git a/TODO.md b/TODO.md index e771d1b..95c0eae 100644 --- a/TODO.md +++ b/TODO.md @@ -2,14 +2,6 @@ Issues list for elf-mangle ========================== -## String search without ELF map ## - -The `--strings` option should be usable without an ELF symbol map, -e.g. to find which one needs to be used. - -Factor out an `idc-strings` utility for supported image file formats. - - ## Override data from binary files ## Symbol override data must be passed as hex bytes on the command line. From 5cd65b3baf549d515d9d2bc8bd4dbd8735d846a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 11 Oct 2016 13:49:28 +0200 Subject: [PATCH 17/23] Return the number of strings found as exit status. Add a counter in nvm_string_list() and change its return type to int for indicating the number of matches. Use this return value as the successful exit status for the lpstrings utility. --- README.md | 5 +++-- src/find_string.c | 12 +++++++----- src/find_string.h | 3 ++- src/lpstrings.c | 6 +++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 885e07a..24a275a 100644 --- a/README.md +++ b/README.md @@ -423,8 +423,9 @@ string length in bytes without NUL terminator for each string if the after the offset with a plus sign and uses the same radix. In contrast to POSIX `strings(1)`, processing the standard input or -more than one file given on the command line is not possible. - +more than one file given on the command line is not possible. A +positive exit status indicates the number of strings found, negative +values indicate errors. Application Extensions diff --git a/src/find_string.c b/src/find_string.c index fddfa46..d2035f7 100644 --- a/src/find_string.c +++ b/src/find_string.c @@ -88,14 +88,15 @@ nvm_string_find(const char* blob, size_t size, uint8_t min_length) /// strings for output. In that case, the offset may be printed in /// octal=8, decimal=10 or hex=16 as specified in the radix parameter. /// If negative, the string length is also included. If no delimiter -/// is specified, a human-readable, verbose efault format is used. A +/// is specified, a human-readable, verbose default format is used. A /// nonzero output_format then avoids translation of the message. -void +int nvm_string_list(const char* blob, size_t size, uint8_t min_length, int output_format, const char *delim) { const char *next, *start = blob, *fmt = NULL; + int found = 0; while (size) { next = nvm_string_find(start, size, min_length); @@ -123,7 +124,10 @@ nvm_string_list(const char* blob, size_t size, next += strlen(next) + 1; size -= next - start; start = next; + found += 1; } + + return found; } @@ -165,8 +169,6 @@ main(void) "\0" //0xff ; - nvm_string_list(data, sizeof(data), 0, -16, " EOS\n\n"); - - return 0; + return nvm_string_list(data, sizeof(data), 0, -16, " EOS\n\n"); } #endif diff --git a/src/find_string.h b/src/find_string.h index bdca1ec..798498c 100644 --- a/src/find_string.h +++ b/src/find_string.h @@ -41,7 +41,8 @@ const char* nvm_string_find( ); ///@brief Find and print all suitable strings in given binary data -void nvm_string_list( +///@return Number of strings found or negative error code +int nvm_string_list( const char* blob, ///< [in] Binary data to search in size_t size, ///< [in] Size of binary data uint8_t min_length, ///< [in] Minimum string length passed to nvm_string_find() diff --git a/src/lpstrings.c b/src/lpstrings.c index faa82e9..cf8aa32 100644 --- a/src/lpstrings.c +++ b/src/lpstrings.c @@ -31,7 +31,7 @@ ///@brief Process binary data according to application arguments -///@return Zero for success, negative on error +///@return Number of strings found or negative error code static int process_image(const tool_config *config) { @@ -42,9 +42,9 @@ process_image(const tool_config *config) // Read input symbol layout and associated image data status = image_memorize_file( //input image loaded config->image_in, &blob_address, &blob_size, config->format_in); - if (0 < status) { + if (status > 0) { // Scan for strings - nvm_string_list( + ret_code = nvm_string_list( blob_address, blob_size, config->lpstring_min, config->offset_radix * (config->show_fields & showByteSize ? -1 : 1), From ca47c5f6a7cb5f95a0fc13ed880b2f0df73cd583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 11 Oct 2016 14:02:21 +0200 Subject: [PATCH 18/23] Include new source files for translation. Add missing or renamed files with translatable string to POTFILES.in. --- po/POTFILES.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 110e093..5963290 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -7,8 +7,11 @@ src/image_formats.c src/image_ihex_input.c src/image_ihex_output.c src/image_raw.c +src/lpstrings.c src/nvm_field.c -src/options.c +src/options_elf-mangle.c +src/options_lpstrings.c src/override.c +src/print_symbols.c src/symbol_map.c src/transform.c From eea1d3ff00b5493544c3c02e61270c78263f418f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 31 Oct 2016 22:21:56 +0100 Subject: [PATCH 19/23] Small documentation fixes. Found during code self-review. --- README.md | 13 +++++++------ src/find_string.c | 9 +++++---- src/find_string.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 24a275a..7da7750 100644 --- a/README.md +++ b/README.md @@ -410,12 +410,13 @@ algorithm described above to a given binary data image. In contrast to scans a binary file in any supported format, as documented for the `--input-format` option. -The default output format used by *elf-mangle* can be switched to a -simpler format if either the `--output-separator` or `--radix` options -are given. The former allows specifying a custom delimiter between -located strings, which is a newline by default. If given, the -`--radix` option causes the start offset to be prepended to each -string, as an octal (`o`), decimal (`d`) or hexadecimal (`x`) number. +The default output format used by `lpstrings` is the same as for +*elf-mangle*, but can be simplified if either the `--output-separator` +or `--radix` options are given. The former allows specifying a custom +delimiter between located strings, which is a newline by default. If +given, the `--radix` option causes the start offset to be prepended to +each string, as an octal (`o`), decimal (`d`) or hexadecimal (`x`) +number. As an extension to the POSIX options, `lpstrings` may print the string length in bytes without NUL terminator for each string if the diff --git a/src/find_string.c b/src/find_string.c index d2035f7..d0a8f74 100644 --- a/src/find_string.c +++ b/src/find_string.c @@ -86,10 +86,11 @@ nvm_string_find(const char* blob, size_t size, uint8_t min_length) /// /// If non-NULL, the delim parameter is used to separate the located /// strings for output. In that case, the offset may be printed in -/// octal=8, decimal=10 or hex=16 as specified in the radix parameter. -/// If negative, the string length is also included. If no delimiter -/// is specified, a human-readable, verbose default format is used. A -/// nonzero output_format then avoids translation of the message. +/// octal=8, decimal=10 or hex=16 as specified in the output_format +/// parameter. If negative, the string length is also included. If +/// no delimiter is specified, a human-readable, verbose default +/// format is used. A nonzero output_format then avoids translation +/// of the message. int nvm_string_list(const char* blob, size_t size, uint8_t min_length, diff --git a/src/find_string.h b/src/find_string.h index 798498c..cbf58be 100644 --- a/src/find_string.h +++ b/src/find_string.h @@ -46,7 +46,7 @@ int nvm_string_list( const char* blob, ///< [in] Binary data to search in size_t size, ///< [in] Size of binary data uint8_t min_length, ///< [in] Minimum string length passed to nvm_string_find() - int output_format, ///< [in] Output format configuration: + int output_format, ///< [in] Output format configuration const char *delim ///< [in] Delimiter for string output, forces simple format if set ); From 3405989fc7d006463cef7eaac6ee8404f2cce91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Mon, 31 Oct 2016 22:38:56 +0100 Subject: [PATCH 20/23] Indentation fixes. --- src/field_list.h | 4 ++-- src/field_print.h | 4 ++-- src/known_fields.h | 2 +- src/nvm_field.h | 10 +++++----- src/options.h | 2 +- src/override.h | 2 +- src/print_symbols.h | 2 +- src/symbol_list.h | 12 ++++++------ src/symbol_map.h | 12 ++++++------ src/transform.h | 2 +- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/field_list.h b/src/field_list.h index 38cb5f1..c0b955f 100644 --- a/src/field_list.h +++ b/src/field_list.h @@ -48,7 +48,7 @@ typedef struct nvm_field_list { const nvm_field* field_list_find( const char *symbol, ///< [in] Symbol name to look for const nvm_field_list *list ///< [in] Field descriptor list - ); +); ///@brief Append and initialize a new field descriptor to the list ///@invariant References to any previously added field descriptors remain valid @@ -58,6 +58,6 @@ const nvm_field* field_list_add( size_t expected_size, ///< [in] Expected symbol size to record in field descriptor const char *symbol, ///< [in] Symbol name to record in field descriptor const char *description ///< [in] Intelligible field name to record in field descriptor - ); +); #endif //FIELD_LIST_H_ diff --git a/src/field_print.h b/src/field_print.h index e001cd3..90bb229 100644 --- a/src/field_print.h +++ b/src/field_print.h @@ -35,13 +35,13 @@ typedef struct nvm_field nvm_field; void print_hex_dump( const char *data, ///< [in] Start address of data block size_t size ///< [in] Size of data block in bytes - ); +); ///@brief Pretty-print data block according to field description void print_field( const nvm_field *field, ///< [in] Field descriptor const char *data, ///< [in] Start address of data block size_t size ///< [in] Actual size of data block in bytes - ); +); #endif //FIELD_PRINT_H_ diff --git a/src/known_fields.h b/src/known_fields.h index 1e2449c..71a14fe 100644 --- a/src/known_fields.h +++ b/src/known_fields.h @@ -37,6 +37,6 @@ int known_fields_expected(void); ///@return Reference to field descriptor or NULL on error const struct nvm_field* find_known_field( const char *symbol ///< [in] Symbol name - ); +); #endif //KNOWN_FIELDS_H_ diff --git a/src/nvm_field.h b/src/nvm_field.h index e2fe92c..fa8f109 100644 --- a/src/nvm_field.h +++ b/src/nvm_field.h @@ -36,7 +36,7 @@ typedef struct nvm_field nvm_field; typedef size_t (*field_resize_f)( const char *src, ///< [in] Data field content size_t initial ///< [in] Currently known symbol size in bytes - ); +); ///@brief Function pointer to copy individual field data intelligently ///@return Number of bytes copied @@ -52,7 +52,7 @@ typedef size_t (*field_copy_f)( typedef void (*field_print_f)( const char *data, ///< [in] Data field content size_t size ///< [in] Size of the data block in bytes - ); +); /// Description of a binary data field struct nvm_field { @@ -76,7 +76,7 @@ const nvm_field* find_field( const char *symbol, ///< [in] Symbol name to look for const nvm_field fields[], ///< [in] Vector of field descriptors size_t num_fields ///< [in] Number of elements in the vector - ); +); ///@brief Copy data field content byte-wise ///@see field_copy_f @@ -86,7 +86,7 @@ size_t copy_field_verbatim( const char *src, ///< [in] Source address for field data size_t dst_size, ///< [in] Maximum size in bytes to write to destination size_t src_size ///< [in] Maximum size in bytes available from source - ); +); ///@brief Do not copy data field content (dummy implementation) ///@see field_copy_f @@ -96,6 +96,6 @@ size_t copy_field_noop( const char *src, ///< [in] Source address for field data size_t dst_size, ///< [in] Maximum size in bytes to write to destination size_t src_size ///< [in] Maximum size in bytes available from source - ); +); #endif //NVM_FIELD_H_ diff --git a/src/options.h b/src/options.h index a8f4855..2cbb02f 100644 --- a/src/options.h +++ b/src/options.h @@ -70,6 +70,6 @@ int check_opts( int argc, ///< [in] Number of tokens on the command line char **argv, ///< [in,out] Vector of command line tokens tool_config *config ///< [out] Storage for parsed application configuration - ); +); #endif //OPTIONS_H_ diff --git a/src/override.h b/src/override.h index d329e0a..839ae85 100644 --- a/src/override.h +++ b/src/override.h @@ -42,6 +42,6 @@ int parse_overrides( char *overrides, ///< [in] Override specification string const nvm_symbol *list, ///< [in] List of symbols to apply overrides int size ///< [in] Number of symbols in the list - ); +); #endif //OVERRIDE_H_ diff --git a/src/print_symbols.h b/src/print_symbols.h index 379d92d..98765e3 100644 --- a/src/print_symbols.h +++ b/src/print_symbols.h @@ -58,6 +58,6 @@ void print_symbol_list( int size, ///< [in] Number of symbols in list enum show_field field, ///< [in] Description display options enum print_content content ///< [in] Content display options - ); +); #endif //PRINT_SYMBOLS_H_ diff --git a/src/symbol_list.h b/src/symbol_list.h index 05e2867..f199ee5 100644 --- a/src/symbol_list.h +++ b/src/symbol_list.h @@ -50,7 +50,7 @@ typedef struct nvm_symbol { typedef const nvm_symbol* (*symbol_list_iterator_f)( const nvm_symbol *symbol, ///< [in] Current symbol to process const void *arg ///< [in] Custom data to control iteration - ); +); ///@brief Append an element to the list @@ -59,7 +59,7 @@ typedef const nvm_symbol* (*symbol_list_iterator_f)( nvm_symbol* symbol_list_append( nvm_symbol *(list[]), ///< [in,out] Start location of the list int *size ///< [out] New list size - ); +); ///@brief Iterate through a list of symbols and call the given function ///@details Iteration stops after the iterator function returns a non-NULL value @@ -69,7 +69,7 @@ const nvm_symbol* symbol_list_foreach( int size, ///< [in] Number of symbols in the list const symbol_list_iterator_f func, ///< [in] Iterator function to be called const void *arg ///< [in] Custom data passed to iterator function - ); +); ///@brief Iterate through a list of symbols and call the given function ///@return Number of iterations where the function returned a NULL value. @@ -78,7 +78,7 @@ int symbol_list_foreach_count( int size, ///< [in] Number of symbols in the list const symbol_list_iterator_f func, ///< [in] Iterator function to be called const void *arg ///< [in] Custom data passed to iterator function - ); +); ///@brief Find the first symbol with a given field descriptor ///@return Address of the first matching symbol or NULL on error @@ -86,7 +86,7 @@ const nvm_symbol* symbol_list_find_field( const nvm_symbol list[], ///< [in] List of symbols to search through int size, ///< [in] Number of symbols in the list const nvm_field *field ///< [in] Field descriptor to look for - ); +); ///@brief Find the first symbol whose field descriptor matches a given name ///@return Address of the first matching symbol or NULL on error @@ -94,6 +94,6 @@ const nvm_symbol* symbol_list_find_symbol( const nvm_symbol list[], ///< [in] List of symbols to search through int size, ///< [in] Number of symbols in the list const char *symbol ///< [in] Symbol name to look for - ); +); #endif //SYMBOL_LIST_H_ diff --git a/src/symbol_map.h b/src/symbol_map.h index 8931dad..bdbe149 100644 --- a/src/symbol_map.h +++ b/src/symbol_map.h @@ -38,7 +38,7 @@ typedef struct nvm_symbol_map_source nvm_symbol_map_source; ///@return Handle of this source for further processing nvm_symbol_map_source* symbol_map_open_file( const char *filename ///< [in] File path to open - ); +); ///@brief Examine symbol map contents, store symbol list and binary data ///@return @@ -49,29 +49,29 @@ int symbol_map_parse( nvm_symbol_map_source *source, ///< [in,out] Handle of the map source const char *section_name, ///< [in] Section within the source to parse nvm_symbol **symbol_list ///< [out] List of symbols found - ); +); ///@brief Access the source's binary data ///@return Address of the binary data or NULL on error char* symbol_map_blob_address( nvm_symbol_map_source *source ///< [in,out] Handle of the map source - ); +); ///@brief Check the size of the source's binary data ///@return Size of binary data or zero on error size_t symbol_map_blob_size( nvm_symbol_map_source *source ///< [in,out] Handle of the map source - ); +); ///@brief Print out the size of the source's binary data void symbol_map_print_size( nvm_symbol_map_source *source, ///< [in] Handle of the map source int parseable ///< [in] Avoid localized output - ); +); ///@brief Close the symbol map source handle and free associated resources void symbol_map_close( nvm_symbol_map_source *source ///< [in,out] Handle of the map source - ); +); #endif //SYMBOL_MAP_H_ diff --git a/src/transform.h b/src/transform.h index 4985148..4daa96b 100644 --- a/src/transform.h +++ b/src/transform.h @@ -36,6 +36,6 @@ void transfer_fields( int num_src, ///< [in] Number of symbols in source list const nvm_symbol *list_dst, ///< [in] Destination list of symbols to copy to int num_dst ///< [in] Number of symbols in destination list - ); +); #endif //TRANSFORM_H_ From 9f7c0eb65ecf1d9a3e23edfd259cd63bc076e4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Wed, 2 Nov 2016 22:27:36 +0100 Subject: [PATCH 21/23] Bump version to 0.6. Add ChangeLog entry and document the new version number in autoconf input. --- ChangeLog | 14 ++++++++++++++ configure.ac | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9fd1ed4..e5a5adf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2016-11-02 André Colomb + + * Fix offset output showing wrong numbers when using the + length-prefixed string search function (--strings option). + * Refactor internal handling of binary blobs to allow loading an + image file into memory for later processing. + * Add the lpstrings utility, similar to the standard POSIX + strings(1) command. + * Fix a corner case in build system configuration which would + overwrite user-supplied CPPFLAGS / LDFLAGS variables. + * Update German translation. + + * Release version 0.6 + 2016-09-19 André Colomb * Minor clean-ups for the build system and detection of libelf diff --git a/configure.ac b/configure.ac index 04f977d..62ec525 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ # . -AC_INIT([elf-mangle], [0.5.1], [src@andre.colomb.de]) +AC_INIT([elf-mangle], [0.6], [src@andre.colomb.de]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/elf-mangle.c]) AC_CONFIG_AUX_DIR([.]) From 083b6ca8909a165e7c5659aa9bdc8ed6ae30561d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Wed, 2 Nov 2016 23:04:19 +0100 Subject: [PATCH 22/23] Merge and extend German translation. Regenerate from sources and translate newly added messages. --- po/de.po | 149 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 48 deletions(-) diff --git a/po/de.po b/po/de.po index f4aaba0..cebbc15 100644 --- a/po/de.po +++ b/po/de.po @@ -1,14 +1,14 @@ # German translations for elf-mangle package. -# Copyright (C) 2014 Andre Colomb +# Copyright (C) 2014, 2016 Andre Colomb # This file is distributed under the same license as the elf-mangle package. -# André Colomb , 2014. +# André Colomb , 2014, 2016. # msgid "" msgstr "" -"Project-Id-Version: elf-mangle 0.1\n" +"Project-Id-Version: elf-mangle 0.6\n" "Report-Msgid-Bugs-To: src@andre.colomb.de\n" -"POT-Creation-Date: 2015-09-14 10:53+0200\n" -"PO-Revision-Date: 2015-07-22 12:56+0100\n" +"POT-Creation-Date: 2016-11-02 22:28+0100\n" +"PO-Revision-Date: 2016-11-02 23:02+0100\n" "Last-Translator: Andre Colomb \n" "Language-Team: German\n" "Language: de\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.7.5\n" +"X-Generator: Poedit 1.8.7.1\n" "X-Poedit-Basepath: .\n" "X-Poedit-SearchPath-0: ..\n" @@ -102,7 +102,7 @@ msgstr "Optionen spezifisch für Beispiel:" msgid "\tMissing %zu of %zu data bytes!" msgstr "\t%zu von %zu Datenbytes fehlen!" -#: src/find_string.c:97 +#: src/find_string.c:121 #, c-format msgid "" "Length prefixed string at offset [%04zx] (%zu bytes + NUL):\n" @@ -111,58 +111,63 @@ msgstr "" "Zeichenkette mit Längenpräfix an Position [%04zx] (%zu Byte + NUL):\n" "\t\"%s\"\n" -#: src/image_formats.c:56 +#: src/image_formats.c:55 src/image_formats.c:93 #, c-format msgid "Image file \"%s\" is not in Intel Hex format, trying raw binary.\n" msgstr "" "Abbilddatei \"%s\" ist nicht im Intel-Hex-Format, versuche Binärformat.\n" -#: src/image_formats.c:70 +#: src/image_formats.c:69 src/image_formats.c:107 #, c-format msgid "Invalid input image file format.\n" msgstr "Ungültiges Format für Binärabbild.\n" -#: src/image_formats.c:83 +#: src/image_formats.c:120 #, c-format msgid "%s: Output file \"%s\" format %d\n" msgstr "%s: Ausgabedatei \"%s\" im Format %d\n" -#: src/image_formats.c:95 +#: src/image_formats.c:132 #, c-format msgid "Invalid output image file format specified.\n" msgstr "Ungültiges Ausgabeformat für Binärabbild.\n" -#: src/image_ihex_input.c:77 src/image_raw.c:173 src/image_raw.c:222 +#: src/image_ihex_input.c:78 src/image_raw.c:175 src/image_raw.c:287 #, c-format msgid "Cannot open image \"%s\" (%s)\n" msgstr "Abbilddatei \"%s\" kann nicht geöffnet werden (%s)\n" -#: src/image_ihex_input.c:82 +#: src/image_ihex_input.c:83 #, c-format msgid "Could not determine data range in Intel Hex file \"%s\" (%s)\n" msgstr "" "Konnte Datenbereich in der Intel-Hex-Datei \"%s\" nicht ermitteln (%s)\n" -#: src/image_ihex_input.c:86 src/image_raw.c:178 +#: src/image_ihex_input.c:87 src/image_raw.c:180 #, c-format msgid "Image file \"%s\" is empty\n" msgstr "Abbilddatei \"%s\" ist leer\n" -#: src/image_ihex_input.c:88 +#: src/image_ihex_input.c:90 #, c-format msgid "%s: %s contains range 0x%04 to 0x%04\n" msgstr "%s: %s umfasst den Bereich 0x%04 bis 0x%04\n" -#: src/image_ihex_input.c:91 src/image_raw.c:181 +#: src/image_ihex_input.c:118 src/image_ihex_input.c:160 src/image_raw.c:210 #, c-format -msgid "Image file \"%s\" is too small, %zu of %zu bytes missing\n" -msgstr "Abbilddatei \"%s\" ist zu klein, %zu von %zu Byte fehlen\n" +msgid "Could not allocate memory for image data: %s\n" +msgstr "Konnte keinen Speicher für Abbilddaten zuweisen: %s\n" -#: src/image_ihex_input.c:99 src/image_ihex_input.c:104 +#: src/image_ihex_input.c:123 src/image_ihex_input.c:165 #, c-format msgid "Could not copy data from Intel Hex file \"%s\" (%s)\n" msgstr "Konnte keine Daten aus der Intel-Hex-Datei \"%s\" kopieren (%s)\n" +#: src/image_ihex_input.c:152 src/image_raw.c:247 +#, c-format +msgid "Image file \"%s\" is too small, %zu of %zu bytes missing\n" +msgstr "Abbilddatei \"%s\" ist zu klein, %zu von %zu Byte fehlen\n" + #: src/image_ihex_output.c:104 #, c-format msgid "%s: Record len=%zu source=%p rest=%zu USBA=%\n" @@ -184,46 +189,54 @@ msgid "Failed to read %s (%zu bytes) from file offset %zu to %p (%s)\n" msgstr "" "Fehler beim Lesen von %s (%zu Byte) von Dateiposition %zu nach %p (%s)\n" -#: src/image_raw.c:190 +#: src/image_raw.c:217 +#, c-format +msgid "Failed to read %zu bytes from file \"%s\" at offset %zu (%s)\n" +msgstr "" +"Fehler beim Lesen von %zu Byte aus Datei \"%s\" von Position %zu (%s)\n" + +#: src/image_raw.c:256 #, c-format msgid "%s: mmap() failed (%s)\n" msgstr "%s: mmap() fehlgeschlagen (%s)\n" -#: src/image_raw.c:225 +#: src/image_raw.c:290 #, c-format msgid "Cannot resize image file \"%s\" to %zu bytes (%s)\n" msgstr "Abbilddatei \"%s\" kann nicht auf %zu Bytes vergrößert werden (%s)\n" -#: src/image_raw.c:233 +#: src/image_raw.c:298 #, c-format msgid "Cannot write image file \"%s\" (%s)\n" msgstr "Abbilddatei \"%s\" kann nicht geschrieben werden (%s)\n" -#: src/options.c:62 +#: src/options_elf-mangle.c:62 src/options_lpstrings.c:54 msgid "Input / output options:" msgstr "Ein- / Ausgabeoptionen:" -#: src/options.c:63 +#: src/options_elf-mangle.c:63 msgid "SECTION" msgstr "SEKTION" -#: src/options.c:64 +#: src/options_elf-mangle.c:64 msgid "Use SECTION from ELF file instead of the default (" msgstr "Benutze SEKTION aus der ELF-Datei anstatt der Standardsektion (" -#: src/options.c:66 src/options.c:77 +#: src/options_elf-mangle.c:66 src/options_elf-mangle.c:77 +#: src/options_lpstrings.c:82 msgid "FILE" msgstr "DATEI" -#: src/options.c:67 +#: src/options_elf-mangle.c:67 msgid "Read binary input data from image FILE" msgstr "Lese Eingabe-Binärdaten aus der Abbild-DATEI" -#: src/options.c:70 src/options.c:81 src/options.c:92 +#: src/options_elf-mangle.c:70 src/options_elf-mangle.c:81 +#: src/options_elf-mangle.c:92 src/options_lpstrings.c:55 msgid "FORMAT" msgstr "FORMAT" -#: src/options.c:71 +#: src/options_elf-mangle.c:71 src/options_lpstrings.c:56 msgid "" "Format of input image file. FORMAT can be either \"raw\", \"ihex\" or \"auto" "\" (default)" @@ -231,11 +244,11 @@ msgstr "" "Format der Eingabe-Abbilddatei. Unterstützte FORMATe: \"raw\", \"ihex\" " "oder \"auto\" (standard)" -#: src/options.c:78 +#: src/options_elf-mangle.c:78 msgid "Write binary data to output image FILE" msgstr "Binärdaten in Ausgabe-Abbilddatei DATEI schreiben" -#: src/options.c:82 +#: src/options_elf-mangle.c:82 msgid "" "Format of output image file. FORMAT can be either \"raw\" or \"ihex" "\" (default)" @@ -243,11 +256,11 @@ msgstr "" "Format der Ausgabe-Abbilddatei. Unterstützte FORMATe: \"raw\" oder \"ihex" "\" (standard)" -#: src/options.c:84 +#: src/options_elf-mangle.c:84 msgid "FIELD=BYTES,..." msgstr "FELD=BYTES,..." -#: src/options.c:85 +#: src/options_elf-mangle.c:85 msgid "" "Override the given fields' values (comma-separated pairs).\n" "Each FIELD symbol name must be followed by an equal sign and the data BYTES " @@ -259,38 +272,38 @@ msgstr "" "Hexadezimal-Kodierung stehen. Nicht spezifizierte Bytes bleiben " "unverändert, zu viele führen zum Fehler." -#: src/options.c:91 +#: src/options_elf-mangle.c:91 src/options_lpstrings.c:68 msgid "Display information from parsed files:" msgstr "Information aus analysierten Dateien auflisten:" -#: src/options.c:93 +#: src/options_elf-mangle.c:93 msgid "" "Print field values. FORMAT can be either \"pretty\" (default) or \"hex\"" msgstr "" "Werte der Felder ausgeben. Unterstützte FORMATe: \"pretty\" (standard) oder " "\"hex\"" -#: src/options.c:96 +#: src/options_elf-mangle.c:96 msgid "Print symbol address for each field" msgstr "Symboladresse für jedes Feld ausgeben" -#: src/options.c:98 +#: src/options_elf-mangle.c:98 msgid "Show object symbol names instead of field decriptions" msgstr "Symbolnamen anstatt Feldbeschreibungen anzeigen" -#: src/options.c:100 +#: src/options_elf-mangle.c:100 msgid "Print size in bytes for each field" msgstr "Größe in Byte für jedes Feld ausgeben" -#: src/options.c:102 +#: src/options_elf-mangle.c:102 msgid "Print size in bytes for the whole image" msgstr "Größe in Byte für das gesamte Abbild ausgeben" -#: src/options.c:103 +#: src/options_elf-mangle.c:103 src/options_lpstrings.c:62 msgid "MIN-LEN" msgstr "ANZAHL" -#: src/options.c:104 +#: src/options_elf-mangle.c:104 src/options_lpstrings.c:63 #, fuzzy msgid "" "Locate strings of at least MIN-LEN bytes in input (argument defaults to " @@ -298,42 +311,77 @@ msgstr "" "Zeichenketten mit mindestens ANZAHL Byte in Eingabe suchen (falls nicht " "angegeben " -#: src/options.c:113 +#: src/options_elf-mangle.c:113 msgid "IN_MAP [OUT_MAP]" msgstr "EINGABE_ELF [AUSGABE_ELF]" -#: src/options.c:117 +#: src/options_elf-mangle.c:117 msgid "" "Analyze, transform and manipulate binary data based on ELF symbol tables." msgstr "" "Analyse, Umwandlung und Manipulation von Binärdaten anhand von ELF-" "Symboltabellen." -#: src/options.c:164 src/options.c:171 +#: src/options_elf-mangle.c:164 src/options_elf-mangle.c:171 +#: src/options_lpstrings.c:121 #, c-format msgid "Invalid binary image format `%s' specified." msgstr "Ungültiges Format '%s' für Binärabbild angegeben." -#: src/options.c:182 +#: src/options_elf-mangle.c:182 src/options_lpstrings.c:128 #, c-format msgid "Minimum string length %d out of range." msgstr "Minimale Zeichenkettenlänge %d außerhalb des gültigen Bereichs." -#: src/options.c:191 +#: src/options_elf-mangle.c:191 #, c-format msgid "Unknown print format `%s' specified." msgstr "Unbekanntes Ausgabeformat '%s' angegeben." -#: src/options.c:213 +#: src/options_elf-mangle.c:213 #, c-format msgid "Too many map file arguments." msgstr "Zu viele Dateien für Symbolzuordnung." -#: src/options.c:218 +#: src/options_elf-mangle.c:218 src/options_lpstrings.c:159 #, c-format msgid "Missing file name." msgstr "Dateiname fehlt." +#: src/options_lpstrings.c:70 +msgid "Print length in bytes for each string" +msgstr "Länge in Byte für jede Zeichenkette ausgeben" + +#: src/options_lpstrings.c:71 +msgid "SEP" +msgstr "TRENNER" + +#: src/options_lpstrings.c:72 +msgid "Separator between strings in output." +msgstr "Trennzeichen für die Ausgabe der Zeichenketten." + +#: src/options_lpstrings.c:74 +msgid "Print the location of the string in base 8, 10 or 16 (default)" +msgstr "" +"Fundstelle der Zeichenkette mit Basis 8, 10 oder 16 (standard) ausgeben" + +#: src/options_lpstrings.c:86 +msgid "" +"Locate length-prefixed strings of printable characters plus NUL terminator." +msgstr "" +"Suche Zeichenketten aus druckbaren Zeichen mit Längenangabe und NUL-" +"Abschluss." + +#: src/options_lpstrings.c:149 +#, c-format +msgid "Invalid offset radix `%s' specified." +msgstr "Ungültige Basis '%s' für Adressabstand angegeben." + +#: src/options_lpstrings.c:154 +#, c-format +msgid "Too many input file arguments." +msgstr "Zu viele Dateien als Eingabe." + #: src/override.c:74 #, c-format msgid "%s: Override directive truncated during append.\n" @@ -382,6 +430,11 @@ msgstr "Feld nicht gefunden" msgid "Unable to parse override `%.*s' (%s)\n" msgstr "Kann Zuweisung '%.*s' nicht parsen (%s)\n" +#: src/print_symbols.c:64 +#, c-format +msgid " %zu bytes" +msgstr " %zu Byte" + #: src/symbol_map.c:91 #, c-format msgid "Could not access section header string table: %s\n" From f1b21227fa733cd59c04b200a40fa923b4f17350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Thu, 3 Nov 2016 11:07:18 +0100 Subject: [PATCH 23/23] Fix autoconf warnings. Move AM_PROG_AR and LT_INIT macros after gl_EARLY invocation, as advised by autoconf. --- configure.ac | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 62ec525..43af0ec 100644 --- a/configure.ac +++ b/configure.ac @@ -27,8 +27,6 @@ AM_INIT_AUTOMAKE([foreign -Wall -Werror]) # Checks for programs. AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC_C99 -AM_PROG_AR -LT_INIT # Use GNU Gnulib if required macros are present m4_ifdef([gl_EARLY], @@ -36,6 +34,10 @@ m4_ifdef([gl_EARLY], gnulib=1], [gnulib=0]) AM_CONDITIONAL([USE_GNULIB], [test "x$gnulib" = x1]) +# More checks for programs. +AM_PROG_AR +LT_INIT + # Checks for libraries. m4_ifdef([gl_INIT], [gl_INIT])