1 /**
2 * @namespace biew
3 * @file bin_util.c
4 * @brief This file contains common functions of plugins/bin of BIEW project.
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 **/
17 #include <limits.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <stdlib.h>
22
23 #include "bin_util.h"
24 #include "reg_form.h"
25 #include "biewutil.h"
26 #include "bmfile.h"
27 #include "bconsole.h"
28 #include "tstrings.h"
29 #include "plugins/disasm.h"
30
31 unsigned fmtActiveState = 0;
32
33 linearArray *PubNames = NULL;
34
fmtSetState(int state)35 void __FASTCALL__ fmtSetState(int state)
36 {
37 if(state == PS_ACTIVE) { if(fmtActiveState < UINT_MAX) fmtActiveState++; }
38 else { if(fmtActiveState) fmtActiveState--; }
39 }
40
fmtComparePubNames(const void __HUGE__ * v1,const void __HUGE__ * v2)41 tCompare __FASTCALL__ fmtComparePubNames(const void __HUGE__ *v1,const void __HUGE__ *v2)
42 {
43 const struct PubName __HUGE__ *pnam1,__HUGE__ *pnam2;
44 pnam1 = (const struct PubName __HUGE__ *)v1;
45 pnam2 = (const struct PubName __HUGE__ *)v2;
46 return __CmpLong__(pnam1->pa,pnam2->pa);
47 }
48
fmtFindPubName(BGLOBAL fmt_cache,char * buff,unsigned cb_buff,__filesize_t pa,ReadPubNameList fmt_readlist,ReadPubName fmt_readpub)49 tBool __FASTCALL__ fmtFindPubName(BGLOBAL fmt_cache,char *buff,unsigned cb_buff,
50 __filesize_t pa,
51 ReadPubNameList fmt_readlist,
52 ReadPubName fmt_readpub)
53 {
54 struct PubName *ret,key;
55 key.pa = pa;
56 if(!PubNames) (*fmt_readlist)(fmt_cache,MemOutBox);
57 ret = la_Find(PubNames,&key,fmtComparePubNames);
58 if(ret)
59 {
60 (*fmt_readpub)(fmt_cache,ret,buff,cb_buff);
61 return True;
62 }
63 return udnFindName(pa,buff,cb_buff);
64 }
65
fmtGetPubSym(BGLOBAL fmt_cache,char * str,unsigned cb_str,unsigned * func_class,__filesize_t pa,tBool as_prev,ReadPubNameList fmt_readlist,ReadPubName fmt_readpub)66 __filesize_t __FASTCALL__ fmtGetPubSym(BGLOBAL fmt_cache,char *str,unsigned cb_str,
67 unsigned *func_class,__filesize_t pa,tBool as_prev,
68 ReadPubNameList fmt_readlist,
69 ReadPubName fmt_readpub)
70 {
71 __filesize_t cfpos,ret_addr,cur_addr;
72 unsigned long i,idx,nitems;
73 struct PubName key,*it;
74 cfpos = bmGetCurrFilePos();
75 if(!PubNames) (*fmt_readlist)(fmt_cache,NULL);
76 if(!PubNames->nItems) return 0;
77 ret_addr = 0L;
78 idx = UINT_MAX;
79 key.pa = pa;
80 i = (unsigned)la_FindNearest(PubNames,&key,fmtComparePubNames);
81 nitems = PubNames->nItems;
82 if(as_prev) idx = i;
83 else
84 {
85 static unsigned long multiref_i = 0;
86 get_next:
87 while((cur_addr = ((struct PubName __HUGE__ *)PubNames->data)[i].pa) <= pa)
88 {
89 i++;
90 if((cur_addr == pa && i > multiref_i) || (i >= nitems - 1)) break;
91 }
92 idx = i;
93 if(idx < PubNames->nItems) ret_addr = cur_addr;
94 else ret_addr = 0L;
95 if(ret_addr && ret_addr == pa)
96 {
97 if(idx <= multiref_i) { i = idx; goto get_next; }
98 else multiref_i = idx;
99 }
100 else multiref_i = 0;
101 }
102 if(idx < PubNames->nItems)
103 {
104 ret_addr = ((struct PubName __HUGE__ *)PubNames->data)[idx].pa;
105 *func_class = ((struct PubName __HUGE__ *)PubNames->data)[idx].attr;
106 if(!idx && pa < ret_addr && as_prev)
107 {
108 ret_addr = 0;
109 }
110 else
111 {
112 it = &((struct PubName __HUGE__ *)PubNames->data)[idx];
113 (*fmt_readpub)(fmt_cache,it,str,cb_str);
114 str[cb_str-1] = 0;
115 }
116 }
117 bmSeek(cfpos,BIO_SEEK_SET);
118 return ret_addr;
119 }
120
ReopenSeek(__filesize_t dist)121 static BGLOBAL __NEAR__ __FASTCALL__ ReopenSeek(__filesize_t dist)
122 {
123 BGLOBAL handle;
124 handle = bioDupEx(bmbioHandle(),BBIO_SMALL_CACHE_SIZE);
125 if(handle != &bNull) bioSeek(handle,dist,BIO_SEEK_SET);
126 else errnoMessageBox(READ_FAIL,NULL,errno);
127 return handle;
128 }
129
fmtShowList(GetNumItems gni,ReadItems ri,const char * title,int flags,unsigned * ordinal)130 int __FASTCALL__ fmtShowList( GetNumItems gni,ReadItems ri,const char * title,int flags,unsigned * ordinal)
131 {
132 int ret;
133 tBool bval;
134 BGLOBAL handle;
135 unsigned nnames;
136 memArray * obj;
137 TWindow* w;
138 ret = -1;
139 if((handle = ReopenSeek(0)) == &bNull) return ret;
140 nnames = gni ? (*gni)(handle) : (unsigned)-1;
141 if(!(obj = ma_Build(nnames,True))) goto exit;
142 w = PleaseWaitWnd();
143 bval = (*ri)(handle,obj,nnames);
144 CloseWnd(w);
145 if(bval)
146 {
147 if(!obj->nItems) { NotifyBox(NOT_ENTRY,title); goto exit; }
148 if(flags)
149 {
150 ret = ma_Display(obj,title,flags,-1);
151 if(ordinal && ret != -1)
152 {
153 char * cptr;
154 char buff[40];
155 cptr = strrchr(obj->data[ret],LB_ORD_DELIMITER);
156 cptr++;
157 strcpy(buff,cptr);
158 *ordinal = atoi(buff);
159 }
160 }
161 else { ret = -1; ma_Display(obj,title,LB_SORTABLE,-1); }
162 }
163 ma_Destroy(obj);
164 exit:
165 bioClose(handle);
166 return ret;
167 }
168
169 /* User Defined names (UDN) */
170
171 typedef struct tagUDN {
172 char name[256];
173 __filesize_t offset;
174 }udn;
175
udn_compare(const void __HUGE__ * e1,const void __HUGE__ * e2)176 static tCompare __FASTCALL__ udn_compare(const void __HUGE__ *e1,const void __HUGE__ *e2)
177 {
178 const udn __HUGE__ *p1 = (const udn __HUGE__ *)e1;
179 const udn __HUGE__ *p2 = (const udn __HUGE__ *)e2;
180 return p1->offset<p2->offset?-1:p1->offset>p2->offset?1:0;
181 }
182
183 static linearArray *udn_list=NULL;
184 static tBool udn_modified=False;
185 static char udn_fname[4096];
186
udnAddItem(void)187 static tBool __FASTCALL__ udnAddItem( void ) {
188 __filesize_t off;
189 udn item,*prev;
190 char ud_name[256],prompt[256];
191 off = BMGetCurrFilePos();
192 sprintf(prompt," Name for %08X offset: ",off);
193 prev=NULL;
194 ud_name[0]='\0';
195 if(udn_list) {
196 item.name[255]='\0';
197 item.offset=off;
198 prev = la_Find(udn_list,&item,udn_compare);
199 if(prev) strcpy(ud_name,prev->name);
200 }
201 if(GetStringDlg(ud_name,prompt," [ENTER] - Proceed ",NAME_MSG))
202 {
203 if(!udn_list) udn_list=la_Build(0,sizeof(udn),NULL);
204 if(udn_list) {
205 if(prev) strcpy(prev->name,ud_name);
206 else {
207 strcpy(item.name,ud_name);
208 item.offset=off;
209 la_AddData(udn_list,&item,NULL);
210 }
211 la_Sort(udn_list,udn_compare);
212 }
213 udn_modified=True;
214 return True;
215 }
216 return False;
217 }
218
udnGetNumItems(BGLOBAL handle)219 static unsigned __FASTCALL__ udnGetNumItems(BGLOBAL handle) {
220 UNUSED(handle);
221 return udn_list->nItems;
222 }
223
udnReadItems(BGLOBAL handle,memArray * names,unsigned nnames)224 static tBool __FASTCALL__ udnReadItems(BGLOBAL handle,memArray * names,unsigned nnames)
225 {
226 char stmp[256];
227 unsigned i;
228 UNUSED(handle);
229 for(i=0;i<nnames;i++) {
230 sprintf(stmp,"%-40s %08lX"
231 ,((udn *)udn_list->data)[i].name
232 ,(unsigned long)((udn *)udn_list->data)[i].offset);
233 if(!ma_AddString(names,stmp,True)) break;
234 }
235 return True;
236 }
237
udnDeleteItem(void)238 static tBool __FASTCALL__ udnDeleteItem( void ) {
239 int rval=-1;
240 if(udn_list) {
241 rval = fmtShowList(udnGetNumItems,udnReadItems,
242 " User-defined Names (aka bookmarks) ",
243 LB_SELECTIVE,NULL);
244 if(rval!=-1) {
245 la_DeleteData(udn_list,rval);
246 la_Sort(udn_list,udn_compare);
247 udn_modified=True;
248 }
249 }
250 else ErrMessageBox("UDN list is empty!",NULL);
251 return rval==-1?False:True;
252 }
253
udnSelectName(__filesize_t * off)254 tBool __FASTCALL__ udnSelectName(__filesize_t *off) {
255 int rval=-1;
256 if(udn_list) {
257 rval = fmtShowList(udnGetNumItems,udnReadItems,
258 " User-defined Names (aka bookmarks) ",
259 LB_SELECTIVE,NULL);
260 if(rval!=-1) *off = ((udn *)udn_list->data)[rval].offset;
261 }
262 else ErrMessageBox("UDN list is empty!",NULL);
263 return rval==-1?False:True;
264 }
265
udnFindName(__filesize_t pa,char * buff,unsigned cb_buff)266 tBool __FASTCALL__ udnFindName(__filesize_t pa,char *buff, unsigned cb_buff) {
267 udn *item;
268 udn key;
269 if(udn_list) {
270 key.name[0]='\0';
271 key.offset = pa;
272 item=la_Find(udn_list,&key,udn_compare);
273 if(item) {
274 strncpy(buff,item->name,cb_buff);
275 buff[cb_buff-1]='\0';
276 return True;
277 }
278 }
279 return False;
280 }
281
__udnSaveList(void)282 tBool __FASTCALL__ __udnSaveList( void )
283 {
284 unsigned i;
285 if(udn_list) {
286 FILE *out;
287 if((out = fopen(udn_fname,"wt"))!=NULL) {
288 fprintf(out,"; This is an automatically generated list of user-defined names\n"
289 "; for: %s\n"
290 "; by Biew-%s\n"
291 ,BMName()
292 ,BIEW_VERSION);
293 for(i=0;i<udn_list->nItems;i++)
294 fprintf(out,"%016llX:%s\n"
295 ,((udn *)udn_list->data)[i].offset
296 ,((udn *)udn_list->data)[i].name);
297 fclose(out);
298 udn_modified=False;
299 return True;
300 }
301 else {
302 char stmp[256];
303 sprintf(stmp,"Can't open file: %s\n",strerror(errno));
304 ErrMessageBox(udn_fname,stmp);
305 }
306 }
307 return False;
308 }
309
310
udnSaveList(void)311 tBool __FASTCALL__ udnSaveList( void ) {
312 if(GetStringDlg(udn_fname," Please enter file name: "," [ENTER] - Proceed ",NAME_MSG))
313 {
314 if(udn_list) return __udnSaveList();
315 else ErrMessageBox("UDN list is empty!",NULL);
316 }
317 return False;
318 }
319
__udnLoadList(void)320 tBool __FASTCALL__ __udnLoadList( void ) {
321 unsigned i;
322 udn item;
323 FILE *in;
324 if((in = fopen(udn_fname,"rt"))!=NULL) {
325 char buff[4096],*brk;
326 unsigned blen;
327 i = 0;
328 while(!feof(in)) {
329 buff[0]='\0';
330 fgets(buff,sizeof(buff),in);
331 i++;
332 if(buff[0]==';'||buff[0]=='\0') continue;
333 brk=strchr(buff,':');
334 if(!brk) {
335 char stmp[256];
336 sprintf(stmp,"Can't recognize line: %u",i);
337 ErrMessageBox(stmp,NULL);
338 return True;
339 }
340 *brk='\0';
341 sscanf(buff,"%016llX",&item.offset);
342 strncpy(item.name,brk+1,sizeof(item.name));
343 item.name[sizeof(item.name)-1]='\0';
344 blen = strlen(item.name);
345 while(item.name[blen-1]==10||item.name[blen-1]==13) {
346 item.name[blen-1]='\0'; blen--;
347 }
348 if(!udn_list) udn_list = la_Build(0,sizeof(udn),NULL);
349 if(udn_list) la_AddData(udn_list,&item,NULL);
350 else break;
351 }
352 fclose(in);
353 if(udn_list) la_Sort(udn_list,udn_compare);
354 return True;
355 }
356 else {
357 char stmp[256];
358 sprintf(stmp,"Can't open file: %s\n",strerror(errno));
359 ErrMessageBox(udn_fname,stmp);
360 }
361 return False;
362 }
363
udnLoadList(void)364 tBool __FASTCALL__ udnLoadList( void ) {
365 if(GetStringDlg(udn_fname," Please enter file name: "," [ENTER] - Proceed ",NAME_MSG))
366 {
367 if(udn_list) return __udnLoadList();
368 else ErrMessageBox("UDN list is empty!",NULL);
369 }
370 return False;
371 }
372
373 static const char *udn_operations[] =
374 {
375 "~Add item",
376 "~Delete item",
377 "~Load list from file",
378 "~Save list to file"
379 };
380 typedef tBool (__FASTCALL__ *udnFunc)( void );
381
382 static udnFunc udn_funcs[] =
383 {
384 udnAddItem,
385 udnDeleteItem,
386 udnLoadList,
387 udnSaveList
388 };
389
udnUserNames(void)390 tBool __FASTCALL__ udnUserNames( void ) {
391 unsigned nModes;
392 int i;
393 nModes = sizeof(udn_operations)/sizeof(char *);
394 i = 0;
395 i = SelBoxA(udn_operations,nModes," Select operation: ",i);
396 if(i != -1)
397 {
398 int ret;
399 TWindow * w;
400 w = PleaseWaitWnd();
401 ret = (*udn_funcs[i])();
402 CloseWnd(w);
403 return ret;
404 }
405 return False;
406 }
407
udnInit(hIniProfile * ini)408 void __FASTCALL__ udnInit( hIniProfile *ini ) {
409 udn_fname[0]='\0';
410 if(isValidIniArgs())
411 {
412 biewReadProfileString(ini,"Biew","Browser","udn_list","",udn_fname,sizeof(udn_fname));
413 if(udn_fname[0]) __udnLoadList();
414 }
415 }
416
udnTerm(hIniProfile * ini)417 void __FASTCALL__ udnTerm( hIniProfile *ini ) {
418 if(udn_list) {
419 if(udn_modified) {
420 WarnMessageBox("User-defined list of names was not saved",NULL);
421 udnSaveList();
422 }
423 la_Destroy(udn_list);
424 }
425 biewWriteProfileString(ini,"Biew","Browser","udn_list",udn_fname);
426 }
427