- 在线时间
- 0 小时
- 最后登录
- 2005-9-17
- 注册时间
- 2005-9-17
- 听众数
- 2
- 收听数
- 0
- 能力
- 0 分
- 体力
- 55 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 21
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 8
- 主题
- 8
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   16.84% 该用户从未签到
 |
< ><STRONG>重要声明:本文乃转载自其他社区,由于在下无法获得任何有关作者和出处的信息,所以不能在此登出,恳请作者原谅,并希望知情者能告知在下。本着资源的共享的精神,在下深信作者不会拒绝在下的转载行为。同时强烈BS数学中国的下载系统,它不但不能及时给予他人需要的帮助,还浪费了他人大量的时间,仅仅是为了获得无聊的点数,而且遗憾的是,那些点数并不能保证你真能获得帮助!</STRONG></P>: L( A& e5 C1 X- W4 E( m" f
< >下面让我们来仔细看看每一小节的内容:</P>
]+ z) j6 K0 z7 x< ><STRONG>First Sec<BR></STRONG> 第一节,通常就是Lib中的每一个小节。它的名称是“/”。其数据部分的结构如下:<BR> typedef struct {<BR> unsigned long SymbolNum; // 库中符号的数量<BR> unsigned long SymbolOffset[n]; // 符号所在目标节的偏移<BR> char StrTable[m]; // 符号名称字符串表<BR> }FirstSec;<BR> 第一个成员SymbolNum是符号的数量。注意!它是以Big-Endian方式储存的(x86平台上的数据是以Little-Endian方式储存的。这里应该注意转换。后面给出的convert函数可以在Little-Endian格式与Big-Endian格式之间进行相互转换)。<BR> 第二个成员SymbolOffset是一个数组,它的长度n就是符号的数量,也就是SymbolNum。这个数组储存了每一个符号所在的目标节的偏移。我们可以方便地通过它来查找符号所在的目标文件。注意!它也是以Big-Endian格式储存的。<BR> 第三个成员StrTable是一个字符串表,它的长度m就是SectionHeader.Size的值减去(SymbolNum+1)*4。其结构很简单,就是一堆以‘\0’结尾的字符串(和COFF文件中的字符串表结构相同)。在有的系统中,它还可能是以“/\n”这两个字符结尾的字符串的集合。<BR> 很简单的一个结构,不过有两个成员的长度是不定的。怎么才能方便地从Lib中读出这些数据,留给大家自己想吧!下面我只给出一个进行Little-Endian与Big-Endian互转的函数。<BR> inline void convert(void * p // 要转换的数据的指针<BR> ,size_t size = 4 // 数据的长度,long为4,short为2<BR> ) {<BR> char * buf=(char*)p;<BR> char temp;<BR> for ( size_t i=0;i<size/2;i++ ) {<BR> temp=buf;<BR> buf=buf[size-i-1];<BR> buf[size-i-1]=temp;<BR> }<BR> } </P>
& ?8 `8 }, x! d2 F) [<DIV> </DIV>
4 m s% W/ |2 f! I$ c9 _<DIV><STRONG>Second Sec<BR></STRONG> 现在看看第二节。<BR> 这一节与第一节很相似!它通常也就是Lib文件的第二个节。它的名字也是“/”(注意:文件中第一个叫“/”的节是第一节,第二个就是第二节)。不过它的结构与第一节有些不同,如下:<BR> typedef struct {<BR> unsigned long ObjNum; // Obj Sec的数量<BR> unsigned long ObjOffset[x]; // 每一个Obj Sec的偏移<BR> unsigned long SymbolNum; // 库中符号的数量<BR> unsigned short SymbolIdx[n]; // 符号在ObjOffset表中的索引<BR> char StrTable[m]; // 符号名称字符串表<BR> }SecondSec;<BR> 第一个成员ObjNum是库中Obj Sec的数量。<BR> 第二个成员ObjOffset是一个偏移表,它记录了库中所有Obj Sec的偏移。这个表的记录数x就是ObjNum。<BR> 第三个成员SymbolNum与First Sec中的SymbolNum意义相同。<BR> 第四个成员SymbolIdx变成了一个索引,它记录了相应名称字符串在ObjOffset这个表中的位置,我们要通过两次索引才能找到我们所要符号的Obj Sec位置。它的项目数n为SymbolNum。但请注意,这个索引是unsigned short型,不再是unsigned long型。<BR> 第五个成员StrTable结构与First Sec中的一样。不过,它的长度m为SectionHeader.Size的值减去((ObjNum+1)*4+(SymbolNum+2)*2)。<BR> 值得注意的是,这里的所有数据都是Little-Endian格式的。千万不要弄错了!<BR><BR><STRONG>Longname Sec</STRONG><BR> 这个小节就是一个字符串表,它的名称为“//”,其结构同FirstSec.StrTable。这里就不多说了。<BR><STRONG><BR>Obj Sec</STRONG><BR> 这一节中的数据就是COFF文件的原始数据,把它读出来存成文件,就是一个COFF文件。它的格式请参考《COFF格式》一文。<BR> 要指出的是它的命名方式有些特殊。如果Obj文件的名称少于16个字符,它就会被保存在SectionHeader的Name成员中,以‘/’字符结尾。如果无法保存在Name成员中,则Name成员的第一个字符就为‘/’,之后再跟上这个名称在Longname Sec中的偏移。<BR><STRONG><BR>例如</STRONG>:<BR>!<arch>\n<BR>……<BR>LongName Sec:<BR>This_Is_Long_Name0001\0<BR>This_Is_Long_Name0002\0<BR>……<BR>Obj Sec1:<BR> Name[16]:“shortname/”<BR> ……<BR>Obj Sec2:<BR> Name[16]:“/0” // 这里使用了第一个长文件名This_Is_Long_Name0001<BR> ……<BR>Obj Sec3:<BR> Name[16]:“/22” // 这里使用了第二个长文件名This_Is_Long_Name0002<BR> ……</DIV>: l( m2 e& y, B' I( v/ S
<DIV> </DIV>+ ^' G2 `5 l C( P
<DIV> OK!现在已经介绍完了Lib文件的结构。大家的连接器可以加新功能了。不过这里只给出了最基本的Lib文件结构,动态连接库(DLL)的导出库有点特别,我将在PE文件格式中进行详细介绍。</DIV> |
zan
|