1 /**
2  * @namespace   biew_plugins_I
3  * @file        plugins/disasm.c
4  * @brief       This file contains universal interface for any disassembler.
5  * @version     -
6  * @remark      this source file is part of Binary vIEW project (BIEW).
7  *              The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8  *              All rights reserved. This software is redistributable under the
9  *              licence given in the file "Licence.en" ("Licence.ru" in russian
10  *              translation) distributed in the BIEW archive.
11  * @note        Requires POSIX compatible development system
12  *
13  * @author      Nickols_K
14  * @since       1995
15  * @note        Development, fixes and improvements
16  * @author      Kostya Nosov <k-nosov@yandex.ru>
17  * @date        12.09.2000
18  * @note        Adding virtual address as argument of jump and call insns
19  * @author      Mauro Giachero
20  * @date        02.11.2007
21  * @note        Reworked inline assemblers support
22 **/
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <limits.h>
27 #include <errno.h>
28 #include <ctype.h>
29 
30 #include "colorset.h"
31 #include "bmfile.h"
32 #include "bin_util.h"
33 #include "plugins/hexmode.h"
34 #include "plugins/disasm.h"
35 #include "biewutil.h"
36 #include "reg_form.h"
37 #include "bconsole.h"
38 #include "editor.h"
39 #include "codeguid.h"
40 #include "search.h"
41 #include "tstrings.h"
42 #include "biewlib/file_ini.h"
43 #include "biewlib/biewlib.h"
44 #include "biewlib/pmalloc.h"
45 #include "biewlib/kbd_code.h"
46 
47 extern REGISTRY_DISASM ix86_Disasm;
48 extern REGISTRY_DISASM Null_Disasm;
49 extern REGISTRY_DISASM AVR_Disasm;
50 extern REGISTRY_DISASM ARM_Disasm;
51 extern REGISTRY_DISASM PPC_Disasm;
52 extern REGISTRY_DISASM Java_Disasm;
53 
54 static REGISTRY_DISASM *mainDisasmTable[] =
55 {
56   &Null_Disasm,
57   &ix86_Disasm,
58   &Java_Disasm,
59   &AVR_Disasm,
60   &ARM_Disasm,
61   &PPC_Disasm
62 };
63 
64 static unsigned DefDisasmSel = __DEFAULT_DISASM;
65 REGISTRY_DISASM *activeDisasm = NULL;
66 
67 static unsigned long PrevPageSize,CurrPageSize,PrevStrLen,CurrStrLen;
68 unsigned disNeedRef = 0;
69 int DisasmCurrLine;
70 unsigned disPanelMode = 0;
71 static int           HiLight = 1;
72 static unsigned char *CurrStrLenBuff = NULL;
73 static unsigned long *PrevStrLenAddr = NULL;
74 static char          LastPrevLen;
75 static char          PrevStrCount = 0;
76 static char *        disCodeBuffer = NULL,*disCodeBuf2 = NULL;
77 static char *        disCodeBufPredict = NULL;
78 static int           disMaxCodeLen;
79 
80 tBool DisasmPrepareMode = False;
81 
82 char *   dis_comments;
83 unsigned dis_severity;
84 
85 static void __NEAR__ __FASTCALL__ disAcceptActions( void );
86 
disSelect_Disasm(void)87 static tBool __FASTCALL__ disSelect_Disasm( void )
88 {
89   const char *modeName[sizeof(mainDisasmTable)/sizeof(REGISTRY_DISASM *)];
90   size_t i,nModes;
91   int retval;
92 
93   nModes = sizeof(mainDisasmTable)/sizeof(REGISTRY_DISASM *);
94   for(i = 0;i < nModes;i++) modeName[i] = mainDisasmTable[i]->name;
95   retval = SelBoxA(modeName,nModes," Select disassembler: ",DefDisasmSel);
96   if(retval != -1)
97   {
98     if(activeDisasm->term) activeDisasm->term();
99     activeDisasm = mainDisasmTable[retval];
100     DefDisasmSel = retval;
101     disAcceptActions();
102     return True;
103   }
104   return False;
105 }
106 
FillPrevAsmPage(__filesize_t bound,unsigned predist)107 static void __FASTCALL__ FillPrevAsmPage(__filesize_t bound,unsigned predist)
108 {
109   __filesize_t distin,addr;
110   unsigned j;
111   unsigned totallen;
112   tAbsCoord height = twGetClientHeight(MainWnd);
113   char showref,addrdet;
114   if(!predist) predist = height*disMaxCodeLen;
115   predist = (predist/16)*16+16;   /** align on 16-byte boundary */
116   distin = bound >= predist ? bound - predist : 0;
117   memset(PrevStrLenAddr,TWC_DEF_FILLER,height*sizeof(long));
118   PrevStrCount = 0;
119   totallen = 0;
120   showref = disNeedRef;
121   addrdet = hexAddressResolv;
122   hexAddressResolv = 0;
123   disNeedRef = 0;
124   DisasmPrepareMode = True;
125   for(j = 0;;j++)
126   {
127     DisasmRet dret;
128        addr = distin + totallen;
129        BMReadBufferEx(disCodeBuffer,disMaxCodeLen,addr,BM_SEEK_SET);
130        dret = Disassembler(distin,(void *)disCodeBuffer,__DISF_SIZEONLY);
131        if(addr >= bound) break;
132        totallen += dret.codelen;
133        if(j < height) PrevStrLenAddr[j] = addr;
134        else
135        {
136           memmove(PrevStrLenAddr,&PrevStrLenAddr[1],(height - 1)*sizeof(long));
137           PrevStrLenAddr[height - 1] = addr;
138        }
139   }
140   PrevStrCount = j < height ? j : height;
141   LastPrevLen = PrevStrCount ? bound - PrevStrLenAddr[PrevStrCount - 1] : 0;
142   disNeedRef = showref;
143   DisasmPrepareMode = False;
144   hexAddressResolv = addrdet;
145 }
146 
PrepareAsmLines(int keycode,__filesize_t cfpos)147 static void __FASTCALL__ PrepareAsmLines(int keycode,__filesize_t cfpos)
148 {
149   tAbsCoord height = twGetClientHeight(MainWnd);
150   switch(keycode)
151   {
152     case KE_DOWNARROW:
153                     PrevStrLen = CurrStrLenBuff[0];
154                     CurrStrLen = CurrStrLenBuff[1];
155                     if((unsigned)PrevStrCount < height) PrevStrCount++;
156                     else                                memmove(PrevStrLenAddr,&PrevStrLenAddr[1],sizeof(long)*(height - 1));
157                     PrevStrLenAddr[PrevStrCount - 1] = cfpos - CurrStrLenBuff[0];
158                     PrevPageSize = PrevStrLenAddr[PrevStrCount - 1] - PrevStrLenAddr[0] + PrevStrLen;
159                     break;
160     case KE_PGDN:
161                     {
162                       size_t i;
163                       unsigned size;
164                       __filesize_t prevpos;
165                       size = Summ(CurrStrLenBuff,height);
166                       prevpos = cfpos - size;
167                       size = 0;
168                       for(i = 0;i < height;i++)
169                       {
170                           size += CurrStrLenBuff[i];
171                           PrevStrLenAddr[i] = prevpos + size;
172                       }
173                       PrevStrLen = CurrStrLenBuff[height - 1];
174                       PrevPageSize = size;
175                       PrevStrCount = height;
176                     }
177                     break;
178    case KE_UPARROW:
179                     FillPrevAsmPage(cfpos,(unsigned)(PrevPageSize + 15));
180                     goto Calc;
181     default:
182                     FillPrevAsmPage(cfpos,0);
183     Calc:
184                     if(PrevStrCount)
185                     {
186                       PrevStrLen = LastPrevLen;
187                       PrevPageSize = PrevStrLenAddr[PrevStrCount - 1] + LastPrevLen - PrevStrLenAddr[0];
188                     }
189                     else
190                     {
191                       PrevStrLen = 0;
192                       PrevPageSize = 0;
193                     }
194                     break;
195   }
196 }
197 
drawAsm(unsigned keycode,unsigned textshift)198 static unsigned __FASTCALL__ drawAsm( unsigned keycode, unsigned textshift )
199 {
200  int i,I,Limit,dir,orig_commpos,orig_commoff;
201  size_t j,len,len_64;
202  __filesize_t cfpos,flen,TopCFPos;
203  static __filesize_t amocpos = 0L;
204  char outstr[__TVIO_MAXSCREENWIDTH];
205  char savstring[20];
206  HLInfo hli;
207  ColorAttr cattr;
208  flen = BMGetFLength();
209  cfpos = TopCFPos = BMGetCurrFilePos();
210  if(keycode == KE_UPARROW)
211  {
212    char showref,addrdet;
213    DisasmRet dret;
214    showref = disNeedRef;
215    addrdet = hexAddressResolv;
216    disNeedRef = hexAddressResolv = 0;
217    BMReadBufferEx(disCodeBuffer,disMaxCodeLen,cfpos,BM_SEEK_SET);
218    DisasmPrepareMode = True;
219    dret = Disassembler(cfpos,(void *)disCodeBuffer,__DISF_SIZEONLY);
220    if(cfpos + dret.codelen != amocpos && cfpos && amocpos) keycode = KE_SUPERKEY;
221    DisasmPrepareMode = False;
222    disNeedRef = showref;
223    hexAddressResolv = addrdet;
224  }
225  PrepareAsmLines(keycode,cfpos);
226  if(amocpos != cfpos || keycode == KE_SUPERKEY || keycode == KE_JUSTFIND)
227  {
228    tAbsCoord height = twGetClientHeight(MainWnd);
229    tAbsCoord width = twGetClientWidth(MainWnd);
230    GidResetGoAddress(keycode);
231    I = 0;
232    twFreezeWin(MainWnd);
233    if(keycode == KE_UPARROW)
234    {
235      dir = -1;
236      Limit = -1;
237      /* All checks we have done above */
238      twScrollWinDn(MainWnd,1,1);
239      memmove(&CurrStrLenBuff[1],CurrStrLenBuff,height-1);
240    }
241    else
242    {
243      dir = 1;
244      Limit = height;
245    }
246    if(keycode == KE_DOWNARROW)
247    {
248      if(CurrStrLenBuff[1])
249      {
250        I = height-1;
251        twScrollWinUp(MainWnd,I,1);
252        memmove(CurrStrLenBuff,&CurrStrLenBuff[1],I);
253        cfpos += Summ(CurrStrLenBuff,I);
254      }
255      else
256      {
257        twRefreshWin(MainWnd);
258        goto bye;
259      }
260    }
261    if(cfpos > flen) cfpos = flen;
262    amocpos = cfpos;
263    twUseWin(MainWnd);
264    for(i = I;i != Limit;i+=1*dir)
265    {
266      DisasmRet dret;
267      memset(outstr,TWC_DEF_FILLER,__TVIO_MAXSCREENWIDTH);
268      DisasmCurrLine = i;
269      if(cfpos < flen)
270      {
271        len = cfpos + disMaxCodeLen < flen ? disMaxCodeLen : (int)(flen - cfpos);
272        memset(disCodeBuffer,0,disMaxCodeLen);
273        BMReadBufferEx((void *)disCodeBuffer,len,cfpos,BM_SEEK_SET);
274        dret = Disassembler(cfpos,(void *)disCodeBuffer,__DISF_NORMAL);
275        if(i == 0) CurrStrLen = dret.codelen;
276        CurrStrLenBuff[i] = dret.codelen;
277        twSetColorAttr(browser_cset.main);
278        len_64=HA_LEN;
279        memcpy(outstr,GidEncodeAddress(cfpos,hexAddressResolv),len_64);
280        len = 0;
281        if(disPanelMode < PANMOD_FULL)
282        {
283          static char _clone;
284          len = len_64;
285          twDirectWrite(1,i + 1,outstr,len);
286          if(!hexAddressResolv)
287          {
288            twSetColorAttr(disasm_cset.family_id);
289            _clone = activeDisasm->CloneShortName(dret.pro_clone);
290            twDirectWrite(len_64,i + 1,&_clone,1);
291            twSetColorAttr(browser_cset.main);
292          }
293        }
294        if(disPanelMode < PANMOD_MEDIUM)
295        {
296          unsigned full_off,med_off,tmp_off;
297          ColorAttr opc;
298          med_off = disMaxCodeLen*2+1;
299          full_off = med_off+len_64;
300          for(j = 0;j < dret.codelen;j++,len+=2)
301             memcpy(&outstr[len],Get2Digit(disCodeBuffer[j]),2);
302          tmp_off = disPanelMode < PANMOD_FULL ? full_off : med_off;
303          if(len < tmp_off) len = tmp_off;
304          if(activeDisasm->GetOpcodeColor)
305 		opc =	HiLight == 2 ? activeDisasm->altGetOpcodeColor(dret.pro_clone) :
306 			HiLight == 1 ? activeDisasm->GetOpcodeColor(dret.pro_clone) : disasm_cset.opcodes;
307 	 else	opc = disasm_cset.opcodes;
308          twSetColorAttr(opc);
309          twDirectWrite(disPanelMode < PANMOD_FULL ? len_64+1 : 1,
310                        i + 1,
311                        &outstr[len_64],
312                        disPanelMode < PANMOD_FULL ? len - (len_64+1) : len - 1);
313          if(isHOnLine(cfpos,dret.codelen))
314          {
315             hli.text = &outstr[len_64];
316             HiLightSearch(MainWnd,cfpos,len_64,dret.codelen,i,&hli,HLS_USE_DOUBLE_WIDTH);
317          }
318        }
319        twSetColorAttr(browser_cset.main);
320        twDirectWrite(len,i + 1," ",1);  len++;
321        cattr =	HiLight == 2 ?  activeDisasm->altGetInsnColor(dret.pro_clone) :
322 		HiLight == 1 ?  activeDisasm->GetInsnColor(dret.pro_clone) :
323                                 browser_cset.main;
324        twSetColorAttr(cattr);
325        j = strlen(dret.str);
326        /* Here adding commentaries */
327        savstring[0] = 0;
328        orig_commoff = orig_commpos = 0;
329        if(j > 5)
330        if(dret.str[j-5] == codeguid_image[0] &&
331           dret.str[j-4] == codeguid_image[1] &&
332           dret.str[j-3] == codeguid_image[2] &&
333           dret.str[j-1] == codeguid_image[4] &&
334           dis_severity > DISCOMSEV_NONE)
335        {
336          int new_idx;
337          orig_commpos = new_idx = j-5;
338          orig_commoff = len;
339          strcpy(savstring,&dret.str[new_idx]);
340          dret.str[new_idx--] = 0;
341          while(dret.str[new_idx] == ' ' && new_idx) new_idx--;
342          if(dret.str[new_idx] != ' ') new_idx++;
343          dret.str[new_idx] = 0;
344          j = strlen(dret.str);
345        }
346        twDirectWrite(len,i+1,dret.str,j); len += j;
347        if(dis_severity > DISCOMSEV_NONE)
348        {
349          twSetColorAttr(disasm_cset.comments);
350          twGotoXY(len,i+1);
351          twPutS(" ; "); len+=3;
352          j = orig_commpos-len;
353          j = min(j,strlen(dis_comments));
354          twDirectWrite(len,i+1,dis_comments,j);
355          len += j;
356          if(savstring[0])
357          {
358            twGotoXY(len,i+1);
359            twClrEOL();
360            twSetColorAttr(cattr);
361            len = orig_commoff + orig_commpos;
362            twDirectWrite(len,i+1,savstring,5);
363            len += 5;
364          }
365        }
366        twSetColorAttr(browser_cset.main);
367        if(len < width)
368        {
369          twGotoXY(len,i + 1);
370          twClrEOL();
371        }
372        cfpos += dret.codelen;
373        BMSeek(cfpos,BM_SEEK_SET);
374      }
375      else
376      {
377        twDirectWrite(1,i + 1,outstr,width);
378        CurrStrLenBuff[i] = 0;
379      }
380    }
381    twRefreshWin(MainWnd);
382    twSetColorAttr(browser_cset.main);
383    lastbyte = TopCFPos + Summ(CurrStrLenBuff,height);
384    CurrPageSize = lastbyte-TopCFPos;
385  }
386  bye:
387  return textshift;
388 }
389 
disPrevPageSize(void)390 static unsigned long __FASTCALL__ disPrevPageSize( void ) { return PrevPageSize; }
disCurrPageSize(void)391 static unsigned long __FASTCALL__ disCurrPageSize( void ) { return CurrPageSize; }
disPrevLineWidth(void)392 static unsigned long __FASTCALL__ disPrevLineWidth( void ) { return PrevStrLen; }
disCurrLineWidth(void)393 static unsigned long __FASTCALL__ disCurrLineWidth( void ) { return CurrStrLen; }
disMiscKeyName(void)394 static const char *  __FASTCALL__ disMiscKeyName( void ) { return "Modify"; }
395 
396 static const char *refsdepth_names[] =
397 {
398    "~None",
399    "~Calls/jmps only (navigation)",
400    "~All",
401    "Reference ~prediction (mostly full)"
402 };
403 
disReferenceResolving(void)404 static tBool __FASTCALL__ disReferenceResolving( void )
405 {
406   size_t nModes;
407   int retval;
408   tBool ret;
409   nModes = sizeof(refsdepth_names)/sizeof(char *);
410   retval = SelBoxA(refsdepth_names,nModes," Reference resolving depth: ",disNeedRef);
411   if(retval != -1)
412   {
413     disNeedRef = retval;
414     ret = True;
415   }
416   else ret = False;
417   if(detectedFormat->set_state)
418     detectedFormat->set_state(disNeedRef ? PS_ACTIVE : PS_INACTIVE);
419   return ret;
420 }
421 
422 static const char *panmod_names[] =
423 {
424    "~Full",
425    "~Medium",
426    "~Wide"
427 };
428 
disSelectPanelMode(void)429 static tBool __FASTCALL__ disSelectPanelMode( void )
430 {
431   unsigned nModes;
432   int i;
433   nModes = sizeof(panmod_names)/sizeof(char *);
434   i = SelBoxA(panmod_names,nModes," Select panel mode: ",disPanelMode);
435   if(i != -1)
436   {
437     disPanelMode = i;
438     return True;
439   }
440   return False;
441 }
442 
443 static const char *hilight_names[] =
444 {
445    "~Mono",
446    "~Highlight",
447    "~Alt Highlight"
448 };
449 
disSelectHiLight(void)450 static tBool __FASTCALL__ disSelectHiLight( void )
451 {
452   unsigned nModes;
453   int i;
454   nModes = sizeof(hilight_names)/sizeof(char *);
455   i = SelBoxA(hilight_names,nModes," Select highlight mode: ",HiLight);
456   if(i != -1)
457   {
458     HiLight = i;
459     return True;
460   }
461   return False;
462 }
463 
disDetect(void)464 static tBool __FASTCALL__ disDetect( void ) { return True; }
465 
DefAsmAction(int _lastbyte,int start)466 static tBool __FASTCALL__ DefAsmAction(int _lastbyte,int start)
467 {
468  int _index;
469  tBool redraw,dox;
470  char xx;
471   redraw = True;
472   xx = edit_x / 2;
473   dox = True;
474   _index = start + xx;
475    switch(_lastbyte)
476    {
477      case KE_F(4)   : EditorMem.buff[_index] = ~EditorMem.buff[_index]; break;
478      case KE_F(5)   : EditorMem.buff[_index] |= edit_XX; break;
479      case KE_F(6)   : EditorMem.buff[_index] &= edit_XX; break;
480      case KE_F(7)   : EditorMem.buff[_index] ^= edit_XX; break;
481      case KE_F(8)   : EditorMem.buff[_index]  = edit_XX; break;
482      case KE_F(9)   : EditorMem.buff[_index] = EditorMem.save[_index]; break;
483      default        : redraw = edit_defaction(_lastbyte); dox = False; break;
484    }
485   if(dox) { xx++; edit_x = xx*2; }
486   return redraw;
487 }
488 
DisasmScreen(TWindow * ewnd,__filesize_t cp,__filesize_t flen,int st,int stop,int start)489 static void __FASTCALL__ DisasmScreen(TWindow* ewnd,__filesize_t cp,__filesize_t flen,int st,int stop,int start)
490 {
491  int i,j,len,lim,len_64;
492  char outstr[__TVIO_MAXSCREENWIDTH+1],outstr1[__TVIO_MAXSCREENWIDTH+1];
493  tAbsCoord width = twGetClientWidth(MainWnd);
494  DisasmRet dret;
495  twFreezeWin(ewnd);
496  for(i = st;i < stop;i++)
497  {
498   if(start + cp < flen)
499   {
500    len_64=HA_LEN;
501    memcpy(outstr,GidEncodeAddress(cp + start,hexAddressResolv),len_64);
502    twUseWin(MainWnd);
503    twSetColorAttr(browser_cset.main);
504    twDirectWrite(1,i + 1,outstr,len_64-1);
505    dret = Disassembler(cp + start,&EditorMem.buff[start],__DISF_NORMAL);
506    EditorMem.alen[i] = dret.codelen;
507    memset(outstr,TWC_DEF_FILLER,width);
508    memset(outstr1,TWC_DEF_FILLER,width);
509    len = 0; for(j = 0;j < EditorMem.alen[i];j++) { memcpy(&outstr1[len],Get2Digit(EditorMem.save[start + j]),2); len += 2; }
510    len = 0; for(j = 0;j < EditorMem.alen[i];j++) { memcpy(&outstr[len],Get2Digit(EditorMem.buff[start + j]),2); len += 2; }
511    twUseWin(ewnd);
512    len = disMaxCodeLen*2;
513    for(j = 0;j < len;j++)
514    {
515      twSetColorAttr(outstr[j] == outstr1[j] ? browser_cset.edit.main : browser_cset.edit.change);
516      twDirectWrite(j + 1,i + 1,&outstr[j],1);
517    }
518    len = strlen(dret.str);
519    memset(outstr,TWC_DEF_FILLER,width);
520    memcpy(outstr,dret.str,len);
521    twUseWin(MainWnd);
522    twSetColorAttr(browser_cset.main);
523    lim = disMaxCodeLen*2+len_64+1;
524    twDirectWrite(lim+1,i + 1,outstr,width-lim);
525    start += EditorMem.alen[i];
526   }
527   else
528   {
529     twUseWin(MainWnd);
530     twGotoXY(1,i + 1);
531     twClrEOL();
532     twUseWin(ewnd);
533     twGotoXY(1,i + 1);
534     twClrEOL();
535     EditorMem.alen[i] = 0;
536   }
537  }
538  twRefreshWin(ewnd);
539 }
540 
FullAsmEdit(TWindow * ewnd)541 static int __NEAR__ __FASTCALL__ FullAsmEdit(TWindow * ewnd)
542 {
543  int j,_lastbyte,start;
544  unsigned rlen,len,flags;
545  __filesize_t flen;
546  unsigned max_buff_size = disMaxCodeLen*tvioHeight;
547  tAbsCoord height = twGetClientHeight(MainWnd);
548  tBool redraw = False;
549  char outstr[__TVIO_MAXSCREENWIDTH],owork[__TVIO_MAXSCREENWIDTH];
550 
551  flen = BMGetFLength();
552  edit_cp = BMGetCurrFilePos();
553  start = 0;
554 
555  rlen = (__filesize_t)edit_cp + max_buff_size < flen ? max_buff_size : (unsigned)(flen - edit_cp);
556  BMReadBufferEx((void *)EditorMem.buff,rlen,edit_cp,BM_SEEK_SET);
557  memcpy(EditorMem.save,EditorMem.buff,max_buff_size);
558  memset(EditorMem.alen,TWC_DEF_FILLER,height);
559 
560  DisasmScreen(ewnd,edit_cp,flen,0,height,start);
561  PaintETitle(0,True);
562  start = 0;
563  twShowWin(ewnd);
564  twSetCursorType(TW_CUR_NORM);
565  while(1)
566  {
567    twUseWin(ewnd);
568 
569    len = 0; for(j = 0;j < EditorMem.alen[edit_y];j++) { memcpy(&owork[len],Get2Digit(EditorMem.save[start + j]),2); len += 2; }
570    len = 0; for(j = 0;j < EditorMem.alen[edit_y];j++) { memcpy(&outstr[len],Get2Digit(EditorMem.buff[start + j]),2); len += 2; }
571    flags = __ESS_FILLER_7BIT | __ESS_WANTRETURN | __ESS_HARDEDIT;
572    if(!redraw) flags |= __ESS_NOREDRAW;
573    _lastbyte = eeditstring(outstr,&legalchars[2],&len,(unsigned)(edit_y + 1),(unsigned *)&edit_x,
574                           flags,owork,NULL);
575    CompressHex(&EditorMem.buff[start],outstr,EditorMem.alen[edit_y],False);
576    switch(_lastbyte)
577    {
578      case KE_CTL_F(4):
579                       {
580                        AsmRet aret;
581                        if(activeDisasm->asm_f)
582                        {
583                          char code[81];
584                          code[0]='\0';
585                          if(GetStringDlg(code,activeDisasm->name,
586                                          NULL,"Enter assembler instruction:"))
587                          {
588                            aret = (*activeDisasm->asm_f)(code);
589                            if(aret.err_code)
590                            {
591                               char *message="Syntax error";
592                               if (aret.insn[0])
593                               {
594                                 message=aret.insn;
595                               }
596                               ErrMessageBox(message,NULL);
597                               continue;
598                            }
599                            else
600                            {
601                               int i;
602                               char bytebuffer[3];
603 
604                               for (i=aret.insn_len-1; i>=0; i--)
605                               {
606                                 sprintf(bytebuffer, "%0.2x", aret.insn[i]);
607                                 ungotstring(bytebuffer);
608                               }
609                            }
610                          }
611                          break;
612                        }
613                        else
614                        {
615                          ErrMessageBox("Sorry, no assembler available",NULL);
616                          continue;
617                        }
618                       }
619      case KE_F(1)    : ExtHelp(); continue;
620      case KE_CTL_F(1): activeDisasm->action[0](); continue;
621      case KE_CTL_F(2): SelectSysInfo(); continue;
622      case KE_CTL_F(3): SelectTool(); continue;
623      case KE_F(2)    :
624                       {
625                          BGLOBAL bHandle;
626                          char *fname;
627                          fname = BMName();
628                          if((bHandle = biewOpenRW(fname,BBIO_SMALL_CACHE_SIZE)) != &bNull)
629                          {
630                            bioSeek(bHandle,edit_cp,BIO_SEEK_SET);
631                            if(!bioWriteBuffer(bHandle,(void *)EditorMem.buff,rlen))
632                               errnoMessageBox(WRITE_FAIL,NULL,errno);
633                            bioClose(bHandle);
634                            BMReRead();
635                          }
636                          else errnoMessageBox("Can't reopen",NULL,errno);
637                       }
638      case KE_F(10):
639      case KE_ESCAPE: goto bye;
640      default: redraw = DefAsmAction(_lastbyte,start); break;
641    }
642    CheckYBounds();
643    start = edit_y ? Summ(EditorMem.alen,edit_y) : 0;
644    if(redraw)
645    {
646      DisasmRet dret;
647      dret = Disassembler(edit_cp + start,&EditorMem.buff[start],__DISF_NORMAL);
648      EditorMem.alen[edit_y] = dret.codelen;
649      DisasmScreen(ewnd,edit_cp,flen,0,height,0);
650    }
651    PaintETitle(start + edit_x/2,True);
652    CheckXYBounds();
653    start = edit_y ? Summ(EditorMem.alen,edit_y) : 0;
654  }
655  bye:
656  twSetCursorType(TW_CUR_OFF);
657  return _lastbyte;
658 }
659 
disEdit(void)660 static void __FASTCALL__ disEdit( void )
661 {
662  unsigned len_64;
663  TWindow * ewnd;
664  len_64=HA_LEN;
665  if(!BMGetFLength()) { ErrMessageBox(NOTHING_EDIT,NULL); return; }
666  ewnd = WindowOpen(len_64+1,2,disMaxCodeLen*2+len_64+1,tvioHeight-1,TWS_CURSORABLE);
667  twSetColorAttr(browser_cset.edit.main); twClearWin();
668  edit_x = edit_y = 0;
669  EditMode = EditMode ? False : True;
670  if(editInitBuffs(disMaxCodeLen,NULL,0))
671  {
672    FullAsmEdit(ewnd);
673    editDestroyBuffs();
674  }
675  EditMode = EditMode ? False : True;
676  CloseWnd(ewnd);
677  PaintTitle();
678 }
679 
HelpAsm(void)680 static void __FASTCALL__ HelpAsm( void )
681 {
682    if( activeDisasm->ShowShortHelp ) activeDisasm->ShowShortHelp();
683 }
684 
disReadIni(hIniProfile * ini)685 static void __FASTCALL__ disReadIni( hIniProfile *ini )
686 {
687   char tmps[10];
688   if(isValidIniArgs())
689   {
690     biewReadProfileString(ini,"Biew","Browser","LastSubMode","0",tmps,sizeof(tmps));
691     DefDisasmSel = (int)strtoul(tmps,NULL,10);
692     if(DefDisasmSel >= sizeof(mainDisasmTable)/sizeof(REGISTRY_DISASM *)) DefDisasmSel = 0;
693     ReadIniAResolv(ini);
694     biewReadProfileString(ini,"Biew","Browser","SubSubMode7","0",tmps,sizeof(tmps));
695     disPanelMode = (int)strtoul(tmps,NULL,10);
696     if(disPanelMode > PANMOD_FULL) disPanelMode = 0;
697     biewReadProfileString(ini,"Biew","Browser","SubSubMode8","0",tmps,sizeof(tmps));
698     disNeedRef = (int)strtoul(tmps,NULL,10);
699     if(disNeedRef > NEEDREF_PREDICT) disNeedRef = 0;
700     biewReadProfileString(ini,"Biew","Browser","SubSubMode9","0",tmps,sizeof(tmps));
701     HiLight = (int)strtoul(tmps,NULL,10);
702     if(HiLight > 2) HiLight = 2;
703     activeDisasm = mainDisasmTable[DefDisasmSel];
704     disAcceptActions();
705     if(activeDisasm->read_ini) activeDisasm->read_ini(ini);
706   }
707 }
708 
disInit(void)709 static void __FASTCALL__ disInit( void )
710 {
711   unsigned i;
712   unsigned def_platform;
713   CurrStrLenBuff = PMalloc(tvioHeight);
714   PrevStrLenAddr = PMalloc(tvioHeight*sizeof(long));
715   dis_comments   = PMalloc(DISCOM_SIZE*sizeof(char));
716   if((!CurrStrLenBuff) || (!PrevStrLenAddr) || (!dis_comments))
717   {
718     err:
719     MemOutBox("Disassembler initialization");
720     exit(EXIT_FAILURE);
721   }
722   def_platform = DISASM_DATA;
723   if(detectedFormat->query_platform) def_platform = detectedFormat->query_platform();
724   activeDisasm = mainDisasmTable[0];
725   DefDisasmSel = DISASM_DATA;
726   for(i=0;i<sizeof(mainDisasmTable)/sizeof(REGISTRY_DISASM *);i++) {
727     if(mainDisasmTable[i]->type == def_platform) {
728 	activeDisasm=mainDisasmTable[i];
729 	DefDisasmSel = def_platform;
730 	break;
731     }
732   }
733   disAcceptActions();
734   if(!initCodeGuider()) goto err;
735 }
736 
disTerm(void)737 static void __FASTCALL__ disTerm( void )
738 {
739   termCodeGuider();
740   if(activeDisasm->term) activeDisasm->term();
741   PFREE(CurrStrLenBuff);
742   PFREE(PrevStrLenAddr);
743   PFREE(dis_comments);
744   PFREE(disCodeBuffer);
745   PFREE(disCodeBuf2);
746   PFREE(disCodeBufPredict);
747 }
748 
disSaveIni(hIniProfile * ini)749 static void __FASTCALL__ disSaveIni( hIniProfile *ini )
750 {
751   char tmps[10];
752   sprintf(tmps,"%i",DefDisasmSel);
753   biewWriteProfileString(ini,"Biew","Browser","LastSubMode",tmps);
754   WriteIniAResolv(ini);
755   sprintf(tmps,"%i",disPanelMode);
756   biewWriteProfileString(ini,"Biew","Browser","SubSubMode7",tmps);
757   sprintf(tmps,"%i",disNeedRef);
758   biewWriteProfileString(ini,"Biew","Browser","SubSubMode8",tmps);
759   sprintf(tmps,"%i",HiLight);
760   biewWriteProfileString(ini,"Biew","Browser","SubSubMode9",tmps);
761   if(activeDisasm->save_ini) activeDisasm->save_ini(ini);
762 }
763 
Disassembler(__filesize_t ulShift,MBuffer buffer,unsigned flags)764 DisasmRet Disassembler(__filesize_t ulShift,MBuffer buffer,unsigned flags)
765 {
766   dis_comments[0] = 0;
767   dis_severity = DISCOMSEV_NONE;
768   return activeDisasm->disasm(ulShift,buffer,flags);
769 }
770 
disCharSize(void)771 static unsigned __FASTCALL__ disCharSize( void ) { return 1; }
772 
disSearch(TWindow * pwnd,__filesize_t start,__filesize_t * slen,unsigned flags,tBool is_continue,tBool * is_found)773 static __filesize_t __FASTCALL__ disSearch(TWindow *pwnd, __filesize_t start,
774                                             __filesize_t *slen, unsigned flags,
775                                             tBool is_continue, tBool *is_found)
776 {
777   DisasmRet dret;
778   __filesize_t tsize, retval, flen, dfpos, cfpos, sfpos; /* If search have no result */
779   char *disSearchBuff;
780   unsigned len, lw, proc, pproc, pmult;
781   int cache[UCHAR_MAX+1];
782   cfpos = sfpos = BMGetCurrFilePos();
783   flen = BMGetFLength();
784   retval = FILESIZE_MAX;
785   disSearchBuff  = PMalloc(1002+DISCOM_SIZE);
786   DumpMode = True;
787   if(!disSearchBuff)
788   {
789      MemOutBox("Disassembler search initialization");
790      goto bye;
791   }
792   cfpos = start;
793   tsize = flen;
794   pmult = 100;
795   if(tsize > FILESIZE_MAX/100) { tsize /= 100; pmult = 1; }
796   pproc = proc = 0;
797   /* Attempt to balance disassembler output */
798   PrepareAsmLines(KE_SUPERKEY, cfpos);
799   lw = disPrevLineWidth();
800   if(cfpos && cfpos >= lw) cfpos -= lw;
801   if(!(is_continue && (flags & SF_REVERSE))) cfpos += disCurrLineWidth();
802   /* end of attempt */
803   fillBoyerMooreCache(cache, search_buff, search_len, flags & SF_CASESENS);
804   while(1)
805   {
806     proc = (unsigned)((cfpos*pmult)/tsize);
807     if(proc != pproc)
808     {
809       if(!ShowPercentInWnd(pwnd,pproc=proc))  break;
810     }
811     if(flags & SF_REVERSE)
812     {
813        PrepareAsmLines(KE_UPARROW, cfpos);
814        lw = disPrevLineWidth();
815        if(cfpos && lw && cfpos >= lw)
816        {
817          len = cfpos + disMaxCodeLen < flen ? disMaxCodeLen : (int)(flen - cfpos);
818          memset(disCodeBuffer,0,disMaxCodeLen);
819          dfpos = cfpos;
820          BMReadBufferEx((void *)disCodeBuffer,len,cfpos,BM_SEEK_SET);
821          dret = Disassembler(cfpos,(void *)disCodeBuffer,__DISF_NORMAL);
822          cfpos -= lw;
823        }
824        else break;
825     }
826     else
827     {
828          len = cfpos + disMaxCodeLen < flen ? disMaxCodeLen : (int)(flen - cfpos);
829          memset(disCodeBuffer,0,disMaxCodeLen);
830          dfpos = cfpos;
831          BMReadBufferEx((void *)disCodeBuffer,len,cfpos,BM_SEEK_SET);
832          dret = Disassembler(cfpos,(void *)disCodeBuffer,__DISF_NORMAL);
833          cfpos += dret.codelen;
834          if(cfpos >= flen) break;
835     }
836     strcpy(disSearchBuff, dret.str);
837     strcat(disSearchBuff, dis_comments);
838     if(strFind(disSearchBuff, strlen(disSearchBuff), search_buff, search_len, cache, flags))
839     {
840       *is_found = True;
841       retval = dfpos;
842       *slen = dret.codelen;
843       break;
844     }
845   }
846   PFREE(disSearchBuff);
847   bye:
848   BMSeek(sfpos, SEEK_SET);
849   DumpMode = False;
850   return retval;
851 }
852 
853 REGISTRY_MODE disMode =
854 {
855   "~Disassembler",
856   { NULL, "Disasm", NULL, NULL, NULL, "AResol", "PanMod", "ResRef", "HiLght", "UsrNam" },
857   { NULL, disSelect_Disasm, NULL, NULL, NULL, hexAddressResolution, disSelectPanelMode, disReferenceResolving, disSelectHiLight, udnUserNames },
858   disDetect,
859   __MF_USECODEGUIDE | __MF_DISASM,
860   drawAsm,
861   NULL,
862   disCharSize,
863   disMiscKeyName,
864   disEdit,
865   disPrevPageSize,
866   disCurrPageSize,
867   disPrevLineWidth,
868   disCurrLineWidth,
869   HelpAsm,
870   disReadIni,
871   disSaveIni,
872   disInit,
873   disTerm,
874   disSearch
875 };
876 
disAcceptActions(void)877 static void __NEAR__ __FASTCALL__ disAcceptActions( void )
878 {
879   if(activeDisasm->init) activeDisasm->init();
880   disMaxCodeLen = activeDisasm->max_insn_len();
881   if(disCodeBuffer) PFREE(disCodeBuffer);
882   disCodeBuffer = PMalloc(disMaxCodeLen);
883   if(disCodeBuf2) PFREE(disCodeBuf2);
884   disCodeBuf2 = PMalloc(disMaxCodeLen);
885   if(disCodeBufPredict) PFREE(disCodeBufPredict);
886   disCodeBufPredict = PMalloc(disMaxCodeLen*PREDICT_DEPTH);
887   if(!(disCodeBuffer && disCodeBuf2 && disCodeBufPredict))
888   {
889     MemOutBox("Disassembler initialization");
890     exit(EXIT_FAILURE);
891   }
892   disMode.prompt[0] = activeDisasm->prompt[0];
893   disMode.action[0] = activeDisasm->action[0];
894   disMode.prompt[2] = activeDisasm->prompt[1];
895   disMode.action[2] = activeDisasm->action[1];
896   disMode.prompt[3] = activeDisasm->prompt[2];
897   disMode.action[3] = activeDisasm->action[2];
898   disMode.prompt[4] = activeDisasm->prompt[3];
899   disMode.action[4] = activeDisasm->action[3];
900 }
901 
902 /** Common disassembler utility */
903 
TabSpace(char * str,unsigned nSpace)904 char * __FASTCALL__ TabSpace(char * str,unsigned nSpace)
905 {
906   int i,mx;
907   unsigned len;
908   len = strlen(str);
909   mx = max(len,nSpace);
910   for(i = len;i < mx;i++) str[i] = TWC_DEF_FILLER;
911   if(len >= nSpace) str[i++] = TWC_DEF_FILLER;
912   str[i] = 0;
913   return str;
914 }
915 
disSetModifier(char * str,const char * modf)916 void  __FASTCALL__ disSetModifier(char *str,const char *modf)
917 {
918   unsigned i,len,mlen;
919   i = 0;
920   len = strlen(str);
921   mlen = strlen(modf);
922   while(str[i] != TWC_DEF_FILLER) i++;
923   i++;
924   memcpy(&str[i],modf,mlen);
925   if(i+mlen > len) { str[i+mlen] = TWC_DEF_FILLER; str[i+mlen+1] = 0; }
926 }
927 
disAppendDigits(char * str,__filesize_t ulShift,int flags,char codelen,void * defval,unsigned type)928 int __FASTCALL__ disAppendDigits(char *str,__filesize_t ulShift,int flags,
929                      char codelen,void *defval,unsigned type)
930 {
931  unsigned long app;
932  char comments[DISCOM_SIZE];
933  const char *appstr;
934  unsigned dig_type;
935  __filesize_t fpos;
936  fpos = bmGetCurrFilePos();
937 #ifndef NDEBUG
938   if(ulShift >= BMGetFLength()-codelen)
939   {
940      char sout[75];
941      static tBool displayed = False;
942      if(!displayed)
943      {
944        strncpy(sout,str,sizeof(sout)-1);
945        sout[sizeof(sout)-1] = 0;
946        if(!strlen(sout)) strcpy(sout,"disAppendDigits");
947        ErrMessageBox(sout," Internal disassembler error detected ");
948        displayed = True;
949        COREDUMP();
950      }
951   }
952 #endif
953   if(hexAddressResolv && detectedFormat->AddressResolving) flags |= APREF_SAVE_VIRT;
954   app = disNeedRef >= NEEDREF_ALL ? AppendAsmRef(str,ulShift,flags,codelen,0L) :
955                                     RAPREF_NONE;
956   if(app != RAPREF_DONE)
957   {
958     dig_type = type & 0x00FFU;
959     comments[0] = 0;
960     /* @todo Remove dependencies from 4-byte size of operand */
961                                          /* Only if immediate operand */
962     if(((type & DISARG_IMM) || (type & DISARG_DISP) ||
963 	(type & DISARG_IDXDISP) || (type & DISARG_RIP)) &&
964 	disNeedRef >= NEEDREF_PREDICT)    /* Only when reference prediction is on */
965     {
966       tUInt64 _defval;
967       unsigned fld_len=1;
968       switch(dig_type)
969       {
970         default:
971         case DISARG_BYTE: _defval = *(tUInt8 *)defval;  fld_len=1; break;
972         case DISARG_CHAR: _defval = *(tInt8 *)defval;   fld_len=1; break;
973         case DISARG_WORD: _defval = *(tUInt16 *)defval; fld_len=2; break;
974         case DISARG_SHORT:_defval = *(tInt16 *)defval;  fld_len=2; break;
975         case DISARG_DWORD:_defval = *(tUInt32 *)defval; fld_len=4; break;
976         case DISARG_LONG: _defval = *(tInt32 *)defval;  fld_len=4; break;
977         case DISARG_QWORD:_defval = *(tUInt64 *)defval; fld_len=8; break;
978         case DISARG_LLONG:_defval = *(tInt64 *)defval;  fld_len=8; break;
979       }
980       if(_defval)         /* Do not perform operation on NULL */
981       {
982       __filesize_t pa,psym;
983       unsigned _class;
984       if(type & DISARG_RIP) {
985 	_defval += (detectedFormat->pa2va ?
986 		    detectedFormat->pa2va(ulShift) :
987 		    ulShift)+fld_len;
988      }
989       if(!app) pa = detectedFormat->va2pa ? detectedFormat->va2pa(_defval) :
990                                            _defval;
991       else pa = app;
992       if(pa)
993       {
994         /* 1. Try to determine immediate as offset to public symbol */
995 	if(type & DISARG_RIP) app = AppendAsmRef(str,pa,flags,codelen,0L);
996 	if(app == RAPREF_DONE) goto next_step;
997         if(dis_severity < DISCOMSEV_FUNC)
998         {
999           strcpy(comments,".*");
1000           if(detectedFormat->GetPubSym)
1001           {
1002             psym = detectedFormat->GetPubSym(&comments[2],sizeof(comments)-2,
1003                                              &_class,pa,False);
1004             if(psym != pa) comments[0] = 0;
1005             else
1006             {
1007                 dis_severity = DISCOMSEV_FUNC;
1008                 strcpy(dis_comments,comments);
1009             }
1010           }
1011         }
1012         /* 2. Try to determine immediate as offset to string constant */
1013         comments[0] = 0;
1014         if(dis_severity < DISCOMSEV_STRPTR)
1015         {
1016           size_t index;
1017           unsigned char rch;
1018           index = 0;
1019           strcat(comments,"->\"");
1020           for(index = 3;index < sizeof(comments)-5;index++)
1021           {
1022             bmSeek(pa+index-3,BM_SEEK_SET);
1023             rch = bmReadByte();
1024             if(isprint(rch)) comments[index] = rch;
1025             else break;
1026           }
1027           if(!comments[3]) comments[0] = 0;
1028           else
1029           {
1030             comments[index++] = '"'; comments[index] = 0;
1031             dis_severity = DISCOMSEV_STRPTR;
1032             strcpy(dis_comments,comments);
1033           }
1034         }
1035       }
1036       }
1037     }
1038     next_step:
1039     comments[0] = 0;
1040     if(app == RAPREF_NONE)
1041     {
1042      switch(dig_type)
1043      {
1044       case DISARG_LLONG:
1045 #ifdef INT64_C
1046 			 appstr = Get16SignDig(*(tInt64 *)defval);
1047 #else
1048 			 appstr = Get16SignDig(((tInt32 *)defval)[0],((tInt32 *)defval)[1]);
1049 #endif
1050                          if(type & DISARG_IMM &&
1051                             disNeedRef >= NEEDREF_PREDICT &&
1052                             dis_severity < DISCOMSEV_STRING &&
1053                             isprint(((unsigned char *)defval)[0]) &&
1054                             isprint(((unsigned char *)defval)[1]) &&
1055                             isprint(((unsigned char *)defval)[2]) &&
1056                             isprint(((unsigned char *)defval)[3]) &&
1057                             isprint(((unsigned char *)defval)[4]) &&
1058                             isprint(((unsigned char *)defval)[5]) &&
1059                             isprint(((unsigned char *)defval)[6]) &&
1060                             isprint(((unsigned char *)defval)[7]))
1061                             sprintf(comments,"\"%c%c%c%c%c%c%c%c\""
1062                                             ,((unsigned char *)defval)[0]
1063                                             ,((unsigned char *)defval)[1]
1064                                             ,((unsigned char *)defval)[2]
1065                                             ,((unsigned char *)defval)[3]
1066                                             ,((unsigned char *)defval)[4]
1067                                             ,((unsigned char *)defval)[5]
1068                                             ,((unsigned char *)defval)[6]
1069                                             ,((unsigned char *)defval)[7]);
1070                          break;
1071       case DISARG_LONG:  appstr = Get8SignDig(*(tInt32 *)defval);
1072                          if(type & DISARG_IMM &&
1073                             disNeedRef >= NEEDREF_PREDICT &&
1074                             dis_severity < DISCOMSEV_STRING &&
1075                             isprint(((unsigned char *)defval)[0]) &&
1076                             isprint(((unsigned char *)defval)[1]) &&
1077                             isprint(((unsigned char *)defval)[2]) &&
1078                             isprint(((unsigned char *)defval)[3]))
1079                             sprintf(comments,"\"%c%c%c%c\""
1080                                             ,((unsigned char *)defval)[0]
1081                                             ,((unsigned char *)defval)[1]
1082                                             ,((unsigned char *)defval)[2]
1083                                             ,((unsigned char *)defval)[3]);
1084                          break;
1085       case DISARG_SHORT: appstr = Get4SignDig(*(tInt16 *)defval);
1086                          if(type & DISARG_IMM &&
1087                             disNeedRef >= NEEDREF_PREDICT &&
1088                             dis_severity < DISCOMSEV_STRING &&
1089                             isprint(((unsigned char *)defval)[0]) &&
1090                             isprint(((unsigned char *)defval)[1]))
1091                             sprintf(comments,"\"%c%c\""
1092                                             ,((unsigned char *)defval)[0]
1093                                             ,((unsigned char *)defval)[1]);
1094                          break;
1095       case DISARG_CHAR:  appstr = Get2SignDig(*(char *)defval);
1096                          if(type & DISARG_IMM &&
1097                             disNeedRef >= NEEDREF_PREDICT &&
1098                             dis_severity < DISCOMSEV_STRING &&
1099                             isprint(*(unsigned char *)defval))
1100                             sprintf(comments,"'%c'",*(unsigned char *)defval);
1101                          break;
1102       case DISARG_BYTE:  appstr = Get2Digit(*(unsigned char *)defval);
1103                          if(type & DISARG_IMM &&
1104                             disNeedRef >= NEEDREF_PREDICT &&
1105                             dis_severity < DISCOMSEV_STRING &&
1106                             isprint(*(unsigned char *)defval))
1107                             sprintf(comments,"'%c'",*(unsigned char *)defval);
1108                          break;
1109       case DISARG_WORD:  appstr = Get4Digit(*(tUInt16 *)defval);
1110                          if(type & DISARG_IMM &&
1111                             disNeedRef >= NEEDREF_PREDICT &&
1112                             dis_severity < DISCOMSEV_STRING &&
1113                             isprint(((unsigned char *)defval)[0]) &&
1114                             isprint(((unsigned char *)defval)[1]))
1115                             sprintf(comments,"\"%c%c\""
1116                                             ,((unsigned char *)defval)[0]
1117                                             ,((unsigned char *)defval)[1]);
1118                          break;
1119       default:
1120       case DISARG_DWORD: appstr = Get8Digit(*(tUInt32 *)defval);
1121                          if(type & DISARG_IMM &&
1122                             disNeedRef >= NEEDREF_PREDICT &&
1123                             dis_severity < DISCOMSEV_STRING &&
1124                             isprint(((unsigned char *)defval)[0]) &&
1125                             isprint(((unsigned char *)defval)[1]) &&
1126                             isprint(((unsigned char *)defval)[2]) &&
1127                             isprint(((unsigned char *)defval)[3]))
1128                             sprintf(comments,"\"%c%c%c%c\""
1129                                             ,((unsigned char *)defval)[0]
1130                                             ,((unsigned char *)defval)[1]
1131                                             ,((unsigned char *)defval)[2]
1132                                             ,((unsigned char *)defval)[3]);
1133                          break;
1134       case DISARG_QWORD:
1135 #ifdef INT64_C
1136 			 appstr = Get16Digit(*(tUInt64 *)defval);
1137 #else
1138 			 appstr = Get16Digit(((tUInt32 *)defval)[0],((tUInt32 *)defval)[1]);
1139 #endif
1140                          if(type & DISARG_IMM &&
1141                             disNeedRef >= NEEDREF_PREDICT &&
1142                             dis_severity < DISCOMSEV_STRING &&
1143                             isprint(((unsigned char *)defval)[0]) &&
1144                             isprint(((unsigned char *)defval)[1]) &&
1145                             isprint(((unsigned char *)defval)[2]) &&
1146                             isprint(((unsigned char *)defval)[3]) &&
1147                             isprint(((unsigned char *)defval)[4]) &&
1148                             isprint(((unsigned char *)defval)[5]) &&
1149                             isprint(((unsigned char *)defval)[6]) &&
1150                             isprint(((unsigned char *)defval)[7]))
1151                             sprintf(comments,"\"%c%c%c%c%c%c%c%c\""
1152                                             ,((unsigned char *)defval)[0]
1153                                             ,((unsigned char *)defval)[1]
1154                                             ,((unsigned char *)defval)[2]
1155                                             ,((unsigned char *)defval)[3]
1156                                             ,((unsigned char *)defval)[4]
1157                                             ,((unsigned char *)defval)[5]
1158                                             ,((unsigned char *)defval)[6]
1159                                             ,((unsigned char *)defval)[7]);
1160                          break;
1161     }
1162     strcat(str,appstr);
1163    }
1164    if(comments[0])
1165    {
1166      dis_severity = DISCOMSEV_STRING;
1167      strcpy(dis_comments,comments);
1168    }
1169   }
1170   bmSeek(fpos,BM_SEEK_SET);
1171   return app;
1172 }
1173 
disAppendFAddr(char * str,__fileoff_t ulShift,__fileoff_t distin,__filesize_t r_sh,char type,unsigned seg,char codelen)1174 int __FASTCALL__ disAppendFAddr(char * str,__fileoff_t ulShift,__fileoff_t distin,__filesize_t r_sh,char type,unsigned seg,char codelen)
1175 {
1176  int needref;
1177  __filesize_t fpos;
1178  char *modif_to;
1179  DisasmRet dret;
1180  int appended = RAPREF_NONE;
1181  int flags;
1182  fpos = bmGetCurrFilePos();
1183  memset(&dret,0,sizeof(DisasmRet));
1184  /* Prepare insn type */
1185  if(disNeedRef > NEEDREF_NONE)
1186  {
1187    /* Forward prediction: ulShift = offset of binded field but r_sh is
1188       pointer where this field is referenced. */
1189    memset(disCodeBufPredict,0,disMaxCodeLen*PREDICT_DEPTH);
1190    bmSeek(r_sh, SEEK_SET);
1191    bmReadBuffer(disCodeBufPredict,disMaxCodeLen*PREDICT_DEPTH);
1192    dret = Disassembler(r_sh,(MBuffer)disCodeBufPredict,__DISF_GETTYPE);
1193  }
1194 #ifndef NDEBUG
1195   if(ulShift >= (__fileoff_t)BMGetFLength()-codelen)
1196   {
1197      char sout[75];
1198      static tBool displayed = False;
1199      if(!displayed)
1200      {
1201        strncpy(sout,str,sizeof(sout)-1);
1202        sout[sizeof(sout)-1] = 0;
1203        if(!strlen(sout)) strcpy(sout,"disAppendFAddr");
1204        ErrMessageBox(sout," Internal disassembler error detected ");
1205        displayed = True;
1206        COREDUMP();
1207      }
1208   }
1209 #endif
1210  if(disNeedRef > NEEDREF_NONE)
1211  {
1212    if(dret.pro_clone == __INSNT_JMPPIC || dret.pro_clone == __INSNT_JMPRIP) goto try_pic; /* skip defaults for PIC */
1213    flags = APREF_TRY_LABEL;
1214    if(hexAddressResolv && detectedFormat->AddressResolving) flags |= APREF_SAVE_VIRT;
1215    if(AppendAsmRef(str,ulShift,flags,codelen,r_sh)) appended = RAPREF_DONE;
1216    else
1217    {
1218       /*
1219          Forwarding references.
1220          Dereferencing ret instruction.
1221          Idea and PE implementation by "Kostya Nosov" <k-nosov@yandex.ru>
1222       */
1223        if(dret.pro_clone == __INSNT_JMPVVT) /* jmp (mod r/m) */
1224        {
1225             if(AppendAsmRef(str,r_sh+dret.field,APREF_TRY_LABEL,dret.codelen,r_sh))
1226             {
1227               appended = RAPREF_DONE;
1228               modif_to = strchr(str,' ');
1229               if(modif_to)
1230               {
1231                 while(*modif_to == ' ') modif_to++;
1232                 *(modif_to-1) = '*';
1233               }
1234               if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
1235             }
1236        }
1237        else
1238        if(dret.pro_clone == __INSNT_JMPPIC) /* jmp [ebx+offset] */
1239        {
1240             try_pic:
1241             if(dret.pro_clone == __INSNT_JMPRIP) goto try_rip;
1242             if(AppendAsmRef(str,r_sh+dret.field,APREF_TRY_PIC,dret.codelen,r_sh))
1243             {
1244               appended = RAPREF_DONE; /* terminate appending any info anyway */
1245               if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
1246             }
1247        }
1248        else
1249        if(dret.pro_clone == __INSNT_JMPRIP) /* calln *(jmp [rip+offset]) */
1250        {
1251 	__filesize_t _defval,fpos,pa;
1252 	unsigned long app;
1253 		try_rip:
1254 		fpos = BMGetCurrFilePos();
1255 		_defval = dret.codelen==8 ? BMReadQWordEx(r_sh+dret.field,SEEKF_START):
1256 					    BMReadDWordEx(r_sh+dret.field,SEEKF_START);
1257 		BMSeek(fpos,SEEKF_START);
1258 	_defval += (detectedFormat->pa2va ?
1259 		    detectedFormat->pa2va(r_sh+dret.field) :
1260 		    r_sh+dret.field)+dret.codelen;
1261 	pa = detectedFormat->va2pa ? detectedFormat->va2pa(_defval) :
1262                                            _defval;
1263 	app=AppendAsmRef(str,pa,APREF_TRY_LABEL,dret.codelen,0L);
1264         if(app)
1265         {
1266 	  appended = RAPREF_DONE; /* terminate appending any info anyway */
1267 	  modif_to = strchr(str,' ');
1268 	  if(modif_to)
1269 	  {
1270 	    while(*modif_to == ' ') modif_to++;
1271 	    *(modif_to-1) = '*';
1272 	  }
1273 	  if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
1274         }
1275        }
1276    }
1277  }
1278    /*
1279       Idea and PE release of "Kostya Nosov" <k-nosov@yandex.ru>:
1280       make virtual address as argument of "jxxx" and "callx"
1281    */
1282  if(!appended)
1283  {
1284    if(hexAddressResolv && detectedFormat->AddressResolving)
1285    {
1286      r_sh = r_sh ? r_sh : (__filesize_t)ulShift;
1287      appended = detectedFormat->AddressResolving(&str[strlen(str)],r_sh) ? RAPREF_DONE : RAPREF_NONE;
1288    }
1289    if(!appended)
1290    {
1291      needref = disNeedRef;
1292      disNeedRef = NEEDREF_NONE;
1293      if(r_sh <= BMGetFLength())
1294      {
1295        const char * cptr;
1296        char lbuf[20];
1297        cptr = DumpMode ? "L" : "file:";
1298        strcat(str,cptr);
1299 #if (__WORDSIZE >= 32) && !defined(__QNX4__)
1300 	if((BMFileFlags&BMFF_USE64))
1301 	    sprintf(lbuf,"%016llX",r_sh);
1302 	else
1303 #endif
1304        sprintf(lbuf,"%08lX",(unsigned long)r_sh);
1305        strcat(str,lbuf);
1306        appended = RAPREF_DONE;
1307      }
1308      else
1309      {
1310        const char * pstr = "";
1311        if(type & DISADR_USESEG)
1312        {
1313          strcat(str,Get4Digit(seg));
1314          strcat(str,":");
1315        }
1316        if(!type) pstr = Get2SignDig((char)distin);
1317        else
1318          if(type & DISADR_NEAR16)
1319               pstr = type & DISADR_USESEG ? Get4Digit((unsigned)distin) :
1320                                             Get4SignDig((unsigned)distin);
1321          else
1322           if(type & DISADR_NEAR32)   pstr = Get8SignDig(distin);
1323 	  else
1324 	   if(type & DISADR_NEAR64) pstr = Get16SignDig(distin);
1325        strcat(str,pstr);
1326      }
1327      disNeedRef = needref;
1328    }
1329    if(disNeedRef >= NEEDREF_PREDICT && dis_severity < DISCOMSEV_INSNREF)
1330    {
1331      const char * comms;
1332      comms = NULL;
1333      switch(dret.pro_clone)
1334      {
1335         case __INSNT_RET:   comms = "RETURN"; break;
1336         case __INSNT_LEAVE: comms = "LEAVE"; break;
1337         default:            break;
1338      }
1339      if(comms)
1340      {
1341         dis_severity = DISCOMSEV_INSNREF;
1342         strcpy(dis_comments,comms);
1343      }
1344    }
1345    if(appended && !DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
1346  }
1347  bmSeek(fpos,BM_SEEK_SET);
1348  return appended;
1349 }
1350 
1351 
1352 
1353 
1354 
1355 
1356 
1357 
1358 
1359 
1360