Compare commits
	
		
			18 Commits
		
	
	
		
			v1.0.0-rc1
			...
			f964ef7b60
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f964ef7b60 | |||
| dd05449f36 | |||
| 3ff626134e | |||
| 29fdc841b7 | |||
| dc30188593 | |||
| 2bea5d288c | |||
| 8a0226a5ea | |||
| ed6373473c | |||
| 80b5f5b1b3 | |||
| 4fab6ffd3a | |||
| 0ee19eaea4 | |||
| 26eb480343 | |||
| 30e47d533a | |||
| faeab33375 | |||
| 7e414f8576 | |||
| 933680c80d | |||
| 891df1803e | |||
| 7be1d6a967 | 
							
								
								
									
										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,8 +134,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
**patchelfcrc** -l -g word --start-magic=0x12345678 --end-magic=0x8754321 -p crc-32-mpeg -f bare -O .outputsection -S .text executable.elf
 | 
					**patchelfcrc** -l -g word --start-magic=0x12345678 --end-magic=0x8754321 -p crc-32-mpeg -f bare -O .outputsection -S .text executable.elf
 | 
				
			||||||
: Calculate the CRC over *.text* section and place the result in the *.outputsection* section.
 | 
					: Calculate the CRC over *.text* section and place the result in the *.outputsection* section.
 | 
				
			||||||
The output sections start and end are checked for the given magic numbers in order to assure correct memory layout.
 | 
					The output sections start and end are checked for the given magic numbers in order to ensure correct memory layout.
 | 
				
			||||||
*CRC-32-MPEG* is used as CRC algorothm.
 | 
					*CRC-32-MPEG* is used as CRC algorithm.
 | 
				
			||||||
The memory is interpreted as *little endian* and the CRC calculation granularity is a 32 bit *word*.
 | 
					The memory is interpreted as *little endian* and the CRC calculation granularity is a 32 bit *word*.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# BUGS
 | 
					# BUGS
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										100
									
								
								src/elfpatch.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								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;
 | 
				
			||||||
@@ -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,
 | 
				
			||||||
@@ -261,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 */
 | 
				
			||||||
@@ -306,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;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -433,12 +470,12 @@ elfpatch_handle_t *elf_patch_open(const char *path, bool readonly, bool expect_l
 | 
				
			|||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
			print_debug("ELF Endianess: little\n");
 | 
								print_debug("ELF Endianess: little\n");
 | 
				
			||||||
			if (!expect_little_endian)
 | 
								if (!expect_little_endian)
 | 
				
			||||||
				print_err("Big endian format expected. File is little endian. Double check settings!\n");
 | 
									print_warn("Big endian format expected. File is little endian. Double check settings!\n");
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 2:
 | 
							case 2:
 | 
				
			||||||
			print_debug("ELF Endianess: big\n");
 | 
								print_debug("ELF Endianess: big\n");
 | 
				
			||||||
			if (expect_little_endian)
 | 
								if (expect_little_endian)
 | 
				
			||||||
				print_err("Little endian format expected. File is big endian. Double check settings!\n");
 | 
									print_warn("Little endian format expected. File is big endian. Double check settings!\n");
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			print_err("Cannot determine endianess of ELF file. EI_DATA is: %d\n", ident[5]);
 | 
								print_err("Cannot determine endianess of ELF file. EI_DATA is: %d\n", ident[5]);
 | 
				
			||||||
@@ -524,25 +561,24 @@ int elf_patch_compute_crc_over_section(elfpatch_handle_t *ep, const char *sectio
 | 
				
			|||||||
	/* Find section */
 | 
						/* Find section */
 | 
				
			||||||
	sec = find_section_in_list(ep->sections, section);
 | 
						sec = find_section_in_list(ep->sections, section);
 | 
				
			||||||
	if (!sec) {
 | 
						if (!sec) {
 | 
				
			||||||
		print_err("Cannot find section %s\n", section);
 | 
							print_err("Cannot find section '%s'\n", section);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data = elf_getdata(sec->scn, NULL);
 | 
						data = elf_getdata(sec->scn, NULL);
 | 
				
			||||||
	if (!data) {
 | 
						if (!data) {
 | 
				
			||||||
		print_err("Error reading section data from %s: %s\n", section, elf_errmsg(-1));
 | 
							print_err("Error reading section data from '%s': %s\n", section, elf_errmsg(-1));
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print_debug("Section data length: %lu\n", data->d_size);
 | 
					 | 
				
			||||||
	if (!data->d_size) {
 | 
						if (!data->d_size) {
 | 
				
			||||||
		print_err("Section %s contains no data.\n", section);
 | 
							print_err("Section '%s' contains no data.\n", section);
 | 
				
			||||||
		return -2;
 | 
							return -2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* NOBIT sections have a length but no data in the file. Abort in this case */
 | 
						/* NOBIT sections have a length but no data in the file. Abort in this case */
 | 
				
			||||||
	if (!data->d_buf) {
 | 
						if (!data->d_buf) {
 | 
				
			||||||
		print_err("Section %s does not contain loadable data.\n", section);
 | 
							print_err("Section '%s' does not contain loadable data.\n", section);
 | 
				
			||||||
		return -2;
 | 
							return -2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -556,7 +592,7 @@ int elf_patch_compute_crc_over_section(elfpatch_handle_t *ep, const char *sectio
 | 
				
			|||||||
		/* Check granularity vs size of section */
 | 
							/* Check granularity vs size of section */
 | 
				
			||||||
		padding_count = (gran_in_bytes - data->d_size % gran_in_bytes) % gran_in_bytes;
 | 
							padding_count = (gran_in_bytes - data->d_size % gran_in_bytes) % gran_in_bytes;
 | 
				
			||||||
		if (padding_count) {
 | 
							if (padding_count) {
 | 
				
			||||||
			print_err("Section '%s' is not a multiple size of the given granularity. %u zero padding bytes will be added.\n",
 | 
								print_warn("Section '%s' is not a multiple size of the given granularity. %u zero padding bytes will be added.\n",
 | 
				
			||||||
				  section, padding_count);
 | 
									  section, padding_count);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -596,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) {
 | 
				
			||||||
@@ -651,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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -748,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;
 | 
				
			||||||
@@ -758,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);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								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,6 +106,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
 | 
				
			|||||||
	case ARG_KEY_USE_VMA:
 | 
						case ARG_KEY_USE_VMA:
 | 
				
			||||||
		args->use_vma = true;
 | 
							args->use_vma = true;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case ARG_KEY_FORCE_NO_COLOR:
 | 
				
			||||||
 | 
							args->force_nocolor = true;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case 'p':
 | 
						case 'p':
 | 
				
			||||||
		/* Polyniomial */
 | 
							/* Polyniomial */
 | 
				
			||||||
		args->crc.polynomial = strtoull(arg, &endptr, 0);
 | 
							args->crc.polynomial = strtoull(arg, &endptr, 0);
 | 
				
			||||||
@@ -195,6 +200,7 @@ static int parse_cmdline_options(int *argc, char ***argv, struct command_line_op
 | 
				
			|||||||
		{"import", ARG_KEY_IMPORT, "XML", 0, "Do not caclulate CRCs but import them from file", 3},
 | 
							{"import", ARG_KEY_IMPORT, "XML", 0, "Do not caclulate CRCs but import them from file", 3},
 | 
				
			||||||
		{"xsd", ARG_KEY_XSD, 0, 0, "Print XSD to stdout", 0},
 | 
							{"xsd", ARG_KEY_XSD, 0, 0, "Print XSD to stdout", 0},
 | 
				
			||||||
		{"use-vma", ARG_KEY_USE_VMA, 0, 0, "Use the VMA instead of the LMA for struct output", 2},
 | 
							{"use-vma", ARG_KEY_USE_VMA, 0, 0, "Use the VMA instead of the LMA for struct output", 2},
 | 
				
			||||||
 | 
							{"no-color", ARG_KEY_FORCE_NO_COLOR, 0, 0, "Force the output to be text only without colors", 0},
 | 
				
			||||||
		/* Sentinel */
 | 
							/* Sentinel */
 | 
				
			||||||
		{NULL, 0, 0, 0, NULL, 0}
 | 
							{NULL, 0, 0, 0, NULL, 0}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -233,12 +239,11 @@ static void prepare_default_opts(struct command_line_options *opts)
 | 
				
			|||||||
	opts->output_section = NULL;
 | 
						opts->output_section = NULL;
 | 
				
			||||||
	opts->export_xml = NULL;
 | 
						opts->export_xml = NULL;
 | 
				
			||||||
	opts->import_xml = NULL;
 | 
						opts->import_xml = NULL;
 | 
				
			||||||
 | 
					    opts->force_nocolor = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_verbose_start_info(const struct command_line_options *cmd_opts)
 | 
					static void print_verbose_start_info(const struct command_line_options *cmd_opts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	SlList *list_iter;
 | 
					 | 
				
			||||||
	const struct named_crc *predef_crc;
 | 
						const struct named_crc *predef_crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print_debug("Start CRC patching\n");
 | 
						print_debug("Start CRC patching\n");
 | 
				
			||||||
@@ -272,11 +277,6 @@ static void print_verbose_start_info(const struct command_line_options *cmd_opts
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts->import_xml)
 | 
						if (cmd_opts->import_xml)
 | 
				
			||||||
		print_debug("Import CRCs from '%s'\n", cmd_opts->import_xml);
 | 
							print_debug("Import CRCs from '%s'\n", cmd_opts->import_xml);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (cmd_opts->section_list) {
 | 
					 | 
				
			||||||
		for (list_iter = cmd_opts->section_list, i = 1; list_iter; list_iter = sl_list_next(list_iter), i++)
 | 
					 | 
				
			||||||
			print_debug("Input section [%d]: \"%s\"\n", i, (const char *)list_iter->data);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void free_cmd_args(struct command_line_options *opts)
 | 
					static void free_cmd_args(struct command_line_options *opts)
 | 
				
			||||||
@@ -425,8 +425,11 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		goto free_cmds;
 | 
							goto free_cmds;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initialize console output */
 | 
				
			||||||
 | 
						reporting_init(cmd_opts.force_nocolor ? COLOR_MODE_COLOR_OFF : COLOR_MODE_DETECT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts.verbose || cmd_opts.dry_run)
 | 
						if (cmd_opts.verbose || cmd_opts.dry_run)
 | 
				
			||||||
		reporting_enable_verbose();
 | 
							reporting_enable_verbose(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print_verbose_start_info(&cmd_opts);
 | 
						print_verbose_start_info(&cmd_opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -450,7 +453,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		print_warn("--use-vma option only has an effect when exporting as struct output.\n");
 | 
							print_warn("--use-vma option only has an effect when exporting as struct output.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cmd_opts.output_section && cmd_opts.export_xml == NULL)
 | 
						if (!cmd_opts.output_section && cmd_opts.export_xml == NULL)
 | 
				
			||||||
		print_err("No output section / XML export specified. Will continue but not create any output\n");
 | 
							print_warn("No output section or XML export specified. Will continue but not create any output.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Prepare libelf for use with the latest ELF version */
 | 
						/* Prepare libelf for use with the latest ELF version */
 | 
				
			||||||
	elf_version(EV_CURRENT);
 | 
						elf_version(EV_CURRENT);
 | 
				
			||||||
@@ -492,7 +495,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (cmd_opts.export_xml) {
 | 
						if (cmd_opts.export_xml) {
 | 
				
			||||||
		if (xml_write_crcs_to_file(cmd_opts.export_xml, crc_data)) {
 | 
							if (xml_write_crcs_to_file(cmd_opts.export_xml, crc_data)) {
 | 
				
			||||||
			print_err("Error during XML generation\n");
 | 
								print_err("Error during XML generation.\n");
 | 
				
			||||||
			ret = -3;
 | 
								ret = -3;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user