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