天天看点

编程技巧如何用一套代码去处理32位、64位的文件结构解析

转载请注明出处。https://rhirufxmbcyj.gitlab.io

不定期更新~~~

如何用一套代码去处理32位、64位的文件结构解析

最近想写一个ELF文件格式解析程序,遇到了这样的一个问题

相信写过ELF或PE解析工具的朋友都会遇到过,就是两者的文件结构都有32位和64位区分

而这个差别也不,无非是结构体不同(某些字段是4字节或8字节)

因为这个微小的差异去写两套处理代码就显得程序过于臃肿,无法将代码合理的复用

不写两套代码的话,又无法动态的选择对应的32位或64位结构体

解决方案

这个方法是从同事那里学来的,巧妙的利用了#include

#include通俗的来说就是将被包含的文件在当前位置展开

例如

a.c里代码是这样写的

xxxxxxx
xxxxxxx
#include "b.c"
xxxxxxx
xxxxxxx
           

中间include了一个b.c,这个b.c的文件在编译过程中其实是相当于全部粘贴到a.c里来的,如果b.c不在工程中,那它根本不会参与编译,参与编译的其实只有a.c文件。

言归正传,用一套代码处理32 和 64两种情况就是利用上边这个方法

demo文件如下:

handle.c 存放处理代码,这个demo中只写了一接口函数的实现

handle.h 存放接口函数的定义,以及根据宏的不同定义不同的宏或变量等

main.c 调用接口函数

a.c 定义宏,然后include handle.c

b.c 定义宏,然后include handle.c

如果使用Cmake管理工程的话,记得不要将handle.c加入编译列表中

如果是用VS直接创建的工程,直接将handle.c从VS工程文件中移除,但是在文件夹中要保留

现在来看各个文件的内容

handle.c

#include <stdio.h>
#include "handle.h"

void CAT(function)()
{
	printf(CAT(name));
	printf("\n");
}
           

这里的CAT是一个宏,起到连接字符串的作用

handle.h

#ifndef	HANDLE_H
#define	HANDLE_H

void aaa_function();
void bbb_function();

#ifdef   AAA
#define CAT(_X_)   aaa_##_X_
char *aaa_name = "aaaaa";
#endif

#ifdef   BBB
#define CAT(_X_)   bbb_##_X_
char *bbb_name = "bbbbb";
#endif

#endif
           

a.c

#define	AAA

#include "handle.c"
           

b.c

#define BBB

#include "handle.c"
           

main.c

#include "handle.h"

int main()
{
	aaa_function();
	bbb_function();
	return 0;
}
           

照着这个demo去编译运行一下,发现确实是能跑通并输出相应的内容的。

编程技巧如何用一套代码去处理32位、64位的文件结构解析

可能直接理解起来有些难,最直观的方法还是手动展开来看比较方便。

咱们就从a.c 和 b.c入手进行展开

展开后的a.c

#define	AAA					//此处定义了AAA

//#include "handle.c"
#include <stdio.h>

//#include "handle.h"
void aaa_function();
void bbb_function();

#ifdef   AAA				//此处代码变成了可用的
#define CAT(_X_)   aaa_##_X_
char *aaa_name = "aaaaa";
#endif

#ifdef   BBB
#define CAT(_X_)   bbb_##_X_
char *bbb_name = "bbbbb";
#endif

void CAT(function)()		 //这里实现了aaa_function的定义
{
	printf(CAT(name));
	printf("\n");
}
           

展开后的b.c

#define	BBB					//此处定义了BBB

//#include "handle.c"
#include <stdio.h>

//#include "handle.h"
void aaa_function();
void bbb_function();

#ifdef   AAA				
#define CAT(_X_)   aaa_##_X_
char *aaa_name = "aaaaa";
#endif

#ifdef   BBB				//此处代码变成了可用的
#define CAT(_X_)   bbb_##_X_
char *bbb_name = "bbbbb";
#endif

void CAT(function)()		 //这里实现了bbb_function的定义
{
	printf(CAT(name));
	printf("\n");
}
           

这样来看,也就一目了然了

程序员写了一套代码handle.c,经过两个文件的include,以及define宏定义和相应的处理变成了两套

编译运行自然没问题,代码也就不用多写一套相似的了

demo:https://rhirufxmbcyj.gitlab.io/files/handle_demo.zip

根据这个思路,可以定义PE32、PE64,或是ELF32、ELF64,然后用ifdef xxx来做相应的处理

用typedef对32位、64位结构体进一步封装使用

也就可以实现一套代码处理两套文件结构了

此方法应该也可用于其他需要多写一套代码处理的情况,请各位根据具体情况具体分析吧

继续阅读