various fixes made when working with older gcc 3.2.3
[dyninst.git] / symtabAPI / src / Object-elf.C
1 /*
2  * Copyright (c) 1996-2007 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 /************************************************************************
33  * $Id: Object-elf.C,v 1.54 2008/11/03 15:19:25 jaw Exp $
34  * Object-elf.C: Object class for ELF file format
35  ************************************************************************/
36
37 #include "symtabAPI/src/Object.h"
38 #include "symtabAPI/h/Symtab.h"
39
40 #include "emitElf.h"
41 #include "Module.h"
42
43 #if defined(x86_64_unknown_linux2_4) || defined(ia64_unknown_linux2_4) || defined(ppc64_linux)
44 #include "emitElf-64.h"
45 #endif
46
47 using namespace Dyninst;
48 using namespace Dyninst::SymtabAPI;
49 using namespace std;
50
51 #if !defined(_Object_elf_h_)
52 #error "Object-elf.h not #included"
53 #endif
54
55 #include <elf.h>
56 #include <stdio.h>
57 #include <algorithm>
58
59 #if defined(USES_DWARF_DEBUG)
60 #include "dwarf.h"
61 #include "libdwarf.h"
62 #endif
63
64 //#include "symutil.h"
65 #include "common/h/pathName.h"
66 #include "Collections.h"
67 #if defined(TIMED_PARSE)
68 #include <sys/time.h>
69 #endif
70 #include <iostream>
71 #include <iomanip>
72
73 #include <fstream>
74 #include <sys/stat.h>
75 #include <boost/crc.hpp>
76 #include <boost/assign/list_of.hpp>
77 #include <boost/assign/std/set.hpp>
78 #include <boost/assign/std/vector.hpp>
79
80 using boost::crc_32_type;
81 using namespace boost::assign;
82
83 #include <libgen.h>
84
85 // add some space to avoid looking for functions in data regions
86 #define EXTRA_SPACE 8
87
88 bool Object::truncateLineFilenames = true;
89 #if defined(os_linux) && (defined(arch_x86) || defined(arch_x86_64))
90 static bool find_catch_blocks(Elf_X &elf, Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
91                               Address txtaddr, Address dataaddr,
92                               std::vector<ExceptionBlock> &catch_addrs);
93 #endif
94     
95 #ifdef BINEDIT_DEBUG
96 bool ____sym_hdr_printed = false;
97 void print_symbols( std::vector< Symbol *>& allsymbols ) {
98     FILE* fd = stdout;
99     Symbol *sym;
100     std::string modname;
101     if (!____sym_hdr_printed) {
102         fprintf(fd, "%-20s  %-15s  %-10s  %5s  SEC  TYP  LN\n", 
103                 "SYMBOL", "MODULE", "ADDR", "SIZE");
104         ____sym_hdr_printed = true;
105     }
106     for (unsigned i=0; i<allsymbols.size(); i++) {
107         sym = allsymbols[i];
108         modname = sym->getModuleName();
109         //if (modname == "libspecial.so" || modname == "libprofile.so") {
110         //if (sym->getLinkage() == Symbol::SL_WEAK) {
111         if (1) {
112             fprintf(fd, "%-20s  %-15s  0x%08lx  %5lu  %3u", 
113                 sym->getName().substr(0,20).c_str(), 
114                 modname.size() > 15 ? modname.substr(modname.size()-15,15).c_str() : modname.c_str(),
115                 (unsigned)sym->getAddr(),
116                 (unsigned)sym->getSize(),
117                 sym->getSec() ? sym->getSec()->getRegionNumber() : 0
118                 );
119             switch (sym->getType()) {
120                 case Symbol::ST_UNKNOWN:  fprintf(fd, "  ???"); break;
121                 case Symbol::ST_FUNCTION: fprintf(fd, "  FUN"); break;
122                 case Symbol::ST_OBJECT:   fprintf(fd, "  OBJ"); break;
123                 case Symbol::ST_MODULE:   fprintf(fd, "  MOD"); break;
124                 case Symbol::ST_NOTYPE:   fprintf(fd, "   - "); break;
125             }
126             switch (sym->getLinkage()) {
127                 case Symbol::SL_UNKNOWN: fprintf(fd, "  ??"); break;
128                 case Symbol::SL_GLOBAL:  fprintf(fd, "  GL"); break;
129                 case Symbol::SL_LOCAL:   fprintf(fd, "  LO"); break;
130                 case Symbol::SL_WEAK:    fprintf(fd, "  WK"); break;
131             }
132             fprintf(fd,"\n");
133         }
134     }
135 }
136 #endif
137
138 string symt_current_func_name;
139 string symt_current_mangled_func_name;
140 Symbol *symt_current_func = NULL;
141
142 #if defined(os_solaris)
143 #include <dlfcn.h>
144 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
145
146 int (*P_native_demangle)(const char *, char *, size_t);
147
148 void loadNativeDemangler() {
149
150     P_native_demangle = NULL;
151     void *hDemangler = dlopen("libdemangle.so", DLOPEN_MODE);
152     if (hDemangler != NULL)
153         P_native_demangle = (int (*) (const char *, char *, size_t))
154     dlsym(hDemangler, "cplus_demangle");
155 }
156                 
157 #endif
158
159 void (*dwarf_err_func)(const char *);   // error callback for dwarf errors
160
161 static bool pdelf_check_ehdr(Elf_X &elf)
162 {
163     // Elf header integrity check
164     return ((elf.e_type() == ET_EXEC || elf.e_type() == ET_DYN) &&
165             (elf.e_phoff() != 0) && (elf.e_shoff() != 0) &&
166             (elf.e_phnum() != 0) && (elf.e_shnum() != 0)) ;
167 }
168
169 const char *pdelf_get_shnames(Elf_X &elf)
170 {
171     const char *result = NULL;
172     size_t shstrndx = elf.e_shstrndx();
173
174     Elf_X_Shdr shstrscn = elf.get_shdr(shstrndx);
175     if (shstrscn.isValid()) {
176         Elf_X_Data shstrdata = shstrscn.get_data();
177         if (shstrdata.isValid())
178             result = shstrdata.get_string();
179     }
180     return result;
181 }
182
183 //
184 // SectionHeaderSortFunction
185 // 
186 // Compare function for use with the Vector<T> sort method.
187 //
188 struct  SectionHeaderSortFunction: public binary_function<Elf_X_Shdr *, Elf_X_Shdr *, bool> 
189 {
190         bool operator()(Elf_X_Shdr *hdr1, Elf_X_Shdr *hdr2) {
191                 return (hdr1->sh_addr() < hdr2->sh_addr()); 
192         }
193 };
194
195 Region::perm_t getSegmentPerms(unsigned long flags){
196     if(flags == 7)
197         return Region::RP_RWX;
198     else if(flags == 6)
199         return Region::RP_RW;
200     else if(flags == 5)
201         return Region::RP_RX;
202     else
203         return Region::RP_R;
204 }
205
206 Region::RegionType getSegmentType(unsigned long type, unsigned long flags)
207 {
208     if(type == PT_DYNAMIC)
209         return Region::RT_DYNAMIC;
210     if(flags == 7)
211         return Region::RT_TEXTDATA;
212     if(flags == 5)
213         return Region::RT_TEXT;
214     if(flags == 6)
215         return Region::RT_DATA;
216     return Region::RT_OTHER;
217 }
218
219 /* binary search to find the section starting at a particular address */
220 Elf_X_Shdr *Object::getRegionHdrByAddr(Offset addr) 
221 {
222     unsigned end = allRegionHdrs.size() - 1, start = 0;
223     unsigned mid = 0; 
224     while(start < end) {
225         mid = start + (end-start)/2;
226         if(allRegionHdrs[mid]->sh_addr() == addr)
227             return allRegionHdrs[mid];
228         else if(allRegionHdrs[mid]->sh_addr() < addr)
229             start = mid + 1;
230         else
231             end = mid;
232     }
233     if(allRegionHdrs[start]->sh_addr() == addr)
234         return allRegionHdrs[start];
235     return NULL;
236 }
237
238 /* Check if there is a section which belongs to the segment and update permissions of that section.
239  * Return value indicates whether the segment has to be added to the list of regions*/
240
241 bool Object::isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned segPerms){
242     bool present = false;
243     for(unsigned i = 0; i < regions_.size() ;i++){
244         if((regions_[i]->getRegionAddr() >= segmentStart) && ((regions_[i]->getRegionAddr()+regions_[i]->getRegionSize()) <= (segmentStart+segmentSize))){
245             present = true;
246             regions_[i]->setRegionPermissions(getSegmentPerms(segPerms));
247         }
248
249     }
250     return present;
251 }
252
253 Region::perm_t getRegionPerms(unsigned long flags){
254     if((flags & SHF_WRITE) && !(flags & SHF_EXECINSTR))
255         return Region::RP_RW;
256     else if(!(flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
257         return Region::RP_RX;
258     else if((flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
259         return Region::RP_RWX;
260     else
261         return Region::RP_R;
262 }
263
264 Region::RegionType getRegionType(unsigned long type, unsigned long flags){
265     switch(type){
266         case SHT_SYMTAB:
267         case SHT_DYNSYM:
268             return Region::RT_SYMTAB;
269         case SHT_STRTAB:
270             return Region::RT_STRTAB;
271         case SHT_REL:
272             return Region::RT_REL;
273         case SHT_RELA:
274             return Region::RT_RELA;
275         case SHT_PROGBITS:
276             if((flags & SHF_EXECINSTR) && (flags & SHF_WRITE))
277                 return Region::RT_TEXTDATA;
278             else if(flags & SHF_EXECINSTR)
279                 return Region::RT_TEXT;
280             else
281                 return Region::RT_DATA;
282         case SHT_DYNAMIC:
283             return Region::RT_DYNAMIC;
284 #if !defined(os_solaris)            
285         case SHT_GNU_versym:
286             return Region::RT_SYMVERSIONS;
287         case SHT_GNU_verdef:
288             return Region::RT_SYMVERDEF;
289         case SHT_GNU_verneed:
290             return Region::RT_SYMVERNEEDED;
291 #endif
292         default:
293             return Region::RT_OTHER;
294     }
295 }
296
297 const char* EDITED_TEXT_NAME = ".edited.text";
298 // const char* INIT_NAME        = ".init";
299 const char *INTERP_NAME      = ".interp";
300 const char* FINI_NAME        = ".fini";
301 const char* TEXT_NAME        = ".text";
302 const char* BSS_NAME         = ".bss";
303 const char* SYMTAB_NAME      = ".symtab";
304 const char* STRTAB_NAME      = ".strtab";
305 const char* STAB_NAME        = ".stab";
306 const char* STABSTR_NAME     = ".stabstr";
307 const char* STAB_INDX_NAME   = ".stab.index";
308 const char* STABSTR_INDX_NAME= ".stab.indexstr";
309 // sections from dynamic executables and shared objects
310 const char* PLT_NAME         = ".plt";
311 #if ! defined( arch_ia64 )
312 const char* REL_PLT_NAME     = ".rela.plt"; // sparc-solaris
313 #else  
314 const char* REL_PLT_NAME     = ".rela.IA_64.pltoff";
315 #endif  
316 const char* REL_PLT_NAME2    = ".rel.plt";  // x86-solaris
317 const char* GOT_NAME         = ".got";
318 const char* DYNSYM_NAME      = ".dynsym";
319 const char* DYNSTR_NAME      = ".dynstr";
320 const char* DATA_NAME        = ".data";
321 const char* RO_DATA_NAME     = ".ro_data";  // mips
322 const char* DYNAMIC_NAME     = ".dynamic";
323 const char* EH_FRAME_NAME    = ".eh_frame";
324 const char* EXCEPT_NAME      = ".gcc_except_table";
325 const char* EXCEPT_NAME_ALT  = ".except_table";
326 const char* DEBUGLINK_NAME   = ".gnu_debuglink";
327 const char* BUILD_ID_NAME    = ".note.gnu.build-id";
328
329 set<string> debugInfoSections = list_of(string(SYMTAB_NAME))
330                                        (string(STRTAB_NAME));
331
332 // loaded_elf(): populate elf section pointers
333 // for EEL rewritten code, also populate "code_*_" members
334 bool Object::loaded_elf(Offset& txtaddr, Offset& dataddr,
335       Elf_X_Shdr*& symscnp, Elf_X_Shdr*& strscnp, 
336       Elf_X_Shdr*& stabscnp, Elf_X_Shdr*& stabstrscnp, 
337       Elf_X_Shdr*& stabs_indxcnp, Elf_X_Shdr*& stabstrs_indxcnp, 
338       Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
339       Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
340       Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr* &dynamic_scnp, Elf_X_Shdr*& eh_frame, 
341       Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp, bool
342 #if defined(os_irix)
343       a_out  // variable not used on other platforms
344 #endif
345       )
346 {
347    dwarf_err_func  = err_func_;
348    entryAddress_ = elfHdr.e_entry();
349
350    no_of_sections_ = elfHdr.e_shnum();
351
352    // ".shstrtab" section: string table for section header names
353    const char *shnames = pdelf_get_shnames(elfHdr);
354    if (shnames == NULL) {
355       fprintf(stderr, "[%s][%d]WARNING: .shstrtab section not found in ELF binary\n",__FILE__,__LINE__);
356       log_elferror(err_func_, ".shstrtab section");
357       //return false;
358    }
359
360    // initialize Object members
361
362    text_addr_ = 0; //ccw 23 jan 2002
363    text_size_ = 0; //for determining if a mutation
364    //falls within the text section 
365    //of a shared library
366
367    dynamic_addr_ = 0;
368    dynsym_addr_ = 0;
369    dynstr_addr_ = 0;
370    fini_addr_ = 0;
371    got_addr_ = 0;
372    got_size_ = 0;
373    plt_addr_ = 0;
374    plt_size_ = 0;
375 #if defined (ppc32_linux)
376    plt_entry_size_ = 8;
377    rel_plt_entry_size_ = 8;
378 #else
379    plt_entry_size_ = 0;
380    rel_plt_entry_size_ = 0;
381 #endif
382    rel_plt_addr_ = 0;
383    rel_plt_size_ = 0;
384    rel_size_ = 0;
385    rel_entry_size_ = 0;
386    stab_off_ = 0;
387    stab_size_ = 0;
388    stabstr_off_ = 0;
389    stab_indx_off_ = 0;
390    stab_indx_size_ = 0;
391    stabstr_indx_off_ = 0;
392 #if defined(os_irix)
393    MIPS_stubs_addr_ = 0;
394    MIPS_stubs_off_ = 0;
395    MIPS_stubs_size_ = 0;
396    got_zero_index_ = -1;
397    dynsym_zero_index_ = -1;
398 #endif
399    dwarvenDebugInfo = false;
400
401    txtaddr = 0;
402
403    set<string> sectionsInOriginalBinary;
404    bool debugInfoValid = true;
405
406    if(mfForDebugInfo->getFD() != -1)
407       elfHdrForDebugInfo = Elf_X(mfForDebugInfo->getFD(), ELF_C_READ);
408    else
409       elfHdrForDebugInfo = Elf_X((char *)mfForDebugInfo->base_addr(), mfForDebugInfo->size());
410    if(!elfHdrForDebugInfo.isValid()) {
411       log_elferror(err_func_, "Elf header");
412       fprintf(stderr, "%s[%d]:  failing to parse line info due to elf prob\n", FILE__, __LINE__);
413       debugInfoValid = false;
414    }
415    else if(!pdelf_check_ehdr(elfHdrForDebugInfo)) {
416       fprintf(stderr, "%s[%d]:  Warning: Elf ehdr failed integrity check\n", FILE__, __LINE__);
417       log_elferror(err_func_, "ELF header failed integrity check");
418       debugInfoValid = false;
419    }
420
421
422    const char *shnamesForDebugInfo = pdelf_get_shnames(elfHdrForDebugInfo);
423    if (shnamesForDebugInfo == NULL) {
424       fprintf(stderr, "[%s][%d]WARNING: .shstrtab section not found in ELF binary\n",__FILE__,__LINE__);
425       log_elferror(err_func_, ".shstrtab section");
426       //return false;
427    }
428
429 #if defined(TIMED_PARSE)
430    struct timeval starttime;
431    gettimeofday(&starttime, NULL);
432 #endif
433
434    Elf_X_Shdr *scnp;
435
436    for (int i = 0; i < elfHdr.e_shnum() + elfHdrForDebugInfo.e_shnum(); ++i) {
437       const char *name;
438
439       if(i < elfHdr.e_shnum()) {
440          scnp = new Elf_X_Shdr( elfHdr.get_shdr(i) );
441          if (! scnp->isValid()) { // section is malformed
442             continue; 
443          } 
444          name = &shnames[scnp->sh_name()];
445          sectionsInOriginalBinary.insert(string(name));
446       }
447       else {
448          if(!debugInfoValid || mfForDebugInfo == mf || hasDwarfInfo())
449             break;
450          scnp = new Elf_X_Shdr(elfHdrForDebugInfo.get_shdr(i - elfHdr.e_shnum()));
451          if(! scnp->isValid()) {
452             continue;
453          }
454          name = &shnamesForDebugInfo[scnp->sh_name()];
455
456          if(debugInfoSections.count(name) == 0)
457             continue;
458          // if(sectionsInOriginalBinary.count(name) > 0)
459          //    continue;
460       }
461
462       allRegionHdrs.push_back( scnp );
463
464       // resolve section name
465
466       //If the section appears in the memory image of a process address is given by sh_addr()
467       //otherwise this is zero and sh_offset() gives the offset to the first byte in section.
468       if(scnp->sh_flags() & SHF_ALLOC)
469           regions_.push_back(new Region(i, name, scnp->sh_addr(), scnp->sh_size(), scnp->sh_addr(), scnp->sh_size(), (mem_image()+scnp->sh_offset()), getRegionPerms(scnp->sh_flags()), getRegionType(scnp->sh_type(), scnp->sh_flags())));
470       else
471           regions_.push_back(new Region(i, name, scnp->sh_addr(), scnp->sh_size(), 0, 0, (mem_image()+scnp->sh_offset()), getRegionPerms(scnp->sh_flags()), getRegionType(scnp->sh_type(), scnp->sh_flags())));
472 //      sections_.push_back(new Region(i, name, scnp->sh_addr(), scnp->sh_size(),(void *)(mem_image()+scnp->sh_offset()), scnp->sh_flags(), scnp->sh_flags() & SHF_EXECINSTR));
473       /*
474          if(scnp->sh_addr() != 0)
475          sections_.push_back(new Region(i, name, scnp->sh_addr(), scnp->sh_size()));
476          else   
477          sections_.push_back(new Region(i, name, scnp->sh_offset(), scnp->sh_size()));
478        */
479       // section-specific processing
480       if (P_strcmp(name, EDITED_TEXT_NAME) == 0) {
481          // EEL rewritten executable
482          EEL = true;
483          if (txtaddr == 0)
484             txtaddr = scnp->sh_addr();
485          char *file_ptr = (char *)mf->base_addr();
486          code_ptr_ = (char *)(void*)&file_ptr[scnp->sh_offset() - EXTRA_SPACE];
487          code_off_ = scnp->sh_addr() - EXTRA_SPACE;
488          code_len_ = scnp->sh_size() + EXTRA_SPACE;
489       }
490       if (strcmp(name, TEXT_NAME) == 0) {
491          text_addr_ = scnp->sh_addr();
492          text_size_ = scnp->sh_size();
493
494          if (txtaddr == 0)
495             txtaddr = scnp->sh_addr();
496       }
497       /* The following sections help us find the PH entry that
498          encompasses the data region. */
499       else if (strcmp(name, DATA_NAME) == 0) {
500          dataddr = scnp->sh_addr();
501       }
502       else if (strcmp(name, RO_DATA_NAME) == 0) {
503          if (!dataddr) dataddr = scnp->sh_addr();
504       }
505       else if (strcmp(name, GOT_NAME) == 0) {
506          got_scnp = scnp;
507          got_addr_ = scnp->sh_addr();
508          got_size_ = scnp->sh_size();
509          if (!dataddr) dataddr = scnp->sh_addr();
510       }
511       else if (strcmp(name, BSS_NAME) == 0) {
512          if (!dataddr) dataddr = scnp->sh_addr();
513       }
514       /* End data region search */
515       else if (strcmp( name, FINI_NAME) == 0) {
516          fini_addr_ = scnp->sh_addr();
517       }
518       else if (strcmp(name, SYMTAB_NAME) == 0) {
519          symscnp = scnp;
520       }
521       else if (strcmp(name, STRTAB_NAME) == 0) {
522          strscnp = scnp;
523       } else if (strcmp(name, STAB_INDX_NAME) == 0) {
524          stabs_indxcnp = scnp;
525          stab_indx_off_ = scnp->sh_offset();
526          stab_indx_size_ = scnp->sh_size();
527       } else if (strcmp(name, STABSTR_INDX_NAME) == 0) {
528          stabstrs_indxcnp = scnp;
529          stabstr_indx_off_ = scnp->sh_offset();
530       } else if (strcmp(name, STAB_NAME) == 0) {
531          stabscnp = scnp;
532          stab_off_ = scnp->sh_offset();
533          stab_size_ = scnp->sh_size();
534       } else if (strcmp(name, STABSTR_NAME) == 0) {
535          stabstrscnp = scnp;
536          stabstr_off_ = scnp->sh_offset();
537       } else if ((strcmp(name, REL_PLT_NAME) == 0) || 
538             (strcmp(name, REL_PLT_NAME2) == 0)) {
539          rel_plt_scnp = scnp;
540          rel_plt_addr_ = scnp->sh_addr();
541          rel_plt_size_ = scnp->sh_size();
542          rel_plt_entry_size_ = scnp->sh_entsize();
543       }
544       else if (strcmp(name, PLT_NAME) == 0) {
545          plt_scnp = scnp;
546          plt_addr_ = scnp->sh_addr();
547          plt_size_ = scnp->sh_size();
548 #if defined(arch_x86)
549          //
550          // On x86, the GNU linker purposefully sets the PLT
551          // table entry size to an incorrect value to be
552          // compatible with the UnixWare linker.  (See the comment
553          // in the elf_i386_finish_dynamic_sections function of
554          // the BFD library.)  The GNU linker sets this value to 4,
555          // when it should be 16.
556          //
557          // I see no good way to determine this value from the
558          // ELF section header information.  We can either (a) hard-code
559          // the value that is used in the BFD library, or (b) compute
560          // it by dividing the size of the PLT by the number of entries
561          // we think should be in the PLT.  I'm not certain, but I
562          // believe the PLT and the .rel.plt section should have the
563          // same number of "real" entries (the x86 PLT has one extra entry
564          // at the beginning).
565          // 
566          // This code is applicable to any x86 system that uses the
567          // GNU linker.  We currently only support Linux on x86 - if
568          // we start supporting some other x86 OS that uses the GNU
569          // linker in the future, it should be enabled for that platform as well.
570          // Note that this problem does not affect the non-x86 platforms
571          // that might use the GNU linker.  For example, programs linked
572          // with gld on SPARC Solaris have the correct PLT entry size.
573          //
574          // Another potential headache in the future is if we support
575          // some other x86 platform that has both the GNU linker and
576             // some other linker.  (Does BSD fall into this category?)
577             // If the two linkers set the entry size differently, we may
578             // need to re-evaluate this code.
579             //
580             plt_entry_size_ = plt_size_ / ((rel_plt_size_ / rel_plt_entry_size_) + 1);
581             assert( plt_entry_size_ == 16 );
582 #else
583
584             plt_entry_size_ = scnp->sh_entsize();
585 #if defined (ppc32_linux)
586        if (!plt_entry_size_)
587           plt_entry_size_ = 8;
588        else {
589           if (plt_entry_size_ != 8) 
590              fprintf(stderr, "%s[%d]:  weird plt_entry_size_ is %d, not 8\n", 
591                    FILE__, __LINE__, plt_entry_size_);
592        }
593 #endif
594 #endif
595         }
596         else if (strcmp(name, DYNSYM_NAME) == 0) {
597         is_dynamic_ = true;
598             dynsym_scnp = scnp;
599             dynsym_addr_ = scnp->sh_addr();
600         }
601         else if (strcmp(name, DYNSTR_NAME) == 0) {
602             dynstr_scnp = scnp;
603             dynstr_addr_ = scnp->sh_addr();
604         }
605         else if (strcmp(name, ".debug_info") == 0) {
606             dwarvenDebugInfo = true;
607         }
608         else if (strcmp(name, EH_FRAME_NAME) == 0) {
609             eh_frame = scnp;
610         }
611         else if ((strcmp(name, EXCEPT_NAME) == 0) || 
612             (strcmp(name, EXCEPT_NAME_ALT) == 0)) {
613             gcc_except = scnp;
614         }
615    else if (strcmp(name, INTERP_NAME) == 0) {
616       interp_scnp = scnp;
617    }
618 //TODO clean up this. it is ugly
619 #if defined(arch_ia64)
620         else if (strcmp(name, DYNAMIC_NAME) == 0) {
621         dynamic_scnp = scnp;
622         dynamic_addr_ = scnp->sh_addr();
623             Elf_X_Data data = scnp->get_data();
624             Elf_X_Dyn dyns = data.get_dyn();
625             for (unsigned i = 0; i < dyns.count(); ++i) {
626                 switch(dyns.d_tag(i)) {
627                 case DT_PLTGOT:
628                         this->gp = dyns.d_ptr(i);
629                              ///* DEBUG */ fprintf( stderr, "%s[%d]: GP = 0x%lx\n", __FILE__, __LINE__, this->gp );
630                             break;
631     
632                         default:
633                             break;
634                 } // switch
635         } // for
636         }
637 #else
638         else if (strcmp(name, DYNAMIC_NAME) == 0) {
639         dynamic_scnp = scnp;
640             dynamic_addr_ = scnp->sh_addr();
641         }
642 #endif /* ia64_unknown_linux2_4 */
643     }
644
645     if(!symscnp || !strscnp) {
646         isStripped = true;
647             if(dynsym_scnp && dynstr_scnp){
648                 symscnp = dynsym_scnp;
649                 strscnp = dynstr_scnp;
650             }
651     }
652
653     loadAddress_ = 0x0;
654 #if defined(os_linux)
655     /**
656      * If the virtual address of the first PT_LOAD element in the
657      * program table is 0, Linux loads the shared object into any
658      * free spot into the address space.  If the virtual address is
659      * non-zero, it gets loaded only at that address.
660      **/
661     for (unsigned i = 0; i < elfHdr.e_phnum() && !loadAddress_; ++i) {
662         Elf_X_Phdr phdr = elfHdr.get_phdr(i);
663
664         if (phdr.p_type() == PT_LOAD) {
665             loadAddress_ = phdr.p_vaddr();
666             break;
667         }
668     }
669 #endif  
670   
671
672   // sort the section headers by base address
673   //allRegionHdrs.sort( SectionHeaderSortFunction );
674   sort(allRegionHdrs.begin(), allRegionHdrs.end(), SectionHeaderSortFunction());
675 #if defined(TIMED_PARSE)
676   struct timeval endtime;
677   gettimeofday(&endtime, NULL);
678   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
679   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
680   unsigned long difftime = lendtime - lstarttime;
681   double dursecs = difftime/(1000 );
682   cout << "main loop of loaded elf took "<<dursecs <<" msecs" << endl;
683 #endif
684
685   if (!dataddr || !symscnp || !strscnp) {
686 //    fprintf(stderr, "[%s][%d]WARNING: One or more of text/bss/symbol/string sections not found in ELF binary\n",__FILE__,__LINE__);
687     log_elferror(err_func_, "no text/bss/symbol/string section");
688     //return false;
689   }
690
691   //if (addressWidth_nbytes == 8) bperr( ">>> 64-bit loaded_elf() successful\n");
692   return true;
693 }
694
695 bool Object::is_offset_in_plt(Offset offset) const
696 {
697   return (offset > plt_addr_ && offset < plt_addr_ + plt_size_);
698 }
699
700 #if !defined(os_solaris)
701 void Object::parseDynamic(Elf_X_Shdr *&dyn_scnp, Elf_X_Shdr *&dynsym_scnp,
702                                                     Elf_X_Shdr *&dynstr_scnp)
703 {
704     Elf_X_Data data = dyn_scnp->get_data();
705     Elf_X_Dyn dyns = data.get_dyn();
706     Elf_X_Shdr *rel_scnp;
707     for (unsigned i = 0; i < dyns.count(); ++i) {
708         switch(dyns.d_tag(i)) {
709           case DT_REL:
710           case DT_RELA:
711                 /*found Relocation section*/
712                 rel_scnp = getRegionHdrByAddr(dyns.d_ptr(i));
713                 rel_size_ = rel_scnp->sh_size();
714                 rel_entry_size_ = rel_scnp->sh_entsize();
715                 get_relocationDyn_entries(rel_scnp, dynsym_scnp, dynstr_scnp);
716                 break;
717           default:
718                 break;
719         }
720     }
721 }
722 #else
723 void Object::parseDynamic(Elf_X_Shdr *&, Elf_X_Shdr *&,
724                           Elf_X_Shdr *&)
725 {
726 }
727 #endif
728
729 /* parse relocations for the sections represented by DT_REL/DT_RELA in
730  * the dynamic section. This section is the one we would want to emit
731  */
732 bool Object::get_relocationDyn_entries( Elf_X_Shdr *&rel_scnp,
733                                      Elf_X_Shdr *&dynsym_scnp, 
734                                      Elf_X_Shdr *&dynstr_scnp )
735 {
736         Elf_X_Data reldata = rel_scnp->get_data();
737         Elf_X_Data symdata = dynsym_scnp->get_data();
738         Elf_X_Data strdata = dynstr_scnp->get_data();
739         
740     if( reldata.isValid() && symdata.isValid() && strdata.isValid() ) {
741             Elf_X_Sym sym = symdata.get_sym();
742             Elf_X_Rel rel = reldata.get_rel();
743             Elf_X_Rela rela = reldata.get_rela();
744             const char *strs = strdata.get_string();
745
746             if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
747                 /* Iterate over the entries. */
748                 for( u_int i = 0; i < (rel_size_/rel_entry_size_); ++i ) {
749                         long offset;
750                 long addend;
751                         long index;
752                 unsigned long type;
753                 Region::RegionType rtype = Region::RT_REL;
754
755                     switch (reldata.d_type()) {
756                       case ELF_T_REL:
757                             offset = rel.r_offset(i);
758                     addend = 0;
759                         index = rel.R_SYM(i);
760                     type = rel.R_TYPE(i);
761                                 break;
762
763                           case ELF_T_RELA:
764                                 offset = rela.r_offset(i);
765                     addend = rela.r_addend(i);
766                                 index = rela.R_SYM(i);
767                     type = rela.R_TYPE(i);
768                     rtype = Region::RT_RELA;
769                                 break;
770
771                       default:
772                         // We should never reach this case.
773                         return false;
774                         };
775                         // /* DEBUG */ fprintf( stderr, "%s: relocation information for target 0x%lx\n", __FUNCTION__, next_plt_entry_addr );
776                     relocationEntry re( offset, string( &strs[ sym.st_name(index) ] ), NULL, type );
777                 re.setAddend(addend);
778                 re.setRegionType(rtype);
779                 if(symbols_.find(&strs[ sym.st_name(index)]) != symbols_.end()){
780                     vector<Symbol *> syms = symbols_[&strs[ sym.st_name(index)]];
781                     re.addDynSym(syms[0]);
782                 }
783
784                     relocation_table_.push_back(re);
785                 }
786                 return true;
787             }
788     }
789     return false;
790 }
791
792 bool Object::get_relocation_entries( Elf_X_Shdr *&rel_plt_scnp,
793                                      Elf_X_Shdr *&dynsym_scnp, 
794                                      Elf_X_Shdr *&dynstr_scnp )
795 {
796     if (rel_plt_size_ && rel_plt_addr_) {
797         Elf_X_Data reldata = rel_plt_scnp->get_data();
798         Elf_X_Data symdata = dynsym_scnp->get_data();
799         Elf_X_Data strdata = dynstr_scnp->get_data();
800
801         if( reldata.isValid() && symdata.isValid() && strdata.isValid() ) {
802             Offset next_plt_entry_addr = plt_addr_;
803
804 #if defined( ia64_unknown_linux2_4 ) 
805             unsigned int functionDescriptorCount = ( rel_plt_size_ / rel_plt_entry_size_ );
806             /* The IA-64 PLT contains 1 special entry, and two entries for each functionDescriptor
807                in the function descriptor table (.IA_64.pltoff, whose count we're deriving from
808                its relocation entries).  These entries are in two groups, the second of which is
809                sometimes separated from the first by 128 bits of zeroes.  The entries in the latter group
810                are call targets that makes an indirect jump using an FD table entry.  If the
811                function they want to call hasn't been linked yet, the FD will point to one of 
812                former group's entries, which will then jump to the first, special entry, in order
813                to invoke the linker.  The linker, after doing the link, will rewrite the FD to
814                point directly to the requested function. 
815
816                As we're only interested in call targets, skip the first group and the buffer entirely,
817                if it's present.
818             */
819             next_plt_entry_addr += (0x10 * 3) + (functionDescriptorCount * 0x10);
820
821             unsigned long long * bufferPtr = (unsigned long long*)(void *)const_cast<char *>(elf_vaddr_to_ptr(next_plt_entry_addr));
822             if( bufferPtr[0] == 0 && bufferPtr[1] == 0 ) { next_plt_entry_addr += 0x10; }
823
824 #elif defined(arch_x86) || defined(arch_x86_64)
825             next_plt_entry_addr += plt_entry_size_;  // 1st PLT entry is special
826 #elif defined (ppc32_linux)
827        //  Do not expect same parameters for ppc64_linux
828        if (!plt_entry_size_) {
829           fprintf(stderr, "%s[%d]:  FIXME:  plt_entry_size not established\n", FILE__, __LINE__);
830           plt_entry_size_ = 8;
831        }
832             next_plt_entry_addr += 9*plt_entry_size_;  // 1st 9 PLT entries are special
833        //fprintf(stderr, "%s[%d]:  skipping %d (6*%d) bytes initial plt\n", 
834        //        FILE__, __LINE__, 9*plt_entry_size_, plt_entry_size_);
835        //  actually this is just fudged to make the offset value 72, which is what binutils uses
836        //  Note that binutils makes the distinction between PLT_SLOT_SIZE (8), 
837        //  and PLT_ENTRY_SIZE (12).  PLT_SLOT_SIZE seems to be what we want, even though we also
838        //  have PLT_INITIAL_ENTRY_SIZE (72)
839        //  see binutils/bfd/elf32-ppc.c/h if more info is needed
840             //next_plt_entry_addr += 72;  // 1st 6 PLT entries art special
841 #else
842             next_plt_entry_addr += 4*(plt_entry_size_); //1st 4 entries are special
843 #endif
844
845             Elf_X_Sym sym = symdata.get_sym();
846             Elf_X_Rel rel = reldata.get_rel();
847             Elf_X_Rela rela = reldata.get_rela();
848             const char *strs = strdata.get_string();
849
850             if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
851                 /* Iterate over the entries. */
852                 for( u_int i = 0; i < (rel_plt_size_/rel_plt_entry_size_); ++i ) {
853                     long offset;
854             long addend;
855                     long index;
856             unsigned long type;
857             Region::RegionType rtype = Region::RT_REL;
858
859                     switch (reldata.d_type()) {
860                     case ELF_T_REL:
861                 offset = rel.r_offset(i);
862                 addend = 0;
863                 index = rel.R_SYM(i);
864                 type = rel.R_TYPE(i);
865                 break;
866
867                     case ELF_T_RELA:
868                 offset = rela.r_offset(i);
869                 addend = rela.r_addend(i);
870                 index = rela.R_SYM(i);
871                 type = rela.R_TYPE(i);
872                 rtype = Region::RT_RELA;
873                 break;
874
875                     default:
876                         // We should never reach this case.
877                         return false;
878                     };
879
880                     // /* DEBUG */ fprintf( stderr, "%s: relocation information for target 0x%lx\n", __FUNCTION__, next_plt_entry_addr );
881                     relocationEntry re( next_plt_entry_addr, offset, string( &strs[ sym.st_name(index) ] ), NULL, type );
882             re.setAddend(addend);
883             re.setRegionType(rtype);
884             if(symbols_.find(&strs[ sym.st_name(index)]) != symbols_.end()){
885                 vector<Symbol *> syms = symbols_[&strs[ sym.st_name(index)]];
886                 re.addDynSym(syms[0]);
887             }
888                     fbt_.push_back(re);
889
890 #if ! defined( arch_ia64 )
891                     next_plt_entry_addr += plt_entry_size_;
892 #else
893                     /* IA-64 headers don't declare a size, because it varies. */
894                     next_plt_entry_addr += 0x20;
895 #endif /* ia64_unknown_linux2_4 */
896                 }
897                 return true;
898             }
899         }
900     }
901     return false;
902 }
903
904 void Object::load_object(bool alloc_syms)
905 {
906    Elf_X_Shdr *symscnp = 0;
907    Elf_X_Shdr *strscnp = 0;
908    Elf_X_Shdr *stabscnp = 0;
909    Elf_X_Shdr *stabstrscnp = 0;
910    Elf_X_Shdr *stabs_indxcnp = 0;
911    Elf_X_Shdr *stabstrs_indxcnp = 0;
912    Offset txtaddr = 0;
913    Offset dataddr = 0;
914    Elf_X_Shdr *rel_plt_scnp = 0;
915    Elf_X_Shdr *plt_scnp = 0; 
916    Elf_X_Shdr *got_scnp = 0;
917    Elf_X_Shdr *dynsym_scnp = 0;
918    Elf_X_Shdr *dynstr_scnp = 0;
919    Elf_X_Shdr *dynamic_scnp = 0;
920    Elf_X_Shdr *eh_frame_scnp = 0;
921    Elf_X_Shdr *gcc_except = 0;
922    Elf_X_Shdr *interp_scnp = 0;
923
924    { // binding contour (for "goto cleanup")
925
926       // initialize object (for failure detection)
927       code_ptr_ = 0;
928       code_off_ = 0;
929       code_len_ = 0;
930       data_ptr_ = 0;
931       data_off_ = 0;
932       data_len_ = 0;
933
934       // initialize "valid" regions of code and data segments
935       code_vldS_ = (Offset) -1;
936       code_vldE_ = 0;
937       data_vldS_ = (Offset) -1;
938       data_vldE_ = 0;
939
940       // And attempt to parse the ELF data structures in the file....
941       // EEL, added one more parameter
942
943       if (!loaded_elf(txtaddr, dataddr, symscnp, strscnp,
944                stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
945                rel_plt_scnp,plt_scnp,got_scnp,dynsym_scnp,
946                dynstr_scnp, dynamic_scnp, eh_frame_scnp,gcc_except, interp_scnp, true)) 
947       {
948          goto cleanup;
949       }
950
951       addressWidth_nbytes = elfHdr.wordSize();
952
953       // find code and data segments....
954       find_code_and_data(elfHdr, txtaddr, dataddr);
955
956       if (elfHdr.e_type() != ET_REL) 
957       {
958          if (!code_ptr_ || !code_len_) 
959          {
960             //bpfatal( "no text segment\n");
961             goto cleanup;
962          }
963
964          if (!data_ptr_ || !data_len_) 
965          {
966             //bpfatal( "no data segment\n");
967             goto cleanup;
968          }
969       }
970       get_valid_memory_areas(elfHdr);
971
972       //fprintf(stderr, "[%s:%u] - Exe Name\n", __FILE__, __LINE__);
973
974 #if defined(os_linux) && (defined(arch_x86) || defined(arch_x86_64))
975       if (eh_frame_scnp != 0 && gcc_except != 0) 
976       {
977          find_catch_blocks(elfHdrForDebugInfo, eh_frame_scnp, gcc_except, 
978                            txtaddr, dataddr, catch_addrs_);
979       }
980 #endif
981       if (interp_scnp)
982          interpreter_name_ = (char *) interp_scnp->get_data().d_buf(); 
983
984       // global symbols are put in global_symbols. Later we read the
985       // stab section to find the module to where they belong.
986       // Experiment : lets try to be a bit more intelligent about
987       // how we initially size the global_symbols table.  
988       // dictionary_lite takes an initial # of bins (2nd param), 
989       // a max bin load (3rd param), and a grow factor (4th param).
990       // Leaving aside the grow factor, lets allocate an initial #
991       // of bins = nsyms / max bin load.
992
993 #if defined(TIMED_PARSE)
994       struct timeval starttime;
995       gettimeofday(&starttime, NULL);
996 #endif
997       if (alloc_syms) 
998       {
999          std::vector<Symbol *> allsymbols;
1000
1001          // find symbol and string data
1002          string module = "DEFAULT_MODULE";
1003          string name   = "DEFAULT_NAME";
1004          Elf_X_Data symdata, strdata;
1005
1006          if (symscnp && strscnp)
1007          {
1008             symdata = symscnp->get_data();
1009             strdata = strscnp->get_data();
1010             parse_symbols(allsymbols, symdata, strdata, false, module);
1011          }   
1012
1013          sort(allsymbols.begin(),allsymbols.end(),symbol_compare);
1014          //VECTOR_SORT(allsymbols,symbol_compare);
1015
1016          no_of_symbols_ = allsymbols.size();
1017          fix_zero_function_sizes(allsymbols, 0);
1018
1019          override_weak_symbols(allsymbols);
1020
1021          // dump "allsymbols" into "symbols_" (data member)
1022          insert_symbols_static(allsymbols);
1023
1024          // try to resolve the module names of global symbols
1025          // Sun compiler stab.index section 
1026          fix_global_symbol_modules_static_stab(stabs_indxcnp, stabstrs_indxcnp);
1027
1028          // STABS format (.stab section)
1029          fix_global_symbol_modules_static_stab(stabscnp, stabstrscnp);
1030
1031          // DWARF format (.debug_info section)
1032          fix_global_symbol_modules_static_dwarf(elfHdrForDebugInfo);
1033
1034          if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
1035          {
1036             symdata = dynsym_scnp->get_data();
1037             strdata = dynstr_scnp->get_data();
1038             parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
1039          }
1040
1041          //TODO
1042          //Have a hash on the symbol table. Iterate over dynamic symbol table to check if it exists
1043          //If yes set dynamic for the symbol ( How to distinguish between symbols only in symtab,
1044          //         symbols only in dynsymtab & symbols present in both).
1045          // Else add dynamic symbol to dictionary
1046          // (or) Have two sepearate dictionaries. Makes life easy!
1047          // Think about it today!!
1048
1049          //allsymbols = merge(allsymbols, alldynSymbols);
1050
1051 #if defined(TIMED_PARSE)
1052          struct timeval endtime;
1053          gettimeofday(&endtime, NULL);
1054          unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1055          unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1056          unsigned long difftime = lendtime - lstarttime;
1057          double dursecs = difftime/(1000);
1058          cout << "parsing/fixing/overriding elf took "<<dursecs <<" msecs" << endl;
1059 #endif
1060
1061          if (dynamic_addr_ && dynsym_scnp && dynstr_scnp) 
1062          {
1063             parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
1064          }
1065
1066          // populate "fbt_"
1067          if (rel_plt_scnp && dynsym_scnp && dynstr_scnp) 
1068          {
1069             if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) 
1070             {
1071                goto cleanup;
1072             }
1073          }
1074       }
1075
1076       //Set object type
1077       int e_type = elfHdr.e_type();
1078
1079       if (e_type == ET_DYN) 
1080       {
1081          obj_type_ = obj_SharedLib;
1082       }
1083       else if (e_type == ET_EXEC) 
1084       {
1085          obj_type_ = obj_Executable;
1086       }
1087
1088       return;
1089    } // end binding contour (for "goto cleanup2")
1090
1091 cleanup: 
1092    {
1093       /* NOTE: The file should NOT be munmap()ed.  The mapped file is
1094          used for function parsing (see dyninstAPI/src/symtab.C) */
1095
1096       fprintf(stderr, "%s[%d]:  failed to load elf object\n", FILE__, __LINE__);
1097    }
1098 }
1099
1100 void Object::load_shared_object(bool alloc_syms) 
1101 {
1102    Elf_X_Shdr *symscnp = 0;
1103    Elf_X_Shdr *strscnp = 0;
1104    Elf_X_Shdr *stabscnp = 0;
1105    Elf_X_Shdr *stabstrscnp = 0;
1106    Elf_X_Shdr *stabs_indxcnp = 0;
1107    Elf_X_Shdr *stabstrs_indxcnp = 0;
1108    Offset txtaddr = 0;
1109    Offset dataddr = 0;
1110    Elf_X_Shdr *rel_plt_scnp = 0;
1111    Elf_X_Shdr *plt_scnp = 0; 
1112    Elf_X_Shdr *got_scnp = 0;
1113    Elf_X_Shdr *dynsym_scnp = 0;
1114    Elf_X_Shdr *dynstr_scnp = 0;
1115    Elf_X_Shdr *dynamic_scnp = 0;
1116    Elf_X_Shdr *eh_frame_scnp = 0;
1117    Elf_X_Shdr *gcc_except = 0;
1118    Elf_X_Shdr *interp_scnp = 0;
1119
1120    { // binding contour (for "goto cleanup2")
1121
1122       // initialize "valid" regions of code and data segments
1123       code_vldS_ = (Offset) -1;
1124       code_vldE_ = 0;
1125       data_vldS_ = (Offset) -1;
1126       data_vldE_ = 0;
1127
1128       if (!loaded_elf(txtaddr, dataddr, symscnp, strscnp,
1129                stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
1130                rel_plt_scnp, plt_scnp, got_scnp, dynsym_scnp,
1131                dynstr_scnp, dynamic_scnp, eh_frame_scnp, gcc_except, interp_scnp))
1132          goto cleanup2;
1133
1134       addressWidth_nbytes = elfHdr.wordSize();
1135
1136       // find code and data segments....
1137       find_code_and_data(elfHdr, txtaddr, dataddr);
1138
1139       get_valid_memory_areas(elfHdr);
1140
1141 #if defined(os_linux) && (defined(arch_x86) || defined(arch_x86_64))
1142       //fprintf(stderr, "[%s:%u] - Mod Name is %s\n", __FILE__, __LINE__, name.c_str());
1143       if (eh_frame_scnp != 0 && gcc_except != 0) {
1144          find_catch_blocks(elfHdrForDebugInfo, eh_frame_scnp, gcc_except, 
1145                            txtaddr, dataddr, catch_addrs_);
1146       }
1147 #endif
1148 #if defined(TIMED_PARSE)
1149       struct timeval starttime;
1150       gettimeofday(&starttime, NULL);
1151 #endif
1152
1153       if (alloc_syms) {
1154          // build symbol dictionary
1155          std::vector<Symbol *> allsymbols;
1156          string module = mf->pathname();
1157          string name   = "DEFAULT_NAME";
1158
1159          // find symbol and string data
1160          Elf_X_Data symdata, strdata;
1161          if (symscnp && strscnp)
1162          {
1163             symdata = symscnp->get_data();
1164             strdata = strscnp->get_data();
1165             if (!symdata.isValid() || !strdata.isValid()) {
1166                log_elferror(err_func_, "locating symbol/string data");
1167                goto cleanup2;
1168             }
1169             parse_symbols(allsymbols, symdata, strdata, false, module);
1170          } 
1171          sort(allsymbols.begin(),allsymbols.end(),symbol_compare);
1172          //VECTOR_SORT(allsymbols,symbol_compare);
1173          no_of_symbols_ = allsymbols.size();
1174
1175          fix_zero_function_sizes(allsymbols, 0);
1176          override_weak_symbols(allsymbols);
1177          insert_symbols_shared(allsymbols);
1178
1179          //     // try to resolve the module names of global symbols
1180          //     // Sun compiler stab.index section 
1181          //     fix_global_symbol_modules_static_stab(stabs_indxcnp, stabstrs_indxcnp);
1182
1183          //     // STABS format (.stab section)
1184          //     fix_global_symbol_modules_static_stab(stabscnp, stabstrscnp);
1185
1186          //     // DWARF format (.debug_info section)
1187          //     fix_global_symbol_modules_static_dwarf(elfHdr);
1188
1189          if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
1190          {
1191             symdata = dynsym_scnp->get_data();
1192             strdata = dynstr_scnp->get_data();
1193             parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
1194          }
1195          //TODO
1196          //Have a hash on the symbol table. Iterate over dynamic symbol table to check if it exists
1197          //If yes set dynamic for the symbol ( How to distinguish between symbols only in symtab,
1198          //         symbols only in dynsymtab & symbols present in both).
1199          // Else add dynamic symbol to dictionary
1200          // (or) Have two sepearate dictionaries. Makes life easy!
1201          // Think about it today!!
1202
1203          //allsymbols = merge(allsymbols, alldynSymbols);
1204
1205 #if defined(TIMED_PARSE)
1206          struct timeval endtime;
1207          gettimeofday(&endtime, NULL);
1208          unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1209          unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1210          unsigned long difftime = lendtime - lstarttime;
1211          double dursecs = difftime/(1000 * 1000);
1212          cout << "*INSERT SYMBOLS* elf took "<<dursecs <<" msecs" << endl;
1213          //cout << "parsing/fixing/overriding/insertion elf took "<<dursecs <<" msecs" << endl;
1214 #endif
1215          if(dynamic_addr_ && dynsym_scnp && dynstr_scnp) {
1216             parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
1217          }
1218
1219          if (rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
1220             if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) { 
1221                goto cleanup2;
1222             }
1223          }
1224       }
1225
1226       //Set object type
1227       int e_type = elfHdr.e_type();
1228       if (e_type == ET_DYN) {
1229          obj_type_ = obj_SharedLib;
1230       }
1231       else if (e_type == ET_EXEC) {
1232          obj_type_ = obj_Executable;
1233       }
1234
1235    } // end binding contour (for "goto cleanup2")
1236
1237 cleanup2: 
1238    {
1239    }
1240 }
1241
1242 static Symbol::SymbolType pdelf_type(int elf_type)
1243 {
1244    switch (elf_type) {
1245       case STT_FILE:   return Symbol::ST_MODULE;
1246       case STT_OBJECT: return Symbol::ST_OBJECT;
1247       case STT_FUNC:   return Symbol::ST_FUNCTION;
1248       case STT_NOTYPE: return Symbol::ST_NOTYPE;
1249    }
1250    return Symbol::ST_UNKNOWN;
1251 }
1252
1253 static Symbol::SymbolLinkage pdelf_linkage(int elf_binding)
1254 {
1255    switch (elf_binding) {
1256       case STB_LOCAL:  return Symbol::SL_LOCAL;
1257       case STB_WEAK:   return Symbol::SL_WEAK;
1258       case STB_GLOBAL: return Symbol::SL_GLOBAL;
1259    }
1260    return Symbol::SL_UNKNOWN;
1261 }
1262
1263 //============================================================================
1264
1265 //#include "dyninstAPI/src/arch.h"
1266 //#include "dyninstAPI/src/inst.h"
1267 //#include "dyninstAPI/src/instPoint.h" // includes instPoint-x86.h
1268 //#include "dyninstAPI/src/instP.h" // class returnInstance
1269 //#include "dyninstAPI/src/rpcMgr.h"
1270
1271 //linear search
1272 bool lookUpSymbol( std::vector< Symbol *>& allsymbols, Offset& addr )
1273 {
1274    for( unsigned i = 0; i < allsymbols.size(); i++ )
1275    {
1276       if( allsymbols[ i ]->getAddr() == addr )
1277       {
1278          return true;
1279       }
1280    }
1281    return false;
1282 }
1283
1284 bool lookUpAddress( std::vector< Offset >& jumpTargets, Offset& addr )
1285 {
1286    for( unsigned i = 0; i < jumpTargets.size(); i++ )
1287    {
1288       if( jumpTargets[ i ] == addr )
1289       {
1290          return true;
1291       }
1292    }
1293    return false;
1294 }
1295
1296 //utitility function to print std::vector of symbols
1297 void printSyms( std::vector< Symbol *>& allsymbols )
1298 {
1299    for( unsigned i = 0; i < allsymbols.size(); i++ )
1300    {
1301       if( allsymbols[ i ]->getType() != Symbol::ST_FUNCTION )
1302       {
1303          continue;
1304       }
1305       cout << allsymbols[ i ] << endl;
1306    } 
1307
1308
1309
1310 // parse_symbols(): populate "allsymbols"
1311 void Object::parse_symbols(std::vector<Symbol *> &allsymbols, 
1312       Elf_X_Data &symdata, Elf_X_Data &strdata,
1313       bool shared, string smodule)
1314 {
1315 #if defined(TIMED_PARSE)
1316    struct timeval starttime;
1317    gettimeofday(&starttime, NULL);
1318 #endif
1319
1320    Elf_X_Sym syms = symdata.get_sym();
1321    const char *strs = strdata.get_string();
1322    for (unsigned i = 0; i < syms.count(); i++) {
1323       // skip undefined symbols
1324       //If it is not a dynamic executable then we need undefined symbols
1325       //in symtab section so that we can resolve symbol references. So 
1326       //we parse & store undefined symbols only if there is no dynamic
1327       //symbol table
1328       //if (is_dynamic_ && (syms.st_shndx(i) == SHN_UNDEF)) continue;
1329       //if (syms.st_shndx(i) == SHN_UNDEF) continue;
1330       int etype = syms.ST_TYPE(i);
1331       int ebinding = syms.ST_BIND(i);
1332
1333       // resolve symbol elements
1334       string sname = &strs[ syms.st_name(i) ];
1335       Symbol::SymbolType stype = pdelf_type(etype);
1336       Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
1337       unsigned ssize = syms.st_size(i);
1338       Offset saddr = syms.st_value(i);
1339       unsigned secNumber = syms.st_shndx(i);
1340
1341       //Get rid of weak symbols which are undefined 
1342       //if((slinkage == Symbol::SL_WEAK) && (secNumber == SHN_UNDEF)) continue;
1343       
1344       if (stype == Symbol::ST_UNKNOWN) continue;
1345       if (slinkage == Symbol::SL_UNKNOWN) continue;
1346
1347       Region *sec;
1348       if(secNumber >= 1 && secNumber <= regions_.size())
1349          sec = regions_[secNumber];
1350       else
1351          sec = NULL;
1352       
1353       //if((secNumber == SHN_ABS) && regions_.size())
1354          //sec = regions_[0];
1355       
1356       Symbol *newsym = new Symbol(sname, smodule, stype, slinkage, saddr, sec, ssize);
1357       if (secNumber == SHN_ABS)
1358           newsym->setIsAbsolute();
1359       // register symbol in dictionary
1360       if ((etype == STT_FILE) && (ebinding == STB_LOCAL) && 
1361             (shared) && (sname == extract_pathname_tail(smodule))) {
1362          // symbols_[sname] = newsym; // special case
1363          symbols_[sname].push_back( newsym );
1364       } else {
1365          allsymbols.push_back(newsym); // normal case
1366       }
1367    }
1368
1369 #if defined(TIMED_PARSE)
1370    struct timeval endtime;
1371    gettimeofday(&endtime, NULL);
1372    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1373    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1374    unsigned long difftime = lendtime - lstarttime;
1375    double dursecs = difftime/(1000 * 1000);
1376    cout << "parsing elf took "<<dursecs <<" secs" << endl;
1377 #endif
1378    //if (addressWidth_nbytes == 8) fprintf(stderr, ">>> 64-bit parse_symbols() successful\n");
1379 }
1380
1381 // parse_symbols(): populate "allsymbols"
1382 // Lazy parsing of dynamic symbol  & string tables
1383 // Parsing the dynamic symbols lazily would certainly not increase the overhead of the entire parse
1384    void Object::parse_dynamicSymbols (Elf_X_Shdr *&
1385 #if !defined(os_solaris)
1386          dyn_scnp
1387 #endif 
1388          , Elf_X_Data &symdata, 
1389          Elf_X_Data &strdata,
1390          bool /*shared*/, 
1391          string smodule)
1392 {
1393 #if defined(TIMED_PARSE)
1394    struct timeval starttime;
1395    gettimeofday(&starttime, NULL);
1396 #endif
1397
1398    Elf_X_Sym syms = symdata.get_sym();
1399    const char *strs = strdata.get_string();
1400 #if !defined(os_solaris)
1401    Elf_X_Shdr *versymSec = NULL, *verneedSec = NULL, *verdefSec = NULL;
1402    Elf_X_Data data = dyn_scnp->get_data();
1403    Elf_X_Dyn dyns = data.get_dyn();
1404    unsigned verneednum = 0, verdefnum = 0;
1405    Elf_X_Versym symVersions;
1406    Elf_X_Verdef *symVersionDefs = NULL;
1407    Elf_X_Verneed *symVersionNeeds = NULL;
1408    for (unsigned i = 0; i < dyns.count(); ++i) {
1409       switch(dyns.d_tag(i)) {
1410          case DT_NEEDED:
1411             deps_.push_back(&strs[dyns.d_ptr(i)]);
1412             break;
1413          case DT_VERSYM:
1414                versymSec = getRegionHdrByAddr(dyns.d_ptr(i));
1415                break;
1416            case DT_VERNEED:
1417                verneedSec = getRegionHdrByAddr(dyns.d_ptr(i));
1418                break;
1419            case DT_VERDEF:
1420                verdefSec = getRegionHdrByAddr(dyns.d_ptr(i));
1421                break;
1422            case DT_VERNEEDNUM:
1423                verneednum = dyns.d_ptr(i);
1424                break;
1425            case DT_VERDEFNUM:
1426                verdefnum = dyns.d_ptr(i);
1427                break;
1428            default:
1429                break;
1430        }
1431    }
1432    if(versymSec)
1433        symVersions = versymSec->get_data().get_versyms();
1434    if(verdefSec)
1435        symVersionDefs = verdefSec->get_data().get_verDefSym();
1436    if(verneedSec)
1437        symVersionNeeds = verneedSec->get_data().get_verNeedSym();
1438     
1439    for(unsigned i = 0; i < verdefnum ;i++) {
1440        Elf_X_Verdaux *aux = symVersionDefs->get_aux();
1441        for(unsigned j=0; j< symVersionDefs->vd_cnt(); j++){
1442            versionMapping[symVersionDefs->vd_ndx()].push_back(&strs[aux->vda_name()]);
1443            Elf_X_Verdaux *auxnext = aux->get_next();
1444            delete aux;
1445            aux = auxnext;
1446        }
1447        Elf_X_Verdef *symVersionDefsnext = symVersionDefs->get_next();
1448        delete symVersionDefs;
1449        symVersionDefs = symVersionDefsnext;
1450    }
1451
1452    for(unsigned i = 0; i < verneednum; i++){
1453        Elf_X_Vernaux *aux = symVersionNeeds->get_aux();
1454        for(unsigned j=0; j< symVersionNeeds->vn_cnt(); j++){
1455            versionMapping[aux->vna_other()].push_back(&strs[aux->vna_name()]);
1456            versionFileNameMapping[aux->vna_other()] = &strs[symVersionNeeds->vn_file()];
1457            Elf_X_Vernaux *auxnext = aux->get_next();
1458            delete aux;
1459            aux = auxnext;
1460        }
1461        Elf_X_Verneed *symVersionNeedsnext = symVersionNeeds->get_next();
1462        delete symVersionNeeds;
1463        symVersionNeeds = symVersionNeedsnext;
1464    }
1465    
1466 #endif
1467   
1468    for (unsigned i = 0; i < syms.count(); i++) {
1469       // skip undefined symbols
1470       int etype = syms.ST_TYPE(i);
1471       int ebinding = syms.ST_BIND(i);
1472       
1473       // resolve symbol elements
1474       string sname = &strs[ syms.st_name(i) ];
1475       if(sname == "")
1476           continue;
1477       Symbol::SymbolType stype = pdelf_type(etype);
1478       Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
1479       unsigned ssize = syms.st_size(i);
1480       Offset saddr = syms.st_value(i);
1481       unsigned secNumber = syms.st_shndx(i);
1482       /* 11/4/08: don't discard symbols with same name and address */
1483       if(symbols_.find(sname) != symbols_.end()) {
1484           vector<Symbol *> syms = symbols_[sname];
1485           for(unsigned j = 0; j < syms.size(); j++){
1486               if(syms[j]->getAddr() == saddr){
1487 #if !defined(os_solaris)
1488                   if(versymSec) {
1489                       if(versionFileNameMapping.find(symVersions.get(i)) != versionFileNameMapping.end())
1490                           syms[j]->setVersionFileName(versionFileNameMapping[symVersions.get(i)]);
1491                       if(versionMapping.find(symVersions.get(i)) != versionMapping.end())
1492                           syms[j]->setVersions(versionMapping[symVersions.get(i)]);
1493                   }
1494 #endif
1495                   syms[j]->setDynSymtab();
1496               }
1497           }
1498           continue;
1499        }
1500       
1501       if (stype == Symbol::ST_UNKNOWN) continue;
1502       if (slinkage == Symbol::SL_UNKNOWN) continue;
1503      
1504       Region *sec;
1505       if(secNumber >= 1 && secNumber <= regions_.size())
1506          sec = regions_[secNumber];
1507       else
1508          sec = NULL;            
1509
1510       //if((secNumber == SHN_ABS) && regions_.size())
1511          //sec = regions_[0];     
1512
1513       Symbol *newsym = new Symbol(sname, smodule, stype, slinkage, saddr, sec, ssize, /*NULL,*/ true, false);
1514       if (secNumber == SHN_ABS)
1515           newsym->setIsAbsolute();
1516 #if !defined(os_solaris)
1517       if(versymSec) {
1518           if(versionFileNameMapping.find(symVersions.get(i)) != versionFileNameMapping.end())
1519               newsym->setVersionFileName(versionFileNameMapping[symVersions.get(i)]);
1520           if(versionMapping.find(symVersions.get(i)) != versionMapping.end())
1521               newsym->setVersions(versionMapping[symVersions.get(i)]);
1522 #ifdef BINEDIT_DEBUG
1523           if (smodule == "libspecial.so") {
1524               printf(" [%s] %s: ", smodule.c_str(), sname.c_str());
1525               std::vector<std::string> svers = versionMapping[symVersions.get(i)];
1526               for (unsigned j=0; j<svers.size(); j++)
1527                   printf(" %s", svers[j].c_str());
1528               printf("\n");
1529           }
1530 #endif
1531       }
1532 #endif
1533       // register symbol in dictionary
1534          
1535       // symbols_[sname] = newsym; // special case
1536       symbols_[sname].push_back( newsym );
1537    }
1538
1539 #if defined(TIMED_PARSE)
1540     struct timeval endtime;
1541     gettimeofday(&endtime, NULL);
1542     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1543     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1544     unsigned long difftime = lendtime - lstarttime;
1545     double dursecs = difftime/(1000 * 1000);
1546     cout << "parsing elf took "<<dursecs <<" secs" << endl;
1547 #endif
1548     //if (addressWidth_nbytes == 8) fprintf(stderr, ">>> 64-bit parse_symbols() successful\n");
1549 }
1550
1551 /********************************************************
1552  *
1553  * Apparently, some compilers do not fill in the symbol sizes
1554  *  correctly (in the symbol table) for functions.  Run through
1555  *  symbol std::vector allsymbols, and compute ?correct? sizes....
1556  * This patch to symbol sizes runs through allsymbols && tries
1557  *  to patch all functions symbols recorded with a size of 0,
1558  *  or which have been EEL overwritten.
1559  * Assumes that allsymbols is sorted, with e.g. symbol_compare....
1560  *
1561 ********************************************************/
1562 void Object::fix_zero_function_sizes(std::vector<Symbol *> &allsymbols, bool isEEL)
1563 {
1564 #if defined(TIMED_PARSE)
1565    struct timeval starttime;
1566    gettimeofday(&starttime, NULL);
1567 #endif
1568    unsigned u, v, nsymbols;
1569
1570    nsymbols = allsymbols.size();
1571         unsigned int u_section_idx = 0;
1572    for (u=0; u < nsymbols; u++) {
1573       //  If function symbol, and size set to 0, or if the
1574       //   executable has been EEL rewritten, patch the size
1575       //
1576                 //  Patch the symbol size to the difference between the address
1577                 //  of this symbol and the next, unless the next symbol is beyond
1578                 //  the boundary of the section to which this symbol belongs.  In
1579                 //  that case, set the size to the difference between the section
1580                 //  end and this symbol.
1581                 // 
1582       if (allsymbols[u]->getType() == Symbol::ST_FUNCTION
1583           && (isEEL || allsymbols[u]->getSize() == 0) )
1584       {
1585                         // find the section to which allsymbols[u] belongs
1586                         // (most likely, it is the section to which allsymbols[u-1] 
1587                         // belonged)
1588                         // Note that this assumes the section headers std::vector is sorted
1589                         // in increasing order
1590                         //
1591                         while( u_section_idx < allRegionHdrs.size() )
1592                         {
1593                                 Offset slow = allRegionHdrs[u_section_idx]->sh_addr();
1594                                 Offset shi = slow + allRegionHdrs[u_section_idx]->sh_size();
1595 #if defined(os_irix)
1596                                 slow -= get_base_addr();
1597                                 shi -= get_base_addr();
1598 #endif
1599                                 if( (allsymbols[u]->getAddr() >= slow) &&
1600                 (allsymbols[u]->getAddr() < shi) )
1601                                 {
1602                                         // we found u's section
1603                                         break;
1604                                 }
1605
1606                                 // try the next section
1607                                 u_section_idx++;
1608                         }
1609
1610          //Some platforms (Fedora Core 2) thought it would be really 
1611          // funny if they stuck size 0 symbols inbetween sections.  
1612          // we'll just delete the symbol in this case.
1613          if (u_section_idx == allRegionHdrs.size())
1614          {
1615             //Delete item u
1616             for (unsigned i = u; i < allsymbols.size()-1; i++)
1617                allsymbols[i] = allsymbols[i+1];
1618             allsymbols.pop_back();
1619             //Search next item
1620             u--; nsymbols--;
1621             continue;
1622          }
1623
1624                         assert( u_section_idx < allRegionHdrs.size() );
1625
1626                         // search for the next symbol after allsymbols[u]
1627          v = u+1;
1628          while (v < nsymbols && allsymbols[v]->getAddr() == allsymbols[u]->getAddr())
1629                         {
1630             v++;
1631                         }
1632
1633                         unsigned int symSize = 0;
1634                         unsigned int v_section_idx = 0;
1635          if (v < nsymbols) {
1636
1637                                 // find the section to which allsymbols[v] belongs
1638                                 // (most likely, it is in the same section as symbol u)
1639                                 // Note that this assumes the section headers std::vector is
1640                                 // sorted in increasing order
1641                                 while( v_section_idx < allRegionHdrs.size() )
1642                                 {
1643                                         Offset slow = allRegionHdrs[v_section_idx]->sh_addr();
1644                                         Offset shi = slow + allRegionHdrs[v_section_idx]->sh_size();
1645 #if defined(os_irix)
1646                                         slow -= get_base_addr();
1647                                         shi -= get_base_addr();
1648 #endif
1649                                         if( (allsymbols[v]->getAddr() >= slow) &&
1650                    (allsymbols[v]->getAddr() < shi) )
1651                                         {
1652                                                 // we found v's section
1653                                                 break;
1654                                         }
1655
1656                                         // try the next section
1657                                         v_section_idx++;
1658                                 }
1659
1660                                 if( u_section_idx == v_section_idx )
1661                                 {
1662                                         // symbol u and symbol v are in the same section
1663                                         // 
1664                                         // take the size of symbol u to be the difference
1665                                         // between their two addresses
1666                                         //
1667                symSize = ((unsigned int)allsymbols[v]->getAddr()) - 
1668                   (unsigned int)allsymbols[u]->getAddr();
1669                                 }
1670          }
1671                         
1672                         if( (v == nsymbols) || (u_section_idx != v_section_idx) )
1673                         {
1674                                 // u is the last symbol in its section
1675                                 //
1676                                 // its size is the distance from its address to the
1677                                 // end of its section
1678                                 //
1679                                 symSize = allRegionHdrs[u_section_idx]->sh_addr() + 
1680                allRegionHdrs[u_section_idx]->sh_size() -
1681 #if defined(os_irix)
1682                (allsymbols[u]->getAddr() + get_base_addr());
1683 #else
1684             allsymbols[u]->getAddr();
1685 #endif
1686                         }
1687
1688                         // update the symbol size
1689          allsymbols[u]->setSize( symSize );
1690       }
1691    }
1692 #if defined(TIMED_PARSE)
1693     struct timeval endtime;
1694     gettimeofday(&endtime, NULL);
1695     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1696     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1697     unsigned long difftime = lendtime - lstarttime;
1698     double dursecs = difftime/(1000 * 1000);
1699     cout << "****fix zero function sizes took "<<dursecs <<" secs" << endl;
1700 #endif
1701 }
1702
1703 /********************************************************
1704  *  
1705  *  Run over list of symbols found in a SHARED LIBRARY ONLY -
1706  *   Override weak AND LOCAL symbol references for which there is also
1707  *   a global symbol reference, by setting the size on the weak
1708  *   reference to 0.
1709  *  Also potentially patches the size on such symbols (note that 
1710  *   Object::fix_symbol_sizes (above) patches sizes on functions
1711  *   recorded with a size of 0).  This fixes non-zero sized functions
1712  *   in the case where 2 functions follow each other in the symbol
1713  *   table, and the first has a size which would extend into the
1714  *   second.  WHY IS THIS ONLY DONE FOR SHARED LIBRARIES.... 
1715  *
1716  *  Assumes that allsymbols is sorted, with e.g. symbol_compare....
1717  *
1718 ********************************************************/
1719 void Object::override_weak_symbols(std::vector<Symbol *> &allsymbols) {
1720 #if defined(TIMED_PARSE)
1721    struct timeval starttime;
1722    gettimeofday(&starttime, NULL);
1723 #endif
1724     signed i, nsymbols; // these need to be signed
1725     u_int next_start;
1726     int next_size;
1727     bool i_weak_or_local;
1728     bool ip1_weak_or_local;
1729
1730     //cerr << "overriding weak symbols for which there is also a global symbol reference...." << endl;
1731     nsymbols = allsymbols.size();
1732     for (i=0; i < nsymbols - 1; i++) {
1733         if((allsymbols[i]->getType() == Symbol::ST_FUNCTION)
1734                 && (allsymbols[i+1]->getType() == Symbol::ST_FUNCTION)) {
1735
1736             // where symbol i+1 should start, based on start of symbol i
1737             //  and size of symbol i....
1738             next_start=allsymbols[i]->getAddr()+allsymbols[i]->getSize();
1739         
1740             // do symbols i and i+1 have weak or local bindings....
1741             i_weak_or_local = ((allsymbols[i]->getLinkage() == Symbol::SL_WEAK) ||
1742                                (allsymbols[i]->getLinkage() == Symbol::SL_LOCAL));
1743             ip1_weak_or_local = ((allsymbols[i+1]->getLinkage() == Symbol::SL_WEAK) ||
1744                                (allsymbols[i+1]->getLinkage() == Symbol::SL_LOCAL));
1745
1746             // if the symbols have the same address and one is weak or local
1747             // and the other is global keeep the global one
1748             if((allsymbols[i]->getAddr() == allsymbols[i+1]->getAddr()) && 
1749                     (((i_weak_or_local) &&
1750                       (allsymbols[i+1]->getLinkage() == Symbol::SL_GLOBAL)) || 
1751                      ((allsymbols[i]->getLinkage() == Symbol::SL_GLOBAL) &&
1752                       (ip1_weak_or_local)))) {
1753
1754                 if (i_weak_or_local) {
1755                     allsymbols[i]->setSize(0);
1756                     //cerr << " (type 1) removing symbol " << allsymbols[i];
1757                 } else {
1758                     allsymbols[i+1]->setSize(0);
1759                     //cerr << " (type 1) removing symbol " << allsymbols[i+1];
1760                 }
1761             }
1762             // looks like may possibly need to patch size of symbol i
1763             //  based on start of symbol i + 1????
1764             else if (next_start > allsymbols[i+1]->getAddr() && 
1765                      allsymbols[i]->getAddr() != allsymbols[i+1]->getAddr()) {
1766                 next_size = allsymbols[i+1]->getAddr() - allsymbols[i]->getAddr();
1767                 allsymbols[i]->setSize(next_size);
1768                   //cerr << " (type 2) changing symbol size of symbol "
1769                   //     << allsymbols[i] << "to size " << next_size << endl;
1770             }
1771         }
1772     }
1773 #if defined(TIMED_PARSE)
1774     struct timeval endtime;
1775     gettimeofday(&endtime, NULL);
1776     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1777     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1778     unsigned long difftime = lendtime - lstarttime;
1779     double dursecs = difftime/(1000 * 1000);
1780     cout << "*****override weak symbols took "<<dursecs <<" secs" << endl;
1781 #endif
1782 }
1783
1784 #if defined(USES_DWARF_DEBUG)
1785
1786 static string find_symbol(string name,
1787               dyn_hash_map<string, std::vector< Symbol *> > &symbols)
1788 {
1789   string name2;
1790
1791   // pass #1: unmodified
1792   name2 = name;
1793   if (symbols.find(name2)!=symbols.end()) return name2;
1794
1795   // pass #2: leading underscore (C)
1796   name2 = "_" + name;
1797   if (symbols.find(name2)!=symbols.end()) return name2;
1798
1799   // pass #3: trailing underscore (Fortran)
1800   name2 = name + "_";
1801   if (symbols.find(name2)!=symbols.end())
1802         return name2;
1803
1804   return "";
1805 }
1806
1807 #endif
1808
1809 // Insert sym into syms. If syms already contains another symbol with the
1810 // same name, inserts sym under a versioned name (,v%d appended to the original
1811 // name)
1812 static void insertUniqdSymbol(Symbol *sym,
1813                               dyn_hash_map<string, std::vector< Symbol *> > *syms,
1814                               dyn_hash_map<Offset, string > *namesByAddr)
1815 {
1816     Offset symAddr = sym->getAddr();
1817     const string & symName = sym->getName();
1818     
1819         /* The old version of this function generated unique names
1820            for conflicting symbols, favoring globally-defined symbols
1821            over local ones.  This is no longer necessary. */       
1822         (*syms)[symName].push_back( sym );
1823
1824         /* This is stupid (because it's legal and normal for more than
1825            one symbol to point at the same address), but duplicates 
1826            what happens below.  The look up by name prefers the global 
1827            symbols to the local ones, but the look up by address 
1828            favors the last-defined. */
1829         (*namesByAddr)[symAddr] = symName;
1830 }
1831
1832 /********************************************************
1833  *
1834  * For object files only....
1835  *   read the .debug_info section to find the module of global symbols
1836  *   see documents...
1837  *   - "DWARF Debugging Information Format"
1838  *   - "A Consumer Libary Interface to DWARF"
1839  *
1840  ********************************************************/
1841
1842 #if defined(USES_DWARF_DEBUG)
1843
1844 void pd_dwarf_handler(Dwarf_Error error, Dwarf_Ptr /*userData*/)
1845 {
1846   if (error == NULL)
1847     return;
1848
1849   char *dwarf_msg = dwarf_errmsg(error);
1850   string str = string("DWARF Error: ")+ dwarf_msg;
1851   dwarf_err_func(str.c_str());
1852       
1853   //bperr( "DWARF error: %s\n", dwarf_msg);
1854 }
1855
1856 Dwarf_Signed declFileNo = 0;
1857 char ** declFileNoToName = NULL;
1858 void fixSymbolsInModule( Dwarf_Debug dbg, string & moduleName, Dwarf_Die dieEntry, dyn_hash_map< string, std::vector< Symbol *> > & symbols, dyn_hash_map< Offset, string > & symbolNamesByAddr ) {
1859         start: Dwarf_Half dieTag;
1860         int status = dwarf_tag( dieEntry, & dieTag, NULL );
1861         assert( status == DW_DLV_OK );
1862
1863         string useModuleName = moduleName;
1864
1865         /* For debugging. */
1866         Dwarf_Off dieOffset;
1867         status = dwarf_die_CU_offset( dieEntry, & dieOffset, NULL );
1868         assert( status == DW_DLV_OK );
1869
1870         switch( dieTag ) {
1871                 case DW_TAG_subprogram: 
1872                 case DW_TAG_entry_point: {
1873                         /* Let's try ignoring artificial entries, hmm-kay? */
1874                         Dwarf_Bool isArtificial;
1875                         status = dwarf_hasattr( dieEntry, DW_AT_artificial, & isArtificial, NULL );
1876                         assert( status == DW_DLV_OK );
1877
1878                         if( isArtificial ) { break; }
1879
1880                         /* Only entries with a PC must be defining declarations.  However,
1881                            to avoid trying to decide in which module a DW_TAG_inlined_subroutine's
1882                            DW_AT_abstract_origin belongs, we just insert the abstract origin itself. */
1883                         Dwarf_Bool hasLowPC;
1884                         status = dwarf_hasattr( dieEntry, DW_AT_low_pc, & hasLowPC, NULL );
1885                         assert( status == DW_DLV_OK );
1886
1887                         Dwarf_Bool isAbstractOrigin;
1888                         status = dwarf_hasattr( dieEntry, DW_AT_inline, & isAbstractOrigin, NULL );
1889                         assert( status == DW_DLV_OK );
1890
1891                         if( ! hasLowPC && ! isAbstractOrigin ) { break; }
1892
1893                         bool isDeclaredNotInlined = false;
1894                         /* Inline functions are "uninstrumentable", so leave them off the where axis. */
1895                         if( isAbstractOrigin ) {
1896                                 Dwarf_Attribute inlineAttribute;
1897                                 status = dwarf_attr( dieEntry, DW_AT_inline, & inlineAttribute, NULL );
1898                                 assert( status == DW_DLV_OK );
1899
1900                                 Dwarf_Unsigned inlineTag;
1901                                 status = dwarf_formudata( inlineAttribute, & inlineTag, NULL );
1902                                 assert( status == DW_DLV_OK );
1903
1904                                 if( inlineTag == DW_INL_inlined || inlineTag == DW_INL_declared_inlined ) { break; }
1905                                 if( inlineTag == DW_INL_declared_not_inlined ) { isDeclaredNotInlined = true; }
1906                                 
1907                                 dwarf_dealloc( dbg, inlineAttribute, DW_DLA_ATTR );
1908                                 }
1909
1910                         /* If a DIE has a specification, the specification has its name
1911                            and (optional) linkage name.  */
1912                         Dwarf_Attribute specificationAttribute;
1913                         status = dwarf_attr( dieEntry, DW_AT_specification, & specificationAttribute, NULL );
1914                         assert( status != DW_DLV_ERROR );
1915
1916                         Dwarf_Die nameEntry = dieEntry;
1917                         if( status == DW_DLV_OK ) {
1918                                 Dwarf_Off specificationOffset;
1919                                 status = dwarf_global_formref( specificationAttribute, & specificationOffset, NULL );
1920                                 assert( status == DW_DLV_OK );
1921
1922                                 status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
1923                                 assert( status == DW_DLV_OK );
1924                                 
1925                                 dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
1926                                 } /* end if the DIE has a specification. */
1927
1928                         /* Ignore artificial entries. */
1929                         status = dwarf_hasattr( nameEntry, DW_AT_artificial, & isArtificial, NULL );
1930                         assert( status == DW_DLV_OK );
1931                         if( isArtificial ) { break; }
1932
1933                         /* What's its name? */
1934                         char * dieName = NULL;
1935                         status = dwarf_diename( nameEntry, & dieName, NULL );
1936                         assert( status != DW_DLV_ERROR );
1937
1938                         /* Prefer the linkage (symbol table) name. */
1939                         Dwarf_Attribute linkageNameAttribute;
1940                         status = dwarf_attr( nameEntry, DW_AT_MIPS_linkage_name, & linkageNameAttribute, NULL );
1941                         assert( status != DW_DLV_ERROR );
1942
1943                         bool hasLinkageName = false;
1944                         if( status == DW_DLV_OK ) {
1945                                 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
1946                                 status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
1947                                 assert( status == DW_DLV_OK );
1948                                 hasLinkageName = true;
1949                                 }
1950
1951                         /* Anonymous functions are useless to us. */
1952                         if( dieName == NULL ) { break; }
1953
1954                         /* Try to find the corresponding global symbol name. */
1955                         Dwarf_Die declEntry = nameEntry;
1956                         string globalSymbol = find_symbol( dieName, symbols );
1957                         if( globalSymbol == "" && ! hasLinkageName && isDeclaredNotInlined ) {
1958                                 /* Then scan forward for its concrete instance. */
1959                                 bool first = true;
1960                                 Dwarf_Die siblingDie = dieEntry;
1961                                 while( true ) {
1962                                         Dwarf_Die priorSibling = siblingDie;
1963                                         status = dwarf_siblingof( dbg, siblingDie, & siblingDie, NULL );
1964                                         assert( status != DW_DLV_ERROR );
1965                                         
1966                                         if( ! first ) { dwarf_dealloc( dbg, priorSibling, DW_DLA_DIE ); }
1967                                         if( status == DW_DLV_NO_ENTRY ) { break; }
1968
1969                                         Dwarf_Attribute abstractOriginAttr;
1970                                         status = dwarf_attr( siblingDie, DW_AT_abstract_origin, & abstractOriginAttr, NULL );
1971                                         assert( status != DW_DLV_ERROR );
1972
1973                                         /* Is its abstract origin the current dieEntry? */
1974                                         if( status == DW_DLV_OK ) {
1975                                                 Dwarf_Off abstractOriginOffset;
1976                                                 status = dwarf_formref( abstractOriginAttr, & abstractOriginOffset, NULL );
1977                                                 assert( status == DW_DLV_OK );
1978                                                 
1979                                                 dwarf_dealloc( dbg, abstractOriginAttr, DW_DLA_ATTR );
1980
1981                                                 if( abstractOriginOffset == dieOffset ) {
1982                                                         Dwarf_Addr lowPC;
1983                                                         status = dwarf_lowpc( siblingDie, & lowPC, NULL );
1984                                                         assert( status == DW_DLV_OK );
1985
1986                                                         // bperr( "Found function with pretty name '%s' inlined-not-declared at 0x%lx in module '%s'\n", dieName, (unsigned long)lowPC, useModuleName.c_str() );
1987                                                         if( symbolNamesByAddr.find((Address)lowPC)!=symbolNamesByAddr.end()) {
1988                                                                 string symName = symbolNamesByAddr[(Address)lowPC];
1989                                                                 if( symbols.find(symName) != symbols.end() ) {
1990                                                                         globalSymbol = symName;
1991                                                                         }
1992                                                                 }
1993                                                                 
1994                                                         dwarf_dealloc( dbg, siblingDie, DW_DLA_DIE );
1995                                                         break;
1996                                                         } /* end if we've found _the_ concrete instance */
1997                                                 } /* end if we've found a concrete instance */
1998                                         first = false;
1999                                         } /* end iteration. */
2000                                 } /* end if we're trying to do a by-address look up. */
2001
2002                         /* Update the module information. */
2003                         if( globalSymbol != "" ) {
2004                                 assert( symbols.find(globalSymbol)!=symbols.end());
2005
2006                                 /* If it's not specified, is an inlined function in the same
2007                                    CU/namespace as its use. */
2008                                 if( isDeclaredNotInlined && nameEntry != dieEntry ) {
2009                                         /* Then the function's definition is where it was
2010                                            declared, not wherever it happens to be referenced.
2011
2012                                            Use the decl_file as the useModuleName, if available. */
2013                                         Dwarf_Attribute fileNoAttribute;
2014                                         status = dwarf_attr( declEntry, DW_AT_decl_file, & fileNoAttribute, NULL );
2015                                         assert( status != DW_DLV_ERROR );
2016
2017                                         if( status == DW_DLV_OK ) {
2018                                                 Dwarf_Unsigned fileNo;
2019                                                 status = dwarf_formudata( fileNoAttribute, & fileNo, NULL );
2020                                                 assert( status == DW_DLV_OK );
2021                                                 
2022                                                 dwarf_dealloc( dbg, fileNoAttribute, DW_DLA_ATTR );
2023
2024                                                 useModuleName = declFileNoToName[ fileNo - 1 ];
2025                                                 // bperr( "Assuming declared-not-inlined function '%s' to be in module '%s'.\n", dieName, useModuleName.c_str() );
2026                                                 } /* end if we have declaration file listed */
2027                                         else {
2028                                                 /* This should never happen, but there's not much
2029                                                    we can do if it does. */
2030                                                 }
2031                                         } /* end if isDeclaredNotInlined */
2032
2033                                 unsigned int count = 0;
2034                                 std::vector< Symbol *> & syms = symbols[ globalSymbol ];
2035                                 
2036                                 // /* DEBUG */ fprintf( stderr, "%s[%d]: symbol '%s' is in module '%s'.\n", __FILE__, __LINE__, globalSymbol.c_str(), useModuleName.c_str() );
2037                                 /* If there's only one of symbol of that name, set it regardless. */
2038                                 if( syms.size() == 1 ) { syms[0]->setModuleName( useModuleName ); }
2039                                 else {
2040                                         for( unsigned int i = 0; i < syms.size(); i++ ) {
2041                                                 if( syms[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
2042                                                         symbols[ globalSymbol ][i]->setModuleName( useModuleName );
2043                                                         count++;
2044                                                         }
2045                                                 }
2046                                         if( count < syms.size() ) {
2047                                                 // /* DEBUG */ fprintf( stderr, "%s[%d]: DWARF-derived module information not applied to all symbols of name '%s'\n", __FILE__, __LINE__, globalSymbol.c_str() );
2048                                                 }
2049                                         }
2050                                 } /* end if we found the name in the global symbols */
2051                         else if( ! isAbstractOrigin && (symbols.find(dieName)!=symbols.end())) {
2052                                 unsigned int count = 0;
2053                                 std::vector< Symbol *> & syms = symbols[ dieName ];
2054
2055                                 /* If there's only one, apply regardless. */
2056                                 if( syms.size() == 1 ) { symbols[ globalSymbol ][0]->setModuleName( useModuleName ); }
2057                                 else { 
2058                                         for( unsigned int i = 0; i < syms.size(); i++ ) {
2059                                                 if( syms[ i ]->getLinkage() == Symbol::SL_LOCAL ) {
2060                                                         symbols[ globalSymbol ][i]->setModuleName( useModuleName );
2061                                                         count++;
2062                                                         }
2063                                                 }
2064                                         if( count < syms.size() ) {
2065                                                 // /* DEBUG */ fprintf( stderr, "%s[%d]: DWARF-derived module information not applied to all symbols of name '%s'\n", __FILE__, __LINE__, dieName );
2066                                                 }
2067                                         }
2068                                 } /* end if we think it's a local symbol */
2069
2070                         dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
2071                         } break;
2072
2073                 case DW_TAG_variable:
2074                 case DW_TAG_constant: {
2075                         /* Is this a declaration? */
2076                         Dwarf_Attribute declAttr;
2077                         status = dwarf_attr( dieEntry, DW_AT_declaration, & declAttr, NULL );
2078                         assert( status != DW_DLV_ERROR );
2079
2080                         if( status != DW_DLV_OK ) { break; }
2081                         dwarf_dealloc( dbg, declAttr, DW_DLA_ATTR );
2082
2083                         /* If a DIE has a specification, the specification has its name
2084                            and (optional) linkage name.  */
2085                         Dwarf_Attribute specificationAttribute;
2086                         status = dwarf_attr( dieEntry, DW_AT_specification, & specificationAttribute, NULL );
2087                         assert( status != DW_DLV_ERROR );
2088
2089                         Dwarf_Die nameEntry = dieEntry;
2090                         if( status == DW_DLV_OK ) {
2091                                 Dwarf_Off specificationOffset;
2092                                 status = dwarf_global_formref( specificationAttribute, & specificationOffset, NULL );
2093                                 assert( status == DW_DLV_OK );
2094                                 
2095                                 dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
2096
2097                                 status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
2098                                 assert( status == DW_DLV_OK );
2099                                 } /* end if the DIE has a specification. */
2100
2101                         /* What's its name? */
2102                         char * dieName = NULL;
2103                         status = dwarf_diename( nameEntry, & dieName, NULL );
2104                         assert( status != DW_DLV_ERROR );
2105
2106                         /* Prefer the linkage (symbol table) name. */
2107                         Dwarf_Attribute linkageNameAttribute;
2108                         status = dwarf_attr( nameEntry, DW_AT_MIPS_linkage_name, & linkageNameAttribute, NULL );
2109                         assert( status != DW_DLV_ERROR );
2110
2111                         if( status == DW_DLV_OK ) {
2112                                 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
2113                                 status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
2114                                 assert( status == DW_DLV_OK );
2115                                 }
2116
2117                         /* Anonymous variables are useless to us. */
2118                         if( dieName == NULL ) { break; }
2119                         
2120                         /* Update the module information. */
2121                         string symName = find_symbol( dieName, symbols );
2122                         if( symName != "" ) {
2123                                 assert(symbols.find(symName)!=symbols.end());
2124
2125                                 /* We're assuming global variables. */
2126                                 unsigned int count = 0;
2127                                 std::vector< Symbol *> & syms = symbols[ symName ];
2128
2129                                 /* If there's only one of symbol of that name, set it regardless. */
2130                                 if( syms.size() == 1 ) { symbols[ symName ][0]->setModuleName( useModuleName ); }
2131                                 else {
2132                                         for( unsigned int i = 0; i < syms.size(); i++ ) {
2133                                                 if( syms[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
2134                                                         symbols[ symName ][i]->setModuleName( useModuleName );
2135                                                         count++;
2136                                                         }
2137                                                 }
2138                                         if( count < syms.size() ) {
2139                                                 // /* DEBUG */ fprintf( stderr, "%s[%d]: DWARF-derived module information not applied to all symbols of name '%s'\n", __FILE__, __LINE__, symName.c_str() );
2140                                                 }                                                                       
2141                                         }
2142                                 }
2143          // /* DEBUG */ fprintf( stderr, "%s[%d]: DWARF-derived module %s for symbols of name '%s'\n", __FILE__, __LINE__, useModuleName.c_str(), symName.c_str() );
2144                                 
2145                         dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
2146                         } break;
2147
2148                 default:
2149                         /* If it's not a function or a variable, ignore it. */
2150                         break;
2151                 } /* end tag switch */
2152
2153         /* Recurse to its child, if any. */
2154         Dwarf_Die childDwarf;
2155         status = dwarf_child( dieEntry, & childDwarf, NULL );
2156         assert( status != DW_DLV_ERROR );
2157         if( status == DW_DLV_OK ) {
2158                 fixSymbolsInModule( dbg, moduleName, childDwarf, symbols, symbolNamesByAddr );
2159                 }
2160
2161         /* Recurse to its sibling, if any. */
2162         Dwarf_Die siblingDwarf;
2163         status = dwarf_siblingof( dbg, dieEntry, & siblingDwarf, NULL );
2164         assert( status != DW_DLV_ERROR );
2165         if( status == DW_DLV_OK ) {
2166                 dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
2167         
2168                 /* Force tail-recursion to avoid stack overflows. */
2169                 dieEntry = siblingDwarf;
2170                 goto start;
2171                 }
2172         } /* end fixSymbolsInModule */
2173
2174 unsigned fixSymbolsInModuleByRange(string &moduleName,
2175       Dwarf_Addr modLowPC, Dwarf_Addr modHighPC,
2176       dyn_hash_map<string, std::vector< Symbol *> > *symbols_)
2177 {
2178    unsigned nsyms_altered = 0;
2179
2180    dyn_hash_map< string, std::vector< Symbol *> >::iterator iter = symbols_->begin();
2181
2182    for (;iter!=symbols_->end();iter++)
2183    {
2184       std::string symName = iter->first;
2185       std::vector<Symbol *> & syms = iter->second;
2186
2187       for ( unsigned int i = 0; i < syms.size(); i++ ) 
2188       {
2189          Symbol *sym = syms[i];
2190
2191          if (sym->getAddr() >= modLowPC && sym->getAddr() < modHighPC) 
2192          {
2193             (*symbols_)[symName][i]->setModuleName(moduleName);
2194             nsyms_altered++;
2195             //fprintf(stderr, "%s[%d]:  %s:%p in range [%p, %p) for module %s\n", 
2196             //      FILE__, __LINE__, sym->getName().c_str(), sym->getAddr(), 
2197             //      modLowPC, modHighPC, moduleName.c_str());
2198          }
2199          else
2200          {
2201             //fprintf(stderr, "%s[%d]:  %s:%p not in range [%p, %p) for module %s\n", 
2202             //      FILE__, __LINE__, sym->getName().c_str(), sym->getAddr(), (void *)modLowPC, (void *)modHighPC, moduleName.c_str());
2203          }
2204       }
2205    }
2206
2207    return nsyms_altered;
2208 }
2209
2210 bool Object::fix_global_symbol_modules_static_dwarf(Elf_X &elf)
2211 {
2212    /* Initialize libdwarf. */
2213    Dwarf_Debug dbg;
2214    Dwarf_Unsigned hdr;
2215    Dwarf_Error err;
2216
2217    int status = dwarf_elf_init( elf.e_elfp(), DW_DLC_READ, 
2218          & pd_dwarf_handler, getErrFunc(), & dbg, &err);
2219
2220    if ( status != DW_DLV_OK ) 
2221    {
2222       //fprintf(stderr, "%s[%d]:  failed to init dwarf\n", FILE__, __LINE__);
2223       return false;
2224    }
2225
2226    /* Iterate over the CU headers. */
2227
2228    while ( dwarf_next_cu_header( dbg, NULL, NULL, NULL, NULL, & hdr, NULL ) == DW_DLV_OK ) 
2229    {
2230
2231       /* Obtain the module DIE. */
2232       Dwarf_Die moduleDIE;
2233       status = dwarf_siblingof( dbg, NULL, & moduleDIE, NULL );
2234       assert( status == DW_DLV_OK );
2235
2236       /* Make sure we've got the right one. */
2237       Dwarf_Half moduleTag;
2238       status = dwarf_tag( moduleDIE, & moduleTag, NULL);
2239       assert( status == DW_DLV_OK );
2240       assert( moduleTag == DW_TAG_compile_unit );
2241
2242       /* Extract the name of this module. */
2243       char * dwarfModuleName = NULL;
2244       status = dwarf_diename( moduleDIE, & dwarfModuleName, NULL );
2245       assert( status != DW_DLV_ERROR );
2246
2247       string moduleName;
2248
2249       if ( status == DW_DLV_NO_ENTRY || dwarfModuleName == NULL ) 
2250       {
2251          moduleName = string( "{ANONYMOUS}" );
2252          //assert( moduleName != NULL );
2253       }
2254       else 
2255       {
2256          moduleName = extract_pathname_tail( string(dwarfModuleName) );
2257       }
2258
2259       Dwarf_Addr modLowPC = 0;
2260       Dwarf_Addr modHighPC = (Dwarf_Addr)(-1);
2261       Dwarf_Bool hasLowPC;
2262       Dwarf_Bool hasHighPC;
2263
2264       if ( (status = dwarf_hasattr(moduleDIE, DW_AT_low_pc, &hasLowPC, NULL)) == DW_DLV_OK &&
2265             hasLowPC &&
2266             (status = dwarf_hasattr(moduleDIE, DW_AT_high_pc, &hasHighPC, NULL)) == DW_DLV_OK && 
2267             hasHighPC ) 
2268       {
2269          // Get PC boundaries for the module, if present
2270          status = dwarf_lowpc(moduleDIE, &modLowPC, NULL);
2271          assert(status == DW_DLV_OK);
2272
2273          status = dwarf_highpc(moduleDIE, &modHighPC, NULL);
2274          assert(status == DW_DLV_OK);
2275
2276          if (modHighPC == 0) 
2277          {
2278             fprintf(stderr, "%s[%d]:  WARNING:  hijacking zero modHighPC\n", FILE__, __LINE__);
2279             modHighPC = (Dwarf_Addr)(-1);
2280          }
2281
2282          // Set module names for all symbols that belong to the range
2283          //int nsyms_altered  =
2284
2285          fixSymbolsInModuleByRange(moduleName, modLowPC, modHighPC,
2286                &symbols_);
2287
2288          //fprintf(stderr, "%s[%d]:  fixSymbolsInModuleByRange(%s,%p, %p), match %d syms\n",
2289          //      FILE__, __LINE__, moduleName.c_str(), (void *) modLowPC, (void *) modHighPC, 
2290          //      nsyms_altered);
2291       }
2292       else 
2293       {
2294          /* Acquire declFileNoToName. */
2295          status = dwarf_srcfiles( moduleDIE, & declFileNoToName, & declFileNo, NULL );
2296          assert( status != DW_DLV_ERROR );
2297
2298          if ( status == DW_DLV_OK ) 
2299          {
2300             /* Walk the tree. */
2301
2302             //fprintf(stderr, "%s[%d]:  about to fixSymbolsInModule(%s,...)\n",
2303             //      FILE__, __LINE__, moduleName.c_str());
2304
2305             fixSymbolsInModule( dbg, moduleName, moduleDIE, symbols_, symbolNamesByAddr );
2306
2307             /* Deallocate declFileNoToName. */
2308
2309             for ( Dwarf_Signed i = 0; i < declFileNo; i++ ) 
2310             {
2311                dwarf_dealloc( dbg, declFileNoToName[i], DW_DLA_STRING );
2312             }
2313
2314             dwarf_dealloc( dbg, declFileNoToName, DW_DLA_LIST );        
2315
2316          } /* end if the srcfile information was available */
2317
2318          //else 
2319          //{
2320             //bperr( "Unable to determine modules (%s): no code range or source file information available.\n", moduleName.c_str() );
2321          //} /* end if no source file information available */
2322
2323       } /* end if code range information unavailable */
2324
2325    } /* end scan over CU headers. */
2326
2327    /* Clean up. */
2328
2329    status = dwarf_finish( dbg, NULL );  
2330    assert ( status == DW_DLV_OK );
2331
2332    return true;
2333 }
2334
2335 #else
2336
2337 // dummy definition for non-DWARF platforms
2338 bool Object::fix_global_symbol_modules_static_dwarf(Elf_X &/*elf*/)
2339 { return false; }
2340
2341 #endif // USES_DWARF_DEBUG
2342
2343 /********************************************************
2344  *
2345  * For object files only....
2346  *  read the .stab section to find the module of global symbols
2347  *
2348  ********************************************************/
2349
2350 bool Object::fix_global_symbol_modules_static_stab(Elf_X_Shdr* stabscnp, Elf_X_Shdr* stabstrscnp) 
2351 {
2352    // Read the stab section to find the module of global symbols.
2353    // The symbols appear in the stab section by module. A module begins
2354    // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
2355    // All the symbols in between those two symbols belong to the module.
2356
2357    if (!stabscnp || !stabstrscnp) return false;
2358
2359    Elf_X_Data stabdata = stabscnp->get_data();
2360    Elf_X_Data stabstrdata = stabstrscnp->get_data();
2361    stab_entry *stabptr = NULL;
2362
2363    if (!stabdata.isValid() || !stabstrdata.isValid()) return false;
2364
2365    switch (addressWidth_nbytes) 
2366    {
2367       case 4:
2368          stabptr = new stab_entry_32(stabdata.d_buf(),
2369                stabstrdata.get_string(),
2370                stabscnp->sh_size() / sizeof(stab32));
2371          break;
2372
2373       case 8:
2374          stabptr = new stab_entry_64(stabdata.d_buf(),
2375                stabstrdata.get_string(),
2376                stabscnp->sh_size() / sizeof(stab64));
2377          break;
2378    };
2379
2380    const char *next_stabstr = stabptr->getStringBase();
2381    string module = "DEFAULT_MODULE";
2382
2383    // the stabstr contains one string table for each module.
2384    // stabstr_offset gives the offset from the begining of stabstr of the
2385    // string table for the current module.
2386
2387    bool is_fortran = false;  // is the current module fortran code?
2388
2389    for (unsigned i = 0; i < stabptr->count(); i++) 
2390    {
2391       switch(stabptr->type(i)) 
2392       {
2393          case N_UNDF: /* start of object file */
2394             stabptr->setStringBase(next_stabstr);
2395             next_stabstr = stabptr->getStringBase() + stabptr->val(i);
2396             break;
2397
2398          case N_ENDM: /* end of object file */
2399             is_fortran = false;
2400             module = "DEFAULT_MODULE";
2401             break;
2402
2403          case N_SO: /* compilation source or file name */
2404             if ((stabptr->desc(i) == N_SO_FORTRAN) || (stabptr->desc(i) == N_SO_F90))
2405                is_fortran = true;
2406
2407             module = string(stabptr->name(i));
2408             break;
2409
2410          case N_ENTRY: /* fortran alternate subroutine entry point */
2411          case N_GSYM: /* global symbol */
2412             // the name string of a function or object appears in the stab 
2413             // string table as <symbol name>:<symbol descriptor><other stuff>
2414             // where <symbol descriptor> is a one char code.
2415             // we must extract the name and descriptor from the string
2416             {
2417                const char *p = stabptr->name(i);
2418                // bperr("got %d type, str = %s\n", stabptr->type(i), p);
2419                // if (stabptr->type(i) == N_FUN && strlen(p) == 0) {
2420
2421                if (strlen(p) == 0) 
2422                {
2423                   // GNU CC 2.8 and higher associate a null-named function
2424                   // entry with the end of a function.  Just skip it.
2425                   break;
2426                }
2427
2428                const char *q = strchr(p,':');
2429                unsigned len;
2430
2431                if (q) 
2432                {
2433                   len = q - p;
2434                } 
2435                else 
2436                {
2437                   len = strlen(p);
2438                }
2439
2440                if (len == 0)
2441                {
2442                   // symbol name is empty.Skip it.- 02/12/07 -Giri
2443                   break;
2444                }                
2445
2446                char *sname = new char[len+1];
2447                strncpy(sname, p, len);
2448                sname[len] = 0;
2449
2450                string SymName = string(sname);
2451
2452                // q points to the ':' in the name string, so 
2453                // q[1] is the symbol descriptor. We must check the symbol descriptor
2454                // here to skip things we are not interested in, such as prototypes.
2455
2456                bool res = (symbols_.find(SymName)!=symbols_.end());
2457
2458                if (!res && is_fortran) 
2459                {
2460                   // Fortran symbols usually appear with an '_' appended in .symtab,
2461                   // but not on .stab
2462                   SymName += "_";
2463                   res = (symbols_.find(SymName)!=symbols_.end());
2464                }
2465
2466                if (res && (q == 0 || q[1] != SD_PROTOTYPE)) 
2467                {
2468                   unsigned int count = 0;
2469                   std::vector< Symbol *> & syms = symbols_[SymName];
2470
2471                   /* If there's only one, apply regardless. */
2472                   if ( syms.size() == 1 ) 
2473                   { 
2474                      symbols_[SymName][0]->setModuleName(module); 
2475                   }
2476                   else 
2477                   {
2478                      for ( unsigned int i = 0; i < syms.size(); i++ ) 
2479                      {
2480                         if ( syms[i]->getLinkage() == Symbol::SL_GLOBAL ) 
2481                         {
2482                            symbols_[SymName][i]->setModuleName(module);
2483                            count++;
2484                         }
2485                      }
2486
2487                      //if ( count < syms.size() ) 
2488                      //{
2489                      // /* DEBUG */ fprintf( stderr, "%s[%d]: STABS-derived module information not applied to all symbols of name '%s'\n", __FILE__, __LINE__, SymName.c_str() );
2490                      //}
2491                   }
2492                }
2493                break;
2494             }
2495             case N_FUN: 
2496             /* function */ 
2497             {
2498                const char *p = stabptr->name(i);
2499
2500                if (strlen(p) == 0) 
2501                {
2502                   // Rumours are that GNU CC 2.8 and higher associate a
2503                   // null-named function entry with the end of a
2504                   // function. Just skip it.
2505                   break;
2506                }
2507
2508                const char *q = strchr(p,':');
2509
2510                if (q == 0) 
2511                {
2512                   // bperr( "Unrecognized stab format: %s\n", p);
2513                   // Happens with the Solaris native compiler (.xstabs entries?)
2514                   break;
2515                }
2516
2517                if (q[1] == SD_PROTOTYPE) 
2518                {
2519                   // We see a prototype, skip it
2520                   break;
2521                }
2522
2523                unsigned long entryAddr = stabptr->val(i);
2524
2525                if (entryAddr == 0) 
2526                {
2527                   // The function stab doesn't contain a function address
2528                   // (happens with the Solaris native compiler). We have to
2529                   // look up the symbol by its name. That's unfortunate, since
2530                   // names may not be unique and we may end up assigning a wrong
2531                   // module name to the symbol.
2532                   unsigned len = q - p;
2533                   if (len == 0)
2534                   {
2535                      // symbol name is empty.Skip it.- 02/12/07 -Giri
2536                      break;
2537                   }             
2538
2539                   char *sname = new char[len+1];
2540                   strncpy(sname, p, len);
2541                   sname[len] = 0;
2542                   string nameFromStab = string(sname);
2543                   delete[] sname;
2544
2545                   if (symbols_.find(nameFromStab)!=symbols_.end()) 
2546                   {
2547                      std::vector< Symbol* > & syms = symbols_[nameFromStab];
2548                      if ( syms.size() == 1 ) 
2549                      {
2550                         symbols_[nameFromStab][0]->setModuleName(module);
2551                      }
2552
2553                      /* DEBUG */ else { fprintf( stderr, "%s[%d]: Nonunique STABS name '%s' in module.\n", __FILE__, __LINE__, nameFromStab.c_str() ); }
2554                      /* Otherwise, don't assign a module if we don't know
2555                         to which symbol this refers. */
2556                   }
2557                }
2558                else 
2559                {
2560                   if (symbolNamesByAddr.find(entryAddr)==symbolNamesByAddr.end()) 
2561                   {
2562                      //bperr( "fix_global_symbol_modules_static_stab "
2563                      //    "can't find address 0x%lx of STABS entry %s\n", entryAddr, p);
2564                      break;
2565                   }
2566
2567                   string symName = symbolNamesByAddr[entryAddr];
2568                   assert(symbols_.find(symName)!=symbols_.end());
2569                   std::vector< Symbol *> & syms = symbols_[symName];
2570
2571                   if ( syms.size() == 1 ) 
2572                   {
2573                      symbols_[symName][0]->setModuleName(module);
2574                   }
2575
2576                   /* DEBUG */ else { fprintf( stderr, "%s[%d]: Nonunique id %s in module.\n", __FILE__, __LINE__, symName.c_str() ); }
2577                   /* Otherwise, don't assign a module if we don't know
2578                      to which symbol this refers. */
2579                }
2580                break;
2581             }
2582
2583             default:
2584             /* ignore other entries */
2585             break;
2586             }
2587       }
2588
2589       delete stabptr;
2590
2591       return true;
2592    }
2593
2594
2595 /********************************************************
2596  *
2597  * Run over allsymbols, and stuff symbols contained according 
2598  *  to following rules:
2599  * LOCAL symbols - into (data member) symbols_
2600  * GLOBAL symbols - into (paramater) global_symbols
2601  * WEAK symbols - looks like this case isn't handled correctly
2602  *  for static libraries....
2603  *
2604  ********************************************************/
2605 void Object::insert_symbols_static(std::vector<Symbol *> &allsymbols)
2606 {
2607    unsigned nsymbols = allsymbols.size();
2608 #ifdef TIMED_PARSE
2609    cout << __FILE__ << ":" << __LINE__ << ": stuffing "<<nsymbols 
2610       << " symbols into symbols_ dictionary" << endl; 
2611 #endif
2612    for (unsigned u = 0; u < nsymbols; u++) 
2613    {
2614       insertUniqdSymbol(allsymbols[u], &symbols_, &symbolNamesByAddr);
2615    }    
2616 }
2617
2618 /********************************************************
2619  *
2620  * Run over allsymbols, and stuff symbols it contains into (data
2621  *  member) symbols_. 
2622  *
2623  * Assumes that all kludges, patches, fixes, hacks, to objects
2624  *  in allsymbols have already been made, and that it safe to
2625  *  dump them into symbols_ (data member, instead of stack var....)....
2626  *
2627  ********************************************************/
2628 void Object::insert_symbols_shared(std::vector<Symbol *> &allsymbols) {
2629    unsigned i, nsymbols;
2630
2631    nsymbols = allsymbols.size();
2632 #ifdef TIMED_PARSE
2633    cout << __FILE__ << ":" << __LINE__ << ": stuffing "<<nsymbols 
2634       << " symbols into symbols_ dictionary" << endl; 
2635 #endif
2636    for (i=0;i<nsymbols;i++) {
2637       insertUniqdSymbol(allsymbols[i], &symbols_, &symbolNamesByAddr);
2638    }
2639 }
2640
2641 // find_code_and_data(): populates the following members:
2642 //   code_ptr_, code_off_, code_len_
2643 //   data_ptr_, data_off_, data_len_
2644 void Object::find_code_and_data(Elf_X &elf,
2645       Offset txtaddr, 
2646       Offset dataddr) 
2647 {
2648    for (int i = 0; i < elf.e_phnum(); ++i) {
2649       Elf_X_Phdr phdr = elf.get_phdr(i);
2650
2651       char *file_ptr = (char *)mf->base_addr();
2652
2653       if(!isRegionPresent(phdr.p_paddr(), phdr.p_filesz(), phdr.p_flags()))
2654          regions_.push_back(new Region(i, "", phdr.p_paddr(), phdr.p_filesz(), phdr.p_vaddr(), phdr.p_memsz(), &file_ptr[phdr.p_offset()], getSegmentPerms(phdr.p_flags()), getSegmentType(phdr.p_type(), phdr.p_flags())));
2655
2656       // The code pointer, offset, & length should be set even if
2657       // txtaddr=0, so in this case we set these values by
2658       // identifying the segment that contains the entryAddress
2659       if (((phdr.p_vaddr() <= txtaddr) && 
2660                (phdr.p_vaddr() + phdr.p_filesz() >= txtaddr)) || 
2661             (!txtaddr && ((phdr.p_vaddr() <= entryAddress_) &&
2662                           (phdr.p_vaddr() + phdr.p_filesz() >= entryAddress_)))) {
2663
2664          if (code_ptr_ == 0 && code_off_ == 0 && code_len_ == 0) {
2665             code_ptr_ = (char *)(void*)&file_ptr[phdr.p_offset()];
2666             code_off_ = (Offset)phdr.p_vaddr();
2667             code_len_ = (unsigned)phdr.p_filesz();
2668          }
2669
2670       } else if (((phdr.p_vaddr() <= dataddr) && 
2671                (phdr.p_vaddr() + phdr.p_filesz() >= dataddr)) || 
2672             (!dataddr && (phdr.p_type() == PT_LOAD))) {
2673          if (data_ptr_ == 0 && data_off_ == 0 && data_len_ == 0) {
2674             data_ptr_ = (char *)(void *)&file_ptr[phdr.p_offset()];
2675             data_off_ = (Offset)phdr.p_vaddr();
2676             data_len_ = (unsigned)phdr.p_filesz();
2677          }
2678       }
2679    }
2680    //if (addressWidth_nbytes == 8) bperr( ">>> 64-bit find_code_and_data() successful\n");
2681 }
2682
2683 const char *Object::elf_vaddr_to_ptr(Offset vaddr) const
2684 {
2685    const char *ret = NULL;
2686    unsigned code_size_ = code_len_;
2687    unsigned data_size_ = data_len_;
2688
2689 #if defined(os_irix)
2690    vaddr -= base_addr;
2691 #endif
2692
2693    if (vaddr >= code_off_ && vaddr < code_off_ + code_size_) {
2694       ret = ((char *)code_ptr_) + (vaddr - code_off_);
2695    } else if (vaddr >= data_off_ && vaddr < data_off_ + data_size_) {
2696       ret = ((char *)data_ptr_) + (vaddr - data_off_);
2697    } 
2698
2699    return ret;
2700 }
2701
2702 stab_entry *Object::get_stab_info() const
2703 {
2704    char *file_ptr = (char *)mf->base_addr();
2705
2706    // check that file has .stab info
2707    if (stab_off_ && stab_size_ && stabstr_off_) {
2708       switch (addressWidth_nbytes) {
2709          case 4: // 32-bit object
2710             return new stab_entry_32(file_ptr + stab_off_,
2711                   file_ptr + stabstr_off_,
2712                   stab_size_ / sizeof(stab32));
2713             break;
2714          case 8: // 64-bit object
2715             return new stab_entry_64(file_ptr + stab_off_,
2716                   file_ptr + stabstr_off_,
2717                   stab_size_ / sizeof(stab64));
2718             break;
2719       };
2720    }
2721
2722    //fprintf(stderr, "%s[%d]:  WARNING:  FIXME, stab_off = %d, stab_size = %d, stabstr_off_ = %d\n", FILE__, __LINE__, stab_off_, stab_size_, stabstr_off_);
2723    return new stab_entry_64();
2724 }
2725
2726 Object::Object(MappedFile *mf_, MappedFile *mfd, void (*err_func)(const char *), 
2727       bool alloc_syms) :
2728    AObject(mf_, mfd, err_func), 
2729    EEL(false)
2730 {
2731 #if defined(TIMED_PARSE)
2732    struct timeval starttime;
2733    gettimeofday(&starttime, NULL);
2734 #endif
2735 #if defined(os_solaris)
2736    loadNativeDemangler();
2737 #endif    
2738    is_aout_ = false;
2739    did_open = false;
2740    interpreter_name_ = NULL;
2741    isStripped = false;
2742    if(mf->getFD() != -1)
2743       elfHdr = Elf_X(mf->getFD(), ELF_C_READ);
2744    else
2745       elfHdr = Elf_X((char *)mf->base_addr(), mf->size());
2746
2747    mfForDebugInfo = findMappedFileForDebugInfo();
2748    // ELF header: sanity check
2749    //if (!elfHdr.isValid()|| !pdelf_check_ehdr(elfHdr)) 
2750    if (!elfHdr.isValid())  {
2751       log_elferror(err_func_, "ELF header");
2752       return;
2753    }
2754    else if (!pdelf_check_ehdr(elfHdr)) {
2755       log_elferror(err_func_, "ELF header failed integrity check");
2756    }
2757    if( elfHdr.e_type() == 3 )
2758       load_shared_object(alloc_syms);
2759    else if( elfHdr.e_type() == 1 || elfHdr.e_type() == 2 ) {
2760       is_aout_ = true;
2761       load_object(alloc_syms);
2762    }    
2763    else {
2764       log_perror(err_func_,"Invalid filetype in Elf header");
2765       return;
2766    }
2767 #if defined(TIMED_PARSE)
2768    struct timeval endtime;
2769    gettimeofday(&endtime, NULL);
2770    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2771    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2772    unsigned long difftime = lendtime - lstarttime;
2773    double dursecs = difftime/(1000 );
2774    cout << "obj parsing in Object-elf took "<<dursecs <<" msecs" << endl;
2775 #endif
2776 }
2777
2778 //Object constructor for archive members
2779 Object::Object(MappedFile *mf_, MappedFile *mfd, std::string &member_name, Offset offset,       
2780       void (*err_func)(const char *), void *base, bool alloc_syms) :
2781    AObject(mf_, mfd, err_func), 
2782    EEL(false) {
2783 #if defined(TIMED_PARSE)
2784       struct timeval starttime;
2785       gettimeofday(&starttime, NULL);
2786 #endif
2787 #if defined(os_solaris)
2788       loadNativeDemangler();
2789 #endif    
2790       is_aout_ = false;
2791       did_open = false;
2792       interpreter_name_ = NULL;
2793       isStripped = false;
2794
2795          elfHdr = *(((Elf_X *)base)->e_rand(offset));
2796          Elf_Arhdr *archdr = elf_getarhdr(elfHdr.e_elfp());
2797          assert(member_name == string(archdr->ar_name));
2798
2799          // ELF header: sanity check
2800          //if (!elfHdr.isValid()|| !pdelf_check_ehdr(elfHdr)) 
2801          if (!elfHdr.isValid())  {
2802             log_elferror(err_func_, "ELF header");
2803             return;
2804          }
2805          assert(elfHdr.e_type() == ET_REL);
2806
2807          if( elfHdr.e_type() == 3 )
2808             load_shared_object(alloc_syms);
2809          else if( elfHdr.e_type() == 1 || elfHdr.e_type() == 2 ) {
2810             is_aout_ = true;
2811             load_object(alloc_syms);
2812          }    
2813          else {
2814             log_perror(err_func_,"Invalid filetype in Elf header");
2815             return;
2816          }
2817 #if defined(TIMED_PARSE)
2818          struct timeval endtime;
2819          gettimeofday(&endtime, NULL);
2820          unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2821          unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2822          unsigned long difftime = lendtime - lstarttime;
2823          double dursecs = difftime/(1000 );
2824          cout << "obj parsing in Object-elf took "<<dursecs <<" msecs" << endl;
2825 #endif
2826       }
2827
2828    Object::Object(const Object& obj)
2829       : AObject(obj), EEL(false)
2830       {
2831 #if defined(os_solaris)
2832          loadNativeDemangler();
2833 #endif    
2834          interpreter_name_ = obj.interpreter_name_;
2835          isStripped = obj.isStripped;
2836          loadAddress_ = obj.loadAddress_;
2837          entryAddress_ = obj.entryAddress_;
2838          relocation_table_ = obj.relocation_table_;
2839          fbt_ = obj.fbt_;
2840          elfHdr = obj.elfHdr;
2841          deps_ = obj.deps_;
2842       }
2843
2844    const Object& Object::operator=(const Object& obj) 
2845    {
2846       (void) AObject::operator=(obj);
2847
2848       dynsym_addr_ = obj.dynsym_addr_;
2849       dynstr_addr_ = obj.dynstr_addr_;
2850       got_addr_ = obj.got_addr_;
2851       plt_addr_ = obj.plt_addr_;
2852       plt_size_ = obj.plt_size_;
2853       plt_entry_size_ = obj.plt_entry_size_;
2854       rel_plt_addr_ = obj.rel_plt_addr_;
2855       rel_plt_size_ = obj.rel_plt_size_;
2856       rel_plt_entry_size_ = obj.rel_plt_entry_size_;
2857       rel_size_ = obj.rel_size_;
2858       rel_entry_size_ = obj.rel_entry_size_;
2859       stab_off_ = obj.stab_off_;
2860       stab_size_ = obj.stab_size_;
2861       stabstr_off_ = obj.stabstr_off_;
2862       relocation_table_  = obj.relocation_table_;
2863       fbt_  = obj.fbt_;
2864       dwarvenDebugInfo = obj.dwarvenDebugInfo;
2865       symbolNamesByAddr = obj.symbolNamesByAddr;
2866       versionMapping = obj.versionMapping;
2867       versionFileNameMapping = obj.versionFileNameMapping;
2868       deps_ = obj.deps_;
2869       elfHdr = obj.elfHdr; 
2870       return *this;
2871    }
2872
2873    Object::~Object()
2874    {
2875       //   if (fileName) free((void *)fileName);
2876       unsigned i;
2877       relocation_table_.clear();
2878       fbt_.clear();
2879       for(i=0; i<allRegionHdrs.size();i++)
2880          delete allRegionHdrs[i];
2881       allRegionHdrs.clear();
2882       symbolNamesByAddr.clear();
2883       versionMapping.clear();
2884       versionFileNameMapping.clear();
2885       deps_.clear();
2886    }
2887
2888    void Object::log_elferror(void (*err_func)(const char *), const char* msg) 
2889    {
2890       const char* err = elf_errmsg(elf_errno());
2891       err = err ? err: "(bad elf error)";
2892       string str = string(err)+string(msg);
2893       err_func(str.c_str());
2894    }
2895
2896    bool Object::get_func_binding_table(std::vector<relocationEntry> &fbt) const 
2897    {
2898       if(!plt_addr_ || (!fbt_.size())) return false;
2899       fbt = fbt_;
2900       return true;
2901    }
2902
2903    bool Object::get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const 
2904    {
2905       if(!plt_addr_ || (!fbt_.size())) return false;
2906       fbt = &fbt_;
2907       return true;
2908    }
2909
2910    void Object::getDependencies(std::vector<std::string> &deps){
2911       deps = deps_;
2912    }
2913
2914    bool Object::addRelocationEntry(relocationEntry &re)
2915    {
2916       relocation_table_.push_back(re);
2917       return true;
2918    }
2919
2920 #ifdef DEBUG
2921
2922    // stream-based debug output
2923    const ostream &Object::dump_state_info(ostream &s) 
2924    {
2925       s << "Debugging Information for Object (address) : " << this << endl;
2926
2927       s << " <<begin debugging info for base object>>" << endl;
2928       AObject::dump_state_info(s);
2929       s << " <<end debuggingo info for base object>>" << endl;
2930
2931       s << " dynsym_addr_ = " << dynsym_addr_ << endl;
2932   s << " dynstr_addr_ = " << dynstr_addr_ << endl;
2933   s << " got_addr_ = " << got_addr_ << endl;
2934   s << " plt_addr_ = " << plt_addr_ << endl;
2935   s << " plt_size_ = " << plt_size_ << endl;
2936   s << " plt_entry_size_ = " << plt_entry_size_ << endl;
2937   s << " rel_plt_addr_ = " << rel_plt_addr_ << endl; 
2938   s << " rel_plt_size_ = " << rel_plt_size_ << endl;
2939   s << " rel_plt_entry_size_ = " << rel_plt_entry_size_ << endl;
2940   s << " rel_size_ = " << rel_size_ << endl;
2941   s << " rel_entry_size_ = " << rel_entry_size_ << endl;
2942   s << " stab_off_ = " << stab_off_ << endl;
2943   s << " stab_size_ = " << stab_size_ << endl;
2944   s << " stabstr_off_ = " << stabstr_off_ << endl;
2945   s << " dwarvenDebugInfo = " << dwarvenDebugInfo << endl;
2946
2947   // and dump the relocation table....
2948   s << " fbt_ = (field seperator :: )" << endl;   
2949   for (unsigned i=0; i < fbt_.size(); i++) {
2950     s << fbt_[i] << " :: "; 
2951   }
2952   s << endl;
2953
2954   return s;
2955
2956
2957 #endif
2958
2959
2960 Offset Object::getPltSlot(string funcName) const
2961 {
2962    relocationEntry re;
2963    bool found= false;
2964    Offset offset=0;
2965
2966    for ( unsigned int i = 0; i < fbt_.size(); i++ ){
2967       if (funcName == fbt_[i].name() ){
2968          found = true;
2969          offset =  fbt_[i].rel_addr();
2970       }
2971    }
2972
2973    return offset;       
2974 }
2975
2976 //
2977 // get_valid_memory_areas - get ranges of code/data segments that have
2978 //                       sections mapped to them
2979 //
2980
2981 void Object::get_valid_memory_areas(Elf_X &elf)
2982 {
2983    for (unsigned i = 0; i < elf.e_shnum(); ++i) {
2984       Elf_X_Shdr shdr = elf.get_shdr(i);
2985       if ( !shdr.isValid()) { 
2986          break; 
2987       }
2988       if (shdr.sh_flags() & SHF_ALLOC) { // This section is in memory
2989          if (code_off_ <= shdr.sh_addr() &&
2990                shdr.sh_addr() <= code_off_ + code_len_) {
2991             if (shdr.sh_addr() < code_vldS_)
2992                code_vldS_ = shdr.sh_addr();
2993             if (shdr.sh_addr() + shdr.sh_size() > code_vldE_)
2994                code_vldE_ = shdr.sh_addr() + shdr.sh_size();
2995
2996          } else if (data_off_ <= shdr.sh_addr() &&
2997                shdr.sh_addr() <= data_off_ + data_len_) {
2998             if (shdr.sh_addr() < data_vldS_)
2999                data_vldS_ = shdr.sh_addr();
3000             if (shdr.sh_addr() + shdr.sh_size() > data_vldE_)
3001                data_vldE_ = shdr.sh_addr() + shdr.sh_size();
3002          }
3003       }
3004    }
3005 }
3006
3007 //
3008 // parseCompilerType - parse for compiler that was used to generate object
3009 //
3010 //
3011 //
3012 #if defined(os_linux)
3013 // Differentiating between g++ and pgCC by stabs info (as in the solaris/
3014 // aix case, below) will not work; the gcc-compiled object files that
3015 // get included at link time will fill in the N_OPT stabs line. Instead,
3016 // look for "pgCC_compiled." symbols.
3017 bool parseCompilerType(Object *objPtr)
3018 {
3019    dyn_hash_map<string, std::vector<Symbol *> >*syms = objPtr->getAllSymbols(); 
3020    if(syms->find("pgCC_compiled.") != syms->end())
3021       return true;
3022    return false;        
3023
3024 #else
3025 bool parseCompilerType(Object *objPtr) 
3026 {
3027    stab_entry *stabptr = objPtr->get_stab_info();
3028    const char *next_stabstr = stabptr->getStringBase();
3029
3030    for (unsigned int i=0; i < stabptr->count(); ++i) {
3031       // if (stabstrs) bperr("parsing #%d, %s\n", stabptr->type(i), stabptr->name(i));
3032       switch (stabptr->type(i)) {
3033
3034          case N_UNDF: /* start of object file */
3035             /* value contains offset of the next string table for next module */
3036             // assert(stabptr.nameIdx(i) == 1);
3037             stabptr->setStringBase(next_stabstr);
3038             next_stabstr = stabptr->getStringBase() + stabptr->val(i);
3039             break;
3040
3041          case N_OPT: /* Compiler options */
3042 #if defined(os_solaris) 
3043             if (strstr(stabptr->name(i), "Sun") != NULL ||
3044                   strstr(stabptr->name(i), "Forte") != NULL)
3045             {
3046                delete stabptr;
3047                return true;
3048             }
3049 #endif
3050             delete stabptr;
3051             return false;
3052       }
3053    }
3054    delete stabptr;
3055    return false; // Shouldn't happen - maybe N_OPT stripped
3056 }
3057 #endif
3058
3059
3060 #if defined(os_linux) && (defined(arch_x86) || defined(arch_x86_64))
3061
3062 static unsigned long read_uleb128(const unsigned char *data, unsigned *bytes_read)
3063 {
3064    unsigned long result = 0;
3065    unsigned shift = 0;
3066    *bytes_read = 0;
3067    while (1)
3068    {
3069       result |= (data[*bytes_read] & 0x7f) << shift;
3070       if ((data[(*bytes_read)++] & 0x80) == 0)
3071          break;
3072       shift += 7;
3073    }
3074    return result;
3075 }
3076
3077 static signed long read_sleb128(const unsigned char *data, unsigned *bytes_read)
3078 {
3079    unsigned long result = 0;
3080    unsigned shift = 0;
3081    *bytes_read = 0;
3082    while (1)
3083    {
3084       result |= (data[*bytes_read] & 0x7f) << shift;
3085       shift += 7;
3086       if ((data[*bytes_read] & 0x80) == 0)
3087          break;
3088       (*bytes_read)++;
3089    }
3090    if (shift < sizeof(int) && (data[*bytes_read] & 0x40))
3091       result |= -(1 << shift);
3092    (*bytes_read)++;
3093    return result;
3094 }
3095
3096 #define DW_EH_PE_absptr  0x00
3097 #define DW_EH_PE_uleb128 0x01
3098 #define DW_EH_PE_udata2  0x02
3099 #define DW_EH_PE_udata4  0x03
3100 #define DW_EH_PE_udata8  0x04
3101 #define DW_EH_PE_sleb128 0x09
3102 #define DW_EH_PE_sdata2  0x0A
3103 #define DW_EH_PE_sdata4  0x0B
3104 #define DW_EH_PE_sdata8  0x0C
3105 #define DW_EH_PE_pcrel   0x10
3106 #define DW_EH_PE_textrel 0x20
3107 #define DW_EH_PE_datarel 0x30
3108 #define DW_EH_PE_funcrel 0x40
3109 #define DW_EH_PE_aligned 0x50
3110 #define DW_EH_PE_omit    0xff
3111
3112 typedef struct {
3113    int word_size;
3114    unsigned long pc;
3115    unsigned long text;
3116    unsigned long data;
3117    unsigned long func;
3118 } mach_relative_info;
3119
3120 static int read_val_of_type(int type, unsigned long *value, const unsigned char *addr,
3121                            const mach_relative_info &mi)
3122 {
3123    unsigned size;
3124    if (type == DW_EH_PE_omit)
3125       return 0;
3126
3127    unsigned long base = 0x0;
3128    /**
3129     * LSB Standard says that the upper four bits (0xf0) encode the base.
3130     * Except that none of these values should their upper bits set,
3131     * and I'm finding the upper bit seems to sometimes contain garbage.
3132     * gcc uses the 0x70 bits in its exception parsing, so that's what we'll do.
3133     **/
3134    switch (type & 0x70)
3135    {
3136       case DW_EH_PE_pcrel:
3137          base = mi.pc;
3138          break;
3139       case DW_EH_PE_textrel:
3140          base = mi.text;
3141          break;
3142       case DW_EH_PE_datarel:
3143          base = mi.data;
3144          break;
3145       case DW_EH_PE_funcrel:
3146          base = mi.func;
3147          break;
3148    }
3149
3150    switch (type & 0x0f)
3151    {
3152       case DW_EH_PE_absptr:
3153          if (mi.word_size == 4) {
3154             *value = (unsigned long) *((const uint32_t *) addr);
3155             size = 4;
3156          }
3157          else if (mi.word_size == 8) {
3158             *value = (unsigned long) *((const uint64_t *) addr);
3159             size = 8;
3160          }
3161          break;
3162       case DW_EH_PE_uleb128:
3163          *value = base + read_uleb128(addr, &size);
3164          break;
3165       case DW_EH_PE_sleb128:
3166          *value = base + read_sleb128(addr, &size);
3167          break;
3168       case DW_EH_PE_udata2:
3169          *value = base + *((const uint16_t *) addr);
3170          size = 2;
3171          break;
3172       case DW_EH_PE_sdata2:         
3173          *value = base + *((const int16_t *) addr);
3174          size = 2;
3175          break;
3176       case DW_EH_PE_udata4:
3177          *value = base + *((const uint32_t *) addr);
3178          size = 4;
3179          break;
3180       case DW_EH_PE_sdata4:
3181          *value = base + *((const int32_t *) addr);
3182          size = 4;
3183          break;
3184       case DW_EH_PE_udata8:
3185          *value = base + *((const uint64_t *) addr);
3186          size = 8;
3187          break;
3188       case DW_EH_PE_sdata8:
3189          *value = base + *((const int64_t *) addr);
3190          size = 8;
3191          break;
3192       default:
3193          return -1;
3194    }
3195
3196    if ((type & 0x70) == DW_EH_PE_aligned)
3197    {
3198       if (mi.word_size == 4) {
3199          *value &= ~(0x3l);
3200       }
3201       else if (mi.word_size == 8) {
3202          *value &= ~(0x7l);
3203       }
3204    }
3205
3206    return size;
3207 }
3208
3209 /**
3210  * On GCC 3.x/x86 we find catch blocks as follows:
3211  *   1. We start with a list of FDE entries in the .eh_frame
3212  *      table.  
3213  *   2. Each FDE entry has a pointer to a  CIE entry.  The CIE
3214  *      tells us whether the FDE has any 'Augmentations', and
3215  *      the types of those augmentations.  The FDE also
3216  *      contains a pointer to a function.
3217  *   3. If one of the FDE augmentations is a 'Language Specific Data Area' 
3218  *      then we have a pointer to one or more entires in the gcc_except_table.
3219  *   4. The gcc_except_table contains entries that point 
3220  *      to try and catch blocks, all encoded as offsets
3221  *      from the function start (it doesn't tell you which
3222  *      function, however). 
3223  *   5. We can add the function offsets from the gcc_except_table
3224  *      to the function pointer from the FDE to get all of
3225  *      the try/catch blocks.  
3226  **/ 
3227 #define SHORT_FDE_HLEN 4 
3228 #define LONG_FDE_HLEN 12
3229 static 
3230 int read_except_table_gcc3(Dwarf_Fde *fde_data, Dwarf_Signed fde_count,
3231                            mach_relative_info &mi,
3232                            Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
3233                            std::vector<ExceptionBlock> &addresses)
3234 {
3235    Dwarf_Error err = (Dwarf_Error) NULL;
3236    Dwarf_Addr low_pc;
3237    Dwarf_Unsigned bytes_in_cie;
3238    Dwarf_Off fde_offset, cie_offset;
3239    Dwarf_Fde fde;
3240    Dwarf_Cie cie;
3241    int status, result, ptr_size;
3242    char *augmentor;
3243    unsigned char lpstart_format, ttype_format, table_format;
3244    unsigned long value, table_end, region_start, region_size;
3245    unsigned long catch_block, action, augmentor_len;
3246    Dwarf_Small *fde_augdata, *cie_augdata;
3247    Dwarf_Unsigned fde_augdata_len, cie_augdata_len;
3248    
3249    //For each FDE
3250    for (int i = 0; i < fde_count; i++) {
3251       unsigned int j;
3252       unsigned char lsda_encoding = 0xff, personality_encoding = 0xff;
3253       unsigned char *lsda_ptr = NULL, *personality_routine = NULL;
3254       unsigned char *cur_augdata;
3255       unsigned long except_off;
3256       unsigned long fde_addr, cie_addr;
3257       unsigned char *fde_bytes, *cie_bytes;
3258
3259       //Get the FDE
3260       status = dwarf_get_fde_n(fde_data, (Dwarf_Unsigned) i, &fde, &err);
3261       if (status != DW_DLV_OK) {
3262          pd_dwarf_handler(err, NULL);
3263          return false;
3264       }
3265
3266       //After this set of computations we should have:
3267       // low_pc = mi.func = the address of the function that contains this FDE
3268       // fde_bytes = the start of the FDE in our memory space
3269       // cie_bytes = the start of the CIE in our memory space
3270       status = dwarf_get_fde_range(fde, &low_pc, NULL, (void **) &fde_bytes,
3271                                    NULL, &cie_offset, NULL, 
3272                                    &fde_offset, &err);
3273       if (status != DW_DLV_OK) {
3274          pd_dwarf_handler(err, NULL);
3275          return false;
3276       }
3277       //The LSB strays from the DWARF here, when parsing the except_eh section
3278       // the cie_offset is relative to the FDE rather than the start of the
3279       // except_eh section.
3280       cie_offset = fde_offset - cie_offset +
3281          (*(uint32_t*)fde_bytes == 0xffffffff ? LONG_FDE_HLEN : SHORT_FDE_HLEN);
3282       cie_bytes = (unsigned char *)eh_frame->get_data().d_buf() + cie_offset;
3283
3284       //Get the CIE for the FDE
3285       status = dwarf_get_cie_of_fde(fde, &cie, &err);
3286       if (status != DW_DLV_OK) {
3287          pd_dwarf_handler(err, NULL);
3288          return false;
3289       }
3290
3291       //Get the Augmentation string for the CIE
3292       status = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, &augmentor, 
3293                                   NULL, NULL, NULL, NULL, NULL, &err); 
3294       if (status != DW_DLV_OK) {
3295          pd_dwarf_handler(err, NULL);
3296          return false;
3297       }
3298       
3299       //Check that the string pointed to by augmentor has a 'L',
3300       // meaning we have a LSDA
3301       augmentor_len = (augmentor == NULL) ? 0 : strlen(augmentor);
3302       for (j = 0; j < augmentor_len; j++) {
3303          if (augmentor[j] == 'L') {
3304             break;
3305          }
3306       }
3307       if (j == augmentor_len)
3308          //If we don't have a language specific data area, then
3309          // we don't care about this FDE.
3310          continue;
3311
3312       //Some ptr encodings may be of type DW_EH_PE_pcrel, which means
3313       // that they're relative to their own location in the binary.  
3314       // We'll figure out where the FDE and CIE original load addresses
3315       // were and use those in pcrel computations.
3316       fde_addr = eh_frame->sh_addr() + fde_offset;
3317       cie_addr = eh_frame->sh_addr() + cie_offset;
3318       
3319       //Extract encoding information from the CIE.  
3320       // The CIE may have augmentation data, specified in the 
3321       // Linux Standard Base. The augmentation string tells us how
3322       // which augmentation data is present.  We only care about one 
3323       // field, a byte telling how the LSDA pointer is encoded.
3324       status = dwarf_get_cie_augmentation_data(cie, 
3325                                                &cie_augdata,
3326                                                &cie_augdata_len,
3327                                                &err);
3328       if (status != DW_DLV_OK) {
3329          pd_dwarf_handler(err, NULL);
3330          return false;
3331       }
3332
3333       cur_augdata = (unsigned char *) cie_augdata;
3334       lsda_encoding = DW_EH_PE_omit;
3335       for (j=0; j<augmentor_len; j++)
3336       {
3337          if (augmentor[j] == 'L')
3338          {
3339             lsda_encoding = *cur_augdata;
3340             cur_augdata++;
3341          }
3342          else if (augmentor[j] == 'P')
3343          {