现在的位置: 首页 > 综合 > 正文

powerbuilder P-code 中的JP跳转指令的反向工程

2017年12月08日 ⁄ 综合 ⁄ 共 6634字 ⁄ 字号 评论关闭

在我的decomplier中关闭JP to statement开关后,得到原始的未经过处理的跳转指令。

类似汇编中我们写的跳转。这就是高级语言和低级语言的差别。低阶语言更繁琐和趋近于机器处理过程。比如汇编中的寻址,基本就是cpu取数和处理数的一个过程。

 

P-code中,顺序结构倒好处理,直接把赋值,函数调用搞定也就没什么了,唯一需要处理的是这些跳转。

 

在汇编中,有许多种的跳转,比如等跳,不等跳等等。。但是在高级语言,如pb中,语言有bool的明确规定,所以if while等conditon部分都必须是bool类型的结构,这也就是c++中比较你写=,不写==不会发生错误的原因,你在pb中的条件判定处写=,编译器就知道是逻辑意义上的判断,而不是赋值。因为没有其他值到bool的隐式转化。所以在pb中,我们只有三种跳转,JTP,JFP,JXP,分别是“为真跳”,“为假跳”,“绝对跳”。当然只是知道这三种区别还不行,还没足够信息反向成高级语言中的statement,我们在分析代码时,顺便在前期已经将跳转时当前offset,和will to address做了比较,区分出了“往前跳”,还是“往后跳”,这样我们不会在长长的字符串中再来繁琐地判定(效率低)。

 

我们编写了几种结构加于分析区别,以便还原。找出其中一些规律。因为现代编程习惯中,已经废弃了goto的使用,虽然它还是关键字,但是我们约定,我们写的statement都是成块的。这样有助于我们得到一个模糊的表述。

 

代码          _0012:     _L_       (1) = 2              _J_F_F_0032

意义:       地址          logic       expression       JP

 

我们拿两个相近似的结构来对比:

(A)

_0000: ls_note = "if ... end if"

_0012: _L_ (1) = 2 _J_F_F_0032
_0024: ll_1 = 1
_0032:

 

(B)

_0052: ls_note = "if ... else ... end if"
_0064: _L_ (1) = 2 _J_F_F_0088
_0076: ll_1 = 3
_0084: _J_X_F_0096
_0088: ll_1 = 3
_0096

 

在a结构中我们看到,可以这么描述我们即将编程的伪码:

如果存在logic(没有logic的话,那就只有goto语言产生的绝对跳转了),并且存在“往后跳”,并且遍历当前行到“跳转目标行”之间再无“logic”和“其他跳转指令”,那我们复活成一条“if ... then ... end if”语句。

 

在b结构中,我们描述为:

如果存在logic,并且存在“往后跳”,并且遍历当前行到“跳转目标行”之间存在“绝对往后跳”,那我们复活成“if ... then ...else ...end if”语句。

 

当然,这也存在嵌套问题,我想出于简化的设计思路,就没必要用递归。可以采用层层剥菜的方式,先处理内层,处理完后扫描一次即可。

就是必须把“最小的块”找到,然后先处理。

 

以上只是大致思路。还未具体实现,估计得耗时几天才能处理好。

 

//20090908:statement反向已经满意搞定,包括缩进显示,都搞好了。

//object name: lf_333.fun
global type lf_333 from lf_333
end type

forward prototypes
global subroutine  lf_333() throws exception
end prototypes

global subroutine  lf_333() throws exception;
//variables list
long ll_1
long a
string ls_note
//global var: string gs_id5

//expression lines: 66

gs_id5 = ""
ls_note = "if ... end if"

if 1 = 2 then
 ll_1 = 1
end if

ls_note = "if .do loop unitl. end if"
1 = 2
ll_1 = 2

do
 ll_1 = 8

 if 1 = 2 then
  ll_1 = 2
 end if

loop while ll_1 = 0

ls_note = "if ... else ... end if"

if 1 = 2 then
 ll_1 = 3
 ll_1 = 3
 ll_1 = 3
else
 ll_1 = 3
 ll_1 = 3
 ll_1 = 3
end if

ls_note = "do while ... loop"

do while ll_1 = 0
 ll_1 = 5
loop

ls_note = "do until ... loop"

do until ll_1 = 0
 ll_1 = 6
loop

ls_note = "do ...loop while"

do
 ll_1 = 7
loop while ll_1 = 0

ls_note = "do ...loop until"

do
 ll_1 = 8
loop while ll_1 = 0

ls_note = "if if if if if end if end if end if end if"

if a = 0 then

 if a = 0 then

  if a = 0 then

   if a = 0 then
    a = 0
   end if

  end if

 end if

end if

ls_note = "choose case.. end choose"

choose case ll_1
 case 1
  ll_1 = 111
  
 case 2
  ll_1 = 111
  
 case 3
  ll_1 = 111
  
 case 4
  ll_1 = 111
  
 case 5
  ll_1 = 111
end choose

choose case ll_1
 case 1
  ll_1 = 222
  
 case 2 , 3 , 4 , 5
  ll_1 = 222
  
 case  2 to  5
  ll_1 = 222
  
 case is >= 3

  do while 1 = 2
   ll_1 = 222
  loop

  ll_1 = 222
  
 case (1 ) ,  2 to  5 ,  5
  ll_1 = 222
end choose

end function

 

 

 

 

////////////////////////////////////////////

顺便写写关键字的缩进处理。

声明结构并初始化:

const strc_INDENTATION KEY_INDENTATION[MAX_KEY_INDENTATION] = {
            1,"if",2,
            3,"else",4,
            3,"elseif",6,
            2,"end",3,
            1,"for",3,
            2,"next",4,
            4,"choose",6,    //特殊,因为case要 -t
            5,"end choose",10,    //特殊,因为case要 -t
            3,"case",4,
            1,"while",5,
            1,"do",2,
            2,"loop",4,
            1,"try",3,
            3,"catch",5,
            3,"finally",7
};

 

 

//直接给代码,很简单也不用解释了。

int iIndent0 = 0;    //current
    short iChanged;
    astring asIndent;
    char chFirst;
   
    ilines = MemoProcess->Lines->Count;
   
    for(int i = 0;i < ilines;i++){
        iChanged = 0;    //是否改变缩进个数
        chFirst = MemoProcess->Lines->Strings[i][1];
        if ('i' == chFirst || 'e' == chFirst || 'f' == chFirst || 'n' == chFirst ||
            'c' == chFirst || 'w' == chFirst || 'd' == chFirst || 'l' == chFirst || 't' == chFirst)
        {
           for(int k = 0;k < MAX_KEY_INDENTATION;k++){
                if(LeftStr(MemoProcess->Lines->Strings[i],KEY_INDENTATION[k].cLen) == KEY_INDENTATION[k].KeyWords){
                   iChanged = KEY_INDENTATION[k].flag;
                   break;   //匹配后退出for内层
                }
            }
        }

        switch (iChanged){
            case 0:        //no changed
                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }
                break;
            case 1:         //do this,next to change
                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }
               
                asIndent = AnsiString::StringOfChar('/t',++iIndent0);
                break;
            case 2:         //change first,then do this row
                if (iIndent0 > 0){
                    asIndent = AnsiString::StringOfChar('/t',--iIndent0);
                }

                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }
                break;
            case 3:         //change +t,do this row,then -t for next
                asIndent = AnsiString::StringOfChar('/t',++iIndent0);
                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }

                if (iIndent0 > 0) {
                    asIndent = AnsiString::StringOfChar('/t',--iIndent0);
                }
               
                break;
            case 4:         //using choose所以必须先加2t
                ++iIndent0;
                asIndent = AnsiString::StringOfChar('/t',++iIndent0);
                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }

                if (iIndent0 > 0) {
                    asIndent = AnsiString::StringOfChar('/t',--iIndent0);
                }
               
                break;
            case 5:         //using end choose所以必须先 -2t
                 if (iIndent0 > 1) {
                    iIndent0 -=2;
                    asIndent = AnsiString::StringOfChar('/t',iIndent0);
                }

                if (iIndent0 > 0) {
                    MemoProcess->Lines->Strings[i] = asIndent + MemoProcess->Lines->Strings[i];
                }
               
                break;
        }
    }

 

//附:

global subroutine  lf_333() throws exception;
//variables list
long ll_1
long a
string ls_note

//exprssion  lines: 42
_0000: ls_note = "if ... end if"
_0012: _L_ (1) = 2 _J_F_F_0032
_0024: ll_1 = 1
_0032: _L_ (1) = 2 _J_F_F_0052
_0044: ll_1 = 2
_0052: ls_note = "if ... else ... end if"
_0064: _L_ (1) = 2 _J_F_F_0088
_0076: ll_1 = 3
_0084: _J_X_F_0096
_0088: ll_1 = 3
_0096: ls_note = "if ... elseif ... end if"
_00A8: _L_ (1) = 2 _J_F_F_00CC
_00BA: ll_1 = 4
_00C8: _J_X_F_00EC
_00CC: _L_ (2) = 3 _J_F_F_00EC
_00DE: ll_1 = 4
_00EC: ls_note = "do while ... loop"
_00FE: _L_ (ll_1) = 0 _J_F_F_0120
_010E: ll_1 = 5
_011C: _J_X_B_00FE
_0120: ls_note = "do until ... loop"
_0132: _L_ (ll_1) = 0 _J_T_F_0154
_0142: ll_1 = 6
_0150: _J_X_B_0132
_0154: ls_note = "do ...loop while"
_0166: ll_1 = 7
_0174: _L_ (ll_1) = 0 _J_T_B_0166
_0184: ls_note = "do ...loop until"
_0196: ll_1 = 8
_01A4: _L_ (ll_1) = 0 _J_F_B_0196
_01B4: ls_note = "if if if if if end if end if end if end if"
_01C6: _L_ (a) = 0 _J_F_F_0214
_01D6: _L_ (a) = 0 _J_F_F_0214
_01E6: _L_ (a) = 0 _J_F_F_0214
_01F6: _L_ (a) = 0 _J_F_F_0214
_0206: a = 0
_0214: _END
end function

抱歉!评论已关闭.