Delphi/C++ Builder Map文件格式解析

【转载请注明出处及作者,文章发现问题会随时更新,要保证浏览最新版本,请访问官网:blog.qdac.cc】

Delphi或C++ Builder在编译程序链接时,可以选择生成扩展名为.map的文件符号映射文件,这个文件记录了程序中各个函数、变量的地址等信息,我们今天要做的就是解析这个文件的格式,以便在QWorker中,能够实时跟踪当前正在执行的作业函数。

首先,我们来了解一下如果让编译器生成map文件:

在工程选项里(Project->Options->Delphi Compiler->Linking),将其中的 Map file generate 设置为Detail模式,以便生成我们需要的符号映射文件。

QQ截图20140926103358

然后我们了详细了解所生成的文件格式:

一、段定义表

此部分描述了各个段的索引号、起始地址、长度、名称和类型信息。我们要查找函数的地址和代码行号等信息,只需要关心第一个代码段的(CODE)内容就可以。

我们可以看到这个映射文件中,序号是0001,后面我们只关心它这一类型的定义。代码段的起始偏移地址是0x00401000,其长度是0x00227CC8(2260168)。

二、段详细映射表

这个表标明了段的详细分配情况,依次是段类别序号:段内偏移、长度、类型、段名称、分组(?不确定)、命名空间,ACBP不清楚是什么

通过段起始偏移+段内偏移,可以很容易看到相应部分代码所隶属的命名空间,反过来也可以很容易的找到命名空间对应的代码范围。在我们的需求中,这段没有使用。

三、函数映射表

这个表记录了每个函数的地址偏移情况,可以根据指定的函数指针地址或EIP寄存器的值,得到其对应的函数名称:

这个只包含两列:地址(段序号:段内偏移地址)、函数名(Publics by Name),解析起来很简单。

四、代码行映射表

这个表记录了每一行对应的代码地址偏移,其行标题指名了其命名空间和文件名。同一命名空间,如果位于不同文件中,会被分成不行的列表。我们在QMapSymbols实现时,没有使用前面段详细信息映射表,直接解析了此处的内容,得到命名空间和源码所在的文件名。

这个映射表每项实际由两部分构成:行号、地址(段序号:段内偏移),解析时注意这个映射表有很多,每个源码+命名空间组合就是一个。

【附注】

我们忽略了三个部分的说明:

1、Publics by value小节的内容的解析,那里记录的是全局变量等的映射信息,我们用不到,所以没有使用。

2、Bound resource files是绑定的资源文件信息,我们用不到,所以也就忽略未曾添加。

3、Program entry point at 是程序入口地址,我们也用不到,忽略。

【地址换算】

注意计算实际程序时址时,要加上一个起始偏移量的,如

QQ截图20140924154616

图中的代码地址是0x006206CB,转换成Map文件中的地址要减去第一个段中声明的代码段的起始偏移量0x00401000,得到的结果是0x21F6CB,然后我们在Map文件中找这个地址,可以得出结果为:

分享到:

4 条评论

沙发空缺中,还不快抢~