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