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