最近事情比较多,驱动开发要放点时间在详细研究。说下coff格式的详细内容吧,window下就是编译过程中产生的obj文件,linux下为out文件。首先看下
http://baike.baidu.com/view/1240794.htm的内容吧,其中内容基本正确,这里只做一些补充
首先提供各我写的例子,本来就是自己看,所以变量值就用断点看吧。
用来生成例子obj的工程
#include
#include
#define PASSWORD_SIZE 100
#define PASSWORD "myGOODpassword/n"
// The CR above is needed
// so as not to cut off
// the user-entered CR.
#pragma data_seg (".kpnc")
// Note that the period before the name
// isn't mandatory, just customary.
char passwd[ ]=PASSWORD;
#pragma data_seg ()
int main ()
{
// The counter for authentication failures
int count=0;
// The buffer for the user-entered password
char buff [PASSWORD_SIZE];
// The main authentication loop
for (;;)
{
// Prompting the user for a password
// and reading it
printf ("Enter password:");
fgets (&buff [0], PASSWORD_SIZE,stdin);
// Matching the entered password against the reference value
if (strcmp (&buff [0], passwd))
// "Scolding" if the passwords don't match;
printf ("Wrong password/n");
// otherwise (if the passwords are identical),
// getting out of the authentication loop
else break;
// Incrementing the counter of authentication failures
// and terminating the program if 3 attempts have been used
if (++count>3) return -1;
}
// Once we're here, the user has entered the right password.
printf ("Password OK/n");
}
分析coff文件的工程
.h文件
iCur+=(strlen(str+iCur)+1); // 计算偏移时不要忘了计算‘/0’字符所占的1个字节!
}
free(str); // 释放字符串表空间
直到这里,整个COFF的结构已经全部介绍完了。很多了解PE格式的朋友一定会奇怪,好像少了很多内容!?是的,标准的COFF文件只有这么多的东西。但MS为了和DOS的可执行文件兼容,以及对可执行文件功能的扩展,在COFF格式中加了很多它自己的标准。让我差点就认不出COFF了。但了解了COFF文件以后,再来学习PE文件的格式,那就很简单了。
想了解PE文件的格式?网上有很多它的资料,我将在本文的基础上再写几篇文章,分别介绍PE,OMF以及ELF的格式。
现在大家可以自己动手,写一个COFF文件解析器或是一个简单的连接程序了!
*/
#pragma pack(push)
#pragma pack(1)
typedef struct{
unsigned short usMagic;
unsigned short usNumSec;
unsigned long ulTime;
unsigned long ulSymolOffset;
unsigned long ulNumSymbol;
unsigned short usOptHdrSZ;
unsigned short usFlags;
}COFF_FILE_HEADER;
typedef struct {
unsigned short usMagic;
unsigned short usVersion;
unsigned long ulTextSize;
unsigned long ulInitDataSZ;
unsigned long ulUnintiDataSZ;
unsigned long uEntry;
unsigned long ulTextBase;
unsigned long ulDataBase;
}OPTHDR;
typedef struct {
char cName[8];
unsigned long ulVSize;
unsigned long ulVAddr;
unsigned long ulSize;
unsigned long ulSecOffset;
unsigned long ulRelOffset;
unsigned long ulLNOffset;
unsigned short ulNumRel;
unsigned short ulNumLN;
unsigned long ulFlags;
}SECHDR;
typedef struct {
unsigned long ulAddr;/* virtual address of reference */
unsigned long uSymbol;
unsigned short usType;
} RELOC;
typedef struct {
unsigned long ulAddrORSymbol;
unsigned short usLineNq;
} LINENO;
typedef struct {
union {
char cName[8];
struct {
unsigned long ulZero;
unsigned long ulOffset;
}e;
}e;
unsigned long ulValue;
short iSection;
unsigned short usType;
unsigned char usClass;
unsigned char usNumAux;
}SYMENT;
#pragma pack(pop)
.cpp
#include "stdafx.h"
#include "coffHeader.h"
#include "stdlib.h"
#include
#include
using namespace std;
#define MaxMemoryBlock 200
void* pMemBlock[MaxMemoryBlock];
void ClearMallocBlock()
{
int iFreeCnt = 0;
while(iFreeCnt++
free(pMemBlock[iFreeCnt]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int nMemCount = 0;
FILE *pCoffFile = fopen("F://0501//Debug//erw.obj","rb+");
int nSectionTotal0ffset = 0;
/*
char rt[500];
fread(rt,1,500,pCoffFile);
int ct = 0;
while(ct++ < 500)
{
if(rt[ct]=='.')
int er = 0;
}
*/
vector
vector
vector
vector
unsigned long ulCheckNum = 0;
COFF_FILE_HEADER *pCoffHeader = (COFF_FILE_HEADER*)malloc(sizeof(COFF_FILE_HEADER));
if(pCoffHeader==NULL)
{
return -1;
}
fread(pCoffHeader,1,sizeof(COFF_FILE_HEADER),pCoffFile);
nSectionTotal0ffset += sizeof(COFF_FILE_HEADER);
printf("the magic number is %d/n",pCoffHeader->usMagic);
printf("the usNumSec is %d/n",pCoffHeader->usNumSec);
if(pCoffHeader->usOptHdrSZ != 0)
{
printf("There is a Opt Header!/n");
OPTHDR *pOptHdr = (OPTHDR*)malloc(sizeof(OPTHDR));
if(pOptHdr==NULL)
return -1;
fread(pOptHdr,1,sizeof(OPTHDR),pCoffFile);
nSectionTotal0ffset+=sizeof(OPTHDR);
}
int nSectionNum = pCoffHeader->usNumSec;
int nTempSectionNum = nSectionNum;
while(nTempSectionNum-->0)
{
SECHDR *pSectionHeader = (SECHDR*)malloc(sizeof(SECHDR));
if(pSectionHeader==NULL)
{
return -1;
}
fseek(pCoffFile,nSectionTotal0ffset,SEEK_SET);
fread(pSectionHeader,1,sizeof(SECHDR),pCoffFile);
printf("Section Name is %s/n",pSectionHeader->cName);
nSectionTotal0ffset+=sizeof(SECHDR);
vSecHdr.push_back(pSectionHeader);
unsigned long lSectionDataSize = pSectionHeader->ulSize;
fseek(pCoffFile,pSectionHeader->ulSecOffset,SEEK_SET);
void* pSectionData = (void*)malloc(lSectionDataSize);
if(pSectionData==NULL)
{
return -1;
}
fread(pSectionData,1,lSectionDataSize,pCoffFile);
vSecData.push_back(pSectionData);
// RELOC Content
if(pSectionHeader->ulSecOffset > 0)
{
fseek(pCoffFile,pSectionHeader->ulRelOffset,SEEK_SET);
int nRelocStruct = pSectionHeader->ulNumRel;
while(nRelocStruct-->0)
{
RELOC* pReloc = (RELOC*)malloc(sizeof(RELOC));
if(pReloc==NULL)
return -1;
fread(pReloc,1,sizeof(RELOC),pCoffFile);
ulCheckNum = pReloc->uSymbol;
vReloc.push_back(pReloc);
}
}
// LINENUM Content
if(pSectionHeader->ulLNOffset > 0)
{
fseek(pCoffFile,pSectionHeader->ulLNOffset,SEEK_SET);
int nLineNumStruct = pSectionHeader->ulNumLN;
while(nLineNumStruct-->0)
{
LINENO* pLineNum = (LINENO*)malloc(sizeof(LINENO));
if(pLineNum==NULL)
return -1;
fread(pLineNum,1,sizeof(LINENO),pCoffFile);
vLineNo.push_back(pLineNum);
}
}
}
//Symbol table
FILE *pSymbolFind = pCoffFile;
fseek(pSymbolFind,pCoffHeader->ulSymolOffset,SEEK_SET);
unsigned long nSymbolNum = pCoffHeader->ulNumSymbol;
vector
while(nSymbolNum--)
{
SYMENT *pSyment = (SYMENT*)malloc(sizeof(SYMENT));
fread(pSyment,1,sizeof(SYMENT),pSymbolFind);
vSymentTotal.push_back(pSyment);
}
int iStrlen,iCur=4; // iStrLen是字符串表的长度,iCur是当前字符串偏移
char *str; // 字符串表
fread(&iStrlen,1, 4,pSymbolFind); // 得到字符串表长度
str = (char *)malloc(iStrlen); // 为字符串表分配空间
// 读字符串表,直到全部读入内存
fread(str,1,iStrlen,pSymbolFind);
iCur=4; // 把当前字符串偏移指到每一个字符串
while (iCur
iCur+=(strlen(str+iCur)+1); // 计算偏移时不要忘了计算‘/0’字符所占的1个字节!
}
free(str); // 释放字符串表空间
fclose(pCoffFile);
return 0;
}
设断点就可以看到各项内容,另外在看一下http://osr507doc.sco.com/en/topics/COFF_SymValFld.html的内容,这个比较详细。
说我补充的几个内容吧,
1.File Header
Optional Header
Section Header 1
......
Section Header n
Section Data 1
Relocation Directives 1
Line Numbers 1
Section Data 2
Relocation Directives 2
Line Numbers 2
Symbol Table
String Table
每一部分的section data后面是接reloc Directive 和line number的信息的例如
例如:.text 的
ulSize = 162
ulSecOffset = 1328
ulRelOffset = 1490
ulLNOffset = 1600
ulNumRel = 11
ulNumLN = 11
下一段 dataoffset为 1666
按照这个结果显示
1328 + 162 = 1490
1490 + 11 *10 = 1600
1600 + 11*6 = 1666
可以看出各部分是完全没有空隙的连接的
2.reloc 表的 ulSymbol 这个所谓符号表索引为就是只第一个,比如coff头说有48个符号,那么ulSymbol
的值小于48,就是指第一个,
在我这里lineNum的ulAddrorsymbol的对应项是address ,至于这个需要对照IDA的结果看了,所以vc编译器的断点可以放在大括号上吧。
3.IDA把.debug$S .debug$T这个没有地址分配的section没有列出来,不过我看了一下,基本都是说明文件路径,lib名等一些辅助信息的,并没有什么实际意义