1 /**
2  * @namespace   biew
3  * @file        codeguid.c
4  * @brief       This file contains code navigation routines.
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        removing difference keys for same locations of jump
19 **/
20 #include <string.h>
21 #include <stdio.h>
22 #include <limits.h>
23 
24 #include "bmfile.h"
25 #include "biewutil.h"
26 #include "plugins/disasm.h"
27 #include "bconsole.h"
28 #include "codeguid.h"
29 #include "reg_form.h"
30 #include "biewlib/biewlib.h"
31 #include "biewlib/twin.h"
32 #include "biewlib/pmalloc.h"
33 #include "biewlib/kbd_code.h"
34 
35 #define BACK_ADDR_SIZE 256
36 #define GO_ADDR_SIZE   37
37 
38 static __filesize_t *BackAddr=NULL;
39 static int BackAddrPtr = -1;
40 static __filesize_t *GoAddr=NULL;
41 static unsigned int  *GoLineNums=NULL;
42 static int GoAddrPtr = -1;
43 static unsigned char Alarm = 0;
44 
45 extern int DisasmCurrLine;
46 
47 char codeguid_image[] = "=>[X]";
48 
initCodeGuider(void)49 tBool __FASTCALL__ initCodeGuider( void )
50 {
51   tBool ret = False;
52   BackAddr = PMalloc(sizeof(__filesize_t)*BACK_ADDR_SIZE);
53   if(BackAddr)
54   {
55     GoAddr = PMalloc(sizeof(__filesize_t)*GO_ADDR_SIZE);
56     if(!GoAddr) PFree(BackAddr);
57     else
58     {
59       GoLineNums = PMalloc(sizeof(unsigned int)*GO_ADDR_SIZE);
60       if(!GoLineNums) { PFree(BackAddr); PFree(GoAddr); }
61       else ret = True;
62     }
63   }
64   return ret;
65 }
66 
termCodeGuider(void)67 void __FASTCALL__ termCodeGuider( void )
68 {
69   PFree(GoLineNums);
70   PFree(GoAddr);
71   PFree(BackAddr);
72 }
73 
74    /*
75       Added by "Kostya Nosov" <k-nosov@yandex.ru>:
76       for removing difference keys for same locations of jump
77    */
78 
gidGetAddressKey(unsigned index)79 static char __FASTCALL__ gidGetAddressKey( unsigned index )
80 {
81   int i,j;
82   char key;
83   tBool found;
84   __filesize_t addr1,addr2;
85   key = 0;
86   addr1 = GoAddr[index];
87   for (i = 0;i <= GoAddrPtr;i++)
88   {
89     addr2 = GoAddr[i];
90     if (addr2 == addr1) break;
91     /* check for presence addr2 above */
92     found = False;
93     for (j = 0;j < i;j++)
94     {
95       if (GoAddr[j] == addr2)
96       {
97         found = True;
98         break;
99       }
100     }
101     if (!found) key++;
102   }
103   return key < 10 ? key + '0' : key - 10 + 'A';
104 }
105 
gidGetKeyIndex(char key)106 static int __FASTCALL__ gidGetKeyIndex( char key )
107 {
108   int res,i,j,index;
109   tBool found;
110   __filesize_t addr;
111   if (key > 'Z') key = key - 'z' + 'Z';
112   key = key > '9' ? key - 'A' + 10 : key - '0';
113   res = GoAddrPtr + 1;
114   index = 0;
115   for (i = 0;i <= GoAddrPtr;i++)
116   {
117     addr = GoAddr[i];
118     /* check for presence addr above */
119     found = False;
120     for (j = 0;j < i;j++)
121     {
122       if (GoAddr[j] == addr)
123       {
124         found = True;
125         break;
126       }
127     }
128     if (i > 0 && !found) index++;
129     if (index == key)
130     {
131       res = i;
132       break;
133     }
134   }
135   return res;
136 }
137 
gidBuildKeyStr(void)138 static char * __NEAR__ __FASTCALL__ gidBuildKeyStr( void )
139 {
140   codeguid_image[3] = gidGetAddressKey(GoAddrPtr);
141   return codeguid_image;
142 }
143 
GidResetGoAddress(int keycode)144 void __FASTCALL__ GidResetGoAddress( int keycode )
145 {
146   Alarm = 0;
147   if(keycode == KE_DOWNARROW)
148   {
149     int i;
150     if(GoAddrPtr >= 0)
151     {
152       if(GoLineNums[0] == 0)
153       {
154         memmove(GoAddr,&GoAddr[1],GoAddrPtr*sizeof(__filesize_t));
155         memmove(GoLineNums,&GoLineNums[1],GoAddrPtr*sizeof(unsigned int));
156         GoAddrPtr--;
157       }
158       for(i = 0;i <= GoAddrPtr;i++)
159       {
160         char dig;
161         GoLineNums[i]--;
162         dig = gidGetAddressKey(i);
163         twDirectWrite(twGetClientWidth(MainWnd)-1,GoLineNums[i]+2,&dig,1);
164       }
165     }
166   }
167   else if(keycode == KE_UPARROW)
168        {
169           int i;
170           Alarm = UCHAR_MAX;
171           if(GoAddrPtr >= 0)
172           {
173             for(i = 0;i <= GoAddrPtr;i++) GoLineNums[i]++;
174             if(GoLineNums[GoAddrPtr] >= twGetClientHeight(MainWnd)) GoAddrPtr--;
175           }
176        }
177        else GoAddrPtr = -1;
178 }
179 
180 extern tBool DisasmPrepareMode;
181 
GidAddGoAddress(char * str,__filesize_t addr)182 void __FASTCALL__ GidAddGoAddress(char *str,__filesize_t addr)
183 {
184   tAbsCoord width = twGetClientWidth(MainWnd);
185   unsigned bytecodes=activeDisasm->max_insn_len()*2;
186   int len,where;
187   if(DisasmPrepareMode) return;
188   len = strlen((char *)str);
189   where = (disPanelMode == PANMOD_FULL ? width :
190            disPanelMode == PANMOD_MEDIUM ? width-HA_LEN : width-(HA_LEN+1)-bytecodes) - 5;
191   if(Alarm)
192   {
193      int i;
194       if(GoAddrPtr < GO_ADDR_SIZE - 2) GoAddrPtr++;
195       memmove(&GoAddr[1],&GoAddr[0],GoAddrPtr*sizeof(long));
196       memmove(&GoLineNums[1],&GoLineNums[0],GoAddrPtr*sizeof(int));
197       GoAddr[0] = addr;
198       GoLineNums[0] = DisasmCurrLine;
199       if(len < where)
200       {
201         memset(&str[len],TWC_DEF_FILLER,where-len);
202         str[where] = 0;
203       }
204       strcat(str,codeguid_image);
205       str[where + 3] = '0';
206       for(i = 1;i <= GoAddrPtr;i++)
207       {
208         char dig;
209         dig = gidGetAddressKey(i);
210         twDirectWrite(width-1,GoLineNums[i]+1,&dig,1);
211       }
212   }
213   else
214   if(GoAddrPtr < GO_ADDR_SIZE - 2)
215   {
216      GoAddrPtr++;
217      GoAddr[GoAddrPtr] = addr;
218      GoLineNums[GoAddrPtr] = DisasmCurrLine;
219      if(len < where)
220      {
221         memset(&str[len],TWC_DEF_FILLER,where-len);
222         str[where] = 0;
223      }
224      strcpy((char *)&str[where],(char *)gidBuildKeyStr());
225   }
226 }
227 
GidAddBackAddress(void)228 void __FASTCALL__ GidAddBackAddress( void )
229 {
230   if(BackAddrPtr >= BACK_ADDR_SIZE - 2)
231   {
232       memmove(BackAddr,&BackAddr[1],BackAddrPtr);
233       BackAddrPtr--;
234   }
235   BackAddrPtr++;
236   BackAddr[BackAddrPtr] = BMGetCurrFilePos();
237 }
238 
GidGetGoAddress(unsigned keycode)239 __filesize_t __FASTCALL__ GidGetGoAddress(unsigned keycode)
240 {
241   __filesize_t ret;
242   if(keycode == KE_BKSPACE)
243        ret = BackAddrPtr >= 0 ? BackAddr[BackAddrPtr--] : BMGetCurrFilePos();
244   else
245   {
246       int ptr;
247       keycode &= 0x00FF;
248       ptr = gidGetKeyIndex(keycode);
249       if(ptr <= GoAddrPtr)
250       {
251         GidAddBackAddress();
252         ret = GoAddr[ptr];
253       }
254       else
255         ret = BMGetCurrFilePos();
256   }
257   return ret;
258 }
259 
GidEncodeAddress(__filesize_t cfpos,tBool AddressDetail)260 char * __FASTCALL__ GidEncodeAddress(__filesize_t cfpos,tBool AddressDetail)
261 {
262   static char addr[11];
263 #if __WORDSIZE >= 32
264   strcpy(addr,((BMFileFlags&BMFF_USE64)?Get16Digit(cfpos):Get8Digit(cfpos)));
265 #else
266   strcpy(addr,Get8Digit(cfpos));
267 #endif
268   if(AddressDetail && detectedFormat->AddressResolving)
269        detectedFormat->AddressResolving(addr,cfpos);
270   strcat(addr,": ");
271   return addr;
272 }
273