PBL文件格式解析
PBL文件是PowerBuilder库文件,在其中存储了应用程序所使用到的所有系统对象和用户自定义对象的集合,同时PBL文件中还存储了源代码控制信息(Source Code Control,简称SCC)。对其文件格式的研究,可以准确地了解程序结构并能对PBL文件中的对象进行修改,同时也有利于库文件的修复,程序动态执行等方面的工作。 PBL文件的存储结构PBL文件存储信息时是以块(Block)为单位为对象分配存储空间的,每个块的大小固定为512字节,块号从0开始计算,块号与块首字节的偏移地址有如下关系:
整个PBL文件由Header块、Bitmap块、Node块、Data块组成。其中除Header块外,其它块均以链表结构组织,其中Data块是Node块中Entry表项的具体内容,是从属于Node块的。下图说明了这些块的关系。 图中Header块、首个Bitmap块及首个Node块在存储空间上是相邻的,其中Node块比较特别,占6个块共3072字节,其余块只占512字节,其空间大小及起始地址如下表所示:
Header块解析Header块是整个PBL的描述信息,它包含了PBL的版本标志,库注释,首个SCC数据块的偏移地址等信息。具体内容如下表所示:
Bitmap块解析Bitmap块中存放的是表示PBL文件存储空间的使用情况。该块数据结构如下表所示:
由上表可知,包含一个Bitmap块的PBL文件最多可使用504 * 8 = 4032个块。当文件空间超过4032个块时,就需要使用第二个Bitmap块,它的偏移地址由当前Bitmap块块内偏移0004-0007处的值表示。如果是最后一个Bitmap块,则对应的字节处为00 00 00 00,即偏移地址为0。这样就形成了Bitmap块的单向链表。 位图用于标识块的使用/空闲情况。在位图中为1的位,表示与该位序号对应的块已被使用;反之,表示对应块未使用。例如FF FF 40 00还原为位图则为11111111 11111111 01000000 00000000,该位图表示PBL文件共有18个块,其中的第16号块空闲未使用。 注意:在实际分析多个PBL文件后发现,位图中的位并不能真实反映对应块的空闲/使用情况,只是记录PBL文件使用了多少个块。 Node块解析Node块是目录块,主要用于存放Entry目录表项。下表是Node块的数据结构:
其中Entry目录表是顺序表。当一个Node块的空间不足以存储所有Entry表项时,可以再使用一个Node块来存储,并且Entry表项不能跨Node块存储,因此Node块中的空间不能完全利用,会有一定的剩余,这个值记录在块内偏移0010-0011处。 Node块的链接方式有些复杂,它使用一种称之为三叉链表(节点包含四个域:数据域、左指针域、右指针域、父指针域)的链式存储结构把所有Node块组织成为一颗二叉树,这可能是PowerBuilder为了提高查找速度而做的一些优化吧。 Entry表项解析每个Entry表项对应于一个对象的源代码或PCODE的描述信息,因此Entry目录表就是整个库中各个对象的索引表,存储了各对象的索引信息。例如,在编程中创建一个名为“pbltest”的Window对象类型,那么在Entry目录表中要存放该对象的两个索引表项,分别为“pbltest.srw”用于存储源代码,“pbltest.win”用于存储PCODE。在Entry目录表中存储的对象有以下这些:
Entry表项的具体数据结构如下表所示:
这里需要说明的是,每个Entry表项的长度并不是固定的,它随着对象名的长度变化而变化,所以要读取下一个Entry表项,只能通过计算上一个Entry表项的长度即24 + 对象名长度来得 到,或者通过搜索下一个ENT*得到。 Data块解析在Entry目录表中的各对象的实际数据内容是存储在Data块中的。Data块的数据结构如下表所示:
由上表可知,若对象的数据内容在502字节以上时,就需用多个Data块存放,这些Data块形成一个单向链表。链表的最后一个Data块的0004-0007中存储的偏移地址为00 00 00 00,表示链表结束。0010-01FF处存放的是对象的实际数据,只有最后一个Data块的长度有可能小于502,且以0x00字节表示结束。 根据上面对PBL文件格式的解析,使用Ruby开发了一个小工具,用来输出PBL文件中存储的各种信息。源代码被放在Github上面,供大家参考。 |
|
来自: quasiceo > 《powerbuilder》