二进制 bin文件 合成工具

时间:2025-03-28 18:38:33
#include <> // 包含标准输入输出库 #include <> // 包含标准库函数 #include <> // 包含字符串处理函数 #include <> // 包含错误号定义 #define BUFFER_SIZE 1024 // 定义缓冲区大小为1024字节 #define PADDING_BYTE 0xFF // 定义填充字节为0xFF #define ALIGNMENT_SIZE 4096 // 定义对齐大小为4096字节 // 定义地址数组 #define BUFFER_SIZE 1024 #define MAX_ADDRESSES 100 // 假设地址的数量不会超过100个 #define _CRT_SECURE_NO_WARNINGS // 禁用安全警告 // 定义宏以禁用安全警告 #define _CRT_SECURE_NO_WARNINGS // 函数声明 int extract_addresses(const char *filename, uintptr_t *addresses, size_t *count); /* */ int main() { FILE *file, *outfile, *temp; // 文件指针数组,分别指向文件列表文件、输出文件和临时二进制文件 char filename[] = ""; // 定义文件名列表文件的名称 char buffer[BUFFER_SIZE]; // 定义缓冲区,用于存储文件名和读取文件内容 char bin_filename[BUFFER_SIZE]; // 定义缓冲区,用于存储二进制文件的完整名称 char address_str[25]; // 定义缓冲区,用于存储24位十六进制地址字符串(加上"0x"前缀) char outfilename[] = "SPL-2MB_0x0.bin"; // 定义输出二进制文件名 long long int address; // 定义长整型变量,用于存储地址 char *token; // 定义字符指针,用于字符串分割 char *address_ptr; // 定义字符指针,用于定位地址字符串 char *bin_file_ptr; // 定义字符指针,用于定位bin文件名 char next_file_index = 1;//下一个文件地址 索引 char file_len = 0; //找地址 printf("===================\n"); uintptr_t addresses[MAX_ADDRESSES]; // 存储地址值的数组 size_t address_count = 0; // 调用函数提取地址 if (extract_addresses("", addresses, &address_count) != 0) { perror("Error extracting addresses"); return EXIT_FAILURE; } // 打印提取出的地址 for (size_t i = 0; i < address_count; ++i) { printf("Address %zu: %p\n", i + 1, (void*)addresses[i]); //printf("Address %zu: %p\n", i + 1, addresses[i]); file_len++; } printf("file num = %d\n", file_len); printf("====================\n"); // 尝试以只读模式打开文件列表文件 if (fopen_s(&file, filename, "r") != 0) { perror("Error opening file"); // 如果打开失败,输出错误信息 return EXIT_FAILURE; // 返回失败状态 } // 创建输出二进制文件,用于写入合并后的内容 if (fopen_s(&outfile, outfilename, "wb+") != 0) { fclose(file); // 如果创建失败,关闭已打开的文件列表文件 perror("Error creating output binary file"); // 输出错误信息 return EXIT_FAILURE; // 返回失败状态 } // 使用fgets函数逐行读取文件列表文件 //读 ==> file ==> 一行行读 while (fgets(buffer, sizeof(buffer), file) != NULL) { // 去除可能的换行符 buffer[strcspn(buffer, "\n")] = 0; // 查找地址字符串的开始位置,即第一个"_"字符后面的内容 token = strchr(buffer, '_'); if (token == NULL) { fprintf(stderr, "Invalid format in file list: missing '_'\n"); // 如果格式错误,输出错误信息 continue; // 继续处理下一行 } // 复制文件名到bin_filename,不包括地址和.bin strncpy_s(bin_filename, sizeof(bin_filename), buffer, token - buffer); bin_filename[token - buffer] = '\0'; // 确保字符串以空字符结尾 // 查找地址字符串,地址字符串以"_"开始,到".bin"结束 address_ptr = token + 1; if (sscanf_s(address_ptr, "0x%24s", address_str, (unsigned)_countof(address_str)) != 1) { fprintf(stderr, "Invalid address format in file list.\n"); // 如果地址格式错误,输出错误信息 continue; // 继续处理下一行 } // 将十六进制地址转换为长长整型 address = strtoll(address_str, NULL, 16); // 查找bin文件名的开始位置,即地址字符串结束后的第一个"."字符 bin_file_ptr = strchr(address_ptr, '.'); if (bin_file_ptr == NULL) { fprintf(stderr, "Invalid format in file list: missing '.bin'\n"); // 如果格式错误,输出错误信息 continue; // 继续处理下一行 } // 复制bin文件名,包括.bin扩展名 strncpy_s(bin_filename, sizeof(bin_filename), buffer, bin_file_ptr - buffer + 4); // +4 为了包括".bin" bin_filename[bin_file_ptr - buffer + 4] = '\0'; // 确保字符串以空字符结尾 // 打印出每个文件的初始地址 printf("\nWriting %s to address: 0x%llx\n", bin_filename, address); // 移动到指定的写入地址 if (fseek(outfile, address, SEEK_SET) != 0) { perror("Error seeking to the specified address"); // 如果定位失败,输出错误信息 fclose(file); fclose(outfile); return EXIT_FAILURE; // 返回失败状态 } // 打开下一个 bin 文件 if (fopen_s(&temp, bin_filename, "rb") != 0) { perror("Error opening binary file listed in "); // 如果打开失败,输出错误信息 continue; // 如果文件打开失败,继续下一个文件 } // 将当前 bin 文件的内容复制到输出文件的指定地址 size_t bytesRead; while ((bytesRead = fread(buffer, 1, sizeof(buffer), temp)) > 0) { fwrite(buffer, 1, bytesRead, outfile); // 写入到指定地址 } fclose(temp); // 关闭当前 bin 文件 // 移动到下一个文件的起始位置 // 计算当前位置到下一个文件起始位置的距离addresses[i] if(file_len > 1) { //printf("file_len =%d\n", file_len); long long int current_position = _ftelli64(outfile); long long int offset_to_next_file = addresses[next_file_index] - current_position; printf("=====current_position = %p =====\n", current_position); printf("=====下一个文件的起始位置 address = %p =====\n", addresses[next_file_index]); printf("=====距离下个文件的距离offset_to_next_file = %p =====\n", offset_to_next_file); next_file_index++; // 如果存在偏移,用0xFF填充 if (offset_to_next_file > 0) { printf("Filling %lld bytes with 0xFF until next file address.\n", offset_to_next_file); while (offset_to_next_file > 0) { size_t bytes_to_write = (size_t)(offset_to_next_file > sizeof(buffer) ? sizeof(buffer) : offset_to_next_file); memset(buffer, PADDING_BYTE, bytes_to_write); // 用0xFF填充缓冲区 fwrite(buffer, 1, bytes_to_write, outfile); // 写入填充字节 offset_to_next_file -= bytes_to_write; // 更新剩余需要填充的字节数 } } file_len--; } } /* 补齐 */ // 关闭所有打开的文件 fclose(file); fclose(outfile); // 重新打开输出文件以进行填充操作 if (fopen_s(&outfile, outfilename, "rb+") != 0) { perror("Error reopening output binary file for padding"); // 如果重新打开失败,输出错误信息 return EXIT_FAILURE; // 返回失败状态 } // 获取输出文件的当前大小 long long int current_size = _ftelli64(outfile); // 计算需要补齐的字节数,以确保文件大小是ALIGNMENT_SIZE字节的整数倍 long long int padding_bytes = (current_size % ALIGNMENT_SIZE) ? (ALIGNMENT_SIZE - (current_size % ALIGNMENT_SIZE)) : 0; // 如果需要补齐,填充剩余的字节为0xFF if (padding_bytes > 0) { printf("Adding %lld bytes (0xFF) to reach a size that is a multiple of %lld bytes.\n", padding_bytes, ALIGNMENT_SIZE); char padding_buffer[ALIGNMENT_SIZE]; // 定义填充缓冲区 memset(padding_buffer, PADDING_BYTE, sizeof(padding_buffer)); // 填充缓冲区为0xFF while (padding_bytes > 0) { size_t bytes_to_write = (size_t)(padding_bytes < sizeof(padding_buffer) ? padding_bytes : sizeof(padding_buffer)); fwrite(padding_buffer, 1, bytes_to_write, outfile); // 写入填充字节 padding_bytes -= bytes_to_write; // 更新剩余需要填充的字节数 } } // 关闭输出二进制文件 fclose(outfile); system("pause"); // 暂停,以便查看程序输出 return EXIT_SUCCESS; // 返回成功状态 } // 从文件中提取地址的函数实现 int extract_addresses(const char *filename, uintptr_t *addresses, size_t *count) { FILE *file; char buffer[BUFFER_SIZE]; char *token; uintptr_t address = 0; // 确保address变量初始化为0 // 打开文件 if (fopen_s(&file, filename, "r") != 0) { perror("Error opening file"); return -1; // 返回-1表示失败 } *count = 0; // 初始化地址计数为0 // 读取文件直到末尾 while (fgets(buffer, sizeof(buffer), file) != NULL && *count < MAX_ADDRESSES) { // 去除可能的换行符 buffer[strcspn(buffer, "\n")] = 0; // 查找地址字符串的开始位置,即第一个"_"字符后面的内容 token = strchr(buffer, '_'); if (token == NULL) { fprintf(stderr, "Invalid format in file list: missing '_'\n"); continue; } // 跳过下划线 token += 1; // 查找文件扩展名 ".bin" 之前的部分 char *end_ptr = strstr(token, ".bin"); if (end_ptr != NULL) { *end_ptr = '\0'; // 终止字符串以获取纯净的地址 address = strtoull(token, NULL, 16); // 转换为无符号长长整型 if (errno == EINVAL || errno == ERANGE) { perror("Error converting address"); fclose(file); return -1; // 返回-1表示失败 } } else { fprintf(stderr, "Invalid format in file list: missing '.bin'\n"); continue; } // 存储地址值 addresses[(*count)++] = address; } fclose(file); return 0; // 成功返回0 }