Compare commits
	
		
			28 Commits
		
	
	
		
			v0.1.0
			...
			f964ef7b60
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f964ef7b60 | |||
| dd05449f36 | |||
| 3ff626134e | |||
| 29fdc841b7 | |||
| dc30188593 | |||
| 2bea5d288c | |||
| 8a0226a5ea | |||
| ed6373473c | |||
| 80b5f5b1b3 | |||
| 4fab6ffd3a | |||
| 0ee19eaea4 | |||
| 26eb480343 | |||
| 30e47d533a | |||
| faeab33375 | |||
| 7e414f8576 | |||
| 933680c80d | |||
| 891df1803e | |||
| 7be1d6a967 | |||
| e8a8abbe65 | |||
| 71b1ad2a32 | |||
| cf7d0c22f7 | |||
| 6f40e37e81 | |||
| 84c60fc461 | |||
| b47828014e | |||
| 2c7ce64722 | |||
| dc85955859 | |||
| 5ec8d8d90b | |||
| e33c48618b | 
							
								
								
									
										2
									
								
								3rdparty/libfort
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								3rdparty/libfort
									
									
									
									
										vendored
									
									
								
							 Submodule 3rdparty/libfort updated: 41237162a9...5a8f9312bd
									
								
							@@ -1,14 +1,14 @@
 | 
				
			|||||||
# Maintainer: Mario Hüttel <mario (dot) huettel (!) gmx (dot) net>
 | 
					# Maintainer: Mario Hüttel <mario (dot) huettel (!) gmx (dot) net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pkgname=patchelfcrc
 | 
					pkgname=patchelfcrc
 | 
				
			||||||
pkgver=5e7f697
 | 
					pkgver=v1.0.0_rc1
 | 
				
			||||||
pkgrel=1
 | 
					pkgrel=1
 | 
				
			||||||
pkgdesc="Tool for patching CRC checksums of sections into ELF binaries"
 | 
					pkgdesc="Tool for patching CRC checksums of sections into ELF binaries"
 | 
				
			||||||
arch=('i686' 'x86_64')
 | 
					arch=('i686' 'x86_64')
 | 
				
			||||||
url="https://git.shimatta.de/mhu/patchelfcrc"
 | 
					url="https://git.shimatta.de/mhu/patchelfcrc"
 | 
				
			||||||
licence=('GPLv2')
 | 
					licence=('GPLv2')
 | 
				
			||||||
depends=('libelf' 'libxml2')
 | 
					depends=('libelf' 'libxml2')
 | 
				
			||||||
makedepends=('cmake' 'pandoc' 'git' 'gvim')
 | 
					makedepends=('cmake' 'pandoc' 'git' 'gvim' 'bash')
 | 
				
			||||||
provides=('patchelfcrc')
 | 
					provides=('patchelfcrc')
 | 
				
			||||||
source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/patchelfcrc" "git+https://git.shimatta.de/3rd-party/libfort.git" "git+https://git.shimatta.de/mhu/linklist-lib")
 | 
					source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/patchelfcrc" "git+https://git.shimatta.de/3rd-party/libfort.git" "git+https://git.shimatta.de/mhu/linklist-lib")
 | 
				
			||||||
sha1sums=('SKIP' 'SKIP' 'SKIP')
 | 
					sha1sums=('SKIP' 'SKIP' 'SKIP')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,12 +28,23 @@ pkg_check_modules(ELF REQUIRED libelf)
 | 
				
			|||||||
find_package(Doxygen)
 | 
					find_package(Doxygen)
 | 
				
			||||||
find_package(LibXml2 REQUIRED)
 | 
					find_package(LibXml2 REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(man)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
aux_source_directory("src" CFILES)
 | 
					aux_source_directory("src" CFILES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated")
 | 
					set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (DEFINED NO_VERSION_INFO)
 | 
				
			||||||
 | 
					add_custom_target(
 | 
				
			||||||
 | 
							version-header
 | 
				
			||||||
 | 
						COMMAND
 | 
				
			||||||
 | 
							 mkdir -p ${GEN_HEADER_PATH} && bash "${CMAKE_CURRENT_SOURCE_DIR}/gen_version_header.sh" "${GEN_HEADER_PATH}/version.h" "dummy"
 | 
				
			||||||
 | 
					        WORKING_DIRECTORY
 | 
				
			||||||
 | 
					                ${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
 | 
					        COMMENT "Generating version header dummy"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						set (NO_VERSION_INFO true)
 | 
				
			||||||
 | 
						message("${BoldMagenta}No Version Information will be built${ColorReset}")
 | 
				
			||||||
 | 
					else(DEFINED NO_VERSION_INFO)
 | 
				
			||||||
add_custom_target(
 | 
					add_custom_target(
 | 
				
			||||||
		version-header
 | 
							version-header
 | 
				
			||||||
	COMMAND
 | 
						COMMAND
 | 
				
			||||||
@@ -42,6 +53,8 @@ add_custom_target(
 | 
				
			|||||||
		${CMAKE_CURRENT_SOURCE_DIR}
 | 
							${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
	COMMENT "Generating version header"
 | 
						COMMENT "Generating version header"
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
						add_subdirectory(man)
 | 
				
			||||||
 | 
					endif(DEFINED NO_VERSION_INFO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_custom_target(schema-header DEPENDS "${GEN_HEADER_PATH}/schema-blob.h")
 | 
					add_custom_target(schema-header DEPENDS "${GEN_HEADER_PATH}/schema-blob.h")
 | 
				
			||||||
add_custom_command(
 | 
					add_custom_command(
 | 
				
			||||||
@@ -66,9 +79,10 @@ target_link_directories(${PROJECT_NAME} PRIVATE ${ELF_LIBRARY_DIRS} ${LIBXML2_LI
 | 
				
			|||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${ELF_INCLUDE_DIRS})
 | 
					target_include_directories(${PROJECT_NAME} PRIVATE ${ELF_INCLUDE_DIRS})
 | 
				
			||||||
target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include")
 | 
					target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include")
 | 
				
			||||||
target_include_directories(${PROJECT_NAME} PRIVATE "include")
 | 
					target_include_directories(${PROJECT_NAME} PRIVATE "include")
 | 
				
			||||||
add_dependencies(${PROJECT_NAME} version-header schema-header)
 | 
					add_dependencies(${PROJECT_NAME} schema-header)
 | 
				
			||||||
 | 
					add_dependencies(${PROJECT_NAME} version-header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (DOXYGEN_FOUND)
 | 
					if (DOXYGEN_FOUND AND (NOT (DEFINED NO_VERSION_INFO)))
 | 
				
			||||||
	set(DOXYFILE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Doxyfile.in")
 | 
						set(DOXYFILE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Doxyfile.in")
 | 
				
			||||||
	set(DOXYFILE_DEST "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
 | 
						set(DOXYFILE_DEST "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
 | 
				
			||||||
	configure_file(${DOXYFILE_SRC} ${DOXYFILE_DEST} @ONLY)
 | 
						configure_file(${DOXYFILE_SRC} ${DOXYFILE_DEST} @ONLY)
 | 
				
			||||||
@@ -87,7 +101,7 @@ if (DOXYGEN_FOUND)
 | 
				
			|||||||
		WORKING_DIRECTORY
 | 
							WORKING_DIRECTORY
 | 
				
			||||||
			${CMAKE_CURRENT_SOURCE_DIR}
 | 
								${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
else (DOXYGEN_FOUND)
 | 
					else  (DOXYGEN_FOUND AND (NOT (DEFINED NO_VERSION_INFO)))
 | 
				
			||||||
	message("${BoldMagenta}Doxygen needs to be installed to generate the doxygen documentation${ColorReset}")
 | 
						message("${BoldMagenta}Doxygen needs to be installed to generate the doxygen documentation${ColorReset}")
 | 
				
			||||||
	message("${BoldMagenta}doxygen target will not be available${ColorReset}")
 | 
						message("${BoldMagenta}doxygen target will not be available${ColorReset}")
 | 
				
			||||||
endif (DOXYGEN_FOUND)
 | 
					endif  (DOXYGEN_FOUND AND (NOT (DEFINED NO_VERSION_INFO)))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,12 @@ if [[ -z $1 ]]; then
 | 
				
			|||||||
	exit -1;
 | 
						exit -1;
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ver=`git describe --tags --always --dirty`
 | 
					if [[ "$2" == "dummy" ]]; then
 | 
				
			||||||
 | 
						ver="v0.0.0-undefined"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						ver=`git describe --tags --always --dirty`
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "#ifndef _VERSION_GENERATED_H_" > $1
 | 
					echo "#ifndef _VERSION_GENERATED_H_" > $1
 | 
				
			||||||
echo "#define _VERSION_GENERATED_H_" >> $1
 | 
					echo "#define _VERSION_GENERATED_H_" >> $1
 | 
				
			||||||
echo "#define GIT_VERSION_STRING \"$ver\"" >> $1
 | 
					echo "#define GIT_VERSION_STRING \"$ver\"" >> $1
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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_ */
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule linklist-lib updated: c20b5c2528...fdd99bad48
									
								
							@@ -10,10 +10,10 @@ add_custom_command(
 | 
				
			|||||||
	OUTPUT
 | 
						OUTPUT
 | 
				
			||||||
		${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE_NAME}
 | 
							${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE_NAME}
 | 
				
			||||||
	COMMAND
 | 
						COMMAND
 | 
				
			||||||
		bash -c "pandoc \"${CMAKE_CURRENT_SOURCE_DIR}/patchelfcrc.1.md\" -s -t man | gzip > \"${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE_NAME}\""
 | 
							bash -c "cat \"${CMAKE_CURRENT_SOURCE_DIR}/patchelfcrc.1.md\" | sed \"s/!version!/`git describe --tags --always --dirty`/\" | pandoc  -s -t man | gzip > \"${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE_NAME}\""
 | 
				
			||||||
	VERBATIM
 | 
						VERBATIM
 | 
				
			||||||
	WORKING_DIRECTORY
 | 
						WORKING_DIRECTORY
 | 
				
			||||||
		${CMAKE_CURRENT_BINARY_DIR}
 | 
							${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
	MAIN_DEPENDENCY
 | 
						MAIN_DEPENDENCY
 | 
				
			||||||
		${CMAKE_CURRENT_SOURCE_DIR}/patchelfcrc.1.md
 | 
							${CMAKE_CURRENT_SOURCE_DIR}/patchelfcrc.1.md
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
% patchelfcrc(1) 0.0.2
 | 
					% patchelfcrc(1) !version!
 | 
				
			||||||
% Mario Huettel
 | 
					% Mario Huettel
 | 
				
			||||||
% October 2022
 | 
					% October 2022
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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,9 +134,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
**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
 | 
				
			||||||
Currently, reversed CRC algorithms are not implemented.
 | 
					None
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										71
									
								
								src/crc.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								src/crc.c
									
									
									
									
									
								
							@@ -34,13 +34,26 @@ int crc_len_from_poly(uint64_t polynomial)
 | 
				
			|||||||
	return pos;
 | 
						return pos;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t reverse_short_poly(uint32_t poly, uint8_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t i;
 | 
				
			||||||
 | 
						uint32_t ret = 0ul;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < len; i++) {
 | 
				
			||||||
 | 
							ret <<= 1;
 | 
				
			||||||
 | 
							ret |= (poly & 1u);
 | 
				
			||||||
 | 
							poly >>= 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t shorten_polynomial(uint64_t poly)
 | 
					static uint64_t shorten_polynomial(uint64_t poly)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 32; i >= 0; i--) {
 | 
				
			||||||
	for (i = 31; i <= 0; i--) {
 | 
							if (poly & ((uint64_t)1ull << i)) {
 | 
				
			||||||
		if (poly & (1 << i)) {
 | 
								poly &= ~((uint64_t)1ull<<i);
 | 
				
			||||||
			poly &= ~(1<<i);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -55,14 +68,22 @@ static void internal_push_byte(struct crc_calc *crc, const uint8_t *data, size_t
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	crc_val = crc->crc_val;
 | 
						crc_val = crc->crc_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < len; i++, data++) {
 | 
						if (crc->settings.rev) {
 | 
				
			||||||
		crc_val = ((crc_val << 8) & crc->crc_mask) ^ crc->table[((crc_val >> (crc->crc_length-8u)) & 0xff) ^ *data];
 | 
							for (i = 0; i < len; i++, data++) {
 | 
				
			||||||
 | 
								crc_val = (crc_val >> 8) ^ crc->table[((crc_val & 0xFF) ^ *data)];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Non reversed algo */
 | 
				
			||||||
 | 
							for (i = 0; i < len; i++, data++) {
 | 
				
			||||||
 | 
								crc_val = ((crc_val << 8) & crc->crc_mask) ^
 | 
				
			||||||
 | 
									crc->table[((crc_val >> (crc->crc_length-8u)) & 0xff) ^ *data];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	crc->crc_val = crc_val;
 | 
						crc->crc_val = crc_val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fill_crc_table(struct crc_calc *crc)
 | 
					static void fill_crc_table_non_reversed(struct crc_calc *crc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t input;
 | 
						uint32_t input;
 | 
				
			||||||
	uint32_t crc_reg;
 | 
						uint32_t crc_reg;
 | 
				
			||||||
@@ -86,10 +107,44 @@ static void fill_crc_table(struct crc_calc *crc)
 | 
				
			|||||||
				crc_reg <<= 1;
 | 
									crc_reg <<= 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		crc->table[input] = crc_reg;
 | 
							crc->table[input] = crc_reg & crc->crc_mask;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fill_crc_table_reversed(struct crc_calc *crc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t input;
 | 
				
			||||||
 | 
						uint32_t crc_reg;
 | 
				
			||||||
 | 
						uint32_t short_poly;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						short_poly = (uint32_t)shorten_polynomial(crc->settings.polynomial);
 | 
				
			||||||
 | 
						short_poly = reverse_short_poly(short_poly, crc->crc_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (input = 0; input <= 255u; input++) {
 | 
				
			||||||
 | 
							crc_reg = (uint32_t)input;
 | 
				
			||||||
 | 
							for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
								/* Check LSB for reversed CRC shifting */
 | 
				
			||||||
 | 
								if (crc_reg & 1u) {
 | 
				
			||||||
 | 
									crc_reg >>= 1;
 | 
				
			||||||
 | 
									crc_reg ^= short_poly;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									crc_reg >>= 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							crc->table[input] = crc_reg & crc->crc_mask;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fill_crc_table(struct crc_calc *crc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (crc->settings.rev)
 | 
				
			||||||
 | 
							fill_crc_table_reversed(crc);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							fill_crc_table_non_reversed(crc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void crc_init(struct crc_calc *crc, const struct crc_settings *settings)
 | 
					void crc_init(struct crc_calc *crc, const struct crc_settings *settings)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										170
									
								
								src/elfpatch.c
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								src/elfpatch.c
									
									
									
									
									
								
							@@ -30,6 +30,19 @@
 | 
				
			|||||||
#include <fort.h>
 | 
					#include <fort.h>
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
#include <patchelfcrc/crc-output-struct.h>
 | 
					#include <patchelfcrc/crc-output-struct.h>
 | 
				
			||||||
 | 
					#include <byteswap.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const union  {
 | 
				
			||||||
 | 
						uint8_t data[4];
 | 
				
			||||||
 | 
						uint32_t val;
 | 
				
			||||||
 | 
					} _endianess_check_union = {{1u, 2u, 3u, 4u}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum endianess {
 | 
				
			||||||
 | 
						END_LITTLE = 0x04030201ul,
 | 
				
			||||||
 | 
						END_BIG = 0x01020304ul,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HOST_ENDIANESS (_endianess_check_union.val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct elf_section {
 | 
					struct elf_section {
 | 
				
			||||||
	GElf_Shdr section_header;
 | 
						GElf_Shdr section_header;
 | 
				
			||||||
@@ -55,16 +68,16 @@ struct elfpatch {
 | 
				
			|||||||
#define is_elfpatch_struct(x) ((x) && (x)->magic == (ELFPATCH_MAGIC))
 | 
					#define is_elfpatch_struct(x) ((x) && (x)->magic == (ELFPATCH_MAGIC))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ret_if_ep_err(ep) do { \
 | 
					#define ret_if_ep_err(ep) do { \
 | 
				
			||||||
	if (!is_elfpatch_struct((ep))) { \
 | 
							if (!is_elfpatch_struct((ep))) { \
 | 
				
			||||||
	return; \
 | 
								return; \
 | 
				
			||||||
	} \
 | 
							} \
 | 
				
			||||||
	} while(0)
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ret_val_if_ep_err(ep, val) do { \
 | 
					#define ret_val_if_ep_err(ep, val) do { \
 | 
				
			||||||
	if (!is_elfpatch_struct((ep))) { \
 | 
							if (!is_elfpatch_struct((ep))) { \
 | 
				
			||||||
	return (val); \
 | 
								return val; \
 | 
				
			||||||
	} \
 | 
							} \
 | 
				
			||||||
	} while(0)
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Convert a series of 4 bytes into a uint32_t dpending on endianess
 | 
					 * @brief Convert a series of 4 bytes into a uint32_t dpending on endianess
 | 
				
			||||||
@@ -77,15 +90,16 @@ static uint32_t get_uint32_from_byte_string(const uint8_t *data, bool little_end
 | 
				
			|||||||
	uint32_t out = 0ul;
 | 
						uint32_t out = 0ul;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Always shift in in big endian format */
 | 
				
			||||||
	for (i = 0; i < 4; i++) {
 | 
						for (i = 0; i < 4; i++) {
 | 
				
			||||||
		if (little_endian)
 | 
					 | 
				
			||||||
			out >>= 8u;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			out <<= 8u;
 | 
								out <<= 8u;
 | 
				
			||||||
 | 
							out |= (uint32_t)data[i];
 | 
				
			||||||
		out |= (((uint32_t)data[i]) << (little_endian ? 24u : 0u));
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Swap bytes if little endian */
 | 
				
			||||||
 | 
						if (little_endian)
 | 
				
			||||||
 | 
							out = bswap_32(out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return out;
 | 
						return out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,14 +110,12 @@ static void write_crc_to_byte_array(uint8_t *byte_array, uint32_t crc, uint8_t c
 | 
				
			|||||||
	if (!byte_array)
 | 
						if (!byte_array)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!little_endian)
 | 
				
			||||||
 | 
							crc = bswap_32(crc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < crc_size_bytes; i++) {
 | 
						for (i = 0; i < crc_size_bytes; i++) {
 | 
				
			||||||
		if (little_endian) {
 | 
							byte_array[i] = (uint8_t)(crc & 0xFFul);
 | 
				
			||||||
			byte_array[i] = (uint8_t)(crc & 0xFFul);
 | 
							crc >>= 8u;
 | 
				
			||||||
			crc >>= 8u;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			byte_array[i] = (uint8_t)((crc & 0xFF000000ul) >> 24u);
 | 
					 | 
				
			||||||
			crc <<= 8u;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -136,6 +148,14 @@ static const char *section_type_to_str(Elf64_Word type)
 | 
				
			|||||||
		return "INIT_ARRAY";
 | 
							return "INIT_ARRAY";
 | 
				
			||||||
	case SHT_FINI_ARRAY:
 | 
						case SHT_FINI_ARRAY:
 | 
				
			||||||
		return "FINI_ARRAY";
 | 
							return "FINI_ARRAY";
 | 
				
			||||||
 | 
						case SHT_PREINIT_ARRAY:
 | 
				
			||||||
 | 
							return "PREINIT_ARRAY";
 | 
				
			||||||
 | 
						case SHT_DYNAMIC:
 | 
				
			||||||
 | 
							return "DYNAMIC";
 | 
				
			||||||
 | 
						case SHT_ARM_ATTRIBUTES:
 | 
				
			||||||
 | 
							return "ARM_ATTRIBUTES";
 | 
				
			||||||
 | 
						case SHT_ARM_PREEMPTMAP:
 | 
				
			||||||
 | 
							return "ARM_PREEMPTMAP";
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -147,6 +167,7 @@ static void print_sections(elfpatch_handle_t *ep)
 | 
				
			|||||||
	SlList *iter;
 | 
						SlList *iter;
 | 
				
			||||||
	ft_table_t *table;
 | 
						ft_table_t *table;
 | 
				
			||||||
	const struct elf_section *section;
 | 
						const struct elf_section *section;
 | 
				
			||||||
 | 
						bool alloc, write, exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret_if_ep_err(ep);
 | 
						ret_if_ep_err(ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,15 +183,23 @@ static void print_sections(elfpatch_handle_t *ep)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Write header */
 | 
						/* Write header */
 | 
				
			||||||
	ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
 | 
						ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
 | 
				
			||||||
	ft_write_ln(table, "Section", "Type", "Size", "VMA", "LMA", "File Offset");
 | 
						ft_write_ln(table, "Section", "Type", "ALLOC", "WRITE", "EXEC", "Size", "VMA", "LMA", "File Offset");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (iter = ep->sections; iter; iter = sl_list_next(iter)) {
 | 
						for (iter = ep->sections; iter; iter = sl_list_next(iter)) {
 | 
				
			||||||
		section = (const struct elf_section *)iter->data;
 | 
							section = (const struct elf_section *)iter->data;
 | 
				
			||||||
		if (!section)
 | 
							if (!section)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		ft_printf_ln(table, "%s|%s|%lu|%p|%p|%p",
 | 
					
 | 
				
			||||||
 | 
							alloc = !!(section->section_header.sh_flags & SHF_ALLOC);
 | 
				
			||||||
 | 
							write = !!(section->section_header.sh_flags & SHF_WRITE);
 | 
				
			||||||
 | 
							exec = !!(section->section_header.sh_flags & SHF_EXECINSTR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ft_printf_ln(table, "%s|%s|%s|%s|%s|%lu|%p|%p|%p",
 | 
				
			||||||
			     section->name,
 | 
								     section->name,
 | 
				
			||||||
			     section_type_to_str(section->section_header.sh_type),
 | 
								     section_type_to_str(section->section_header.sh_type),
 | 
				
			||||||
 | 
								     alloc ? "x" : "",
 | 
				
			||||||
 | 
								     write ? "x" : "",
 | 
				
			||||||
 | 
								     exec ? "x" : "",
 | 
				
			||||||
			     section->section_header.sh_size,
 | 
								     section->section_header.sh_size,
 | 
				
			||||||
			     (void *)section->section_header.sh_addr,
 | 
								     (void *)section->section_header.sh_addr,
 | 
				
			||||||
			     (void *)section->lma,
 | 
								     (void *)section->lma,
 | 
				
			||||||
@@ -197,7 +226,7 @@ static SlList *elf_patch_get_sections(elfpatch_handle_t *ep)
 | 
				
			|||||||
		sl_list_free_full(ret, (void (*)(void *))free_elf_section_element);
 | 
							sl_list_free_full(ret, (void (*)(void *))free_elf_section_element);
 | 
				
			||||||
	ep->sections = NULL;
 | 
						ep->sections = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (elf_getshdrstrndx (ep->elf , &shstrndx) != 0) {
 | 
						if (elf_getshdrstrndx(ep->elf, &shstrndx) != 0) {
 | 
				
			||||||
		print_err("ELF error: %s\n", elf_errmsg(-1));
 | 
							print_err("ELF error: %s\n", elf_errmsg(-1));
 | 
				
			||||||
		goto ret_free_section_list;
 | 
							goto ret_free_section_list;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -218,9 +247,10 @@ static SlList *elf_patch_get_sections(elfpatch_handle_t *ep)
 | 
				
			|||||||
		sec->lma = (uint64_t)sec->section_header.sh_addr;
 | 
							sec->lma = (uint64_t)sec->section_header.sh_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		name = elf_strptr(ep->elf, shstrndx, sec->section_header.sh_name);
 | 
							name = elf_strptr(ep->elf, shstrndx, sec->section_header.sh_name);
 | 
				
			||||||
		if (name) {
 | 
					
 | 
				
			||||||
 | 
							if (name)
 | 
				
			||||||
			sec->name = strdup(name);
 | 
								sec->name = strdup(name);
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		ret = sl_list_append(ret, sec);
 | 
							ret = sl_list_append(ret, sec);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -260,6 +290,12 @@ static int elf_patch_read_program_headers(elfpatch_handle_t *ep)
 | 
				
			|||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (header_count == 0) {
 | 
				
			||||||
 | 
							/* No program headers found. This ELF file is probably not linked */
 | 
				
			||||||
 | 
							ep->program_headers_count = 0;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ep->program_headers = (GElf_Phdr *)malloc(header_count * sizeof(GElf_Phdr));
 | 
						ep->program_headers = (GElf_Phdr *)malloc(header_count * sizeof(GElf_Phdr));
 | 
				
			||||||
	if (!ep->program_headers) {
 | 
						if (!ep->program_headers) {
 | 
				
			||||||
		/* Mem error. Abort. Program will crash eventually */
 | 
							/* Mem error. Abort. Program will crash eventually */
 | 
				
			||||||
@@ -305,9 +341,11 @@ static void resolve_section_lmas(elfpatch_handle_t *ep)
 | 
				
			|||||||
		if (!sec)
 | 
							if (!sec)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* By default each sections LMA is assumed to be its LMA as well */
 | 
				
			||||||
 | 
							sec->lma = (uint64_t)sec->section_header.sh_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sec->section_header.sh_type == SHT_NOBITS) {
 | 
							if (sec->section_header.sh_type == SHT_NOBITS) {
 | 
				
			||||||
			/* Section does not contain data. It may be allocated but is not loaded. Therefore, LMA=VMA. */
 | 
								/* Section does not contain data. It may be allocated but is not loaded. Therefore, LMA=VMA. */
 | 
				
			||||||
			sec->lma = (uint64_t)sec->section_header.sh_addr;
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -431,15 +469,13 @@ elfpatch_handle_t *elf_patch_open(const char *path, bool readonly, bool expect_l
 | 
				
			|||||||
		switch (ident[5]) {
 | 
							switch (ident[5]) {
 | 
				
			||||||
		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]);
 | 
				
			||||||
@@ -454,9 +490,8 @@ close_elf:
 | 
				
			|||||||
		ep->elf = NULL;
 | 
							ep->elf = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
close_fd:
 | 
					close_fd:
 | 
				
			||||||
	if (ep->fd > 0) {
 | 
						if (ep->fd > 0)
 | 
				
			||||||
		close(ep->fd);
 | 
							close(ep->fd);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
free_struct:
 | 
					free_struct:
 | 
				
			||||||
	free(ep);
 | 
						free(ep);
 | 
				
			||||||
	ep = NULL;
 | 
						ep = NULL;
 | 
				
			||||||
@@ -491,14 +526,14 @@ int elf_patch_check_for_section(elfpatch_handle_t *ep, const char *section)
 | 
				
			|||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t translate_index(size_t index, enum granularity granularity, bool little_endian)
 | 
					static size_t translate_index(size_t index, enum granularity granularity, bool little_endian, bool reversed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t word_idx;
 | 
						size_t word_idx;
 | 
				
			||||||
	size_t part_idx;
 | 
						size_t part_idx;
 | 
				
			||||||
	size_t d_index;
 | 
						size_t d_index;
 | 
				
			||||||
	size_t gran_in_bytes;
 | 
						size_t gran_in_bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!little_endian || granularity == GRANULARITY_BYTE)
 | 
						if ((!little_endian && !reversed) || (little_endian && reversed) || granularity == GRANULARITY_BYTE)
 | 
				
			||||||
		return index;
 | 
							return index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gran_in_bytes = (size_t)granularity / 8u;
 | 
						gran_in_bytes = (size_t)granularity / 8u;
 | 
				
			||||||
@@ -526,30 +561,30 @@ 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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If big endian or granularity is byte, simply compute CRC. No reordering is necessary */
 | 
						/* If big endian for non reversed / little endian for reversed or granularity is byte, simply compute CRC. No reordering is necessary */
 | 
				
			||||||
	if (!little_endian || granularity == GRANULARITY_BYTE) {
 | 
						if ((!little_endian && !crc->settings.rev) || (little_endian && crc->settings.rev) ||
 | 
				
			||||||
 | 
								granularity == GRANULARITY_BYTE) {
 | 
				
			||||||
		crc_push_bytes(crc, data->d_buf, data->d_size);
 | 
							crc_push_bytes(crc, data->d_buf, data->d_size);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/* Little endian case with > byte sized chunks */
 | 
							/* Little endian case with > byte sized chunks */
 | 
				
			||||||
@@ -557,18 +592,21 @@ 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);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (idx = 0; idx < data->d_size; idx++) {
 | 
							for (idx = 0; idx < data->d_size; idx++)
 | 
				
			||||||
			crc_push_byte(crc, ((char *)data->d_buf)[translate_index(idx, granularity, little_endian)]);
 | 
								crc_push_byte(crc,
 | 
				
			||||||
		}
 | 
									      ((char *)data->d_buf)[
 | 
				
			||||||
 | 
										translate_index(idx, granularity,
 | 
				
			||||||
 | 
											little_endian,
 | 
				
			||||||
 | 
											crc->settings.rev)
 | 
				
			||||||
 | 
										]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Pad with zeroes */
 | 
							/* Pad with zeroes */
 | 
				
			||||||
		for (idx = 0; idx < padding_count; idx++) {
 | 
							for (idx = 0; idx < padding_count; idx++)
 | 
				
			||||||
			crc_push_byte(crc, 0x00);
 | 
								crc_push_byte(crc, 0x00);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
@@ -594,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) {
 | 
				
			||||||
@@ -649,6 +687,7 @@ int elf_patch_write_crcs_to_section(elfpatch_handle_t *ep, const char *output_se
 | 
				
			|||||||
	struct crc_out_struct_32bit crc_32bit;
 | 
						struct crc_out_struct_32bit crc_32bit;
 | 
				
			||||||
	struct crc_out_struct_64bit crc_64bit;
 | 
						struct crc_out_struct_64bit crc_64bit;
 | 
				
			||||||
	uint64_t in_sec_addr, in_sec_len;
 | 
						uint64_t in_sec_addr, in_sec_len;
 | 
				
			||||||
 | 
						bool needs_byteswap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret_val_if_ep_err(ep, -1000);
 | 
						ret_val_if_ep_err(ep, -1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -711,8 +750,8 @@ int elf_patch_write_crcs_to_section(elfpatch_handle_t *ep, const char *output_se
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	print_debug("Single CRC requires %u bytes.\n", (unsigned int)crc_size_bytes);
 | 
						print_debug("Single CRC requires %u bytes.\n", (unsigned int)crc_size_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	needed_space = calculate_needed_space_for_crcs(format, crc_data->elf_bits, check_start_magic, check_end_magic, crc_size_bytes,
 | 
						needed_space = calculate_needed_space_for_crcs(format, crc_data->elf_bits, check_start_magic,
 | 
				
			||||||
						       crc_count);
 | 
							check_end_magic, crc_size_bytes, crc_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print_debug("Required space for %zu CRCs%s: %zu (available: %zu)\n",
 | 
						print_debug("Required space for %zu CRCs%s: %zu (available: %zu)\n",
 | 
				
			||||||
		    crc_count,
 | 
							    crc_count,
 | 
				
			||||||
@@ -746,6 +785,12 @@ int elf_patch_write_crcs_to_section(elfpatch_handle_t *ep, const char *output_se
 | 
				
			|||||||
		if (check_start_magic && crc_data->elf_bits == 64)
 | 
							if (check_start_magic && crc_data->elf_bits == 64)
 | 
				
			||||||
			sec_bytes += 4u;
 | 
								sec_bytes += 4u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							needs_byteswap = false;
 | 
				
			||||||
 | 
							if ((HOST_ENDIANESS != END_LITTLE && little_endian) ||
 | 
				
			||||||
 | 
									(HOST_ENDIANESS == END_LITTLE && !little_endian)) {
 | 
				
			||||||
 | 
								needs_byteswap = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (iter = crc_data->crc_entries, idx = 0; iter; iter = sl_list_next(iter), idx++) {
 | 
							for (iter = crc_data->crc_entries, idx = 0; iter; iter = sl_list_next(iter), idx++) {
 | 
				
			||||||
			crc_entry = (struct crc_entry *)iter->data;
 | 
								crc_entry = (struct crc_entry *)iter->data;
 | 
				
			||||||
			in_sec_addr = use_vma ? crc_entry->vma : crc_entry->lma;
 | 
								in_sec_addr = use_vma ? crc_entry->vma : crc_entry->lma;
 | 
				
			||||||
@@ -756,18 +801,19 @@ int elf_patch_write_crcs_to_section(elfpatch_handle_t *ep, const char *output_se
 | 
				
			|||||||
			print_debug("Corresponding input section at 0x%"PRIx64", length: %"PRIu64"\n",
 | 
								print_debug("Corresponding input section at 0x%"PRIx64", length: %"PRIu64"\n",
 | 
				
			||||||
				    in_sec_addr,
 | 
									    in_sec_addr,
 | 
				
			||||||
				    in_sec_len);
 | 
									    in_sec_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (crc_data->elf_bits == 32) {
 | 
								if (crc_data->elf_bits == 32) {
 | 
				
			||||||
				crc_32bit.crc = crc_entry->crc;
 | 
									crc_32bit.crc = needs_byteswap ? bswap_32(crc_entry->crc) : crc_entry->crc;
 | 
				
			||||||
				crc_32bit.length = (uint32_t)in_sec_len;
 | 
									crc_32bit.length = needs_byteswap ? bswap_32((uint32_t)in_sec_len) : (uint32_t)in_sec_len;
 | 
				
			||||||
				crc_32bit.start_address = (uint32_t)in_sec_addr;
 | 
									crc_32bit.start_address = needs_byteswap ? bswap_32((uint32_t)in_sec_addr) : (uint32_t)in_sec_addr;
 | 
				
			||||||
				memcpy(sec_bytes, &crc_32bit, sizeof(crc_32bit));
 | 
									memcpy(sec_bytes, &crc_32bit, sizeof(crc_32bit));
 | 
				
			||||||
				sec_bytes += sizeof(crc_32bit);
 | 
									sec_bytes += sizeof(crc_32bit);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				/* 64 bit case */
 | 
									/* 64 bit case */
 | 
				
			||||||
				crc_64bit.crc = crc_entry->crc;
 | 
									crc_64bit.crc = needs_byteswap ? bswap_32(crc_entry->crc) : crc_entry->crc;
 | 
				
			||||||
				crc_64bit._unused_dummy = 0ul;
 | 
									crc_64bit._unused_dummy = 0ul;
 | 
				
			||||||
				crc_64bit.length = in_sec_len;
 | 
									crc_64bit.length = needs_byteswap ? bswap_64(in_sec_len) : in_sec_len;
 | 
				
			||||||
				crc_64bit.start_address = in_sec_addr;
 | 
									crc_64bit.start_address = needs_byteswap ? bswap_64(in_sec_addr) : in_sec_addr;
 | 
				
			||||||
				memcpy(sec_bytes, &crc_64bit, sizeof(crc_64bit));
 | 
									memcpy(sec_bytes, &crc_64bit, sizeof(crc_64bit));
 | 
				
			||||||
				sec_bytes += sizeof(crc_64bit);
 | 
									sec_bytes += sizeof(crc_64bit);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -782,11 +828,10 @@ int elf_patch_write_crcs_to_section(elfpatch_handle_t *ep, const char *output_se
 | 
				
			|||||||
		crc_64bit.length = 0ull;
 | 
							crc_64bit.length = 0ull;
 | 
				
			||||||
		crc_64bit.start_address = 0ull;
 | 
							crc_64bit.start_address = 0ull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (crc_data->elf_bits == 32) {
 | 
							if (crc_data->elf_bits == 32)
 | 
				
			||||||
			memcpy(sec_bytes, &crc_32bit, sizeof(crc_32bit));
 | 
								memcpy(sec_bytes, &crc_32bit, sizeof(crc_32bit));
 | 
				
			||||||
		} else {
 | 
							else
 | 
				
			||||||
			memcpy(sec_bytes, &crc_64bit, sizeof(crc_64bit));
 | 
								memcpy(sec_bytes, &crc_64bit, sizeof(crc_64bit));
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Flag section data as invalid to trigger rewrite.
 | 
						/* Flag section data as invalid to trigger rewrite.
 | 
				
			||||||
@@ -808,9 +853,8 @@ void elf_patch_close_and_free(elfpatch_handle_t *ep)
 | 
				
			|||||||
		if (ep->readonly) {
 | 
							if (ep->readonly) {
 | 
				
			||||||
			print_debug("DRY RUN: File will not be updated\n");
 | 
								print_debug("DRY RUN: File will not be updated\n");
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (elf_update(ep->elf, ELF_C_WRITE) < 0) {
 | 
								if (elf_update(ep->elf, ELF_C_WRITE) < 0)
 | 
				
			||||||
				print_err("Error writing ELF file: %s\n", elf_errmsg(-1));
 | 
									print_err("Error writing ELF file: %s\n", elf_errmsg(-1));
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										67
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								src/main.c
									
									
									
									
									
								
							@@ -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,15 +106,18 @@ 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);
 | 
				
			||||||
		if (endptr == arg) {
 | 
							if (endptr == arg) {
 | 
				
			||||||
			if ((looked_up_crc = lookup_named_crc(arg))) {
 | 
								looked_up_crc = lookup_named_crc(arg);
 | 
				
			||||||
 | 
								if (looked_up_crc)
 | 
				
			||||||
				memcpy(&args->crc, &looked_up_crc->settings, sizeof(struct crc_settings));
 | 
									memcpy(&args->crc, &looked_up_crc->settings, sizeof(struct crc_settings));
 | 
				
			||||||
			} else {
 | 
								else
 | 
				
			||||||
				argp_error(state, "Error parsing polynomial: %s\n", arg);
 | 
									argp_error(state, "Error parsing polynomial: %s\n", arg);
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 'l':
 | 
						case 'l':
 | 
				
			||||||
@@ -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");
 | 
				
			||||||
@@ -261,28 +266,17 @@ static void print_verbose_start_info(const struct command_line_options *cmd_opts
 | 
				
			|||||||
		print_debug("CRC length: %d\n", crc_len_from_poly(cmd_opts->crc.polynomial));
 | 
							print_debug("CRC length: %d\n", crc_len_from_poly(cmd_opts->crc.polynomial));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts->elf_path) {
 | 
						if (cmd_opts->elf_path)
 | 
				
			||||||
		print_debug("ELF file: %s\n", cmd_opts->elf_path);
 | 
							print_debug("ELF file: %s\n", cmd_opts->elf_path);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts->output_section) {
 | 
						if (cmd_opts->output_section)
 | 
				
			||||||
		print_debug("Output section: %s\n", cmd_opts->output_section);
 | 
							print_debug("Output section: %s\n", cmd_opts->output_section);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts->export_xml) {
 | 
						if (cmd_opts->export_xml)
 | 
				
			||||||
		print_debug("Export CRCs to '%s'\n", cmd_opts->export_xml);
 | 
							print_debug("Export CRCs to '%s'\n", cmd_opts->export_xml);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
@@ -322,6 +316,7 @@ static int check_all_sections_present(elfpatch_handle_t *ep, SlList *list)
 | 
				
			|||||||
		sec_name = (const char *)iter->data;
 | 
							sec_name = (const char *)iter->data;
 | 
				
			||||||
		if (!sec_name)
 | 
							if (!sec_name)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (elf_patch_check_for_section(ep, sec_name)) {
 | 
							if (elf_patch_check_for_section(ep, sec_name)) {
 | 
				
			||||||
			print_err("Cannot find section '%s'\n", sec_name);
 | 
								print_err("Cannot find section '%s'\n", sec_name);
 | 
				
			||||||
			ret = -2;
 | 
								ret = -2;
 | 
				
			||||||
@@ -340,7 +335,8 @@ static int check_all_sections_present(elfpatch_handle_t *ep, SlList *list)
 | 
				
			|||||||
 * @param opts Command line options. Used for CRC generation
 | 
					 * @param opts Command line options. Used for CRC generation
 | 
				
			||||||
 * @return CRC data
 | 
					 * @return CRC data
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static struct crc_import_data *compute_crcs(elfpatch_handle_t *ep, SlList *list, const struct command_line_options *opts)
 | 
					static struct crc_import_data *compute_crcs(elfpatch_handle_t *ep, SlList *list,
 | 
				
			||||||
 | 
						const struct command_line_options *opts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SlList *iter;
 | 
						SlList *iter;
 | 
				
			||||||
	const char *sec_name;
 | 
						const char *sec_name;
 | 
				
			||||||
@@ -423,13 +419,18 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	prepare_default_opts(&cmd_opts);
 | 
						prepare_default_opts(&cmd_opts);
 | 
				
			||||||
	parse_cmdline_options(&argc, &argv, &cmd_opts);
 | 
						parse_cmdline_options(&argc, &argv, &cmd_opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts.print_xsd) {
 | 
						if (cmd_opts.print_xsd) {
 | 
				
			||||||
		xml_print_xsd();
 | 
							xml_print_xsd();
 | 
				
			||||||
		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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts.list) {
 | 
						if (cmd_opts.list) {
 | 
				
			||||||
@@ -448,19 +449,11 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		return -2;
 | 
							return -2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts.use_vma && cmd_opts.format != FORMAT_STRUCT) {
 | 
						if (cmd_opts.use_vma && cmd_opts.format != FORMAT_STRUCT)
 | 
				
			||||||
		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");
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Do error printing if using a reversed polynomial. It is not implemented yet! */
 | 
					 | 
				
			||||||
	if (cmd_opts.crc.rev) {
 | 
					 | 
				
			||||||
		print_err("Reversed polynomials are not supported yet\nExiting...\n");
 | 
					 | 
				
			||||||
		goto free_cmds;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* 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);
 | 
				
			||||||
@@ -481,13 +474,11 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		/* Compute CRCs over sections */
 | 
							/* Compute CRCs over sections */
 | 
				
			||||||
		crc_data = compute_crcs(ep, cmd_opts.section_list, &cmd_opts);
 | 
							crc_data = compute_crcs(ep, cmd_opts.section_list, &cmd_opts);
 | 
				
			||||||
		if (!crc_data) {
 | 
							if (!crc_data)
 | 
				
			||||||
			goto ret_close_elf;
 | 
								goto ret_close_elf;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (reporting_get_verbosity()) {
 | 
							if (reporting_get_verbosity())
 | 
				
			||||||
			print_crcs(crc_data);
 | 
								print_crcs(crc_data);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		crc_data = xml_import_from_file(cmd_opts.import_xml);
 | 
							crc_data = xml_import_from_file(cmd_opts.import_xml);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -504,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;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@
 | 
				
			|||||||
		.xor = outxor, \
 | 
							.xor = outxor, \
 | 
				
			||||||
		.start_value = init, \
 | 
							.start_value = init, \
 | 
				
			||||||
		.rev = reverse \
 | 
							.rev = reverse \
 | 
				
			||||||
}}
 | 
					} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct named_crc predefined_crc_table[] = {
 | 
					const struct named_crc predefined_crc_table[] = {
 | 
				
			||||||
	NAMED_CRC("crc-8", 0x107, false, 0x00, 0x00),
 | 
						NAMED_CRC("crc-8", 0x107, false, 0x00, 0x00),
 | 
				
			||||||
@@ -70,7 +70,7 @@ const struct named_crc predefined_crc_table[] = {
 | 
				
			|||||||
	NAMED_CRC("jamcrc", 0x104C11DB7, true, 0xFFFFFFFF, 0x00000000),
 | 
						NAMED_CRC("jamcrc", 0x104C11DB7, true, 0xFFFFFFFF, 0x00000000),
 | 
				
			||||||
	NAMED_CRC("xfer", 0x1000000AF, false, 0x00000000, 0x00000000),
 | 
						NAMED_CRC("xfer", 0x1000000AF, false, 0x00000000, 0x00000000),
 | 
				
			||||||
	/* SENTINEL */
 | 
						/* SENTINEL */
 | 
				
			||||||
	{.name = NULL, .settings = {0, 0, 0, false}},
 | 
						{ .name = NULL, .settings = {0, 0, 0, false} },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct named_crc *reverse_lookup_named_crc(const struct crc_settings *settings)
 | 
					const struct named_crc *reverse_lookup_named_crc(const struct crc_settings *settings)
 | 
				
			||||||
@@ -110,19 +110,26 @@ void list_predefined_crcs(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	ft_table_t *table;
 | 
						ft_table_t *table;
 | 
				
			||||||
	const struct named_crc *iter;
 | 
						const struct named_crc *iter;
 | 
				
			||||||
 | 
						struct crc_calc crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	table = ft_create_table();
 | 
						table = ft_create_table();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
 | 
						ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
 | 
				
			||||||
	ft_write_ln(table, "Name", "Polynomial", "Reversed", "Start Value", "Output XOR");
 | 
						ft_write_ln(table, "Name", "Polynomial", "Reversed", "Start Value", "Output XOR", "Test Value");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (iter = predefined_crc_table; iter->name; iter++) {
 | 
						for (iter = predefined_crc_table; iter->name; iter++) {
 | 
				
			||||||
		ft_printf_ln(table, "%s|0x%lx|%s|0x%x|0x%x",
 | 
							crc_init(&crc, &iter->settings);
 | 
				
			||||||
 | 
							/* Calculate the test value */
 | 
				
			||||||
 | 
							crc_push_bytes(&crc, (const uint8_t *)"123456789", 9);
 | 
				
			||||||
 | 
							crc_finish_calc(&crc);
 | 
				
			||||||
 | 
							ft_printf_ln(table, "%s|0x%lx|%s|0x%x|0x%x|0x%x",
 | 
				
			||||||
			     iter->name,
 | 
								     iter->name,
 | 
				
			||||||
			     iter->settings.polynomial,
 | 
								     iter->settings.polynomial,
 | 
				
			||||||
			     iter->settings.rev ? "yes" : "no",
 | 
								     iter->settings.rev ? "yes" : "no",
 | 
				
			||||||
			     iter->settings.start_value,
 | 
								     iter->settings.start_value,
 | 
				
			||||||
			     iter->settings.xor);
 | 
								     iter->settings.xor,
 | 
				
			||||||
 | 
								     crc_get_value(&crc));
 | 
				
			||||||
 | 
							crc_destroy(&crc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("%s\n", ft_to_string(table));
 | 
						printf("%s\n", ft_to_string(table));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										101
									
								
								src/reporting.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/reporting.c
									
									
									
									
									
								
							@@ -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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								src/xml.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/xml.c
									
									
									
									
									
								
							@@ -30,9 +30,8 @@ int xml_write_crcs_to_file(const char *path, const struct crc_import_data *crc_d
 | 
				
			|||||||
	const struct crc_entry *entry;
 | 
						const struct crc_entry *entry;
 | 
				
			||||||
	size_t index;
 | 
						size_t index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!path || !crc_data) {
 | 
						if (!path || !crc_data)
 | 
				
			||||||
		return -1000;
 | 
							return -1000;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	writer = xmlNewTextWriterFilename(path, 0);
 | 
						writer = xmlNewTextWriterFilename(path, 0);
 | 
				
			||||||
	if (!writer) {
 | 
						if (!writer) {
 | 
				
			||||||
@@ -67,7 +66,9 @@ int xml_write_crcs_to_file(const char *path, const struct crc_import_data *crc_d
 | 
				
			|||||||
	xmlTextWriterStartElement(writer, BAD_CAST "sections");
 | 
						xmlTextWriterStartElement(writer, BAD_CAST "sections");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Output all section CRCs */
 | 
						/* Output all section CRCs */
 | 
				
			||||||
	for (entry_iter = crc_data->crc_entries, index = 0u; entry_iter; entry_iter = sl_list_next(entry_iter), index++) {
 | 
						for (entry_iter = crc_data->crc_entries, index = 0u;
 | 
				
			||||||
 | 
						entry_iter;
 | 
				
			||||||
 | 
						entry_iter = sl_list_next(entry_iter), index++) {
 | 
				
			||||||
		entry = (const struct crc_entry *)entry_iter->data;
 | 
							entry = (const struct crc_entry *)entry_iter->data;
 | 
				
			||||||
		xmlTextWriterStartElement(writer, BAD_CAST "crc");
 | 
							xmlTextWriterStartElement(writer, BAD_CAST "crc");
 | 
				
			||||||
		xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "name", "%s", entry->name);
 | 
							xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "name", "%s", entry->name);
 | 
				
			||||||
@@ -222,7 +223,8 @@ static int convert_number_string_to_uint(const char *data, uint64_t *output)
 | 
				
			|||||||
 * @return 0 if successful
 | 
					 * @return 0 if successful
 | 
				
			||||||
 * @return negative in case of an error
 | 
					 * @return negative in case of an error
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int get_uint64_from_xpath_content(const char *xpath, xmlXPathContextPtr xpath_ctx, uint64_t *output, bool required)
 | 
					static int get_uint64_from_xpath_content(const char *xpath, xmlXPathContextPtr xpath_ctx,
 | 
				
			||||||
 | 
											uint64_t *output, bool required)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *data;
 | 
						const char *data;
 | 
				
			||||||
	int ret = -1;
 | 
						int ret = -1;
 | 
				
			||||||
@@ -245,7 +247,8 @@ static int get_uint64_from_xpath_content(const char *xpath, xmlXPathContextPtr x
 | 
				
			|||||||
 * @return 0 if successful
 | 
					 * @return 0 if successful
 | 
				
			||||||
 * @return negative in case of an error
 | 
					 * @return negative in case of an error
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int get_uint32_from_xpath_content(const char *xpath, xmlXPathContextPtr xpath_ctx, uint32_t *output, bool required)
 | 
					static int get_uint32_from_xpath_content(const char *xpath, xmlXPathContextPtr xpath_ctx,
 | 
				
			||||||
 | 
											uint32_t *output, bool required)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *data;
 | 
						const char *data;
 | 
				
			||||||
	uint64_t tmp;
 | 
						uint64_t tmp;
 | 
				
			||||||
@@ -359,10 +362,10 @@ struct crc_import_data *xml_import_from_file(const char *path)
 | 
				
			|||||||
		print_err("Error reading XML file: %s\n", path);
 | 
							print_err("Error reading XML file: %s\n", path);
 | 
				
			||||||
		goto ret_none;
 | 
							goto ret_none;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	root_node = xmlDocGetRootElement(doc);
 | 
						root_node = xmlDocGetRootElement(doc);
 | 
				
			||||||
	if (!root_node) {
 | 
						if (!root_node)
 | 
				
			||||||
		goto ret_close_doc;
 | 
							goto ret_close_doc;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Validate the document */
 | 
						/* Validate the document */
 | 
				
			||||||
	if (!validate_xml_doc(doc)) {
 | 
						if (!validate_xml_doc(doc)) {
 | 
				
			||||||
@@ -372,9 +375,8 @@ struct crc_import_data *xml_import_from_file(const char *path)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Get xpath context */
 | 
						/* Get xpath context */
 | 
				
			||||||
	xpath_ctx = xmlXPathNewContext(doc);
 | 
						xpath_ctx = xmlXPathNewContext(doc);
 | 
				
			||||||
	if (!xpath_ctx) {
 | 
						if (!xpath_ctx)
 | 
				
			||||||
		goto ret_close_doc;
 | 
							goto ret_close_doc;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the version number and print error in case of incompatibility. Continue either way */
 | 
						/* Get the version number and print error in case of incompatibility. Continue either way */
 | 
				
			||||||
	cptr = (char *)xmlGetProp(root_node, BAD_CAST "version");
 | 
						cptr = (char *)xmlGetProp(root_node, BAD_CAST "version");
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user