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