二进制文件操作(添加头信息)

论坛 期权论坛 脚本     
已经匿名di用户   2022-7-2 21:51   5780   0

在做bootloader升级的时候,经常需要给需要升级的APP添加头信息,如果是成熟的项目,公司会用一个简单的上位机来添加头信息,但是对于预言项目,这个头信息就需要手动添加了,经过多种方法尝试,发现两种可行方法,总结如下。

1. 常用工具比较

工具修改添加插件
ultraedit可以不可以
(未深究)
不需要
Notepad++可以不可以
(未深究)
需要
FreeHexEditorNeo可以可以不需要
vi/vim(linxu)可以可以
(不建议)
不需要

2. 软件实现

使用“FreeHexEditorNeo”这个小工具是可以以二进制(16进制)的方式添加和删除字节的,但是想到可以通过软件实现,就尝试了一下,如下:

  • 将头信息和数据信息写到一个新的文件中:

        /* 头文件 */
        #include <unistd.h>
        #include <stdio.h>
        #include <string.h>
    
        /* 宏定义 */
        #define BUFSIZE  1024
        #define HEADERSIZE 41 /* 通过修改这个值来确定header的长度. */
    
        /* 类型定义 */
        typedef unsigned char Uint8;
    
        void main(int argc, char** argv)
        {
            FILE *m_pstFDSrcPart;
            FILE *m_pstFDSrcAll;
            FILE *m_pstFDDest;
            Uint8 m_ucBuf[BUFSIZE];
            char  m_ucFileName[100];
            int   m_ssRdCnt;
            
            m_pstFDSrcPart = fopen(argv[1],"rb"); /* 第一个参数放头信息 */
            m_pstFDSrcAll  = fopen(argv[2],"rb"); /* 第二个参数放数据信息 */
            strncpy(m_ucFileName,argv[3],strlen(argv[3]));
            m_ucFileName[strlen(argv[3])] = '\0';
            m_pstFDDest = fopen(m_ucFileName, "wb" ); /* 数据最终写到新文件中 */
        
        /* debug information. */
            printf("header:%s + data:%s = dest:%s\n",argv[1],argv[2],m_ucFileName);
    
            /* 操作Header部分:先读后写. */
            m_ssRdCnt = fread(m_ucBuf,sizeof(unsigned char), HEADERSIZE, m_pstFDSrcPart);
            if(m_ssRdCnt != HEADERSIZE)
            {
                printf("read error!\n");
            }    
            fwrite( m_ucBuf, sizeof( unsigned char ), m_ssRdCnt, m_pstFDDest );
    
            /* 操作Data部分:先读后写.  */
            m_ssRdCnt = 0;
            while( (m_ssRdCnt = fread(m_ucBuf,sizeof(unsigned char), BUFSIZE, m_pstFDSrcAll)) != 0 )
            {
                fwrite( m_ucBuf, sizeof( unsigned char ), m_ssRdCnt, m_pstFDDest );
            } 
    
            /* 等待写磁盘操作结束 */
            fsync(fileno(m_pstFDDest));
            
            fclose(m_pstFDSrcPart);
            fclose(m_pstFDSrcAll);
            fclose(m_pstFDDest);
        }
    
    • 通过宏"HEADERSIZE"来确定头信息的长度;
    • 编译之后,通过命令传参来生成目标文件,格式:./Merge header.bin data.bin dest.bin
    • 最终会在当前目录生成"dest.bin"带有头信息的可执行文件;
  • 有些文件可能长度过长,而实际只需要前面的一些字节,可以截断该文件,上面的程序可以在不截断的情况下操作,代码如下:

        /* 头文件 */
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/types.h>
    
        int main(int agrc, char** argv)
        {
            unsigned int m_usLenth;
    
            m_usLenth = atoi(argv[2]);
            truncate(argv[1],m_usLenth);
            return 0;
        }
    
    • 通过gcc -o trunc trunc.c生成执行程序;
    • 通过命令传参的方式实现截断文件:./trunc header.bin 41,这里是将header.bin文件截断为41个字节;

3. 备注

  • ultraedit 和 Notepad++ 也许可以添加字节,但是未深究;

  • 使用 vi 查看二进制文件:

    • 执行vi -b file.bin,以二进制方式打开文件;
    • 在末行模式下输入::%!xxd -g 1,可以切换到16进制显示模式;

    "vi"工具可以添加、修改文件,但是不智能,vi会将bin文件中的所有内容(包括地址字段,数据字段,注释字段)当作修改对象,不会自动变换地址,会破坏可执行文件,强烈建议不要使用vi修改二进制文件;

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP