Build identifier class
[dyninst.git] / pdutil / src / Object-elf.C
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 #include "util/h/Object.h"
43 #include "util/h/Object-elf32.h"
44
45 /**********************************************
46  *
47  * Implementation of "Object" (descriptive name, huh??) class for 
48  *  32 bit ELF format....
49  *
50 **********************************************/
51
52 #ifdef _Object_elf32_h_
53
54 Object::~Object() {
55 }
56
57 const Object&
58 Object::operator=(const Object& obj) {
59
60     (void) AObject::operator=(obj);
61
62     plt_addr_ = obj.plt_addr_;
63     plt_size_ = obj.plt_size_;
64     plt_entry_size_ = obj.plt_entry_size_;
65     got_addr_ = obj.got_addr_;
66     rel_plt_addr_ = obj.rel_plt_addr_;
67     rel_plt_size_ = obj.rel_plt_size_;
68     rel_plt_entry_size_ = obj.rel_plt_entry_size_;
69     dyn_sym_addr_ = obj.dyn_sym_addr_;
70     dyn_str_addr_ = obj.dyn_str_addr_;
71     relocation_table_  = obj.relocation_table_;
72     return *this;
73 }
74
75 void Object::log_elferror(void (*pfunc)(const char *), const char* msg) {
76     const char* err = elf_errmsg(elf_errno());
77     log_printf(pfunc, "%s: %s\n", msg, err ? err : "(bad elf error)");
78 }
79
80
81
82 //EEL
83 //
84 #define EXTRA_SPACE 8     //added some EXTRA_SPACE space, such that,
85                        // we won't look for functions in the data space
86
87
88 // Added one extra parameter 'char *ptr', for EEL rewritten software
89 // code_ptr_, code_offset_, code_len_ is calculated in this function
90 // For more detail , see comments with the word 'EEL'
91 //
92 bool
93 Object::loaded_elf(int fd, char *ptr, bool& did_elf, Elf*& elfp, 
94     Elf32_Ehdr*& ehdrp,
95     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
96     Elf_Scn*& symscnp, Elf_Scn*& strscnp, Elf_Scn*& stabscnp, 
97     Elf_Scn*& stabstrscnp, Elf_Scn*& rel_plt_scnp, Elf_Scn*& plt_scnp, 
98     Elf_Scn*& got_scnp,  Elf_Scn*& dynsym_scnp, Elf_Scn*& dynstr_scnp) {
99
100     elf_version(EV_CURRENT);
101     elf_errno();
102
103     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
104         || (elf_kind(elfp) != ELF_K_ELF)) {
105         log_elferror(err_func_, "opening file");
106         return false;
107     }
108     did_elf = true;
109
110     if (((ehdrp = elf32_getehdr(elfp)) == 0)
111         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
112         || (ehdrp->e_type != ET_EXEC && ehdrp->e_type != ET_DYN)
113            // support shared library code here also....
114         || (ehdrp->e_phoff == 0)
115         || (ehdrp->e_shoff == 0)
116         || (ehdrp->e_phnum == 0)
117         || (ehdrp->e_shnum == 0)) {
118         log_elferror(err_func_, "2: loading eheader");
119         return false;
120     }
121
122     if ((phdrp = elf32_getphdr(elfp)) == 0) {
123         log_elferror(err_func_, "loading pheader");
124         return false;
125     }
126
127     Elf_Scn*    shstrscnp  = 0;
128     Elf32_Shdr* shstrshdrp = 0;
129     Elf_Data*   shstrdatap = 0;
130     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
131         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
132         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
133         log_elferror(err_func_, "loading header section");
134         return false;
135     }
136
137     const char* shnames = (const char *) shstrdatap->d_buf;
138     Elf_Scn*    scnp    = 0;
139
140     // moved const char declrs out of loop....
141     const char* EDITED_TEXT_NAME   = ".edited_text";
142     const char* TEXT_NAME   = ".text";
143     const char* BSS_NAME    = ".bss";
144     const char* SYMTAB_NAME = ".symtab";
145     const char* STRTAB_NAME = ".strtab";
146     const char* STAB_NAME   = ".stab";
147     const char* STABSTR_NAME= ".stabstr";
148
149     // sections from dynamic executables and shared objects
150     const char* PLT_NAME = ".plt";
151     const char* REL_PLT_NAME = ".rela.plt";        // sparc-solaris
152     const char* REL_PLT_NAME2 = ".rel.plt";        // x86-solaris
153     const char* GOT_NAME = ".got";         
154     const char* DYNSYM_NAME = ".dynsym";           
155     const char* DYNSTR_NAME = ".dynstr";           
156
157     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
158         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
159         if (!shdrp) {
160             log_elferror(err_func_, "scanning sections");
161             return false;
162         }
163
164         const char* name        = (const char *) &shnames[shdrp->sh_name];
165
166         if (strcmp(name, EDITED_TEXT_NAME) == 0) {
167                 // EEL rewriten executable
168                 printf("This is an EEL rewritten executable \n") ;
169                 EEL = true ;
170                 txtaddr = shdrp->sh_addr;
171                 code_ptr_ = (Word *) ((void*)&ptr[shdrp->sh_offset-EXTRA_SPACE]);
172                 code_off_ = (Address) shdrp->sh_addr -EXTRA_SPACE ;
173                 code_len_ = ((unsigned) shdrp->sh_size + EXTRA_SPACE) / sizeof(Word);
174         }
175         if (strcmp(name, TEXT_NAME) == 0) {
176             txtaddr = shdrp->sh_addr;
177         }
178         else if (strcmp(name, BSS_NAME) == 0) {
179             bssaddr = shdrp->sh_addr;
180         }
181         else if (strcmp(name, SYMTAB_NAME) == 0) {
182             symscnp = scnp;
183         }
184         else if (strcmp(name, STRTAB_NAME) == 0) {
185             strscnp = scnp;
186         }
187         else if (strcmp(name, STAB_NAME) == 0) {
188             stabscnp = scnp;
189         }
190         else if (strcmp(name, STABSTR_NAME) == 0) {
191             stabstrscnp = scnp;
192         }
193         else if ((strcmp(name, REL_PLT_NAME) == 0) 
194                 || (strcmp(name, REL_PLT_NAME2) == 0)) {
195              rel_plt_scnp = scnp;
196              rel_plt_addr_ = shdrp->sh_addr;
197              rel_plt_size_ = shdrp->sh_size;
198              rel_plt_entry_size_ = shdrp->sh_entsize;
199         }
200         else if (strcmp(name, PLT_NAME) == 0) {
201             plt_scnp = scnp;
202             plt_addr_ = shdrp->sh_addr;
203             plt_size_ = shdrp->sh_size;
204             plt_entry_size_ = shdrp->sh_entsize;
205         }
206         else if (strcmp(name, GOT_NAME) == 0) {
207             got_scnp = scnp;
208             got_addr_ = shdrp->sh_addr;
209         }
210         else if (strcmp(name, DYNSYM_NAME) == 0) {
211             dynsym_scnp = scnp;
212             dyn_sym_addr_ = shdrp->sh_addr;
213         }
214         else if (strcmp(name, DYNSTR_NAME) == 0) {
215             dynstr_scnp = scnp;
216             dyn_str_addr_ = shdrp->sh_addr;
217         }
218
219     }
220     if(!symscnp || !strscnp) {
221       if(dynsym_scnp && dynstr_scnp){
222           symscnp = dynsym_scnp;
223           strscnp = dynstr_scnp;
224       }
225     }
226     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
227         log_elferror(err_func_, "no text/bss/symbol/string section");
228         return false;
229     }
230
231     return true;
232 }
233
234 static int symbol_compare(const void *x, const void *y) {
235     const Symbol *s1 = (const Symbol *)x;
236     const Symbol *s2 = (const Symbol *)y;
237     return (s1->addr() - s2->addr());
238 }
239
240 bool Object::get_relocation_entries(Elf_Scn*& rel_plt_scnp,
241                         Elf_Scn*& dynsymscnp, Elf_Scn*& dynstrscnp) {
242
243 #if defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0)
244         Elf32_Rel *next_entry = 0;
245         Elf32_Rel *entries = 0;
246 #else
247         Elf32_Rela *next_entry = 0;
248         Elf32_Rela *entries = 0;
249 #endif
250
251     if(rel_plt_size_ && rel_plt_addr_) {
252         Elf_Data *reldatap = elf_getdata(rel_plt_scnp, 0);
253         Elf_Data* symdatap = elf_getdata(dynsymscnp, 0);
254         Elf_Data* strdatap = elf_getdata(dynstrscnp, 0);
255         if(!reldatap || !symdatap || !strdatap) return false;
256
257         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
258         const char* strs   = (const char *) strdatap->d_buf;
259         Address next_plt_entry_addr = plt_addr_;
260
261 #if defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0)
262         entries  = (Elf32_Rel *) reldatap->d_buf;
263         next_plt_entry_addr += plt_entry_size_;  // 1st PLT entry is special
264 #else
265         entries  = (Elf32_Rela *) reldatap->d_buf;
266         next_plt_entry_addr += 4*(plt_entry_size_); //1st 4 entries are special
267 #endif
268         if(!entries) return false;
269
270         next_entry = entries;
271         for(u_int i=0; i < (rel_plt_size_/rel_plt_entry_size_); i++) {
272             Elf32_Word sym_index = ELF32_R_SYM(next_entry->r_info); 
273             relocationEntry re(next_plt_entry_addr, next_entry->r_offset,
274                                 string(&strs[syms[sym_index].st_name]));
275             relocation_table_ += re; 
276             next_entry++;
277             next_plt_entry_addr += plt_entry_size_;
278         }
279     }
280     return true;
281 }
282
283 /*************************************************************
284  *
285  *  New (Experimenta) version of code for loading statically linked
286  *   object files....
287  *
288 *************************************************************/
289 void Object::load_object() {
290         const char* file = file_.string_of();
291     struct stat st;
292     int         fd   = -1;
293     char*       ptr  = 0;
294     Elf*        elfp = 0;
295
296     bool        did_open = false;
297     bool        did_elf  = false;
298
299     /* try */ {
300         //  try to open file for reading, and also use fstat to read info
301         //   about the file in st structure....
302         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
303             log_perror(err_func_, file);
304             /* throw exception */ goto cleanup;
305         }
306         did_open = true;
307
308         //  attempt to memory map entire file.  st.st_size should contain file
309         //   size (in bytes)....
310         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
311             == (char *) -1) {
312             log_perror(err_func_, "mmap");
313             /* throw exception */ goto cleanup;
314         }
315
316         Elf32_Ehdr* ehdrp   = 0;  /* ELF header */
317         Elf32_Phdr* phdrp   = 0;  /* program header */
318         Elf_Scn*    symscnp = 0;
319         Elf_Scn*    strscnp = 0;
320         Elf_Scn*    stabscnp = 0;
321         Elf_Scn*    stabstrscnp = 0;
322         unsigned    txtaddr = 0;
323         unsigned    bssaddr = 0;
324         Elf_Scn* rel_plt_scnp = 0;
325         Elf_Scn* plt_scnp = 0; 
326         Elf_Scn* got_scnp = 0;
327         Elf_Scn* dynsym_scnp = 0;
328         Elf_Scn* dynstr_scnp = 0;
329
330         // EEL, initialize the stuff to zero, so that we know, it is not 
331         // EEL rewritten, if they have not been changed by loaded_elf
332         //
333         code_ptr_ = 0; code_off_ = 0 ;  code_len_ = 0 ;
334
335         // And attempt to parse the ELF data structures in the file....
336         // EEL, added one more parameter
337         if (!loaded_elf(fd, ptr, did_elf, elfp, ehdrp, phdrp, txtaddr,
338                 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp,
339                 rel_plt_scnp,plt_scnp,got_scnp,dynsym_scnp,dynstr_scnp)) {
340                 /* throw exception */ goto cleanup;
341         }
342
343         // find code and data segments....
344         find_code_and_data(ehdrp, phdrp, ptr, txtaddr, bssaddr);
345
346         //  if could not find code or data segments, log error....
347         if (!code_ptr_ || !code_off_ || !code_len_) {
348             log_printf(err_func_, "cannot locate instructions\n");
349             /* throw exception */ goto cleanup;
350         }
351         if (!data_ptr_ || !data_off_ || !data_len_) {
352             log_printf(err_func_, "cannot locate data segment\n");
353             /* throw exception */ goto cleanup;
354         }
355
356         Elf_Data* symdatap = elf_getdata(symscnp, 0);
357         Elf_Data* strdatap = elf_getdata(strscnp, 0);
358         if (!symdatap || !strdatap) {
359             log_elferror(err_func_, "locating symbol/string data");
360             /* throw exception */ goto cleanup;
361         }
362
363         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
364         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
365         const char* strs   = (const char *) strdatap->d_buf;
366         string      module = "DEFAULT_MODULE";
367         string      name   = "DEFAULT_NAME";
368
369         // global symbols are put in global_symbols. Later we read the
370         // stab section to find the module to where they belong.
371         // Experiment : lets try to be a bit more intelligent about
372         // how we initially size the global_symbols table.  
373         // dictionary_lite takes an initial # of bins (2nd param), 
374         // a max bin load (3rd param), and a grow factor (4th param).
375         // Leaving aside the grow factor, lets allocate an initial #
376         // of bins = nsyms / max bin load.
377         dictionary_hash<string, Symbol> global_symbols(string::hash, \
378                        nsyms, 1.0);
379
380         vector<Symbol> allsymbols;
381
382         // try to resolve all symbols found in symbol table + 
383         //  enter them into <allsymbols>.
384         parse_symbols(allsymbols, syms, nsyms, strs, 1, \
385             module);
386
387         // Sort all the symbols - for patching symbol data sizes....
388         allsymbols.sort(symbol_compare);
389
390         // patch 0 symbol sizes....
391         fix_zero_function_sizes(allsymbols, 0);
392         
393         // override instances of weak symbols w/ instances of strong ones,
394         //  also currently has effect of making sure that symbols dont
395         //  extend beyond the marked beginning of the next symbo....
396         override_weak_symbols(allsymbols);
397
398         // and dump <allsymbols> into (data member) symbols_
399         //  or (paramater) <global_symbols> accoriding to linkage.... 
400         insert_symbols_static(allsymbols, global_symbols);
401
402         // try to use the .stab section to figure modules for symbols
403         //  in global <global_symbols>....
404         fix_global_symbol_modules_static(global_symbols, \
405             stabscnp, stabstrscnp);               
406
407         if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
408             if(!get_relocation_entries(rel_plt_scnp,\
409                     dynsym_scnp,dynstr_scnp)) {
410                 goto cleanup;
411             }
412         }
413         
414     }  /* try */
415
416         /* catch */
417 cleanup: 
418     {
419         if (did_elf && (elf_end(elfp) != 0)) {
420             log_elferror(err_func_, "closing file");
421         }
422         if (did_open && (close(fd) == -1)) {
423             log_perror(err_func_, "close");
424         }
425     }
426 }
427
428
429 /*************************************************************
430  *
431  *  New (Experimental) version of code for loading shared
432  *   libraries....
433  *
434 *************************************************************/
435
436 void
437 Object::load_shared_object() {
438     const char* file = file_.string_of();
439     struct stat st;
440     int         fd   = -1;
441     char*       ptr  = 0;
442     Elf*        elfp = 0;
443
444     bool        did_open = false;
445     bool        did_elf  = false;
446
447     /* try */ {
448         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
449             log_perror(err_func_, file);
450             /* throw exception */ goto cleanup2;
451         }
452         did_open = true;
453
454         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
455             == (char *) -1) {
456             log_perror(err_func_, "mmap");
457             /* throw exception */ goto cleanup2;
458         }
459
460         Elf32_Ehdr* ehdrp   = 0;  /* ELF header */
461         Elf32_Phdr* phdrp   = 0;  /* program header */
462         Elf_Scn*    symscnp = 0;
463         Elf_Scn*    stabscnp = 0;
464         Elf_Scn*    stabstrscnp = 0;
465         Elf_Scn*    strscnp = 0;
466         unsigned    txtaddr = 0;
467         unsigned    bssaddr = 0;
468         Elf_Scn* rel_plt_scnp = 0;
469         Elf_Scn* plt_scnp = 0; 
470         Elf_Scn* got_scnp = 0;
471         Elf_Scn* dynsym_scnp = 0;
472         Elf_Scn* dynstr_scnp = 0;
473
474         /***  ptr, stabscnp, stabstrscnp should NOT be filled in if the parsed
475               object was a shared library  ***/
476         /* The above is not necessarily true...if the shared object was 
477          * compiled with -g then these will be filled in
478          */
479         if (!loaded_elf(fd, ptr, did_elf, elfp, ehdrp, phdrp, txtaddr,
480                             bssaddr, symscnp, strscnp, stabscnp, stabstrscnp,
481                             rel_plt_scnp, plt_scnp,got_scnp,dynsym_scnp, dynstr_scnp)) {
482                 /* throw exception */ goto cleanup2;
483         }
484
485         // find code and data segments....
486         find_code_and_data(ehdrp, phdrp, ptr, txtaddr, bssaddr);
487
488         Elf_Data* symdatap = elf_getdata(symscnp, 0);
489         Elf_Data* strdatap = elf_getdata(strscnp, 0);
490         if (!symdatap || !strdatap) {
491             log_elferror(err_func_, "locating symbol/string data");
492             /* throw exception */ goto cleanup2;
493         }
494
495         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
496         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
497         const char* strs   = (const char *) strdatap->d_buf;
498         string      module = "DEFAULT_MODULE";
499         string      name   = "DEFAULT_NAME";
500
501         // for shared objects add a module that is the file name
502         // and add all the global symbols as functions 
503         const char *libname = file_.string_of();
504         // find short name
505         const char *last = 0;
506         for(u_int i=0; i < file_.length();i++) {
507             if(libname[i] == '/'){
508                 last = (const char *)(&(libname[i]));
509                 // log_elferror(err_func_, P_strdup(last));
510             }
511         }
512         if(last){
513             module = (const char *)(last +1);  
514         }
515         else{
516             module = string("DEFAULT_MODULE");  
517         }
518         
519         // temporary vector of symbols
520         vector<Symbol> allsymbols;
521         
522         // try to resolve all symbols found in symbol table + 
523         //  enter them into <allsymbols>.
524         parse_symbols(allsymbols, syms, nsyms, strs, 1, \
525             module);
526
527         // Sort all the symbols - for patching symbol data sizes....
528         allsymbols.sort(symbol_compare);
529
530         // patch 0 symbol sizes....
531         fix_zero_function_sizes(allsymbols, 0);
532         
533         // override instances of weak symbols w/ instances of strong ones,
534         //  also currently has effect of making sure that symbols dont
535         //  extend beyond the marked beginning of the next symbo....
536         override_weak_symbols(allsymbols);
537
538         // and inset all found (and theoretically patched) symbols
539         //  into (data member) symbols_.
540         insert_symbols_shared(allsymbols);
541        
542         if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
543             if(!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) { 
544                 goto cleanup2;
545             }
546         }
547
548     }  /* try */
549
550     /* catch */
551
552 cleanup2: {
553         if (did_elf && (elf_end(elfp) != 0)) {
554             log_elferror(err_func_, "closing file");
555         }
556         if (did_open && (close(fd) == -1)) {
557             log_perror(err_func_, "close");
558         }
559     }
560 }
561
562
563 /*************************************************************
564 *
565 *  Run through symbol table <syms> (with <nsyms> entries, where
566 *   <strs> points to string table), finding all symbols
567 *   of type in {STT_FILE, STT_OBJECT, STT_FUNC, STT_NOTYPE}, and
568 *   registering the symbol in allsymbols with appropriate type,
569 *   scope, etc..
570 *   shared - indicates whether the object file being parsed is a
571 *    shared library.  
572 *   module - only filled in for shared libraries.  Contains name
573 *    of shared library module.  As per origional (spaghetti) code
574 *    scattered in old load_object && load_shared_object, the symbol
575 *    reference with the same name as the shared library itself
576 *    s stuffed directly itno (data member) symbols_ .... 
577 *
578 **************************************************************/
579 void Object::parse_symbols(vector<Symbol> &allsymbols, Elf32_Sym*  \
580         syms, unsigned nsyms, const char *strs, bool shared_library, \
581         string module) {
582
583     // local vars....
584     //  name of symbol, and name of module under which to register function,
585     //  respectively.... 
586     string name, module_name_used;
587     unsigned i1;
588
589     Symbol::SymbolType type;
590     Symbol::SymbolLinkage linkage;
591     int binding;
592
593     //cerr << "PARSING SYMBOLS FOR MODULE " << module << endl;
594     for (i1 = 0; i1 < nsyms; i1++) {
595         // First, we must check st_shndx. 
596         // if st_shndx == SHN_UNDEF, this is an undefined symbol,
597         // probably defined in a shared object that will be dynamically
598         // linked with the executable. We just ignore it for now.
599         if (syms[i1].st_shndx != SHN_UNDEF) {
600             name = string(&strs[syms[i1].st_name]);
601             //cerr << " Found non undefined symbol : " << name << endl;
602             bool st_kludge = false;
603             type = Symbol::PDST_UNKNOWN;
604             // resolve symbol type....
605             switch (type = ELF32_ST_TYPE(syms[i1].st_info)) {
606             case STT_FILE: {
607                 //cerr << "    name matches module name" << endl;
608                 type   = Symbol::PDST_MODULE;
609                 //cerr << "  ELF32_ST_TYPE = STT_FILE";
610                 break;
611             }
612             case STT_OBJECT:
613                 //cerr << "  ELF32_ST_TYPE = STT_OBJECT";
614                 type = Symbol::PDST_OBJECT;
615                 break;
616
617             case STT_FUNC:
618                 //cerr << "  ELF32_ST_TYPE = STT_FUNC";
619                 type = Symbol::PDST_FUNCTION;
620                 break;
621
622             case STT_NOTYPE:
623                 //cerr << "  ELF32_ST_TYPE = STT_NOTYPE";
624                 type = Symbol::PDST_NOTYPE;
625                 break;
626
627             default:
628                 //cerr << "  ELF32_ST_TYPE not supported";
629                 continue;
630             }
631
632             // and resolve symbol binding....
633             switch (binding = ELF32_ST_BIND(syms[i1].st_info)) {
634             case STB_LOCAL: 
635                 //cerr << "  ELF_32_ST_BIND = STB_LOCAL" << endl;
636                 linkage = Symbol::SL_LOCAL;
637                 break;
638             case STB_WEAK:
639                 //cerr << "  ELF_32_ST_BIND = STB_WEAK" << endl;
640                 linkage = Symbol::SL_WEAK;
641                 break;
642             case STB_GLOBAL: 
643                 //cerr << "  ELF_32_ST_BIND = STB_GLOBAL" << endl;
644                 linkage = Symbol::SL_GLOBAL;
645                 break;
646             default :
647                 //cerr << "  ELF_32_ST_BIND UNKNOWN!!!!" << endl;
648                 continue;
649             } 
650
651             // special case for shared libraries.  If the symbol
652             //  is of type file, and the binding is local binding, and
653             //  name matches the module name, then stick the symbol
654             //  directly into (data member) symbols_ (as SL_LOCAL).
655             if (type == STT_FILE && binding == STB_LOCAL && \
656                     name == module) {
657                 symbols_[name] = Symbol(name, module, type, linkage,
658                                     syms[i1].st_value, st_kludge, 
659                                     syms[i1].st_size);
660             } else {
661                 // otherwise, register found symbol under its name &&
662                 //  type....
663                 allsymbols += Symbol(name, module, 
664                                         type, linkage,
665                                         syms[i1].st_value, st_kludge,
666                                         syms[i1].st_size);
667             }
668         
669         }
670
671     }
672 }
673
674 /********************************************************
675  *
676  * Apparently, some compilers do not fill in the symbol sizes
677  *  correctly (in the symbol table) for functions.  Run through
678  *  symbol vector allsymbols, and compute ?correct? sizes....
679  * This patch to symbol sizes runs through allsymbols && tries
680  *  to patch all functions symbols recorded with a size of 0,
681  *  or which have been EEL overwritten.
682  * Assumes that allsymbols is sorted, with e.g. symbol_compare....
683  *
684 ********************************************************/
685 void Object::fix_zero_function_sizes(vector<Symbol> &allsymbols, bool EEL) {
686     unsigned u, v, nsymbols;
687
688     nsymbols = allsymbols.size();
689     for (u=0; u < nsymbols; u++) {
690         //  If function symbol, and size set to 0, or if the
691         //   executable has been EEL rewritten, patch the size
692         //   to the offset of next symbol - offset of this symbol....
693         if (allsymbols[u].type() == Symbol::PDST_FUNCTION
694                && (EEL || allsymbols[u].size() == 0)) {
695             v = u+1;
696             while (v < nsymbols && allsymbols[v].addr() == allsymbols[u].addr())
697                 v++;
698             if (v < nsymbols) {
699                 allsymbols[u].change_size((unsigned)allsymbols[v].addr()
700                                         - (unsigned)allsymbols[u].addr());
701             }
702         }
703     }
704 }
705
706 /********************************************************
707  *  
708  *  Run over list of symbols found in a SHARED LIBRARY ONLY -
709  *   Override weak AND LOCAL symbol references for which there is also
710  *   a global symbol reference, by setting the size on the weak
711  *   reference to 0.
712  *  Also potentially patches the size on such symbols (note that 
713  *   Object::fix_symbol_sizes (above) patches sizes on functions
714  *   recorded with a size of 0.  This fixes nonero sized functions
715  *   in the case where 2 functions follow eachother in the symbol
716  *   table, and the first has a size which would extend into the
717  *   second.  WHY IS THIS ONLY DONE FOR SHARED LIBRARIES.... 
718  *
719  *  Assumes that allsymbols is sorted, with e.g. symbol_compare....
720  *
721 ********************************************************/
722 void Object::override_weak_symbols(vector<Symbol> &allsymbols) {
723     unsigned i, nsymbols;
724     u_int next_start;
725     int next_size;
726     bool i_weak_or_local;
727     bool ip1_weak_or_local;
728
729     //cerr << "overriding weak symbols for which there is also a global symbol reference...." << endl;
730     nsymbols = allsymbols.size();
731     for (i=0; i < nsymbols; i++) {
732         if((allsymbols[i].type() == Symbol::PDST_FUNCTION)
733                 && (allsymbols[i+1].type() == Symbol::PDST_FUNCTION)) {
734
735             // where symbol i+1 should start, based on start of symbol i
736             //  and size of symbol i....
737             next_start=allsymbols[i].addr()+allsymbols[i].size();
738         
739             // do symbols i and i+1 have weak or local bindings....
740             i_weak_or_local = ((allsymbols[i].linkage() == Symbol::SL_WEAK) || \
741                                (allsymbols[i].linkage() == Symbol::SL_LOCAL));
742             ip1_weak_or_local = ((allsymbols[i+1].linkage() == Symbol::SL_WEAK) || \
743                                (allsymbols[i+1].linkage() == Symbol::SL_LOCAL));
744
745             // if the symbols have the same address and one is weak or local
746             // and the other is global keeep the global one
747             if((allsymbols[i].addr() == allsymbols[i+1].addr()) && 
748                     (((i_weak_or_local) &&
749                       (allsymbols[i+1].linkage() == Symbol::SL_GLOBAL)) || 
750                      ((allsymbols[i].linkage() == Symbol::SL_GLOBAL) &&
751                       (ip1_weak_or_local)))) {
752
753                 if (i_weak_or_local) {
754                     allsymbols[i].change_size(0);
755                     //cerr << " (type 1) removing symbol " << allsymbols[i];
756                 } else {
757                     allsymbols[i+1].change_size(0);
758                     //cerr << " (type 1) removing symbol " << allsymbols[i+1];
759                 }
760             }
761             // looks like may possibly need to patch size of symbol i
762             //  based on start of symbol i + 1????
763             else if (next_start > allsymbols[i+1].addr()) {
764                 next_size = allsymbols[i+1].addr() - allsymbols[i].addr();
765                 allsymbols[i].change_size(next_size);
766                   //cerr << " (type 2) changing symbol size of symbol " << \
767                   allsymbols[i] << "to size " << next_size << endl;
768             }
769         }
770     }
771 }
772
773 /********************************************************
774  *
775  * For object files only....
776  *  read the .stab section to find the module of global symbols
777  *
778 ********************************************************/
779 void Object::fix_global_symbol_modules_static( \
780         dictionary_hash<string, Symbol> global_symbols, \
781         Elf_Scn* stabscnp, Elf_Scn* stabstrscnp) {
782     // Read the stab section to find the module of global symbols.
783     // The symbols appear in the stab section by module. A module begins
784     // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
785     // All the symbols in between those two symbols belong to the module.
786
787     Elf_Data* stabdatap = elf_getdata(stabscnp, 0);
788     Elf_Data* stabstrdatap = elf_getdata(stabstrscnp, 0);
789     struct stab_entry *stabsyms = 0;
790     unsigned stab_nsyms;
791     const char *stabstrs = 0;
792     string module;
793
794     if (stabdatap && stabstrdatap) {
795         stabsyms = (struct stab_entry *) stabdatap->d_buf;
796         stab_nsyms = stabdatap->d_size / sizeof(struct stab_entry);
797         stabstrs = (const char *) stabstrdatap->d_buf;
798     }
799     else 
800         stab_nsyms = 0;
801
802     // the stabstr contains one string table for each module.
803     // stabstr_offset gives the offset from the begining of stabstr of the
804     // string table for the current module.
805     // stabstr_nextoffset gives the offset for the next module.
806     unsigned stabstr_offset = 0;
807     unsigned stabstr_nextoffset = 0;
808
809     bool is_fortran = false;  // is the current module fortran code?
810     /* we must know if we are reading a fortran module because fortran
811        symbol names are different in the .stab and .symtab sections.
812        A symbol that appears as 'foo' in the .stab section, appears
813        as 'foo_' in .symtab.
814      */
815     module = "";
816   
817     for (unsigned i = 0; i < stab_nsyms; i++) {
818         switch(stabsyms[i].type) {
819         case N_UNDF: /* start of object file */
820             assert(stabsyms[i].name == 1);
821             stabstr_offset = stabstr_nextoffset;
822             // stabsyms[i].val has the size of the string table of this module.
823             // We use this value to compute the offset of the next string table.
824             stabstr_nextoffset = stabstr_offset + stabsyms[i].val;
825             module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
826             break;
827
828         case N_ENDM: /* end of object file */
829             is_fortran = false;
830             module = "";
831             break;
832
833         case N_SO: /* compilation source or file name */
834             if (stabsyms[i].desc == N_SO_FORTRAN)
835               is_fortran = true;
836
837             module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
838             break;
839
840         case N_ENTRY: /* fortran alternate subroutine entry point */
841         case N_FUN: /* function */
842         case N_GSYM: /* global symbol */
843             // the name string of a function or object appears in the stab string table
844             // as <symbol name>:<symbol descriptor><other stuff>
845             // where <symbol descriptor> is a one char code.
846             // we must extract the name and descriptor from the string
847           {
848             const char *p = &stabstrs[stabstr_offset+stabsyms[i].name];
849             const char *q = strchr(p,':');
850             assert(q);
851             unsigned len = q - p;
852             assert(len > 0);
853             char *sname = new char[len+1];
854             strncpy(sname, p, len);
855             sname[len] = 0;
856             
857             // q points to the ':' in the name string, so 
858             // q[1] is the symbol descriptor. We must check the symbol descriptor
859             // here to skip things we are not interested in, such as local functions
860             // and prototypes.
861             if (q[1] == SD_GLOBAL_FUN || q[1] == SD_GLOBAL_VAR || stabsyms[i].type==N_ENTRY) { 
862                 string SymName = string(sname);
863                 bool res = global_symbols.defines(SymName);
864                 if (!res && is_fortran) {
865                     // Fortran symbols usually appear with an '_' appended in .symtab,
866                     // but not on .stab
867                     SymName += "_";
868                     res = global_symbols.defines(SymName);
869                 }
870
871                 if (!res) break;
872 //              assert(res); // All globals in .stab should be defined in .symtab
873
874                 Symbol sym = global_symbols[SymName];
875                 symbols_[SymName] = Symbol(sym.name(), module, \
876                     sym.type(), sym.linkage(), sym.addr(), \
877                     sym.kludge(), sym.size());
878             }
879           }
880           break;
881
882         default:
883             /* ignore other entries */
884             break;
885         }
886     }
887
888     /* The remaing symbols go without module */
889     vector<string> k = global_symbols.keys();
890     for (unsigned i2 = 0; i2 < k.size(); i2++) {
891         Symbol sym = global_symbols[k[i2]];
892         if (!(symbols_.defines(sym.name())))
893             symbols_[sym.name()] = sym;
894     }
895 }
896
897 /********************************************************
898  *
899  * Run over allsymbols, and stuff symbols contained according 
900  *  to following rules:
901  * LOCAL symbols - into (data member) symbols_
902  * GLOBAL symbols - into (paramater) global_symbols
903  * WEAK symbols - looks like this case isnt handled correctly
904  *  for static libraries....
905  *
906 ********************************************************/
907 void Object::insert_symbols_static(vector<Symbol> allsymbols, \
908         dictionary_hash<string, Symbol> &global_symbols) {
909     unsigned u, nsymbols = allsymbols.size();
910
911     for (u=0;u<nsymbols;u++) {
912         // We are done with the local symbols. We save the global so that
913         // we can get their module from the .stab section.
914         if (allsymbols[u].linkage() == Symbol::SL_LOCAL)
915             symbols_[allsymbols[u].name()] = allsymbols[u];
916         else {
917             // globals should be unique
918             assert(!(global_symbols.defines(allsymbols[u].name()))); 
919             global_symbols[allsymbols[u].name()] = allsymbols[u];
920         }
921     }    
922 }
923
924 /********************************************************
925  *
926  * Run over allsymbols, and stuff symbols it contains into (data
927  *  member) symbols_. 
928  *
929  * Assumes that all kludges, patches, fixes, hacks, to objects
930  *  in allsymbols have already been made, and that it safe to
931  *  dump them into symbols_ (data member, instead of stack var....)....
932  *
933 ********************************************************/
934 void Object::insert_symbols_shared(vector<Symbol> allsymbols) {
935     unsigned i, nsymbols;
936
937     nsymbols = allsymbols.size();
938     for (i=0;i<nsymbols;i++) {
939         symbols_[allsymbols[i].name()] =
940                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
941                     allsymbols[i].type(), allsymbols[i].linkage(),
942                     allsymbols[i].addr(), allsymbols[i].kludge(),
943                     allsymbols[i].size());
944     }
945 }
946
947 /*********************************************************
948  *
949  * Object::find_code_and_data - find addressm offset, and
950  *  length of code and data sections of file described
951  *  by ehdrp && phdrp.
952  *
953  * fills in (data members) code_ptr_, code_off_, code_len_,
954  *  data_ptr_, data_off_, data_len_.  As per origional code
955  *  of which this is a severely cleaned up version, does not
956  *  check here for success or failure.
957  *
958  * mcheyney - 970904
959  *
960 *********************************************************/
961 void Object::find_code_and_data(Elf32_Ehdr* ehdrp, Elf32_Phdr* phdrp, \
962         char *ptr, unsigned txtaddr, unsigned bssaddr) {
963     unsigned i0;
964   
965     for (i0 = 0; i0 < ehdrp-> e_phnum;i0++) {
966         if ((phdrp[i0].p_vaddr <= txtaddr)
967                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
968             if (code_ptr_ == 0 && code_off_ == 0 && code_len_ == 0) {
969                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
970                 code_off_ = (Address) phdrp[i0].p_vaddr;
971                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
972             }
973
974         }
975         else if ((phdrp[i0].p_vaddr <= bssaddr)
976                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
977           if (data_ptr_ == 0 && data_off_ == 0 && data_len_ == 0) {
978                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
979                 data_off_ = (Address) phdrp[i0].p_vaddr;
980                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
981           }
982         }
983     }
984 }
985
986 Object::Object(const string file, void (*err_func)(const char *))
987     : AObject(file, err_func), EEL(false) {
988     load_object();
989     //dump_state_info(cerr);
990 }
991
992 Object::Object(const string file, u_int ,void (*err_func)(const char *))
993     : AObject(file, err_func), EEL(false)  {
994     load_shared_object();
995     //dump_state_info(cerr);
996 }
997
998 Object::Object(const Object& obj)
999     : AObject(obj), EEL(false) {
1000     load_object();
1001 }
1002
1003 inline bool Object::get_func_binding_table(vector<relocationEntry> &fbt) const {
1004     if(!plt_addr_ || (!relocation_table_.size())) return false;
1005     fbt = relocation_table_;
1006     return true;
1007 }
1008
1009 inline bool Object::get_func_binding_table_ptr(const vector<relocationEntry> *&fbt) const {
1010     if(!plt_addr_ || (!relocation_table_.size())) return false;
1011     fbt = &relocation_table_;
1012     return true;
1013 }
1014
1015 /**************************************************
1016  *
1017  *  Stream based debuggering output - for resgreesion testing.
1018  *  Dump info on state of object *this....
1019  *
1020 **************************************************/
1021
1022 const ostream &Object::dump_state_info(ostream &s) {
1023     unsigned i;
1024
1025     s << "Debugging Information for Object (address) : " << this << endl;
1026
1027     s << " <<begin debugging info for base object>>" << endl;
1028     AObject::dump_state_info(s);
1029     s << " <<end debuggingo info for base object>>" << endl;
1030
1031     s << " plt_addr_ = " << plt_addr_ << endl;
1032     s << " plt_size_ = " << plt_size_ << endl;
1033     s << " plt_entry_size_ = " << plt_entry_size_ << endl;
1034     s << " get_addr_ = " << got_addr_ << endl;
1035     s << " rel_plt_addr_ = " << rel_plt_addr_ << endl; 
1036     s << " rel_plt_size_ = " << rel_plt_size_ << endl;
1037     s << " rel_plt_entry_size_ = " << rel_plt_entry_size_ << endl;
1038     s << " dyn_sym_addr_ = " << dyn_sym_addr_ << endl;
1039     s << " dyn_str_addr_ = " << dyn_str_addr_ << endl;
1040
1041     // and dump the relocation table....
1042     s << " relocation_table_ = (field seperator :: )" << endl;   
1043     for (i=0;i<relocation_table_.size();i++) {
1044         s << relocation_table_[i] << " :: "; 
1045     }
1046     s << endl;
1047
1048     return s;
1049
1050
1051 #endif  /* #ifdef Object_elf32_h_ */
1052