首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> 专家专栏 >> 雨夜孤星 >> 正文
如何使用LIB文件转储动态链接库
作者:Dmitril    文章来源:newlc.com    更新时间:2006-4-20 3:53:36

                                 作者:Dmitril     2004.9.15

 

如何使用LIB文件转储动态链接库

 

有时理解应用程序连接到什么系统API是必要的。其他场合需要找到一个按次序的输出函数。这个序数可以为动态连接传给RLibrary::Lookup(色彩序数)。

Petran

Symbian为探测Symbian的内容提供一些工具。 举例来说,对Symbian E32版本,petran.exe(和SDK包含在一起) 通常在造创建转换PE时使用。但是petran也能用来转储E32文件的内容。 举例来说:

 

petran HelloWorld.app

 

将会打印E32头文件的内容, 打印转储2进制代码并打印输入功能列表, 举例来说:

............

从APPARC[10003a3d].DLL输入

       3

       6

       27

       71

............

从 EUSER[100039e5].DLL输入

       3

       809

       828

       858

       1504

       1582

       1611

............

为较多的信息观察Symbian可执行文件格式。对petran C++作为Symbian OS C++ Build工具的一部分是可用的。你可以找一个下载 Symbian OS工具的连接。 petran的大限制是不能为输入函数打印名字,这是因为这些名字不在E32文件中出现。

DepTool

 

从相同的下载连接可以下到的另一个被称为 " DepTool"是可用的 。 它同样被讨论。不像 petran ,DepTool在Perl被写。大概可能如petran一样认为:检查E32 文件格式并打印文件输入和输出。(然而, 它不打印头文件和二进转储) DepTool有一种重要的额外好处: 它会尝试查找位LIB文件通讯到给定的E32 文件并且从中得出输出文件名。 这一个功能对DLL写入者是非常有价值的,但是它不会为 HelloWorld工作,因为它不是一个DLL并且也没有LIB文件。通过DepTool的DLL我没有找到得到EUSER.DLL输出名。写我自己的Perl工程,可能使用DepDb.pm(DepTool的启动),但下面有个更加简单的解释。

Binutils

 

为了计算出从EUSER.DLL输出口#3为什么(为例)我们需要检查 euser.lib入口库。对于Windows模拟器(在 Epoc32\ release\win\udeb 中) 这个任务是很容易的: 只需运行

 

dumpbin /exports %EPOCROOT%Epoc32\release\wins\udeb\euser.lib

 

看所有的输出。但是顺序依Symbian的版本而不同。因为它被建立使用角马工具,不幸地,dumpbin不能在Symbian的Epoc32\ release\armi\urel下使用,因为它是使用GNU工具创建的。我们需要使用在Symbian SDK中Epoc32\ gcc\bin下的二进制程式(binutils)。这里有很多对lib工作的效用。举例来说," ar"允许在档案库中列举目标文件就如提取文件一样。举例来说:

ar- t 的 %EPOCROOT% Epoc32\release\armi\urel\ euser.lib

 

打印目标文件列表:

............

ds00003.o

ds00001.o

ds00002.o

ds01621.o

............

一个比较详细的信息是由" nm" 提供, 举例来说:

nm --demangle %EPOCROOT%Epoc32\release\armi\urel\euser.lib

 

prints:

............

ds00003.o:

00000000 b .bss

00000000 d .data

00000000 ? .idata$4

00000000 ? .idata$5

00000000 ? .idata$6

00000000 ? .idata$7

00000000 t .text

00000000 ? CBase::__imp_newL(unsigned int)

        U _head____EPOC32_RELEASE_ARMI_UREL_EUSER_LIB

00000000 ? _imp__newL__5CBaseUi

00000000 T CBase::newL(unsigned int)

.............

事实上,我们已经发现我们的问题答案。它出现在6.1版的"在LIB中匹配序数的输出口文件名"。这引证来自上面被提到的文件DepDb.pm 作为以上提及部分的注释。如果这是真实的, 那么ds00003.o 符合#3 ,并且它的名字是 "CBase::newL(unsigned int)"。这是从EUSER中通过HelloWorld的功能。(见上面)

 

DepDb.pm为提取序数提供了两个方法: ReadLib和ReadLibExtreme。 ReadLib调用 "nm demangle lib-name" 并且依赖与文件名与序数匹配。ReadLibExtreme完成一个比较彻底的作业而且从输入口中读取序数。首先它使用"ar -p lib-file obj-file"从 LIB 中提取目标文件,然后调用"objdump -s -j .idata\$5 obj-file-name" 转储包含序数的.idata\$5。

在我发现DepTool 和 DepDb.pm 之前我发展了自己的输出转储。我的工具叫 "objdump disassemble-all demangle lib-file" 在存档中转储所有的目标文件, 然后为".text" 解析(有输出的功能如标示) 和".idata$5",包含了序数。 这是相同的转储"ds00003.o"对象,它包含了 CBase::newL:(unsigned int):

 

C:/DOCUME~1/INBUIL~1/LOCALS~1/Temp/d1000s_00003.o:     文件格式 epoc-pe-arm-little

 

片段的分解 .text:

 

00000000 <CBase::newL(unsigned int)>:

  0:        e59fc004         ldr        r12, [pc, #4]        ; c <CBase::newL(unsigned int)+0xc>

  4:        e59cc000         ldr        r12, [r12]

  8:        e12fff1c         bx        r12

  c:        00000000         andeq        r0, r0, r0

片段的分解 .data:

片段的分解 .idata$7:

 

00000000 <.idata$7>:

  0:        00000000         andeq        r0, r0, r0

片段的分解 .idata$5:

 

00000000 <CBase::__imp_newL(unsigned int)>:

  0:        80000003         andhi        r0, r0, r3

片段的分解 .idata$4:

 

00000000 <.idata$4>:

  0:        80000003         andhi        r0, r0, r3

片段的分解.idata$6:

更多输入平台的信息请查找".idata$5"在 microsoft.com ".

这是我的 Perl源代码:

 

文件 1: epoc_exports.pl:

#目的: 读来来自标准的输入EPOC入口库的转储,

# 提取并转储序数: 成对的输出名字功能。

# 转储必须由"objdump --disassemble-all --demangle library_path.lib"创建

my $InSection = "";

my $Name = "";

while (<STDIN>) {

   #print("$_\n");

   if(($F1) = (m/Disassembly of section (\S+)\:/)) {

       #Example: Disassembly of section .text:

       #Example: Disassembly of section .idata$5:

                $InSection = $F1;

        }

   elsif(($InSection eq ".text") && (($F1) = (m/00000000 \<(.+)\>\:/))) {

       #Example: 00000000 <CBase::newL(unsigned int)>:

       $Name = $F1;

   }

   elsif(($InSection eq '.idata$5') && (($F1) = (m/^\s+0\:\s+(\S+)/))) {

       #Example:    0:        80000003         andhi        r0, r0, r3

       $Ordinal = hex($F1) & 0x7fffffff;

       printf("%d(0x%x):%s\n", $Ordinal, $Ordinal, $Name);

   }

}

 

文件 2: epoc_dump_and_export.pl:

#目的:在给定的目录中列举所有的 EPOC.lib文件并转储序数:成对命名#用法: perl epoc_dump_and_export.pl目录#路径上需要objdump的EPOC版本,File::Basename Perl module 和在相同路径中epoc_exports.pl作为当前文件。

 

use File::Basename;

 

$dir=shift(@ARGV);

$our_dir=dirname($0);

opendir(DIR, $dir) || die "can't opendir $dir: $!"; while($file = readdir(DIR)) {

   if(index($file,".lib") > 0) {

       $path = "$dir/$file";

       print("$path\n");

       system("objdump --disassemble-all --demangle $path | perl $our_dir/epoc_exports.pl > $file.exp");

   }

}

closedir DIR;

 

用法: 转储一个单独的LIB文件:

objdump--反向组译- 所有的 -- demangle%EPOCROOT% Epoc32\ release\armi\urel\ euser.lib| perl epoc_exports.pl

这将会产生来自EUSER.DLL的一个所有输出的非常长的列表:

.............

3(0 x3):CBase::newL(不签署了 int)

1(0 x1):memset

2(0 x2):memcpy

1621(0 x655):TUidType::值机员[](int)const

1620(0 x654):TRegion::值机员[](int)const

1619(0 x653):CObjectIx::值机员[](int)

1618(0 x652):CObjectCon::值机员[](int)

.............

转储所有的 LIB 文件:

perl epoc_dump_and_export.pl%EPOCROOT% Epoc32\release\armi\ urel\

这将会在给定的目录中为每个 lib文件产生一个以lib.exp为扩展名的文件。

 

结论:理解输入、输出功能名和序数可以帮助我们调试和为应用程序除错,如装载库文件和动态地调用函数一样。

相关文章:
关于60系列设备的对象调试
如何定义 Symbian WINS模拟器的内存配置
Hello World!
 

站点地图 | 加入收藏 | 联系站长 | 广告服务 |
QQ:280529124  Tel:0592-8271361 辽ICP备05021703号