Object-elf.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 /************************************************************************
00032  * $Id: Object-elf.C,v 1.54 2008/11/03 15:19:25 jaw Exp $
00033  * Object-elf.C: Object class for ELF file format
00034  ************************************************************************/
00035 
00036 #include "Type.h"
00037 #include "Variable.h"
00038 #include "Symbol.h"
00039 #include "Symtab.h"
00040 #include "Object.h"
00041 
00042 #include "emitElf.h"
00043 #include "Module.h"
00044 #include "Aggregate.h"
00045 #include "Function.h"
00046 
00047 #include "debug.h"
00048 
00049 #include "dwarf/h/dwarfHandle.h"
00050 
00051 #if defined(x86_64_unknown_linux2_4) || \
00052     defined(ppc64_linux) || \
00053     (defined(os_freebsd) && defined(arch_x86_64))
00054 #include "emitElf-64.h"
00055 #endif
00056 
00057 #include "dwarfWalker.h"
00058 
00059 using namespace Dyninst;
00060 using namespace Dyninst::SymtabAPI;
00061 using namespace Dyninst::Dwarf;
00062 using namespace std;
00063 
00064 #if !defined(_Object_elf_h_)
00065 #error "Object-elf.h not #included"
00066 #endif
00067 
00068 #include <elf.h>
00069 #include <stdio.h>
00070 #include <algorithm>
00071 
00072 #if defined(USES_DWARF_DEBUG)
00073 #include "dwarf.h"
00074 #include "libdwarf.h"
00075 #endif
00076 
00077 //#include "symutil.h"
00078 #include "common/h/pathName.h"
00079 #include "Collections.h"
00080 #if defined(TIMED_PARSE)
00081 #include <sys/time.h>
00082 #endif
00083 #include <iostream>
00084 #include <iomanip>
00085 
00086 #include <fstream>
00087 #include <sys/stat.h>
00088 
00089 #include <boost/assign/list_of.hpp>
00090 #include <boost/assign/std/set.hpp>
00091 
00092 #include "dynutil/h/SymReader.h"
00093 
00094 using namespace boost::assign;
00095 
00096 #include <libgen.h>
00097 
00098 // add some space to avoid looking for functions in data regions
00099 #define EXTRA_SPACE 8
00100 
00101 bool Object::truncateLineFilenames = true;
00102     
00103 string symt_current_func_name;
00104 string symt_current_mangled_func_name;
00105 Symbol *symt_current_func = NULL;
00106 
00107 std::vector<Symbol *> opdsymbols_;
00108 
00109 extern void print_symbols( std::vector< Symbol *>& allsymbols );
00110 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
00111 
00112 void (*dwarf_err_func)(const char *);   // error callback for dwarf errors
00113 
00114 static bool pdelf_check_ehdr(Elf_X &elf)
00115 {
00116   // Elf header integrity check
00117 
00118   // This implies a valid header is a header for an executable, a shared object
00119   // or a relocatable file (e.g .o) and it either has section headers or program headers
00120 
00121   return ( (elf.e_type() == ET_EXEC || elf.e_type() == ET_DYN || elf.e_type() == ET_REL ) &&
00122            (   ((elf.e_shoff() != 0) && (elf.e_shnum() != 0)) 
00123             || ((elf.e_phoff() != 0) && (elf.e_phnum() != 0))
00124            )
00125          );
00126 }
00127 
00128 const char *pdelf_get_shnames(Elf_X *elf)
00129 {
00130   const char *result = NULL;
00131   size_t shstrndx = elf->e_shstrndx();
00132 
00133   Elf_X_Shdr &shstrscn = elf->get_shdr(shstrndx);
00134   if (shstrscn.isValid()) {
00135     Elf_X_Data shstrdata = shstrscn.get_data();
00136     if (shstrdata.isValid())
00137       result = shstrdata.get_string();
00138   }
00139   return result;
00140 }
00141 
00142 //
00143 // SectionHeaderSortFunction
00144 // 
00145 // Compare function for use with the Vector<T> sort method.
00146 //
00147 struct  SectionHeaderSortFunction: public binary_function<Elf_X_Shdr *, Elf_X_Shdr *, bool> 
00148 {
00149   bool operator()(Elf_X_Shdr *hdr1, Elf_X_Shdr *hdr2) {
00150     return (hdr1->sh_addr() < hdr2->sh_addr()); 
00151   }
00152 };
00153 
00154 Region::perm_t getSegmentPerms(unsigned long flags){
00155   if(flags == 7)
00156     return Region::RP_RWX;
00157   else if(flags == 6)
00158     return Region::RP_RW;
00159   else if(flags == 5)
00160     return Region::RP_RX;
00161   else
00162     return Region::RP_R;
00163 }
00164 
00165 Region::RegionType getSegmentType(unsigned long type, unsigned long flags)
00166 {
00167   if(type == PT_DYNAMIC)
00168     return Region::RT_DYNAMIC;
00169   if(flags == 7)
00170     return Region::RT_TEXTDATA;
00171   if(flags == 5)
00172     return Region::RT_TEXT;
00173   if(flags == 6)
00174     return Region::RT_DATA;
00175   return Region::RT_OTHER;
00176 }
00177 
00178 /* binary search to find the section starting at a particular address */
00179 Elf_X_Shdr *Object::getRegionHdrByAddr(Offset addr) 
00180 {
00181   unsigned end = allRegionHdrs.size() - 1, start = 0;
00182   unsigned mid = 0; 
00183   while(start < end) {
00184     mid = start + (end-start)/2;
00185     if(allRegionHdrs[mid]->sh_addr() == addr)
00186       return allRegionHdrs[mid];
00187     else if(allRegionHdrs[mid]->sh_addr() < addr)
00188       start = mid + 1;
00189     else
00190       end = mid;
00191   }
00192   if(allRegionHdrs[start]->sh_addr() == addr)
00193     return allRegionHdrs[start];
00194   return NULL;
00195 }
00196 
00197 /* binary search to find the index into the RegionHdrs vector
00198    of the section starting at a partidular address*/
00199 int Object::getRegionHdrIndexByAddr(Offset addr) 
00200 {
00201   int end = allRegionHdrs.size() - 1, start = 0;
00202   int mid = 0; 
00203   while(start < end) {
00204     mid = start + (end-start)/2;
00205     if(allRegionHdrs[mid]->sh_addr() == addr)
00206       return mid;
00207     else if(allRegionHdrs[mid]->sh_addr() < addr)
00208       start = mid + 1;
00209     else
00210       end = mid;
00211   }
00212   if(allRegionHdrs[start]->sh_addr() == addr)
00213     return start;
00214   return -1;
00215 }
00216 
00217 Elf_X_Shdr *Object::getRegionHdrByIndex(unsigned index) 
00218 {
00219   if (index >= allRegionHdrs.size())
00220     return NULL;
00221   return allRegionHdrs[index];
00222 }
00223 
00224 /* Check if there is a section which belongs to the segment and update permissions of that section.
00225  * Return value indicates whether the segment has to be added to the list of regions*/
00226 bool Object::isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned segPerms){
00227   bool present = false;
00228   for(unsigned i = 0; i < regions_.size() ;i++){
00229     if((regions_[i]->getDiskOffset() >= segmentStart) && 
00230        ((regions_[i]->getDiskOffset()+regions_[i]->getDiskSize()) <= (segmentStart+segmentSize))){
00231       present = true;
00232       regions_[i]->setRegionPermissions(getSegmentPerms(segPerms));
00233     }
00234 
00235   }
00236   return present;
00237 }
00238 
00239 Region::perm_t getRegionPerms(unsigned long flags){
00240   if((flags & SHF_WRITE) && !(flags & SHF_EXECINSTR))
00241     return Region::RP_RW;
00242   else if(!(flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
00243     return Region::RP_RX;
00244   else if((flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
00245     return Region::RP_RWX;
00246   else
00247     return Region::RP_R;
00248 }
00249 
00250 Region::RegionType getRegionType(unsigned long type, unsigned long flags, const char *reg_name){
00251   switch(type){
00252   case SHT_SYMTAB:
00253   case SHT_DYNSYM:
00254     return Region::RT_SYMTAB;
00255   case SHT_STRTAB:
00256     return Region::RT_STRTAB;
00257   case SHT_REL:
00258     return Region::RT_REL;
00259   case SHT_RELA:
00260     return Region::RT_RELA;
00261   case SHT_NOBITS:
00262      //Darn it, Linux/PPC has the PLT as a NOBITS.  Can't just default
00263      // call this bss
00264      if (strcmp(reg_name, ".plt") == 0)
00265         return Region::RT_OTHER;
00266      else
00267         return Region::RT_BSS;
00268   case SHT_PROGBITS:
00269     if((flags & SHF_EXECINSTR) && (flags & SHF_WRITE))
00270       return Region::RT_TEXTDATA;
00271     else if(flags & SHF_EXECINSTR)
00272       return Region::RT_TEXT;
00273     else
00274       return Region::RT_DATA;
00275   case SHT_DYNAMIC:
00276     return Region::RT_DYNAMIC;
00277   case SHT_HASH:
00278     return Region::RT_HASH;
00279   case SHT_GNU_versym:
00280     return Region::RT_SYMVERSIONS;
00281   case SHT_GNU_verdef:
00282     return Region::RT_SYMVERDEF;
00283   case SHT_GNU_verneed:
00284     return Region::RT_SYMVERNEEDED;
00285   default:
00286     return Region::RT_OTHER;
00287   }
00288 }
00289 
00290 static Region::RegionType getRelTypeByElfMachine(Elf_X *localHdr) {
00291     Region::RegionType ret;
00292     switch(localHdr->e_machine()) {
00293         case EM_SPARC:
00294         case EM_SPARC32PLUS:
00295         case EM_SPARCV9:
00296         case EM_PPC:
00297         case EM_PPC64:
00298         case EM_X86_64:
00299         case EM_IA_64:
00300             ret = Region::RT_RELA;
00301             break;
00302         default:
00303             ret = Region::RT_REL;
00304             break;
00305     }
00306     return ret;
00307 }
00308 
00309 const char* EDITED_TEXT_NAME = ".edited.text";
00310 // const char* INIT_NAME        = ".init";
00311 const char *INTERP_NAME      = ".interp";
00312 const char* FINI_NAME        = ".fini";
00313 const char* TEXT_NAME        = ".text";
00314 const char* BSS_NAME         = ".bss";
00315 const char* SYMTAB_NAME      = ".symtab";
00316 const char* STRTAB_NAME      = ".strtab";
00317 const char* STAB_NAME        = ".stab";
00318 const char* STABSTR_NAME     = ".stabstr";
00319 const char* STAB_INDX_NAME   = ".stab.index";
00320 const char* STABSTR_INDX_NAME= ".stab.indexstr";
00321 const char* COMMENT_NAME= ".comment";
00322 const char* OPD_NAME         = ".opd"; // PPC64 Official Procedure Descriptors
00323 // sections from dynamic executables and shared objects
00324 const char* PLT_NAME         = ".plt";
00325 #if defined(os_vxworks)
00326 const char* REL_PLT_NAME     = ".rela.text";
00327 #else
00328 const char* REL_PLT_NAME     = ".rela.plt"; // sparc-solaris
00329 #endif  
00330 const char* REL_PLT_NAME2    = ".rel.plt";  // x86-solaris
00331 const char* GOT_NAME         = ".got";
00332 const char* DYNSYM_NAME      = ".dynsym";
00333 const char* DYNSTR_NAME      = ".dynstr";
00334 const char* DATA_NAME        = ".data";
00335 const char* RO_DATA_NAME     = ".ro_data";  // mips
00336 const char* DYNAMIC_NAME     = ".dynamic";
00337 const char* EH_FRAME_NAME    = ".eh_frame";
00338 const char* EXCEPT_NAME      = ".gcc_except_table";
00339 const char* EXCEPT_NAME_ALT  = ".except_table";
00340 
00341 set<string> debugInfoSections = list_of(string(SYMTAB_NAME))
00342   (string(STRTAB_NAME));
00343 
00344 // loaded_elf(): populate elf section pointers
00345 // for EEL rewritten code, also populate "code_*_" members
00346 bool Object::loaded_elf(Offset& txtaddr, Offset& dataddr,
00347                         Elf_X_Shdr* &bssscnp,
00348                         Elf_X_Shdr*& symscnp, Elf_X_Shdr*& strscnp, 
00349                         Elf_X_Shdr*& stabscnp, Elf_X_Shdr*& stabstrscnp, 
00350                         Elf_X_Shdr*& stabs_indxcnp, Elf_X_Shdr*& stabstrs_indxcnp, 
00351                         Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
00352                         Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
00353                         Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr* &dynamic_scnp, 
00354                         Elf_X_Shdr*& eh_frame, Elf_X_Shdr*& gcc_except, 
00355                         Elf_X_Shdr *& interp_scnp, Elf_X_Shdr *& opd_scnp, 
00356                         bool)
00357 {
00358    std::map<std::string, int> secnNameMap;
00359    dwarf_err_func  = err_func_;
00360    entryAddress_ = elfHdr->e_entry();
00361 
00362    no_of_sections_ = elfHdr->e_shnum();
00363 
00364    // ".shstrtab" section: string table for section header names
00365    const char *shnames = pdelf_get_shnames(elfHdr);
00366    if (shnames == NULL) {
00367       //fprintf(stderr, "[%s][%d]WARNING: .shstrtab section not found in ELF binary\n",__FILE__,__LINE__);
00368       log_elferror(err_func_, ".shstrtab section");
00369       //return false;
00370    }
00371 
00372    // initialize Object members
00373 
00374    text_addr_ = 0; //ccw 23 jan 2002
00375    text_size_ = 0; //for determining if a mutation
00376    //falls within the text section 
00377    //of a shared library
00378 
00379    elf_hash_addr_ = 0;
00380    gnu_hash_addr_ = 0;
00381 
00382    dynamic_offset_ = 0;
00383    dynamic_addr_ = 0;
00384    dynsym_addr_ = 0;
00385    dynsym_size_ = 0;
00386    dynstr_addr_ = 0;
00387    init_addr_ = 0;
00388    fini_addr_ = 0;
00389    got_addr_ = 0;
00390    got_size_ = 0;
00391    plt_addr_ = 0;
00392    plt_size_ = 0;
00393    symtab_addr_ = 0;
00394    strtab_addr_ = 0;
00395 #if defined (ppc32_linux) || defined(ppc32_bgp)
00396    plt_entry_size_ = 8;
00397    rel_plt_entry_size_ = 8;
00398 #else
00399    plt_entry_size_ = 0;
00400    rel_plt_entry_size_ = 0;
00401 #endif
00402    rel_plt_addr_ = 0;
00403    rel_plt_size_ = 0;
00404    rel_addr_ = 0;
00405    rel_size_ = 0;
00406    rel_entry_size_ = 0;
00407    stab_off_ = 0;
00408    stab_size_ = 0;
00409    stabstr_off_ = 0;
00410    stab_indx_off_ = 0;
00411    stab_indx_size_ = 0;
00412    stabstr_indx_off_ = 0;
00413 #if defined(os_irix)
00414    MIPS_stubs_addr_ = 0;
00415    MIPS_stubs_off_ = 0;
00416    MIPS_stubs_size_ = 0;
00417    got_zero_index_ = -1;
00418    dynsym_zero_index_ = -1;
00419 #endif
00420    dwarvenDebugInfo = false;
00421 
00422    txtaddr = 0;
00423 
00424    set<string> sectionsInOriginalBinary;
00425 
00426 #if defined(TIMED_PARSE)
00427    struct timeval starttime;
00428    gettimeofday(&starttime, NULL);
00429 #endif
00430 
00431    // Find pointer to dynamic section and interpreter section
00432    bool foundInterp = false;
00433    unsigned phdr_max_count = elfHdr->e_phnum();
00434 
00435    for (unsigned i = 0; i < phdr_max_count; i++) {
00436       Elf_X_Phdr &elfPhdr = elfHdr->get_phdr(i);
00437       if(elfPhdr.p_type() == PT_DYNAMIC){
00438           dynamic_offset_ = elfPhdr.p_offset();
00439           dynamic_size_ = elfPhdr.p_memsz();
00440         } else if (elfPhdr.p_type() == PT_INTERP) {
00441           foundInterp = true;
00442       }
00443    }
00444 
00445    if (elfHdr->e_type() == ET_DYN || foundInterp || elfHdr->e_type() == ET_REL) {
00446       is_static_binary_ = false;    
00447    } else {
00448       is_static_binary_ = true; 
00449    }
00450 
00451    bool foundDynamicSection = false;
00452    int dynamic_section_index = -1;
00453    unsigned int dynamic_section_type = 0;
00454    size_t dynamic_section_size = 0;
00455    for (int i = 0; i < elfHdr->e_shnum();++i) {
00456       Elf_X_Shdr &scn = elfHdr->get_shdr(i);
00457       if (! scn.isValid()) {  // section is malformed
00458          continue; 
00459       }
00460       if ((dynamic_offset_ !=0) && (scn.sh_offset() == dynamic_offset_)) {
00461          if (!foundDynamicSection) {
00462             dynamic_section_index = i;
00463             dynamic_section_size = scn.sh_size();
00464             dynamic_section_type = scn.sh_type();
00465             foundDynamicSection = true;
00466          } else {   
00467             // If there are two or more sections with the same offset as the dynamic_offset,
00468             // use other fields to chose which one the the dynamic section  
00469             if (dynamic_section_size == dynamic_size_ && dynamic_section_type == SHT_DYNAMIC) {
00470                // We already have the right section
00471             } else if ((scn.sh_size() == dynamic_size_ && scn.sh_type() == SHT_DYNAMIC) ||
00472                        (scn.sh_size() == dynamic_size_)) {
00473                // This section is a better match to be the dynamic section
00474                // than the previous one!
00475                dynamic_section_index = i;
00476                dynamic_section_size = scn.sh_size();
00477                dynamic_section_type = scn.sh_type();
00478             }
00479          } 
00480       } 
00481    }
00482 
00483    if (dynamic_section_index != -1) {
00484       Elf_X_Shdr &scn = elfHdr->get_shdr(dynamic_section_index);
00485       Elf_X_Data data = scn.get_data();
00486       Elf_X_Dyn dynsecData = data.get_dyn();
00487       // Ubuntu 12.04 - we have debug files with NOBITS dynamic sections. 
00488       if (dynsecData.isValid()) {
00489          for (unsigned j = 0; j < dynsecData.count(); ++j) {
00490             switch (dynsecData.d_tag(j)) {
00491                case DT_REL:
00492                   hasReldyn_ = true;
00493                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00494                   break;
00495                case DT_RELA:
00496                   hasReladyn_ = true;
00497                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00498                   break;
00499                case DT_JMPREL:
00500                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00501                   break;
00502                case DT_SYMTAB:
00503                case DT_STRTAB:
00504                case DT_VERSYM:
00505                case DT_VERNEED:
00506                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00507                   break;
00508                case DT_HASH:
00509                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00510                   elf_hash_addr_ = dynsecData.d_ptr(j);
00511                   break;
00512                case  0x6ffffef5: //DT_GNU_HASH (not defined on all platforms)
00513                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00514                   gnu_hash_addr_ = dynsecData.d_ptr(j);
00515                   break;
00516                case DT_PLTGOT:
00517                   secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00518                   break;
00519                case DT_RELSZ:
00520                   secTagSizeMapping[DT_REL] = dynsecData.d_val(j);
00521                   break;
00522                case DT_RELASZ:
00523                   secTagSizeMapping[DT_RELA] = dynsecData.d_val(j);
00524                   break;
00525                case DT_PLTRELSZ:
00526                   secTagSizeMapping[DT_JMPREL] = dynsecData.d_val(j);
00527                   break;
00528                case DT_STRSZ:
00529                   secTagSizeMapping[DT_STRTAB] = dynsecData.d_val(j);
00530                   break;
00531                case DT_PLTREL: 
00532                   if (dynsecData.d_val(j) == DT_REL)
00533                      hasRelplt_ = true;
00534                   else if (dynsecData.d_val(j) == DT_RELA)
00535                      hasRelaplt_ = true;
00536                   break;
00537       
00538             }
00539          }
00540       }
00541       dyn_hash_map<Offset, int>::iterator it = secAddrTagMapping.begin();
00542       while (it != secAddrTagMapping.end()) {
00543          int tag = it->second;
00544          switch (tag) {
00545             // Only sections with these tags are moved in the new rewritten binary 
00546             case DT_REL:
00547             case DT_RELA:
00548             case DT_JMPREL:
00549             case DT_SYMTAB:
00550             case DT_STRTAB:
00551             case DT_VERSYM:
00552             case DT_VERNEED:
00553             case DT_HASH:
00554             case  0x6ffffef5: // DT_GNU_HASH (not defined on all platforms)
00555       
00556                if (secTagSizeMapping.find(tag) != secTagSizeMapping.end()) {
00557                   vector<Offset> row;
00558                   row.push_back(it->first);
00559                   row.push_back(it->first+ secTagSizeMapping[tag]);
00560                   moveSecAddrRange.push_back(row);
00561                } else {
00562                   vector<Offset> row;
00563                   row.push_back(it->first);
00564                   row.push_back(it->first);
00565                   moveSecAddrRange.push_back(row);
00566                }
00567                break;
00568          }
00569          it++;
00570       }
00571    }
00572    
00573    isBlueGeneP_ = false;
00574    isBlueGeneQ_ = false;
00575 
00576    hasNoteSection_ = false;
00577  
00578    const char *shnamesForDebugInfo = NULL;
00579    unsigned int elfHdrDbg_numSections = 0;
00580    unsigned int elfHdr_numSections = elfHdr->e_shnum();
00581    Elf_X *elfHdrDbg = dwarf->debugLinkFile();
00582    if (elfHdrDbg) {
00583       shnamesForDebugInfo = pdelf_get_shnames(elfHdrDbg);
00584       if (shnamesForDebugInfo == NULL) {
00585          log_elferror(err_func_, ".shstrtab section");
00586       }
00587       elfHdrDbg_numSections = elfHdrDbg->e_shnum();
00588    }
00589 
00590    for (unsigned int i = 0; i < elfHdr_numSections + elfHdrDbg_numSections; i++) {
00591       const char *name;
00592 
00593       bool isFromDebugFile = (i >= elfHdr_numSections);
00594       Elf_X_Shdr &scn = (!isFromDebugFile) ? elfHdr->get_shdr(i) :
00595                                              elfHdrDbg->get_shdr(i - elfHdr_numSections);
00596       if (! scn.isValid()) { // section is malformed
00597          continue; 
00598       } 
00599       Elf_X_Shdr *scnp = &scn;
00600 
00601       if (!isFromDebugFile) {
00602          name = &shnames[scn.sh_name()];
00603          sectionsInOriginalBinary.insert(string(name));
00604          
00605          if(scn.sh_flags() & SHF_ALLOC) {
00606             DbgAddrConversion_t orig;
00607             orig.name = std::string(name);
00608             orig.orig_offset = scn.sh_addr();
00609             secnNameMap[orig.name] = DebugSectionMap.size();
00610             DebugSectionMap.push_back(orig);
00611          }
00612       }
00613       else {
00614          if (!shnamesForDebugInfo) 
00615             break;
00616          name = &shnamesForDebugInfo[scn.sh_name()];
00617 
00618          std::string sname(name);
00619          std::map<std::string, int>::iterator s = secnNameMap.find(sname);
00620          if (s != secnNameMap.end()) {
00621             int i = (*s).second;
00622             DebugSectionMap[i].dbg_offset = scn.sh_addr();
00623             DebugSectionMap[i].dbg_size = scn.sh_size();
00624          }
00625          scn.setDebugFile(true);
00626 
00627          if (scn.sh_type() == SHT_NOBITS) {
00628             continue;
00629          }
00630       }
00631 
00632       if(scn.sh_type() == SHT_NOTE) {
00633          hasNoteSection_ = true;
00634       }
00635 
00636 
00637       //If the section appears in the memory image of a process address is given by 
00638       // sh_addr()
00639       //otherwise this is zero and sh_offset() gives the offset to the first byte 
00640       // in section.
00641       if (!scn.isFromDebugFile()) {
00642          allRegionHdrs.push_back(&scn);
00643          if(scn.sh_flags() & SHF_ALLOC) {
00644             // .bss, etc. have a disk size of 0
00645             unsigned long diskSize  = (scn.sh_type() == SHT_NOBITS) ? 0 : scn.sh_size();
00646             Region *reg = new Region(i, name, scn.sh_addr(), diskSize, 
00647                                      scn.sh_addr(), scn.sh_size(), 
00648                                      (mem_image()+scn.sh_offset()), 
00649                                      getRegionPerms(scn.sh_flags()), 
00650                                      getRegionType(scn.sh_type(), 
00651                                                    scn.sh_flags(),
00652                                                    name), 
00653                                      true, ((scn.sh_flags() & SHF_TLS) != 0),
00654                                      scn.sh_addralign());
00655             reg->setFileOffset(scn.sh_offset());
00656             regions_.push_back(reg);
00657          }
00658          else {
00659             Region *reg = new Region(i, name, scn.sh_addr(), scn.sh_size(), 0, 0, 
00660                                      (mem_image()+scn.sh_offset()), 
00661                                      getRegionPerms(scn.sh_flags()), 
00662                                      getRegionType(scn.sh_type(), 
00663                                                    scn.sh_flags(),
00664                                                    name), 
00665                                      false, ((scn.sh_flags() & SHF_TLS) != 0),
00666                                      scn.sh_addralign());
00667 
00668             reg->setFileOffset(scn.sh_offset());
00669             regions_.push_back(reg);
00670          }
00671       }
00672 
00673       // section-specific processing
00674       if (P_strcmp(name, EDITED_TEXT_NAME) == 0) {
00675          // EEL rewritten executable
00676          EEL = true;
00677          if (txtaddr == 0)
00678             txtaddr = scn.sh_addr();
00679          char *file_ptr = (char *)mf->base_addr();
00680          code_ptr_ = (char *)(void*)&file_ptr[scn.sh_offset() - EXTRA_SPACE];
00681          code_off_ = scn.sh_addr() - EXTRA_SPACE;
00682          code_len_ = scn.sh_size() + EXTRA_SPACE;
00683       }
00684 
00685       if (strcmp(name, TEXT_NAME) == 0) {
00686          text_addr_ = scn.sh_addr();
00687          text_size_ = scn.sh_size();
00688 
00689          if (txtaddr == 0)
00690             txtaddr = scn.sh_addr();
00691       
00692          // .o's don't have program headers, so these members need
00693          // to be populated here
00694          if( !elfHdr->e_phnum() && !code_len_) {
00695             // Populate code members
00696             code_ptr_ = reinterpret_cast<char *>(scn.get_data().d_buf());
00697             code_off_ = scn.sh_offset();
00698             code_len_ = scn.sh_size();
00699          }
00700       }
00701       /* The following sections help us find the PH entry that
00702          encompasses the data region. */
00703       else if (strcmp(name, DATA_NAME) == 0) {
00704          dataddr = scn.sh_addr();
00705 
00706          // .o's don't have program headers, so these members need
00707          // to be populated here
00708          if( !elfHdr->e_phnum() && !data_len_) {
00709             // Populate data members
00710             data_ptr_ = reinterpret_cast<char *>(scn.get_data().d_buf());
00711             data_off_ = scn.sh_offset();
00712             data_len_ = scn.sh_size();
00713          }
00714       }
00715       else if (strcmp(name, RO_DATA_NAME) == 0) {
00716          if (!dataddr) dataddr = scn.sh_addr();
00717       }
00718       else if (strcmp(name, GOT_NAME) == 0) {
00719          got_scnp = scnp;
00720          got_addr_ = scn.sh_addr();
00721          got_size_ = scn.sh_size();
00722          if (!dataddr) dataddr = scn.sh_addr();
00723       }
00724       else if (strcmp(name, BSS_NAME) == 0) {
00725          bssscnp = scnp;
00726          if (!dataddr) dataddr = scn.sh_addr();
00727       }
00728       /* End data region search */
00729       /*else if (strcmp( name, FINI_NAME) == 0) {
00730         fini_addr_ = scn.sh_addr();
00731         }*/
00732       else if (strcmp(name, SYMTAB_NAME) == 0) {
00733          if (!symscnp) {
00734             symscnp = scnp;
00735             symtab_addr_ = scn.sh_addr();
00736          }
00737       }
00738       else if (strcmp(name, STRTAB_NAME) == 0) {
00739          if (!strscnp) {
00740             strscnp = scnp;
00741             strtab_addr_ = scn.sh_addr();
00742          }  
00743       } else if (strcmp(name, STAB_INDX_NAME) == 0) {
00744          stabs_indxcnp = scnp;
00745          stab_indx_off_ = scn.sh_offset();
00746          stab_indx_size_ = scn.sh_size();
00747       } else if (strcmp(name, STABSTR_INDX_NAME) == 0) {
00748          stabstrs_indxcnp = scnp;
00749          stabstr_indx_off_ = scn.sh_offset();
00750       } else if (strcmp(name, STAB_NAME) == 0) {
00751          stabscnp = scnp;
00752          stab_off_ = scn.sh_offset();
00753          stab_size_ = scn.sh_size();
00754       } else if (strcmp(name, STABSTR_NAME) == 0) {
00755          stabstrscnp = scnp;
00756          stabstr_off_ = scn.sh_offset();
00757       } 
00758 #if defined(os_vxworks)
00759       else if ((strcmp(name, REL_PLT_NAME) == 0) || 
00760                (strcmp(name, REL_PLT_NAME2) == 0)) {
00761          rel_plt_scnp = scnp;
00762          rel_plt_addr_ = scn.sh_addr();
00763          rel_plt_size_ = scn.sh_size();
00764          rel_plt_entry_size_ = scn.sh_entsize();
00765       }
00766 #else
00767       else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) && 
00768                secAddrTagMapping[scn.sh_addr()] == DT_JMPREL ) {
00769          rel_plt_scnp = scnp;
00770          rel_plt_addr_ = scn.sh_addr();
00771          rel_plt_size_ = scn.sh_size();
00772          rel_plt_entry_size_ = scn.sh_entsize();
00773       }
00774 #endif
00775       else if (strcmp(name, OPD_NAME) == 0) {
00776          opd_scnp = scnp;
00777          opd_addr_ = scn.sh_addr();
00778          opd_size_ = scn.sh_size();
00779       }
00780       else if (strcmp(name, PLT_NAME) == 0) {
00781          plt_scnp = scnp;
00782          plt_addr_ = scn.sh_addr();
00783          plt_size_ = scn.sh_size();
00784 #if defined(arch_x86) || defined(arch_x86_64)
00785          //
00786          // On x86, the GNU linker purposefully sets the PLT
00787          // table entry size to an incorrect value to be
00788          // compatible with the UnixWare linker.  (See the comment
00789          // in the elf_i386_finish_dynamic_sections function of
00790          // the BFD library.)  The GNU linker sets this value to 4,
00791          // when it should be 16.
00792          //
00793          // I see no good way to determine this value from the
00794          // ELF section header information.  We can either (a) hard-code
00795          // the value that is used in the BFD library, or (b) compute
00796          // it by dividing the size of the PLT by the number of entries
00797          // we think should be in the PLT.  I'm not certain, but I
00798          // believe the PLT and the .rel.plt section should have the
00799          // same number of "real" entries (the x86 PLT has one extra entry
00800          // at the beginning).
00801          // 
00802          // This code is applicable to any x86 system that uses the
00803          // GNU linker.  We currently only support Linux on x86 - if
00804          // we start supporting some other x86 OS that uses the GNU
00805          // linker in the future, it should be enabled for that platform as well.
00806          // Note that this problem does not affect the non-x86 platforms
00807          // that might use the GNU linker.  For example, programs linked
00808          // with gld on SPARC Solaris have the correct PLT entry size.
00809          //
00810          // Another potential headache in the future is if we support
00811          // some other x86 platform that has both the GNU linker and
00812          // some other linker.  (Does BSD fall into this category?)
00813          // If the two linkers set the entry size differently, we may
00814          // need to re-evaluate this code.
00815          //
00816          //plt_entry_size_ = plt_size_ / ((rel_plt_size_ / rel_plt_entry_size_) + 1);
00817          plt_entry_size_ = 16;
00818          assert( plt_entry_size_ == 16 );
00819 #else
00820          plt_entry_size_ = scn.sh_entsize();
00821       
00822          // X86-64: if we're on a 32-bit binary then set the PLT entry size to 16
00823          // as above
00824 #if defined(arch_x86_64)
00825          if (addressWidth_nbytes == 4) {
00826             plt_entry_size_ = 16;
00827             assert( plt_entry_size_ == 16 );
00828          }
00829          else {
00830             assert(addressWidth_nbytes == 8);
00831          }
00832 #endif
00833 
00834 
00835 #if defined (ppc32_linux) || defined(ppc32_bgp)
00836          if (scn.sh_flags() & SHF_EXECINSTR) {
00837             // Old style executable PLT
00838             if (!plt_entry_size_)
00839                plt_entry_size_ = 8;
00840             else {
00841                if (plt_entry_size_ != 8) 
00842                   fprintf(stderr, "%s[%d]:  weird plt_entry_size_ is %d, not 8\n", 
00843                           FILE__, __LINE__, plt_entry_size_);
00844             }
00845 
00846          } else {
00847             // New style secure PLT
00848             plt_entry_size_ = 16;
00849          }
00850 #endif
00851 #endif
00852       } else if (strcmp(name, COMMENT_NAME) == 0) {
00853          /* comment section is a sequence of NULL-terminated strings.
00854             We want to concatenate them and search for BGP to determine
00855             if the binary is built for BGP compute nodes */
00856 
00857          Elf_X_Data data = scn.get_data();
00858         
00859          unsigned int index = 0;
00860          size_t size = data.d_size();
00861          char *buf = (char *) data.d_buf();
00862          while (buf && (index < size))
00863          {
00864             string comment = buf+index;
00865             size_t pos_p = comment.find("BGP");
00866             size_t pos_q = comment.find("BGQ");
00867             if (pos_p !=string::npos) {
00868                isBlueGeneP_ = true;
00869                break;
00870             } else if (pos_q !=string::npos) {
00871                isBlueGeneQ_ = true;
00872                break;
00873             }
00874             index += comment.size();
00875             if (comment.size() == 0) { // Skip NULL characters in the comment section
00876                index ++;
00877             }
00878          }
00879       }
00880 
00881       else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) &&
00882                secAddrTagMapping[scn.sh_addr()] == DT_SYMTAB ) {
00883          is_dynamic_ = true;
00884          dynsym_scnp = scnp;
00885          dynsym_addr_ = scn.sh_addr();
00886          dynsym_size_ = scn.sh_size()/scn.sh_entsize();
00887       }
00888       else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) && 
00889                secAddrTagMapping[scn.sh_addr()] == DT_STRTAB ) {
00890          dynstr_scnp = scnp;
00891          dynstr_addr_ = scn.sh_addr();
00892       }
00893       else if (strcmp(name, ".debug_info") == 0) {
00894          dwarvenDebugInfo = true;
00895       }
00896       else if (strcmp(name, EH_FRAME_NAME) == 0) {
00897          eh_frame = scnp;
00898       }
00899       else if ((strcmp(name, EXCEPT_NAME) == 0) || 
00900                (strcmp(name, EXCEPT_NAME_ALT) == 0)) {
00901          gcc_except = scnp;
00902       }
00903       else if (strcmp(name, INTERP_NAME) == 0) {
00904          interp_scnp = scnp;
00905       }
00906       else if ((int) i == dynamic_section_index) {
00907          dynamic_scnp = scnp;
00908          dynamic_addr_ = scn.sh_addr();
00909       }
00910    }
00911 
00912    if(!symscnp || !strscnp) {
00913       isStripped = true;
00914       if(dynsym_scnp && dynstr_scnp){
00915          symscnp = dynsym_scnp;
00916          strscnp = dynstr_scnp;
00917       }
00918    }
00919 
00920    loadAddress_ = 0x0;
00921 #if defined(os_linux) || defined(os_freebsd)
00922    /**
00923     * If the virtual address of the first PT_LOAD element in the
00924     * program table is 0, Linux loads the shared object into any
00925     * free spot into the address space.  If the virtual address is
00926     * non-zero, it gets loaded only at that address.
00927     **/
00928    for (unsigned i = 0; i < elfHdr->e_phnum() && !loadAddress_; ++i) {
00929       Elf_X_Phdr &phdr = elfHdr->get_phdr(i);
00930 
00931       if (phdr.p_type() == PT_LOAD) {
00932          loadAddress_ = phdr.p_vaddr();
00933          break;
00934       }
00935    }
00936 #endif  
00937   
00938    // save a copy of region headers, maintaining order in section header table
00939    allRegionHdrsByShndx = allRegionHdrs;
00940 
00941    // sort the section headers by base address
00942    sort(allRegionHdrs.begin(), allRegionHdrs.end(), SectionHeaderSortFunction());
00943 
00944    for (unsigned j = 0 ; j < regions_.size() ; j++) {
00945       if (secAddrTagMapping.find(regions_[j]->getDiskOffset()) != secAddrTagMapping.end()) {
00946          secTagRegionMapping[secAddrTagMapping[regions_[j]->getDiskOffset()]] = regions_[j];
00947       }
00948    }
00949 
00950 #if defined(TIMED_PARSE)
00951    struct timeval endtime;
00952    gettimeofday(&endtime, NULL);
00953    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
00954    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
00955    unsigned long difftime = lendtime - lstarttime;
00956    double dursecs = difftime/(1000 );
00957    cout << "main loop of loaded elf took "<<dursecs <<" msecs" << endl;
00958 #endif
00959 
00960    if (!dataddr || !symscnp || !strscnp) {
00961       //log_elferror(err_func_, "no text/bss/symbol/string section");
00962    }
00963    //if (addressWidth_nbytes == 8) bperr( ">>> 64-bit loaded_elf() successful\n");
00964    return true;
00965 }
00966 
00967 bool Object::is_offset_in_plt(Offset offset) const
00968 {
00969   return (offset > plt_addr_ && offset < plt_addr_ + plt_size_);
00970 }
00971 
00972 void Object::parseDynamic(Elf_X_Shdr *&dyn_scnp, Elf_X_Shdr *&dynsym_scnp,
00973               Elf_X_Shdr *&dynstr_scnp)
00974 {
00975   Elf_X_Data data = dyn_scnp->get_data();
00976   Elf_X_Dyn dyns = data.get_dyn();
00977   int rel_scnp_index = -1;
00978 
00979   for (unsigned i = 0; i < dyns.count(); ++i) {
00980     switch(dyns.d_tag(i)) {
00981     case DT_REL:
00982     case DT_RELA:
00983       /*found Relocation section*/
00984       rel_addr_ = (Offset) dyns.d_ptr(i);
00985       rel_scnp_index = getRegionHdrIndexByAddr(dyns.d_ptr(i));
00986       break;
00987     case DT_JMPREL:
00988     rel_plt_addr_ = (Offset) dyns.d_ptr(i);
00989     break;
00990     case DT_PLTRELSZ:
00991     rel_plt_size_ = dyns.d_val(i) ;
00992     break;
00993     case DT_RELSZ:
00994     case DT_RELASZ:
00995       rel_size_ = dyns.d_val(i) ;
00996       break;
00997     case DT_RELENT:
00998     case DT_RELAENT:
00999       rel_entry_size_ = dyns.d_val(i);
01000       /* Maybe */
01001       //rel_plt_entry_size_ = dyns.d_val(i);
01002       break;
01003     case DT_INIT:
01004         init_addr_ = dyns.d_val(i);
01005         break;
01006     case DT_FINI:
01007         fini_addr_ = dyns.d_val(i);
01008         break;
01009         default:
01010       break;
01011     }
01012   }
01013   if (rel_scnp_index  != -1)
01014     get_relocationDyn_entries(rel_scnp_index, dynsym_scnp, dynstr_scnp);
01015 }
01016 
01017 /* parse relocations for the sections represented by DT_REL/DT_RELA in
01018  * the dynamic section. This section is the one we would want to emit
01019  */
01020 bool Object::get_relocationDyn_entries( unsigned rel_scnp_index,
01021                     Elf_X_Shdr *&dynsym_scnp, 
01022                     Elf_X_Shdr *&dynstr_scnp )
01023 {
01024   Elf_X_Data symdata = dynsym_scnp->get_data();
01025   Elf_X_Data strdata = dynstr_scnp->get_data();
01026   Elf_X_Shdr* rel_scnp = NULL;
01027   if( !symdata.isValid() || !strdata.isValid()) 
01028     return false;
01029   const char *strs = strdata.get_string();
01030   Elf_X_Sym sym = symdata.get_sym();
01031 
01032   unsigned num_rel_entries_found = 0;
01033   unsigned num_rel_entries = rel_size_/rel_entry_size_;
01034   
01035   if (rel_addr_ + rel_size_ > rel_plt_addr_){
01036     // REL/RELA section overlaps with REL PLT section
01037     num_rel_entries = (rel_plt_addr_-rel_addr_)/rel_entry_size_;
01038   }
01039   while (num_rel_entries_found != num_rel_entries) {
01040     rel_scnp = getRegionHdrByIndex(rel_scnp_index++);
01041     Elf_X_Data reldata = rel_scnp->get_data();
01042 
01043     if( ! reldata.isValid()) return false;
01044     Elf_X_Rel rel = reldata.get_rel();
01045     Elf_X_Rela rela = reldata.get_rela();
01046 
01047     if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
01048       /* Iterate over the entries. */
01049       for( u_int i = 0; i < (reldata.d_size()/rel_entry_size_); ++i ) {
01050     num_rel_entries_found++;
01051     long offset;
01052     long addend;
01053     long index;
01054     unsigned long type;
01055     Region::RegionType rtype = Region::RT_REL;
01056 
01057     switch (reldata.d_type()) {
01058     case ELF_T_REL:
01059       offset = rel.r_offset(i);
01060       addend = 0;
01061       index = rel.R_SYM(i);
01062       type = rel.R_TYPE(i);
01063       break;
01064     
01065     case ELF_T_RELA:
01066       offset = rela.r_offset(i);
01067       addend = rela.r_addend(i);
01068       index = rela.R_SYM(i);
01069       type = rela.R_TYPE(i);
01070       rtype = Region::RT_RELA;
01071       break;
01072 
01073     default:
01074       // We should never reach this case.
01075       return false;
01076     };
01077     // /* DEBUG */ fprintf( stderr, "%s: relocation information for target 0x%lx\n", __FUNCTION__, next_plt_entry_addr );
01078     relocationEntry re( offset, string( &strs[ sym.st_name(index) ] ), NULL, type );
01079     re.setAddend(addend);
01080     re.setRegionType(rtype);
01081     if(symbols_.find(&strs[ sym.st_name(index)]) != symbols_.end()){
01082       vector<Symbol *> &syms = symbols_[&strs[ sym.st_name(index)]];
01083      for (vector<Symbol *>::iterator i = syms.begin(); i != syms.end(); i++) {
01084         if (!(*i)->isInDynSymtab())
01085            continue;
01086         re.addDynSym(*i);
01087         break;
01088      }
01089     }
01090 
01091     relocation_table_.push_back(re);
01092       }
01093     } else {
01094       return false;
01095     }
01096     
01097   }
01098   return true;
01099 }
01100 
01101 bool Object::get_relocation_entries( Elf_X_Shdr *&rel_plt_scnp,
01102                      Elf_X_Shdr *&dynsym_scnp, 
01103                      Elf_X_Shdr *&dynstr_scnp )
01104 {
01105   if (rel_plt_size_ && rel_plt_addr_) {
01106     Elf_X_Data reldata = rel_plt_scnp->get_data();
01107     Elf_X_Data symdata = dynsym_scnp->get_data();
01108     Elf_X_Data strdata = dynstr_scnp->get_data();
01109 
01110     if( reldata.isValid() && symdata.isValid() && strdata.isValid() ) {
01111       Offset next_plt_entry_addr = plt_addr_;
01112 
01113 #if defined(arch_x86) || defined(arch_x86_64)
01114       next_plt_entry_addr += plt_entry_size_;  // 1st PLT entry is special
01115 
01116 #elif defined (ppc32_linux) || defined(ppc32_bgp)
01117       bool extraStubs = false;
01118 
01119       // Sanity check.
01120       if (!plt_entry_size_) {
01121     fprintf(stderr, "%s[%d]:  FIXME:  plt_entry_size not established\n", FILE__, __LINE__);
01122     plt_entry_size_ = 8;
01123       }
01124 
01125       if (plt_entry_size_ == 8) {
01126           // Old style executable PLT section
01127       next_plt_entry_addr += 9*plt_entry_size_;  // 1st 9 PLT entries are special
01128 
01129       } else if (plt_entry_size_ == 16) {
01130           // New style secure PLT
01131           Region *plt = NULL, *relplt = NULL, *dynamic = NULL,
01132                  *got = NULL, *glink = NULL;
01133           unsigned int glink_addr = 0;
01134           unsigned int stub_addr = 0;
01135 
01136           // Find the GLINK section.  See ppc_elf_get_synthetic_symtab() in
01137           // bfd/elf32-ppc.c of GNU's binutils for more information.
01138 
01139           for (unsigned iter = 0; iter < regions_.size(); ++iter) {
01140               std::string name = regions_[iter]->getRegionName();
01141               if (name == PLT_NAME) plt = regions_[iter];
01142               else if (name == REL_PLT_NAME) relplt = regions_[iter];
01143               else if (name == DYNAMIC_NAME) dynamic = regions_[iter];
01144               else if (name == GOT_NAME) got = regions_[iter];
01145           }
01146 
01147           // Rely on .dynamic section for prelinked binaries.
01148           if (dynamic != NULL) {
01149               Elf32_Dyn *dyn = (Elf32_Dyn *)dynamic->getPtrToRawData();
01150               unsigned int count = dynamic->getMemSize() / sizeof(Elf32_Dyn);
01151 
01152               for (unsigned int i = 0; i < count; ++i) {
01153                   // Use DT_LOPROC instead of DT_PPC_GOT to circumvent problems
01154                   // caused by early versions of libelf where DT_PPC_GOT has
01155                   // yet to be defined.
01156                   if (dyn[i].d_tag == DT_LOPROC) {
01157                       unsigned int g_o_t = dyn[i].d_un.d_val;
01158                       if (got != NULL) {
01159                           unsigned char *data =
01160                               (unsigned char *)got->getPtrToRawData();
01161                           glink_addr = *(unsigned int *)
01162                               (data + (g_o_t - got->getMemOffset() + 4));
01163                           break;
01164                       }
01165                   }
01166               }
01167           }
01168 
01169           // Otherwise, first entry in .plt section holds the glink address
01170           if (glink_addr == 0) {
01171               unsigned char *data = (unsigned char *)plt->getPtrToRawData();
01172               glink_addr = *(unsigned int *)(data);
01173           }
01174 
01175           // Search for region that contains glink address
01176           for (unsigned iter = 0; iter < regions_.size(); ++iter) {
01177               unsigned int start = regions_[iter]->getMemOffset();
01178               unsigned int end = start + regions_[iter]->getMemSize();
01179               if (start <= glink_addr && glink_addr < end) {
01180                   glink = regions_[iter];
01181                   break;
01182               }
01183           }
01184 
01185           if (!glink) {
01186 //              fprintf(stderr, "*** Cound not find .glink section for '%s'.\n",
01187 //                      mf->pathname().c_str());
01188 //              fprintf(stderr, "*** It may not be a ppc32 elf object.\n");
01189               return false;
01190           }
01191 
01192           // Find PLT function stubs.  They preceed the glink section.
01193           stub_addr = glink_addr - (rel_plt_size_/rel_plt_entry_size_) * 16;
01194 
01195           const unsigned int LWZ_11_30   = 0x817e0000;
01196           const unsigned int ADDIS_11_30 = 0x3d7e0000;
01197           const unsigned int LWZ_11_11   = 0x816b0000;
01198           const unsigned int MTCTR_11    = 0x7d6903a6;
01199           const unsigned int BCTR        = 0x4e800420;
01200 
01201           unsigned char *sec_data = (unsigned char *)glink->getPtrToRawData();
01202           unsigned int *insn = (unsigned int *)
01203               (sec_data + (stub_addr - glink->getMemOffset()));
01204 
01205           // Keep moving pointer back if more -fPIC stubs are found.
01206           while (sec_data < (unsigned char *)insn) {
01207               unsigned int *back = insn - 4;
01208 
01209               if ((  (back[0] & 0xffff0000) == LWZ_11_30
01210                    && back[1] == MTCTR_11
01211                    && back[2] == BCTR)
01212 
01213                   || (   (back[0] & 0xffff0000) == ADDIS_11_30
01214                       && (back[1] & 0xffff0000) == LWZ_11_11
01215                       &&  back[2] == MTCTR_11
01216                       &&  back[3] == BCTR))
01217                   {
01218                       extraStubs = true;
01219                       stub_addr -= 16;
01220                       insn = back;
01221                   } else {
01222                       break;
01223                   }
01224           }
01225 
01226           // Okay, this is where things get hairy.  If we have a one to one
01227           // relationship between the glink stubs and plt entries (meaning
01228           // extraStubs == false), then we can generate our relocationEntry
01229           // objects normally below.
01230 
01231           // However, if we have extra glink stubs, then we must generate
01232           // relocations with unknown destinations for *all* stubs.  Then,
01233           // we use the loop below to store additional information about
01234           // the data plt entry keyed by plt entry address.
01235 
01236           // Finally, if a symbol with any of the following forms:
01237           //     [hex_addr].got2.plt_pic32.[sym_name]
01238           //     [hex_addr].plt_pic32.[sym_name]
01239           //
01240           // matches the glink stub address, then stub symbols exist and we
01241           // can rely on these tell us where the stub will eventually go.
01242 
01243           if (extraStubs == true) {
01244               std::string name;
01245               relocationEntry re;
01246 
01247               while (stub_addr < glink_addr) {
01248                   if (symsByOffset_.find(stub_addr) != symsByOffset_.end()) {
01249                       name = (symsByOffset_[stub_addr])[0]->getMangledName();
01250                       name = name.substr( name.rfind("plt_pic32.") + 10 );
01251                   }
01252 
01253                   if (!name.empty()) {
01254                       re = relocationEntry( stub_addr, 0, name, NULL, 0 );
01255                   } else {
01256                       re = relocationEntry( stub_addr, 0, "@plt", NULL, 0 );
01257                   }
01258                   fbt_.push_back(re);
01259                   stub_addr += 16;
01260               }
01261 
01262               // Now prepare to iterate over plt below.
01263               next_plt_entry_addr = plt_addr_;
01264               plt_entry_size_ = 4;
01265 
01266           } else {
01267               next_plt_entry_addr = stub_addr;
01268           }
01269 
01270       } else {
01271           fprintf(stderr, "ERROR: Can't handle %d PLT entry size\n",
01272                   plt_entry_size_);
01273           return false;
01274       }
01275 
01276       //fprintf(stderr, "%s[%d]:  skipping %d (6*%d) bytes initial plt\n", 
01277       //        FILE__, __LINE__, 9*plt_entry_size_, plt_entry_size_);
01278       //  actually this is just fudged to make the offset value 72, which is what binutils uses
01279       //  Note that binutils makes the distinction between PLT_SLOT_SIZE (8), 
01280       //  and PLT_ENTRY_SIZE (12).  PLT_SLOT_SIZE seems to be what we want, even though we also
01281       //  have PLT_INITIAL_ENTRY_SIZE (72)
01282       //  see binutils/bfd/elf32-ppc.c/h if more info is needed
01283       //next_plt_entry_addr += 72;  // 1st 6 PLT entries art special
01284 
01285 #elif defined(arch_power) && defined(arch_64bit) && defined(os_linux)
01286       // Unlike PPC32 Linux, we don't have a deterministic way of finding
01287       // PPC64 Linux linker stubs.  So, we'll wait until the CFG is built
01288       // inside Dyninst, and code read at that point.  To find them at this
01289       // point would require a scan of the entire .text section.
01290       //
01291       // If we're lucky, symbols may exist for these linker stubs.  They will
01292       // come in the following forms:
01293       //     [hex_addr].plt_call.[sym_name]
01294       //     [hex_addr].plt_branch.[sym_name]
01295       //     [hex_addr].long_branch.[sym_name]
01296       //     [hex_addr].plt_branch_r2off.[sym_name]
01297       //     [hex_addr].long_branch_r2off.[sym_name]
01298       //
01299       // Again unlike PPC32 above, we have no glink stub address to compare
01300       // against, so we must search through all symbols to find these names.
01301       //
01302 
01303       // First, build a map of the .rela.plt symbol name -> .rela.plt offset:
01304       dyn_hash_map<std::string, Offset> plt_rel_map;
01305 
01306       // I'm not a fan of code duplication, but merging this into the
01307       // loop below would be ugly and difficult to maintain.
01308       Elf_X_Sym  _sym  = symdata.get_sym();
01309       Elf_X_Rel  _rel  = reldata.get_rel();
01310       Elf_X_Rela _rela = reldata.get_rela();
01311       const char *_strs = strdata.get_string();
01312 
01313       for( u_int i = 0; i < (rel_plt_size_/rel_plt_entry_size_); ++i ) {
01314       long _offset;
01315       long _index;
01316 
01317       switch (reldata.d_type()) {
01318       case ELF_T_REL:
01319               _offset = _rel.r_offset(i);
01320               _index  = _rel.R_SYM(i);
01321               break;
01322 
01323       case ELF_T_RELA:
01324               _offset = _rela.r_offset(i);
01325               _index  = _rela.R_SYM(i);
01326               break;
01327 
01328       default:
01329         // We should never reach this case.
01330         return false;
01331       };
01332 
01333           std::string _name = &_strs[ _sym.st_name(_index) ];
01334           // I'm interested to see if this assert will ever fail.
01335           assert(_name.length());
01336 
01337           plt_rel_map[_name] = _offset;
01338       }
01339       // End code duplication.
01340 
01341       dyn_hash_map<std::string, std::vector<Symbol *> >::iterator iter;
01342       for (iter = symbols_.begin(); iter != symbols_.end(); ++iter) {
01343           std::string name = iter->first;
01344           if (name.length() > 8) {
01345               if (name.substr(8, 10) == ".plt_call.")
01346                   name = name.substr(8 + 10);
01347               else if (name.substr(8, 12) == ".plt_branch.")
01348                   name = name.substr(8 + 12);
01349               else if (name.substr(8, 13) == ".long_branch.")
01350                   name = name.substr(8 + 13);
01351               else if (name.substr(8, 18) == ".plt_branch_r2off.")
01352                   name = name.substr(8 + 18);
01353               else if (name.substr(8, 19) == ".long_branch_r2off.")
01354                   name = name.substr(8 + 19);
01355               else
01356                   continue;
01357 
01358               // Remove possible trailing addend value.
01359               std::string::size_type pos = name.rfind('+');
01360               if (pos != std::string::npos) name.erase(pos);
01361 
01362               // Remove possible version number.
01363               pos = name.find('@');
01364               if (pos != std::string::npos) name.erase(pos);
01365 
01366               // Find the dynamic symbol this linker stub branches to.
01367               Symbol *targ_sym = NULL;
01368               if (symbols_.find(name) != symbols_.end())
01369                   for (unsigned i = 0; i < symbols_[name].size(); ++i)
01370                       if ( (symbols_[name])[i]->isInDynSymtab())
01371                           targ_sym = (symbols_[name])[i];
01372 
01373               // If a corresponding target symbol cannot be found for a
01374               // named linker stub, then ignore it.  We'll find it during
01375               // parsing.
01376               if (!targ_sym) continue;
01377               
01378               // I'm interested to see if these asserts will ever fail.
01379               assert(iter->second.size() == 1);
01380               assert(plt_rel_map.count(name) == 1);
01381               
01382               Symbol *stub_sym = iter->second[0];
01383               relocationEntry re(stub_sym->getOffset(),
01384                                  plt_rel_map[name],
01385                                  name,
01386                                  targ_sym);
01387               fbt_.push_back(re);
01388     }
01389       }
01390 
01391       // 1st plt entry is special.
01392       next_plt_entry_addr += plt_entry_size_;
01393 
01394 #else
01395       next_plt_entry_addr += 4*(plt_entry_size_); //1st 4 entries are special
01396 #endif
01397 
01398       Elf_X_Sym sym = symdata.get_sym();
01399       Elf_X_Rel rel = reldata.get_rel();
01400       Elf_X_Rela rela = reldata.get_rela();
01401       const char *strs = strdata.get_string();
01402 
01403       if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
01404 
01405         // Sometimes, PPC32 Linux may use this loop to update fbt entries.
01406         // Should stay -1 for all other platforms.  See notes above.
01407         int fbt_iter = -1;
01408         if (fbt_.size() > 0 && !fbt_[0].rel_addr() && fbt_[0].name() != "@plt")
01409             fbt_iter = 0;
01410 
01411     for( u_int i = 0; i < (rel_plt_size_/rel_plt_entry_size_); ++i ) {
01412       long offset;
01413       long addend;
01414       long index;
01415       unsigned long type;
01416           Region::RegionType rtype;
01417 
01418       switch (reldata.d_type()) {
01419       case ELF_T_REL:
01420         offset = rel.r_offset(i);
01421         addend = 0;
01422         index = rel.R_SYM(i);
01423         type = rel.R_TYPE(i);
01424             rtype = Region::RT_REL;
01425         break;
01426 
01427       case ELF_T_RELA:
01428         offset = rela.r_offset(i);
01429         addend = rela.r_addend(i);
01430         index = rela.R_SYM(i);
01431         type = rela.R_TYPE(i);
01432         rtype = Region::RT_RELA;
01433         break;
01434 
01435       default:
01436         // We should never reach this case.
01437         return false;
01438       };
01439 
01440           std::string targ_name = &strs[ sym.st_name(index) ];
01441           vector<Symbol *> dynsym_list;
01442           if (symbols_.find(targ_name) != symbols_.end()) 
01443           {
01444              vector<Symbol *> &syms = symbols_[&strs[ sym.st_name(index)]];
01445              for (vector<Symbol *>::iterator i = syms.begin(); i != syms.end(); i++) {             
01446                 if (!(*i)->isInDynSymtab())
01447                    continue;
01448                 dynsym_list.push_back(*i);
01449              }
01450           } 
01451           else {
01452             dynsym_list.clear();
01453           }
01454 
01455 #if defined(os_vxworks)
01456           // VxWorks Kernel Images don't use PLT's, but we'll use the fbt to
01457           // note all function call relocations, and we'll fix these up later
01458           // in Symtab::fixup_RegionAddr()
01459           next_plt_entry_addr = sym.st_value(index);
01460 #endif
01461 
01462           if (fbt_iter == -1) { // Create new relocation entry.
01463             relocationEntry re( next_plt_entry_addr, offset, targ_name,
01464                                 NULL, type );
01465             re.setAddend(addend);
01466             re.setRegionType(rtype);
01467             if (dynsym_list.size() > 0)
01468                 re.addDynSym(dynsym_list[0]);
01469             fbt_.push_back(re);
01470 
01471           } else { // Update existing relocation entry.
01472             while ((unsigned)fbt_iter < fbt_.size() &&
01473                    fbt_[fbt_iter].name() == targ_name) {
01474 
01475               fbt_[fbt_iter].setRelAddr(offset);
01476               fbt_[fbt_iter].setAddend(addend);
01477               fbt_[fbt_iter].setRegionType(rtype);
01478               if (dynsym_list.size() > 0)
01479                 fbt_[fbt_iter].addDynSym(dynsym_list[0]);
01480 
01481               ++fbt_iter;
01482             }
01483           }
01484 
01485 #if defined(os_vxworks)
01486           // Nothing to increment here.
01487 #else
01488       next_plt_entry_addr += plt_entry_size_;
01489 #endif
01490     }
01491     return true;
01492       }
01493     }
01494   }
01495   return false;
01496 }
01497 
01498 void Object::load_object(bool alloc_syms)
01499 {
01500   Elf_X_Shdr *bssscnp = 0;
01501   Elf_X_Shdr *symscnp = 0;
01502   Elf_X_Shdr *strscnp = 0;
01503   Elf_X_Shdr *stabscnp = 0;
01504   Elf_X_Shdr *stabstrscnp = 0;
01505   Elf_X_Shdr *stabs_indxcnp = 0;
01506   Elf_X_Shdr *stabstrs_indxcnp = 0;
01507   Offset txtaddr = 0;
01508   Offset dataddr = 0;
01509   Elf_X_Shdr *rel_plt_scnp = 0;
01510   Elf_X_Shdr *plt_scnp = 0; 
01511   Elf_X_Shdr *got_scnp = 0;
01512   Elf_X_Shdr *dynsym_scnp = 0;
01513   Elf_X_Shdr *dynstr_scnp = 0;
01514   Elf_X_Shdr *dynamic_scnp = 0;
01515   Elf_X_Shdr *eh_frame_scnp = 0;
01516   Elf_X_Shdr *gcc_except = 0;
01517   Elf_X_Shdr *interp_scnp = 0;
01518   Elf_X_Shdr *opd_scnp = NULL;
01519 
01520   { // binding contour (for "goto cleanup")
01521 
01522     // initialize object (for failure detection)
01523     code_ptr_ = 0;
01524     code_off_ = 0;
01525     code_len_ = 0;
01526     data_ptr_ = 0;
01527     data_off_ = 0;
01528     data_len_ = 0;
01529 
01530     // initialize "valid" regions of code and data segments
01531     code_vldS_ = (Offset) -1;
01532     code_vldE_ = 0;
01533     data_vldS_ = (Offset) -1;
01534     data_vldE_ = 0;
01535 
01536     // And attempt to parse the ELF data structures in the file....
01537     // EEL, added one more parameter
01538 
01539     if (!loaded_elf(txtaddr, dataddr, bssscnp, symscnp, strscnp,
01540             stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
01541             rel_plt_scnp, plt_scnp, got_scnp, dynsym_scnp, dynstr_scnp,
01542                     dynamic_scnp, eh_frame_scnp,gcc_except, interp_scnp, 
01543             opd_scnp, true))
01544       {
01545     goto cleanup;
01546       }
01547 
01548     addressWidth_nbytes = elfHdr->wordSize();
01549 
01550     // find code and data segments....
01551     find_code_and_data(*elfHdr, txtaddr, dataddr);
01552 
01553     if (elfHdr->e_type() != ET_REL) 
01554       {
01555     if (!code_ptr_ || !code_len_) 
01556       {
01557             //bpfatal( "no text segment\n");
01558             goto cleanup;
01559       }
01560 
01561     if (!data_ptr_ || !data_len_) 
01562       {
01563             //bpfatal( "no data segment\n");
01564             goto cleanup;
01565       }
01566       }
01567     get_valid_memory_areas(*elfHdr);
01568 
01569     //fprintf(stderr, "[%s:%u] - Exe Name\n", __FILE__, __LINE__);
01570 
01571 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
01572     if (eh_frame_scnp != 0 && gcc_except != 0) 
01573       {
01574     find_catch_blocks(eh_frame_scnp, gcc_except, 
01575               txtaddr, dataddr, catch_addrs_);
01576       }
01577 #endif
01578     if (interp_scnp) {
01579       interpreter_name_ = (char *) interp_scnp->get_data().d_buf(); 
01580     }
01581 
01582     // global symbols are put in global_symbols. Later we read the
01583     // stab section to find the module to where they belong.
01584     // Experiment : lets try to be a bit more intelligent about
01585     // how we initially size the global_symbols table.  
01586     // dictionary_lite takes an initial # of bins (2nd param), 
01587     // a max bin load (3rd param), and a grow factor (4th param).
01588     // Leaving aside the grow factor, lets allocate an initial #
01589     // of bins = nsyms / max bin load.
01590 
01591 #if defined(TIMED_PARSE)
01592     struct timeval starttime;
01593     gettimeofday(&starttime, NULL);
01594 #endif
01595     if (alloc_syms) 
01596       {
01597     // find symbol and string data
01598 #if defined(os_vxworks)
01599         // Avoid assigning symbols to DEFAULT_MODULE on VxWorks
01600         string module = mf->pathname();
01601 #else
01602     string module = "DEFAULT_MODULE";
01603 #endif
01604     string name   = "DEFAULT_NAME";
01605     Elf_X_Data symdata, strdata;
01606 
01607     if (symscnp && strscnp)
01608       {
01609             symdata = symscnp->get_data();
01610             strdata = strscnp->get_data();
01611             parse_symbols(symdata, strdata, bssscnp, symscnp, false, module);
01612       }   
01613 
01614     no_of_symbols_ = nsymbols();
01615 
01616     // try to resolve the module names of global symbols
01617     // Sun compiler stab.index section 
01618     fix_global_symbol_modules_static_stab(stabs_indxcnp, stabstrs_indxcnp);
01619 
01620     // STABS format (.stab section)
01621     fix_global_symbol_modules_static_stab(stabscnp, stabstrscnp);
01622 
01623     // DWARF format (.debug_info section)
01624     fix_global_symbol_modules_static_dwarf();
01625 
01626     if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
01627       {
01628             symdata = dynsym_scnp->get_data();
01629             strdata = dynstr_scnp->get_data();
01630             parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
01631       }
01632 
01633     //TODO
01634     //Have a hash on the symbol table. Iterate over dynamic symbol table to check if it exists
01635     //If yes set dynamic for the symbol ( How to distinguish between symbols only in symtab,
01636     //         symbols only in dynsymtab & symbols present in both).
01637     // Else add dynamic symbol to dictionary
01638     // (or) Have two sepearate dictionaries. Makes life easy!
01639     // Think about it today!!
01640 
01641     //allsymbols = merge(allsymbols, alldynSymbols);
01642 
01643 #if defined(TIMED_PARSE)
01644     struct timeval endtime;
01645     gettimeofday(&endtime, NULL);
01646     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
01647     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
01648     unsigned long difftime = lendtime - lstarttime;
01649     double dursecs = difftime/(1000);
01650     cout << "parsing/fixing/overriding elf took "<<dursecs <<" msecs" << endl;
01651 #endif
01652 
01653     if (dynamic_addr_ && dynsym_scnp && dynstr_scnp) 
01654       {
01655             parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
01656       }
01657 
01658 #if defined(os_vxworks)
01659         // Load relocations like they are PLT entries.
01660         // Use the non-dynamic symbol tables.
01661         if (rel_plt_scnp && symscnp && strscnp) {
01662             if (!get_relocation_entries(rel_plt_scnp, symscnp, strscnp))
01663                 goto cleanup;
01664         }
01665 #endif
01666 
01667     // populate "fbt_"
01668     if (rel_plt_scnp && dynsym_scnp && dynstr_scnp) 
01669       {
01670             if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) 
01671           {
01672         goto cleanup;
01673           }
01674       }
01675         parse_all_relocations(*elfHdr, dynsym_scnp, dynstr_scnp,
01676                 symscnp, strscnp);
01677 
01678     handle_opd_relocations();    
01679       }
01680 
01681     //Set object type
01682     int e_type = elfHdr->e_type();
01683 
01684     if (e_type == ET_DYN) {
01685     obj_type_ = obj_SharedLib;
01686     }else if (e_type == ET_EXEC) {
01687     obj_type_ = obj_Executable;
01688     }else if (e_type == ET_REL) {
01689         obj_type_ = obj_RelocatableFile;
01690     }
01691 
01692     // Set rel type based on the ELF machine type
01693     relType_ = getRelTypeByElfMachine(elfHdr);
01694 
01695     if (opd_scnp) {
01696       parse_opd(opd_scnp);
01697     }
01698 
01699     return;
01700   } // end binding contour (for "goto cleanup2")
01701 
01702  cleanup: 
01703   {
01704     /* NOTE: The file should NOT be munmap()ed.  The mapped file is
01705        used for function parsing (see dyninstAPI/src/symtab.C) */
01706 
01707     fprintf(stderr, "%s[%d]:  failed to load elf object\n", FILE__, __LINE__);
01708   }
01709 }
01710 
01711 void Object::load_shared_object(bool alloc_syms) 
01712 {
01713   Elf_X_Shdr *bssscnp = 0;
01714   Elf_X_Shdr *symscnp = 0;
01715   Elf_X_Shdr *strscnp = 0;
01716   Elf_X_Shdr *stabscnp = 0;
01717   Elf_X_Shdr *stabstrscnp = 0;
01718   Elf_X_Shdr *stabs_indxcnp = 0;
01719   Elf_X_Shdr *stabstrs_indxcnp = 0;
01720   Offset txtaddr = 0;
01721   Offset dataddr = 0;
01722   Elf_X_Shdr *rel_plt_scnp = 0;
01723   Elf_X_Shdr *plt_scnp = 0; 
01724   Elf_X_Shdr *got_scnp = 0;
01725   Elf_X_Shdr *dynsym_scnp = 0;
01726   Elf_X_Shdr *dynstr_scnp = 0;
01727   Elf_X_Shdr *dynamic_scnp = 0;
01728   Elf_X_Shdr *eh_frame_scnp = 0;
01729   Elf_X_Shdr *gcc_except = 0;
01730   Elf_X_Shdr *interp_scnp = 0;
01731   Elf_X_Shdr *opd_scnp = NULL;
01732 
01733   { // binding contour (for "goto cleanup2")
01734 
01735     // initialize "valid" regions of code and data segments
01736     code_vldS_ = (Offset) -1;
01737     code_vldE_ = 0;
01738     data_vldS_ = (Offset) -1;
01739     data_vldE_ = 0;
01740 
01741     if (!loaded_elf(txtaddr, dataddr, bssscnp, symscnp, strscnp,
01742             stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
01743             rel_plt_scnp, plt_scnp, got_scnp, dynsym_scnp, dynstr_scnp,
01744                     dynamic_scnp, eh_frame_scnp, gcc_except, interp_scnp, opd_scnp))
01745       goto cleanup2;
01746 
01747     if (interp_scnp)
01748       interpreter_name_ = (char *) interp_scnp->get_data().d_buf(); 
01749 
01750     addressWidth_nbytes = elfHdr->wordSize();
01751 
01752     // find code and data segments....
01753     find_code_and_data(*elfHdr, txtaddr, dataddr);
01754 
01755     get_valid_memory_areas(*elfHdr);
01756 
01757 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
01758     //fprintf(stderr, "[%s:%u] - Mod Name is %s\n", __FILE__, __LINE__, name.c_str());
01759     if (eh_frame_scnp != 0 && gcc_except != 0) {
01760       find_catch_blocks(eh_frame_scnp, gcc_except, 
01761             txtaddr, dataddr, catch_addrs_);
01762     }
01763 #endif
01764 
01765 #if defined(TIMED_PARSE)
01766     struct timeval starttime;
01767     gettimeofday(&starttime, NULL);
01768 #endif
01769 
01770     if (alloc_syms) {
01771       // build symbol dictionary
01772       string module = mf->pathname();
01773       string name   = "DEFAULT_NAME";
01774 
01775       Elf_X_Data symdata, strdata;
01776       if (symscnp && strscnp)
01777     {
01778       symdata = symscnp->get_data();
01779       strdata = strscnp->get_data();
01780       if (!symdata.isValid() || !strdata.isValid()) {
01781         log_elferror(err_func_, "locating symbol/string data");
01782         goto cleanup2;
01783       }
01784       bool result = parse_symbols(symdata, strdata, bssscnp, symscnp, false, module);
01785       if (!result) {
01786         log_elferror(err_func_, "locating symbol/string data");
01787         goto cleanup2;
01788       }
01789     } 
01790 
01791       no_of_symbols_ = nsymbols();
01792 
01793       if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
01794     {
01795       symdata = dynsym_scnp->get_data();
01796       strdata = dynstr_scnp->get_data();
01797       parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
01798     }
01799 
01800 #if defined(TIMED_PARSE)
01801       struct timeval endtime;
01802       gettimeofday(&endtime, NULL);
01803       unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
01804       unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
01805       unsigned long difftime = lendtime - lstarttime;
01806       double dursecs = difftime/(1000 * 1000);
01807       cout << "*INSERT SYMBOLS* elf took "<<dursecs <<" msecs" << endl;
01808       //cout << "parsing/fixing/overriding/insertion elf took "<<dursecs <<" msecs" << endl;
01809 #endif
01810       if(dynamic_addr_ && dynsym_scnp && dynstr_scnp) {
01811     parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
01812       }
01813 
01814 #if defined(os_vxworks)
01815       // Load relocations like they are PLT entries.
01816       // Use the non-dynamic symbol tables.
01817       if (rel_plt_scnp && symscnp && strscnp) {
01818           if (!get_relocation_entries(rel_plt_scnp, symscnp, strscnp))
01819               goto cleanup2;
01820       }
01821 #endif
01822 
01823       if (rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
01824          if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) { 
01825             goto cleanup2;
01826          }
01827       }
01828 
01829       parse_all_relocations(*elfHdr, dynsym_scnp, dynstr_scnp,
01830                 symscnp, strscnp);
01831     // Apply relocations to opd
01832     handle_opd_relocations();    
01833     }
01834 
01835     //Set object type
01836     int e_type = elfHdr->e_type();
01837     if (e_type == ET_DYN) {
01838       obj_type_ = obj_SharedLib;
01839     }
01840     else if (e_type == ET_EXEC) {
01841       obj_type_ = obj_Executable;
01842     }else if( e_type == ET_REL ) {
01843         obj_type_ = obj_RelocatableFile;
01844     }
01845 
01846 
01847     if (opd_scnp) {
01848       parse_opd(opd_scnp);
01849     }
01850 
01851     // Set rel type based on the ELF machine type
01852     relType_ = getRelTypeByElfMachine(elfHdr);
01853 
01854   } // end binding contour (for "goto cleanup2")
01855 
01856  cleanup2: 
01857   {
01858   }
01859 }
01860 
01861 static Symbol::SymbolType pdelf_type(int elf_type)
01862 {
01863   switch (elf_type) {
01864   case STT_FILE:   return Symbol::ST_MODULE;
01865   case STT_SECTION:return Symbol::ST_SECTION;
01866   case STT_OBJECT: return Symbol::ST_OBJECT;
01867   case STT_TLS:    return Symbol::ST_TLS;
01868   case STT_FUNC:   return Symbol::ST_FUNCTION;
01869   case STT_NOTYPE: return Symbol::ST_NOTYPE;
01870 #if defined(STT_GNU_IFUNC)
01871   case STT_GNU_IFUNC: return Symbol::ST_INDIRECT;
01872 #endif
01873   default: return Symbol::ST_UNKNOWN;
01874   }
01875 }
01876 
01877 static Symbol::SymbolLinkage pdelf_linkage(int elf_binding)
01878 {
01879   switch (elf_binding) {
01880   case STB_LOCAL:  return Symbol::SL_LOCAL;
01881   case STB_WEAK:   return Symbol::SL_WEAK;
01882   case STB_GLOBAL: return Symbol::SL_GLOBAL;
01883   }
01884   return Symbol::SL_UNKNOWN;
01885 }
01886 
01887 static Symbol::SymbolVisibility pdelf_visibility(int elf_visibility)
01888 {
01889   switch (elf_visibility) {
01890   case STV_DEFAULT:    return Symbol::SV_DEFAULT;
01891   case STV_INTERNAL:   return Symbol::SV_INTERNAL;
01892   case STV_HIDDEN:     return Symbol::SV_HIDDEN;
01893   case STV_PROTECTED:  return Symbol::SV_PROTECTED;
01894   }
01895   return Symbol::SV_UNKNOWN;
01896 }
01897 
01898 //============================================================================
01899 
01900 //#include "dyninstAPI/src/arch.h"
01901 //#include "dyninstAPI/src/inst.h"
01902 //#include "dyninstAPI/src/instPoint.h" // includes instPoint-x86.h
01903 //#include "dyninstAPI/src/instP.h" // class returnInstance
01904 //#include "dyninstAPI/src/rpcMgr.h"
01905 
01906 //linear search
01907 bool lookUpSymbol( std::vector< Symbol *>& allsymbols, Offset& addr )
01908 {
01909   for( unsigned i = 0; i < allsymbols.size(); i++ )
01910     {
01911       if( allsymbols[ i ]->getOffset() == addr )
01912     {
01913       return true;
01914     }
01915     }
01916   return false;
01917 }
01918 
01919 bool lookUpAddress( std::vector< Offset >& jumpTargets, Offset& addr )
01920 {
01921   for( unsigned i = 0; i < jumpTargets.size(); i++ )
01922     {
01923       if( jumpTargets[ i ] == addr )
01924     {
01925       return true;
01926     }
01927     }
01928   return false;
01929 }
01930 
01931 //utitility function to print std::vector of symbols
01932 void printSyms( std::vector< Symbol *>& allsymbols )
01933 {
01934   for( unsigned i = 0; i < allsymbols.size(); i++ )
01935     {
01936       if( allsymbols[ i ]->getType() != Symbol::ST_FUNCTION )
01937     {
01938       continue;
01939     }
01940       cout << allsymbols[ i ] << endl;
01941     } 
01942 } 
01943 
01944 // Official Procedure Descriptor handler
01945 //
01946 // Some platforms (PPC64 Linux libc v2.1) only produce function
01947 // symbols which point into the .opd section.  Find the actual
01948 // function address in .text, and fix the symbol.
01949 //
01950 // Additionally, large binaries may contain multiple TOC values.
01951 // Use the .opd section to determine the correct per-function TOC.
01952 // See binutils' bfd/elf64-ppc.c for all the gory details.
01953 //
01954 // Symbol altering routines should be minimized to prevent problems
01955 // in the rewrite case.  Instead, return a new symbol the encapsulates
01956 // the correct information.
01957 
01958 // In statically linked binaries, there are relocations against 
01959 // .opd section. We need to apply the relocations before using
01960 // opd symbols. 
01961 
01962 void Object::parse_opd(Elf_X_Shdr *opd_hdr) {
01963   // If the OPD is filled in, parse it and fill in our TOC table
01964   assert(opd_hdr);
01965 
01966   Elf_X_Data data = opd_hdr->get_data();
01967   assert(data.isValid());
01968   
01969   // Let's read this puppy
01970   unsigned long *buf = (unsigned long *)data.d_buf();
01971 
01972   // In some cases, the OPD is a set of 3-tuples: <func offset, TOC, environment ptr>.
01973   // In others, it's a set of 2-tuples. Since we can't tell the difference, we
01974   // instead look for function offsets. 
01975   // Heck, it can even change within the opd!
01976 
01977   // In almost all cases, the TOC is the same. So let's store it at the
01978   // special location 0 and only record differences. 
01979   Offset baseTOC = buf[1];
01980   TOC_table_[0] = baseTOC;
01981 
01982   // Note the lack of 32/64 here: okay because the only platform with an OPD
01983   // is 64-bit elf. 
01984   unsigned i = 0;
01985   while (i < (data.d_size() / sizeof(unsigned long))) {
01986     Offset func = buf[i];
01987     Offset toc = buf[i+1];
01988 
01989     if (func == 0 && i != 0) break;
01990 
01991     if (symsByOffset_.find(func) == symsByOffset_.end()) {
01992       i++;
01993       continue;
01994     }
01995 
01996     if (toc != baseTOC) {
01997       TOC_table_[func] = toc;
01998     }
01999     i += 2;
02000   }
02001 }
02002 
02003 void Object::handle_opd_relocations(){
02004 
02005   unsigned int i = 0, opdregion = 0;
02006   while (i < regions_.size()) {
02007     if(regions_[i]->getRegionName().compare(".opd") == 0){
02008         opdregion = i;
02009         break;
02010     }
02011     i++;
02012    }
02013 
02014   vector<relocationEntry> region_rels = (regions_[opdregion])->getRelocations();
02015   vector<relocationEntry>::iterator rel_it;
02016   vector<Symbol *>::iterator sym_it;
02017   for(sym_it = opdsymbols_.begin(); sym_it != opdsymbols_.end(); ++sym_it) {
02018     for(rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
02019       if((*sym_it)->getPtrOffset() == (*rel_it).rel_addr()) {
02020     i = 0;
02021     while (i < regions_.size()) {
02022       if(regions_[i]->getRegionName().compare((*rel_it).getDynSym()->getMangledName()) == 0){
02023         Region *targetRegion = regions_[i];
02024         Offset regionOffset = targetRegion->getDiskOffset()+(*rel_it).addend();
02025         (*sym_it)->setRegion(targetRegion);
02026         (*sym_it)->setOffset(regionOffset);   // Store code address for the function.
02027         break;
02028       }
02029       ++i;
02030     }
02031       }
02032     }
02033   }
02034   opdsymbols_.clear();
02035 }
02036 
02037 Symbol *Object::handle_opd_symbol(Region *opd, Symbol *sym)
02038 {
02039   if (!sym) return NULL;
02040 
02041   Offset soffset = sym->getOffset();
02042   Offset *opd_entry = (Offset *)(((char *)opd->getPtrToRawData()) +
02043                                  (soffset - opd->getDiskOffset()));
02044   assert(opd->isOffsetInRegion(soffset));  // Symbol must be in .opd section.
02045 
02046   Symbol *retval = new Symbol(*sym); // Copy the .opd symbol.
02047   retval->setOffset(opd_entry[0]);   // Store code address for the function.
02048   retval->setLocalTOC(opd_entry[1]); // Store TOC address for this function.
02049   retval->setPtrOffset(soffset);     // Original address is the ptr address.
02050 
02051   // Find the appropriate region for the new symbol.
02052   unsigned int i = 0;
02053   while (i < regions_.size()) {
02054     if (regions_[i]->isOffsetInRegion(opd_entry[0])) {
02055       retval->setRegion(regions_[i]);
02056       break;
02057     }
02058     ++i;
02059   }
02060   assert(i < regions_.size());
02061   retval->setSymbolType(Symbol::ST_FUNCTION);
02062 #if 0
02063   retval->tag_ = Symbol::TAG_INTERNAL;  // Not sure if this is an appropriate
02064                                         // use of the tag field, but we need
02065                                         // to mark this symbol somehow as a
02066                                         // fake.
02067 #endif
02068   ///* DEBUG */ fprintf(stderr, "addr:0x%lx ptr_addr:0x%lx toc:0x%lx section:%s\n", opd_entry[0], soffset, opd_entry[1], regions_[i]->getRegionName().c_str());
02069   return retval;
02070 }
02071 
02072 // parse_symbols(): populate "allsymbols"
02073 bool Object::parse_symbols(Elf_X_Data &symdata, Elf_X_Data &strdata,
02074                            Elf_X_Shdr* bssscnp,
02075                            Elf_X_Shdr* symscnp,
02076                            bool /*shared*/, string smodule)
02077 {
02078 #if defined(TIMED_PARSE)
02079    struct timeval starttime;
02080    gettimeofday(&starttime, NULL);
02081 #endif
02082 
02083    if (!symdata.isValid() || !strdata.isValid()) {
02084       return false;
02085    }
02086 
02087    Elf_X_Sym syms = symdata.get_sym();
02088    const char *strs = strdata.get_string();
02089    if(syms.isValid()){
02090       for (unsigned i = 0; i < syms.count(); i++) {
02091          //If it is not a dynamic executable then we need undefined symbols
02092          //in symtab section so that we can resolve symbol references. So 
02093          //we parse & store undefined symbols only if there is no dynamic
02094          //symbol table
02095          //1/09: not so anymore--we want to preserve all symbols,
02096          //regardless of file type
02097       
02098          int etype = syms.ST_TYPE(i);
02099          int ebinding = syms.ST_BIND(i);
02100          int evisibility = syms.ST_VISIBILITY(i);
02101 
02102          // resolve symbol elements
02103          string sname = &strs[ syms.st_name(i) ];
02104          Symbol::SymbolType stype = pdelf_type(etype);
02105          Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
02106          Symbol::SymbolVisibility svisibility = pdelf_visibility(evisibility);
02107          unsigned ssize = syms.st_size(i);
02108          unsigned secNumber = syms.st_shndx(i);
02109 
02110          Offset soffset;
02111          if (symscnp->isFromDebugFile()) {
02112             Offset soffset_dbg = syms.st_value(i);
02113             soffset = soffset_dbg;
02114             if (soffset_dbg) {
02115                bool result = convertDebugOffset(soffset_dbg, soffset);
02116                if (!result) {
02117                   //Symbol does not match any section, can't convert
02118                   continue;
02119                }
02120             }
02121          }
02122          else {
02123             soffset = syms.st_value(i);
02124          }
02125 
02126          /* icc BUG: Variables in BSS are categorized as ST_NOTYPE instead of 
02127             ST_OBJECT.  To fix this, we check if the symbol is in BSS and has 
02128             size > 0. If so, we can almost always say it is a variable and hence, 
02129             change the type from ST_NOTYPE to ST_OBJECT.
02130          */
02131          if (bssscnp) {
02132             Offset bssStart = Offset(bssscnp->sh_addr());
02133             Offset bssEnd = Offset (bssStart + bssscnp->sh_size()) ;
02134             
02135             if(( bssStart <= soffset) && ( soffset < bssEnd ) && (ssize > 0) && 
02136                (stype == Symbol::ST_NOTYPE)) 
02137             {
02138                stype = Symbol::ST_OBJECT;
02139             }
02140          }
02141 
02142          // discard "dummy" symbol at beginning of file
02143          if (i==0 && sname == "" && soffset == (Offset)0)
02144             continue;
02145 
02146 
02147          Region *sec;
02148          if(secNumber >= 1 && secNumber < regions_.size()) {
02149             sec = regions_[secNumber];
02150          } else {
02151             sec = NULL;
02152          }
02153          int ind = int (i);
02154          int strindex = syms.st_name(i);
02155 
02156           if(stype == Symbol::ST_SECTION && sec != NULL) {
02157             sname = sec->getRegionName();
02158             soffset = sec->getDiskOffset();
02159           } 
02160 
02161          if (stype == Symbol::ST_MODULE) {
02162             smodule = sname;
02163          }
02164          Symbol *newsym = new Symbol(sname, 
02165                                      stype,
02166                                      slinkage, 
02167                                      svisibility, 
02168                                      soffset,
02169                                      NULL,
02170                                      sec, 
02171                                      ssize,
02172                                      false,
02173                                      (secNumber == SHN_ABS),
02174                                      ind,
02175                                      strindex,
02176                                      (secNumber == SHN_COMMON));
02177 
02178          if (stype == Symbol::ST_UNKNOWN)
02179             newsym->setInternalType(etype);
02180 
02181          if (sec && sec->getRegionName() == OPD_NAME && stype == Symbol::ST_FUNCTION ) {
02182             newsym = handle_opd_symbol(sec, newsym);
02183 
02184         opdsymbols_.push_back(newsym);
02185             symbols_[sname].push_back(newsym);
02186             symsByOffset_[newsym->getOffset()].push_back(newsym);
02187             symsToModules_[newsym] = smodule; 
02188          } else {
02189             symbols_[sname].push_back(newsym);
02190             symsByOffset_[newsym->getOffset()].push_back(newsym);
02191             symsToModules_[newsym] = smodule; 
02192     }
02193 
02194       }
02195    } // syms.isValid()
02196 #if defined(TIMED_PARSE)
02197    struct timeval endtime;
02198    gettimeofday(&endtime, NULL);
02199    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02200    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02201    unsigned long difftime = lendtime - lstarttime;
02202    double dursecs = difftime/(1000 * 1000);
02203    cout << "parsing elf took "<<dursecs <<" secs" << endl;
02204 #endif
02205    return true;
02206 }
02207 
02208 // parse_symbols(): populate "allsymbols"
02209 // Lazy parsing of dynamic symbol  & string tables
02210 // Parsing the dynamic symbols lazily would certainly 
02211 // not increase the overhead of the entire parse
02212 void Object::parse_dynamicSymbols (Elf_X_Shdr *&
02213                                    dyn_scnp
02214                                    , Elf_X_Data &symdata,
02215                                    Elf_X_Data &strdata,
02216                                    bool /*shared*/, 
02217                                    std::string smodule)
02218 {
02219 #if defined(TIMED_PARSE)
02220   struct timeval starttime;
02221   gettimeofday(&starttime, NULL);
02222 #endif
02223 
02224   Elf_X_Sym syms = symdata.get_sym();
02225   const char *strs = strdata.get_string();
02226   Elf_X_Shdr *versymSec = NULL, *verneedSec = NULL, *verdefSec = NULL;
02227   Elf_X_Data data = dyn_scnp->get_data();
02228   Elf_X_Dyn dyns = data.get_dyn();
02229   unsigned verneednum = 0, verdefnum = 0;
02230   Elf_X_Versym symVersions;
02231   Elf_X_Verdef *symVersionDefs = NULL;
02232   Elf_X_Verneed *symVersionNeeds = NULL;
02233   for (unsigned i = 0; i < dyns.count(); ++i) {
02234     switch(dyns.d_tag(i)) {
02235     case DT_NEEDED:
02236       deps_.push_back(&strs[dyns.d_ptr(i)]);
02237       break;
02238     case DT_VERSYM:
02239       versymSec = getRegionHdrByAddr(dyns.d_ptr(i));
02240       break;
02241     case DT_VERNEED:
02242       verneedSec = getRegionHdrByAddr(dyns.d_ptr(i));
02243       break;
02244     case DT_VERDEF:
02245       verdefSec = getRegionHdrByAddr(dyns.d_ptr(i));
02246       break;
02247     case DT_VERNEEDNUM:
02248       verneednum = dyns.d_ptr(i);
02249       break;
02250     case DT_VERDEFNUM:
02251       verdefnum = dyns.d_ptr(i);
02252       break;
02253     default:
02254       break;
02255     }
02256   }
02257   if(versymSec)
02258     symVersions = versymSec->get_data().get_versyms();
02259   if(verdefSec)
02260     symVersionDefs = verdefSec->get_data().get_verDefSym();
02261   if(verneedSec)
02262     symVersionNeeds = verneedSec->get_data().get_verNeedSym();
02263     
02264   for(unsigned i = 0; i < verdefnum ;i++) {
02265     Elf_X_Verdaux *aux = symVersionDefs->get_aux();
02266     for(unsigned j=0; j< symVersionDefs->vd_cnt(); j++){
02267       versionMapping[symVersionDefs->vd_ndx()].push_back(&strs[aux->vda_name()]);
02268       Elf_X_Verdaux *auxnext = aux->get_next();
02269       delete aux;
02270       aux = auxnext;
02271     }
02272     Elf_X_Verdef *symVersionDefsnext = symVersionDefs->get_next();
02273     delete symVersionDefs;
02274     symVersionDefs = symVersionDefsnext;
02275   }
02276 
02277   for(unsigned i = 0; i < verneednum; i++){
02278     Elf_X_Vernaux *aux = symVersionNeeds->get_aux();
02279     for(unsigned j=0; j< symVersionNeeds->vn_cnt(); j++){
02280       versionMapping[aux->vna_other()].push_back(&strs[aux->vna_name()]);
02281       versionFileNameMapping[aux->vna_other()] = &strs[symVersionNeeds->vn_file()];
02282       Elf_X_Vernaux *auxnext = aux->get_next();
02283       delete aux;
02284       aux = auxnext;
02285     }
02286     Elf_X_Verneed *symVersionNeedsnext = symVersionNeeds->get_next();
02287     delete symVersionNeeds;
02288     symVersionNeeds = symVersionNeedsnext;
02289   }
02290    
02291   if(syms.isValid()) {
02292     for (unsigned i = 0; i < syms.count(); i++) {
02293       int etype = syms.ST_TYPE(i);
02294       int ebinding = syms.ST_BIND(i);
02295       int evisibility = syms.ST_VISIBILITY(i);
02296       
02297       // resolve symbol elements
02298       string sname = &strs[ syms.st_name(i) ];
02299       Symbol::SymbolType stype = pdelf_type(etype);
02300       Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
02301       Symbol::SymbolVisibility svisibility = pdelf_visibility(evisibility);
02302       unsigned ssize = syms.st_size(i);
02303       Offset soffset = syms.st_value(i);
02304       unsigned secNumber = syms.st_shndx(i);
02305 
02306       // discard "dummy" symbol at beginning of file
02307       if (i==0 && sname == "" && soffset == (Offset)0)
02308          continue;
02309       
02310       Region *sec;
02311       if(secNumber >= 1 && secNumber < regions_.size()) {
02312          sec = regions_[secNumber];
02313       } else {
02314          sec = NULL;
02315       }
02316 
02317       int ind = int (i);
02318       int strindex = syms.st_name(i);
02319 
02320       if (stype == Symbol::ST_MODULE) {
02321          smodule = sname;
02322       }
02323 
02324       Symbol *newsym = new Symbol(sname, 
02325                                   stype, 
02326                                   slinkage, 
02327                                   svisibility, 
02328                                   soffset, 
02329                                   NULL,
02330                                   sec, 
02331                                   ssize, 
02332                                   true,  // is dynamic
02333                                   (secNumber == SHN_ABS),
02334                                   ind,
02335                                   strindex,
02336                                   (secNumber == SHN_COMMON));
02337 
02338       if (stype == Symbol::ST_UNKNOWN)
02339          newsym->setInternalType(etype);
02340       
02341       if(versymSec) {
02342     unsigned short raw = symVersions.get(i);
02343     bool hidden = raw >> 15;
02344     int index = raw & 0x7fff;
02345          if(versionFileNameMapping.find(index) != versionFileNameMapping.end()) {
02346        //printf("version filename for %s: %s\n", sname.c_str(),
02347        //versionFileNameMapping[index].c_str());
02348             newsym->setVersionFileName(versionFileNameMapping[index]);
02349          }
02350          if(versionMapping.find(index) != versionMapping.end()) {
02351        //printf("versions for %s: ", sname.c_str());
02352        //for (unsigned k=0; k < versionMapping[index].size(); k++)
02353        //printf(" %s", versionMapping[index][k].c_str());
02354        newsym->setVersions(versionMapping[index]);
02355        //printf("\n");
02356          }
02357      if (hidden) {
02358        newsym->setVersionHidden();
02359      }
02360       }
02361       // register symbol in dictionary
02362 
02363       if (sec && sec->getRegionName() == OPD_NAME && stype == Symbol::ST_FUNCTION ) {
02364          newsym = handle_opd_symbol(sec, newsym);
02365          opdsymbols_.push_back(newsym);
02366          
02367          symbols_[sname].push_back(newsym);
02368          symsByOffset_[newsym->getOffset()].push_back(newsym);
02369          symsToModules_[newsym] = smodule;
02370       } else {
02371          symbols_[sname].push_back(newsym);
02372          symsByOffset_[newsym->getOffset()].push_back(newsym);
02373          symsToModules_[newsym] = smodule; 
02374       }
02375     }
02376   }
02377   
02378 #if defined(TIMED_PARSE)
02379   struct timeval endtime;
02380   gettimeofday(&endtime, NULL);
02381   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02382   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02383   unsigned long difftime = lendtime - lstarttime;
02384   double dursecs = difftime/(1000 * 1000);
02385   cout << "parsing elf took "<<dursecs <<" secs" << endl;
02386 #endif
02387 }
02388 
02389 #if defined(USES_DWARF_DEBUG)
02390 
02391 string Object::find_symbol(string name)
02392 {
02393   string name2;
02394 
02395   // pass #1: unmodified
02396   name2 = name;
02397   if (symbols_.find(name2)!=symbols_.end()) return name2;
02398 
02399   // pass #2: leading underscore (C)
02400   name2 = "_" + name;
02401   if (symbols_.find(name2)!=symbols_.end()) return name2;
02402 
02403   // pass #3: trailing underscore (Fortran)
02404   name2 = name + "_";
02405   if (symbols_.find(name2)!=symbols_.end())
02406     return name2;
02407 
02408   return "";
02409 }
02410 
02411 #endif
02412 
02413 
02414 /********************************************************
02415  *
02416  * For object files only....
02417  *   read the .debug_info section to find the module of global symbols
02418  *   see documents...
02419  *   - "DWARF Debugging Information Format"
02420  *   - "A Consumer Libary Interface to DWARF"
02421  *
02422  ********************************************************/
02423 
02424 #if defined(USES_DWARF_DEBUG)
02425 
02426 void pd_dwarf_handler(Dwarf_Error error, Dwarf_Ptr /*userData*/)
02427 {
02428   if (error == NULL)
02429     return;
02430 
02431   char *dwarf_msg = dwarf_errmsg(error);
02432   string str = string("DWARF Error: ")+ dwarf_msg;
02433   dwarf_err_func(str.c_str());
02434       
02435   //bperr( "DWARF error: %s\n", dwarf_msg);
02436 }
02437 
02438 Dwarf_Signed declFileNo = 0;
02439 char ** declFileNoToName = NULL;
02440 
02441 bool Object::fixSymbolsInModule( Dwarf_Debug dbg, string & moduleName, Dwarf_Die dieEntry)
02442 {
02443  start: 
02444 
02445    Dwarf_Half dieTag;
02446    string useModuleName;
02447    int status = dwarf_tag( dieEntry, & dieTag, NULL );
02448    if (status != DW_DLV_OK) goto error;
02449 
02450    useModuleName = moduleName;
02451 
02452    /* For debugging. */
02453    Dwarf_Off dieOffset;
02454    status = dwarf_die_CU_offset( dieEntry, & dieOffset, NULL );
02455    if (status != DW_DLV_OK) goto error;
02456 
02457    switch( dieTag ) {
02458       case DW_TAG_subprogram: 
02459       case DW_TAG_entry_point: 
02460          {
02461             /* Let's try ignoring artificial entries, hmm-kay? */
02462 
02463             Dwarf_Bool isArtificial;
02464             status = dwarf_hasattr( dieEntry, DW_AT_artificial, & isArtificial, NULL );
02465             if (status != DW_DLV_OK) goto error;
02466 
02467             if ( isArtificial ) 
02468             {
02469                break; 
02470             }
02471 
02472             /* Only entries with a PC must be defining declarations.  However,
02473                to avoid trying to decide in which module a DW_TAG_inlined_subroutine's
02474                DW_AT_abstract_origin belongs, we just insert the abstract origin itself. */
02475 
02476             Dwarf_Bool hasLowPC;
02477             status = dwarf_hasattr( dieEntry, DW_AT_low_pc, & hasLowPC, NULL );
02478             if (status != DW_DLV_OK) goto error;
02479 
02480             Dwarf_Bool isAbstractOrigin;
02481             status = dwarf_hasattr( dieEntry, DW_AT_inline, & isAbstractOrigin, NULL );
02482             if (status != DW_DLV_OK) goto error;
02483 
02484             if ( ! hasLowPC && ! isAbstractOrigin ) 
02485             {
02486                break; 
02487             }
02488 
02489             bool isDeclaredNotInlined = false;
02490 
02491             /* Inline functions are "uninstrumentable", so leave them off the where axis. */
02492 
02493             if ( isAbstractOrigin ) 
02494             {
02495                Dwarf_Attribute inlineAttribute;
02496                status = dwarf_attr( dieEntry, DW_AT_inline, & inlineAttribute, NULL );
02497                if (status != DW_DLV_OK) goto error;
02498 
02499                Dwarf_Unsigned inlineTag;
02500                status = dwarf_formudata( inlineAttribute, & inlineTag, NULL );
02501                if (status != DW_DLV_OK) goto error;
02502 
02503                if ( inlineTag == DW_INL_inlined || inlineTag == DW_INL_declared_inlined ) 
02504                {
02505                   break; 
02506                }
02507 
02508                if ( inlineTag == DW_INL_declared_not_inlined ) 
02509                {
02510                   isDeclaredNotInlined = true; 
02511                }
02512 
02513                dwarf_dealloc( dbg, inlineAttribute, DW_DLA_ATTR );
02514             }
02515 
02516             /* If a DIE has a specification, the specification has its name
02517                and (optional) linkage name.  */
02518 
02519             Dwarf_Attribute specificationAttribute;
02520             status = dwarf_attr(dieEntry, DW_AT_specification, &specificationAttribute, NULL);
02521 
02522             if (status == DW_DLV_ERROR) goto error;
02523 
02524 
02525             Dwarf_Die nameEntry = dieEntry;
02526 
02527             if ( status == DW_DLV_OK ) 
02528             {
02529                Dwarf_Off specificationOffset;
02530                status = dwarf_global_formref(specificationAttribute, &specificationOffset, NULL);
02531                if (status != DW_DLV_OK) goto error;
02532 
02533                status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
02534                if (status != DW_DLV_OK) goto error;
02535 
02536                dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
02537             } /* end if the DIE has a specification. */
02538 
02539             /* Ignore artificial entries. */
02540 
02541             status = dwarf_hasattr( nameEntry, DW_AT_artificial, & isArtificial, NULL );
02542             if (status != DW_DLV_OK) goto error;
02543 
02544             if ( isArtificial ) 
02545             {
02546                break; 
02547             }
02548 
02549             /* What's its name? */
02550             char * dieName = NULL;
02551             status = dwarf_diename( nameEntry, & dieName, NULL );
02552             if (status == DW_DLV_ERROR) goto error;
02553 
02554             /* Prefer the linkage (symbol table) name. */
02555             Dwarf_Attribute linkageNameAttribute;
02556             status = dwarf_attr(nameEntry, DW_AT_MIPS_linkage_name, &linkageNameAttribute, NULL);
02557             if (status == DW_DLV_ERROR) goto error;
02558 
02559             bool hasLinkageName = false;
02560 
02561             if ( status == DW_DLV_OK ) 
02562             {
02563                dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02564                status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
02565                if (status != DW_DLV_OK) goto error;
02566                hasLinkageName = true;
02567             }
02568 
02569             /* Anonymous functions are useless to us. */
02570 
02571             if ( dieName == NULL ) 
02572             {
02573                break;
02574             }
02575 
02576             /* Try to find the corresponding global symbol name. */
02577 
02578             Dwarf_Die declEntry = nameEntry;
02579 
02580             std::vector<Symbol *> foundSymbols;
02581             
02582             string globalSymbol = find_symbol(dieName);
02583 
02584             if (globalSymbol != "") {
02585                foundSymbols = symbols_[globalSymbol];
02586             }
02587             else if ( globalSymbol == "" && ! hasLinkageName && isDeclaredNotInlined ) 
02588             {
02589                /* Then scan forward for its concrete instance. */
02590 
02591                bool first = true;
02592                Dwarf_Die siblingDie = dieEntry;
02593 
02594                while ( true ) 
02595                {
02596                   Dwarf_Die priorSibling = siblingDie;
02597                   status = dwarf_siblingof( dbg, siblingDie, & siblingDie, NULL );
02598                   if (status == DW_DLV_ERROR) goto error;
02599 
02600                   if ( ! first ) 
02601                   {
02602                      dwarf_dealloc( dbg, priorSibling, DW_DLA_DIE ); 
02603                   }
02604                   if ( status == DW_DLV_NO_ENTRY ) 
02605                   {
02606                      break; 
02607                   }
02608 
02609                   Dwarf_Attribute abstractOriginAttr;
02610                   status = dwarf_attr(siblingDie, DW_AT_abstract_origin, &abstractOriginAttr, NULL);
02611 
02612                   if (status == DW_DLV_ERROR) goto error;
02613 
02614                   /* Is its abstract origin the current dieEntry? */
02615 
02616                   if ( status == DW_DLV_OK ) 
02617                   {
02618                      Dwarf_Off abstractOriginOffset;
02619                      status = dwarf_formref( abstractOriginAttr, & abstractOriginOffset, NULL );
02620                      if (status != DW_DLV_OK) goto error;
02621 
02622                      dwarf_dealloc( dbg, abstractOriginAttr, DW_DLA_ATTR );
02623 
02624                      if ( abstractOriginOffset == dieOffset ) 
02625                      {
02626                         Dwarf_Addr lowPC;
02627                         status = dwarf_lowpc( siblingDie, & lowPC, NULL );
02628                         if (status != DW_DLV_OK) goto error;
02629 
02630                         // bperr( "Found function with pretty name '%s' inlined-not-declared at 0x%lx in module '%s'\n", dieName, (unsigned long)lowPC, useModuleName.c_str() );
02631 
02632                         if ( symsByOffset_.find((Address)lowPC) != 
02633                              symsByOffset_.end()) {
02634                            foundSymbols = symsByOffset_[(Address)lowPC];
02635                         }
02636 
02637                         dwarf_dealloc( dbg, siblingDie, DW_DLA_DIE );
02638                         break;
02639 
02640                      } /* end if we've found _the_ concrete instance */
02641                   } /* end if we've found a concrete instance */
02642 
02643                   first = false;
02644 
02645                } /* end iteration. */
02646             } /* end if we're trying to do a by-address look up. */
02647 
02648             if (foundSymbols.size()) {
02649                /* If it's not specified, is an inlined function in the same
02650                   CU/namespace as its use. */
02651                 
02652                if ( isDeclaredNotInlined && nameEntry != dieEntry ) {
02653                   /* Then the function's definition is where it was
02654                      declared, not wherever it happens to be referenced.
02655                        
02656                      Use the decl_file as the useModuleName, if available. */
02657                     
02658                   Dwarf_Attribute fileNoAttribute;
02659                   status = dwarf_attr( declEntry, DW_AT_decl_file, & fileNoAttribute, NULL );
02660                   if (status == DW_DLV_ERROR) goto error;
02661 
02662                     
02663                   if ( status == DW_DLV_OK ) {
02664                      Dwarf_Unsigned fileNo;
02665                      status = dwarf_formudata( fileNoAttribute, & fileNo, NULL );
02666                      if (status != DW_DLV_OK) goto error;
02667                         
02668                      dwarf_dealloc( dbg, fileNoAttribute, DW_DLA_ATTR );
02669                         
02670                      useModuleName = declFileNoToName[ fileNo - 1 ];
02671 
02672                      //create_printf("%s[%d]: Assuming declared-not-inlined function '%s' to be in module '%s'.\n", FILE__, __LINE__, dieName, useModuleName.c_str());
02673                         
02674                   } /* end if we have declaration file listed */
02675                   else {
02676                      /* This should never happen, but there's not much
02677                         we can do if it does. */
02678                   }
02679                } /* end if isDeclaredNotInlined */
02680                 
02681                if (foundSymbols.size() == 1) {
02682                   symsToModules_[foundSymbols[0]] = useModuleName;
02683                }
02684                else {
02685                   for ( unsigned int i = 0; i < foundSymbols.size(); i++ ) {
02686                      if ( foundSymbols[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
02687                         symsToModules_[foundSymbols[i]] = useModuleName;
02688                      }
02689                   }
02690                }
02691             } /* end if we found the name in the global symbols */
02692             else if ( !isAbstractOrigin &&
02693                       (symbols_.find(dieName) != symbols_.end())) {
02694                std::vector< Symbol *> & syms = symbols_[ dieName ];
02695 
02696                /* If there's only one, apply regardless. */
02697 
02698                if ( syms.size() == 1 ) {
02699                   symsToModules_[syms[0]] = useModuleName;
02700                }
02701                else {
02702                   for ( unsigned int i = 0; i < syms.size(); i++ ) {
02703                      if ( syms[ i ]->getLinkage() == Symbol::SL_LOCAL ) {
02704                         symsToModules_[syms[i]] = useModuleName;
02705                      }
02706                   }
02707                }
02708             } /* end if we think it's a local symbol */
02709             dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02710          } 
02711 
02712          break;
02713 
02714       case DW_TAG_variable:
02715       case DW_TAG_constant: 
02716          {
02717             /* Is this a declaration? */
02718 
02719             Dwarf_Attribute declAttr;
02720             status = dwarf_attr( dieEntry, DW_AT_declaration, & declAttr, NULL );
02721             if (status == DW_DLV_ERROR) goto error;
02722 
02723             if ( status != DW_DLV_OK ) 
02724             { 
02725                break; 
02726             }
02727 
02728             dwarf_dealloc( dbg, declAttr, DW_DLA_ATTR );
02729 
02730             /* If a DIE has a specification, the specification has its name
02731                and (optional) linkage name.  */
02732 
02733             Dwarf_Attribute specificationAttribute;
02734             status = dwarf_attr(dieEntry, DW_AT_specification, &specificationAttribute, NULL);
02735             if (status == DW_DLV_ERROR) goto error;
02736 
02737             Dwarf_Die nameEntry = dieEntry;
02738 
02739             if ( status == DW_DLV_OK ) 
02740             {
02741                Dwarf_Off specificationOffset;
02742                status = dwarf_global_formref(specificationAttribute, &specificationOffset, NULL);
02743                if (status != DW_DLV_OK) goto error;
02744 
02745                dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
02746 
02747                status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
02748                if (status != DW_DLV_OK) goto error;
02749 
02750             } /* end if the DIE has a specification. */
02751 
02752             /* What's its name? */
02753 
02754             char * dieName = NULL;
02755             status = dwarf_diename( nameEntry, & dieName, NULL );
02756             if (status == DW_DLV_ERROR) goto error;
02757 
02758             /* Prefer the linkage (symbol table) name. */
02759 
02760             Dwarf_Attribute linkageNameAttribute;
02761             status = dwarf_attr(nameEntry, DW_AT_MIPS_linkage_name, &linkageNameAttribute, NULL);
02762             if (status == DW_DLV_ERROR) goto error;
02763 
02764             if ( status == DW_DLV_OK ) 
02765             {
02766                dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02767                status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
02768                if (status != DW_DLV_OK) goto error;
02769             }
02770 
02771             /* Anonymous variables are useless to us. */
02772             if ( dieName == NULL ) 
02773             {
02774                break; 
02775             }
02776 
02777             /* Update the module information. */
02778 
02779             string symName = find_symbol(dieName);
02780 
02781             if ( symName != "" ) 
02782             {
02783                assert(symbols_.find(symName)!=symbols_.end());
02784 
02785                /* We're assuming global variables. */
02786                std::vector< Symbol *> & syms = symbols_[ symName ];
02787 
02788                /* If there's only one of symbol of that name, set it regardless. */
02789                if ( syms.size() == 1 ) {
02790                   symsToModules_[syms[0]] = useModuleName; 
02791                }
02792                else {
02793                   for ( unsigned int i = 0; i < syms.size(); i++ ) {
02794                      if ( syms[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
02795                         symsToModules_[syms[i]] = useModuleName;
02796                      }
02797                   }
02798                }
02799             }
02800 
02801             // /* DEBUG */ fprintf( stderr, "%s[%d]: DWARF-derived module %s for symbols of name '%s'\n", __FILE__, __LINE__, useModuleName.c_str(), symName.c_str() );
02802 
02803             dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02804 
02805          } 
02806 
02807          break;
02808 
02809       default:
02810          /* If it's not a function or a variable, ignore it. */
02811          break;
02812    } /* end tag switch */
02813 
02814    /* Recurse to its child, if any. */
02815 
02816    Dwarf_Die childDwarf;
02817    status = dwarf_child( dieEntry, & childDwarf, NULL );
02818    if (status == DW_DLV_ERROR) goto error;
02819 
02820    if ( status == DW_DLV_OK )  {
02821       fixSymbolsInModule(dbg, moduleName, childDwarf); 
02822    }
02823 
02824    /* Recurse to its sibling, if any. */
02825 
02826    Dwarf_Die siblingDwarf;
02827    status = dwarf_siblingof( dbg, dieEntry, & siblingDwarf, NULL );
02828    if (status == DW_DLV_ERROR) goto error;
02829 
02830    if ( status == DW_DLV_OK ) 
02831    {
02832       dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02833 
02834       /* Force tail-recursion to avoid stack overflows. */
02835       dieEntry = siblingDwarf;
02836       goto start;
02837    }
02838    else
02839    {
02840        dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02841        return true;
02842    }
02843  error:
02844  dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02845  return false;
02846 } /* end fixSymbolsInModule */
02847 
02848 
02849 unsigned Object::fixSymbolsInModuleByRange(IntervalTree<Dwarf_Addr, std::string> &modules) 
02850 {
02851    if (modules.empty()) return 0;
02852 
02853    unsigned nsyms_altered = 0;
02854    
02855    for (dyn_hash_map<Offset, std::vector<Symbol *> >::iterator iter = symsByOffset_.begin();
02856         iter != symsByOffset_.end();
02857         iter++) {
02858       Offset off = iter->first;
02859       std::vector<Symbol *> &syms = iter->second;       
02860       
02861       std::string modname;
02862       if (modules.find((Dwarf_Addr) off, modname)) {
02863          for (unsigned i = 0; i < syms.size(); i++) {
02864             symsToModules_[syms[i]] = modname;
02865             nsyms_altered++;
02866          }
02867       }
02868    }
02869 
02870    return nsyms_altered;
02871 }
02872 
02873 bool Object::fix_global_symbol_modules_static_dwarf()
02874 { 
02875    int status;
02876    /* Initialize libdwarf. */
02877    Dwarf_Debug *dbg_ptr = dwarf->type_dbg();
02878    if (!dbg_ptr)
02879       return false;
02880 
02881    Dwarf_Debug &dbg = *dbg_ptr;
02882 
02883    Dwarf_Unsigned hdr;
02884 
02885    IntervalTree<Dwarf_Addr, std::string> module_ranges;
02886 
02887    /* Iterate over the CU headers. */
02888    while ( dwarf_next_cu_header_c( dbg, 1, 
02889                    NULL, NULL, NULL, // len, stamp, abbrev
02890                    NULL, NULL, NULL, // address, offset, extension
02891                    NULL, NULL, // signature, typeoffset
02892                    & hdr, NULL ) == DW_DLV_OK ) 
02893    {
02894       /* Obtain the module DIE. */
02895       Dwarf_Die moduleDIE;
02896       status = dwarf_siblingof( dbg, NULL, & moduleDIE, NULL );
02897       if (status != DW_DLV_OK) goto error;
02898 
02899       /* Make sure we've got the right one. */
02900       Dwarf_Half moduleTag;
02901       status = dwarf_tag( moduleDIE, & moduleTag, NULL);
02902       if (status != DW_DLV_OK) goto error;
02903       if (moduleTag != DW_TAG_compile_unit) goto error;
02904 
02905       /* Extract the name of this module. */
02906       char * dwarfModuleName = NULL;
02907       status = dwarf_diename( moduleDIE, & dwarfModuleName, NULL );
02908       if (status == DW_DLV_ERROR) goto error;
02909 
02910       string moduleName;
02911 
02912       if ( status == DW_DLV_NO_ENTRY || dwarfModuleName == NULL ) 
02913       {
02914          moduleName = string( "{ANONYMOUS}" );
02915       }
02916       else 
02917       {
02918          moduleName = extract_pathname_tail( string(dwarfModuleName) );
02919       }
02920 
02921       Dwarf_Addr modLowPC = 0;
02922       Dwarf_Addr modHighPC = (Dwarf_Addr)(-1);
02923       Dwarf_Bool hasLowPC = false;
02924       Dwarf_Bool hasHighPC = false;
02925 
02926       if (dwarf_hasattr(moduleDIE, DW_AT_low_pc, &hasLowPC, NULL) != DW_DLV_OK) {
02927          hasLowPC = false;
02928       }
02929       if (dwarf_hasattr(moduleDIE, DW_AT_high_pc, &hasHighPC, NULL) != DW_DLV_OK) {
02930          hasHighPC = false;
02931       }
02932       if (hasLowPC && hasHighPC) {
02933          // Get PC boundaries for the module, if present
02934          status = dwarf_lowpc(moduleDIE, &modLowPC, NULL);
02935          if (status != DW_DLV_OK) goto error;
02936 
02937          status = dwarf_highpc(moduleDIE, &modHighPC, NULL);
02938          if (status != DW_DLV_OK) goto error;
02939 
02940          if (modHighPC == 0) 
02941          {
02942             modHighPC = (Dwarf_Addr)(-1);
02943          }
02944 
02945          // Set module names for all symbols that belong to the range
02946          module_ranges.insert(modLowPC, modHighPC, moduleName);
02947       }
02948       else 
02949       {
02950          /* Acquire declFileNoToName. */
02951          status = dwarf_srcfiles( moduleDIE, & declFileNoToName, & declFileNo, NULL );
02952          if (status == DW_DLV_ERROR) goto error;
02953 
02954          if ( status == DW_DLV_OK ) 
02955          {
02956             /* Walk the tree. */
02957 
02958             //fprintf(stderr, "%s[%d]:  about to fixSymbolsInModule(%s,...)\n",
02959             //     FILE__, __LINE__, moduleName.c_str());
02960 
02961             bool result = fixSymbolsInModule(dbg, moduleName, moduleDIE);
02962             if (!result) goto error;
02963              
02964             /* Deallocate declFileNoToName. */
02965              
02966             for ( Dwarf_Signed i = 0; i < declFileNo; i++ ) {                
02967                dwarf_dealloc( dbg, declFileNoToName[i], DW_DLA_STRING );
02968             }
02969 
02970             dwarf_dealloc( dbg, declFileNoToName, DW_DLA_LIST );    
02971 
02972          } /* end if the srcfile information was available */
02973       } /* end if code range information unavailable */
02974 
02975       modules_.push_back(std::pair<std::string, Offset>(moduleName, modLowPC));
02976    } /* end scan over CU headers. */
02977 
02978    if (!module_ranges.empty()) {
02979       fixSymbolsInModuleByRange(module_ranges);
02980    }
02981 
02982    return true;
02983  error:
02984    return false;
02985 }
02986 
02987 #else
02988 
02989 // dummy definition for non-DWARF platforms
02990 bool Object::fix_global_symbol_modules_static_dwarf()
02991 { return false; }
02992 
02993 #endif // USES_DWARF_DEBUG
02994 
02995 /********************************************************
02996  *
02997  * For object files only....
02998  *  read the .stab section to find the module of global symbols
02999  *
03000  ********************************************************/
03001 
03002 bool Object::fix_global_symbol_modules_static_stab(Elf_X_Shdr* stabscnp, Elf_X_Shdr* stabstrscnp) 
03003 {
03004   // Read the stab section to find the module of global symbols.
03005   // The symbols appear in the stab section by module. A module begins
03006   // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
03007   // All the symbols in between those two symbols belong to the module.
03008 
03009   if (!stabscnp || !stabstrscnp) return false;
03010 
03011   Elf_X_Data stabdata = stabscnp->get_data();
03012   Elf_X_Data stabstrdata = stabstrscnp->get_data();
03013   stab_entry *stabptr = NULL;
03014 
03015   if (!stabdata.isValid() || !stabstrdata.isValid()) return false;
03016 
03017   switch (addressWidth_nbytes) 
03018     {
03019     case 4:
03020       stabptr = new stab_entry_32(stabdata.d_buf(),
03021                   stabstrdata.get_string(),
03022                   stabscnp->sh_size() / sizeof(stab32));
03023       break;
03024 
03025     case 8:
03026       stabptr = new stab_entry_64(stabdata.d_buf(),
03027                   stabstrdata.get_string(),
03028                   stabscnp->sh_size() / sizeof(stab64));
03029       break;
03030     };
03031 
03032   const char *next_stabstr = stabptr->getStringBase();
03033   string module = "DEFAULT_MODULE";
03034 
03035   // the stabstr contains one string table for each module.
03036   // stabstr_offset gives the offset from the begining of stabstr of the
03037   // string table for the current module.
03038 
03039   bool is_fortran = false;  // is the current module fortran code?
03040 
03041   for (unsigned i = 0; i < stabptr->count(); i++) 
03042     {
03043       switch(stabptr->type(i)) 
03044     {
03045     case N_UNDF: /* start of object file */
03046       stabptr->setStringBase(next_stabstr);
03047       next_stabstr = stabptr->getStringBase() + stabptr->val(i);
03048       break;
03049 
03050     case N_ENDM: /* end of object file */
03051       is_fortran = false;
03052       module = "DEFAULT_MODULE";
03053       break;
03054 
03055     case N_SO: /* compilation source or file name */
03056       if ((stabptr->desc(i) == N_SO_FORTRAN) || (stabptr->desc(i) == N_SO_F90))
03057         is_fortran = true;
03058 
03059       module = string(stabptr->name(i));
03060       break;
03061 
03062     case N_ENTRY: /* fortran alternate subroutine entry point */
03063     case N_GSYM: /* global symbol */
03064       // the name string of a function or object appears in the stab 
03065       // string table as <symbol name>:<symbol descriptor><other stuff>
03066       // where <symbol descriptor> is a one char code.
03067       // we must extract the name and descriptor from the string
03068       {
03069         const char *p = stabptr->name(i);
03070         // bperr("got %d type, str = %s\n", stabptr->type(i), p);
03071         // if (stabptr->type(i) == N_FUN && strlen(p) == 0) {
03072 
03073         if (strlen(p) == 0) 
03074           {
03075         // GNU CC 2.8 and higher associate a null-named function
03076         // entry with the end of a function.  Just skip it.
03077         break;
03078           }
03079 
03080         const char *q = strchr(p,':');
03081         unsigned len;
03082 
03083         if (q) 
03084           {
03085         len = q - p;
03086           } 
03087         else 
03088           {
03089         len = strlen(p);
03090           }
03091 
03092         if (len == 0)
03093           {
03094         // symbol name is empty.Skip it.- 02/12/07 -Giri
03095         break;
03096           }     
03097 
03098         char *sname = new char[len+1];
03099         strncpy(sname, p, len);
03100         sname[len] = 0;
03101 
03102         string SymName = string(sname);
03103 
03104         // q points to the ':' in the name string, so 
03105         // q[1] is the symbol descriptor. We must check the symbol descriptor
03106         // here to skip things we are not interested in, such as prototypes.
03107 
03108         bool res = (symbols_.find(SymName)!=symbols_.end());
03109 
03110         if (!res && is_fortran) 
03111           {
03112         // Fortran symbols usually appear with an '_' appended in .symtab,
03113         // but not on .stab
03114         SymName += "_";
03115         res = (symbols_.find(SymName)!=symbols_.end());
03116           }
03117 
03118         if (res && (q == 0 || q[1] != SD_PROTOTYPE)) 
03119           {
03120         unsigned int count = 0;
03121         std::vector< Symbol *> & syms = symbols_[SymName];
03122 
03123         /* If there's only one, apply regardless. */
03124         if ( syms.size() == 1 ) 
03125                   { 
03126                      // TODO: set module
03127 //          symbols_[SymName][0]->setModuleName(module); 
03128                   }
03129         else 
03130                   {
03131             for ( unsigned int i = 0; i < syms.size(); i++ ) 
03132               {
03133                         if ( syms[i]->getLinkage() == Symbol::SL_GLOBAL ) 
03134               {
03135                              // TODO: set module
03136 //              symbols_[SymName][i]->setModuleName(module);
03137                 count++;
03138               }
03139               }
03140           }
03141           }
03142         break;
03143       }
03144     case N_FUN: 
03145       /* function */ 
03146       {
03147         const char *p = stabptr->name(i);
03148 
03149         if (strlen(p) == 0) 
03150           {
03151         // Rumours are that GNU CC 2.8 and higher associate a
03152         // null-named function entry with the end of a
03153         // function. Just skip it.
03154         break;
03155           }
03156 
03157         const char *q = strchr(p,':');
03158 
03159         if (q == 0) 
03160           {
03161         // bperr( "Unrecognized stab format: %s\n", p);
03162         // Happens with the Solaris native compiler (.xstabs entries?)
03163         break;
03164           }
03165 
03166         if (q[1] == SD_PROTOTYPE) 
03167           {
03168         // We see a prototype, skip it
03169         break;
03170           }
03171 
03172         unsigned long entryAddr = stabptr->val(i);
03173 
03174         if (entryAddr == 0) 
03175           {
03176         // The function stab doesn't contain a function address
03177         // (happens with the Solaris native compiler). We have to
03178         // look up the symbol by its name. That's unfortunate, since
03179         // names may not be unique and we may end up assigning a wrong
03180         // module name to the symbol.
03181         unsigned len = q - p;
03182         if (len == 0)
03183                   {
03184             // symbol name is empty.Skip it.- 02/12/07 -Giri
03185             break;
03186                   }     
03187 
03188         char *sname = new char[len+1];
03189         strncpy(sname, p, len);
03190         sname[len] = 0;
03191         string nameFromStab = string(sname);
03192         delete[] sname;
03193 
03194         for (unsigned i = 0; i < symbols_[nameFromStab].size(); i++) {
03195           symsToModules_[symbols_[nameFromStab][i]] = module;
03196         }
03197           }
03198         else 
03199           {
03200         if (symsByOffset_.find(entryAddr)==symsByOffset_.end()) {
03201           //bperr( "fix_global_symbol_modules_static_stab "
03202           //       "can't find address 0x%lx of STABS entry %s\n", entryAddr, p);
03203           break;
03204         }
03205         for (unsigned i = 0; i < symsByOffset_[entryAddr].size(); i++) {
03206           symsToModules_[symsByOffset_[entryAddr][i]] = module;
03207         }
03208       }
03209         break;
03210       }
03211 
03212     default:
03213       /* ignore other entries */
03214       break;
03215     }
03216     }
03217 
03218   delete stabptr;
03219 
03220   return true;
03221 }
03222 
03223 
03224 // find_code_and_data(): populates the following members:
03225 //   code_ptr_, code_off_, code_len_
03226 //   data_ptr_, data_off_, data_len_
03227 void Object::find_code_and_data(Elf_X &elf,
03228                 Offset txtaddr, 
03229                 Offset dataddr) 
03230 {
03231     /* Note:
03232      * .o's don't have program headers, so these fields are populated earlier
03233      * when the sections are processed -> see loaded_elf()
03234      */
03235 
03236     for (int i = 0; i < elf.e_phnum(); ++i) {
03237         Elf_X_Phdr &phdr = elf.get_phdr(i);
03238 
03239         char *file_ptr = (char *)mf->base_addr();
03240 
03241         if(!isRegionPresent(phdr.p_paddr(), phdr.p_filesz(), phdr.p_flags())) {
03242             Region *reg = new Region(i, "", phdr.p_paddr(), phdr.p_filesz(),
03243                                      phdr.p_vaddr(), phdr.p_memsz(),
03244                                      &file_ptr[phdr.p_offset()],
03245                                      getSegmentPerms(phdr.p_flags()),
03246                                      getSegmentType(phdr.p_type(), phdr.p_flags()));
03247             reg->setFileOffset(phdr.p_offset());
03248             regions_.push_back(reg);
03249         }
03250 
03251         // The code pointer, offset, & length should be set even if
03252         // txtaddr=0, so in this case we set these values by
03253         // identifying the segment that contains the entryAddress
03254         if (((phdr.p_vaddr() <= txtaddr) && 
03255              (phdr.p_vaddr() + phdr.p_filesz() >= txtaddr)) || 
03256             (!txtaddr && ((phdr.p_vaddr() <= entryAddress_) &&
03257                           (phdr.p_vaddr() + phdr.p_filesz() >= entryAddress_)))) {
03258 
03259             if (code_ptr_ == 0 && code_off_ == 0 && code_len_ == 0) {
03260                 code_ptr_ = (char *)(void*)&file_ptr[phdr.p_offset()];
03261                 code_off_ = (Offset)phdr.p_vaddr();
03262                 code_len_ = (unsigned)phdr.p_filesz();
03263             }
03264 
03265         } else if (((phdr.p_vaddr() <= dataddr) && 
03266                     (phdr.p_vaddr() + phdr.p_filesz() >= dataddr)) || 
03267                    (!dataddr && (phdr.p_type() == PT_LOAD))) {
03268             if (data_ptr_ == 0 && data_off_ == 0 && data_len_ == 0) {
03269                 data_ptr_ = (char *)(void *)&file_ptr[phdr.p_offset()];
03270                 data_off_ = (Offset)phdr.p_vaddr();
03271                 data_len_ = (unsigned)phdr.p_filesz();
03272             }
03273         }
03274     }
03275     //if (addressWidth_nbytes == 8) bperr( ">>> 64-bit find_code_and_data() successful\n");
03276 }
03277 
03278 const char *Object::elf_vaddr_to_ptr(Offset vaddr) const
03279 {
03280   const char *ret = NULL;
03281   unsigned code_size_ = code_len_;
03282   unsigned data_size_ = data_len_;
03283 
03284 #if defined(os_irix)
03285   vaddr -= base_addr;
03286 #endif
03287 
03288   if (vaddr >= code_off_ && vaddr < code_off_ + code_size_) {
03289     ret = ((char *)code_ptr_) + (vaddr - code_off_);
03290   } else if (vaddr >= data_off_ && vaddr < data_off_ + data_size_) {
03291     ret = ((char *)data_ptr_) + (vaddr - data_off_);
03292   } 
03293 
03294   return ret;
03295 }
03296 
03297 stab_entry *Object::get_stab_info() const
03298 {
03299   char *file_ptr = (char *)mf->base_addr();
03300 
03301   // check that file has .stab info
03302   if (stab_off_ && stab_size_ && stabstr_off_) {
03303     switch (addressWidth_nbytes) {
03304     case 4: // 32-bit object
03305       return new stab_entry_32(file_ptr + stab_off_,
03306                    file_ptr + stabstr_off_,
03307                    stab_size_ / sizeof(stab32));
03308       break;
03309     case 8: // 64-bit object
03310       return new stab_entry_64(file_ptr + stab_off_,
03311                    file_ptr + stabstr_off_,
03312                    stab_size_ / sizeof(stab64));
03313       break;
03314     };
03315   }
03316 
03317   //fprintf(stderr, "%s[%d]:  WARNING:  FIXME, stab_off = %d, stab_size = %d, stabstr_off_ = %d\n", FILE__, __LINE__, stab_off_, stab_size_, stabstr_off_);
03318   return new stab_entry_64();
03319 }
03320 
03321 Object::Object(MappedFile *mf_, bool, void (*err_func)(const char *), 
03322            bool alloc_syms) :
03323   AObject(mf_, err_func), 
03324   hasReldyn_(false),
03325   hasReladyn_(false),
03326   hasRelplt_(false),
03327   hasRelaplt_(false),
03328   relType_(Region::RT_REL),
03329   opd_addr_(0),
03330   opd_size_(0),
03331   dwarf(NULL),
03332   EEL(false),
03333   DbgSectionMapSorted(false)
03334 {
03335 
03336 #if defined(TIMED_PARSE)
03337   struct timeval starttime;
03338   gettimeofday(&starttime, NULL);
03339 #endif
03340   is_aout_ = false;
03341   did_open = false;
03342   interpreter_name_ = NULL;
03343   isStripped = false;
03344 
03345   if(mf->getFD() != -1) {
03346      elfHdr = Elf_X::newElf_X(mf->getFD(), ELF_C_READ, NULL, mf_->pathname());
03347   }
03348   else {
03349      elfHdr = Elf_X::newElf_X((char *)mf->base_addr(), mf->size(), mf_->pathname());
03350   }
03351 
03352   // ELF header: sanity check
03353   //if (!elfHdr->isValid()|| !pdelf_check_ehdr(elfHdr)) 
03354   if (!elfHdr->isValid())  {
03355     log_elferror(err_func_, "ELF header");
03356     has_error = true;
03357     return;
03358   }
03359   else if (!pdelf_check_ehdr(*elfHdr)) {
03360     log_elferror(err_func_, "ELF header failed integrity check");
03361     has_error = true;
03362     return;
03363   }
03364 
03365   dwarf = DwarfHandle::createDwarfHandle(mf_->pathname(), elfHdr);
03366   if( elfHdr->e_type() == ET_DYN )
03367     load_shared_object(alloc_syms);
03368   else if( elfHdr->e_type() == ET_REL || elfHdr->e_type() == ET_EXEC ) {
03369     // Differentiate between an executable and an object file
03370     if( elfHdr->e_phnum() ) is_aout_ = true;
03371     else is_aout_ = false;
03372 
03373     load_object(alloc_syms);
03374   }    
03375   else {
03376     log_perror(err_func_,"Invalid filetype in Elf header");
03377     has_error = true;
03378     return;
03379   }
03380 
03381 #ifdef BINEDIT_DEBUG
03382   print_symbol_map(&symbols_);
03383 #endif
03384 #if defined(TIMED_PARSE)
03385   struct timeval endtime;
03386   gettimeofday(&endtime, NULL);
03387   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
03388   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
03389   unsigned long difftime = lendtime - lstarttime;
03390   double dursecs = difftime/(1000 );
03391   cout << "obj parsing in Object-elf took "<<dursecs <<" msecs" << endl;
03392 #endif
03393 }
03394 
03395 Object::Object(const Object& obj)
03396   : AObject(obj), 
03397     dwarf(NULL),
03398     EEL(false)
03399 {
03400   interpreter_name_ = obj.interpreter_name_;
03401   isStripped = obj.isStripped;
03402   loadAddress_ = obj.loadAddress_;
03403   entryAddress_ = obj.entryAddress_;
03404   relocation_table_ = obj.relocation_table_;
03405   fbt_ = obj.fbt_;
03406   elfHdr = obj.elfHdr;
03407   deps_ = obj.deps_;
03408   DbgSectionMapSorted = obj.DbgSectionMapSorted;
03409   relType_ = obj.relType_;
03410 }
03411 
03412 Object::~Object()
03413 {
03414   unsigned i;
03415   relocation_table_.clear();
03416   fbt_.clear();
03417   for(i=0; i<allRegionHdrs.size();i++) {
03418 #if !defined(os_freebsd)
03419     // This claims a double-delete on FreeBSD
03420     delete allRegionHdrs[i];
03421 #endif
03422   }
03423   allRegionHdrs.clear();
03424   versionMapping.clear();
03425   versionFileNameMapping.clear();
03426   deps_.clear();
03427 }
03428 
03429 void Object::log_elferror(void (*err_func)(const char *), const char* msg) 
03430 {
03431   const char* err = elf_errmsg(elf_errno());
03432   err = err ? err: "(bad elf error)";
03433   string str = string(err)+string(msg);
03434   err_func(str.c_str());
03435 }
03436 
03437 bool Object::get_func_binding_table(std::vector<relocationEntry> &fbt) const 
03438 {
03439 #if !defined(os_vxworks)
03440   if(!plt_addr_ || (!fbt_.size())) return false;
03441 #endif
03442   fbt = fbt_;
03443   return true;
03444 }
03445 
03446 bool Object::get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const 
03447 {
03448   if(!plt_addr_ || (!fbt_.size())) return false;
03449   fbt = &fbt_;
03450   return true;
03451 }
03452 
03453 void Object::getDependencies(std::vector<std::string> &deps){
03454   deps = deps_;
03455 }
03456 
03457 bool Object::addRelocationEntry(relocationEntry &re)
03458 {
03459   relocation_table_.push_back(re);
03460   return true;
03461 }
03462 
03463 #ifdef DEBUG
03464 
03465 // stream-based debug output
03466 const ostream &Object::dump_state_info(ostream &s) 
03467 {
03468   s << "Debugging Information for Object (address) : " << this << endl;
03469 
03470   s << " <<begin debugging info for base object>>" << endl;
03471   AObject::dump_state_info(s);
03472   s << " <<end debuggingo info for base object>>" << endl;
03473 
03474   s << " dynsym_addr_ = " << dynsym_addr_ << endl;
03475   s << " dynstr_addr_ = " << dynstr_addr_ << endl;
03476   s << " got_addr_ = " << got_addr_ << endl;
03477   s << " plt_addr_ = " << plt_addr_ << endl;
03478   s << " plt_size_ = " << plt_size_ << endl;
03479   s << " plt_entry_size_ = " << plt_entry_size_ << endl;
03480   s << " rel_plt_addr_ = " << rel_plt_addr_ << endl; 
03481   s << " rel_plt_size_ = " << rel_plt_size_ << endl;
03482   s << " rel_plt_entry_size_ = " << rel_plt_entry_size_ << endl;
03483   s << " rel_size_ = " << rel_size_ << endl;
03484   s << " rel_entry_size_ = " << rel_entry_size_ << endl;
03485   s << " stab_off_ = " << stab_off_ << endl;
03486   s << " stab_size_ = " << stab_size_ << endl;
03487   s << " stabstr_off_ = " << stabstr_off_ << endl;
03488   s << " dwarvenDebugInfo = " << dwarvenDebugInfo << endl;
03489 
03490   // and dump the relocation table....
03491   s << " fbt_ = (field seperator :: )" << endl;   
03492   for (unsigned i=0; i < fbt_.size(); i++) {
03493     s << fbt_[i] << " :: "; 
03494   }
03495   s << endl;
03496 
03497   return s;
03498 } 
03499 
03500 #endif
03501 
03502 
03503 Offset Object::getPltSlot(string funcName) const
03504 {
03505   relocationEntry re;
03506   Offset offset=0;
03507 
03508   for ( unsigned int i = 0; i < fbt_.size(); i++ ){
03509     if (funcName == fbt_[i].name() ){
03510       offset =  fbt_[i].rel_addr();
03511     }
03512   }
03513 
03514   return offset;    
03515 }
03516 
03517 //
03518 // get_valid_memory_areas - get ranges of code/data segments that have
03519 //                       sections mapped to them
03520 //
03521 
03522 void Object::get_valid_memory_areas(Elf_X &elf)
03523 {
03524   for (unsigned i = 0; i < elf.e_shnum(); ++i) {
03525     Elf_X_Shdr &shdr = elf.get_shdr(i);
03526     if ( !shdr.isValid()) { 
03527       break; 
03528     }
03529     if (shdr.sh_flags() & SHF_ALLOC) { // This section is in memory
03530       if (code_off_ <= shdr.sh_addr() &&
03531       shdr.sh_addr() <= code_off_ + code_len_) {
03532     if (shdr.sh_addr() < code_vldS_)
03533       code_vldS_ = shdr.sh_addr();
03534     if (shdr.sh_addr() + shdr.sh_size() > code_vldE_)
03535       code_vldE_ = shdr.sh_addr() + shdr.sh_size();
03536 
03537       } else if (data_off_ <= shdr.sh_addr() &&
03538          shdr.sh_addr() <= data_off_ + data_len_) {
03539     if (shdr.sh_addr() < data_vldS_)
03540       data_vldS_ = shdr.sh_addr();
03541     if (shdr.sh_addr() + shdr.sh_size() > data_vldE_)
03542       data_vldE_ = shdr.sh_addr() + shdr.sh_size();
03543       }
03544     }
03545   }
03546 }
03547 
03548 //
03549 // parseCompilerType - parse for compiler that was used to generate object
03550 //
03551 //
03552 //
03553 #if defined(os_linux)
03554 // Differentiating between g++ and pgCC by stabs info (as in the solaris/
03555 // aix case, below) will not work; the gcc-compiled object files that
03556 // get included at link time will fill in the N_OPT stabs line. Instead,
03557 // look for "pgCC_compiled." symbols.
03558 bool parseCompilerType(Object *objPtr)
03559 {
03560   dyn_hash_map<string, std::vector<Symbol *> >*syms = objPtr->getAllSymbols();  
03561   if(syms->find("pgCC_compiled.") != syms->end())
03562     return true;
03563   return false; 
03564 } 
03565 #else
03566 bool parseCompilerType(Object *objPtr) 
03567 {
03568   stab_entry *stabptr = objPtr->get_stab_info();
03569   const char *next_stabstr = stabptr->getStringBase();
03570 
03571   for (unsigned int i=0; i < stabptr->count(); ++i) {
03572     // if (stabstrs) bperr("parsing #%d, %s\n", stabptr->type(i), stabptr->name(i));
03573     switch (stabptr->type(i)) {
03574 
03575     case N_UNDF: /* start of object file */
03576       /* value contains offset of the next string table for next module */
03577       // assert(stabptr.nameIdx(i) == 1);
03578       stabptr->setStringBase(next_stabstr);
03579       next_stabstr = stabptr->getStringBase() + stabptr->val(i);
03580       break;
03581 
03582     case N_OPT: /* Compiler options */
03583       delete stabptr;
03584       return false;
03585     }
03586   }
03587   delete stabptr;
03588   return false; // Shouldn't happen - maybe N_OPT stripped
03589 }
03590 #endif
03591 
03592 
03593 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
03594 
03595 static unsigned long read_uleb128(const unsigned char *data, unsigned *bytes_read)
03596 {
03597   unsigned long result = 0;
03598   unsigned shift = 0;
03599   *bytes_read = 0;
03600   while (1)
03601     {
03602       result |= (data[*bytes_read] & 0x7f) << shift;
03603       if ((data[(*bytes_read)++] & 0x80) == 0)
03604     break;
03605       shift += 7;
03606     }
03607   return result;
03608 }
03609 
03610 static signed long read_sleb128(const unsigned char *data, unsigned *bytes_read)
03611 {
03612   unsigned long result = 0;
03613   unsigned shift = 0;
03614   *bytes_read = 0;
03615   while (1)
03616     {
03617       result |= (data[*bytes_read] & 0x7f) << shift;
03618       shift += 7;
03619       if ((data[*bytes_read] & 0x80) == 0)
03620     break;
03621       (*bytes_read)++;
03622     }
03623   if (shift < sizeof(int) && (data[*bytes_read] & 0x40))
03624     result |= -(1 << shift);
03625   (*bytes_read)++;
03626   return result;
03627 }
03628 
03629 #define DW_EH_PE_absptr  0x00
03630 #define DW_EH_PE_uleb128 0x01
03631 #define DW_EH_PE_udata2  0x02
03632 #define DW_EH_PE_udata4  0x03
03633 #define DW_EH_PE_udata8  0x04
03634 #define DW_EH_PE_sleb128 0x09
03635 #define DW_EH_PE_sdata2  0x0A
03636 #define DW_EH_PE_sdata4  0x0B
03637 #define DW_EH_PE_sdata8  0x0C
03638 #define DW_EH_PE_pcrel   0x10
03639 #define DW_EH_PE_textrel 0x20
03640 #define DW_EH_PE_datarel 0x30
03641 #define DW_EH_PE_funcrel 0x40
03642 #define DW_EH_PE_aligned 0x50
03643 #define DW_EH_PE_omit    0xff
03644 
03645 typedef struct {
03646   int word_size;
03647   unsigned long pc;
03648   unsigned long text;
03649   unsigned long data;
03650   unsigned long func;
03651 } mach_relative_info;
03652 
03653 static int read_val_of_type(int type, unsigned long *value, const unsigned char *addr,
03654                 const mach_relative_info &mi)
03655 {
03656   unsigned size = 0;
03657   if (type == DW_EH_PE_omit)
03658     return 0;
03659 
03660   unsigned long base = 0x0;
03661   /**
03662    * LSB Standard says that the upper four bits (0xf0) encode the base.
03663    * Except that none of these values should their upper bits set,
03664    * and I'm finding the upper bit seems to sometimes contain garbage.
03665    * gcc uses the 0x70 bits in its exception parsing, so that's what we'll do.
03666    **/
03667   switch (type & 0x70)
03668     {
03669     case DW_EH_PE_pcrel:
03670       base = mi.pc;
03671       break;
03672     case DW_EH_PE_textrel:
03673       base = mi.text;
03674       break;
03675     case DW_EH_PE_datarel:
03676       base = mi.data;
03677       break;
03678     case DW_EH_PE_funcrel:
03679       base = mi.func;
03680       break;
03681     }
03682 
03683   switch (type & 0x0f)
03684     {
03685     case DW_EH_PE_absptr:
03686       if (mi.word_size == 4) {
03687     *value = (unsigned long) *((const uint32_t *) addr);
03688     size = 4;
03689       }
03690       else if (mi.word_size == 8) {
03691     *value = (unsigned long) *((const uint64_t *) addr);
03692     size = 8;
03693       }
03694       break;
03695     case DW_EH_PE_uleb128:
03696       *value = base + read_uleb128(addr, &size);
03697       break;
03698     case DW_EH_PE_sleb128:
03699       *value = base + read_sleb128(addr, &size);
03700       break;
03701     case DW_EH_PE_udata2:
03702       *value = base + *((const uint16_t *) addr);
03703       size = 2;
03704       break;
03705     case DW_EH_PE_sdata2:         
03706       *value = base + *((const int16_t *) addr);
03707       size = 2;
03708       break;
03709     case DW_EH_PE_udata4:
03710       *value = base + *((const uint32_t *) addr);
03711       size = 4;
03712       break;
03713     case DW_EH_PE_sdata4:
03714       *value = base + *((const int32_t *) addr);
03715       size = 4;
03716       break;
03717     case DW_EH_PE_udata8:
03718       *value = base + *((const uint64_t *) addr);
03719       size = 8;
03720       break;
03721     case DW_EH_PE_sdata8:
03722       *value = base + *((const int64_t *) addr);
03723       size = 8;
03724       break;
03725     default:
03726       return -1;
03727     }
03728 
03729   if ((type & 0x70) == DW_EH_PE_aligned)
03730     {
03731       if (mi.word_size == 4) {
03732     *value &= ~(0x3l);
03733       }
03734       else if (mi.word_size == 8) {
03735     *value &= ~(0x7l);
03736       }
03737     }
03738 
03739   return size;
03740 }
03741 
03742 /**
03743  * On GCC 3.x/x86 we find catch blocks as follows:
03744  *   1. We start with a list of FDE entries in the .eh_frame
03745  *      table.  
03746  *   2. Each FDE entry has a pointer to a  CIE entry.  The CIE
03747  *      tells us whether the FDE has any 'Augmentations', and
03748  *      the types of those augmentations.  The FDE also
03749  *      contains a pointer to a function.
03750  *   3. If one of the FDE augmentations is a 'Language Specific Data Area' 
03751  *      then we have a pointer to one or more entires in the gcc_except_table.
03752  *   4. The gcc_except_table contains entries that point 
03753  *      to try and catch blocks, all encoded as offsets
03754  *      from the function start (it doesn't tell you which
03755  *      function, however). 
03756  *   5. We can add the function offsets from the gcc_except_table
03757  *      to the function pointer from the FDE to get all of
03758  *      the try/catch blocks.  
03759  **/ 
03760 #define SHORT_FDE_HLEN 4 
03761 #define LONG_FDE_HLEN 12
03762 static 
03763 int read_except_table_gcc3(Dwarf_Fde *fde_data, Dwarf_Signed fde_count,
03764                            mach_relative_info &mi,
03765                            Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
03766                            std::vector<ExceptionBlock> &addresses)
03767 {
03768   Dwarf_Error err = (Dwarf_Error) NULL;
03769   Dwarf_Addr low_pc;
03770   Dwarf_Unsigned bytes_in_cie;
03771   Dwarf_Off fde_offset, cie_offset;
03772   Dwarf_Fde fde;
03773   Dwarf_Cie cie;
03774   int status, result, ptr_size;
03775   char *augmentor;
03776   unsigned char lpstart_format, ttype_format, table_format;
03777   unsigned long value, table_end, region_start, region_size;
03778   unsigned long catch_block, action, augmentor_len;
03779   Dwarf_Small *fde_augdata, *cie_augdata;
03780   Dwarf_Unsigned fde_augdata_len, cie_augdata_len;
03781    
03782   //For each FDE
03783   for (int i = 0; i < fde_count; i++) {
03784     unsigned int j;
03785     unsigned char lsda_encoding = 0xff, personality_encoding = 0xff;
03786     unsigned char *lsda_ptr = NULL;
03787     unsigned char *cur_augdata;
03788     unsigned long except_off;
03789     unsigned long fde_addr, cie_addr;
03790     unsigned char *fde_bytes, *cie_bytes;
03791 
03792     //Get the FDE
03793     status = dwarf_get_fde_n(fde_data, (Dwarf_Unsigned) i, &fde, &err);
03794     if (status != DW_DLV_OK) {
03795       pd_dwarf_handler(err, NULL);
03796       return false;
03797     }
03798 
03799     //After this set of computations we should have:
03800     // low_pc = mi.func = the address of the function that contains this FDE
03801     // fde_bytes = the start of the FDE in our memory space
03802     // cie_bytes = the start of the CIE in our memory space
03803     status = dwarf_get_fde_range(fde, &low_pc, NULL, (void **) &fde_bytes,
03804                  NULL, &cie_offset, NULL, 
03805                  &fde_offset, &err);
03806     if (status != DW_DLV_OK) {
03807       pd_dwarf_handler(err, NULL);
03808       return false;
03809     }
03810     //The LSB strays from the DWARF here, when parsing the except_eh section
03811     // the cie_offset is relative to the FDE rather than the start of the
03812     // except_eh section.
03813     cie_offset = fde_offset - cie_offset +
03814       (*(uint32_t*)fde_bytes == 0xffffffff ? LONG_FDE_HLEN : SHORT_FDE_HLEN);
03815     cie_bytes = (unsigned char *)eh_frame->get_data().d_buf() + cie_offset;
03816 
03817     //Get the CIE for the FDE
03818     status = dwarf_get_cie_of_fde(fde, &cie, &err);
03819     if (status != DW_DLV_OK) {
03820       pd_dwarf_handler(err, NULL);
03821       return false;
03822     }
03823 
03824     //Get the Augmentation string for the CIE
03825     status = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, &augmentor, 
03826                 NULL, NULL, NULL, NULL, NULL, &err); 
03827     if (status != DW_DLV_OK) {
03828       pd_dwarf_handler(err, NULL);
03829       return false;
03830     }
03831       
03832     //Check that the string pointed to by augmentor has a 'L',
03833     // meaning we have a LSDA
03834     augmentor_len = (augmentor == NULL) ? 0 : strlen(augmentor);
03835     for (j = 0; j < augmentor_len; j++) {
03836       if (augmentor[j] == 'L') {
03837     break;
03838       }
03839     }
03840     if (j == augmentor_len)
03841       //If we don't have a language specific data area, then
03842       // we don't care about this FDE.
03843       continue;
03844 
03845     //Some ptr encodings may be of type DW_EH_PE_pcrel, which means
03846     // that they're relative to their own location in the binary.  
03847     // We'll figure out where the FDE and CIE original load addresses
03848     // were and use those in pcrel computations.
03849     fde_addr = eh_frame->sh_addr() + fde_offset;
03850     cie_addr = eh_frame->sh_addr() + cie_offset;
03851       
03852     //Extract encoding information from the CIE.  
03853     // The CIE may have augmentation data, specified in the 
03854     // Linux Standard Base. The augmentation string tells us how
03855     // which augmentation data is present.  We only care about one 
03856     // field, a byte telling how the LSDA pointer is encoded.
03857     status = dwarf_get_cie_augmentation_data(cie, 
03858                          &cie_augdata,
03859                          &cie_augdata_len,
03860                          &err);
03861     if (status != DW_DLV_OK) {
03862       pd_dwarf_handler(err, NULL);
03863       return false;
03864     }
03865 
03866     cur_augdata = (unsigned char *) cie_augdata;
03867     lsda_encoding = DW_EH_PE_omit;
03868     for (j=0; j<augmentor_len; j++)
03869       {
03870     if (augmentor[j] == 'L')
03871       {
03872             lsda_encoding = *cur_augdata;
03873             cur_augdata++;
03874       }
03875     else if (augmentor[j] == 'P')
03876       {
03877             //We don't actually need the personality info, but we extract it 
03878             // anyways to make sure we properly extract the LSDA.
03879             personality_encoding = *cur_augdata;
03880             cur_augdata++;
03881             unsigned long personality_val;
03882             mi.pc = cie_addr + (unsigned long) (cur_augdata - cie_bytes);
03883             cur_augdata += read_val_of_type(personality_encoding, 
03884                                             &personality_val, cur_augdata, mi);
03885       }
03886     else if (augmentor[j] == 'z' || augmentor[j] == 'R')
03887       {
03888             //Do nothing, these don't affect the CIE encoding.
03889       }
03890     else
03891       {
03892             //Fruit, Someone needs to check the Linux Standard Base, 
03893             // section 11.6 (as of v3.1), to see what new encodings 
03894             // exist and how we should decode them in the CIE.
03895             break;
03896       }
03897       }
03898     if (lsda_encoding == DW_EH_PE_omit)
03899       continue;
03900 
03901 
03902     //Read the LSDA pointer out of the FDE.
03903     // The FDE has an augmentation area, similar to the above one in the CIE.
03904     // Where-as the CIE augmentation tends to contain things like bytes describing 
03905     // pointer encodings, the FDE contains the actual pointers.
03906     status = dwarf_get_fde_augmentation_data(fde, 
03907                          &fde_augdata,
03908                          &fde_augdata_len,
03909                          &err);
03910     if (status != DW_DLV_OK) {
03911       pd_dwarf_handler(err, NULL);
03912       return false;
03913     }
03914     cur_augdata = (unsigned char *) fde_augdata;
03915     for (j=0; j<augmentor_len; j++)
03916       {
03917     if (augmentor[j] == 'L')
03918       {
03919             unsigned long lsda_val;
03920             mi.pc = fde_addr + (unsigned long) (cur_augdata - fde_bytes);          
03921             ptr_size = read_val_of_type(lsda_encoding, &lsda_val, cur_augdata, mi);
03922             if (ptr_size == -1)
03923           break;
03924             lsda_ptr = (unsigned char *) lsda_val;
03925             cur_augdata += ptr_size;
03926       }
03927     else if (augmentor[j] == 'P' ||
03928          augmentor[j] == 'z' ||
03929          augmentor[j] == 'R')
03930       {
03931             //These don't affect the FDE augmentation data, do nothing
03932       }
03933     else
03934       {
03935             //See the comment for the 'else' case in the above CIE parsing
03936             break;
03937       }
03938       }
03939     if (!lsda_ptr)
03940       //Many FDE's have an LSDA area, but then have a NULL LSDA ptr.  
03941       // Just means there's no exception info here.
03942       continue;
03943 
03944     // Get the exception data from the section.
03945     Elf_X_Data data = except_scn->get_data();
03946     if (!data.isValid()) {
03947       return false;
03948     }
03949 
03950     const unsigned char *datap = (const unsigned char *) data.get_string();
03951     unsigned long int except_size = data.d_size();
03952 
03953     except_off = (unsigned long) (lsda_ptr - except_scn->sh_addr());
03954     if (except_off >= except_size) {
03955       continue;
03956     }
03957 
03958     // Read some variable length header info that we don't really
03959     // care about.
03960     lpstart_format = datap[except_off++];
03961     if (lpstart_format != DW_EH_PE_omit)
03962       except_off += read_val_of_type(DW_EH_PE_uleb128, &value, datap + except_off, mi);
03963     ttype_format = datap[except_off++];
03964     if (ttype_format != DW_EH_PE_omit)
03965       except_off += read_val_of_type(DW_EH_PE_uleb128, &value, datap + except_off, mi);
03966 
03967     // This 'type' byte describes the data format of the entries in the 
03968     // table and the format of the table_size field.
03969     table_format = datap[except_off++];
03970     mi.pc = except_scn->sh_addr() + except_off;
03971     result = read_val_of_type(table_format, &table_end, datap + except_off, mi);
03972     if (result == -1) {
03973       continue;
03974     }
03975     except_off += result;
03976     table_end += except_off;
03977 
03978     while (except_off < table_end && except_off < except_size) {
03979       //The entries in the gcc_except_table are the following format:
03980       //   <type>   region start
03981       //   <type>   region length
03982       //   <type>   landing pad
03983       //  uleb128   action
03984       //The 'region' is the try block, the 'landing pad' is the catch.
03985       mi.pc = except_scn->sh_addr() + except_off;
03986       except_off += read_val_of_type(table_format, &region_start, 
03987                      datap + except_off, mi);
03988       mi.pc = except_scn->sh_addr() + except_off;
03989       except_off += read_val_of_type(table_format, &region_size, 
03990                      datap + except_off, mi);
03991       mi.pc = except_scn->sh_addr() + except_off;
03992       except_off += read_val_of_type(table_format, &catch_block, 
03993                      datap + except_off, mi);
03994       except_off += read_val_of_type(DW_EH_PE_uleb128, &action, 
03995                      datap + except_off, mi);
03996 
03997       if (catch_block == 0)
03998     continue;
03999       ExceptionBlock eb(region_start + low_pc, (unsigned) region_size, 
04000             catch_block + low_pc);
04001       addresses.push_back(eb);
04002     }
04003   }
04004 
04005   return true;
04006 }
04007 
04008 /**
04009  * Things were much simpler in the old days.  On gcc 2.x
04010  * the gcc_except_table looks like:
04011  *   <long> try_start
04012  *   <long> try_end
04013  *   <long> catch_start
04014  * Where everything is an absolute address, even when compiled
04015  * with PIC.  All we got to do is read the catch_start entries
04016  * out of it.
04017  **/
04018 static bool read_except_table_gcc2(Elf_X_Shdr *except_table, 
04019                                    std::vector<ExceptionBlock> &addresses,
04020                                    const mach_relative_info &mi)
04021 {
04022   Offset try_start;
04023   Offset try_end;
04024   Offset catch_start;
04025 
04026   Elf_X_Data data = except_table->get_data();
04027   const unsigned char *datap = (const unsigned char *)data.get_string();
04028   unsigned long except_size = data.d_size();
04029 
04030   unsigned i = 0;
04031   while (i < except_size) {
04032     if (mi.word_size == 4) {
04033       i += read_val_of_type(DW_EH_PE_udata4, &try_start, datap + i, mi);
04034       i += read_val_of_type(DW_EH_PE_udata4, &try_end, datap + i, mi);
04035       i += read_val_of_type(DW_EH_PE_udata4, &catch_start, datap + i, mi);
04036     }
04037     else if (mi.word_size == 8) {
04038       i += read_val_of_type(DW_EH_PE_udata8, &try_start, datap + i, mi);
04039       i += read_val_of_type(DW_EH_PE_udata8, &try_end, datap + i, mi);
04040       i += read_val_of_type(DW_EH_PE_udata8, &catch_start, datap + i, mi);
04041     }
04042 
04043     if (try_start != (Offset) -1 && try_end != (Offset) -1) {
04044       ExceptionBlock eb(try_start, (unsigned) (try_end - try_start), catch_start);
04045       addresses.push_back(eb);
04046     }
04047   }
04048   return true;
04049 }
04050 
04051 struct  exception_compare: public binary_function<const ExceptionBlock &, const ExceptionBlock &, bool> 
04052 {
04053   bool operator()(const ExceptionBlock &e1, const ExceptionBlock &e2) {
04054     if (e1.tryStart() < e2.tryStart())
04055       return true;
04056     return false;
04057   }
04058 };
04059 
04060 /**
04061  * Finds the addresses of catch blocks in a g++ generated elf file.
04062  *  'except_scn' should point to the .gcc_except_table section
04063  *  'eh_frame' should point to the .eh_frame section
04064  *  the addresses will be pushed into 'addresses'
04065  **/
04066 bool Object::find_catch_blocks(Elf_X_Shdr *eh_frame, 
04067                    Elf_X_Shdr *except_scn, 
04068                    Address txtaddr, Address dataaddr,
04069                    std::vector<ExceptionBlock> &catch_addrs)
04070 {
04071   Dwarf_Cie *cie_data;
04072   Dwarf_Fde *fde_data;
04073   Dwarf_Signed cie_count, fde_count;
04074   Dwarf_Error err = (Dwarf_Error) NULL;
04075   Dwarf_Unsigned bytes_in_cie;
04076   char *augmentor;
04077   int status, gcc_ver = 3;
04078   unsigned i;
04079   bool result = false;
04080 
04081   if (except_scn == NULL) {
04082     //likely to happen if we're not using gcc
04083     return true;
04084   }
04085 
04086   Dwarf_Debug *dbg_ptr = dwarf->frame_dbg();
04087   if (!dbg_ptr) {
04088     pd_dwarf_handler(err, NULL);
04089     return false;
04090   }
04091   Dwarf_Debug &dbg = *dbg_ptr;
04092 
04093   //Read the FDE and CIE information
04094   status = dwarf_get_fde_list_eh(dbg, &cie_data, &cie_count,
04095                  &fde_data, &fde_count, &err);
04096   if (status != DW_DLV_OK) {
04097     //fprintf(stderr, "[%s:%u] - No fde data\n", __FILE__, __LINE__);
04098     //No actual stackwalk info in this object
04099     return false;
04100   }
04101   //fprintf(stderr, "[%s:%u] - Found %d fdes\n", __FILE__, __LINE__, fde_count);
04102 
04103   mach_relative_info mi;
04104   mi.text = txtaddr;
04105   mi.data = dataaddr;
04106   mi.pc = 0x0;
04107   mi.func = 0x0;
04108   mi.word_size = eh_frame->wordSize();
04109 
04110 
04111   //GCC 2.x has "eh" as its augmentor string in the CIEs
04112   for (i = 0; i < cie_count; i++) {
04113     status = dwarf_get_cie_info(cie_data[i], &bytes_in_cie, NULL,
04114                 &augmentor, NULL, NULL, NULL, NULL, NULL, &err);
04115     if (status != DW_DLV_OK) {
04116       pd_dwarf_handler(err, NULL);
04117       goto cleanup;
04118     }
04119     if (augmentor[0] == 'e' && augmentor[1] == 'h') {
04120       gcc_ver = 2;
04121     }
04122   }
04123 
04124   //Parse the gcc_except_table
04125   if (gcc_ver == 2) {
04126     result = read_except_table_gcc2(except_scn, catch_addrs, mi);
04127 
04128   } else if (gcc_ver == 3) {
04129     result = read_except_table_gcc3(fde_data, fde_count, mi,
04130                     eh_frame, except_scn, 
04131                     catch_addrs);
04132   }
04133   sort(catch_addrs.begin(),catch_addrs.end(),exception_compare());
04134   //VECTOR_SORT(catch_addrs, exception_compare);
04135 
04136  cleanup:
04137   //Unallocate fde and cie information 
04138   for (i = 0; i < cie_count; i++)
04139     dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
04140   for (i = 0; i < fde_count; i++)
04141     dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
04142   dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
04143   dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
04144 
04145   return result;
04146 }
04147 
04148 #endif
04149 
04150 ObjectType Object::objType() const 
04151 {
04152   return obj_type_;
04153 }
04154 
04155 void Object::getModuleLanguageInfo(dyn_hash_map<string, supportedLanguages> *mod_langs)
04156 { 
04157   string working_module;
04158   const char *ptr;
04159   // check .stabs section to get language info for modules:
04160   //   int stab_nsyms;
04161   //   char *stabstr_nextoffset;
04162   //   const char *stabstrs = 0;
04163    
04164   string mod_string;
04165 
04166   // This ugly flag is set when certain (sun) fortran compilers are detected.
04167   // If it is set at any point during the following iteration, this routine
04168   // ends with "backtrack mode" and reiterates through all chosen languages, changing
04169   // lang_Fortran to lang_Fortran_with_pretty_debug.
04170   //
04171   // This may be ugly, but it is set up this way since the information that is used
04172   // to determine whether this flag is set comes from the N_OPT field, which 
04173   // seems to come only once per image.  The kludge is that we assume that all
04174   // fortran sources in the module have this property (they probably do, but
04175   // could conceivably be mixed (???)).
04176   int fortran_kludge_flag = 0;
04177     
04178   // "state variables" we use to accumulate potentially useful information
04179   //  A final module<->language decision is not made until we have arrived at the
04180   //  next module entry, at which point we use any and all info we have to 
04181   //  make the most sensible guess
04182   supportedLanguages working_lang = lang_Unknown;
04183   char *working_options = NULL;
04184   const char *working_name = NULL;
04185    
04186   stab_entry *stabptr = NULL;
04187   const char *next_stabstr = NULL;
04188 #if defined(TIMED_PARSE)
04189   struct timeval starttime;
04190   gettimeofday(&starttime, NULL);
04191 #endif
04192    
04193   //Using the Object to get the pointers to the .stab and .stabstr
04194   // XXX - Elf32 specific needs to be in seperate file -- jkh 3/18/99
04195   stabptr = get_stab_info();
04196   next_stabstr = stabptr->getStringBase();
04197    
04198   for( unsigned int i = 0; i < stabptr->count(); i++ ) 
04199     {
04200       if (stabptr->type(i) == N_UNDF)
04201     {/* start of object file */
04202          /* value contains offset of the next string table for next module */
04203          // assert(stabptr->nameIdx(i) == 1);
04204       stabptr->setStringBase(next_stabstr);
04205       next_stabstr = stabptr->getStringBase() + stabptr->val(i); 
04206     }
04207       else if (stabptr->type(i) == N_OPT)
04208     {
04209       //  We can use the compiler option string (in a pinch) to guess at the source file language
04210       //  There is possibly more useful information encoded somewhere around here, but I lack
04211       //  an immediate reference....
04212       if (working_name)
04213             working_options = const_cast<char *>(stabptr->name(i)); 
04214     }
04215       else if ((stabptr->type(i) == N_SO)  || (stabptr->type(i) == N_ENDM))
04216     { /* compilation source or file name */
04217       // We have arrived at the next source file, finish up with the last one and reset state
04218       // before starting next
04219 
04220 
04221       //   XXXXXXXXXXX  This block is mirrored near the end of routine, if you edit it,
04222       //   XXXXXXXXXXX  change it there too.
04223       if  (working_name)
04224         {
04225           working_lang = pickLanguage(working_module, working_options, working_lang);
04226           if (working_lang == lang_Fortran_with_pretty_debug)
04227         fortran_kludge_flag = 1;
04228           (*mod_langs)[working_module] = working_lang;
04229 
04230         }
04231       //   XXXXXXXXXXX
04232     
04233       // reset "state" here
04234       working_lang = lang_Unknown;
04235       working_options = NULL;
04236 
04237       //  Now:  out with the old, in with the new
04238 
04239       if (stabptr->type(i) == N_ENDM)
04240         {
04241           // special case:
04242           // which is most likely both broken (and ignorable ???)
04243           working_name = "DEFAULT_MODULE";
04244         }
04245       else
04246         {
04247           working_name = stabptr->name(i);
04248           ptr = strrchr(working_name, '/');
04249           if (ptr)
04250         {
04251           ptr++;
04252           working_name = ptr;
04253         }
04254         }
04255       working_module = string(working_name);
04256 
04257       if ((mod_langs->find(working_module) != mod_langs->end()) && (*mod_langs)[working_module] != lang_Unknown) 
04258         {
04259           //  we already have a module with this name in the map.  If it has been given
04260           //  a language assignment (not lang_Unknown), we can just skip ahead
04261           working_name = NULL;
04262           working_options = NULL;
04263           continue;
04264         } 
04265       else 
04266         {
04267           //cerr << __FILE__ << __LINE__ << ":  Module: " <<working_module<< " has language "<< stabptr->desc(i) << endl;  
04268           switch (stabptr->desc(i))
04269         {
04270         case N_SO_FORTRAN: 
04271                   working_lang = lang_Fortran;
04272                   break;
04273         case N_SO_F90:
04274                   working_lang = lang_Fortran;  // not sure if this should be different from N_SO_FORTRAN
04275                   break;
04276         case N_SO_AS:
04277                   working_lang = lang_Assembly;
04278                   break;
04279         case N_SO_ANSI_C:
04280         case N_SO_C:
04281                   working_lang = lang_C;
04282                   break;
04283         case N_SO_CC:
04284                   working_lang = lang_CPlusPlus;
04285                   break;
04286         default:
04287                   //  currently uncovered options are lang_CMFortran, and lang_GnuCPlusPlus
04288                   //  do we need to make this kind of distinction here?
04289                   working_lang = lang_Unknown;
04290                   break;
04291         }
04292     
04293         } 
04294     } // end N_SO section
04295     } // for loop
04296 
04297   //  Need to make sure we finish up with the module we were last collecting information 
04298   //  about
04299 
04300   //   XXXXXXXXXXX  see note above (find the X's)
04301   if  (working_name)
04302     {
04303       working_lang = pickLanguage(working_module, working_options, working_lang);     
04304       if (working_lang == lang_Fortran_with_pretty_debug)
04305     fortran_kludge_flag = 1;
04306       (*mod_langs)[working_module] = working_lang;
04307     }
04308   //   XXXXXXXXXXX
04309 
04310   if (fortran_kludge_flag)
04311     {
04312       //  XXX  This code does not appear to be used anymore??  
04313       // go through map and change all lang_Fortran to lang_Fortran_with_pretty_symtab
04314       dyn_hash_map<string, supportedLanguages>::iterator iter = (*mod_langs).begin();
04315       string aname;
04316       supportedLanguages alang;
04317       for(;iter!=(*mod_langs).end();iter++)
04318     {
04319       aname = iter->first;
04320       alang = iter->second;
04321       if(lang_Fortran == alang)
04322         {
04323           (*mod_langs)[aname] = lang_Fortran_with_pretty_debug;
04324           //fprintf(stderr, "%s[%d]:  UPDATE: lang_Fortran->langFortran_with_pretty_debug\n", FILE__, __LINE__);
04325         }
04326     }
04327     }
04328 #if defined(TIMED_PARSE)
04329   struct timeval endtime;
04330   gettimeofday(&endtime, NULL);
04331   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
04332   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
04333   unsigned long difftime = lendtime - lstarttime;
04334   double dursecs = difftime/(1000 );
04335   cout << __FILE__ << ":" << __LINE__ <<": getModuleLanguageInfo took "<<dursecs <<" msecs" << endl;
04336 #endif
04337   delete stabptr;
04338 
04339 #if defined(cap_dwarf)
04340   if (hasDwarfInfo())
04341     {
04342       int status;
04343       Dwarf_Debug *dbg_ptr = dwarf->type_dbg();
04344       if (!dbg_ptr)
04345     return;
04346       Dwarf_Debug &dbg = *dbg_ptr;
04347       
04348       Dwarf_Unsigned hdr;      
04349       char * moduleName = NULL;
04350       Dwarf_Die moduleDIE = NULL;
04351       Dwarf_Attribute languageAttribute = NULL;
04352       bool done = false;
04353 
04354       while( !done && 
04355              dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, & hdr, NULL) == DW_DLV_OK )
04356     {
04357       Dwarf_Half moduleTag;
04358       Dwarf_Unsigned languageConstant;
04359 
04360       status = dwarf_siblingof(dbg, NULL, &moduleDIE, NULL);
04361       if (status != DW_DLV_OK) {
04362             done = true;
04363             goto cleanup_dwarf;
04364       }
04365          
04366       status = dwarf_tag( moduleDIE, & moduleTag, NULL);
04367       if (status != DW_DLV_OK || moduleTag != DW_TAG_compile_unit) {
04368             done = true;
04369             goto cleanup_dwarf;
04370       }
04371          
04372       /* Extract the name of this module. */
04373       status = dwarf_diename( moduleDIE, & moduleName, NULL );
04374       if (status != DW_DLV_OK || !moduleName) {
04375             done = true;
04376             goto cleanup_dwarf;
04377       }
04378       ptr = strrchr(moduleName, '/');
04379       if (ptr)
04380             ptr++;
04381       else
04382             ptr = moduleName;
04383          
04384       working_module = string(ptr);
04385          
04386       status = dwarf_attr( moduleDIE, DW_AT_language, & languageAttribute, NULL );
04387       if (status == DW_DLV_ERROR) {
04388             done = true;
04389             goto cleanup_dwarf;
04390       }
04391             
04392       status = dwarf_formudata( languageAttribute, & languageConstant, NULL );
04393       if (status != DW_DLV_OK) {
04394             done = true;
04395             goto cleanup_dwarf;
04396       }
04397          
04398       switch( languageConstant )
04399         {
04400             case DW_LANG_C:
04401             case DW_LANG_C89:
04402           (*mod_langs)[working_module] = lang_C;
04403           break;
04404             case DW_LANG_C_plus_plus:
04405           (*mod_langs)[working_module] = lang_CPlusPlus;
04406           break;
04407             case DW_LANG_Fortran77:
04408             case DW_LANG_Fortran90:
04409             case DW_LANG_Fortran95:
04410           (*mod_langs)[working_module] = lang_Fortran;
04411           break;
04412             default:
04413           /* We know what the language is but don't care. */
04414           break;
04415         } /* end languageConstant switch */
04416     cleanup_dwarf:
04417       if (languageAttribute)
04418             dwarf_dealloc( dbg, languageAttribute, DW_DLA_ATTR );
04419       if (moduleName)
04420             dwarf_dealloc( dbg, moduleName, DW_DLA_STRING );
04421       if (moduleDIE)
04422             dwarf_dealloc( dbg, moduleDIE, DW_DLA_DIE );
04423       languageAttribute = NULL;
04424       moduleName = NULL;
04425       moduleDIE = NULL;
04426     }
04427 
04428     }
04429 #endif
04430 
04431 }
04432 
04433 bool AObject::getSegments(vector<Segment> &segs) const
04434 {
04435   unsigned i;
04436   for(i=0;i<regions_.size();i++)
04437     {
04438       if((regions_[i]->getRegionName() == ".text") || (regions_[i]->getRegionName() == ".init") || (regions_[i]->getRegionName() == ".fini") ||
04439      (regions_[i]->getRegionName() == ".rodata") || (regions_[i]->getRegionName() == ".plt") || (regions_[i]->getRegionName() == ".data"))
04440         {
04441       Segment seg;
04442       seg.data = regions_[i]->getPtrToRawData();
04443       seg.loadaddr = regions_[i]->getDiskOffset();
04444       seg.size = regions_[i]->getDiskSize();
04445       seg.name = regions_[i]->getRegionName();
04446       //            seg.segFlags = regions_[i]->getFlags();
04447       segs.push_back(seg);
04448         }
04449     }
04450   return true;
04451 }
04452 
04453 bool Object::emitDriver(Symtab *obj, string fName,
04454             std::vector<Symbol *>&allSymbols,
04455                         unsigned /*flag*/)
04456 {
04457 #ifdef BINEDIT_DEBUG
04458   printf("emitting...\n");
04459   //print_symbol_map(&symbols_);
04460   print_symbols(allSymbols);
04461   printf("%d total symbol(s)\n", allSymbols.size());
04462 #endif
04463   if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS32)
04464     {
04465       emitElf *em = new emitElf(elfHdr, isStripped, this, err_func_);
04466       if( !em->createSymbolTables(obj, allSymbols) ) return false;
04467       return em->driver(obj, fName);
04468     }
04469 #if defined(x86_64_unknown_linux2_4) || \
04470     defined(ppc64_linux) || \
04471     (defined(os_freebsd) && defined(arch_x86_64))
04472   else if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS64) 
04473     {
04474       emitElf64 *em = new emitElf64(elfHdr, isStripped, this, err_func_);
04475       if( !em->createSymbolTables(obj, allSymbols) ) return false;
04476       return em->driver(obj, fName);
04477     }
04478 #endif
04479   return false;
04480 }
04481 
04482 const char *Object::interpreter_name() const 
04483 {
04484   return interpreter_name_;
04485 }
04486 
04487 /* Parse everything in the file on disk, and cache that we've done so,
04488    because our modules may not bear any relation to the name source files. */
04489 void Object::parseStabFileLineInfo(Symtab *st, dyn_hash_map<std::string, LineInformation> &li) 
04490 {
04491   static dyn_hash_map< string, bool > haveParsedFileMap;
04492 
04493   /* We haven't parsed this file already, so iterate over its stab entries. */
04494 
04495   stab_entry * stabEntry = get_stab_info();
04496   assert( stabEntry != NULL );
04497   const char * nextStabString = stabEntry->getStringBase();
04498 
04499   const char * currentSourceFile = NULL;
04500   const char * moduleName = NULL;
04501   Function *currentFunction = NULL;
04502   Offset currentAddress = 0;
04503   unsigned currentLineBase = 0;
04504   unsigned functionLineToPossiblyAdd = 0;
04505 
04506   //Offset baseAddress = getBaseAddress();
04507 
04508   for ( unsigned int i = 0; i < stabEntry->count(); i++ ) 
04509     {
04510       switch (stabEntry->type( i )) 
04511     {
04512     case N_UNDF: /* start of an object file */ 
04513       {
04514         stabEntry->setStringBase( nextStabString );
04515         nextStabString = stabEntry->getStringBase() + stabEntry->val( i );
04516 
04517         currentSourceFile = NULL;
04518       }
04519       break;
04520 
04521     case N_SO: /* compilation source or file name */
04522       {
04523         const char * sourceFile = stabEntry->name( i );
04524         currentSourceFile = strrchr( sourceFile, '/' );
04525 
04526         if ( currentSourceFile == NULL ) 
04527           {
04528         currentSourceFile = sourceFile; 
04529           }
04530         else 
04531           { 
04532         ++currentSourceFile; 
04533           }
04534 
04535         moduleName = currentSourceFile;
04536 
04537         // /* DEBUG */ fprintf( stderr, "%s[%d]: using file name '%s'\n", __FILE__, __LINE__, currentSourceFile );
04538       }
04539       break;
04540 
04541     case N_SOL: /* file name (possibly an include file) */ 
04542       {
04543         const char * sourceFile = stabEntry->name( i );
04544         currentSourceFile = strrchr( sourceFile, '/' );
04545         if ( currentSourceFile == NULL ) 
04546           {
04547         currentSourceFile = sourceFile; 
04548           }
04549         else 
04550           {
04551         ++currentSourceFile; 
04552           }
04553 
04554         // /* DEBUG */ fprintf( stderr, "%s[%d]: using file name '%s'\n", __FILE__, __LINE__, currentSourceFile );
04555       }
04556       break;
04557 
04558     case N_FUN: /* a function */ 
04559       {
04560         //fprintf(stderr, "%s[%d]:  N_FUN [%s, %lu, %lu, %lu, %lu]\n", 
04561         //      FILE__, __LINE__, stabEntry->name(i) ? stabEntry->name(i) : "no_name",
04562         //      stabEntry->nameIdx(i), stabEntry->other(i), 
04563         //      stabEntry->desc(i), stabEntry->val(i));
04564 
04565         if ( *stabEntry->name( i ) == 0 ) 
04566           {
04567         currentFunction = NULL;
04568         currentLineBase = 0;
04569         //fprintf(stderr, "%s[%d]:  GOT EOF marker\n", FILE__, __LINE__);
04570         break;
04571           } /* end if the N_FUN is an end-of-function-marker. */
04572 
04573         std::vector<Function *> funcs;
04574         char stringbuf[2048];
04575         const char *stabstr = stabEntry->name(i);
04576         unsigned iter = 0;
04577 
04578         while (iter < 2048)
04579           {
04580         char c = stabstr[iter];
04581 
04582         if ( (c == ':')  || (c == '\0'))
04583                   {
04584             //stabstrs use ':' as delimiter
04585             stringbuf[iter] = '\0';
04586             break;
04587                   }
04588 
04589         stringbuf[iter] = c;
04590 
04591         iter++;
04592           }
04593 
04594         if (iter >= 2047) 
04595           {
04596         fprintf(stderr, "%s[%d]:  something went horribly awry\n", FILE__, __LINE__);
04597         continue;
04598           }
04599         else 
04600           {
04601         switch (stabstr[iter+1])
04602                   {
04603           case 'F':
04604           case 'f':
04605             //  A "good" function
04606             break;
04607           case 'P':
04608           case 'p':
04609             //  A prototype function? need to discard
04610             //fprintf(stderr, "%s[%d]:  discarding prototype %s\n", FILE__, __LINE__, stabstr);
04611             continue;
04612             break;
04613           default:
04614             fprintf(stderr, "%s[%d]:  discarding unknown %s, key = %c\n", 
04615                 FILE__, __LINE__, stabstr, stabstr[iter +1]);
04616             continue;
04617             break;
04618                   };
04619           }
04620 
04621         if (! st->findFunctionsByName(funcs, std::string(stringbuf))
04622         || !funcs.size())
04623           {
04624         fprintf(stderr, "%s[%d]:  failed to find function with name %s\n", 
04625                         FILE__, __LINE__, stabEntry->name(i));
04626         continue;
04627           }
04628 
04629         if (funcs.size() > 1)
04630           {
04631               //  we see a lot of these on solaris (solaris only)
04632         fprintf(stderr, "%s[%d]:  WARN:  found %lu functions with name %s (stringbuf %s)\n", 
04633             FILE__, __LINE__, (unsigned long) funcs.size(), stabEntry->name(i), stringbuf);
04634           }
04635 
04636         currentFunction = funcs[0];
04637         currentLineBase = stabEntry->desc(i);
04638         functionLineToPossiblyAdd = currentLineBase;
04639 
04640         assert(currentFunction);
04641         currentAddress = currentFunction->getOffset();
04642 
04643       }
04644       break;
04645 
04646     case N_SLINE: 
04647       {
04648         unsigned current_col = 0;
04649 
04650         //fprintf(stderr, "%s[%d]:  N_SLINE [%s, %lu, %lu, %lu, %lu]\n", 
04651         // FILE__, __LINE__, stabEntry->name(i) ? stabEntry->name(i) : "no_name",
04652         // stabEntry->nameIdx(i), stabEntry->other(i), stabEntry->desc(i), 
04653         // stabEntry->val(i));
04654 
04655         if (!currentLineBase)
04656           {
04657         //fprintf(stderr, "%s[%d]:  skipping SLINE b/c no earlier line base\n", 
04658         //     FILE__, __LINE__);
04659         //fprintf(stderr, "%s[%d]:  N_FUN [%s, %lu, %lu, %lu, %lu]\n", 
04660         //      FILE__, __LINE__, stabEntry->name(last_fun) ? stabEntry->name(last_fun) : "no_name",
04661         //      stabEntry->nameIdx(last_fun), stabEntry->other(last_fun), 
04662         //      stabEntry->desc(last_fun), stabEntry->val(last_fun));
04663         //fprintf(stderr, "%s[%d]:  N_SLINE [%s, %lu, %lu, %lu, %lu]\n", 
04664         //      FILE__, __LINE__, stabEntry->name(i) ? stabEntry->name(i) : "no_name",
04665         //      stabEntry->nameIdx(i), stabEntry->other(i), stabEntry->desc(i), 
04666         //      stabEntry->val(i));
04667         continue;
04668           }
04669 
04670         unsigned newLineSpec = stabEntry->desc(i);
04671 
04672         //if (newLineSpec > (currentLineBase + 100)) 
04673         //{
04674         //fprintf(stderr, "%s[%d]:  FIXME???? newLineSpec = %d, currentLineBase = %d\n", FILE__, __LINE__, newLineSpec, currentLineBase);
04675         //}
04676 
04677         //  Addresses specified in SLINEs are relative to the beginning of the fn
04678         Offset newLineAddress = stabEntry->val(i) + currentFunction->getOffset();
04679 
04680         if (newLineAddress <= currentAddress)
04681           {
04682         //fprintf(stderr, "%s[%d]:  skipping addLine for bad address %lu <= %lu\n", 
04683         //     FILE__, __LINE__, newLineAddress, currentAddress);
04684         continue;
04685           }
04686 
04687         //  If we just got our first N_SLINE after a function definition
04688         //  its possible that the line number specified in the function 
04689         //  definition was less than the line number that we are currently on
04690         //  If so, add an additional line number entry that encompasses
04691         //  the line number of the original function definition in addition
04692         //  to this SLINE ( use the same address range)
04693 
04694         if (functionLineToPossiblyAdd)
04695           {
04696         if (functionLineToPossiblyAdd < newLineSpec)
04697                   {
04698             li[moduleName].addLine(currentSourceFile, 
04699                        functionLineToPossiblyAdd, 
04700                        current_col, currentAddress, 
04701                        newLineAddress );
04702                   }
04703 
04704         functionLineToPossiblyAdd = 0;
04705           }
04706 
04707         //fprintf(stderr, "%s[%d]:  addLine(%s:%d [%p-%p]\n", 
04708         //      FILE__, __LINE__, currentSourceFile, newLineSpec, 
04709         //      currentAddress, newLineAddress);
04710 
04711         li[moduleName].addLine(currentSourceFile, newLineSpec, 
04712                    current_col, currentAddress, 
04713                    newLineAddress );
04714 
04715         currentAddress = newLineAddress;
04716         currentLineBase = newLineSpec + 1;
04717 
04718       }
04719       break;
04720 
04721     } /* end switch on the ith stab entry's type */
04722 
04723     } /* end iteration over stab entries. */
04724 
04725   //  haveParsedFileMap[ key ] = true;
04726 } /* end parseStabFileLineInfo() */
04727 
04728 // Dwarf Debug Format parsing
04729 void Object::parseDwarfFileLineInfo(dyn_hash_map<std::string, LineInformation> &li) 
04730 {
04731     Dwarf_Debug *dbg_ptr = dwarf->line_dbg();
04732     if (!dbg_ptr)
04733         return; 
04734     Dwarf_Debug &dbg = *dbg_ptr;
04735 
04736     /* Itereate over the CU headers. */
04737     Dwarf_Unsigned header;
04738     while ( dwarf_next_cu_header( dbg, NULL, NULL, NULL, NULL, & header, NULL ) == DW_DLV_OK ) 
04739     {
04740         /* Acquire the CU DIE. */
04741         Dwarf_Die cuDIE;
04742         int status = dwarf_siblingof( dbg, NULL, & cuDIE, NULL);
04743         if ( status != DW_DLV_OK ) { 
04744             /* If we can get no (more) CUs, we're done. */
04745             break;
04746         }
04747 
04748         char * cuName;
04749         const char *moduleName;
04750         status = dwarf_diename( cuDIE, &cuName, NULL );
04751         if ( status == DW_DLV_NO_ENTRY ) {
04752             cuName = NULL;
04753             moduleName = "DEFAULT_MODULE";
04754         }
04755         else {
04756             moduleName = strrchr(cuName, '/');
04757             if (!moduleName)
04758                 moduleName = strrchr(cuName, '\\');
04759             if (moduleName)
04760                 moduleName++;
04761             else
04762                 moduleName = cuName;
04763         }
04764         //fprintf(stderr, "[%s:%u] - llparsing for module %s\n", __FILE__, __LINE__, moduleName);
04765 
04766         /* Acquire this CU's source lines. */
04767         Dwarf_Line * lineBuffer;
04768         Dwarf_Signed lineCount;
04769         status = dwarf_srclines( cuDIE, & lineBuffer, & lineCount, NULL );
04770 
04771         /* See if we can get anything useful out of the next CU
04772            if this one is corrupt. */
04773         assert( status != DW_DLV_ERROR );
04774 
04775         /* It's OK for a CU not to have line information. */
04776         if ( status != DW_DLV_OK ) {
04777             /* Free this CU's DIE. */
04778             dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
04779             continue;
04780         }
04781         assert( status == DW_DLV_OK );
04782 
04783         /* The 'lines' returned are actually interval markers; the code
04784            generated from lineNo runs from lineAddr up to but not including
04785            the lineAddr of the next line. */               
04786         bool isPreviousValid = false;
04787         Dwarf_Unsigned previousLineNo = 0;
04788         Dwarf_Signed previousLineColumn = 0;
04789         Dwarf_Addr previousLineAddr = 0x0;
04790         char * previousLineSource = NULL;
04791 
04792         //Offset baseAddr = obj()->codeBase();
04793         Offset baseAddr = getBaseAddress();
04794 
04795         /* Iterate over this CU's source lines. */
04796         for ( int i = 0; i < lineCount; i++ ) 
04797         {
04798             /* Acquire the line number, address, source, and end of sequence flag. */
04799             Dwarf_Unsigned lineNo;
04800             status = dwarf_lineno( lineBuffer[i], & lineNo, NULL );
04801             if ( status != DW_DLV_OK ) { continue; }
04802 
04803             Dwarf_Signed lineOff;
04804             status = dwarf_lineoff( lineBuffer[i], & lineOff, NULL );
04805             if ( status != DW_DLV_OK ) { lineOff = 0; }
04806 
04807             Dwarf_Addr lineAddr;
04808             status = dwarf_lineaddr( lineBuffer[i], & lineAddr, NULL );
04809             if ( status != DW_DLV_OK ) 
04810             { 
04811                 fprintf(stderr, "%s[%d]:  dwarf_lineaddr() failed\n", FILE__, __LINE__);
04812                 continue; 
04813             }
04814 
04815             lineAddr += baseAddr;
04816 
04817             if (dwarf->debugLinkFile()) {
04818                 Offset new_lineAddr;
04819                 bool result = convertDebugOffset(lineAddr, new_lineAddr);
04820                 if (result)
04821                     lineAddr = new_lineAddr;
04822             }
04823 
04824             char * lineSource;
04825             status = dwarf_linesrc( lineBuffer[i], & lineSource, NULL );
04826             if ( status != DW_DLV_OK ) { continue; }
04827 
04828             Dwarf_Bool isEndOfSequence;
04829             status = dwarf_lineendsequence( lineBuffer[i], & isEndOfSequence, NULL );
04830             if ( status != DW_DLV_OK ) { continue; }
04831 
04832             if ( isPreviousValid ) 
04833             {
04834                 /* If we're talking about the same (source file, line number) tuple,
04835                    and it isn't the end of the sequence, we can coalesce the range.
04836                    (The end of sequence marker marks discontinuities in the ranges.) */
04837                 if ( lineNo == previousLineNo && strcmp( lineSource, previousLineSource ) == 0 
04838                         && ! isEndOfSequence ) 
04839                 {
04840                     /* Don't update the prev* values; just keep going until we hit the end of 
04841                        a sequence or  new sourcefile. */
04842                     continue;
04843                 } /* end if we can coalesce this range */
04844 
04845                 char *canonicalLineSource;
04846                 if (truncateLineFilenames) {
04847                     canonicalLineSource = strrchr( previousLineSource, '/' );
04848                     if( canonicalLineSource == NULL ) { canonicalLineSource = previousLineSource; }
04849                     else { ++canonicalLineSource; }
04850                 }
04851                 else {
04852                     canonicalLineSource = previousLineSource;
04853                 }
04854 
04855 
04856 
04857                 Dyninst::Offset startAddrToUse = previousLineAddr;
04858                 Dyninst::Offset endAddrToUse = lineAddr;
04859 
04860             if (startAddrToUse && endAddrToUse)
04861             {
04862                //fprintf(stderr, "%s[%d]:  adding %s[%llu]: 0x%lx -> 0x%lx to line info\n", FILE__, __LINE__, canonicalLineSource, previousLineNo,  startAddrToUse, endAddrToUse);
04863                
04864                li[std::string(moduleName)].addLine(canonicalLineSource, 
04865                                                    (unsigned int) previousLineNo, 
04866                                                    (unsigned int) previousLineColumn, 
04867                                                    startAddrToUse, 
04868                                                    endAddrToUse );
04869             }
04870                 /* The line 'canonicalLineSource:previousLineNo' has an address range of [previousLineAddr, lineAddr). */
04871             } /* end if the previous* variables are valid */
04872 
04873             /* If the current line ends the sequence, invalidate previous; otherwise, update. */
04874             if ( isEndOfSequence ) 
04875             {
04876                 dwarf_dealloc( dbg, lineSource, DW_DLA_STRING );
04877                 isPreviousValid = false;
04878             }
04879             else {
04880                 if( isPreviousValid ) { dwarf_dealloc( dbg, previousLineSource, DW_DLA_STRING ); }
04881                 previousLineNo = lineNo;
04882                 previousLineSource = lineSource;
04883                 previousLineAddr = lineAddr;
04884                 previousLineColumn = lineOff;
04885 
04886                 isPreviousValid = true;
04887             } /* end if line was not the end of a sequence */
04888         } /* end iteration over source line entries. */
04889 
04890         /* Free this CU's source lines. */
04891         for ( int i = 0; i < lineCount; i++ ) {
04892             dwarf_dealloc( dbg, lineBuffer[i], DW_DLA_LINE );
04893         }
04894         dwarf_dealloc( dbg, lineBuffer, DW_DLA_LIST );
04895         if (cuName)
04896             dwarf_dealloc( dbg, cuName, DW_DLA_STRING );  
04897 
04898         /* Free this CU's DIE. */
04899         dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
04900     } /* end CU header iteration */
04901     /* Note that we've parsed this file. */
04902 } /* end parseDwarfFileLineInfo() */
04903 
04904 void Object::parseFileLineInfo(Symtab *st, dyn_hash_map<string, LineInformation> &li)
04905 {
04906     parseStabFileLineInfo(st, li);
04907     parseDwarfFileLineInfo(li);
04908 }
04909 
04910 void Object::parseTypeInfo(Symtab *obj)
04911 {
04912 #if defined(TIMED_PARSE)
04913     struct timeval starttime;
04914     gettimeofday(&starttime, NULL);
04915 #endif   
04916 
04917     parseStabTypes(obj);
04918 
04919    DwarfWalker walker(obj, *(dwarf->type_dbg()));
04920    walker.parse();
04921    //parseDwarfTypes(obj);
04922         
04923 #if defined(TIMED_PARSE)
04924     struct timeval endtime;
04925     gettimeofday(&endtime, NULL);
04926     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
04927     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
04928     unsigned long difftime = lendtime - lstarttime;
04929     double dursecs = difftime/(1000 );
04930     cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< obj->file()
04931         <<") took "<< dursecs <<" msecs" << endl;
04932 #endif   
04933 }
04934 
04935 void Object::parseStabTypes(Symtab *obj)
04936 {
04937     types_printf("Entry to parseStabTypes for %s\n", obj->name().c_str());
04938     stab_entry *stabptr = NULL;
04939     const char *next_stabstr = NULL;
04940 
04941     unsigned i;
04942     char *modName = NULL;
04943     string temp;
04944     char *ptr = NULL, *ptr2 = NULL, *ptr3 = NULL;
04945     bool parseActive = false;
04946 
04947     std::string *currentFunctionName = NULL;
04948     Symbol *commonBlockVar = NULL;
04949     string *commonBlockName = NULL;
04950     typeCommon *commonBlock = NULL;
04951     int mostRecentLinenum = 0;
04952 
04953   Module *mod;
04954   typeCollection *tc = NULL;
04955 
04956 #if defined(TIMED_PARSE)
04957   struct timeval starttime;
04958   gettimeofday(&starttime, NULL);
04959   unsigned int pss_count = 0;
04960   double pss_dur = 0;
04961   unsigned int src_count = 0;
04962   double src_dur = 0;
04963   unsigned int fun_count = 0;
04964   double fun_dur = 0;
04965   struct timeval t1, t2;
04966 #endif
04967 
04968 
04969   stabptr = get_stab_info();
04970   if (!stabptr) {
04971     types_printf("\tWarning: no stab ptr, returning immediately\n");
04972     return;
04973   }
04974 
04975   //Using the Object to get the pointers to the .stab and .stabstr
04976   // XXX - Elf32 specific needs to be in seperate file -- jkh 3/18/99
04977   next_stabstr = stabptr->getStringBase();
04978   types_printf("\t Parsing %d stab entries\n", stabptr->count());
04979   for (i=0; i<stabptr->count(); i++) {
04980     switch(stabptr->type(i)){
04981     case N_UNDF: /* start of object file */
04982       /* value contains offset of the next string table for next module */
04983       // assert(stabptr->nameIdx(i) == 1);
04984       stabptr->setStringBase(next_stabstr);
04985       next_stabstr = stabptr->getStringBase() + stabptr->val(i);
04986 
04987       //N_UNDF is the start of object file. It is time to
04988       //clean source file name at this moment.
04989       /*
04990     if(currentSourceFile){
04991     delete currentSourceFile;
04992     currentSourceFile = NULL;
04993     delete absoluteDirectory;
04994     absoluteDirectory = NULL;
04995     delete currentFunctionName;
04996     currentFunctionName = NULL;
04997     currentFileInfo = NULL;
04998     currentFuncInfo = NULL;
04999     }
05000       */
05001       break;
05002            
05003     case N_ENDM: /* end of object file */
05004       break;
05005            
05006     case N_SO: /* compilation source or file name */
05007            /* bperr("Resetting CURRENT FUNCTION NAME FOR NEXT OBJECT FILE\n");*/
05008 #ifdef TIMED_PARSE
05009       src_count++;
05010       gettimeofday(&t1, NULL);
05011 #endif
05012       symt_current_func_name = ""; // reset for next object file
05013       symt_current_mangled_func_name = ""; // reset for next object file
05014       symt_current_func = NULL;
05015 
05016       modName = const_cast<char*>(stabptr->name(i));
05017       // cerr << "checkpoint B" << endl;
05018       ptr = strrchr(modName, '/');
05019       //  cerr << "checkpoint C" << endl;
05020       if (ptr) {
05021     ptr++;
05022     modName = ptr;
05023       }
05024       if (obj->findModuleByName(mod, modName)) {
05025           tc = typeCollection::getModTypeCollection(mod);
05026     parseActive = true;
05027     if (!mod) {
05028       fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
05029     }
05030     else if (!tc) 
05031       {
05032         fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
05033       }
05034     else 
05035         tc->clearNumberedTypes();
05036       } 
05037       else {
05038     //parseActive = false;
05039     mod = obj->getDefaultModule();
05040     tc = typeCollection::getModTypeCollection(mod);
05041     types_printf("\t Warning: failed to find module name matching %s, using %s\n", modName, mod->fileName().c_str());
05042       }
05043 
05044 #ifdef TIMED_PARSE
05045       gettimeofday(&t2, NULL);
05046       src_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05047       //src_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000) ;
05048 #endif
05049       break;
05050     case N_SLINE:
05051       mostRecentLinenum = stabptr->desc(i);
05052       break;
05053     default:
05054       break;
05055     }
05056     if(parseActive || !is_aout()) {
05057       std::vector<Symbol *> bpfv;
05058       switch(stabptr->type(i)){
05059       case N_FUN:
05060 #ifdef TIMED_PARSE
05061     fun_count++;
05062     gettimeofday(&t1, NULL);
05063 #endif
05064     //all we have to do with function stabs at this point is to assure that we have
05065     //properly set the var currentFunctionName for the later case of (parseActive)
05066     symt_current_func = NULL;
05067     int currentEntry = i;
05068     int funlen = strlen(stabptr->name(currentEntry));
05069     ptr = new char[funlen+1];
05070     strcpy(ptr, stabptr->name(currentEntry));
05071     while(strlen(ptr) != 0 && ptr[strlen(ptr)-1] == '\\'){
05072       ptr[strlen(ptr)-1] = '\0';
05073       currentEntry++;
05074       strcat(ptr,stabptr->name(currentEntry));
05075     }
05076     char* colonPtr = NULL;
05077     if(currentFunctionName) delete currentFunctionName;
05078     if(!ptr || !(colonPtr = strchr(ptr,':')))
05079       currentFunctionName = NULL;
05080     else {
05081       char* tmp = new char[colonPtr-ptr+1];
05082       strncpy(tmp,ptr,colonPtr-ptr);
05083       tmp[colonPtr-ptr] = '\0';
05084       currentFunctionName = new string(tmp);
05085       // Shouldn't this be a function name lookup?
05086       std::vector<Symbol *>syms;
05087       if(!obj->findSymbol(syms, 
05088                     *currentFunctionName, 
05089                     Symbol::ST_FUNCTION,
05090                     mangledName)) {
05091         if(!obj->findSymbol(syms, 
05092                       "_"+*currentFunctionName, 
05093                       Symbol::ST_FUNCTION,
05094                       mangledName)) {
05095           string fortranName = *currentFunctionName + string("_");
05096           if (obj->findSymbol(syms, 
05097                     fortranName,
05098                     Symbol::ST_FUNCTION,
05099                     mangledName)) {
05100         delete currentFunctionName;
05101         currentFunctionName = new string(fortranName);
05102           }
05103         }
05104       }
05105       syms.clear();
05106       delete[] tmp;
05107     }
05108     delete[] ptr;
05109 #ifdef TIMED_PARSE
05110     gettimeofday(&t2, NULL);
05111     fun_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05112     //fun_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000);
05113 #endif
05114     break;
05115       }
05116       if (!parseActive) continue;
05117       switch(stabptr->type(i)){
05118       case N_BCOMM:     {
05119     // begin Fortran named common block
05120     string tmp = string(stabptr->name(i));
05121     commonBlockName = &tmp;
05122     // find the variable for the common block
05123 
05124     //TODO? change this. findLocalVar will cause an infinite loop
05125     std::vector<Symbol *>vars;
05126     if(!obj->findSymbol(vars, 
05127                   *commonBlockName, 
05128                   Symbol::ST_OBJECT,
05129                   mangledName)) {
05130       if(!obj->findSymbol(vars, 
05131                     *commonBlockName, 
05132                     Symbol::ST_OBJECT,
05133                     mangledName,
05134                     true))
05135         commonBlockVar = NULL;
05136       else
05137         commonBlockVar = vars[0];
05138     }
05139     else
05140       commonBlockVar = vars[0];
05141     if (!commonBlockVar) {
05142       // //bperr("unable to find variable %s\n", commonBlockName);
05143     } else {
05144       commonBlock = dynamic_cast<typeCommon *>(tc->findVariableType(*commonBlockName));
05145       if (commonBlock == NULL) {
05146         // its still the null type, create a new one for it
05147         commonBlock = new typeCommon(*commonBlockName);
05148         tc->addGlobalVariable(*commonBlockName, commonBlock);
05149       }
05150       // reset field list
05151       commonBlock->beginCommonBlock();
05152     }
05153     break;
05154       }
05155       case N_ECOMM: {
05156     //copy this set of fields
05157     assert(currentFunctionName);
05158     if(!obj->findSymbol(bpfv, 
05159                   *currentFunctionName, 
05160                   Symbol::ST_FUNCTION,
05161                   mangledName)) {
05162       if(!obj->findSymbol(bpfv, 
05163                     *currentFunctionName, 
05164                     Symbol::ST_FUNCTION, 
05165                     mangledName,
05166                     true)){
05167         // //bperr("unable to locate current function %s\n", currentFunctionName->c_str());
05168       }
05169       else{
05170         Symbol *func = bpfv[0];
05171         commonBlock->endCommonBlock(func, (void *)commonBlockVar->getOffset());
05172       }    
05173     } else {
05174       if (bpfv.size() > 1) {
05175         // warn if we find more than one function with this name
05176         // //bperr("%s[%d]:  WARNING: found %d funcs matching name %s, using the first\n",
05177         //                     __FILE__, __LINE__, bpfv.size(), currentFunctionName->c_str());
05178       }
05179       Symbol *func = bpfv[0];
05180       commonBlock->endCommonBlock(func, (void *)commonBlockVar->getOffset());
05181     }
05182     //TODO?? size for local variables??
05183     //       // update size if needed
05184     //       if (commonBlockVar)
05185     //           commonBlockVar->setSize(commonBlock->getSize());
05186     commonBlockVar = NULL;
05187     commonBlock = NULL;
05188     break;
05189       }
05190     // case C_BINCL: -- what is the elf version of this jkh 8/21/01
05191     // case C_EINCL: -- what is the elf version of this jkh 8/21/01
05192       case 32:    // Global symbols -- N_GYSM
05193       case 38:    // Global Static -- N_STSYM
05194       case N_FUN:
05195       case 128:   // typedefs and variables -- N_LSYM
05196       case 160:   // parameter variable -- N_PSYM
05197       case 0xc6:  // position-independant local typedefs -- N_ISYM
05198       case 0xc8: // position-independant external typedefs -- N_ESYM
05199 #ifdef TIMED_PARSE
05200     pss_count++;
05201     gettimeofday(&t1, NULL);
05202 #endif
05203     if (stabptr->type(i) == N_FUN) symt_current_func = NULL;
05204     ptr = const_cast<char *>(stabptr->name(i));
05205     while (ptr[strlen(ptr)-1] == '\\') {
05206       //ptr[strlen(ptr)-1] = '\0';
05207       ptr2 =  const_cast<char *>(stabptr->name(i+1));
05208       ptr3 = (char *) malloc(strlen(ptr) + strlen(ptr2) + 1);
05209       strcpy(ptr3, ptr);
05210       ptr3[strlen(ptr)-1] = '\0';
05211       strcat(ptr3, ptr2);
05212       ptr = ptr3;
05213       i++;
05214       // XXX - memory leak on multiple cont. lines
05215     }
05216     // bperr("stab #%d = %s\n", i, ptr);
05217     // may be nothing to parse - XXX  jdd 5/13/99
05218             
05219     if (parseCompilerType(this))
05220       temp = parseStabString(mod, mostRecentLinenum, (char *)ptr, stabptr->val(i), commonBlock);
05221     else
05222       temp = parseStabString(mod, stabptr->desc(i), (char *)ptr, stabptr->val(i), commonBlock);
05223     if (temp.length()) {
05224       //Error parsing the stabstr, return should be \0
05225       // //bperr( "Stab string parsing ERROR!! More to parse: %s\n",
05226       //                                  temp.c_str());
05227       // //bperr( "  symbol: %s\n", ptr);
05228     }
05229 #ifdef TIMED_PARSE
05230     gettimeofday(&t2, NULL);
05231     pss_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05232     //      pss_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000);
05233 #endif
05234     break;
05235       default:
05236     break;
05237       }             
05238     }
05239   }
05240 #if defined(TIMED_PARSE)
05241   struct timeval endtime;
05242   gettimeofday(&endtime, NULL);
05243   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
05244   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
05245   unsigned long difftime = lendtime - lstarttime;
05246   double dursecs = difftime/(1000 );
05247   cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName()
05248        <<") took "<<dursecs <<" msecs" << endl;
05249   cout << "Breakdown:" << endl;
05250   cout << "     Functions: " << fun_count << " took " << fun_dur << "msec" << endl;
05251   cout << "     Sources: " << src_count << " took " << src_dur << "msec" << endl;
05252   cout << "     parseStabString: " << pss_count << " took " << pss_dur << "msec" << endl;
05253   cout << "     Total: " << pss_dur + fun_dur + src_dur
05254        << " msec" << endl;
05255 #endif
05256 } 
05257 
05258 bool sort_dbg_map(const Object::DbgAddrConversion_t &a, 
05259                   const Object::DbgAddrConversion_t &b)
05260 {
05261   return (a.dbg_offset < b.dbg_offset);
05262 }
05263 
05264 bool Object::convertDebugOffset(Offset off, Offset &new_off)
05265 {
05266   if (!DbgSectionMapSorted) {
05267     std::sort(DebugSectionMap.begin(), DebugSectionMap.end(), sort_dbg_map);
05268     DbgSectionMapSorted = true;
05269   }
05270 
05271   int hi = DebugSectionMap.size();
05272   int low = 0;
05273   int cur = -1;
05274 
05275   for (;;) {
05276     int last_cur = cur;
05277     cur = (low + hi) / 2;
05278     if (cur == last_cur) {
05279       new_off = off;
05280       return true;
05281     }
05282       
05283     const DbgAddrConversion_t &cur_d = DebugSectionMap[cur];
05284       
05285     if (off >= cur_d.dbg_offset && off < cur_d.dbg_offset+cur_d.dbg_size) {
05286       new_off = off - cur_d.dbg_offset + cur_d.orig_offset;
05287       return true;
05288     }
05289     else if (off > cur_d.dbg_offset)
05290       {
05291     low = cur;
05292       }
05293     else if (off < cur_d.dbg_offset)
05294       {
05295     hi = cur;
05296       }
05297   }
05298 
05299 }
05300 
05301 void Object::insertPrereqLibrary(std::string libname)
05302 {
05303    prereq_libs.insert(libname);
05304 }
05305 
05306 bool Object::removePrereqLibrary(std::string libname)
05307 {
05308    rmd_deps.push_back(libname);
05309    return true;
05310 }
05311 
05312 std::vector<std::string> &Object::libsRMd()
05313 {
05314    return rmd_deps;
05315 }
05316 
05317 void Object::insertDynamicEntry(long name, long value)
05318 {
05319    new_dynamic_entries.push_back(std::pair<long, long>(name, value));
05320 }
05321 
05322 // Parses sections with relocations and links these relocations to
05323 // existing symbols
05324 bool Object::parse_all_relocations(Elf_X &elf, Elf_X_Shdr *dynsym_scnp,
05325         Elf_X_Shdr *dynstr_scnp, Elf_X_Shdr *symtab_scnp,
05326         Elf_X_Shdr *strtab_scnp) {
05327 
05328    //const char *shnames = pdelf_get_shnames(*elfHdr);
05329     // Setup symbol table access
05330     Offset dynsym_offset = 0;
05331     Elf_X_Data dynsym_data, dynstr_data;    
05332     Elf_X_Sym dynsym;
05333     const char *dynstr = NULL;
05334     if( dynsym_scnp && dynstr_scnp ) {
05335         dynsym_offset = dynsym_scnp->sh_offset();
05336         dynsym_data = dynsym_scnp->get_data();
05337         dynstr_data = dynstr_scnp->get_data();
05338         if( !(dynsym_data.isValid() && dynstr_data.isValid()) ) {
05339             return false;
05340         }
05341         dynsym = dynsym_data.get_sym();
05342         dynstr = dynstr_data.get_string();
05343     }
05344 
05345     Offset symtab_offset = 0;
05346     Elf_X_Data symtab_data, strtab_data;
05347     Elf_X_Sym symtab;
05348     const char *strtab = NULL;
05349     if( symtab_scnp && strtab_scnp) {
05350        symtab_offset = symtab_scnp->sh_offset();
05351        symtab_data = symtab_scnp->get_data();
05352        strtab_data = strtab_scnp->get_data();
05353        if( !(symtab_data.isValid() && strtab_data.isValid()) ) {
05354            return false;
05355        }
05356        symtab = symtab_data.get_sym();
05357        strtab = strtab_data.get_string();
05358     }
05359 
05360     if( dynstr == NULL && strtab == NULL ) return false;
05361 
05362     // Symbols are only truly uniquely idenfitied by their index in their
05363     // respective symbol table (this really applies to the symbols associated
05364     // with sections) So, a map for each symbol table needs to be built so a
05365     // relocation can be associated with the correct symbol
05366     dyn_hash_map<int, Symbol *> symtabByIndex;
05367     dyn_hash_map<int, Symbol *> dynsymByIndex;
05368 
05369     dyn_hash_map<std::string, std::vector<Symbol *> >::iterator symVec_it;
05370     for(symVec_it = symbols_.begin(); symVec_it != symbols_.end(); ++symVec_it) {
05371         std::vector<Symbol *>::iterator sym_it;
05372         for(sym_it = symVec_it->second.begin(); sym_it != symVec_it->second.end(); ++sym_it) {
05373             // Skip any symbols pointing to the undefined symbol entry
05374       if( (*sym_it)->getIndex() == STN_UNDEF ) {
05375         continue;
05376       }
05377       if( (*sym_it)->tag() == Symbol::TAG_INTERNAL ) {
05378         continue;
05379       }
05380 
05381             std::pair<dyn_hash_map<int, Symbol *>::iterator, bool> result;
05382             if( (*sym_it)->isInDynSymtab() ) {
05383                 result = dynsymByIndex.insert(std::make_pair((*sym_it)->getIndex(), (*sym_it)));
05384             }else{
05385                 result = symtabByIndex.insert(std::make_pair((*sym_it)->getIndex(), (*sym_it)));
05386             }
05387 
05388             // A symbol should be uniquely identified by its index in the symbol table
05389             assert(result.second);
05390         }
05391     }
05392 
05393     // Build mapping from section headers to Regions
05394     std::vector<Region *>::iterator reg_it;
05395     dyn_hash_map<unsigned, Region *> shToRegion;
05396     for(reg_it = regions_.begin(); reg_it != regions_.end(); ++reg_it) {
05397         std::pair<dyn_hash_map<unsigned, Region *>::iterator, bool> result;
05398         result = shToRegion.insert(std::make_pair((*reg_it)->getRegionNumber(), (*reg_it)));
05399     }
05400 
05401     for(unsigned i = 0; i < elf.e_shnum(); ++i) {
05402         Elf_X_Shdr *shdr = allRegionHdrsByShndx[i];
05403         if( shdr->sh_type() != SHT_REL && shdr->sh_type() != SHT_RELA ) continue;
05404 
05405         Elf_X_Data reldata = shdr->get_data();
05406         Elf_X_Rel rel = reldata.get_rel();
05407         Elf_X_Rela rela = reldata.get_rela();
05408 
05409         Elf_X_Shdr *curSymHdr = allRegionHdrsByShndx[shdr->sh_link()];
05410 
05411     // Apparently, relocation entries may not have associated symbols. 
05412 
05413         for(unsigned j = 0; j < (shdr->sh_size() / shdr->sh_entsize()); ++j) {
05414             // Relocation entry fields - need to be populated
05415 
05416             Offset relOff, addend = 0;
05417             std::string name;
05418             unsigned long relType;
05419             Region::RegionType regType;
05420 
05421             long symbol_index;
05422             switch(shdr->sh_type()) {
05423                 case SHT_REL:
05424                     relType = rel.R_TYPE(j);
05425                     relOff = rel.r_offset(j);
05426                     symbol_index = rel.R_SYM(j);
05427                     regType = Region::RT_REL;
05428                     break;
05429                 case SHT_RELA:
05430                     relType = rela.R_TYPE(j);
05431                     relOff = rela.r_offset(j);
05432                     symbol_index = rela.R_SYM(j);
05433                     regType = Region::RT_RELA;
05434                     addend = rela.r_addend(j);
05435                     break;
05436                 default:
05437                     continue;
05438             }
05439 
05440             // Determine which symbol table to use
05441             Symbol *sym = NULL;
05442             // Use dynstr to ensure we've initialized dynsym...
05443             if( dynstr && curSymHdr->sh_offset() == dynsym_offset ) {
05444                name = string( &dynstr[dynsym.st_name(symbol_index)] );
05445 
05446                 dyn_hash_map<int, Symbol *>::iterator sym_it;
05447                 sym_it = dynsymByIndex.find(symbol_index);
05448                 if( sym_it != dynsymByIndex.end() ) {
05449                     sym = sym_it->second;
05450             if(sym->getType() == Symbol::ST_SECTION) {
05451             name = sym->getRegion()->getRegionName().c_str();
05452                 }        
05453                 }
05454             }else if( strtab && curSymHdr->sh_offset() == symtab_offset ) {
05455                 name = string( &strtab[symtab.st_name(symbol_index)] );
05456                 dyn_hash_map<int, Symbol *>::iterator sym_it;
05457                 sym_it = symtabByIndex.find(symbol_index);
05458                 if( sym_it != symtabByIndex.end() ) {
05459                     sym = sym_it->second;
05460             if(sym->getType() == Symbol::ST_SECTION) {
05461             name = sym->getRegion()->getRegionName().c_str();
05462             }
05463                 }
05464             }
05465 
05466         Region *region = NULL;
05467             dyn_hash_map<unsigned, Region *>::iterator shToReg_it;
05468             shToReg_it = shToRegion.find(i);
05469             if( shToReg_it != shToRegion.end() ) {
05470           region = shToReg_it->second;
05471             }
05472         
05473             assert(region != NULL);
05474 
05475             relocationEntry newrel(0, relOff, addend, name, sym, relType, regType);
05476             region->addRelocationEntry(newrel);
05477             // relocations are also stored with their targets
05478             // Need to find target region
05479         if (sym) {
05480           if (shdr->sh_info() != 0) {
05481         Region *targetRegion = NULL;
05482         shToReg_it = shToRegion.find(shdr->sh_info());
05483         if( shToReg_it != shToRegion.end() ) {
05484           targetRegion = shToReg_it->second;
05485         }
05486         assert(targetRegion != NULL);
05487         targetRegion->addRelocationEntry(newrel);
05488           }
05489         }
05490         
05491         }
05492     }
05493 
05494     return true;
05495 }
05496 
05497 bool Region::isStandardCode()
05498 {
05499    return ((getRegionPermissions() == RP_RX || getRegionPermissions() == RP_RWX) &&
05500            ((name_ == std::string(".text")) ||
05501             (name_ == std::string(".init")) ||
05502             (name_ == std::string(".fini"))));
05503 }
05504 
05505 void Object::setTruncateLinePaths(bool value)
05506 {
05507    truncateLineFilenames = value;
05508 }
05509 
05510 bool Object::getTruncateLinePaths()
05511 {
05512    return truncateLineFilenames;
05513 }
05514 
05515 Dyninst::Architecture Object::getArch()
05516 {
05517 #if defined(arch_power)
05518    if (getAddressWidth() == 4) {
05519       return Dyninst::Arch_ppc32;
05520    }
05521    return Dyninst::Arch_ppc64;
05522 #elif defined(arch_x86) || defined(arch_x86_64)
05523    if (getAddressWidth() == 4) {
05524       return Dyninst::Arch_x86;
05525    }
05526    return Dyninst::Arch_x86_64;
05527 #else
05528    return Arch_none;
05529 #endif
05530 }
05531 
05532 Offset Object::getTOCoffset(Offset off) const {
05533   if (TOC_table_.empty()) return 0;
05534   Offset baseTOC = TOC_table_.find(0)->second;
05535   // We only store exceptions to the base TOC, so if we can't find it
05536   // return the base
05537 
05538   std::map<Offset, Offset>::const_iterator iter = TOC_table_.find(off);
05539   if (iter == TOC_table_.end()) {
05540     return baseTOC;
05541   }
05542   return iter->second;
05543 }
05544 
05545 void Object::setTOCoffset(Offset off) {
05546   TOC_table_.clear();
05547   TOC_table_[0] = off;
05548 }
05549 
05550 void Object::getSegmentsSymReader(vector<SymSegment> &segs) {
05551    for (unsigned i = 0; i < elfHdr->e_phnum(); ++i) {
05552       Elf_X_Phdr &phdr = elfHdr->get_phdr(i);
05553       
05554       SymSegment seg;
05555       seg.file_offset = phdr.p_offset();
05556       seg.mem_addr = phdr.p_vaddr();
05557       seg.file_size = phdr.p_filesz();
05558       seg.mem_size = phdr.p_memsz();
05559       seg.type = phdr.p_type();
05560       seg.perms = phdr.p_flags() & 0x7;
05561 
05562       segs.push_back(seg);
05563    }
05564 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1