added support for parsing relocation entries and procedure_linkage_table
[dyninst.git] / pdutil / h / Object-elf.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * Object-elf32.h: ELF-32 object files.
44 ************************************************************************/
45
46
47 #if !defined(_Object_elf32_h_)
48 #define _Object_elf32_h_
49
50
51
52 /************************************************************************
53  * header files.
54 ************************************************************************/
55
56 #include <util/h/DictionaryLite.h>
57 #include <util/h/String.h>
58 #include <util/h/Symbol.h>
59 #include <util/h/Types.h>
60 #include <util/h/Vector.h>
61 #include <libelf.h>
62
63 extern "C" {
64 #include <libelf.h>
65 #include <fcntl.h>
66 #include <stdlib.h>
67 #include <unistd.h>
68
69 #include <sys/types.h>
70 #include <sys/mman.h>
71 #include <sys/stat.h>
72 }
73
74 /***
75    The standard symbol table in an elf file is the .symtab section. This section does
76    not have information to find the module to which a global symbol belongs, so we must
77    also read the .stab section to get this info.
78 ***/
79
80 // Declarations for the .stab section.
81 // These are not declared in any system header files, so we must provide our own
82 // declarations. The declarations below were taken from:
83 //       SPARCWorks 3.0.x Debugger Interface, July 1994/
84
85 struct stab_entry { // an entry in the stab section
86   unsigned long name;  // stabstr table index for this symbol
87   unsigned char type; // type of this symbol
88   unsigned char other; 
89   unsigned short desc; 
90   unsigned long val; // value of this symbol -- usually zero. The real value must
91                      // be obtained from the symtab section
92 };
93
94 // Types 
95 #define N_UNDF  0x00 /* start of object file */
96 #define N_GSYM  0x20 /* global symbol */
97 #define N_FUN   0x24 /* function or procedure */
98 #define N_STSYM 0x26 /* initialized static symbol */
99 #define N_LCSYM 0x28 /* unitialized static symbol */
100 #define N_ROSYM 0x2c /* read-only static symbol */
101 #define N_ENDM  0x62 /* end module */
102 #define N_SO    0x64 /* source directory and file */
103 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
104
105 // Language code -- the desc field in a N_SO entry is a language code
106 #define N_SO_AS      1 /* assembler source */
107 #define N_SO_C       2 /* K & R C source */
108 #define N_SO_ANSI_C  3 /* ANSI C source */
109 #define N_SO_CC      4 /* C++ source */
110 #define N_SO_FORTRAN 5 /* fortran source */
111 #define N_SO_PASCAL  6 /* Pascal source */
112
113 // Symbol descriptors
114 // The format of a name is "<name>:<symbol descriptor><rest of name>
115 // The following are the descriptors of interest
116 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
117 #define SD_PROTOTYPE 'P'  /* function prototypes */
118 #define SD_GLOBAL_VAR 'G' /* global variable */
119
120 // end of stab declarations
121
122 \f
123
124
125 /************************************************************************
126  * class Object
127 ************************************************************************/
128
129 class Object : public AObject {
130 public:
131              Object (const string, void (*)(const char *) = log_msg);
132              Object (const string, u_int baseAddr, 
133                      void (*)(const char *) = log_msg);
134              Object (const Object &);
135     virtual ~Object ();
136
137     const Object& operator= (const Object &);
138
139     bool     needs_function_binding() const {return (plt_addr_  > 0);} 
140     bool     get_func_binding_table(vector<relocationEntry> &fbt) const;
141
142 private:
143     static
144     void    log_elferror (void (*)(const char *), const char *);
145
146     bool    EEL ; //set to true if EEL rewritten
147     //added char *ptr, to deal with EEL rewritten software
148     //
149     bool      loaded_elf (int, char *, bool &, Elf* &, Elf32_Ehdr* &, 
150                           Elf32_Phdr* &, unsigned &, unsigned &, Elf_Scn* &, 
151                           Elf_Scn* &, Elf_Scn* &, Elf_Scn* &,
152                           Elf_Scn*& rel_plt_scnp, Elf_Scn*& plt_scnp, 
153                           Elf_Scn*& got_scnp,  Elf_Scn*& dynsym_scnp,
154                           Elf_Scn*& dynstr_scnp);
155     bool      loaded_elf_obj (int, bool &, Elf* &, Elf32_Ehdr* &,Elf32_Phdr* &,
156                               unsigned &, unsigned &, Elf_Scn* &, Elf_Scn*&,
157                               Elf_Scn*& rel_plt_scnp, Elf_Scn*& plt_scnp, 
158                               Elf_Scn*& got_scnp,  Elf_Scn*& dynsym_scnp,
159                               Elf_Scn*& dynstr_scnp);
160     void     load_object ();
161     void     load_shared_object ();
162
163     // initialize relocation_table_ from .rel.plt or .rela.plt section entryies 
164     bool     get_relocation_entries(Elf_Scn*& rel_plt_scnp,
165                         Elf_Scn*& dynsymscnp, Elf_Scn*& dynstrcnp);
166
167     // elf-specific stuff from dynamic executables and shared objects
168     Address     plt_addr_;      // address of _PROCEDURE_LINKAGE_TABLE_ 
169     u_int       plt_size_;
170     u_int       plt_entry_size_;
171     Address     got_addr_;      // address of _GLOBAL_OFFSET_TABLE_
172     Address     rel_plt_addr_;  // address of .rela.plt or .rel.plt section 
173     u_int       rel_plt_size_;
174     u_int       rel_plt_entry_size_;
175     Address     dyn_sym_addr_;  // address of .dynsym section
176     Address     dyn_str_addr_;  // address of .dynstr section
177
178     // for sparc-solaris this is a table of PLT entry addr, function_name
179     // for x86-solaris this is a table of GOT entry addr, function_name
180     // on sparc-solaris the runtime linker modifies the PLT entry when it
181     // binds a function, on X86 the PLT entry is not modified, but it uses
182     // an indirect jump to a GOT entry that is modified when the function 
183     // is bound....is this correct???? or should it be <PLTentry_addr, name> 
184     // for both?
185     vector<relocationEntry> relocation_table_;
186 };
187
188 inline
189 Object::~Object() {
190 }
191
192 inline
193 const Object&
194 Object::operator=(const Object& obj) {
195
196     (void) AObject::operator=(obj);
197
198     plt_addr_ = obj.plt_addr_;
199     plt_size_ = obj.plt_size_;
200     plt_entry_size_ = obj.plt_entry_size_;
201     got_addr_ = obj.got_addr_;
202     rel_plt_addr_ = obj.rel_plt_addr_;
203     rel_plt_size_ = obj.rel_plt_size_;
204     rel_plt_entry_size_ = obj.rel_plt_entry_size_;
205     dyn_sym_addr_ = obj.dyn_sym_addr_;
206     dyn_str_addr_ = obj.dyn_str_addr_;
207     relocation_table_  = obj.relocation_table_;
208     return *this;
209 }
210
211 inline void Object::log_elferror(void (*pfunc)(const char *), const char* msg) {
212     const char* err = elf_errmsg(elf_errno());
213     log_printf(pfunc, "%s: %s\n", msg, err ? err : "(bad elf error)");
214 }
215
216
217
218 //EEL
219 //
220 #define EXTRA_SPACE 8     //added some EXTRA_SPACE space, such that,
221                        // we won't look for functions in the data space
222
223
224 // Added one extra parameter 'char *ptr', for EEL rewritten software
225 // code_ptr_, code_offset_, code_len_ is calculated in this function
226 // For more detail , see comments with the word 'EEL'
227 //
228 inline
229 bool
230 Object::loaded_elf(int fd, char *ptr, bool& did_elf, Elf*& elfp, 
231     Elf32_Ehdr*& ehdrp,
232     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
233     Elf_Scn*& symscnp, Elf_Scn*& strscnp, Elf_Scn*& stabscnp, 
234     Elf_Scn*& stabstrscnp, Elf_Scn*& rel_plt_scnp, Elf_Scn*& plt_scnp, 
235     Elf_Scn*& got_scnp,  Elf_Scn*& dynsym_scnp, Elf_Scn*& dynstr_scnp) {
236
237     elf_version(EV_CURRENT);
238     elf_errno();
239
240     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
241         || (elf_kind(elfp) != ELF_K_ELF)) {
242         log_elferror(err_func_, "opening file");
243         return false;
244     }
245     did_elf = true;
246
247     if (((ehdrp = elf32_getehdr(elfp)) == 0)
248         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
249         || (ehdrp->e_type != ET_EXEC)
250         || (ehdrp->e_phoff == 0)
251         || (ehdrp->e_shoff == 0)
252         || (ehdrp->e_phnum == 0)
253         || (ehdrp->e_shnum == 0)) {
254         log_elferror(err_func_, "2: loading eheader");
255         return false;
256     }
257
258     if ((phdrp = elf32_getphdr(elfp)) == 0) {
259         log_elferror(err_func_, "loading pheader");
260         return false;
261     }
262
263     Elf_Scn*    shstrscnp  = 0;
264     Elf32_Shdr* shstrshdrp = 0;
265     Elf_Data*   shstrdatap = 0;
266     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
267         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
268         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
269         log_elferror(err_func_, "loading header section");
270         return false;
271     }
272
273     const char* shnames = (const char *) shstrdatap->d_buf;
274     Elf_Scn*    scnp    = 0;
275     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
276         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
277         if (!shdrp) {
278             log_elferror(err_func_, "scanning sections");
279             return false;
280         }
281
282         const char* EDITED_TEXT_NAME   = ".edited_text";
283         const char* TEXT_NAME   = ".text";
284         const char* BSS_NAME    = ".bss";
285         const char* SYMTAB_NAME = ".symtab";
286         const char* STRTAB_NAME = ".strtab";
287         const char* STAB_NAME   = ".stab";
288         const char* STABSTR_NAME= ".stabstr";
289
290         // sections from dynamic executables and shared objects
291         const char* PLT_NAME = ".plt";
292         const char* REL_PLT_NAME = ".rela.plt";    // sparc-solaris
293         const char* REL_PLT_NAME2 = ".rel.plt";    // x86-solaris
294         const char* GOT_NAME = ".got";     
295         const char* DYNSYM_NAME = ".dynsym";       
296         const char* DYNSTR_NAME = ".dynstr";       
297
298         const char* name        = (const char *) &shnames[shdrp->sh_name];
299
300         if (strcmp(name, EDITED_TEXT_NAME) == 0) {
301                 // EEL rewriten executable
302                 printf("This is an EEL rewritten executable \n") ;
303                 EEL = true ;
304                 txtaddr = shdrp->sh_addr;
305                 code_ptr_ = (Word *) ((void*)&ptr[shdrp->sh_offset-EXTRA_SPACE]);
306                 code_off_ = (Address) shdrp->sh_addr -EXTRA_SPACE ;
307                 code_len_ = ((unsigned) shdrp->sh_size + EXTRA_SPACE) / sizeof(Word);
308         }
309         if (strcmp(name, TEXT_NAME) == 0) {
310             txtaddr = shdrp->sh_addr;
311         }
312         else if (strcmp(name, BSS_NAME) == 0) {
313             bssaddr = shdrp->sh_addr;
314         }
315         else if (strcmp(name, SYMTAB_NAME) == 0) {
316             symscnp = scnp;
317         }
318         else if (strcmp(name, STRTAB_NAME) == 0) {
319             strscnp = scnp;
320         }
321         else if (strcmp(name, STAB_NAME) == 0) {
322             stabscnp = scnp;
323         }
324         else if (strcmp(name, STABSTR_NAME) == 0) {
325             stabstrscnp = scnp;
326         }
327         else if ((strcmp(name, REL_PLT_NAME) == 0) 
328                 || (strcmp(name, REL_PLT_NAME2) == 0)) {
329              rel_plt_scnp = scnp;
330              rel_plt_addr_ = shdrp->sh_addr;
331              rel_plt_size_ = shdrp->sh_size;
332              rel_plt_entry_size_ = shdrp->sh_entsize;
333         }
334         else if (strcmp(name, PLT_NAME) == 0) {
335             plt_scnp = scnp;
336             plt_addr_ = shdrp->sh_addr;
337             plt_size_ = shdrp->sh_size;
338             plt_entry_size_ = shdrp->sh_entsize;
339         }
340         else if (strcmp(name, GOT_NAME) == 0) {
341             got_scnp = scnp;
342             got_addr_ = shdrp->sh_addr;
343         }
344         else if (strcmp(name, DYNSYM_NAME) == 0) {
345             dynsym_scnp = scnp;
346             dyn_sym_addr_ = shdrp->sh_addr;
347         }
348         else if (strcmp(name, DYNSTR_NAME) == 0) {
349             dynstr_scnp = scnp;
350             dyn_str_addr_ = shdrp->sh_addr;
351         }
352
353     }
354     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
355         log_elferror(err_func_, "no text/bss/symbol/string section");
356         return false;
357     }
358
359     return true;
360 }
361
362
363 inline
364 bool
365 Object::loaded_elf_obj(int fd, bool& did_elf, Elf*& elfp, Elf32_Ehdr*& ehdrp,
366     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
367     Elf_Scn*& symscnp, Elf_Scn*& strscnp, Elf_Scn*& rel_plt_scnp, 
368     Elf_Scn*& plt_scnp, Elf_Scn*& got_scnp, Elf_Scn*& dynsym_scnp,
369     Elf_Scn*& dynstr_scnp) {
370
371     elf_version(EV_CURRENT);
372     elf_errno();
373
374     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
375         || (elf_kind(elfp) != ELF_K_ELF)) {
376         log_elferror(err_func_, "opening file");
377         return false;
378     }
379     did_elf = true;
380
381     if (((ehdrp = elf32_getehdr(elfp)) == 0)
382         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
383         || (ehdrp->e_type != ET_DYN)
384         || (ehdrp->e_phoff == 0)
385         || (ehdrp->e_shoff == 0)
386         || (ehdrp->e_phnum == 0)
387         || (ehdrp->e_shnum == 0)) {
388         log_elferror(err_func_, "loading eheader");
389         return false;
390     }
391
392     if ((phdrp = elf32_getphdr(elfp)) == 0) {
393         log_elferror(err_func_, "loading pheader");
394         return false;
395     }
396
397     Elf_Scn*    shstrscnp  = 0;
398     Elf32_Shdr* shstrshdrp = 0;
399     Elf_Data*   shstrdatap = 0;
400     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
401         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
402         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
403         log_elferror(err_func_, "loading header section");
404         return false;
405     }
406
407     const char* shnames = (const char *) shstrdatap->d_buf;
408     Elf_Scn*    scnp    = 0;
409     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
410         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
411         if (!shdrp) {
412             log_elferror(err_func_, "scanning sections");
413             return false;
414         }
415
416         const char* TEXT_NAME   = ".text";
417         const char* BSS_NAME    = ".bss";
418         const char* SYMTAB_NAME = ".symtab";
419         const char* STRTAB_NAME = ".strtab";
420
421         // sections from dynamic executables and shared objects
422         const char* PLT_NAME = ".plt";
423         const char* REL_PLT_NAME = ".rela.plt";    // sparc-solaris
424         const char* REL_PLT_NAME2 = ".rel.plt";    // x86-solaris
425         const char* GOT_NAME = ".got";     
426         const char* DYNSYM_NAME = ".dynsym";       
427         const char* DYNSTR_NAME = ".dynstr";       
428
429         const char* name        = (const char *) &shnames[shdrp->sh_name];
430
431         if (strcmp(name, TEXT_NAME) == 0) {
432             txtaddr = shdrp->sh_addr;
433         }
434         else if (strcmp(name, BSS_NAME) == 0) {
435             bssaddr = shdrp->sh_addr;
436         }
437         else if (strcmp(name, SYMTAB_NAME) == 0) {
438             symscnp = scnp;
439         }
440         else if (strcmp(name, STRTAB_NAME) == 0) {
441             strscnp = scnp;
442         }
443         else if ((strcmp(name, REL_PLT_NAME) == 0) 
444                 || (strcmp(name, REL_PLT_NAME2) == 0)) {
445              rel_plt_scnp = scnp;
446              rel_plt_addr_ = shdrp->sh_addr;
447              rel_plt_size_ = shdrp->sh_size;
448              rel_plt_entry_size_ = shdrp->sh_entsize;
449         }
450         else if (strcmp(name, PLT_NAME) == 0) {
451             plt_scnp = scnp;
452             plt_addr_ = shdrp->sh_addr;
453             plt_size_ = shdrp->sh_size;
454             plt_entry_size_ = shdrp->sh_entsize;
455         }
456         else if (strcmp(name, GOT_NAME) == 0) {
457             got_scnp = scnp;
458             got_addr_ = shdrp->sh_addr;
459         }
460         else if (strcmp(name, DYNSYM_NAME) == 0) {
461             dynsym_scnp = scnp;
462             dyn_sym_addr_ = shdrp->sh_addr;
463         }
464         else if (strcmp(name, DYNSTR_NAME) == 0) {
465             dynstr_scnp = scnp;
466             dyn_str_addr_ = shdrp->sh_addr;
467         }
468     }
469     string temp = string(" text: ");
470     temp += string((u_int)txtaddr);
471     temp += string(" bss: ");
472     temp += string((u_int)bssaddr);
473     temp += string(" symtab: ");
474     temp += string((u_int)symscnp);
475     temp += string(" strtab: ");
476     temp += string((u_int)strscnp);
477     temp += string(" ehdrp: ");
478     temp += string((u_int)ehdrp);
479     temp += string(" phdrp: ");
480     temp += string((u_int)phdrp);
481     temp += string("\n");
482     // log_elferror(err_func_, P_strdup(temp.string_of()));
483
484     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
485         log_elferror(err_func_, "no text/bss/symbol/string section");
486         return false;
487     }
488
489     return true;
490 }
491
492
493 static int symbol_compare(const void *x, const void *y) {
494     const Symbol *s1 = (const Symbol *)x;
495     const Symbol *s2 = (const Symbol *)y;
496     return (s1->addr() - s2->addr());
497 }
498
499 inline bool Object::get_relocation_entries(Elf_Scn*& rel_plt_scnp,
500                         Elf_Scn*& dynsymscnp, Elf_Scn*& dynstrscnp) {
501
502 #if defined (i386_unknown_solaris2_5)
503         Elf32_Rel *next_entry = 0;
504         Elf32_Rel *entries = 0;
505 #else
506         Elf32_Rela *next_entry = 0;
507         Elf32_Rela *entries = 0;
508 #endif
509
510     if(rel_plt_size_ && rel_plt_addr_) {
511         Elf_Data *reldatap = elf_getdata(rel_plt_scnp, 0);
512         Elf_Data* symdatap = elf_getdata(dynsymscnp, 0);
513         Elf_Data* strdatap = elf_getdata(dynstrscnp, 0);
514         if(!reldatap || !symdatap || !strdatap) return false;
515
516         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
517         const char* strs   = (const char *) strdatap->d_buf;
518         Address next_plt_entry_addr = plt_addr_;
519
520 #if defined (i386_unknown_solaris2_5)
521         entries  = (Elf32_Rel *) reldatap->d_buf;
522         next_plt_entry_addr += plt_entry_size_;  // 1st PLT entry is special
523 #else
524         entries  = (Elf32_Rela *) reldatap->d_buf;
525         next_plt_entry_addr += 4*(plt_entry_size_); //1st 4 entries are special
526 #endif
527         if(!entries) return false;
528
529         next_entry = entries;
530         for(u_int i=0; i < (rel_plt_size_/rel_plt_entry_size_); i++) {
531             Elf32_Word sym_index = ELF32_R_SYM(next_entry->r_info); 
532             relocationEntry re(next_plt_entry_addr, next_entry->r_offset,
533                                 string(&strs[syms[sym_index].st_name]));
534             relocation_table_ += re; 
535             next_entry++;
536             next_plt_entry_addr += plt_entry_size_;
537         }
538     }
539     return true;
540 }
541
542
543 inline
544 void
545 Object::load_object() {
546     const char* file = file_.string_of();
547     struct stat st;
548     int         fd   = -1;
549     char*       ptr  = 0;
550     Elf*        elfp = 0;
551
552     bool        did_open = false;
553     bool        did_elf  = false;
554
555     /* try */ {
556         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
557             log_perror(err_func_, file);
558             /* throw exception */ goto cleanup;
559         }
560         did_open = true;
561
562         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
563             == (char *) -1) {
564             log_perror(err_func_, "mmap");
565             /* throw exception */ goto cleanup;
566         }
567
568         Elf32_Ehdr* ehdrp   = 0;
569         Elf32_Phdr* phdrp   = 0;
570         Elf_Scn*    symscnp = 0;
571         Elf_Scn*    strscnp = 0;
572         Elf_Scn*    stabscnp = 0;
573         Elf_Scn*    stabstrscnp = 0;
574         unsigned    txtaddr = 0;
575         unsigned    bssaddr = 0;
576         Elf_Scn* rel_plt_scnp = 0;
577         Elf_Scn* plt_scnp = 0; 
578         Elf_Scn* got_scnp = 0;
579         Elf_Scn* dynsym_scnp = 0;
580         Elf_Scn* dynstr_scnp = 0;
581
582         // EEL, initialize the stuff to zero, so that we know, it is not 
583         // EEL rewritten, if they have not been changed by loaded_elf
584         //
585         code_ptr_ = 0; code_off_ = 0 ;  code_len_ = 0 ;
586
587         // EEL, added one more parameter
588         if (!loaded_elf(fd, ptr, did_elf, elfp, ehdrp, phdrp, txtaddr,
589                 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp,
590                 rel_plt_scnp,plt_scnp,got_scnp,dynsym_scnp,dynstr_scnp)) {
591                 /* throw exception */ goto cleanup;
592         }
593
594         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
595             if(!code_ptr_ && !code_off_ && !code_len_)
596             {//NON EEL
597              //This can be tested differently, by testing if EEL is false
598              //  printf("This is a regular executable\n") ;
599
600                 if ((phdrp[i0].p_vaddr <= txtaddr)
601                         && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
602                         code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
603                         code_off_ = (Address) phdrp[i0].p_vaddr;
604                         code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
605                 }
606             }
607             if ((phdrp[i0].p_vaddr <= bssaddr)
608                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
609                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
610                 data_off_ = (Address) phdrp[i0].p_vaddr;
611                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
612             }
613         }
614         if (!code_ptr_ || !code_off_ || !code_len_) {
615             log_printf(err_func_, "cannot locate instructions\n");
616             /* throw exception */ goto cleanup;
617         }
618         if (!data_ptr_ || !data_off_ || !data_len_) {
619             log_printf(err_func_, "cannot locate data segment\n");
620             /* throw exception */ goto cleanup;
621         }
622
623         Elf_Data* symdatap = elf_getdata(symscnp, 0);
624         Elf_Data* strdatap = elf_getdata(strscnp, 0);
625         if (!symdatap || !strdatap) {
626             log_elferror(err_func_, "locating symbol/string data");
627             /* throw exception */ goto cleanup;
628         }
629
630         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
631         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
632         const char* strs   = (const char *) strdatap->d_buf;
633         string      module = "DEFAULT_MODULE";
634         string      name   = "DEFAULT_NAME";
635
636         // global symbols are put in global_symbols. Later we read the
637         // stab section to find the module to where they belong.
638         dictionary_hash<string, Symbol> global_symbols(string::hash);
639
640         vector<Symbol> allsymbols;
641
642         for (unsigned i1 = 0; i1 < nsyms; i1++) {
643           // First, we must check st_shndx. 
644           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
645           // probably defined in a shared object that will be dynamically
646           // linked with the executable. We just ignore it for now.
647           if (syms[i1].st_shndx != SHN_UNDEF) {
648             bool st_kludge = false;
649             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
650             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
651             case STT_FILE:
652                 module = string(&strs[syms[i1].st_name]);
653                 type   = Symbol::PDST_MODULE;
654                 break;
655
656             case STT_OBJECT:
657                 type = Symbol::PDST_OBJECT;
658                 break;
659
660             case STT_FUNC:
661                 type = Symbol::PDST_FUNCTION;
662                 break;
663
664             default:
665                 continue;
666             }
667
668             name = string(&strs[syms[i1].st_name]);
669
670             if (ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) {
671                allsymbols += Symbol(name, module, type, Symbol::SL_LOCAL,
672                                     syms[i1].st_value, st_kludge, 
673                                     syms[i1].st_size);
674             }
675             else {
676                allsymbols += Symbol(name, string(""), type, Symbol::SL_GLOBAL,
677                                     syms[i1].st_value, st_kludge,
678                                     syms[i1].st_size);
679             }
680           }
681         }
682
683         // some functions may have size zero in the symbol table,
684         // we need to find the correct size
685         // EEL: for EEL rewritten software, the size maybe incorrect
686         //      So that we have to recalculate the size for all functions
687
688         allsymbols.sort(symbol_compare);
689         unsigned nsymbols = allsymbols.size();
690         for (unsigned u = 0; u < nsymbols; u++) {
691           if (allsymbols[u].type() == Symbol::PDST_FUNCTION
692                && (EEL || allsymbols[u].size() == 0)) {
693             unsigned v = u+1;
694             while (v < nsymbols && allsymbols[v].addr() == allsymbols[u].addr())
695               v++;
696             if (v < nsymbols) {
697               allsymbols[u].change_size((unsigned)allsymbols[v].addr()
698                                         - (unsigned)allsymbols[u].addr());
699             }
700           }
701
702           // We are done with the local symbols. We save the global so that
703           // we can get their module from the .stab section.
704           if (allsymbols[u].linkage() == Symbol::SL_LOCAL)
705             symbols_[allsymbols[u].name()] = allsymbols[u];
706           else {
707             // globals should be unique
708             assert(!(global_symbols.defines(allsymbols[u].name()))); 
709             global_symbols[allsymbols[u].name()] = allsymbols[u];
710           }
711         }      
712         
713
714         // Read the stab section to find the module of global symbols.
715         // The symbols appear in the stab section by module. A module begins
716         // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
717         // All the symbols in between those two symbols belong to the module.
718
719         Elf_Data* stabdatap = elf_getdata(stabscnp, 0);
720         Elf_Data* stabstrdatap = elf_getdata(stabstrscnp, 0);
721         struct stab_entry *stabsyms = 0;
722         unsigned stab_nsyms;
723         const char *stabstrs = 0;
724
725         if (stabdatap && stabstrdatap) {
726           stabsyms = (struct stab_entry *) stabdatap->d_buf;
727           stab_nsyms = stabdatap->d_size / sizeof(struct stab_entry);
728           stabstrs = (const char *) stabstrdatap->d_buf;
729         }
730         else 
731           stab_nsyms = 0;
732
733         // the stabstr contains one string table for each module.
734         // stabstr_offset gives the offset from the begining of stabstr of the
735         // string table for the current module.
736         // stabstr_nextoffset gives the offset for the next module.
737         unsigned stabstr_offset = 0;
738         unsigned stabstr_nextoffset = 0;
739
740         bool is_fortran = false;  // is the current module fortran code?
741            /* we must know if we are reading a fortran module because fortran
742               symbol names are different in the .stab and .symtab sections.
743               A symbol that appears as 'foo' in the .stab section, appears
744               as 'foo_' in .symtab.
745            */
746         module = "";
747   
748         for (unsigned i = 0; i < stab_nsyms; i++) {
749           switch(stabsyms[i].type) {
750           case N_UNDF: /* start of object file */
751             assert(stabsyms[i].name == 1);
752             stabstr_offset = stabstr_nextoffset;
753             // stabsyms[i].val has the size of the string table of this module.
754             // We use this value to compute the offset of the next string table.
755             stabstr_nextoffset = stabstr_offset + stabsyms[i].val;
756             module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
757             break;
758
759           case N_ENDM: /* end of object file */
760             is_fortran = false;
761             module = "";
762             break;
763
764           case N_SO: /* compilation source or file name */
765             if (stabsyms[i].desc == N_SO_FORTRAN)
766               is_fortran = true;
767             break;
768
769           case N_ENTRY: /* fortran alternate subroutine entry point */
770           case N_FUN: /* function */
771           case N_GSYM: /* global symbol */
772             // the name string of a function or object appears in the stab string table
773             // as <symbol name>:<symbol descriptor><other stuff>
774             // where <symbol descriptor> is a one char code.
775             // we must extract the name and descriptor from the string
776           {
777             const char *p = &stabstrs[stabstr_offset+stabsyms[i].name];
778             const char *q = strchr(p,':');
779             assert(q);
780             unsigned len = q - p;
781             assert(len > 0);
782             char *sname = new char[len+1];
783             strncpy(sname, p, len);
784             sname[len] = 0;
785             
786             // q points to the ':' in the name string, so 
787             // q[1] is the symbol descriptor. We must check the symbol descriptor
788             // here to skip things we are not interested in, such as local functions
789             // and prototypes.
790             if (q[1] == SD_GLOBAL_FUN || q[1] == SD_GLOBAL_VAR || stabsyms[i].type==N_ENTRY) { 
791               string SymName = string(sname);
792               bool res = global_symbols.defines(SymName);
793               if (!res && is_fortran) {
794                 // Fortran symbols usually appear with an '_' appended in .symtab,
795                 // but not on .stab
796                 SymName += "_";
797                 res = global_symbols.defines(SymName);
798               }
799
800               if (!res) break;
801 //              assert(res); // All globals in .stab should be defined in .symtab
802
803               Symbol sym = global_symbols[SymName];
804               symbols_[SymName] = Symbol(sym.name(), module, sym.type(), sym.linkage(), 
805                                   sym.addr(), sym.kludge(), sym.size());
806             }
807           }
808             break;
809
810           default:
811             /* ignore other entries */
812             break;
813           }
814         }
815
816         /* The remaing symbols go without module */
817         vector<string> k = global_symbols.keys();
818         for (unsigned i2 = 0; i2 < k.size(); i2++) {
819           Symbol sym = global_symbols[k[i2]];
820           if (!(symbols_.defines(sym.name())))
821              symbols_[sym.name()] = sym;
822         }
823
824         if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
825             if(!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) {
826                 goto cleanup;
827             }
828         }
829
830     }  /* try */
831
832     /* catch */
833 cleanup: {
834         if (did_elf && (elf_end(elfp) != 0)) {
835             log_elferror(err_func_, "closing file");
836         }
837         if (did_open && (close(fd) == -1)) {
838             log_perror(err_func_, "close");
839         }
840     }
841 }
842
843
844 inline
845 void
846 Object::load_shared_object() {
847     const char* file = file_.string_of();
848     struct stat st;
849     int         fd   = -1;
850     char*       ptr  = 0;
851     Elf*        elfp = 0;
852
853     bool        did_open = false;
854     bool        did_elf  = false;
855
856     /* try */ {
857         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
858             log_perror(err_func_, file);
859             /* throw exception */ goto cleanup2;
860         }
861         did_open = true;
862
863         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
864             == (char *) -1) {
865             log_perror(err_func_, "mmap");
866             /* throw exception */ goto cleanup2;
867         }
868
869         Elf32_Ehdr* ehdrp   = 0;  /* ELF header */
870         Elf32_Phdr* phdrp   = 0;  /* program header */
871         Elf_Scn*    symscnp = 0;
872         Elf_Scn*    strscnp = 0;
873         unsigned    txtaddr = 0;
874         unsigned    bssaddr = 0;
875         Elf_Scn* rel_plt_scnp = 0;
876         Elf_Scn* plt_scnp = 0; 
877         Elf_Scn* got_scnp = 0;
878         Elf_Scn* dynsym_scnp = 0;
879         Elf_Scn* dynstr_scnp = 0;
880
881         if (!loaded_elf_obj(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
882                             bssaddr, symscnp, strscnp, rel_plt_scnp,
883                             plt_scnp,got_scnp,dynsym_scnp, dynstr_scnp)) {
884                 /* throw exception */ goto cleanup2;
885         }
886
887         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
888             if ((phdrp[i0].p_vaddr <= txtaddr)
889                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
890                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
891                 code_off_ = (Address) phdrp[i0].p_vaddr;
892                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
893             }
894             else if ((phdrp[i0].p_vaddr <= bssaddr)
895                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
896                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
897                 data_off_ = (Address) phdrp[i0].p_vaddr;
898                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
899             }
900         }
901
902         Elf_Data* symdatap = elf_getdata(symscnp, 0);
903         Elf_Data* strdatap = elf_getdata(strscnp, 0);
904         if (!symdatap || !strdatap) {
905             log_elferror(err_func_, "locating symbol/string data");
906             /* throw exception */ goto cleanup2;
907         }
908
909         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
910         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
911         const char* strs   = (const char *) strdatap->d_buf;
912         string      module = "DEFAULT_MODULE";
913         string      name   = "DEFAULT_NAME";
914
915         // for shared objects add a module that is the file name
916         // and add all the global symbols as functions 
917         const char *libname = file_.string_of();
918         // find short name
919         const char *last = 0;
920         for(u_int i=0; i < file_.length();i++) {
921             if(libname[i] == '/'){
922                 last = (const char *)(&(libname[i]));
923                 // log_elferror(err_func_, P_strdup(last));
924             }
925         }
926         if(last){
927             module = (const char *)(last +1);  
928         }
929         else{
930             module = string("DEFAULT_MODULE");  
931         }
932         // string blah = string("module name: ");
933         // blah += module.string_of();
934         // blah += ("\n");
935         // log_elferror(err_func_, P_strdup(blah.string_of()));
936
937         vector<Symbol> allsymbols;
938         bool found = false;
939         for (unsigned i1 = 0; i1 < nsyms; i1++) {
940           // First, we must check st_shndx. 
941           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
942           // probably defined in a shared object that will be dynamically
943           // linked with the executable. We just ignore it for now.
944           if (syms[i1].st_shndx != SHN_UNDEF) {
945             bool st_kludge = false;
946             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
947             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
948             case STT_FILE: {
949                 string temp2 = string(&strs[syms[i1].st_name]);
950                 if(temp2 == module){
951                     module = string(&strs[syms[i1].st_name]);
952                     type   = Symbol::PDST_MODULE;
953                     found = true;
954                 }
955                 break;
956                 }
957
958             case STT_OBJECT:
959                 type = Symbol::PDST_OBJECT;
960                 break;
961
962             case STT_FUNC:
963                 type = Symbol::PDST_FUNCTION;
964                 break;
965
966             case STT_NOTYPE:
967                 type = Symbol::PDST_NOTYPE;
968                 break;
969
970             default:
971                 continue;
972             }
973
974             name = string(&strs[syms[i1].st_name]);
975
976             // only add symbols of type STB_LOCAL and  FILE if they are 
977             // the shared object name
978             if ((ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) && (found)){
979                    symbols_[name] = Symbol(name, module, type, Symbol::SL_LOCAL,
980                                     syms[i1].st_value, st_kludge, 
981                                     syms[i1].st_size);
982                    found = false;
983             }
984             else if((ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL)
985                         && (ELF32_ST_TYPE(syms[i1].st_info) != STT_FUNC)) {
986                 allsymbols += Symbol(name, module, type, Symbol::SL_LOCAL,
987                                                 syms[i1].st_value, st_kludge,
988                                                 syms[i1].st_size);
989             }
990             else {
991                if(ELF32_ST_BIND(syms[i1].st_info) == STB_WEAK){
992                    allsymbols += Symbol(name, module, 
993                                         type, Symbol::SL_WEAK,
994                                         syms[i1].st_value, st_kludge,
995                                         syms[i1].st_size);
996                }
997                else{
998                    allsymbols += Symbol(name, module, 
999                                         type, Symbol::SL_GLOBAL,
1000                                         syms[i1].st_value, st_kludge,
1001                                         syms[i1].st_size);
1002                }
1003             }
1004           }
1005         }
1006
1007
1008         // Sort all the symbols, and fix the sizes
1009         allsymbols.sort(symbol_compare);
1010
1011         // if the symbol is type PDST_FUNCTION and the next symbol is 
1012         // type PDST_FUNCTION size needs to be changed...this occurs when
1013         // one function's binding is WEAK and the other is GLOBAL, or when
1014         // two functions overlap 
1015         for(u_int i=0; i < (allsymbols.size() -1); i++){
1016             u_int new_size = 0;
1017             bool  change_size = false;
1018
1019             // some functions may have size zero in the symbol table
1020             // we have to fix the size of the global functions
1021             if (allsymbols[i].type() == Symbol::PDST_FUNCTION
1022                 && allsymbols[i].linkage() == Symbol::SL_GLOBAL
1023                 && allsymbols[i].size() == 0) {
1024                unsigned j = i+1;
1025                while (j < allsymbols.size() 
1026                       && allsymbols[j].addr() == allsymbols[i].addr())
1027                  j++;
1028                allsymbols[i].change_size(allsymbols[j].addr()-allsymbols[i].addr());
1029             }
1030
1031             if((allsymbols[i].type() == Symbol::PDST_FUNCTION)
1032                 && (allsymbols[i+1].type() == Symbol::PDST_FUNCTION)){
1033                 u_int next_start=allsymbols[i].addr()+allsymbols[i].size();
1034
1035                 // if the symbols have the same address and one is weak
1036                 // and the other is global keeep the global one
1037                 if((allsymbols[i].addr() == allsymbols[i+1].addr()) && 
1038                     (((allsymbols[i].linkage() == Symbol::SL_WEAK) &&
1039                       (allsymbols[i+1].linkage() == Symbol::SL_GLOBAL)) || 
1040                      ((allsymbols[i].linkage() == Symbol::SL_GLOBAL) &&
1041                       (allsymbols[i+1].linkage() == Symbol::SL_WEAK)))) {
1042
1043                       if(allsymbols[i].linkage() == Symbol::SL_WEAK){
1044                           allsymbols[i].change_size(0);
1045                       } else {
1046                           allsymbols[i+1].change_size(0);
1047                       }
1048                 }
1049                 else if(next_start > allsymbols[i+1].addr()){
1050                         new_size =  allsymbols[i+1].addr()-allsymbols[i].addr();
1051                         change_size = true;
1052                 }
1053             }
1054
1055             if((allsymbols[i].type() == Symbol::PDST_FUNCTION) && change_size){
1056                 symbols_[allsymbols[i].name()] =
1057                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
1058                     allsymbols[i].type(), allsymbols[i].linkage(),
1059                     allsymbols[i].addr(), allsymbols[i].kludge(),
1060                     new_size);
1061             }
1062             else {
1063                 symbols_[allsymbols[i].name()] =
1064                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
1065                     allsymbols[i].type(), allsymbols[i].linkage(),
1066                     allsymbols[i].addr(), allsymbols[i].kludge(),
1067                     allsymbols[i].size());
1068             }
1069         }
1070         // add last symbol
1071         u_int last_sym = allsymbols.size()-1;
1072         symbols_[allsymbols[last_sym].name()] =
1073             Symbol(allsymbols[last_sym].name(), allsymbols[last_sym].module(),
1074             allsymbols[last_sym].type(), allsymbols[last_sym].linkage(),
1075             allsymbols[last_sym].addr(), allsymbols[last_sym].kludge(),
1076             allsymbols[last_sym].size());
1077
1078         if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
1079             if(!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) { 
1080                 goto cleanup2;
1081             }
1082         }
1083
1084     }  /* try */
1085
1086     /* catch */
1087
1088 cleanup2: {
1089         if (did_elf && (elf_end(elfp) != 0)) {
1090             log_elferror(err_func_, "closing file");
1091         }
1092         if (did_open && (close(fd) == -1)) {
1093             log_perror(err_func_, "close");
1094         }
1095     }
1096 }
1097
1098
1099 inline
1100 Object::Object(const string file, void (*err_func)(const char *))
1101     : AObject(file, err_func), EEL(false) {
1102     load_object();
1103 }
1104
1105 inline
1106 Object::Object(const string file, u_int ,void (*err_func)(const char *))
1107     : AObject(file, err_func), EEL(false)  {
1108     load_shared_object();
1109 }
1110
1111 inline
1112 Object::Object(const Object& obj)
1113     : AObject(obj), EEL(false) {
1114     load_object();
1115 }
1116
1117 inline bool Object::get_func_binding_table(vector<relocationEntry> &fbt) const {
1118     if(!plt_addr_ || (!relocation_table_.size())) return false;
1119     fbt = relocation_table_;
1120     return true;
1121 }
1122
1123 #endif /* !defined(_Object_elf32_h_) */