1 /**
2 * @namespace biew_plugins_auto
3 * @file plugins/bin/coff386.c
4 * @brief This file contains implementation of COFF-i386 file format decoder.
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 1999
15 * @note Development, fixes and improvements
16 **/
17 #include <limits.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21
22 #include "reg_form.h"
23 #include "tstrings.h"
24 #include "codeguid.h"
25 #include "colorset.h"
26 #include "bconsole.h"
27 #include "bin_util.h"
28 #include "bmfile.h"
29 #include "biewutil.h"
30 #include "biewhelp.h"
31 #include "plugins/bin/coff386.h"
32 #include "plugins/disasm.h"
33 #include "biewlib/kbd_code.h"
34 #include "biewlib/pmalloc.h"
35
36 #define COFF_WORD(cval) ((tUInt16)(*(const tUInt16 *)(const tUInt8 *)cval))
37 #define COFF_DWORD(cval) ((tUInt32)(*(const tUInt32 *)(const tUInt8 *)cval))
38
39
40 static struct external_filehdr coff386hdr;
41 static AOUTHDR coff386ahdr;
42 static SCNHDR *coff386so;
43 static tUIntFast16 nsections;
44 static BGLOBAL coff_cache;
45 static __filesize_t strings_ptr;
46
47 static void __FASTCALL__ coff_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ *mem_out)(const char *));
48 static void __FASTCALL__ coff_ReadPubName(BGLOBAL b_cache,const struct PubName *it,
49 char *buff,unsigned cb_buff);
50 static unsigned __FASTCALL__ coff386_GetObjAttr(__filesize_t pa,char *name,unsigned cb_name,
51 __filesize_t *start,__filesize_t *end,int *_class,int *bitness);
52
FindPubName(char * buff,unsigned cb_buff,__filesize_t pa)53 static tBool __NEAR__ __FASTCALL__ FindPubName(char *buff,unsigned cb_buff,__filesize_t pa)
54 {
55 return fmtFindPubName(coff_cache,buff,cb_buff,pa,
56 coff_ReadPubNameList,
57 coff_ReadPubName);
58 }
59
60
coffReadLongName(BGLOBAL handle,__filesize_t offset,char * str,unsigned slen)61 static void __NEAR__ __FASTCALL__ coffReadLongName(BGLOBAL handle,__filesize_t offset,
62 char *str, unsigned slen)
63 {
64 unsigned i;
65 __filesize_t fpos;
66 fpos = bioTell(handle);
67 bioSeek(handle,offset+strings_ptr,BIO_SEEK_SET);
68 for(i = 0;i < slen;i++)
69 {
70 unsigned char ch;
71 ch = bioReadByte(handle);
72 if(ch && !bioEOF(handle)) str[i] = ch;
73 else break;
74 }
75 str[i] = 0;
76 bioSeek(handle,fpos,BIO_SEEK_SET);
77 }
78
coff386_VA2PA(__filesize_t va)79 static __filesize_t __FASTCALL__ coff386_VA2PA(__filesize_t va)
80 {
81 tUIntFast16 i;
82 for(i = 0;i < nsections;i++)
83 {
84 if(va >= COFF_DWORD(coff386so[i].s_vaddr) && va <= COFF_DWORD(coff386so[i].s_vaddr)+COFF_DWORD(coff386so[i].s_size))
85 {
86 return COFF_DWORD(coff386so[i].s_scnptr) + (va - COFF_DWORD(coff386so[i].s_vaddr));
87 }
88 }
89 return 0L;
90 }
91
coff386_PA2VA(__filesize_t pa)92 static __filesize_t __FASTCALL__ coff386_PA2VA(__filesize_t pa)
93 {
94 tUIntFast16 i;
95 for(i = 0;i < nsections;i++)
96 {
97 if(pa >= COFF_DWORD(coff386so[i].s_scnptr) && pa <= COFF_DWORD(coff386so[i].s_scnptr)+COFF_DWORD(coff386so[i].s_size))
98 {
99 return COFF_DWORD(coff386so[i].s_vaddr) + (pa - COFF_DWORD(coff386so[i].s_scnptr));
100 }
101 }
102 return 0L;
103 }
104
105
coffObjPaint(TWindow * win,const void ** names,unsigned start,unsigned nlist)106 static void __FASTCALL__ coffObjPaint(TWindow * win,const void ** names,unsigned start,unsigned nlist)
107 {
108 char buffer[81];
109 const SCNHDR ** obj = (const SCNHDR **)names;
110 const SCNHDR * objs = obj[start];
111 twUseWin(win);
112 twFreezeWin(win);
113 twClearWin();
114 sprintf(buffer," Object Table [ %u / %u ] ",start + 1,nlist);
115 twSetTitleAttr(win,buffer,TW_TMODE_CENTER,dialog_cset.title);
116 twSetFooterAttr(win,PAGEBOX_SUB,TW_TMODE_RIGHT,dialog_cset.selfooter);
117 twGotoXY(1,1);
118 twPrintF("Object Name = %8s\n"
119 "Physical address = %08lXH\n"
120 "Virtual address = %08lXH\n"
121 "Section size = %08lXH\n"
122 "File pointer to raw data = %08lXH\n"
123 "File pointer to relocations = %08lXH\n"
124 "File pointer to line numbers = %08lXH\n"
125 "Number of relocations = %04XH\n"
126 "Number of line numbers = %04XH\n"
127 "Flags = %08lXH\n"
128 " [%c] - section type is text\n"
129 " [%c] - section type is data\n"
130 " [%c] - section type is bss"
131 ,objs->s_name
132 ,COFF_DWORD(objs->s_paddr)
133 ,COFF_DWORD(objs->s_vaddr)
134 ,COFF_DWORD(objs->s_size)
135 ,COFF_DWORD(objs->s_scnptr)
136 ,COFF_DWORD(objs->s_relptr)
137 ,COFF_DWORD(objs->s_lnnoptr)
138 ,COFF_WORD(objs->s_nreloc)
139 ,COFF_WORD(objs->s_nlnno)
140 ,COFF_DWORD(objs->s_flags)
141 ,GetBool((COFF_DWORD(objs->s_flags) & STYP_TEXT) == STYP_TEXT)
142 ,GetBool((COFF_DWORD(objs->s_flags) & STYP_DATA) == STYP_DATA)
143 ,GetBool((COFF_DWORD(objs->s_flags) & STYP_BSS) == STYP_BSS)
144 );
145 twRefreshFullWin(win);
146 }
147
__coffReadObjects(BGLOBAL handle,memArray * obj,unsigned n)148 static tBool __NEAR__ __FASTCALL__ __coffReadObjects(BGLOBAL handle,memArray * obj,unsigned n)
149 {
150 size_t i;
151 for(i = 0;i < n;i++)
152 {
153 SCNHDR po;
154 if(IsKbdTerminate() || bioEOF(handle)) break;
155 bioReadBuffer(handle,&po,sizeof(SCNHDR));
156 if(!ma_AddData(obj,&po,sizeof(SCNHDR),True)) break;
157 }
158 return True;
159 }
160
coffShowObjects(void)161 static __filesize_t __FASTCALL__ coffShowObjects( void )
162 {
163 BGLOBAL handle;
164 unsigned nnames;
165 __filesize_t fpos,off;
166 memArray * obj;
167 fpos = BMGetCurrFilePos();
168 nnames = COFF_WORD(coff386hdr.f_nscns);
169 if(!nnames) { NotifyBox(NOT_ENTRY," Objects Table "); return fpos; }
170 if(!(obj = ma_Build(nnames,True))) return fpos;
171 handle = coff_cache;
172 off = sizeof(coff386hdr);
173 if(COFF_WORD(coff386hdr.f_opthdr)) off += COFF_WORD(coff386hdr.f_opthdr);
174 bioSeek(handle,off,SEEK_SET);
175 if(__coffReadObjects(handle,obj,nnames))
176 {
177 int ret;
178 ret = PageBox(70,13,(const void **)obj->data,obj->nItems,coffObjPaint);
179 if(ret != -1) fpos = COFF_DWORD(((SCNHDR *)obj->data[ret])->s_scnptr);
180 }
181 ma_Destroy(obj);
182 return fpos;
183 }
184
coff386_encode_hdr(unsigned info)185 static const char * __NEAR__ __FASTCALL__ coff386_encode_hdr(unsigned info)
186 {
187 switch(info)
188 {
189 case I386MAGIC: return " i386 coff ";
190 case I386PTXMAGIC: return " i386 PTX coff ";
191 case I386AIXMAGIC: return " i386 AIX coff ";
192 case LYNXCOFFMAGIC: return " Lynx coff ";
193 default: return " Unknown coff i386 format ";
194 }
195 }
196
ShowCoff386Header(void)197 static __filesize_t __FASTCALL__ ShowCoff386Header( void )
198 {
199 __filesize_t fpos,entry,v_entry;
200 unsigned keycode;
201 TWindow * w;
202 fpos = BMGetCurrFilePos();
203 v_entry = entry = 0L;
204 if(*(unsigned short *)coff386ahdr.magic == ZMAGIC)
205 {
206 v_entry = entry = *(__filesize_t *)&coff386ahdr.entry;
207 entry = coff386_VA2PA(v_entry);
208 }
209 w = CrtDlgWndnls(coff386_encode_hdr(COFF_WORD(coff386hdr.f_magic)),54,12);
210 twGotoXY(1,1);
211 twPrintF("Number of sections = %04XH\n"
212 "Time & date stamp = %08lXH\n"
213 "File pointer to symtab = %08lXH\n"
214 "Number of symtab entries = %08lXH\n"
215 "Size of optional header = %04XH\n"
216 "COFF flags = %04XH\n"
217 " [%c] - Rel. info stripped\n"
218 " [%c] - File is executable (no unresolv. refs.)\n"
219 " [%c] - Line numbers stripped\n"
220 " [%c] - Local symbols stripped\n"
221 " [%c] - File is 32-bits little endian\n"
222 ,COFF_WORD(coff386hdr.f_nscns)
223 ,COFF_DWORD(coff386hdr.f_timdat)
224 ,COFF_DWORD(coff386hdr.f_symptr)
225 ,COFF_DWORD(coff386hdr.f_nsyms)
226 ,COFF_WORD(coff386hdr.f_opthdr)
227 ,COFF_WORD(coff386hdr.f_flags)
228 ,GetBool((COFF_WORD(coff386hdr.f_flags) & F_RELFLG) == F_RELFLG)
229 ,GetBool((COFF_WORD(coff386hdr.f_flags) & F_EXEC) == F_EXEC)
230 ,GetBool((COFF_WORD(coff386hdr.f_flags) & F_LNNO) == F_LNNO)
231 ,GetBool((COFF_WORD(coff386hdr.f_flags) & F_LSYMS) == F_LSYMS)
232 ,GetBool((COFF_WORD(coff386hdr.f_flags) & F_AR32WR) == F_AR32WR));
233 twSetColorAttr(dialog_cset.entry);
234 twPrintF("Entry point = %08lXH (VA=%08lXH)"
235 ,entry,v_entry);
236 twClrEOL();
237 twSetColorAttr(dialog_cset.main);
238 while(1)
239 {
240 keycode = GetEvent(drawEmptyPrompt,NULL,w);
241 if(keycode == KE_ENTER) { fpos = entry; break; }
242 else
243 if(keycode == KE_ESCAPE || keycode == KE_F(10)) break;
244 }
245 CloseWnd(w);
246 return fpos;
247 }
248
coffEncodeType(unsigned type)249 static const char * __NEAR__ __FASTCALL__ coffEncodeType(unsigned type)
250 {
251 const char *ret;
252 switch(type)
253 {
254 case T_NULL: ret = "T_NULL"; break;
255 case T_VOID: ret = "T_VOID"; break;
256 case T_CHAR: ret = "T_CHAR"; break;
257 case T_SHORT: ret = "T_SHORT"; break;
258 case T_INT: ret = "T_INT"; break;
259 case T_LONG: ret = "T_LONG"; break;
260 case T_FLOAT: ret = "T_FLOAT"; break;
261 case T_DOUBLE: ret = "T_DOUBLE"; break;
262 case T_STRUCT: ret = "T_STRUCT"; break;
263 case T_UNION: ret = "T_UNION"; break;
264 case T_ENUM: ret = "T_ENUM"; break;
265 case T_MOE: ret = "T_MOE"; break;
266 case T_UCHAR: ret = "T_UCHAR"; break;
267 case T_USHORT: ret = "T_USHORT"; break;
268 case T_UINT: ret = "T_UINT"; break;
269 case T_ULONG: ret = "T_ULONG"; break;
270 case T_LNGDBL: ret = "T_LNGDBL"; break;
271 default: ret = "T_UNK"; break;
272 }
273 return ret;
274 }
275
coffEncodeClass(unsigned _class)276 static const char * __NEAR__ __FASTCALL__ coffEncodeClass(unsigned _class)
277 {
278 const char *ret;
279 switch(_class)
280 {
281 case C_EFCN: ret = "C_EFCN"; break;
282 case C_NULL: ret = "C_NULL"; break;
283 case C_AUTO: ret = "C_AUTO"; break;
284 case C_EXT: ret = "C_EXT"; break;
285 case C_STAT: ret = "C_STAT"; break;
286 case C_REG: ret = "C_REG"; break;
287 case C_EXTDEF: ret = "C_EXTDEF"; break;
288 case C_LABEL: ret = "C_LABEL"; break;
289 case C_ULABEL: ret = "C_ULABEL"; break;
290 case C_MOS: ret = "C_MOS"; break;
291 case C_ARG: ret = "C_ARG"; break;
292 case C_STRTAG: ret = "C_STRTAG"; break;
293 case C_MOU: ret = "C_MOU"; break;
294 case C_UNTAG: ret = "C_UNTAG"; break;
295 case C_TPDEF: ret = "C_TPDEF"; break;
296 case C_USTATIC: ret = "C_USTATIC"; break;
297 case C_ENTAG: ret = "C_ENTAG"; break;
298 case C_MOE: ret = "C_MOE"; break;
299 case C_REGPARM: ret = "C_REGPARM"; break;
300 case C_FIELD: ret = "C_FIELD"; break;
301 case C_AUTOARG: ret = "C_AUTOARG"; break;
302 case C_LASTENT: ret = "C_LASTENT"; break;
303 case C_BLOCK: ret = "C_BLOCK"; break;
304 case C_FCN: ret = "C_FCN"; break;
305 case C_EOS: ret = "C_EOS"; break;
306 case C_FILE: ret = "C_FILE"; break;
307 case C_LINE: ret = "C_LINE"; break;
308 case C_ALIAS: ret = "C_ALIAS"; break;
309 case C_HIDDEN: ret = "C_HIDDEN"; break;
310 default: ret = "C_UNK"; break;
311 }
312 return ret;
313 }
314
315
coffSymTabNumItems(BGLOBAL handle)316 static unsigned __FASTCALL__ coffSymTabNumItems(BGLOBAL handle)
317 {
318 UNUSED(handle);
319 return (unsigned)COFF_DWORD(coff386hdr.f_nsyms);
320 }
321
coffSymTabReadItems(BGLOBAL handle,memArray * obj,unsigned nnames)322 static tBool __FASTCALL__ coffSymTabReadItems(BGLOBAL handle,memArray * obj,unsigned nnames)
323 {
324 unsigned i;
325 unsigned length;
326 bioSeek(handle,COFF_DWORD(coff386hdr.f_symptr),SEEKF_START);
327 for(i = 0;i < nnames;i++)
328 {
329 struct external_syment cse;
330 char stmp[256];
331 memset(stmp,0,sizeof(stmp));
332 bioReadBuffer(handle,&cse,sizeof(struct external_syment));
333 if(COFF_DWORD(cse.e.e.e_zeroes) == 0L &&
334 COFF_DWORD(cse.e.e.e_offset) >= 4)
335 coffReadLongName(handle,COFF_DWORD(cse.e.e.e_offset),stmp,sizeof(stmp));
336 else
337 {
338 memcpy(stmp,cse.e.e_name,E_SYMNMLEN);
339 stmp[E_SYMNMLEN] = 0;
340 }
341 if(IsKbdTerminate() || bioEOF(handle)) break;
342 length = strlen(stmp);
343 if(length > 38) strcpy(&stmp[38],">>>");
344 else { memset(&stmp[length],' ',38-length); stmp[38] = 0; }
345 sprintf(&stmp[strlen(stmp)-1],"(%04hX.%08lX) %s.%s"
346 ,COFF_WORD(cse.e_scnum)
347 ,(unsigned long)COFF_DWORD(cse.e_value)
348 ,coffEncodeClass(cse.e_sclass[0])
349 ,coffEncodeType(COFF_WORD(cse.e_type)));
350 if(!ma_AddString(obj,stmp,True)) break;
351 }
352 return True;
353 }
354
CalcEntryCoff(unsigned long idx,tBool display_msg)355 static __filesize_t __NEAR__ __FASTCALL__ CalcEntryCoff(unsigned long idx,tBool display_msg)
356 {
357 struct external_syment cse;
358 tUIntFast16 sec_num;
359 __filesize_t fpos;
360 fpos = 0L;
361 bmSeek(COFF_DWORD(coff386hdr.f_symptr)+idx*sizeof(struct external_syment),BM_SEEK_SET);
362 bmReadBuffer(&cse,sizeof(struct external_syment));
363 sec_num = COFF_WORD(cse.e_scnum);
364 if(sec_num && sec_num <= COFF_WORD(coff386hdr.f_nscns) &&
365 ((cse.e_sclass[0] == C_EXT ||
366 cse.e_sclass[0] == C_STAT ||
367 cse.e_sclass[0] == C_HIDDEN) ||
368 (cse.e_sclass[0] == C_LABEL &&
369 COFF_DWORD(cse.e_value))))
370 {
371 fpos = COFF_DWORD(coff386so[sec_num-1].s_scnptr)+COFF_DWORD(cse.e_value);
372 }
373 else
374 if(display_msg)
375 ErrMessageBox(NO_ENTRY,NULL);
376 return fpos;
377 }
378
coffShowSymTab(void)379 static __filesize_t __FASTCALL__ coffShowSymTab( void )
380 {
381 __filesize_t fpos = BMGetCurrFilePos();
382 int ret;
383 ret = fmtShowList(coffSymTabNumItems,coffSymTabReadItems,
384 "Symbol Table",
385 LB_SELECTIVE,NULL);
386 if(ret != -1)
387 {
388 fpos = CalcEntryCoff(ret,True);
389 }
390 return fpos;
391 }
392
393 /***************************************************************************/
394 /********************* REFS COFF386 **************************************/
395 /***************************************************************************/
396 static char __codelen;
397
398 typedef struct tagRELOC_COFF386
399 {
400 unsigned long offset;
401 unsigned long nameoff;
402 unsigned type;
403 }RELOC_COFF386;
404
405 static linearArray *RelocCoff386 = NULL;
406
coff386_compare_rels(const void __HUGE__ * e1,const void __HUGE__ * e2)407 static tCompare __FASTCALL__ coff386_compare_rels(const void __HUGE__ *e1,const void __HUGE__ *e2)
408 {
409 const RELOC_COFF386 __HUGE__ *r1,__HUGE__ *r2;
410 r1 = e1;
411 r2 = e2;
412 return __CmpLong__(r1->offset,r2->offset);
413 }
414
BuildRelocCoff386(void)415 static void __NEAR__ __FASTCALL__ BuildRelocCoff386( void )
416 {
417 TWindow * w,*usd;
418 size_t j,segcount, nr;
419 RELOC_COFF386 rel;
420 usd = twUsedWin();
421 if(!(RelocCoff386 = la_Build(0,sizeof(RELOC_COFF386),MemOutBox))) return;
422 w = CrtDlgWndnls(SYSTEM_BUSY,49,1);
423 if(!PubNames) coff_ReadPubNameList(bmbioHandle(),MemOutBox);
424 twUseWin(w);
425 twGotoXY(1,1);
426 twPutS(BUILD_REFS);
427 twUseWin(usd);
428 for(segcount = 0;segcount < COFF_WORD(coff386hdr.f_nscns);segcount++)
429 {
430 tBool is_eof;
431 is_eof = False;
432 bmSeek(COFF_DWORD(coff386so[segcount].s_relptr),BM_SEEK_SET);
433 nr = COFF_WORD(coff386so[segcount].s_nreloc);
434 for(j = 0;j < nr;j++)
435 {
436 struct external_reloc er;
437 bmReadBuffer(&er,sizeof(struct external_reloc));
438 if((is_eof = bmEOF()) != 0) break;
439 rel.offset = er.r_vaddr + COFF_DWORD(coff386so[segcount].s_scnptr);
440 rel.nameoff = er.r_symndx;
441 rel.type = er.r_type;
442 if(!la_AddData(RelocCoff386,&rel,MemOutBox)) goto next;
443 }
444 if(is_eof) break;
445 }
446 next:
447 la_Sort(RelocCoff386,coff386_compare_rels);
448 CloseWnd(w);
449 }
450
coffSymTabReadItemsIdx(BGLOBAL handle,unsigned long idx,char * name,unsigned cb_name,unsigned * secnum,__filesize_t * offset)451 static tBool __NEAR__ __FASTCALL__ coffSymTabReadItemsIdx(BGLOBAL handle,unsigned long idx,
452 char *name,unsigned cb_name,
453 unsigned *secnum,
454 __filesize_t *offset)
455 {
456 struct external_syment cse;
457 if(idx >= COFF_DWORD(coff386hdr.f_nsyms)) return False;
458 bioSeek(handle,COFF_DWORD(coff386hdr.f_symptr) + idx*sizeof(struct external_syment),SEEKF_START);
459 bioReadBuffer(handle,&cse,sizeof(struct external_syment));
460 if(COFF_DWORD(cse.e.e.e_zeroes) == 0L &&
461 COFF_DWORD(cse.e.e.e_offset) >= 4)
462 coffReadLongName(handle,COFF_DWORD(cse.e.e.e_offset),name,cb_name);
463 else
464 {
465 memcpy(name,cse.e.e_name,E_SYMNMLEN);
466 name[E_SYMNMLEN] = 0;
467 }
468 *secnum = COFF_WORD(cse.e_scnum);
469 *offset = COFF_DWORD(cse.e_value);
470 return True;
471 }
472
BuildReferStrCoff386(char * str,RELOC_COFF386 * rne,int flags)473 static __filesize_t __NEAR__ __FASTCALL__ BuildReferStrCoff386(char *str,RELOC_COFF386 *rne,int flags)
474 {
475 __filesize_t offset,retval,s,e;
476 unsigned long val;
477 tUIntFast16 secnum=0;
478 tBool is_idx,val_assigned;
479 int c,b;
480 char name[256],pubname[256],secname[256];
481 retval = RAPREF_DONE;
482 val = bmReadDWordEx(rne->offset,BM_SEEK_SET);
483 /* rne->nameoff it's only pointer to name descriptor */
484 is_idx = coffSymTabReadItemsIdx(coff_cache,rne->nameoff,name,sizeof(name),&secnum,&offset);
485 val_assigned = False;
486 if(is_idx)
487 {
488 if(!offset && secnum)
489 {
490 /*
491 try resolve some relocations (like .text+1234) with names from
492 public name list
493 */
494 if(FindPubName(pubname,sizeof(pubname),COFF_DWORD(coff386so[secnum-1].s_scnptr) + val))
495 {
496 strcat(str,pubname);
497 val_assigned = True;
498 }
499 else goto def_val;
500 }
501 else
502 {
503 def_val:
504 strcat(str,name);
505 }
506 }
507 else
508 strcat(str,".?bad?");
509 if(val && !val_assigned)
510 {
511 strcat(str,"+");
512 strcat(str,Get8Digit(val));
513 if(secnum) retval = COFF_DWORD(coff386so[secnum-1].s_scnptr)+val;
514 else retval = RAPREF_NONE;
515 }
516 if(rne->type == RELOC_REL32 && (flags & APREF_TRY_LABEL) != APREF_TRY_LABEL)
517 {
518 coff386_GetObjAttr(rne->offset,secname,sizeof(secname),&s,&e,&c,&b);
519 strcat(str,"-");
520 strcat(str,secname);
521 }
522 e = CalcEntryCoff(rne->nameoff,False);
523 if(!DumpMode && !EditMode && e && (flags & APREF_TRY_LABEL) == APREF_TRY_LABEL)
524 GidAddGoAddress(str,e);
525 return retval;
526 }
527
coff386_AppendRef(char * str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)528 static unsigned long __FASTCALL__ coff386_AppendRef(char *str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)
529 {
530 RELOC_COFF386 *rcoff386,key;
531 __filesize_t ret;
532 char buff[400];
533 ret = RAPREF_NONE;
534 if(flags & APREF_TRY_PIC) return RAPREF_NONE;
535 if(!PubNames) coff_ReadPubNameList(bmbioHandle(),MemOutBox);
536 if((COFF_WORD(coff386hdr.f_flags) & F_RELFLG) == F_RELFLG) goto try_pub;
537 if(!RelocCoff386) BuildRelocCoff386();
538 key.offset = ulShift;
539 __codelen = codelen;
540 rcoff386 = la_Find(RelocCoff386,&key,coff386_compare_rels);
541 if(rcoff386) ret = BuildReferStrCoff386(str,rcoff386,flags);
542 try_pub:
543 if(!ret && (flags & APREF_TRY_LABEL))
544 {
545 if(FindPubName(buff,sizeof(buff),r_sh))
546 {
547 strcat(str,buff);
548 if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
549 ret = RAPREF_DONE;
550 }
551 }
552 return flags & APREF_TRY_LABEL ? ret ? RAPREF_DONE : RAPREF_NONE : ret;
553 }
554
coff386_check_fmt(void)555 static tBool __FASTCALL__ coff386_check_fmt( void )
556 {
557 tUIntFast16 id;
558 id = bmReadWordEx(0,SEEKF_START);
559 return !(I386BADMAG(id));
560 }
561
coff386_init_fmt(void)562 static void __FASTCALL__ coff386_init_fmt( void )
563 {
564 BGLOBAL main_handle;
565 __filesize_t s_off = sizeof(coff386hdr);
566 tUIntFast16 i;
567 bmReadBufferEx(&coff386hdr,sizeof(struct external_filehdr),0,SEEKF_START);
568 if(COFF_WORD(coff386hdr.f_opthdr)) bmReadBuffer(&coff386ahdr,sizeof(AOUTHDR));
569 nsections = COFF_WORD(coff386hdr.f_nscns);
570 if(!(coff386so = PMalloc((unsigned)(sizeof(SCNHDR)*nsections))))
571 {
572 MemOutBox("Coff386 initialization");
573 exit(EXIT_FAILURE);
574 }
575 main_handle = bmbioHandle();
576 if((coff_cache = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) coff_cache = main_handle;
577 if(COFF_WORD(coff386hdr.f_opthdr)) s_off += COFF_WORD(coff386hdr.f_opthdr);
578 bioSeek(coff_cache,s_off,BIO_SEEK_SET);
579 for(i = 0;i < nsections;i++)
580 {
581 bioReadBuffer(coff_cache,&coff386so[i],sizeof(SCNHDR));
582 }
583 strings_ptr = COFF_DWORD(coff386hdr.f_symptr)+COFF_DWORD(coff386hdr.f_nsyms)*sizeof(struct external_syment);
584 }
585
coff386_destroy_fmt(void)586 static void __FASTCALL__ coff386_destroy_fmt( void )
587 {
588 BGLOBAL main_handle;
589 PFREE(coff386so);
590 if(PubNames) { la_Destroy(PubNames); PubNames = 0; }
591 main_handle = bmbioHandle();
592 if(coff_cache != &bNull && coff_cache != main_handle) bioClose(coff_cache);
593 }
594
coff386_bitness(__filesize_t off)595 static int __FASTCALL__ coff386_bitness(__filesize_t off)
596 {
597 UNUSED(off);
598 return DAB_USE32;
599 }
600
coff386_AddrResolv(char * addr,__filesize_t cfpos)601 static tBool __FASTCALL__ coff386_AddrResolv(char *addr,__filesize_t cfpos)
602 {
603 /* Since this function is used in references resolving of disassembler
604 it must be seriously optimized for speed. */
605 tBool bret = True;
606 tUInt32 res;
607 if(cfpos < sizeof(struct external_filehdr))
608 {
609 strcpy(addr,"coffih:");
610 strcpy(&addr[7],Get2Digit(cfpos));
611 }
612 else
613 if((res=coff386_PA2VA(cfpos))!=0)
614 {
615 addr[0] = '.';
616 strcpy(&addr[1],Get8Digit(res));
617 }
618 else bret = False;
619 return bret;
620 }
621
coff386Help(void)622 static __filesize_t __FASTCALL__ coff386Help( void )
623 {
624 hlpDisplay(10002);
625 return BMGetCurrFilePos();
626 }
627
coff_ReadPubName(BGLOBAL b_cache,const struct PubName * it,char * buff,unsigned cb_buff)628 static void __FASTCALL__ coff_ReadPubName(BGLOBAL b_cache,const struct PubName *it,
629 char *buff,unsigned cb_buff)
630 {
631 if(!it->addinfo)
632 coffReadLongName(b_cache,it->nameoff,buff,cb_buff);
633 else
634 {
635 bioSeek(b_cache,it->nameoff,BIO_SEEK_SET);
636 bioReadBuffer(b_cache,buff,it->addinfo);
637 buff[it->addinfo] = 0;
638 }
639 }
640
coff_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ * mem_out)(const char *))641 static void __FASTCALL__ coff_ReadPubNameList(BGLOBAL handle,
642 void (__FASTCALL__ *mem_out)(const char *))
643 {
644 unsigned i,nnames;
645 struct PubName pn;
646 if(!(PubNames = la_Build(0,sizeof(struct PubName),mem_out))) return;
647 bioSeek(handle,COFF_DWORD(coff386hdr.f_symptr),SEEKF_START);
648 nnames = coffSymTabNumItems(handle);
649 for(i = 0;i < nnames;i++)
650 {
651 struct external_syment cse;
652 __filesize_t where;
653 tUIntFast16 sec_num;
654 where = bioTell(handle);
655 bioReadBuffer(handle,&cse,sizeof(struct external_syment));
656 sec_num = COFF_WORD(cse.e_scnum);
657 if(sec_num && sec_num <= COFF_WORD(coff386hdr.f_nscns) &&
658 (cse.e_sclass[0] == C_EXT ||
659 cse.e_sclass[0] == C_STAT ||
660 cse.e_sclass[0] == C_HIDDEN ||
661 cse.e_sclass[0] == C_LABEL))
662 {
663 if(COFF_DWORD(cse.e.e.e_zeroes) == 0L &&
664 COFF_DWORD(cse.e.e.e_offset) >= 4)
665 {
666 pn.nameoff = COFF_DWORD(cse.e.e.e_offset);
667 pn.addinfo = 0;
668 }
669 else
670 {
671 pn.nameoff = where;
672 pn.addinfo = E_SYMNMLEN;
673 }
674 pn.pa = COFF_DWORD(coff386so[sec_num-1].s_scnptr)+COFF_DWORD(cse.e_value);
675 pn.attr = cse.e_sclass[0] == C_EXT ? SC_GLOBAL : SC_LOCAL;
676 if(!la_AddData(PubNames,&pn,mem_out)) break;
677 }
678 if(bioEOF(handle)) break;
679 }
680 la_Sort(PubNames,fmtComparePubNames);
681 }
682
coff386_GetPubSym(char * str,unsigned cb_str,unsigned * func_class,__filesize_t pa,tBool as_prev)683 static __filesize_t __FASTCALL__ coff386_GetPubSym(char *str,unsigned cb_str,unsigned *func_class,
684 __filesize_t pa,tBool as_prev)
685 {
686 return fmtGetPubSym(coff_cache,str,cb_str,func_class,pa,as_prev,
687 coff_ReadPubNameList,
688 coff_ReadPubName);
689 }
690
coff386_GetObjAttr(__filesize_t pa,char * name,unsigned cb_name,__filesize_t * start,__filesize_t * end,int * _class,int * bitness)691 static unsigned __FASTCALL__ coff386_GetObjAttr(__filesize_t pa,char *name,unsigned cb_name,
692 __filesize_t *start,__filesize_t *end,int *_class,int *bitness)
693 {
694 unsigned ret;
695 tUIntFast16 i;
696 *start = 0;
697 *end = bmGetFLength();
698 *_class = OC_NOOBJECT;
699 *bitness = DAB_USE32;
700 name[0] = 0;
701 ret = 0;
702 for(i = 0;i < nsections;i++)
703 {
704 if(pa >= *start && pa < COFF_DWORD(coff386so[i].s_scnptr))
705 {
706 /** means between two objects */
707 *end = COFF_DWORD(coff386so[i].s_scnptr);
708 ret = 0;
709 break;
710 }
711 if(pa >= COFF_DWORD(coff386so[i].s_scnptr) && pa < COFF_DWORD(coff386so[i].s_scnptr) + COFF_DWORD(coff386so[i].s_size))
712 {
713 *start = COFF_DWORD(coff386so[i].s_scnptr);
714 *end = *start + COFF_DWORD(coff386so[i].s_size);
715 *_class = (COFF_DWORD(coff386so[i].s_flags) & STYP_TEXT) == STYP_TEXT ? OC_CODE : OC_DATA;
716 strncpy(name,(const char *)coff386so[i].s_name,min(sizeof(coff386so[i].s_name),cb_name));
717 name[sizeof(coff386so[i].s_name)] = 0;
718 ret = i+1;
719 break;
720 }
721 *start = COFF_DWORD(coff386so[i].s_scnptr) + COFF_DWORD(coff386so[i].s_size);
722 }
723 return ret;
724 }
725
coff386_platform(void)726 static int __FASTCALL__ coff386_platform( void ) { return DISASM_CPU_IX86; }
727
728 REGISTRY_BIN coff386Table =
729 {
730 "coff-i386 (Common Object File Format)",
731 { "CofHlp", NULL, NULL, NULL, NULL, NULL, "SymTab", NULL, NULL, "Objects" },
732 { coff386Help, NULL, NULL, NULL, NULL, NULL, coffShowSymTab, NULL, NULL, coffShowObjects },
733 coff386_check_fmt,
734 coff386_init_fmt,
735 coff386_destroy_fmt,
736 ShowCoff386Header,
737 coff386_AppendRef,
738 fmtSetState,
739 coff386_platform,
740 coff386_bitness,
741 NULL,
742 coff386_AddrResolv,
743 coff386_VA2PA,
744 coff386_PA2VA,
745 coff386_GetPubSym,
746 coff386_GetObjAttr,
747 NULL,
748 NULL
749 };
750