0xAA55 发表于 2014-1-26 03:47:57

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下载:

as3852711 发表于 2016-2-13 22:42:36

没想到我是沙发

誓不回头 发表于 2018-5-3 20:16:44

提取BCB编译的LIB失败啊,当然它是OMF格式,而不是COFF,不过还是麻烦楼主研究一下这个问题!!
页: [1]
查看完整版本: LIB格式的文件的读取(提取OBJ)