1 /**
2  * @namespace   biew_plugins_auto
3  * @file        plugins/bin/elf386.c
4  * @brief       This file contains implementation of ELF-32 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 
18 /*
19     A short ELF hacker's guide from author of biew.
20     ===============================================
21     IMHO ELF is too complex format and contains surplusing information
22     like SECTION HEADERS and PROGRAM HEADERS.
23     As a rule, in normal ELF files both types are present.
24     But there is minor number of non-standard ELF files where
25     some type of headers are missing (or section or program ones).
26     In case when SECTION HEADERS are lost, executable files and shared
27     objects are workable, but BFD utilities can not handle such file
28     properly, and so it will be no longer possible to link something
29     against such file (but biew works with such files properly).
30     In case when PROGRAM HEADERS are lost, executable files and shared
31     objects are not workable, but RELOCATABLE OBJECTS will be normally
32     linked to target executable or shared object.
33     See also:
34 
35     http://www.caldera.com/developers/gabi/
36     http://segfault.net/~scut/cpu/generic/
37     http://www.linuxassembly.org
38 
39     ELFkickers This distribution is a collection of programs that are generally
40                unrelated, except in that they all deal with the ELF file format.
41 
42     teensy     tools that are provided as exhibitions of just how compressed a
43                Linux ELF executable can be and still function.
44 
45     These can be found at:
46     http://www.muppetlabs.com/~breadbox/software/
47 */
48 
49 #include <limits.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 #include "colorset.h"
55 #include "plugins/bin/elf386.h"
56 #include "plugins/disasm.h"
57 #include "bin_util.h"
58 #include "codeguid.h"
59 #include "bmfile.h"
60 #include "biewhelp.h"
61 #include "tstrings.h"
62 #include "biewutil.h"
63 #include "bconsole.h"
64 #include "reg_form.h"
65 #include "biewlib/biewlib.h"
66 #include "biewlib/pmalloc.h"
67 #include "biewlib/kbd_code.h"
68 
69 static char is_msbf; /* is most significand byte first */
70 static char is_64bit;
71 
72 typedef union
73 {
74   Elf386_External_Ehdr e32;
75   Elf64_External_Ehdr  e64;
76 }ElfXX_External_Ehdr;
77 
78 static ElfXX_External_Ehdr elf;
79 #define ELF_EHDR(e,FIELD) (is_64bit?(((Elf64_External_Ehdr *)&e.e64)->FIELD):(((Elf386_External_Ehdr *)&e.e32)->FIELD))
80 #define ELF_EHDR_SIZE() (is_64bit?sizeof(Elf64_External_Ehdr):sizeof(Elf386_External_Ehdr))
81 
82 typedef union
83 {
84   Elf386_External_Dyn e32;
85   Elf64_External_Dyn  e64;
86 }ElfXX_External_Dyn;
87 #define ELF_EDYN(e,FIELD) (is_64bit?(((Elf64_External_Dyn *)&e.e64)->FIELD):(((Elf386_External_Dyn *)&e.e32)->FIELD))
88 #define ELF_EDYN_SIZE() (is_64bit?sizeof(Elf64_External_Dyn):sizeof(Elf386_External_Dyn))
89 
90 typedef union
91 {
92   Elf386_External_Phdr e32;
93   Elf64_External_Phdr  e64;
94 }ElfXX_External_Phdr;
95 #define ELF_PHDR(e,FIELD) (is_64bit?(((Elf64_External_Phdr *)&e.e64)->FIELD):(((Elf386_External_Phdr *)&e.e32)->FIELD))
96 #define ELF_PHDR_SIZE() (is_64bit?sizeof(Elf64_External_Phdr):sizeof(Elf386_External_Phdr))
97 
98 typedef union
99 {
100   Elf386_External_Shdr e32;
101   Elf64_External_Shdr  e64;
102 }ElfXX_External_Shdr;
103 #define ELF_SHDR(e,FIELD) (is_64bit?(((Elf64_External_Shdr *)&e.e64)->FIELD):(((Elf386_External_Shdr *)&e.e32)->FIELD))
104 #define ELF_SHDR_SIZE() (is_64bit?sizeof(Elf64_External_Shdr):sizeof(Elf386_External_Shdr))
105 
106 typedef union
107 {
108   Elf386_External_Sym e32;
109   Elf64_External_Sym  e64;
110 }ElfXX_External_Sym;
111 #define ELF_SYM(e,FIELD) (is_64bit?(((Elf64_External_Sym *)&e.e64)->FIELD):(((Elf386_External_Sym *)&e.e32)->FIELD))
112 #define ELF_SYM_SIZE() (is_64bit?sizeof(Elf64_External_Sym):sizeof(Elf386_External_Sym))
113 
114 typedef union
115 {
116   Elf386_External_Rel e32;
117   Elf64_External_Rel  e64;
118 }ElfXX_External_Rel;
119 #define ELF_REL(e,FIELD) (is_64bit?(((Elf64_External_Rel *)&e.e64)->FIELD):(((Elf386_External_Rel *)&e.e32)->FIELD))
120 #define ELF_REL_SIZE() (is_64bit?sizeof(Elf64_External_Rel):sizeof(Elf386_External_Rel))
121 
122 typedef union
123 {
124   Elf386_External_Rela e32;
125   Elf64_External_Rela  e64;
126 }ElfXX_External_Rela;
127 #define ELF_RELA(e,FIELD) (is_64bit?(((Elf64_External_Rela *)&e.e64)->FIELD):(((Elf386_External_Rela *)&e.e32)->FIELD))
128 #define ELF_RELA_SIZE() (is_64bit?sizeof(Elf64_External_Rela):sizeof(Elf386_External_Rela))
129 
130 static __filesize_t active_shtbl = 0;
131 static __filesize_t elf_min_va = FILESIZE_MAX;
132 static unsigned long __elfNumSymTab = 0;
133 static __filesize_t  __elfSymShTbl = 0;
134 static unsigned long __elfSymEntSize = 0;
135 static __filesize_t  __elfSymPtr = 0L;
136 
137 struct tag_elfVAMap
138 {
139   __filesize_t va;
140   __filesize_t size;
141   __filesize_t foff;
142   __filesize_t nameoff;
143   __filesize_t flags;
144 };
145 
146 #define ELF_HALF(cval) FMT_WORD(cval,is_msbf)
147 #define ELF_WORD(cval) FMT_DWORD(cval,is_msbf)
148 #define ELF_XWORD(cval) (is_64bit?FMT_QWORD(cval,is_msbf):FMT_DWORD(cval,is_msbf))
149 #define ELF_ADDR(cval) ELF_XWORD(cval)
150 #define ELF_OFF(cval) ELF_XWORD(cval)
151 
152 static tBool __NEAR__ __FASTCALL__ FindPubName(char *buff,unsigned cb_buff,__filesize_t pa);
153 static void __FASTCALL__ elf_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ *mem_out)(const char *));
154 static __filesize_t __FASTCALL__ elfVA2PA(__filesize_t va);
155 static __filesize_t __FASTCALL__ elfPA2VA(__filesize_t pa);
156 static tBool IsSectionsPresent;
157 
findPHEntry(unsigned long type,unsigned * nitems)158 static __filesize_t __NEAR__ __FASTCALL__ findPHEntry(unsigned long type,unsigned *nitems)
159 {
160   __filesize_t fpos,dynptr;
161   ElfXX_External_Phdr phdr;
162   size_t i,limit;
163   fpos = bmGetCurrFilePos();
164   dynptr = 0;
165   *nitems = 0;
166   limit = ELF_HALF(ELF_EHDR(elf,e_phnum));
167   for(i = 0;i < limit;i++)
168   {
169    bmReadBufferEx(&phdr,sizeof(phdr),ELF_OFF(ELF_EHDR(elf,e_phoff)) + i*ELF_HALF(ELF_EHDR(elf,e_phentsize)),SEEKF_START);
170    if(bmEOF()) break;
171    if(ELF_WORD(ELF_PHDR(phdr,p_type)) == type)
172    {
173      dynptr = ELF_OFF(ELF_PHDR(phdr,p_offset));
174      *nitems = ELF_OFF(ELF_PHDR(phdr,p_filesz))/ELF_EDYN_SIZE();
175      break;
176    }
177   }
178   bmSeek(fpos,SEEKF_START);
179   return dynptr;
180 }
181 
findPHDynEntry(unsigned long type,__filesize_t dynptr,unsigned long nitems)182 static __filesize_t __NEAR__ __FASTCALL__ findPHDynEntry(unsigned long type,
183 							__filesize_t dynptr,
184 							unsigned long nitems)
185 {
186   unsigned i;
187   __filesize_t fpos;
188   tBool is_found = False;
189   ElfXX_External_Dyn dyntab;
190   fpos = bmGetCurrFilePos();
191   bmSeek(dynptr,SEEKF_START);
192   for(i = 0;i < nitems;i++)
193   {
194     bmReadBufferEx(&dyntab,ELF_EDYN_SIZE(),dynptr,SEEKF_START);
195     if(bmEOF()) break;
196     dynptr += ELF_EDYN_SIZE();
197     if(ELF_XWORD(ELF_EDYN(dyntab,d_tag)) == type) { is_found = True; break; }
198   }
199   bmSeek(fpos,SEEKF_START);
200   return is_found ? ELF_XWORD(ELF_EDYN(dyntab,d_un.d_ptr)) : 0L;
201 }
202 
findPHPubSyms(unsigned long * number,unsigned long * ent_size,__filesize_t * act_shtbl)203 static __filesize_t __NEAR__ __FASTCALL__ findPHPubSyms(unsigned long *number,
204 							unsigned long *ent_size,
205 							__filesize_t *act_shtbl)
206 {
207   __filesize_t fpos, dynptr, dyn_ptr;
208   unsigned i, nitems;
209   fpos = bmGetCurrFilePos();
210   *ent_size = UINT_MAX;
211     /* Here we did an attempt to detect symbol table even if sections header
212        are lost */
213     dyn_ptr = dynptr = findPHEntry(PT_DYNAMIC,&nitems);
214     if(dynptr)
215     {
216       dynptr = elfVA2PA(findPHDynEntry(DT_SYMTAB,dyn_ptr,nitems));
217       if(dynptr)
218       {
219         *act_shtbl = elfVA2PA(findPHDynEntry(DT_STRTAB,dyn_ptr,nitems));
220         *ent_size = findPHDynEntry(DT_SYMENT,dyn_ptr,nitems);
221        /* Only way to determine size of symbol table entries it's find
222            nearest section that follows DT_SYMTAB.
223 	   FixME: It dangerous technique. May be there exists most safety way ?
224 	*/
225         {
226           __filesize_t _fpos,dptr,max_val,cur_ptr;
227           ElfXX_External_Dyn dyntab;
228           _fpos = bmGetCurrFilePos();
229 	  dptr = dyn_ptr;
230           bmSeek(dptr,SEEKF_START);
231 	  max_val = bmGetFLength(); /* if section is last */
232           for(i = 0;i < nitems;i++)
233           {
234             bmReadBufferEx(&dyntab,sizeof(dyntab),dptr,SEEKF_START);
235             if(bmEOF()) break;
236             dptr += ELF_EDYN_SIZE();
237 	    cur_ptr = elfVA2PA(ELF_XWORD(ELF_EDYN(dyntab,d_un.d_ptr)));
238             if(cur_ptr > dynptr && cur_ptr < max_val) max_val = cur_ptr;
239           }
240           bmSeek(_fpos,SEEKF_START);
241   	  *number = (max_val - dynptr) / *ent_size;
242         }
243       }
244     }
245   bmSeek(fpos, SEEKF_START);
246   return dynptr;
247 }
248 
249 static __filesize_t __NEAR__ __FASTCALL__
findSHEntry(BGLOBAL b_cache,unsigned long type,unsigned long * nitems,__filesize_t * link,unsigned long * ent_size)250                      findSHEntry(BGLOBAL b_cache, unsigned long type,
251                                  unsigned long *nitems,__filesize_t *link,
252                                  unsigned long *ent_size)
253 {
254   ElfXX_External_Shdr shdr;
255   __filesize_t fpos, tableptr;
256   size_t i, limit;
257   fpos = bioTell(b_cache);
258   tableptr = 0L;
259   limit = ELF_HALF(ELF_EHDR(elf,e_shnum));
260   for(i = 0;i < limit;i++)
261   {
262    bioSeek(b_cache,ELF_OFF(ELF_EHDR(elf,e_shoff)) + i*ELF_HALF(ELF_EHDR(elf,e_shentsize)),SEEKF_START);
263    bioReadBuffer(b_cache,&shdr,sizeof(shdr));
264    if(bioEOF(b_cache)) break;
265    if(ELF_WORD(ELF_SHDR(shdr,sh_type)) == type)
266    {
267      tableptr = ELF_OFF(ELF_SHDR(shdr,sh_offset));
268      *nitems = ELF_XWORD(ELF_SHDR(shdr,sh_size))/ELF_XWORD(ELF_SHDR(shdr,sh_entsize));
269      *link = ELF_WORD(ELF_SHDR(shdr,sh_link));
270      *ent_size = ELF_XWORD(ELF_SHDR(shdr,sh_entsize));
271      break;
272    }
273   }
274   bioSeek(b_cache, fpos, SEEKF_START);
275   return tableptr;
276 }
277 
278 static BGLOBAL namecache = &bNull;
279 static BGLOBAL namecache2 = &bNull;
280 static BGLOBAL elfcache = &bNull;
281 
282 static linearArray *va_map_phys,* va_map_virt;
283 
vamap_comp_virt(const void __HUGE__ * v1,const void __HUGE__ * v2)284 static tCompare __FASTCALL__ vamap_comp_virt(const void __HUGE__ *v1,const void __HUGE__ *v2)
285 {
286   const struct tag_elfVAMap __HUGE__ *pnam1,__HUGE__ *pnam2;
287   pnam1 = (const struct tag_elfVAMap __HUGE__ *)v1;
288   pnam2 = (const struct tag_elfVAMap __HUGE__ *)v2;
289   return pnam1->va<pnam2->va?-1:pnam1->va>pnam2->va?1:0;
290 }
291 
vamap_comp_phys(const void __HUGE__ * v1,const void __HUGE__ * v2)292 static tCompare __FASTCALL__ vamap_comp_phys(const void __HUGE__ *v1,const void __HUGE__ *v2)
293 {
294   const struct tag_elfVAMap __HUGE__ *pnam1,__HUGE__ *pnam2;
295   pnam1 = (const struct tag_elfVAMap __HUGE__ *)v1;
296   pnam2 = (const struct tag_elfVAMap __HUGE__ *)v2;
297   return pnam1->foff<pnam2->foff?-1:pnam1->foff>pnam2->foff?1:0;
298 }
299 
elfVA2PA(__filesize_t va)300 static __filesize_t __FASTCALL__ elfVA2PA(__filesize_t va)
301 {
302   unsigned long i;
303   if(va_map_virt)
304   for(i = 0; i < va_map_virt->nItems;i++)
305   {
306     struct tag_elfVAMap __HUGE__ *evm;
307     evm = &((struct tag_elfVAMap __HUGE__ *)va_map_virt->data)[i];
308     if(va >= evm->va && va < evm->va + evm->size) return evm->foff + (va - evm->va);
309   }
310   return 0L;
311 }
312 
elfPA2VA(__filesize_t pa)313 static __filesize_t __FASTCALL__ elfPA2VA(__filesize_t pa)
314 {
315   unsigned long i;
316   __filesize_t ret;
317   ret = 0L;
318   for(i = 0; i < va_map_phys->nItems;i++)
319   {
320     struct tag_elfVAMap __HUGE__ *evm;
321     evm = &((struct tag_elfVAMap __HUGE__ *)va_map_phys->data)[i];
322     if(pa >= evm->foff && pa < evm->foff + evm->size)
323     {
324       ret = evm->va + (pa - evm->foff);
325       break;
326     }
327   }
328   return ret;
329 }
330 
elfLowMemFunc(unsigned long need_mem)331 static tBool __FASTCALL__ elfLowMemFunc( unsigned long need_mem )
332 {
333   UNUSED(need_mem);
334   if(!fmtActiveState)
335   {
336     if(PubNames)
337     {
338        la_Destroy(PubNames);
339        PubNames = NULL;
340        return True;
341     }
342   }
343   return False;
344 }
345 
elf386_readnametable(__filesize_t off,char * buf,unsigned blen)346 static void __NEAR__ __FASTCALL__ elf386_readnametable(__filesize_t off,char *buf,unsigned blen)
347 {
348   __filesize_t foff;
349   ElfXX_External_Shdr sh;
350   unsigned char ch;
351   unsigned freq;
352 
353   BGLOBAL b_cache,b_cache2;
354   b_cache = namecache;
355   b_cache2 = namecache2;
356   foff = ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_HALF(ELF_EHDR(elf,e_shstrndx))*ELF_HALF(ELF_EHDR(elf, e_shentsize));
357   bioSeek(b_cache2,foff,SEEKF_START);
358   bioReadBuffer(b_cache2,&sh,sizeof(sh));
359   foff = ELF_OFF(ELF_SHDR(sh,sh_offset)) + off;
360   freq = 0;
361   while(1)
362   {
363      bioSeek(b_cache,foff++,SEEKF_START);
364      ch = bioReadByte(b_cache);
365      buf[freq++] = ch;
366      if(!ch || freq >= blen || bioEOF(b_cache)) break;
367   }
368 }
369 
elf386_readnametableex(__filesize_t off,char * buf,unsigned blen)370 static void __NEAR__ __FASTCALL__ elf386_readnametableex(__filesize_t off,char *buf,unsigned blen)
371 {
372   __filesize_t foff;
373   ElfXX_External_Shdr sh;
374   unsigned char ch;
375   unsigned freq;
376   BGLOBAL b_cache,b_cache2;
377   b_cache = namecache;
378   b_cache2 = namecache2;
379   if(ELF_OFF(ELF_EHDR(elf,e_shoff)))
380   {
381     foff = ELF_OFF(ELF_EHDR(elf,e_shoff))+active_shtbl*ELF_HALF(ELF_EHDR(elf, e_shentsize));
382     bioSeek(b_cache2,foff,SEEKF_START);
383     bioReadBuffer(b_cache2,&sh,sizeof(sh));
384     foff = ELF_OFF(ELF_SHDR(sh,sh_offset)) + off;
385   }
386   /* if section headers are lost then active_shtbl should directly point to
387      required string table */
388   else  foff = active_shtbl + off;
389   freq = 0;
390   while(1)
391   {
392      bioSeek(b_cache,foff++,SEEKF_START);
393      ch = bioReadByte(b_cache);
394      buf[freq++] = ch;
395      if(!ch || freq >= blen || bioEOF(b_cache)) break;
396   }
397 }
398 
elf_class(unsigned char id)399 static const char * __NEAR__ __FASTCALL__ elf_class(unsigned char id)
400 {
401   switch(id)
402   {
403     case ELFCLASSNONE:	return "Invalid";
404     case ELFCLASS32:	return "32-bit";
405     case ELFCLASS64:	return "64-bit";
406     default:		return "Unknown";
407   }
408 }
409 
elf_data(unsigned char id)410 static const char * __NEAR__ __FASTCALL__ elf_data(unsigned char id)
411 {
412   switch(id)
413   {
414     case ELFDATANONE:	return "Invalid";
415     case ELFDATA2LSB:	return "LSB - little endian";
416     case ELFDATA2MSB:	return "MSB - big endian";
417     default:		return "Unknown";
418   }
419 }
420 
elf_otype(unsigned id)421 static const char *__NEAR__ __FASTCALL__ elf_otype(unsigned id)
422 {
423   switch(id)
424   {
425     case ET_NONE:	return "none";
426     case ET_REL:	return "relocatable";
427     case ET_EXEC:	return "executable";
428     case ET_DYN:	return "shared object";
429     case ET_CORE:	return "core";
430     case ET_LOOS:	return "OS-specific low";
431     case ET_HIOS:	return "OS-specific high";
432     case ET_LOPROC:	return "processor-specific low";
433     case ET_HIPROC:	return "processor-specific high";
434     default:		return "Unknown";
435   }
436 }
437 
438 /*
439     only common machine types are used, add remaining if needed
440 */
441 
elf_machine(unsigned id,unsigned * disasm)442 static const char *__NEAR__ __FASTCALL__ elf_machine(unsigned id,unsigned *disasm)
443 {
444   *disasm=DISASM_DATA;
445   switch(id)
446   {
447     case EM_NONE:	return "None";
448     case EM_M32:	return "AT&T WE32100";
449     case EM_SPARC:	*disasm = DISASM_CPU_SPARC; return "Sun SPARC";
450     case EM_386:	*disasm = DISASM_CPU_IX86; return "Intel 386";
451     case EM_68K:	*disasm = DISASM_CPU_PPC; return "Motorola m68k";
452     case EM_88K:	*disasm = DISASM_CPU_PPC; return "Motorola m88k";
453     case EM_860:	return "Intel 80860";
454     case EM_MIPS:	*disasm = DISASM_CPU_MIPS; return "MIPS I";
455     case EM_S370:	return "IBM System/370";
456     case EM_MIPS_RS3_LE:*disasm = DISASM_CPU_MIPS; return "MIPS R3000";
457     case EM_PARISC:	return "HP PA-RISC";
458     case EM_SPARC32PLUS:*disasm = DISASM_CPU_SPARC; return "SPARC v8plus";
459     case EM_960:	return "Intel 80960";
460     case EM_PPC:	*disasm = DISASM_CPU_PPC; return "Power PC 32-bit";
461     case EM_PPC64:	*disasm = DISASM_CPU_PPC; return "Power PC 64-bit";
462     case EM_S390:	return "IBM System/390";
463     case EM_ADSP:	return "Atmel ADSP";
464     case EM_V800:	return "NEC V800";
465     case EM_FR20:	return "Fujitsu FR20";
466     case EM_RH32:	return "TRW RH-32";
467     case EM_RCE:	return "Motorola RCE";
468     case EM_ARM:	*disasm=DISASM_CPU_ARM; return "ARM";
469     case EM_ALPHA:	*disasm = DISASM_CPU_ALPHA; return "DEC Alpha";
470     case EM_SH:		*disasm = DISASM_CPU_SH; return "Hitachi SH";
471     case EM_SPARCV9:	*disasm = DISASM_CPU_SPARC; return "SPARC v9 64-bit";
472     case EM_TRICORE:	return "Siemens TriCore embedded processor";
473     case EM_ARC:	return "Argonaut RISC Core";
474     case EM_H8_300:	return "Hitachi H8/300";
475     case EM_H8_300H:	return "Hitachi H8/300H";
476     case EM_H8S:	return "Hitachi H8S";
477     case EM_H8_500:	return "Hitachi H8/500";
478     case EM_IA_64:	*disasm = DISASM_CPU_IA64; return "Intel IA-64";
479     case EM_MIPS_X:	*disasm = DISASM_CPU_MIPS; return "Stanford MIPS-X";
480     case EM_COLDFIRE:	return "Motorola ColdFire";
481     case EM_68HC12:	return "Motorola M68HC12";
482     case EM_MMA:	return "Fujitsu MMA Multimedia Accelerator";
483     case EM_PCP:	return "Siemens PCP";
484     case EM_NCPU:	return "Sony nCPU embedded RISC processor";
485     case EM_NDR1:	return "Denso NDR1 microprocessor";
486     case EM_STARCORE:	return "Motorola StarCore processor";
487     case EM_ME16:	return "Toyota ME16 processor";
488     case EM_ST100:	return "STMicroelectronics ST100 processor";
489     case EM_TINYJ:	return "Advanced Logic Corp. TinyJ";
490     case EM_X86_64:	*disasm = DISASM_CPU_IX86; return "AMD x86-64";
491     case EM_PDSP:	return "Sony DSP Processor";
492     case EM_PDP10:	return "DEC PDP-10";
493     case EM_PDP11:	return "DEC PDP-11";
494     case EM_FX66:	return "Siemens FX66 microcontroller";
495     case EM_ST9PLUS:	return "STMicroelectronics ST9+ 8/16 bit microcontroller";
496     case EM_ST7:	return "STMicroelectronics ST7 8-bit microcontroller";
497     case EM_68HC16:	return "Motorola MC68HC16 Microcontroller";
498     case EM_68HC11:	return "Motorola MC68HC11 Microcontroller";
499     case EM_68HC08:	return "Motorola MC68HC08 Microcontroller";
500     case EM_68HC05:	return "Motorola MC68HC05 Microcontroller";
501     case EM_SVX:	return "Silicon Graphics SVx";
502     case EM_ST19:	return "STMicroelectronics ST19 8-bit microcontroller";
503     case EM_VAX:	return "DEC VAX";
504     case EM_CRIS:	return "Axis Comm. 32-bit embedded processor";
505     case EM_JAVELIN:	return "Infineon Tech. 32-bit embedded processor";
506     case EM_FIREPATH:	return "Element 14 64-bit DSP Processor";
507     case EM_ZSP:	return "LSI Logic 16-bit DSP Processor";
508     case EM_MMIX:	return "Donald Knuth's educational 64-bit processor";
509     case EM_HUANY:	return "Harvard University machine-independent object files";
510     case EM_PRISM:	return "SiTera Prism";
511     case EM_AVR:	*disasm=DISASM_CPU_AVR; return "Atmel AVR 8-bit";
512     case EM_FR30:	return "Fujitsu FR30";
513     case EM_D10V:	return "Mitsubishi D10V";
514     case EM_D30V:	return "Mitsubishi D30V";
515     case EM_V850:	return "NEC v850";
516     case EM_M32R:	return "Mitsubishi M32R";
517     case EM_MN10300:	return "Matsushita MN10300";
518     case EM_MN10200:	return "Matsushita MN10200";
519     case EM_PJ:		return "picoJava";
520     case EM_OPENRISC:	return "OpenRISC 32-bit embedded processor";
521     case EM_ARC_A5:	return "ARC Cores Tangent-A5";
522     case EM_XTENSA:	return "Tensilica Xtensa Architecture";
523     case EM_VIDEOCORE:	return "Alphamosaic VideoCore processor";
524     case EM_TMM_GPP:	return "Thompson Multimedia General Purpose Processor";
525     case EM_NS32K:	return "National Semiconductor 32000 series";
526     case EM_TPC:	return "Tenor Network TPC processor";
527     case EM_SNP1K:	return "Trebia SNP 1000 processor";
528     case EM_IP2K:	return "Ubicom IP2022 micro controller";
529     case EM_CR:		return "National Semiconductor CompactRISC";
530     case EM_MSP430:	return "TI msp430 micro controller";
531     case EM_BLACKFIN:	return "ADI Blackfin";
532     case EM_ALTERA_NIOS2: return "Altera Nios II soft-core processor";
533     case EM_CRX:	return "National Semiconductor CRX";
534     case EM_XGATE:	return "Motorola XGATE embedded processor";
535     case EM_C166:	return "Infineon C16x/XC16x processor";
536     case EM_M16C:	return "Renesas M16C series microprocessors";
537     case EM_DSPIC30F:	return "Microchip Technology dsPIC30F Digital Signal Controller";
538     case EM_CE:		return "Freescale Communication Engine RISC core";
539     case EM_M32C:	return "Renesas M32C series microprocessors";
540     case EM_TSK3000:	return "Altium TSK3000 core";
541     case EM_RS08:	return "Freescale RS08 embedded processor";
542     case EM_ECOG2:	return "Cyan Technology eCOG2 microprocessor";
543     case EM_SCORE:	return "Sunplus Score";
544     case EM_DSP24:	return "New Japan Radio (NJR) 24-bit DSP Processor";
545     case EM_VIDEOCORE3:	return "Broadcom VideoCore III processor";
546     case EM_LATTICEMICO32: return "RISC processor for Lattice FPGA architecture";
547     case EM_SE_C17:	return "Seiko Epson C17 family";
548     case EM_MMDSP_PLUS:	return "STMicroelectronics 64bit VLIW Data Signal Processor";
549     case EM_CYPRESS_M8C:return "Cypress M8C microprocessor";
550     case EM_R32C:	return "Renesas R32C series microprocessors";
551     case EM_TRIMEDIA:	return "NXP Semiconductors TriMedia architecture family";
552     case EM_QDSP6:	return "QUALCOMM DSP6 Processor";
553     case EM_8051:	return "Intel 8051 and variants";
554     case EM_STXP7X:	return "STMicroelectronics STxP7x family";
555     case EM_NDS32:	return "Andes Technology compact code size embedded RISC processor family";
556     case EM_ECOG1X:	return "Cyan Technology eCOG1X family";
557     case EM_MAXQ30:	return "Dallas Semiconductor MAXQ30 Core Micro-controllers";
558     case EM_XIMO16:	return "New Japan Radio (NJR) 16-bit DSP Processor";
559     case EM_MANIK:	return "M2000 Reconfigurable RISC Microprocessor";
560     case EM_CRAYNV2:	*disasm = DISASM_CPU_CRAY; return "Cray Inc. NV2 vector architecture";
561     case EM_RX:		return "Renesas RX family";
562     case EM_METAG:	return "Imagination Technologies META processor architecture";
563     case EM_MCST_ELBRUS:return "MCST Elbrus general purpose hardware architecture";
564     case EM_ECOG16:	return "Cyan Technology eCOG16 family";
565     case EM_CR16:	return "National Semiconductor CompactRISC 16-bit processor";
566     default:		return "Unknown";
567   }
568 }
569 
elf_version(unsigned long id)570 static const char *__NEAR__ __FASTCALL__ elf_version(unsigned long id)
571 {
572   switch(id)
573   {
574     case EV_NONE:    return "Invalid";
575     case EV_CURRENT: return "Current";
576     default:         return "Unknown";
577   }
578 }
579 
elf_osabi(unsigned char id)580 static const char *__NEAR__ __FASTCALL__ elf_osabi(unsigned char id)
581 {
582   switch(id)
583   {
584     case ELFOSABI_SYSV:		return "UNIX System V";
585     case ELFOSABI_HPUX:		return "HP-UX";
586     case ELFOSABI_NETBSD:	return "NetBSD";
587     case ELFOSABI_LINUX:	return "GNU/Linux";
588     case ELFOSABI_HURD:		return "GNU/Hurd";
589     case ELFOSABI_86OPEN:	return "86Open";
590     case ELFOSABI_SOLARIS:	return "Solaris";
591     case ELFOSABI_MONTEREY:	return "Monterey";
592     case ELFOSABI_IRIX:		return "IRIX";
593     case ELFOSABI_FREEBSD:	return "FreeBSD";
594     case ELFOSABI_TRU64:	return "TRU64 UNIX";
595     case ELFOSABI_MODESTO:	return "Novell Modesto";
596     case ELFOSABI_OPENBSD:	return "OpenBSD";
597     case ELFOSABI_ARM:		return "ARM";
598     case ELFOSABI_STANDALONE:	return "Standalone (embedded) application";
599     default:			return "Unknown";
600   }
601 }
602 
603 
ShowELFHeader(void)604 static __filesize_t __FASTCALL__ ShowELFHeader( void )
605 {
606   __filesize_t fpos;
607   TWindow *w;
608   char hdr[81];
609   unsigned keycode,dummy;
610   __filesize_t entrya;
611   fpos = BMGetCurrFilePos();
612   entrya = elfVA2PA(ELF_ADDR(ELF_EHDR(elf,e_entry)));
613   sprintf(hdr," ELF (Executable and Linking Format) ");
614   w = CrtDlgWndnls(hdr,74,19);
615   twGotoXY(1,1);
616   twPrintF("Signature                         = %02X %02X %02X %02XH (%c%c%c%c)\n"
617            "File class                        = %02XH (%s)\n"
618            "Data encoding                     = %02XH (%s)\n"
619            "ELF header version                = %02XH (%s)\n"
620            "Operating system / ABI            = %02XH (%s)\n"
621            "ABI version                       = %02XH (%d)\n"
622            "Object file type                  = %04XH (%s)\n"
623            "Machine architecture              = %04XH (%s)\n"
624            "Object file version               = %08lXH (%s)\n"
625 	    ,ELF_EHDR(elf,e_ident[EI_MAG0]),	ELF_EHDR(elf, e_ident[EI_MAG1])
626 	    ,ELF_EHDR(elf,e_ident[EI_MAG2]),	ELF_EHDR(elf,e_ident[EI_MAG3])
627 	    ,ELF_EHDR(elf,e_ident[EI_MAG0]),	ELF_EHDR(elf,e_ident[EI_MAG1])
628 	    ,ELF_EHDR(elf,e_ident[EI_MAG2]),	ELF_EHDR(elf,e_ident[EI_MAG3])
629 	    ,ELF_EHDR(elf,e_ident[EI_CLASS]), 	elf_class(ELF_EHDR(elf,e_ident[EI_CLASS]))
630 	    ,ELF_EHDR(elf,e_ident[EI_DATA]),	elf_data(ELF_EHDR(elf,e_ident[EI_DATA]))
631 	    ,ELF_EHDR(elf,e_ident[EI_VERSION]),	elf_version(ELF_EHDR(elf,e_ident[EI_VERSION]))
632 	    ,ELF_EHDR(elf,e_ident[EI_OSABI]),	elf_osabi(ELF_EHDR(elf,e_ident[EI_OSABI]))
633 	    ,ELF_EHDR(elf,e_ident[EI_ABIVERSION]),ELF_EHDR(elf,e_ident[EI_ABIVERSION])
634 	    ,ELF_HALF(ELF_EHDR(elf,e_type)),	elf_otype(ELF_HALF(ELF_EHDR(elf,e_type)))
635 	    ,ELF_HALF(ELF_EHDR(elf,e_machine)),	elf_machine(ELF_HALF(ELF_EHDR(elf,e_machine)),&dummy)
636 	    ,ELF_WORD(ELF_EHDR(elf,e_version)),	elf_version(ELF_WORD(ELF_EHDR(elf,e_version)))
637   );
638   twSetColorAttr(dialog_cset.entry);
639   if(is_64bit)
640     twPrintF("Entry point VA             = %016llXH (offset: %016llXH)"
641            ,(unsigned long long)ELF_ADDR(ELF_EHDR(elf,e_entry)),(unsigned long long)entrya);
642   else
643     twPrintF("Entry point VA                    = %08lXH (offset: %08lXH)"
644            ,(unsigned)ELF_ADDR(ELF_EHDR(elf,e_entry)),(unsigned)entrya);
645   twClrEOL(); twPrintF("\n");
646   twSetColorAttr(dialog_cset.main);
647   if(is_64bit)
648     twPrintF("Program header table offset       = %016llXH\n"
649            "Section header table offset       = %016llXH\n"
650            ,ELF_OFF(ELF_EHDR(elf,e_phoff))
651            ,ELF_OFF(ELF_EHDR(elf,e_shoff)));
652   else
653     twPrintF("Program header table offset       = %08lXH\n"
654            "Section header table offset       = %08lXH\n"
655            ,ELF_OFF(ELF_EHDR(elf,e_phoff))
656            ,ELF_OFF(ELF_EHDR(elf,e_shoff)));
657   twPrintF(
658            "Processor specific flag           = %08lXH\n"
659            "ELF header size (bytes)           = %04XH\n"
660            "Program header table entry size   = %04XH\n"
661            "Program header table entry count  = %04XH\n"
662            "Section header table entry size   = %04XH\n"
663            "Section header table entry count  = %04XH\n"
664            "Section header string table index = %04XH"
665            ,ELF_WORD(ELF_EHDR(elf,e_flags))
666            ,ELF_HALF(ELF_EHDR(elf,e_ehsize))
667            ,ELF_HALF(ELF_EHDR(elf,e_phentsize))
668            ,ELF_HALF(ELF_EHDR(elf,e_phnum))
669            ,ELF_HALF(ELF_EHDR(elf,e_shentsize))
670            ,ELF_HALF(ELF_EHDR(elf,e_shnum))
671            ,ELF_HALF(ELF_EHDR(elf,e_shstrndx)));
672   while(1)
673   {
674     keycode = GetEvent(drawEmptyPrompt,NULL,w);
675     if(keycode == KE_ENTER) { fpos = entrya; break; }
676     else
677       if(keycode == KE_ESCAPE || keycode == KE_F(10)) break;
678   }
679   CloseWnd(w);
680   return fpos;
681 }
682 
elf_encode_p_type(long p_type)683 static const char * __NEAR__ __FASTCALL__ elf_encode_p_type(long p_type)
684 {
685    switch(p_type)
686    {
687       case PT_NULL: return "Unusable";
688       case PT_LOAD: return "Loadable";
689       case PT_DYNAMIC: return "Dynalinking";
690       case PT_INTERP: return "Interpreter";
691       case PT_NOTE:  return "Auxiliary";
692       case PT_SHLIB: return "Unspecified";
693       case PT_PHDR:  return "header itself";
694       case PT_NUM: return "Number of types";
695       case PT_LOPROC: return "Low processor";
696       case PT_HIPROC: return "High processor";
697       default:  return "Unknown";
698    }
699 }
700 
__elfReadPrgHdr(BGLOBAL handle,memArray * obj,unsigned nnames)701 static tBool __FASTCALL__ __elfReadPrgHdr(BGLOBAL handle,memArray *obj,unsigned nnames)
702 {
703  size_t i;
704   bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_phoff)),SEEKF_START);
705   for(i = 0;i < nnames;i++)
706   {
707    __filesize_t fp;
708    char stmp[80];
709    ElfXX_External_Phdr phdr;
710    if(IsKbdTerminate() || bioEOF(handle)) break;
711    fp = bioTell(handle);
712    bioReadBuffer(handle,&phdr,sizeof(phdr));
713    bioSeek(handle,fp+ELF_HALF(ELF_EHDR(elf,e_phentsize)),SEEKF_START);
714    sprintf(stmp,"%-15s %08lX %08lX %08lX %08lX %08lX %c%c%c %08lX",
715                 elf_encode_p_type(ELF_WORD(ELF_PHDR(phdr,p_type))),
716                 (unsigned long)ELF_OFF(ELF_PHDR(phdr,p_offset)),
717                 (unsigned long)ELF_ADDR(ELF_PHDR(phdr,p_vaddr)),
718                 (unsigned long)ELF_ADDR(ELF_PHDR(phdr,p_paddr)),
719                 (unsigned long)ELF_OFF(ELF_PHDR(phdr,p_filesz)),
720                 (unsigned long)ELF_OFF(ELF_PHDR(phdr,p_memsz)),
721                 (ELF_WORD(ELF_PHDR(phdr,p_flags)) & PF_X) == PF_X ? 'X' : ' ',
722                 (ELF_WORD(ELF_PHDR(phdr,p_flags)) & PF_W) == PF_W ? 'W' : ' ',
723                 (ELF_WORD(ELF_PHDR(phdr,p_flags)) & PF_R) == PF_R ? 'R' : ' ',
724                 (unsigned long)ELF_OFF(ELF_PHDR(phdr,p_align))
725           );
726    if(!ma_AddString(obj,stmp,True)) break;
727   }
728   return True;
729 }
730 
elf_encode_sh_type(long sh_type)731 static const char * __NEAR__ __FASTCALL__ elf_encode_sh_type(long sh_type)
732 {
733    switch(sh_type)
734    {
735       case SHT_NULL: return "NULL";
736       case SHT_PROGBITS: return "PRGBTS";
737       case SHT_SYMTAB: return "SYMTAB";
738       case SHT_STRTAB: return "STRTAB";
739       case SHT_RELA:  return "RELA";
740       case SHT_HASH: return "HSHTAB";
741       case SHT_DYNAMIC:  return "DYNLNK";
742       case SHT_NOTE: return "NOTES";
743       case SHT_NOBITS: return "NOBITS";
744       case SHT_REL:  return "REL";
745       case SHT_SHLIB: return "UNSPEC";
746       case SHT_DYNSYM: return "DYNSYM";
747       case SHT_NUM: return "NTYPES";
748       case SHT_GNU_verdef: return "VERDEF";
749       case SHT_GNU_verneed: return "VERNED";
750       case SHT_GNU_versym: return "SYMVER";
751       case SHT_LOPROC: return "LOPROC";
752       case SHT_HIPROC: return "HIPROC";
753       case SHT_LOUSER: return "LOUSER";
754       case SHT_HIUSER: return "HIUSER";
755       default:  return "UNK";
756    }
757 }
758 
__elfReadSecHdr(BGLOBAL handle,memArray * obj,unsigned nnames)759 static tBool __FASTCALL__ __elfReadSecHdr(BGLOBAL handle,memArray *obj,unsigned nnames)
760 {
761  size_t i;
762   bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff)),SEEKF_START);
763   for(i = 0;i < nnames;i++)
764   {
765    ElfXX_External_Shdr shdr;
766    char tmp[17];
767    __filesize_t fp;
768    char stmp[80];
769    if(IsKbdTerminate() || bioEOF(handle)) break;
770    fp = bioTell(handle);
771    bioReadBuffer(handle,&shdr,sizeof(shdr));
772    elf386_readnametable(ELF_WORD(ELF_SHDR(shdr,sh_name)),tmp,sizeof(tmp));
773    bioSeek(handle,fp+ELF_HALF(ELF_EHDR(elf,e_shentsize)),SEEKF_START);
774    tmp[16] = 0;
775    sprintf(stmp,"%-16s %-6s %c%c%c %08lX %08lX %08lX %04hX %04hX %04hX %04hX",
776                 tmp,
777                 elf_encode_sh_type(ELF_WORD(ELF_SHDR(shdr,sh_type))),
778                 (ELF_XWORD(ELF_SHDR(shdr,sh_flags)) & SHF_WRITE) == SHF_WRITE ? 'W' : ' ',
779                 (ELF_XWORD(ELF_SHDR(shdr,sh_flags)) & SHF_ALLOC) == SHF_ALLOC ? 'A' : ' ',
780                 (ELF_XWORD(ELF_SHDR(shdr,sh_flags)) & SHF_EXECINSTR) == SHF_EXECINSTR ? 'X' : ' ',
781                 (unsigned long)ELF_ADDR(ELF_SHDR(shdr,sh_addr)),
782                 (unsigned long)ELF_OFF(ELF_SHDR(shdr,sh_offset)),
783                 (unsigned long)ELF_XWORD(ELF_SHDR(shdr,sh_size)),
784                 (tUInt16)ELF_WORD(ELF_SHDR(shdr,sh_link)),
785                 (tUInt16)ELF_WORD(ELF_SHDR(shdr,sh_info)),
786                 (tUInt16)ELF_XWORD(ELF_SHDR(shdr,sh_addralign)),
787                 (tUInt16)ELF_XWORD(ELF_SHDR(shdr,sh_entsize))
788           );
789     if(!ma_AddString(obj,stmp,True)) break;
790   }
791   return True;
792 }
793 
elf_SymTabType(char type)794 static const char * __NEAR__ __FASTCALL__ elf_SymTabType(char type)
795 {
796   switch(ELF_ST_TYPE(type))
797   {
798     case STT_NOTYPE:  return "NoType";
799     case STT_OBJECT:  return "Object";
800     case STT_FUNC:    return "Func. ";
801     case STT_SECTION: return "Sect. ";
802     case STT_FILE:    return "File  ";
803     case STT_NUM:     return "Number";
804     case STT_LOPROC:  return "LoProc";
805     case STT_HIPROC:  return "HiProc";
806     default: return "Unknwn";
807   }
808 }
809 
elf_SymTabBind(char type)810 static const char * __NEAR__ __FASTCALL__ elf_SymTabBind(char type)
811 {
812   switch(ELF_ST_BIND(type))
813   {
814     case STB_LOCAL:  return "Local ";
815     case STB_GLOBAL: return "Global";
816     case STB_WEAK:   return "Weak  ";
817     case STB_NUM:    return "Number";
818     case STB_LOPROC: return "LoProc";
819     case STB_HIPROC: return "HiProc";
820     default: return "Unknwn";
821   }
822 }
823 
elf_SymTabShNdx(unsigned idx)824 static const char * __NEAR__ __FASTCALL__ elf_SymTabShNdx(unsigned idx)
825 {
826   static char ret[10];
827   switch(idx)
828   {
829     case SHN_UNDEF:  return "Undef ";
830     case SHN_LOPROC: return "LoProc";
831     case SHN_HIPROC: return "HiProc";
832     case SHN_ABS:    return "Abs.  ";
833     case SHN_COMMON: return "Common";
834     case SHN_HIRESERVE: return "HiRes.";
835     default: sprintf(ret,"%04XH ",idx); return ret;
836   }
837 }
838 
ELF_IS_SECTION_PHYSICAL(unsigned sec_num)839 static tBool __NEAR__ __FASTCALL__ ELF_IS_SECTION_PHYSICAL(unsigned sec_num)
840 {
841   return !(sec_num == SHN_UNDEF || sec_num == SHN_LOPROC ||
842            sec_num == SHN_HIPROC || sec_num == SHN_ABS ||
843            sec_num == SHN_COMMON || sec_num == SHN_HIRESERVE);
844 }
845 
__elfGetNumSymTab(BGLOBAL handle)846 static unsigned __FASTCALL__ __elfGetNumSymTab( BGLOBAL handle )
847 {
848   UNUSED(handle);
849   return __elfNumSymTab;
850 }
851 
__elfReadSymTab(BGLOBAL handle,memArray * obj,unsigned nsym)852 static tBool __FASTCALL__ __elfReadSymTab(BGLOBAL handle,memArray *obj,unsigned nsym)
853 {
854  size_t i,tlen;
855  char text[37];
856   tlen=is_64bit?29:37;
857   bioSeek(handle,__elfSymPtr,SEEK_SET);
858   for(i = 0;i < nsym;i++)
859   {
860    __filesize_t fp;
861    char stmp[80];
862    ElfXX_External_Sym sym;
863    if(IsKbdTerminate() || bioEOF(handle)) break;
864    fp = bioTell(handle);
865    bioReadBuffer(handle,&sym,sizeof(sym));
866    bioSeek(handle,fp+__elfSymEntSize,SEEKF_START);
867    elf386_readnametableex(ELF_WORD(ELF_SYM(sym,st_name)),text,tlen);
868    text[tlen-1] = 0;
869    if(is_64bit)
870    sprintf(stmp,"%-29s %016llX %08lX %04hX %s %s %s"
871                ,text
872                ,(unsigned long long)ELF_XWORD(ELF_SYM(sym,st_value))
873                ,(unsigned)ELF_XWORD(ELF_SYM(sym,st_size))
874                ,ELF_HALF(ELF_SYM(sym,st_other))
875                ,elf_SymTabType(ELF_SYM(sym,st_info[0]))
876                ,elf_SymTabBind(ELF_SYM(sym,st_info[0]))
877                ,elf_SymTabShNdx(ELF_HALF(ELF_SYM(sym,st_shndx)))
878                );
879    else
880    sprintf(stmp,"%-37s %08lX %08lX %04hX %s %s %s"
881                ,text
882                ,(unsigned)ELF_XWORD(ELF_SYM(sym,st_value))
883                ,(unsigned)ELF_XWORD(ELF_SYM(sym,st_size))
884                ,ELF_HALF(ELF_SYM(sym,st_other))
885                ,elf_SymTabType(ELF_SYM(sym,st_info[0]))
886                ,elf_SymTabBind(ELF_SYM(sym,st_info[0]))
887                ,elf_SymTabShNdx(ELF_HALF(ELF_SYM(sym,st_shndx)))
888                );
889    if(!ma_AddString(obj,stmp,True)) break;
890   }
891   return True;
892 }
893 
__elfReadDynTab(BGLOBAL handle,memArray * obj,unsigned ntbl,__filesize_t entsize)894 static tBool __NEAR__ __FASTCALL__ __elfReadDynTab(BGLOBAL handle,memArray *obj, unsigned ntbl,__filesize_t entsize)
895 {
896  size_t i;
897  char sout[80];
898  unsigned len,rlen,rborder;
899   for(i = 0;i < ntbl;i++)
900   {
901    __filesize_t fp;
902    char stmp[80];
903    ElfXX_External_Dyn pdyn;
904    fp = bioTell(handle);
905    bioReadBuffer(handle,&pdyn,sizeof(pdyn));
906    bioSeek(handle,fp+entsize,SEEKF_START);
907    fp = bioTell(handle);
908    /* Note: elf-64 specs requre ELF_XWORD here! But works ELF_WORD !!! */
909    elf386_readnametableex(ELF_WORD(ELF_EDYN(pdyn,d_tag)),sout,sizeof(sout));
910    len = strlen(sout);
911    rborder=is_64bit?52:60;
912    if(len > rborder-4) len = rborder-7;
913    if(IsKbdTerminate() || bioEOF(handle)) break;
914    strncpy(stmp,sout,len);
915    stmp[len] = 0;
916    if(len > rborder-4) strcat(stmp,"...");
917    rlen = strlen(stmp);
918    if(rlen < rborder) { memset(&stmp[rlen],' ',rborder-rlen); stmp[rborder] = 0; }
919    if(is_64bit)
920     sprintf(&stmp[strlen(stmp)]," vma=%016llXH",(unsigned long long)ELF_XWORD(ELF_EDYN(pdyn,d_un.d_val)));
921    else
922     sprintf(&stmp[strlen(stmp)]," vma=%08lXH",(unsigned long)ELF_XWORD(ELF_EDYN(pdyn,d_un.d_val)));
923    if(!ma_AddString(obj,stmp,True)) break;
924    bioSeek(handle,fp,SEEKF_START);
925   }
926   return True;
927 }
928 
Elf386PrgHdrNumItems(BGLOBAL handle)929 static unsigned __FASTCALL__ Elf386PrgHdrNumItems(BGLOBAL handle)
930 {
931    UNUSED(handle);
932    return ELF_HALF(ELF_EHDR(elf,e_phnum));
933 }
934 
ShowPrgHdrElf(void)935 static __filesize_t __FASTCALL__ ShowPrgHdrElf(void)
936 {
937   __filesize_t fpos;
938   int ret;
939   fpos = BMGetCurrFilePos();
940   ret = fmtShowList(Elf386PrgHdrNumItems,__elfReadPrgHdr,
941                     " type            fileoffs virtaddr physaddr filesize memsize  flg align   ",
942                     LB_SELECTIVE,NULL);
943   if(ret != -1)
944   {
945     ElfXX_External_Phdr it;
946     bmSeek(ELF_OFF(ELF_EHDR(elf,e_phoff))+ELF_PHDR_SIZE()*ret,SEEKF_START);
947     bmReadBuffer(&it,sizeof(it));
948     fpos = ELF_OFF(ELF_PHDR(it,p_offset));
949   }
950   return fpos;
951 }
952 
Elf386SecHdrNumItems(BGLOBAL handle)953 static unsigned __FASTCALL__ Elf386SecHdrNumItems(BGLOBAL handle)
954 {
955   UNUSED(handle);
956   return IsSectionsPresent ? ELF_HALF(ELF_EHDR(elf,e_shnum)) : 0;
957 }
958 
ShowSecHdrElf(void)959 static __filesize_t __FASTCALL__ ShowSecHdrElf(void)
960 {
961   __filesize_t fpos;
962   int ret;
963   fpos = BMGetCurrFilePos();
964   ret = fmtShowList(Elf386SecHdrNumItems,__elfReadSecHdr,
965                     " name             type   flg virtaddr fileoffs   size   link info algn esiz",
966                    LB_SELECTIVE,NULL);
967   if(ret != -1)
968   {
969     ElfXX_External_Shdr it;
970 //    bmSeek(ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_SHDR_SIZE()*ret,SEEKF_START);
971     bmSeek(ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_HALF(ELF_EHDR(elf, e_shentsize))*ret,SEEKF_START);
972     bmReadBuffer(&it,sizeof(it));
973     fpos = ELF_OFF(ELF_SHDR(it,sh_offset));
974   }
975   return fpos;
976 }
977 
__calcSymEntry(BGLOBAL handle,__filesize_t num,tBool display_msg)978 static __filesize_t __calcSymEntry(BGLOBAL handle,__filesize_t num,tBool display_msg)
979 {
980    ElfXX_External_Sym it;
981    ElfXX_External_Shdr sec;
982    __filesize_t ffpos,fpos = 0L;
983    ffpos = bioTell(handle);
984    bioSeek(handle,__elfSymPtr+__elfSymEntSize*num,SEEKF_START);
985    bioReadBuffer(handle,&it,sizeof(it));
986 //   bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_SHDR_SIZE()*ELF_HALF(ELF_SYM(it,st_shndx)),SEEKF_START);
987    bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_HALF(ELF_EHDR(elf, e_shentsize))*ELF_HALF(ELF_SYM(it,st_shndx)),SEEKF_START);
988    bioReadBuffer(handle,&sec,sizeof(sec));
989    bioSeek(handle,ffpos,SEEKF_START);
990    if(ELF_IS_SECTION_PHYSICAL(ELF_HALF(ELF_SYM(it,st_shndx))))
991 /*
992    In relocatable files, st_value holds alignment constraints for a
993    symbol whose section index is SHN_COMMON.
994 
995    In relocatable files, st_value holds a section offset for a defined
996    symbol. That is, st_value is an offset from the beginning of the
997    section that st_shndx identifies.
998 
999    In executable and shared object files, st_value holds a virtual
1000    address. To make these files' symbols more useful for the dynamic
1001    linker, the section offset (file interpretation) gives way to a
1002    virtual address (memory interpretation) for which the section number
1003    is irrelevant.
1004 */
1005      fpos = ELF_HALF(ELF_EHDR(elf,e_type)) == ET_REL ?
1006             ELF_OFF(ELF_SHDR(sec,sh_offset)) + ELF_XWORD(ELF_SYM(it,st_value)):
1007             elfVA2PA(ELF_XWORD(ELF_SYM(it,st_value)));
1008    else
1009      if(display_msg) ErrMessageBox(NO_ENTRY,BAD_ENTRY);
1010    return fpos;
1011 }
1012 
displayELFsymtab(void)1013 static __filesize_t __NEAR__ __FASTCALL__ displayELFsymtab( void )
1014 {
1015   __filesize_t fpos;
1016   int ret;
1017   fpos = BMGetCurrFilePos();
1018   ret = fmtShowList(__elfGetNumSymTab,__elfReadSymTab,
1019                 " Name                                  Value    Size     Oth. Type   Bind   Sec# ",
1020                 LB_SELECTIVE,NULL);
1021   if(ret != -1)
1022   {
1023     __filesize_t ea;
1024     ea = __calcSymEntry(bmbioHandle(),ret,True);
1025     fpos = ea ? ea : fpos;
1026   }
1027   return fpos;
1028 }
1029 
displayELFdyntab(__filesize_t dynptr,unsigned long nitem,long entsize)1030 static __filesize_t __NEAR__ __FASTCALL__ displayELFdyntab(__filesize_t dynptr,
1031 							unsigned long nitem,
1032 							long entsize)
1033 {
1034   __filesize_t fpos;
1035   memArray *obj;
1036   BGLOBAL handle;
1037   unsigned ndyn;
1038   fpos = BMGetCurrFilePos();
1039   ndyn = (unsigned)nitem;
1040   if(!(obj = ma_Build(ndyn,True))) return fpos;
1041   handle = elfcache;
1042   bioSeek(handle,dynptr,SEEK_SET);
1043   if(__elfReadDynTab(handle,obj,ndyn,entsize))
1044   {
1045     int ret;
1046     ret = ma_Display(obj," Dynamic section ",LB_SELECTIVE | LB_SORTABLE,-1);
1047     if(ret != -1)
1048     {
1049        char *addr;
1050        addr = strstr(obj->data[ret],"vma=");
1051        if(addr)
1052        {
1053          __filesize_t addr_probe;
1054          addr_probe = is_64bit?strtoull(&addr[4],NULL,16):strtoul(&addr[4],NULL,16);
1055          if(addr_probe && addr_probe >= elf_min_va)
1056          {
1057            addr_probe = elfVA2PA(addr_probe);
1058            if(addr_probe && addr_probe < bmGetFLength()) fpos = addr_probe;
1059            else goto not_entry;
1060          }
1061          else goto not_entry;
1062        }
1063        else
1064        {
1065          not_entry:
1066          ErrMessageBox(NOT_ENTRY,NULL);
1067        }
1068     }
1069   }
1070   ma_Destroy(obj);
1071   return fpos;
1072 }
1073 
ShowELFSymTab(void)1074 static __filesize_t __FASTCALL__ ShowELFSymTab( void )
1075 {
1076   __filesize_t fpos;
1077   fpos = BMGetCurrFilePos();
1078   if(!__elfSymPtr) { NotifyBox(NOT_ENTRY," ELF symbol table "); return fpos; }
1079   active_shtbl = __elfSymShTbl;
1080   return displayELFsymtab();
1081 }
1082 
ShowELFDynSec(void)1083 static __filesize_t __FASTCALL__ ShowELFDynSec( void )
1084 {
1085   __filesize_t fpos,dynptr;
1086   unsigned long number;
1087   unsigned long nitems,ent_size = UINT_MAX;
1088   fpos = BMGetCurrFilePos();
1089   dynptr = findSHEntry(bmbioHandle(), SHT_DYNSYM, &number, &active_shtbl, &ent_size);
1090   if(!dynptr)
1091   {
1092     dynptr = findPHPubSyms(&nitems, &ent_size, &active_shtbl);
1093     number = nitems;
1094   }
1095   if(!dynptr) { NotifyBox(NOT_ENTRY," ELF dynamic symbol table "); return fpos; }
1096   return displayELFdyntab(dynptr,number,ent_size);
1097 }
1098 
1099 /***************************************************************************/
1100 /************************ RELOCATION FOR ELF *******************************/
1101 /***************************************************************************/
1102 typedef struct tagElfRefChain
1103 {
1104   __filesize_t  offset;
1105   __filesize_t  info;
1106   __filesize_t  addend;
1107   __filesize_t  sh_idx;
1108 }Elf_Reloc;
1109 static linearArray *CurrElfChain = NULL;
1110 
compare_elf_reloc(const void __HUGE__ * e1,const void __HUGE__ * e2)1111 static tCompare __FASTCALL__ compare_elf_reloc(const void __HUGE__ *e1,const void __HUGE__ *e2)
1112 {
1113   const Elf_Reloc __HUGE__ *p1,__HUGE__ *p2;
1114   p1 = (const Elf_Reloc __HUGE__ *)e1;
1115   p2 = (const Elf_Reloc __HUGE__ *)e2;
1116   return p1->offset<p2->offset?-1:p1->offset>p2->offset?1:0;
1117 }
1118 
get_f_offset(__filesize_t r_offset,__filesize_t sh_link)1119 static __filesize_t get_f_offset(__filesize_t r_offset,__filesize_t sh_link)
1120 {
1121   /*
1122     r_offset member gives the location at which to apply the relocation
1123     action. For a relocatable file, the value is the byte offset from
1124     the beginning of the section to the storage unit affected by the
1125     relocation. For an executable file or a shared object, the value is
1126     the virtual address of the storage unit affected by the relocation.
1127   */
1128   __filesize_t f_offset;
1129   BGLOBAL handle = elfcache;
1130   switch(ELF_HALF(ELF_EHDR(elf,e_type)))
1131   {
1132      case ET_REL:
1133                 {
1134                   ElfXX_External_Shdr shdr;
1135                   __filesize_t fp;
1136                   fp = bioTell(handle);
1137 //                  bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+sh_link*ELF_SHDR_SIZE(),SEEKF_START);
1138                   bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+sh_link*ELF_HALF(ELF_EHDR(elf, e_shentsize)),SEEKF_START);
1139                   bioReadBuffer(handle,&shdr,sizeof(shdr));
1140 		  bioSeek(handle,fp,SEEKF_START);
1141 		  f_offset = ELF_OFF(ELF_SHDR(shdr,sh_offset)) + r_offset;
1142                 }
1143      default: f_offset = elfVA2PA(r_offset);
1144               break;
1145   }
1146   return f_offset;
1147 }
1148 
1149 #define bioRead30(handle2) (bioReadDWord(handle2)&0x3FFFFFFFUL)
1150 #define bioRead25(handle2) (bioReadDWord(handle2)&0x01FFFFFFUL)
1151 #define bioRead24(handle2) (bioReadDWord(handle2)&0x00FFFFFFUL)
1152 #define bioRead22(handle2) (bioReadDWord(handle2)&0x003FFFFFUL)
1153 #define bioRead19(handle2) (bioReadDWord(handle2)&0x0007FFFFUL)
1154 #define bioRead12(handle2) (bioReadWord(handle2)&0x0FFFUL)
1155 
__elf_arm_read_erc(BGLOBAL handle2,Elf_Reloc * erc)1156 static void __elf_arm_read_erc(BGLOBAL handle2,Elf_Reloc *erc)
1157 {
1158     switch(ELF32_R_TYPE(erc->info))
1159     {
1160       case R_ARM_THM_JUMP6:
1161       case R_ARM_THM_PC8:
1162       case R_ARM_ABS8:
1163       case R_ARM_THM_JUMP8:
1164                erc->addend = bioReadByte(handle2);
1165                break;
1166       case R_ARM_THM_JUMP11:
1167       case R_ARM_GOT_BREL12:
1168       case R_ARM_GOTOFF12:
1169       case R_ARM_TLS_LDO12:
1170       case R_ARM_TLS_LE12:
1171       case R_ARM_TLS_IE12GP:
1172       case R_ARM_ABS12:
1173       case R_ARM_THM_PC12:
1174                erc->addend = bioRead12(handle2);
1175                break;
1176       case R_ARM_ABS16:
1177                erc->addend = bioReadWord(handle2);
1178                break;
1179       case R_ARM_THM_JUMP19:
1180                erc->addend = bioRead19(handle2);
1181                break;
1182       case R_ARM_THM_XPC22:
1183       case R_ARM_THM_RPC22:
1184                erc->addend = bioRead22(handle2);
1185                break;
1186       case R_ARM_SWI24:
1187       case R_ARM_JUMP24:
1188       case R_ARM_THM_JUMP24:
1189       case R_ARM_RPC24:
1190                erc->addend = bioRead24(handle2);
1191                break;
1192       case R_ARM_XPC25:
1193       case R_ARM_RXPC25:
1194                erc->addend = bioRead25(handle2);
1195                break;
1196       default:
1197                erc->addend = bioReadDWord(handle2);
1198                break;
1199     }
1200 }
1201 
__elf_i386_read_erc(BGLOBAL handle2,Elf_Reloc * erc)1202 static void __elf_i386_read_erc(BGLOBAL handle2,Elf_Reloc *erc)
1203 {
1204     switch(ELF32_R_TYPE(erc->info))
1205     {
1206       case R_386_GNU_8:
1207       case R_386_GNU_PC8:
1208                erc->addend = bioReadByte(handle2);
1209                break;
1210       case R_386_GNU_16:
1211       case R_386_GNU_PC16:
1212                erc->addend = bioReadWord(handle2);
1213                break;
1214       default:
1215                erc->addend = bioReadDWord(handle2);
1216                break;
1217     }
1218 }
1219 
__elf_x86_64_read_erc(BGLOBAL handle2,Elf_Reloc * erc)1220 static void __elf_x86_64_read_erc(BGLOBAL handle2,Elf_Reloc *erc) {
1221     switch(ELF32_R_TYPE(erc->info))
1222     {
1223       case R_X86_64_8:
1224       case R_X86_64_PC8:
1225                erc->addend = bioReadByte(handle2);
1226                break;
1227       case R_X86_64_16:
1228       case R_X86_64_PC16:
1229                erc->addend = bioReadWord(handle2);
1230                break;
1231       case R_X86_64_32:
1232       case R_X86_64_32S:
1233       case R_X86_64_PC32:
1234       case R_X86_64_GOT32:
1235       case R_X86_64_PLT32:
1236       case R_X86_64_DTPOFF32:
1237       case R_X86_64_GOTTPOFF:
1238       case R_X86_64_TPOFF32:
1239       case R_X86_64_GOTPC32_TLSDESC:
1240                erc->addend = bioReadDWord(handle2);
1241                break;
1242       default:
1243                erc->addend = bioReadQWord(handle2);
1244                break;
1245     }
1246 }
1247 
__elf_ppc_read_erc(BGLOBAL handle2,Elf_Reloc * erc)1248 static void __elf_ppc_read_erc(BGLOBAL handle2,Elf_Reloc *erc)
1249 {
1250     switch(ELF32_R_TYPE(erc->info))
1251     {
1252       case R_ARM_THM_JUMP6:
1253       case R_ARM_THM_PC8:
1254       case R_ARM_ABS8:
1255       case R_ARM_THM_JUMP8:
1256                erc->addend = bioReadByte(handle2);
1257                break;
1258       case R_ARM_THM_JUMP11:
1259       case R_ARM_GOT_BREL12:
1260       case R_ARM_GOTOFF12:
1261       case R_ARM_TLS_LDO12:
1262       case R_ARM_TLS_LE12:
1263       case R_ARM_TLS_IE12GP:
1264       case R_ARM_ABS12:
1265       case R_ARM_THM_PC12:
1266                erc->addend = bioRead12(handle2);
1267                break;
1268       default:
1269                erc->addend = bioReadWord(handle2);
1270                break;
1271       case R_PPC_ADDR24:
1272       case R_PPC_REL24:
1273       case R_PPC_PLTREL24:
1274       case R_PPC_LOCAL24PC:
1275                erc->addend = bioRead24(handle2);
1276                break;
1277       case R_PPC_ADDR32:
1278       case R_PPC_GLOB_DAT:
1279       case R_PPC_JMP_SLOT:
1280       case R_PPC_RELATIVE:
1281       case R_PPC_UADDR32:
1282       case R_PPC_REL32:
1283       case R_PPC_PLT32:
1284       case R_PPC_PLTREL32:
1285       case R_PPC_ADDR30:
1286       case R_PPC_DTPMOD32:
1287       case R_PPC_TPREL32:
1288       case R_PPC_DTPREL32:
1289       case R_PPC_EMB_NADDR32:
1290       case R_PPC_RELAX32:
1291       case R_PPC_RELAX32PC:
1292       case R_PPC_RELAX32_PLT:
1293       case R_PPC_RELAX32PC_PLT:
1294       case R_PPC_GNU_VTINHERIT:
1295       case R_PPC_GNU_VTENTRY:
1296                erc->addend = bioReadDWord(handle2);
1297                break;
1298       case R_PPC64_ADDR64:
1299       case R_PPC64_UADDR64:
1300       case R_PPC64_REL64:
1301       case R_PPC64_PLT64:
1302       case R_PPC64_PLTREL64:
1303       case R_PPC64_TOC:
1304                erc->addend = bioReadQWord(handle2);
1305                break;
1306     }
1307 }
1308 
__elfReadRelSection(__filesize_t offset,__filesize_t size,__filesize_t sh_link,__filesize_t info,__filesize_t entsize)1309 static void __NEAR__ __FASTCALL__ __elfReadRelSection(__filesize_t offset,
1310 							__filesize_t size,
1311 							__filesize_t sh_link,
1312 							__filesize_t info,
1313 							__filesize_t entsize)
1314 {
1315   BGLOBAL handle = elfcache,handle2 = namecache;
1316   size_t i,nitems;
1317   ElfXX_External_Rel relent;
1318   __filesize_t fp, sfp, lfp;
1319   if(!entsize) return;
1320   fp = bioTell(handle);
1321   bioSeek(handle,offset,SEEKF_START);
1322   nitems = (size_t)(size / entsize);
1323   sfp = bioTell(handle2);
1324   for(i = 0;i < nitems;i++)
1325   {
1326     Elf_Reloc erc;
1327     lfp=bioTell(handle);
1328     bioReadBuffer(handle,&relent,sizeof(relent));
1329     bioSeek(handle,lfp+ELF_REL_SIZE(),SEEKF_START);
1330     if(entsize > ELF_REL_SIZE()) bioSeek(handle,entsize-ELF_REL_SIZE(),SEEKF_CUR);
1331     erc.offset = get_f_offset(ELF_OFF(ELF_REL(relent,r_offset)),info);
1332     erc.info = ELF_XWORD(ELF_REL(relent,r_info));
1333     /* Entries of type Elf32_Rel store an implicit addend in the
1334        location to be modified */
1335     bioSeek(handle2, erc.offset, SEEKF_START);
1336     switch(ELF_HALF(ELF_EHDR(elf,e_machine)))
1337     {
1338       default: erc.addend = 0;
1339       case EM_ARM: __elf_arm_read_erc(handle2,&erc); break;
1340       case EM_386: __elf_i386_read_erc(handle2,&erc); break;
1341       case EM_X86_64: __elf_x86_64_read_erc(handle2,&erc); break;
1342       case EM_PPC:
1343       case EM_PPC64: __elf_ppc_read_erc(handle2,&erc); break;
1344     }
1345     erc.sh_idx = sh_link;
1346     if(!la_AddData(CurrElfChain,&erc,NULL)) break;
1347   }
1348   bioSeek(handle2,sfp,SEEKF_START);
1349   bioSeek(handle,fp,SEEKF_START);
1350 }
1351 
__elfReadRelaSection(__filesize_t offset,__filesize_t size,__filesize_t sh_link,__filesize_t info,__filesize_t entsize)1352 static void __NEAR__ __FASTCALL__ __elfReadRelaSection(__filesize_t offset,
1353 							__filesize_t size,
1354 							__filesize_t sh_link,
1355 							__filesize_t info,
1356 							__filesize_t entsize)
1357 {
1358   BGLOBAL handle = elfcache;
1359   size_t i,nitems;
1360   ElfXX_External_Rela relent;
1361   __filesize_t fp, lfp;
1362   if(!entsize) return;
1363   fp = bioTell(handle);
1364   bioSeek(handle,offset,SEEKF_START);
1365   nitems = (size_t)(size / entsize);
1366   for(i = 0;i < nitems;i++)
1367   {
1368     Elf_Reloc erc;
1369     lfp=bioTell(handle);
1370     bioReadBuffer(handle,&relent,sizeof(relent));
1371     bioSeek(handle,lfp+ELF_RELA_SIZE(), SEEKF_START);
1372     if(entsize > ELF_RELA_SIZE()) bioSeek(handle,entsize-ELF_RELA_SIZE(),SEEKF_CUR);
1373     erc.offset = get_f_offset(ELF_OFF(ELF_RELA(relent,r_offset)),info);
1374     erc.info = ELF_XWORD(ELF_RELA(relent,r_info));
1375     erc.addend = ELF_XWORD(ELF_RELA(relent,r_addend));
1376     erc.sh_idx = sh_link;
1377     if(!la_AddData(CurrElfChain,&erc,NULL)) break;
1378   }
1379   bioSeek(handle,fp,SEEKF_START);
1380 }
1381 
buildElf386RelChain(void)1382 static void __NEAR__ __FASTCALL__ buildElf386RelChain( void )
1383 {
1384   size_t i,_nitems;
1385   TWindow *w,*usd;
1386   BGLOBAL handle = elfcache;
1387   __filesize_t fp;
1388   usd = twUsedWin();
1389   if(!(CurrElfChain = la_Build(0,sizeof(Elf_Reloc),MemOutBox))) return;
1390   w = CrtDlgWndnls(SYSTEM_BUSY,49,1);
1391   twUseWin(w);
1392   twGotoXY(1,1);
1393   twPutS(BUILD_REFS);
1394   twUseWin(usd);
1395   fp = bioTell(handle);
1396   if(IsSectionsPresent) /* Section headers are present */
1397   {
1398     bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff)),SEEKF_START);
1399     _nitems = ELF_HALF(ELF_EHDR(elf,e_shnum));
1400     for(i = 0;i < _nitems;i++)
1401     {
1402       ElfXX_External_Shdr shdr;
1403       __filesize_t fp;
1404       if(IsKbdTerminate() || bioEOF(handle)) break;
1405       fp=bioTell(handle);
1406       bioReadBuffer(handle,&shdr,sizeof(shdr));
1407 //      bioSeek(handle,fp+ELF_SHDR_SIZE(),SEEKF_START);
1408       bioSeek(handle,fp+ELF_HALF(ELF_EHDR(elf, e_shentsize)),SEEKF_START);
1409       switch(ELF_WORD(ELF_SHDR(shdr,sh_type)))
1410       {
1411         case SHT_REL: __elfReadRelSection(ELF_OFF(ELF_SHDR(shdr,sh_offset)),
1412                			          ELF_XWORD(ELF_SHDR(shdr,sh_size)),
1413             			          ELF_WORD(ELF_SHDR(shdr,sh_link)),
1414             			          ELF_WORD(ELF_SHDR(shdr,sh_info)),
1415             			          ELF_XWORD(ELF_SHDR(shdr,sh_entsize)));
1416                       break;
1417         case SHT_RELA: __elfReadRelaSection(ELF_OFF(ELF_SHDR(shdr,sh_offset)),
1418             				    ELF_XWORD(ELF_SHDR(shdr,sh_size)),
1419             				    ELF_WORD(ELF_SHDR(shdr,sh_link)),
1420             			            ELF_WORD(ELF_SHDR(shdr,sh_info)),
1421             			            ELF_XWORD(ELF_SHDR(shdr,sh_entsize)));
1422                       break;
1423         default: break;
1424      }
1425     }
1426   }
1427   else if(ELF_HALF(ELF_EHDR(elf,e_type)) != ET_REL)
1428   {
1429     /* If section headers are lost then information can be taken
1430        from program headers
1431     */
1432     __filesize_t dyn_ptr,dynptr,link,type;
1433     unsigned tsize,nitems;
1434     dynptr = findPHEntry(PT_DYNAMIC,&nitems);
1435     link = elfVA2PA(findPHDynEntry(DT_SYMTAB,dynptr,nitems));
1436     if(dynptr)
1437     {
1438       dyn_ptr = elfVA2PA(findPHDynEntry(DT_RELA,dynptr,nitems));
1439       if(dyn_ptr)
1440       {
1441         tsize = findPHDynEntry(DT_RELASZ,dynptr,nitems);
1442 	__elfReadRelaSection(dyn_ptr,
1443             		     tsize,
1444             		     link,
1445             		     0,/* only executable can lose sections */
1446             		     sizeof(Elf386_External_Rela));
1447       }
1448       dyn_ptr = elfVA2PA(findPHDynEntry(DT_REL,dynptr,nitems));
1449       if(dyn_ptr)
1450       {
1451         tsize = findPHDynEntry(DT_RELSZ,dynptr,nitems);
1452 	__elfReadRelSection(dyn_ptr,
1453         		    tsize,
1454             		    link,
1455             		    0,/* only executable can lose sections */
1456             		    sizeof(Elf386_External_Rel));
1457       }
1458       dyn_ptr = elfVA2PA(findPHDynEntry(DT_JMPREL,dynptr,nitems));
1459       if(dyn_ptr)
1460       {
1461         tsize = findPHDynEntry(DT_PLTRELSZ,dynptr,nitems);
1462         type = findPHDynEntry(DT_PLTREL,dynptr,nitems);
1463         if(type == DT_REL)
1464 	__elfReadRelSection(dyn_ptr,
1465         		    tsize,
1466             		    link,
1467             		    0,/* only executable can lose sections */
1468             		    sizeof(Elf386_External_Rel));
1469         else
1470 	__elfReadRelaSection(dyn_ptr,
1471         	 	     tsize,
1472             		     link,
1473             		     0,/* only executable can lose sections */
1474             		     sizeof(Elf386_External_Rel));
1475       }
1476     }
1477   }
1478   la_Sort(CurrElfChain,compare_elf_reloc);
1479   bioSeek(handle,fp,SEEKF_START);
1480   CloseWnd(w);
1481   return;
1482 }
1483 
__found_ElfRel(__filesize_t offset)1484 static Elf_Reloc __HUGE__ * __NEAR__ __FASTCALL__ __found_ElfRel(__filesize_t offset)
1485 {
1486   Elf_Reloc key;
1487   if(!CurrElfChain) buildElf386RelChain();
1488   key.offset = offset;
1489   return la_Find(CurrElfChain,&key,compare_elf_reloc);
1490 }
1491 
__readRelocName(Elf_Reloc __HUGE__ * erl,char * buff,size_t cbBuff)1492 static tBool __NEAR__ __FASTCALL__ __readRelocName(Elf_Reloc __HUGE__ *erl, char *buff, size_t cbBuff)
1493 {
1494   __filesize_t r_sym;
1495   ElfXX_External_Shdr shdr;
1496   ElfXX_External_Sym sym;
1497   BGLOBAL handle = elfcache;
1498   __filesize_t fp;
1499   tBool ret = True;
1500   r_sym = is_64bit?ELF64_R_SYM(erl->info):ELF32_R_SYM(erl->info);
1501   fp = bioTell(handle);
1502   if(IsSectionsPresent) /* Section headers are present */
1503   {
1504 //     bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+erl->sh_idx*ELF_SHDR_SIZE(),SEEKF_START);
1505      bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+erl->sh_idx*ELF_HALF(ELF_EHDR(elf, e_shentsize)),SEEKF_START);
1506 
1507      bioReadBuffer(handle,&shdr,sizeof(shdr));
1508      bioSeek(handle,ELF_OFF(ELF_SHDR(shdr,sh_offset)),SEEKF_START);
1509      /* Minor integrity test */
1510      ret = ELF_WORD(ELF_SHDR(shdr,sh_type)) == SHT_SYMTAB || ELF_WORD(ELF_SHDR(shdr,sh_type)) == SHT_DYNSYM;
1511   }
1512   else bioSeek(handle,erl->sh_idx,SEEKF_START);
1513   if(ret)
1514   {
1515     /* We assume that dynsym and symtab are equal */
1516     unsigned old_active;
1517     old_active = active_shtbl;
1518     if(IsSectionsPresent) active_shtbl = ELF_WORD(ELF_SHDR(shdr,sh_link));
1519     else
1520     {
1521       __filesize_t dynptr;
1522       unsigned nitems;
1523       dynptr = findPHEntry(PT_DYNAMIC,&nitems);
1524       active_shtbl = elfVA2PA(findPHDynEntry(DT_STRTAB,dynptr,nitems));
1525     }
1526     bioSeek(handle,r_sym*ELF_SYM_SIZE(),SEEKF_CUR);
1527     bioReadBuffer(handle,&sym,sizeof(sym));
1528     elf386_readnametableex(ELF_WORD(ELF_SYM(sym,st_name)),buff,cbBuff);
1529     buff[cbBuff-1] = '\0';
1530     active_shtbl = old_active;
1531     if(!buff[0])
1532     {
1533       /* reading name failed - try read at least section name */
1534       if(IsSectionsPresent)
1535       {
1536        if(ELF_ST_TYPE(ELF_SYM(sym,st_info[0])) == STT_SECTION &&
1537           ELF_HALF(ELF_SYM(sym,st_shndx)) &&
1538           ELF_IS_SECTION_PHYSICAL(ELF_HALF(ELF_SYM(sym,st_shndx))))
1539        {
1540 //         bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_HALF(ELF_SYM(sym,st_shndx))*ELF_SHDR_SIZE(),SEEKF_START);
1541          bioSeek(handle,ELF_OFF(ELF_EHDR(elf,e_shoff))+ELF_HALF(ELF_SYM(sym,st_shndx))*ELF_HALF(ELF_EHDR(elf, e_shentsize)),SEEKF_START);
1542          bioReadBuffer(handle,&shdr,sizeof(shdr));
1543          if(!FindPubName(buff, cbBuff, ELF_OFF(ELF_SHDR(shdr,sh_offset))+erl->addend))
1544                       elf386_readnametable(ELF_WORD(ELF_SHDR(shdr,sh_name)),buff,cbBuff);
1545        }
1546       }
1547       if(!buff[0]) strcpy(buff,"?noname");
1548     }
1549   }
1550   bioSeek(handle,fp,SEEKF_START);
1551   return ret;
1552 }
1553 
BuildReferStrElf_arm(char * str,Elf_Reloc __HUGE__ * erl,int flags,unsigned codelen,__filesize_t defval)1554 static unsigned long __NEAR__ __FASTCALL__ BuildReferStrElf_arm(char *str,
1555 							Elf_Reloc __HUGE__ *erl,
1556 							int flags,unsigned codelen,
1557 							__filesize_t defval)
1558 {
1559   unsigned long retval = RAPREF_DONE;
1560   tUInt32 r_type;
1561   tBool ret=False, use_addend = False;
1562   char buff[300];
1563   UNUSED(codelen);
1564   UNUSED(defval);
1565   r_type = ELF32_R_TYPE(erl->info);
1566   buff[0] = 0;
1567   switch(r_type)
1568   {
1569     default:
1570     case R_ARM_RELATIVE: /* BVA + addendum */
1571     case R_ARM_NONE: /* nothing to do */
1572     case R_ARM_COPY: /* nothing to do */
1573                    retval = RAPREF_NONE;
1574                    break;
1575     case R_ARM_THM_ABS5:
1576     case R_ARM_ABS8:
1577     case R_ARM_ABS12:
1578     case R_ARM_ABS16:
1579     case R_ARM_ABS32:  /* symbol + addendum */
1580                    ret = __readRelocName(erl, buff, sizeof(buff));
1581                    if(buff[0] && ret)
1582                    {
1583 		     strcat(str,buff);
1584 		     use_addend = True;
1585 		   }
1586                    else retval = RAPREF_NONE;
1587 		   break;
1588     case R_ARM_THM_PC8:
1589     case R_ARM_THM_PC12:
1590     case R_ARM_PC24: /* symbol + addendum - this */
1591                    ret = __readRelocName(erl, buff, sizeof(buff));
1592                    if(buff[0] && ret)
1593                    {
1594 		     strcat(str,buff);
1595 		     /* strcat(str,"-.here"); <- it's commented for readability */
1596 		     use_addend = True;
1597 		   }
1598                    else retval = RAPREF_NONE;
1599 		   break;
1600     case R_ARM_PLT32: /* PLT[offset] + addendum - this */
1601                    strcat(str,"PLT-");
1602                    strcat(str,Get8Digit(erl->offset));
1603 		   use_addend = True;
1604 		   break;
1605     case R_ARM_GLOB_DAT:  /* symbol */
1606     case R_ARM_JUMP_SLOT:  /* symbol */
1607                    ret = __readRelocName(erl, buff, sizeof(buff));
1608                    if(buff[0] && ret) strcat(str,buff);
1609 		   break;
1610     case R_ARM_GOTOFF32: /* symbol + addendum - GOT */
1611                    ret = __readRelocName(erl, buff, sizeof(buff));
1612                    if(buff[0] && ret)
1613                    {
1614   		     strcat(str,buff);
1615 		     strcat(str,"-GOT");
1616 		     use_addend = True;
1617 		   }
1618                    else retval = RAPREF_NONE;
1619 		   break;
1620   }
1621   if(erl->addend && use_addend && ret &&
1622      !(flags & APREF_TRY_LABEL)) /* <- it for readability */
1623   {
1624     strcat(str,"+");
1625     strcat(str,Get8Digit(erl->addend));
1626   }
1627   return retval;
1628 }
1629 
BuildReferStrElf_i386(char * str,Elf_Reloc __HUGE__ * erl,int flags,unsigned codelen,__filesize_t defval)1630 static unsigned long __NEAR__ __FASTCALL__ BuildReferStrElf_i386(char *str,
1631 							Elf_Reloc __HUGE__ *erl,
1632 							int flags,unsigned codelen,
1633 							__filesize_t defval)
1634 {
1635   unsigned long retval = RAPREF_DONE;
1636   tUInt32 r_type;
1637   tBool ret=False, use_addend = False;
1638   char buff[300];
1639   UNUSED(codelen);
1640   UNUSED(defval);
1641   r_type = ELF32_R_TYPE(erl->info);
1642   buff[0] = 0;
1643   switch(r_type)
1644   {
1645     default:
1646     case R_386_RELATIVE: /* BVA + addend. Ignoring it is best choice */
1647     case R_386_NONE: /* nothing to do */
1648     case R_386_COPY: /* nothing to do */
1649                    retval = RAPREF_NONE;
1650                    break;
1651     case R_386_GNU_8:
1652     case R_386_GNU_16:
1653     case R_386_32:  /* symbol + addendum */
1654                    ret = __readRelocName(erl, buff, sizeof(buff));
1655                    if(buff[0] && ret)
1656                    {
1657 		     strcat(str,buff);
1658 		     use_addend = True;
1659 		   }
1660                    else retval = RAPREF_NONE;
1661 		   break;
1662     case R_386_GNU_PC8:
1663     case R_386_GNU_PC16:
1664     case R_386_PC32: /* symbol + addendum - this */
1665                    ret = __readRelocName(erl, buff, sizeof(buff));
1666                    if(buff[0] && ret)
1667                    {
1668 		     strcat(str,buff);
1669 		     /* strcat(str,"-.here"); <- it's commented for readability */
1670 		     use_addend = True;
1671 		   }
1672                    else retval = RAPREF_NONE;
1673 		   break;
1674     case R_386_GOT32: /* GOT[offset] + addendum - this */
1675                    strcat(str,"GOT-");
1676                    strcat(str,Get8Digit(erl->offset));
1677 		   use_addend = True;
1678 		   break;
1679     case R_386_PLT32: /* PLT[offset] + addendum - this */
1680                    strcat(str,"PLT-");
1681                    strcat(str,Get8Digit(erl->offset));
1682 		   use_addend = True;
1683 		   break;
1684     case R_386_GLOB_DAT:  /* symbol */
1685     case R_386_JMP_SLOT:  /* symbol */
1686                    ret = __readRelocName(erl, buff, sizeof(buff));
1687                    if(buff[0] && ret) strcat(str,buff);
1688 		   break;
1689     case R_386_GOTOFF: /* symbol + addendum - GOT */
1690                    ret = __readRelocName(erl, buff, sizeof(buff));
1691                    if(buff[0] && ret)
1692                    {
1693   		     strcat(str,buff);
1694 		     strcat(str,"-GOT");
1695 		     use_addend = True;
1696 		   }
1697                    else retval = RAPREF_NONE;
1698 		   break;
1699     case R_386_GOTPC: /* GOT + addendum - this */
1700 		   strcat(str,"GOT-.here");
1701 		   use_addend = True;
1702 		   break;
1703   }
1704   if(erl->addend && use_addend && ret &&
1705      !(flags & APREF_TRY_LABEL)) /* <- it for readability */
1706   {
1707     strcat(str,"+");
1708     strcat(str,Get8Digit(erl->addend));
1709   }
1710   return retval;
1711 }
1712 
BuildReferStrElf_x86_64(char * str,Elf_Reloc __HUGE__ * erl,int flags,unsigned codelen,__filesize_t defval)1713 static unsigned long __NEAR__ __FASTCALL__ BuildReferStrElf_x86_64(char *str,
1714 							Elf_Reloc __HUGE__ *erl,
1715 							int flags,unsigned codelen,
1716 							__filesize_t defval)
1717 {
1718   unsigned long retval = RAPREF_DONE;
1719   tUInt32 r_type;
1720   tBool ret=False, use_addend = False;
1721   char buff[300];
1722   UNUSED(codelen);
1723   UNUSED(defval);
1724   r_type = ELF32_R_TYPE(erl->info);
1725   buff[0] = 0;
1726   switch(r_type)
1727   {
1728     default:
1729     case R_X86_64_RELATIVE: /* BVA + addendum */
1730     case R_X86_64_NONE: /* nothing to do */
1731     case R_X86_64_COPY: /* nothing to do */
1732                    retval = RAPREF_NONE;
1733                    break;
1734     case R_X86_64_8:
1735     case R_X86_64_16:
1736     case R_X86_64_32:
1737     case R_X86_64_64:  /* symbol + addendum */
1738                    ret = __readRelocName(erl, buff, sizeof(buff));
1739                    if(buff[0] && ret)
1740                    {
1741 		     strcat(str,buff);
1742 		     use_addend = True;
1743 		   }
1744                    else retval = RAPREF_NONE;
1745 		   break;
1746     case R_X86_64_PC8:
1747     case R_X86_64_PC16:
1748     case R_X86_64_PC32:
1749     case R_X86_64_PC64: /* symbol + addendum - this */
1750                    ret = __readRelocName(erl, buff, sizeof(buff));
1751                    if(buff[0] && ret)
1752                    {
1753 		     strcat(str,buff);
1754 		     /* strcat(str,"-.here"); <- it's commented for readability */
1755 		     use_addend = True;
1756 		   }
1757                    else retval = RAPREF_NONE;
1758 		   break;
1759     case R_X86_64_GOT32:
1760                    strcat(str,"GOT-");
1761                    strcat(str,Get8Digit(erl->offset));
1762 		   use_addend = True;
1763 		   break;
1764     case R_X86_64_GOT64:
1765     case R_X86_64_GOTPC64:
1766     case R_X86_64_GOTPLT64: /* GOT[offset] + addendum - this */
1767                    strcat(str,"GOT-");
1768                    strcat(str,Get16Digit(erl->offset));
1769 		   use_addend = True;
1770 		   break;
1771     case R_X86_64_PLT32:
1772                    strcat(str,"PLT-");
1773                    strcat(str,Get8Digit(erl->offset));
1774 		   use_addend = True;
1775 		   break;
1776     case R_X86_64_PLTOFF64: /* PLT[offset] + addendum - this */
1777                    strcat(str,"PLT-");
1778                    strcat(str,Get16Digit(erl->offset));
1779 		   use_addend = True;
1780 		   break;
1781     case R_X86_64_GLOB_DAT:  /* symbol */
1782     case R_X86_64_JUMP_SLOT:  /* symbol */
1783                    ret = __readRelocName(erl, buff, sizeof(buff));
1784                    if(buff[0] && ret) strcat(str,buff);
1785 		   break;
1786     case R_X86_64_GOTOFF64: /* symbol + addendum - GOT */
1787                    ret = __readRelocName(erl, buff, sizeof(buff));
1788                    if(buff[0] && ret)
1789                    {
1790   		     strcat(str,buff);
1791 		     strcat(str,"-GOT");
1792 		     use_addend = True;
1793 		   }
1794                    else retval = RAPREF_NONE;
1795 		   break;
1796     case R_X86_64_GOTPCREL64: /* GOT + addendum - this */
1797 		   strcat(str,"GOT-.here");
1798 		   use_addend = True;
1799 		   break;
1800   }
1801   if(erl->addend && use_addend && ret &&
1802      !(flags & APREF_TRY_LABEL)) /* <- it for readability */
1803   {
1804     strcat(str,"+");
1805     strcat(str,Get8Digit(erl->addend));
1806   }
1807   return retval;
1808 }
1809 
BuildReferStrElf_ppc(char * str,Elf_Reloc __HUGE__ * erl,int flags,unsigned codelen,__filesize_t defval)1810 static unsigned long __NEAR__ __FASTCALL__ BuildReferStrElf_ppc(char *str,
1811 							Elf_Reloc __HUGE__ *erl,
1812 							int flags,unsigned codelen,
1813 							__filesize_t defval)
1814 {
1815   unsigned long retval = RAPREF_DONE;
1816   tUInt32 r_type;
1817   tBool ret=False, use_addend = False;
1818   char buff[300];
1819   UNUSED(codelen);
1820   UNUSED(defval);
1821   r_type = ELF32_R_TYPE(erl->info);
1822   buff[0] = 0;
1823   switch(r_type)
1824   {
1825     default:
1826     case R_PPC_RELATIVE: /* BVA + addendum */
1827     case R_PPC_NONE: /* nothing to do */
1828     case R_PPC_COPY: /* nothing to do */
1829                    retval = RAPREF_NONE;
1830                    break;
1831     case R_PPC_ADDR14:
1832     case R_PPC_ADDR14_BRTAKEN:
1833     case R_PPC_ADDR14_BRNTAKEN:
1834     case R_PPC_ADDR16:
1835     case R_PPC_ADDR16_LO:
1836     case R_PPC_ADDR16_HI:
1837     case R_PPC_ADDR16_HA:
1838     case R_PPC_ADDR24:
1839     case R_PPC_ADDR32:
1840     case R_PPC_UADDR32:
1841     case R_PPC64_ADDR64:
1842     case R_PPC64_UADDR64: /* symbol + addendum */
1843                    ret = __readRelocName(erl, buff, sizeof(buff));
1844                    if(buff[0] && ret)
1845                    {
1846 		     strcat(str,buff);
1847 		     use_addend = True;
1848 		   }
1849                    else retval = RAPREF_NONE;
1850 		   break;
1851     case R_PPC_REL14:
1852     case R_PPC_REL14_BRTAKEN:
1853     case R_PPC_REL14_BRNTAKEN:
1854     case R_PPC_REL16:
1855     case R_PPC_REL16_LO:
1856     case R_PPC_REL16_HI:
1857     case R_PPC_REL16_HA:
1858     case R_PPC_REL24:
1859     case R_PPC_REL32:
1860     case R_PPC64_REL64: /* symbol + addendum - this */
1861                    ret = __readRelocName(erl, buff, sizeof(buff));
1862                    if(buff[0] && ret)
1863                    {
1864 		     strcat(str,buff);
1865 		     /* strcat(str,"-.here"); <- it's commented for readability */
1866 		     use_addend = True;
1867 		   }
1868                    else retval = RAPREF_NONE;
1869 		   break;
1870     case R_PPC_GOT16_LO:
1871     case R_PPC_GOT16_HI:
1872     case R_PPC_GOT16_HA:
1873 		   strcat(str,"GOT-");
1874 		strcat(str,Get8Digit(erl->offset));
1875 		   use_addend = True;
1876 		   break;
1877     case R_PPC_PLT16_LO:
1878     case R_PPC_PLT16_HI:
1879     case R_PPC_PLT16_HA:
1880     case R_PPC_PLT32:
1881                    strcat(str,"PLT-");
1882                    strcat(str,Get8Digit(erl->offset));
1883 		   use_addend = True;
1884 		   break;
1885     case R_PPC64_PLT64: /* PLT[offset] + addendum - this */
1886                    strcat(str,"PLT-");
1887                    strcat(str,Get16Digit(erl->offset));
1888 		   use_addend = True;
1889 		   break;
1890     case R_PPC_GLOB_DAT:  /* symbol */
1891     case R_PPC_JMP_SLOT:  /* symbol */
1892                    ret = __readRelocName(erl, buff, sizeof(buff));
1893                    if(buff[0] && ret) strcat(str,buff);
1894 		   break;
1895   }
1896   if(erl->addend && use_addend && ret &&
1897      !(flags & APREF_TRY_LABEL)) /* <- it for readability */
1898   {
1899     strcat(str,"+");
1900     strcat(str,Get8Digit(erl->addend));
1901   }
1902   return retval;
1903 }
1904 
BuildReferStrElf(char * str,Elf_Reloc __HUGE__ * erl,int flags,unsigned codelen,__filesize_t defval)1905 static unsigned long __NEAR__ __FASTCALL__ BuildReferStrElf(char *str,
1906 							Elf_Reloc __HUGE__ *erl,
1907 							int flags,unsigned codelen,
1908 							__filesize_t defval)
1909 {
1910     switch(ELF_HALF(ELF_EHDR(elf,e_machine)))
1911     {
1912       default: return RAPREF_NONE;
1913       case EM_ARM: return BuildReferStrElf_arm(str,erl,flags,codelen,defval);
1914       case EM_386: return BuildReferStrElf_i386(str,erl,flags,codelen,defval);
1915       case EM_X86_64: return BuildReferStrElf_x86_64(str,erl,flags,codelen,defval);
1916       case EM_PPC:
1917       case EM_PPC64: return BuildReferStrElf_ppc(str,erl,flags,codelen,defval);
1918     }
1919 }
1920 
1921 #define S_INTERPRETER "Interpreter : "
1922 
displayELFdyninfo(__filesize_t f_off,unsigned nitems)1923 static void __NEAR__ __FASTCALL__ displayELFdyninfo(__filesize_t f_off,unsigned nitems)
1924 {
1925   ElfXX_External_Dyn dyntab;
1926   __filesize_t curroff,stroff;
1927   unsigned i;
1928   tBool is_add;
1929   memArray * obj;
1930   char stmp[80];
1931   stroff = 0;
1932   stroff = elfVA2PA(findPHDynEntry(DT_STRTAB,f_off,nitems));
1933   if(!stroff) { NotifyBox(" String information not found!",NULL); return; }
1934   bmSeek(f_off,SEEKF_START);
1935   if(!(obj = ma_Build(0,True))) return;
1936   strcpy(stmp,S_INTERPRETER);
1937   curroff = findPHEntry(PT_INTERP, &i);
1938   if(curroff) bmReadBufferEx(&stmp[sizeof(S_INTERPRETER) - 1],sizeof(stmp)-sizeof(S_INTERPRETER)-1,
1939                              curroff,SEEKF_START);
1940   if(!ma_AddString(obj,stmp,True)) goto dyn_end;
1941   bmSeek(f_off,SEEKF_START);
1942   for(i = 0;i < nitems;i++)
1943   {
1944     bmReadBufferEx(&dyntab,sizeof(dyntab),f_off,SEEKF_START);
1945     if(bmEOF()) break;
1946     f_off += ELF_EDYN_SIZE();
1947     is_add = True;
1948     switch(ELF_XWORD(ELF_EDYN(dyntab,d_tag)))
1949     {
1950       case DT_NULL: goto dyn_end;
1951       case DT_NEEDED:
1952                     {
1953                       strcpy(stmp,"Needed : ");
1954                       bmReadBufferEx(&stmp[strlen(stmp)],70,ELF_XWORD(ELF_EDYN(dyntab,d_un.d_ptr)) + stroff,SEEKF_START);
1955                     }
1956                     break;
1957       case DT_SONAME:
1958                     {
1959                       strcpy(stmp,"SO name: ");
1960                       bmReadBufferEx(&stmp[strlen(stmp)],70,ELF_XWORD(ELF_EDYN(dyntab,d_un.d_ptr)) + stroff,SEEKF_START);
1961                     }
1962                     break;
1963       case DT_RPATH:
1964                     {
1965                       strcpy(stmp,"LibPath: ");
1966                       bmReadBufferEx(&stmp[strlen(stmp)],70,ELF_XWORD(ELF_EDYN(dyntab,d_un.d_ptr)) + stroff,SEEKF_START);
1967                     }
1968                     break;
1969        default:     is_add = False; break;
1970     }
1971     if(is_add) if(!ma_AddString(obj,stmp,True)) break;
1972   }
1973   dyn_end:
1974   ma_Display(obj," Dynamic linking information ",LB_SORTABLE,-1);
1975   ma_Destroy(obj);
1976 }
1977 
ShowELFDynInfo(void)1978 static __filesize_t __FASTCALL__ ShowELFDynInfo( void )
1979 {
1980   __filesize_t dynptr,fpos;
1981   unsigned number;
1982   fpos = BMGetCurrFilePos();
1983   dynptr = findPHEntry(PT_DYNAMIC,&number);
1984   if(!dynptr) { NotifyBox(NOT_ENTRY," ELF dynamic linking information "); return fpos; }
1985   displayELFdyninfo(dynptr,number);
1986   BMSeek(fpos, SEEKF_START);
1987   return fpos;
1988 }
1989 
AppendELFRef(char * str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)1990 static unsigned long __FASTCALL__ AppendELFRef(char *str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)
1991 {
1992   char buff[400];
1993   unsigned long ret = RAPREF_NONE;
1994   Elf_Reloc __HUGE__ *erl;
1995   __filesize_t defval;
1996   switch(codelen) {
1997     default:
1998     case 1: defval = bmReadByteEx(ulShift, SEEKF_START); break;
1999     case 2: defval = bmReadWordEx(ulShift, SEEKF_START); break;
2000     case 4: defval = bmReadDWordEx(ulShift, SEEKF_START); break;
2001     case 8: defval = bmReadQWordEx(ulShift, SEEKF_START); break;
2002   }
2003   if(flags & APREF_TRY_PIC)
2004   {
2005        __filesize_t off_in_got = defval;
2006        __filesize_t dynptr, dyn_ent, got_off;
2007        unsigned nitems;
2008 /** @todo: If "program header" will be lost and will be present "section
2009     header" only then we should handle such situation propertly too */
2010        dynptr = findPHEntry(PT_DYNAMIC,&nitems);
2011        if(dynptr)
2012        {
2013          dyn_ent = findPHDynEntry(DT_PLTGOT,dynptr,nitems);
2014          if(dyn_ent)
2015          {
2016            got_off = elfVA2PA(dyn_ent);
2017            return AppendELFRef(str, got_off + off_in_got, flags & ~APREF_TRY_PIC, codelen, r_sh);
2018          }
2019        }
2020        return RAPREF_NONE;
2021   }
2022   if(!PubNames) elf_ReadPubNameList(bmbioHandle(),MemOutBox);
2023   if((erl = __found_ElfRel(ulShift)) != NULL)
2024   {
2025     ret = BuildReferStrElf(str,erl,flags,codelen,defval);
2026   }
2027   if(!ret && ELF_HALF(ELF_EHDR(elf,e_type))>ET_REL && codelen>=4)
2028   {
2029     if((erl = __found_ElfRel(elfVA2PA(bmReadDWordEx(ulShift,SEEKF_START)))) != NULL)
2030     {
2031       ret = BuildReferStrElf(str,erl,flags,codelen,defval);
2032     }
2033   }
2034   if(!ret)
2035   {
2036     memset(buff,-1,sizeof(buff));
2037     if(flags & APREF_TRY_LABEL)
2038     {
2039        if(FindPubName(buff,sizeof(buff),r_sh))
2040        {
2041          if(strlen(buff))
2042          {
2043            strcat(str,buff);
2044            if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
2045            ret = RAPREF_DONE;
2046          }
2047        }
2048     }
2049   }
2050   return flags & APREF_TRY_LABEL ? ret ? RAPREF_DONE : RAPREF_NONE : ret;
2051 }
2052 
IsELF32(void)2053 static tBool __FASTCALL__ IsELF32( void )
2054 {
2055   char id[4];
2056   bmReadBufferEx(id,sizeof(id),0,SEEKF_START);
2057   return IS_ELF(id);
2058 //  [0] == EI_MAG0 && id[1] == EI_MAG1 && id[2] == 'L' && id[3] == 'F';
2059 }
2060 
__elfReadSegments(linearArray ** to,tBool is_virt)2061 static void __FASTCALL__ __elfReadSegments(linearArray **to, tBool is_virt )
2062 {
2063  ElfXX_External_Phdr phdr;
2064  ElfXX_External_Shdr shdr;
2065  struct tag_elfVAMap vamap;
2066  __filesize_t fp;
2067  unsigned va_map_count;
2068  tBool test;
2069  size_t i;
2070    /* We'll try to build section headers first
2071       since they is used in calculations of objects.
2072       For translation of virtual address to physical and vise versa
2073       more preferred to use program headers. But they often are not presented
2074       and often is unordered by file offsets. */
2075    if(IsSectionsPresent) /* Section headers are present */
2076    {
2077      va_map_count = ELF_HALF(ELF_EHDR(elf,e_shnum));
2078      if(!(*to = la_Build(0,sizeof(struct tag_elfVAMap),MemOutBox)))
2079      {
2080        exit(EXIT_FAILURE);
2081      }
2082      bmSeek(ELF_OFF(ELF_EHDR(elf,e_shoff)),SEEKF_START);
2083      for(i = 0;i < va_map_count;i++)
2084      {
2085        __filesize_t flg,x_flags;
2086        fp = bmGetCurrFilePos();
2087        bmReadBuffer(&shdr,sizeof(shdr));
2088        bmSeek(fp+ELF_HALF(ELF_EHDR(elf,e_shentsize)),SEEKF_START);
2089        vamap.va = ELF_OFF(ELF_SHDR(shdr,sh_addr));
2090        vamap.size = ELF_XWORD(ELF_SHDR(shdr,sh_size));
2091        vamap.foff = ELF_OFF(ELF_SHDR(shdr,sh_offset));
2092        vamap.nameoff = ELF_WORD(ELF_SHDR(shdr,sh_name));
2093        flg = ELF_XWORD(ELF_SHDR(shdr,sh_flags));
2094        x_flags = 0;
2095        /* I think - it would be better to use for computation of virtual and
2096           physical addresses maps only that sections which occupy memory
2097           during execution. All other are rubbish for analyze */
2098        if((flg & SHF_ALLOC) == SHF_ALLOC)
2099        {
2100          x_flags |= PF_R; /* Ugle: means flags is not empty */
2101          if(flg & SHF_WRITE)     x_flags |= PF_W;
2102          if(flg & SHF_EXECINSTR) x_flags |= PF_X;
2103          vamap.flags = x_flags;
2104          test = is_virt ? elfVA2PA(vamap.va) != 0 : elfPA2VA(vamap.foff) != 0;
2105          if(!test)
2106          {
2107            if(!la_AddData(*to,&vamap,MemOutBox)) exit(EXIT_FAILURE);
2108            /** We must sort va_map after adding of each element because ELF section
2109                header has unsorted and nested elements */
2110            la_Sort(*to,is_virt ? vamap_comp_virt : vamap_comp_phys);
2111          }
2112        }
2113      }
2114    }
2115    else /* Try to build program headers map */
2116     if((va_map_count = ELF_HALF(ELF_EHDR(elf,e_phnum))) != 0) /* Program headers are present */
2117     {
2118       if(!(*to = la_Build(va_map_count,sizeof(struct tag_elfVAMap),MemOutBox)))
2119       {
2120         exit(EXIT_FAILURE);
2121       }
2122       bmSeek(ELF_OFF(ELF_EHDR(elf,e_phoff)),SEEKF_START);
2123       for(i = 0;i < va_map_count;i++)
2124       {
2125         fp = bmGetCurrFilePos();
2126         bmReadBuffer(&phdr,sizeof(phdr));
2127         bmSeek(fp+ELF_HALF(ELF_EHDR(elf,e_phentsize)),SEEKF_START);
2128         vamap.va = ELF_ADDR(ELF_PHDR(phdr,p_vaddr));
2129         vamap.size = max(ELF_OFF(ELF_PHDR(phdr,p_filesz)), ELF_OFF(ELF_PHDR(phdr,p_memsz)));
2130         vamap.foff = ELF_OFF(ELF_PHDR(phdr,p_offset));
2131         vamap.nameoff = ELF_WORD(ELF_PHDR(phdr,p_type)) & 0x000000FFUL ? ~ELF_WORD(ELF_PHDR(phdr,p_type)) : 0xFFFFFFFFUL;
2132         vamap.flags = ELF_WORD(ELF_PHDR(phdr,p_flags));
2133         test = is_virt ? elfVA2PA(vamap.va) != 0 : elfPA2VA(vamap.foff) != 0;
2134         if(!test)
2135         {
2136           if(!la_AddData(*to,&vamap,MemOutBox))
2137           {
2138             exit(EXIT_FAILURE);
2139           }
2140           /** We must sort va_map after adding of each element because ELF program
2141               header has unsorted and has nested elements */
2142           la_Sort(*to,is_virt ? vamap_comp_virt : vamap_comp_phys);
2143         }
2144       }
2145     }
2146 }
2147 
ELFinit(void)2148 static void __FASTCALL__ ELFinit( void )
2149 {
2150  BGLOBAL main_handle;
2151  __filesize_t fs;
2152  size_t i;
2153    PMRegLowMemCallBack(elfLowMemFunc);
2154    bmReadBufferEx(&elf,sizeof(ElfXX_External_Ehdr),0,SEEKF_START);
2155    is_msbf = ELF_EHDR(elf,e_ident[EI_DATA]) == ELFDATA2MSB;
2156    is_64bit = ELF_EHDR(elf,e_ident[EI_CLASS]) == ELFCLASS64;
2157    fs = bmGetFLength();
2158    IsSectionsPresent = ELF_HALF(ELF_EHDR(elf,e_shnum)) != 0 &&
2159                        ELF_OFF(ELF_EHDR(elf,e_shoff)) &&
2160                        ELF_OFF(ELF_EHDR(elf,e_shoff)) < fs &&
2161                        ELF_OFF(ELF_EHDR(elf,e_shoff)) +
2162                        ELF_HALF(ELF_EHDR(elf,e_shnum))*ELF_HALF(ELF_EHDR(elf,e_shentsize)) <= fs;
2163    __elfReadSegments(&va_map_virt,True);
2164    __elfReadSegments(&va_map_phys,False);
2165    /** Find min value of virtual address */
2166    if(va_map_virt)
2167    for(i = 0; i < va_map_virt->nItems;i++)
2168    {
2169      struct tag_elfVAMap __HUGE__ *evm;
2170      evm = &((struct tag_elfVAMap __HUGE__ *)va_map_virt->data)[i];
2171      if(evm->va < elf_min_va) elf_min_va = evm->va;
2172    }
2173    main_handle = bmbioHandle();
2174    if((namecache = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) namecache = main_handle;
2175    if((namecache2 = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) namecache2 = main_handle;
2176    if((elfcache = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) elfcache = main_handle;
2177    /** Computing symbol table entry */
2178    __elfSymPtr = findSHEntry(bmbioHandle(), SHT_SYMTAB, &__elfNumSymTab, &__elfSymShTbl, &__elfSymEntSize);
2179 }
2180 
ELFdestroy(void)2181 static void __FASTCALL__ ELFdestroy( void )
2182 {
2183    BGLOBAL main_handle;
2184    main_handle = bmbioHandle();
2185    if(namecache != &bNull && namecache != main_handle) bioClose(namecache);
2186    if(namecache2 != &bNull && namecache2 != main_handle) bioClose(namecache2);
2187    if(elfcache != &bNull && elfcache != main_handle) bioClose(elfcache);
2188    if(PubNames) { la_Destroy(PubNames); PubNames = 0; }
2189    if(CurrElfChain) { la_Destroy(CurrElfChain); CurrElfChain = 0; }
2190    PMUnregLowMemCallBack(elfLowMemFunc);
2191    la_Destroy(va_map_virt);
2192    la_Destroy(va_map_phys);
2193 }
2194 
ELFbitness(__filesize_t off)2195 static int __FASTCALL__ ELFbitness(__filesize_t off)
2196 {
2197   UNUSED(off);
2198   return is_64bit?DAB_USE64:DAB_USE32;
2199 }
2200 
ELFHelp(void)2201 static __filesize_t __FASTCALL__ ELFHelp( void )
2202 {
2203   hlpDisplay(10003);
2204   return BMGetCurrFilePos();
2205 }
2206 
ELFAddrResolv(char * addr,__filesize_t cfpos)2207 static tBool __FASTCALL__ ELFAddrResolv(char *addr,__filesize_t cfpos)
2208 {
2209  /* Since this function is used in references resolving of disassembler
2210     it must be seriously optimized for speed. */
2211   tBool bret = True;
2212   __filesize_t res;
2213   if(cfpos < ELF_EHDR_SIZE())
2214   {
2215     strcpy(addr,"ELFhdr:");
2216     strcpy(&addr[7],Get2Digit(cfpos));
2217   }
2218   else
2219     if((res=elfPA2VA(cfpos))!=0)
2220     {
2221       addr[0] = '.';
2222       strcpy(&addr[1],Get8Digit(res));
2223     }
2224     else bret = False;
2225   return bret;
2226 }
2227 
compare_pubnames(const void __HUGE__ * v1,const void __HUGE__ * v2)2228 static tCompare __FASTCALL__ compare_pubnames(const void __HUGE__ *v1,const void __HUGE__ *v2)
2229 {
2230   const struct PubName __HUGE__ *pnam1,__HUGE__ *pnam2;
2231   pnam1 = (const struct PubName __HUGE__ *)v1;
2232   pnam2 = (const struct PubName __HUGE__ *)v2;
2233   return __CmpLong__(pnam1->pa,pnam2->pa);
2234 }
2235 
FindPubName(char * buff,unsigned cb_buff,__filesize_t pa)2236 static tBool __NEAR__ __FASTCALL__ FindPubName(char *buff,unsigned cb_buff,__filesize_t pa)
2237 {
2238   struct PubName *ret,key;
2239   key.pa = pa;
2240   ret = la_Find(PubNames,&key,compare_pubnames);
2241   if(ret)
2242   {
2243     active_shtbl = ret->addinfo;
2244     elf386_readnametableex(ret->nameoff,buff,cb_buff);
2245     buff[cb_buff-1] = 0;
2246     return True;
2247   }
2248   return udnFindName(pa,buff,cb_buff);
2249 }
2250 
elf_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ * mem_out)(const char *))2251 static void __FASTCALL__ elf_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ *mem_out)(const char *))
2252 {
2253   __filesize_t fpos,fp,tableptr,pubname_shtbl;
2254   unsigned long i,number,ent_size,nitems;
2255   struct PubName epn;
2256   BGLOBAL b_cache;
2257   b_cache = handle;
2258   if(!(PubNames = la_Build(0,sizeof(struct PubName),mem_out))) return;
2259   fpos = bioTell(b_cache);
2260   tableptr = findSHEntry(b_cache, SHT_DYNSYM, &number, &pubname_shtbl, &ent_size);
2261   if(!tableptr)
2262   {
2263     tableptr = findPHPubSyms(&nitems, &ent_size, &pubname_shtbl);
2264     number = nitems;
2265   }
2266   if(!(PubNames = la_Build(0,sizeof(struct PubName),mem_out))) return;
2267   if(tableptr)
2268   {
2269     bioSeek(b_cache,tableptr,SEEK_SET);
2270     for(i = 0;i < number;i++)
2271     {
2272      ElfXX_External_Dyn pdyn;
2273      fp = bioTell(b_cache);
2274      bioReadBuffer(b_cache,&pdyn,sizeof(pdyn));
2275      if(bioEOF(b_cache)) break;
2276      bioSeek(b_cache,fp+ent_size,SEEKF_START);
2277      epn.nameoff = ELF_XWORD(ELF_EDYN(pdyn,d_tag));
2278      epn.pa = elfVA2PA(ELF_XWORD(ELF_EDYN(pdyn,d_un.d_val)));
2279      epn.addinfo = pubname_shtbl;
2280      epn.attr = ELF_ST_INFO(STB_GLOBAL,STT_NOTYPE);
2281      if(!la_AddData(PubNames,&epn,mem_out)) break;
2282     }
2283   }
2284   /** If present symbolic information we must read it */
2285 
2286   if(__elfNumSymTab)
2287   {
2288     bioSeek(handle,__elfSymPtr,SEEK_SET);
2289     for(i = 0;i < __elfNumSymTab;i++)
2290     {
2291       ElfXX_External_Sym sym;
2292       fp = bioTell(handle);
2293       bioReadBuffer(handle,&sym,sizeof(sym));
2294       if(bioEOF(handle) || IsKbdTerminate()) break;
2295       bioSeek(handle,fp+__elfSymEntSize,SEEKF_START);
2296       if(ELF_IS_SECTION_PHYSICAL(ELF_HALF(ELF_SYM(sym,st_shndx))) &&
2297          ELF_ST_TYPE(ELF_SYM(sym,st_info[0])) != STT_SECTION)
2298       {
2299         epn.pa = __calcSymEntry(handle,i,False);
2300         epn.nameoff = ELF_WORD(ELF_SYM(sym,st_name));
2301         epn.addinfo = __elfSymShTbl;
2302         epn.attr = ELF_SYM(sym,st_info[0]);
2303         if(!la_AddData(PubNames,&epn,MemOutBox)) break;
2304       }
2305     }
2306   }
2307   la_Sort(PubNames,compare_pubnames);
2308   bioSeek(b_cache,fpos,SEEK_SET);
2309 }
2310 
elf_ReadPubName(BGLOBAL b_cache,const struct PubName * it,char * buff,unsigned cb_buff)2311 static void __FASTCALL__ elf_ReadPubName(BGLOBAL b_cache,const struct PubName *it,
2312                             char *buff,unsigned cb_buff)
2313 {
2314    UNUSED(b_cache);
2315    active_shtbl = it->addinfo;
2316    elf386_readnametableex(it->nameoff,buff,cb_buff);
2317 }
2318 
elfGetPubSym(char * str,unsigned cb_str,unsigned * func_class,__filesize_t pa,tBool as_prev)2319 static __filesize_t __FASTCALL__ elfGetPubSym(char *str,unsigned cb_str,unsigned *func_class,
2320                            __filesize_t pa,tBool as_prev)
2321 {
2322    return fmtGetPubSym(elfcache,str,cb_str,func_class,pa,as_prev,
2323                        elf_ReadPubNameList,
2324                        elf_ReadPubName);
2325 }
2326 
elfGetObjAttr(__filesize_t pa,char * name,unsigned cb_name,__filesize_t * start,__filesize_t * end,int * _class,int * bitness)2327 static unsigned __FASTCALL__ elfGetObjAttr(__filesize_t pa,char *name,unsigned cb_name,
2328                        __filesize_t *start,__filesize_t *end,int *_class,int *bitness)
2329 {
2330   unsigned i,ret;
2331   struct tag_elfVAMap *evam;
2332   *start = 0;
2333   *end = bmGetFLength();
2334   *_class = OC_NOOBJECT;
2335   *bitness = ELFbitness(pa);
2336   name[0] = 0;
2337   ret = 0;
2338   evam = va_map_phys->data;
2339   for(i = 0;i < va_map_phys->nItems;i++)
2340   {
2341     if(!(evam[i].foff && evam[i].size)) continue;
2342     if(pa >= *start && pa < evam[i].foff)
2343     {
2344       /** means between two objects */
2345       *end = evam[i].foff;
2346       ret = 0;
2347       break;
2348     }
2349     if(pa >= evam[i].foff &&
2350        pa < evam[i].foff + evam[i].size)
2351     {
2352       *start = evam[i].foff;
2353       *end = *start + evam[i].size;
2354       if(evam[i].flags)
2355       {
2356         if(evam[i].flags & PF_X) *_class = OC_CODE;
2357         else                     *_class = OC_DATA;
2358       }
2359       else  *_class = OC_NOOBJECT;
2360       elf386_readnametable(evam[i].nameoff,name,cb_name);
2361       ret = i+1;
2362       break;
2363     }
2364     *start = evam[i].foff + evam[i].size;
2365   }
2366   return ret;
2367 }
2368 
ELFplatform(void)2369 static int __FASTCALL__ ELFplatform( void ) {
2370     unsigned id;
2371     elf_machine(ELF_HALF(ELF_EHDR(elf,e_machine)),&id);
2372     return id;
2373 }
2374 
ELFendian(__filesize_t off)2375 static int __FASTCALL__ ELFendian(__filesize_t off) {
2376  UNUSED(off);
2377  return is_msbf?DAE_BIG:DAE_LITTLE;
2378 }
2379 
2380 REGISTRY_BIN elf386Table =
2381 {
2382   "ELF (Executable and Linking Format)",
2383   { "ELFhlp", "DynInf", "DynSec", NULL, NULL, NULL, "SymTab", NULL, "SecHdr", "PrgDef" },
2384   { ELFHelp, ShowELFDynInfo, ShowELFDynSec, NULL, NULL, NULL, ShowELFSymTab, NULL, ShowSecHdrElf, ShowPrgHdrElf },
2385   IsELF32, ELFinit, ELFdestroy,
2386   ShowELFHeader,
2387   AppendELFRef,
2388   fmtSetState,
2389   ELFplatform,
2390   ELFbitness,
2391   ELFendian,
2392   ELFAddrResolv,
2393   elfVA2PA,
2394   elfPA2VA,
2395   elfGetPubSym,
2396   elfGetObjAttr,
2397   NULL,
2398   NULL
2399 };
2400