QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2187|回复: 1
打印 上一主题 下一主题

[转载]COFF文件格式(4)

[复制链接]
字体大小: 正常 放大
Blackbird        

8

主题

2

听众

21

积分

升级  16.84%

该用户从未签到

新人进步奖

跳转到指定楼层
1#
发表于 2005-9-17 14:02 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<><STRONG>重要声明:本文乃转载自其他社区,由于在下无法获得任何有关作者和出处的信息,所以不能在此登出,恳请作者原谅,并希望知情者能告知在下。本着资源的共享的精神,在下深信作者不会拒绝在下的转载行为。同时强烈BS数学中国的下载系统,它不但不能及时给予他人需要的帮助,还浪费了他人大量的时间,仅仅是为了获得无聊的点数,而且遗憾的是,那些点数并不能保证你真能获得帮助!</STRONG></P>+ H. w; A7 s4 M6 a. D
<><STRONG>重定位表<br></STRONG>    这个表所保存的是各个段的重定位信息。这是一张很大的表,因为所有段的重定位信息都在这个表里。各个段落头记录了自己的重定位信息的偏移和数量。要用到重定位信息时就到这个表里来读。当然,你也可以把整个重定位表看成多个重定位表,每个段落都有一个自己的重定位表。这个表只在目标文件中有,可执行文件中是不存在这个表的。<br>    既然有表,那么就会有记录。重定位表中的每一条记录就是一条重定位信息。这个记录的结构很简单,如下:<br>typedef struct {<br>  unsigned long  ulAddr;  // 定位偏移<br>  unsigned long  ulSymbol;  // 符号<br>  unsigned short usType;  // 定位类型<br>} RELOC;<br>    有够简单吧,一共只三个成员!ulAddr是要定位的内容在段内偏移。比如:一个正文段,起始位置为0x010,ulAddr的值为0x05,那你的定位信息就要写在0x15处。而且信息的长度要看你的代码的类型,32位的代码要写4个字节,16位的就只要字2个字节。<br>    ulSymbol是符号索引,它指向符号表中的一个记录。注意,这里是索引,不是偏移!它只是符号表中的一个记录的记录号。这个成员指明了重定位信息所对映的符号。<br>usType是重定位类型的标识。32位代码中,通常只用两种定位方式。一是绝对定位,二是相对定位。其代码如下:<br>  v$ F0 Q+ @' I6 D: A
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width="80%" align=center bgColor=#ffffff borderColorLight=#000000 border=1>8 X) C$ X4 D3 o& n

2 b5 r9 R1 L) j5 ]2 a<TR>
0 L7 w, Z& a5 O5 t& t1 F7 @<TD vAlign=top width=55>值</TD>
) V; _; p. d% b& t$ W% @4 e* r<TD vAlign=top width=72>名称 </TD>5 n, Z$ d: a- U% C
<TD vAlign=top width=441>说明</TD></TR># s: d: A8 a( |/ C6 [: q: P; ^
<TR>& r3 u' X! Z9 r" o3 Z, U7 q0 ?
<TD vAlign=top width=55>6</TD>% r2 [. y0 o" A$ j0 r* a
<TD vAlign=top width=72>RELOC_ADDR32</TD>
$ ?/ T% T/ z! o5 a5 U7 \1 Y& f9 a' Q: a<TD vAlign=top width=441>32位绝对定位。</TD></TR>
6 Z  {2 H+ z8 V  E9 s<TR>
7 g8 l0 J1 U8 x6 p" p8 k2 K/ |6 m<TD vAlign=top width=55>20</TD>4 J2 O$ `1 C/ {$ \& p+ p
<TD vAlign=top width=72>RELOC_REL32 </TD>! |9 ?; A* d& k0 E$ \
<TD vAlign=top width=441>32位相对定位。</TD></TR></TD></TR></TABLE>    对于不同的处理器,这些值也不尽相同。这里给出的是i386平台上最常用的两个种定位方式的标识。<br>    其定位方式如下:<br>    <STRONG>绝对定位</STRONG><br>    在绝对定位方式下,你要给出符号的绝对地址(注意,有时候这里可能不是地址,而是值,对于常量来说,你不用给出它的地值,只用给出它的值)。当然,这个地址也不是现成的,你要用符号的相对地址+它所在段的相对地址来得到它的绝对地址。<br>    <STRONG>公式:符号绝对地址=段偏移+符号偏移</STRONG><br>    这些偏移量你要分别从段落头和符号表中得到。当段落要重定位时,当然还要先重定位段落,才能定位其中的符号。<br>    <STRONG>相对定位</STRONG><br>    相对定位要复杂一些。它所要的地址信息是相对于当前位置的偏移,这个当前位置就是ulAddr所指向的这个偏移的绝对地址后四个字节(32位代码是四个字节,16位是两个字节)的位置。也就是用定位偏移+当前段偏移+机器字长÷8<br>    <STRONG>公式:当前地址=定位偏移+当前段偏移+机器字长÷8</STRONG><br>    有了当前地址,相对地址就好计算了。只要用符号的绝对地址减去当前地址就可以了。<br>    <STRONG>公式:相对地址=符号绝对地址-当前地址</STRONG><br>    计算好了地址,把它写到ulAddr所指向的位置,就一切OK!你已经完成了重定位的工作了。<br><br>    <STRONG>行号表</STRONG><br>    行号表在调试时很有用。它把可执行的二进制代码与源代码的行号之间建立了对映关系。这样,当程序执行不正确时(其实正确的也可以<FONT color=#000000>J</FONT>),我们就可以根据当前执行代码的位置得知出错源代码的行号,再加以修改。如果没有它的话,鬼才知道是哪一行出了毛病!<br>    它的格式也很简单。只有两个成员,如下:<br>typedef struct {<br>    unsigned long ulAddrORSymbol;  // 代码地址或符号索引<br>    unsigned short usLineNo;  // 行号<br>} LINENO;<br>    让我们先看第二个成员,usLineNo。这是一个从1开始计数的计数器,它代表源代码的行号。第一个成员ulAddrORSymbol在行号大于0时,代表源代码的地址;而当行号为0时,它就成了行号所对映的符号在符号表中的索引。下面让我们来看看符号表吧!<br></P>
: b6 d0 o0 z) a' e) T! c2 e6 q6 v7 b
[此贴子已经被作者于2005-9-17 14:59:16编辑过]
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信

1

主题

2

听众

60

积分

升级  57.89%

该用户从未签到

新人进步奖

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-4-20 04:34 , Processed in 0.413729 second(s), 57 queries .

回顶部