LIB格式的文件的读取(提取OBJ)
LIB文件就是多个OBJ文件的集合。为什么会有LIB呢?因为有了LIB,链接器就可以筛选掉不需要的OBJ文件,把需要的OBJ提取出来并连接起来。VC6、MinGW编译通过。/*
LIB文件的结构:
文件标记:"!<arch>\n"
第一节
第二节
各种节
其中第一节的数据为:
节头
LIB文件的所有符号以及偏移信息(都是Big-Endian)
第二节的数据为:
节头
LIB文件所有符号所在OBJ文件的索引,OBJ文件的数量以及偏移
其中每个OBJ文件占用一个节(也就是后面的“各种节”的内容)
解析LIB文件的流程:
打开LIB文件,得到一个FILE*
读取前8个字节,判断文件标识是不是"!<arch>\n"
调用ReadSecHead读取第一个节头
调用ReadFirstSecData读取第一个节的信息
调用ReadSecHead读取第二个节头
调用ReadSecondSecData读取第二个节的信息
调用ExtractOBJFiles提取所有OBJ
关闭文件
有些LIB有一个名为"//"的节,内容是OBJ文件名的表,可无视。
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#ifndef MAX_PATH
#define MAX_PATH 260 //标准的路径不超过260字节
#endif
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned int BOOL;
#define TRUE 1
#define FALSE 0
//主要函数:
void ReadSecHead(FILE *fp); //读取节头
BOOL ReadFirstSecData(FILE *fp); //读取第一节的数据,也就是LIB的所有符号以及偏移信息(都是Big-Endian)
BOOL ReadSecondSecData(FILE *fp); //读取第二节的数据,也就是OBJ文件的数量、偏移信息
BOOL ExtractOBJFiles(FILE *fp,char *szObjDir); //提取所有OBJ文件
//辅助函数:
BOOL MoveFileSec(FILE* fpr,size_t Size,FILE* fpw); //把文件1中的内容移动到文件2(并不是逐字节移动,所以比较快,但是占内存)
void ReadOneSymbol(FILE *fp); //从文件的当前位置读取一个字符串,读到0就停止,读一个字节打印一个字节。
void PrintSecHead(); //打印节头信息
//读取到的LIB文件的一些信息
//节头信息(字符串,用空格补齐)
char g_szName; //节名
char g_szTime; //时间戳
char g_szUserID; //用户ID
char g_szGroupID; //组ID
char g_szMode; //模式
char g_szSize; //大小(除去节头外,十进制)
char g_szEnd; //结束标记("`\n")
//第一节的数据
DWORD g_dwFirstSecSymbols;
DWORD*g_pdwFirstSecSymbolOffsets;
//第二节的数据
DWORD g_dwObjFiles;
DWORD*g_pdwObjOffsets;
DWORD g_dwSymbols;
WORD* g_pwSymbolIndices;
//Big-Endian转Little-Endian的宏,汇编可以使用BSWAP指令来完成(影响可移植性,所以只用宏)
#define BE2LE(x) ((((x)&0x000000FFL)<<24)|(((x)&0x0000FF00L)<<8)|(((x)&0x00FF0000L)>>8)|(((x)&0xFF000000L)>>24))
//=============================================================================
//MoveFileSec:
//分段拷贝文件内容
//-----------------------------------------------------------------------------
BOOL MoveFileSec(FILE* fpr,size_t Size,FILE* fpw)
{
char *pBuf;
size_tlBufferSize,lBytesRest;
lBufferSize=lBytesRest=Size;
do
pBuf=(char*)malloc(lBufferSize--);
while(!pBuf&&lBufferSize);
if(!lBufferSize)
return FALSE;
lBufferSize++;
while(lBytesRest>lBufferSize)
{
fread(pBuf,1,lBufferSize,fpr);
fwrite(pBuf,1,lBufferSize,fpw);
lBytesRest-=lBufferSize;
}
fread(pBuf,1,lBytesRest,fpr);
fwrite(pBuf,1,lBytesRest,fpw);
free(pBuf);
return TRUE;
}
//=============================================================================
//ReadOneSymbol:
//读取一个符号
//-----------------------------------------------------------------------------
void ReadOneSymbol(FILE *fp)
{
int ch;
for(ch=fgetc(fp);ch;ch=fgetc(fp))
putchar(ch);
}
//=============================================================================
//ReadSecHead:
//读取节头
//-----------------------------------------------------------------------------
void ReadSecHead(FILE *fp)
{
fread(g_szName,1,16,fp); g_szName=0;
fread(g_szTime,1,12,fp); g_szTime=0;
fread(g_szUserID,1,6,fp); g_szUserID=0;
fread(g_szGroupID,1,6,fp);g_szGroupID=0;
fread(g_szMode,1,8,fp); g_szMode=0;
fread(g_szSize,1,10,fp); g_szSize=0;
fread(g_szEnd,1,2,fp); g_szEnd=0;
}
//=============================================================================
//PrintSecHead:
//打印节头
//-----------------------------------------------------------------------------
void PrintSecHead()
{
printf(
"Name:\t\t%s\n"
"Time:\t\t%s\n"
"User ID:\t%s\n"
"Group ID:\t%s\n"
"Mode:\t\t%s\n"
"Size:\t\t%s\n"
"End:\t\t%s\n"
,
g_szName,
g_szTime,
g_szUserID,
g_szGroupID,
g_szMode,
g_szSize,
g_szEnd);
}
//=============================================================================
//ReadFirstSecData:
//读取第一节数据
//-----------------------------------------------------------------------------
BOOL ReadFirstSecData(FILE *fp)
{
DWORD i;
fread(&g_dwFirstSecSymbols,1,sizeof(g_dwFirstSecSymbols),fp);
g_dwFirstSecSymbols=BE2LE(g_dwFirstSecSymbols);
printf("Symbols:%lu\n",g_dwFirstSecSymbols);
g_pdwFirstSecSymbolOffsets=(DWORD*)malloc(sizeof(DWORD)*g_dwFirstSecSymbols);
if(!g_pdwFirstSecSymbolOffsets)
{
printf("Insufficient memory.\n");
return FALSE;
}
fread(g_pdwFirstSecSymbolOffsets,sizeof(g_dwFirstSecSymbols),g_dwFirstSecSymbols,fp);
printf("Offset:\t\tSymbol name:\n");
for(i=0;i<g_dwFirstSecSymbols;i++)
{
printf("0x%08X\t",BE2LE(g_pdwFirstSecSymbolOffsets));
ReadOneSymbol(fp);
putchar('\n');
}
return TRUE;
}
//=============================================================================
//ReadFirstSecData:
//读取第二节数据
//-----------------------------------------------------------------------------
BOOL ReadSecondSecData(FILE *fp)
{
DWORD i;
fread(&g_dwObjFiles,1,sizeof(g_dwObjFiles),fp);
printf("OBJ files: %lu\n",g_dwObjFiles);
g_pdwObjOffsets=(DWORD*)malloc(sizeof(DWORD)*g_dwObjFiles);
if(!g_pdwObjOffsets)
{
printf("Insufficient memory.\n");
return FALSE;
}
fread(g_pdwObjOffsets,sizeof(DWORD),g_dwObjFiles,fp);
printf("OBJ file offsets:\n");
for(i=0;i<g_dwObjFiles;i++)
printf("\t0x%08X\n",g_pdwObjOffsets);
fread(&g_dwSymbols,1,sizeof(g_dwSymbols),fp);
printf("Symbols: %lu\n",g_dwSymbols);
g_pwSymbolIndices=(WORD*)malloc(sizeof(WORD)*g_dwSymbols);
if(!g_pwSymbolIndices)
{
printf("Insufficient memory.\n");
return FALSE;
}
fread(g_pwSymbolIndices,sizeof(WORD),g_dwSymbols,fp);
for(i=0;i<g_dwSymbols;i++)
{
printf("Symbol \"");
ReadOneSymbol(fp);
switch(g_pwSymbolIndices)
{
case 1:
printf("\" can be found in the 1st OBJ file.\n");
break;
case 2:
printf("\" can be found in the 2nd OBJ file.\n");
break;
case 3:
printf("\" can be found in the 3rd OBJ file.\n");
break;
default:
printf("\" can be found in the %uth OBJ file.\n",g_pwSymbolIndices);
break;
}
}
return TRUE;
}
//=============================================================================
//ExtractOBJFiles:
//提取OBJ文件
//-----------------------------------------------------------------------------
BOOL ExtractOBJFiles(FILE *fp,char *szObjDir)
{
FILE *fpw;
char szFile;
size_tSize;
DWORD i;
for(i=0;i<g_dwObjFiles;i++)
{
sprintf(szFile,"%s_%u.obj",szObjDir,i+1);
printf("Writing %s:\n",szFile);
fpw=fopen(szFile,"wb");
if(!fpw)
{
printf("Couldn't open %s.\n");
return FALSE;
}
fseek(fp,g_pdwObjOffsets,SEEK_SET);
ReadSecHead(fp);
printf("OBJ section information:\n");
PrintSecHead();
Size=atol(g_szSize);
if(Size)
{
if(!MoveFileSec(fp,Size,fpw))
{
printf("Couldn't write to OBJ.\n");
fclose(fpw);
return FALSE;
}
}
else
{
printf("Incorrect LIB sector header.\n");
fclose(fpw);
return FALSE;
}
printf("Success.\n\n");
fclose(fpw);
}
return TRUE;
}
//=============================================================================
//main:
//程序入口点
//-----------------------------------------------------------------------------
int main(int argc,char** argv)
{
FILE* fp;
char szSignature;
char szDir,*pch;
if(argc<2)
{
printf("Usage:\n\tANALIB LIBFILE.LIB\n");
return -1;
}
fp=fopen(argv,"rb");
if(!fp)
{
printf("Unable to open %s.\n",argv);
return -1;
}
fread(szSignature,1,8,fp); //读取文件标记
szSignature=0;
if(strcmp(szSignature,"!<arch>\n")) //判断文件标记
{
printf("Not a LIB file.\n");
fclose(fp);
return -1;
}
#define V(arg)if(!(arg)){fclose(fp);return -1;}
//读取第一个节
printf("Now is reading the 1st section in the LIB file.\n");
ReadSecHead(fp);
PrintSecHead();
V(ReadFirstSecData(fp));
//读取第二个节
printf("Now is reading the 2nd section in the LIB file.\n");
ReadSecHead(fp);
PrintSecHead();
V(ReadSecondSecData(fp));
//提取所有OBJ
printf("Now is extracting OBJ files from the LIB file.\n");
strcpy(szDir,argv);
pch=strrchr(szDir,'.');
if(pch)*pch=0;
V(ExtractOBJFiles(fp,szDir));
fclose(fp);
return FALSE;
}SRC+BIN下载: 没想到我是沙发 提取BCB编译的LIB失败啊,当然它是OMF格式,而不是COFF,不过还是麻烦楼主研究一下这个问题!!
页:
[1]