Object-xcoff.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 // $Id: Object-xcoff.C,v 1.32 2008/09/20 03:56:10 jaw Exp $
00032 
00033 // Define this before all others to insure xcoff.h is included
00034 // with __XCOFF_HYBRID__ defined.
00035 #define __XCOFF_HYBRID__
00036 
00037 #include <regex.h>
00038 
00039 #include "symtabAPI/h/Symtab.h"
00040 #include "symtabAPI/src/Object.h"
00041 #include "common/h/pathName.h"
00042 
00043 #include "Collections.h"
00044 #include "Symtab.h"
00045 #include "Module.h"
00046 
00047 using namespace Dyninst;
00048 using namespace Dyninst::SymtabAPI;
00049 
00050 #include "debug.h"
00051 
00052 #include <procinfo.h>
00053 
00054 #include <sys/ioctl.h>
00055 #include <sys/types.h>
00056 #include <fcntl.h>
00057 #include <assert.h>
00058 #include <stdlib.h>
00059 #include <fcntl.h>
00060 #include <unistd.h>
00061 #include <stdio.h>
00062 #include <string.h>
00063 #include <sys/time.h>
00064 #include <sys/reg.h>
00065 #include <sys/user.h>
00066 #include <sys/wait.h>
00067 #include <procinfo.h> // struct procsinfo
00068 #include <sys/types.h>
00069 #include <sys/param.h> // PAGESIZE
00070 #include <set>
00071 using namespace std;
00072 #include <iomanip>
00073 
00074 #include <xcoff.h>
00075 #include <exceptab.h>
00076 #define __AR_BIG__
00077 #define __AR_SMALL__
00078 #include <ar.h> // archive file format.
00079 #include <scnhdr.h>
00080 
00081 #include <dlfcn.h>
00082 #include "common/h/debugOstream.h"
00083 
00084 /* For some reason this symbol type isn't global */
00085 #if !defined(C_WEAKEXT)
00086 #define C_WEAKEXT 0
00087 #endif
00088 
00089 char errorLine[100];
00090 std::string symt_current_func_name;
00091 std::string symt_current_mangled_func_name;
00092 Symbol *symt_current_func = NULL;
00093 
00094 // 07/11/2006 giri: definitions below are borrowed from dyninstAPI/src/arch-power.h
00095 // to remove the dependency on dyninst. Only the ones required have been borrowed
00096 
00097 #define Bop             18      /* (unconditional) branch */
00098 #define Lop             32      /* load (word) (aka lwz op in PowerPC) */
00099 #define BCLRop          19      /* branch conditional link register */
00100 #define BCCTRxop        528     /* branch conditional count register */
00101 
00102 struct iform {            // unconditional branch +
00103   unsigned op : 6;
00104   signed   li : 24;
00105   unsigned aa : 1;
00106   unsigned lk : 1;
00107 
00108 };
00109 
00110 struct dform {
00111     unsigned op : 6;
00112     unsigned rt : 5;        // rt, rs, frt, frs, to, bf_l
00113     unsigned ra : 5;
00114     signed   d_or_si : 16;  // d, si, ui
00115 };
00116 
00117 struct xlform {
00118   unsigned op : 6;
00119   unsigned bt : 5;   // rt, bo, bf_
00120   unsigned ba : 5;   // ba, bi, bfa_
00121   unsigned bb : 5;
00122   unsigned xo : 10;  // xo, eo
00123   unsigned lk : 1;
00124 };
00125 
00126 typedef union {
00127   struct iform  iform;  // branch;
00128   struct dform  dform;
00129   struct xlform xlform;
00130   unsigned int  raw;
00131 } instructUnion;
00132 
00133 unsigned long roundup4(unsigned long val) {
00134     val += 3;
00135     return val - (val % 4);
00136 }
00137 
00138 // Methods to read file and ar header for both small (32-bit) and
00139 // large (64-bit) archive files. This lets us have a single archive
00140 // parsing method.
00141 int xcoffArchive_32::read_arhdr()
00142 {
00143   char tmpstring[13];
00144 
00145   if (!fo_->set(0))
00146       return -1;
00147   if (!fo_->read(&filehdr, sizeof(struct fl_hdr)))
00148       return -1;
00149   if (strncmp(filehdr.fl_magic, AIAMAG, SAIAMAG))
00150     return -1;
00151   strncpy(tmpstring, filehdr.fl_fstmoff, 12);
00152   tmpstring[12] = 0; first_offset = atol(tmpstring);
00153   if (first_offset % 2) first_offset++;
00154   strncpy(tmpstring, filehdr.fl_lstmoff, 12);
00155   tmpstring[12] = 0; last_offset = atol(tmpstring);
00156   if (last_offset % 2) last_offset++;
00157   next_offset = first_offset;
00158   // Offsets are always even
00159   return 0;
00160 }
00161 
00162 int xcoffArchive_64::read_arhdr()
00163 {
00164   char tmpstring[22];
00165 
00166   if (!fo_->set(0))
00167       return -1;
00168 
00169   if (!fo_->read(&filehdr, sizeof(struct fl_hdr_big)))
00170       return -1;
00171 
00172   if (strncmp(filehdr.fl_magic, AIAMAGBIG, SAIAMAG))
00173     return -1;
00174   strncpy(tmpstring, filehdr.fl_fstmoff, 21);
00175   tmpstring[21] = 0; first_offset = atol(tmpstring);
00176   if (first_offset % 2) first_offset++;
00177   strncpy(tmpstring, filehdr.fl_lstmoff, 21);
00178   tmpstring[21] = 0; last_offset = atol(tmpstring);
00179   if (last_offset % 2) last_offset++;
00180   next_offset = first_offset;
00181 
00182   return 0;
00183 }
00184 
00185 // Archive member header parsing function for 32/64-bit archives
00186 // Pre:  takes an offset into the ar file which is the start point
00187 //       of a member header
00188 // Post: member_name contains the name of the file corresponding to
00189 //       the member header
00190 //       next_offset contains the offset to the next member header
00191 //       or 0 if there are no members
00192 //       aout_offset contains the offset to the file corresponding 
00193 //       to the member name
00194 
00195 int xcoffArchive_32::read_mbrhdr()
00196 {
00197     char tmpstring[13];
00198     
00199     if (next_offset == 0) return -1;
00200 
00201     if (!fo_->set(next_offset))
00202         return -1;
00203 
00204     if (!fo_->read(&memberhdr, sizeof(struct ar_hdr) - 2))
00205         return -1;
00206 
00207     strncpy(tmpstring, memberhdr.ar_namlen, 4);
00208     tmpstring[4] = 0; member_len = atol(tmpstring);
00209     if (member_name) free(member_name);
00210     member_name = (char *)malloc(member_len+1);
00211     
00212     if (!fo_->read(member_name, member_len))
00213         return -1;
00214     // Terminating null
00215     member_name[member_len] = 0;
00216     
00217     // Set the file offset for this member
00218     aout_offset = next_offset + sizeof(struct ar_hdr) + member_len;
00219     if (aout_offset % 2) aout_offset += 1;
00220     
00221     // Fix up next_offset
00222     if (next_offset == last_offset)
00223         next_offset = 0; // termination condition
00224     else {
00225         strncpy(tmpstring, memberhdr.ar_nxtmem, 12);
00226         tmpstring[12] = 0; next_offset = atol(tmpstring);
00227         if (next_offset % 2) next_offset++;
00228     }
00229     
00230     return 0;
00231 }
00232 // 64-bit function. Differences: structure size
00233 // A lot of shared code. 
00234 int xcoffArchive_64::read_mbrhdr()
00235 {
00236   char tmpstring[21];
00237   
00238   if (next_offset == 0) return -1;
00239 
00240     if (!fo_->set(next_offset))
00241         return -1;
00242 
00243     if (!fo_->read(&memberhdr, sizeof(struct ar_hdr_big) - 2))
00244         return -1;
00245 
00246     strncpy(tmpstring, memberhdr.ar_namlen, 4);
00247     tmpstring[4] = 0; member_len = atol(tmpstring);
00248     if (member_name) free(member_name);
00249     member_name = (char *)malloc(member_len+1);
00250 
00251     if (!fo_->read(member_name, member_len))
00252         return -1;
00253     // Terminating null
00254     member_name[member_len] = 0;
00255     
00256     // Set the file offset for this member
00257     aout_offset = next_offset + sizeof(struct ar_hdr_big) + member_len;
00258     if (aout_offset % 2) aout_offset += 1;
00259     
00260     // Fix up next_offset
00261     if (next_offset == last_offset)
00262         next_offset = 0; // termination condition
00263     else {
00264         strncpy(tmpstring, memberhdr.ar_nxtmem, 20);
00265         tmpstring[20] = 0; next_offset = atol(tmpstring);
00266         if (next_offset % 2) next_offset++;
00267     }
00268 
00269     return 0;
00270 }
00271 
00272 // Wrapper to handle the 1:many mapping of archives and members
00273 
00274 std::vector<fileOpener *> fileOpener::openedFiles;
00275 
00276 fileOpener *fileOpener::openFile(void *ptr, unsigned size) 
00277 {
00278     // Logic: if we're opening a library, match by name. If
00279     // we're opening an a.out, then we have to uniquely
00280     // open each time (as we open in /proc, and exec has the
00281     // same name).
00282 
00283    for (unsigned i = 0; i < openedFiles.size(); i++) 
00284    {
00285        if ((openedFiles[i]->mem_image() == ptr) && (openedFiles[i]->size() == size)){
00286            openedFiles[i]->refcount_++;
00287            return openedFiles[i];
00288        }
00289     }
00290     
00291     // New file. Neeefty.
00292     fileOpener *newFO = new fileOpener(ptr,size);
00293     assert(newFO);
00294     
00295     openedFiles.push_back(newFO);
00296 
00297     return newFO;
00298 }
00299 
00300 void fileOpener::closeFile() 
00301 {
00302    refcount_--;
00303 
00304    if (refcount_ > 0) return;
00305 
00306    // Remove us from the big list...
00307    std::vector<fileOpener *>::iterator iter = openedFiles.begin();
00308    for (; iter!=openedFiles.end(); iter++)
00309    {
00310       if (*iter == this)
00311          openedFiles.erase(iter);
00312    }
00313 
00314    /*for (unsigned i = 0; i < openedFiles.size(); i++) {
00315      if (openedFiles[i] == this)
00316      openedFiles.erase(i));
00317      }*/
00318 
00319    if (file()!="") //only if its not a mem image
00320    {
00321       ::munmap(mmapStart_, size_);
00322 
00323       ::close(fd_);
00324    } 
00325    mmapStart_ = 0;
00326    fd_ = 0;
00327    size_ = 0;
00328 
00329    delete this;
00330 }
00331 
00332 fileOpener::~fileOpener() {
00333    // Assert that we're already closed?
00334    assert(fd_ == 0);
00335    assert(mmapStart_ == 0);
00336    assert(size_ == 0);
00337 }
00338 
00339 bool fileOpener::set(unsigned addr) 
00340 {
00341     //assert(fd_);     may not be present if its a mem image
00342     assert(size_);
00343     assert(mmapStart_);
00344 
00345     if (addr >= size_) {
00346         fprintf(stderr, "%s[%d]: Warning: attempting to set offset to address %d (0x%x) greater than size %d (0x%x)\n", FILE__, __LINE__, 
00347                 addr, addr,
00348                 size_, size_);
00349         return false;
00350     }
00351     offset_ = addr;
00352     return true;
00353 }
00354 
00355 bool fileOpener::read(void *buf, unsigned size) 
00356 {
00357     //assert(fd_); may not be present if its a mem image
00358     assert(size_);
00359     assert(mmapStart_);
00360 
00361     if ((offset_ + size) >= size_)
00362         return false;
00363 
00364     memcpy(buf, ptr(), size);
00365 
00366     offset_ += size;
00367     return true;
00368 }
00369 
00370 bool fileOpener::seek(int offset) {
00371     if ((((int) offset_ + offset) < 0) ||
00372         ((offset_ + offset) >= size_))
00373         return false;
00374     offset_ += offset;
00375     return true;
00376 }
00377 
00378 void *fileOpener::ptr() const {
00379     // Return a pointer to the current offset
00380     char *tmpPtr = (char *)mmapStart_ + offset_;
00381     return (void *)tmpPtr;
00382 }
00383 
00384 void *fileOpener::getPtrAtOffset(unsigned offset) const
00385 {
00386     char *tmpPtr = (char *)mmapStart_ + offset;
00387     return (void *)tmpPtr;
00388 }
00389 
00390 Region::perm_t getRegionPerms(unsigned flags){
00391     if(flags & STYP_TEXT)
00392         return Region::RP_RX;
00393     else if(flags & STYP_DATA)
00394         return Region::RP_RW;
00395     else if(flags & STYP_DATA)
00396         return Region::RP_RW;
00397     else if(flags & STYP_DATA)
00398         return Region::RP_RW;
00399     else
00400         return Region::RP_R;
00401 }
00402 
00403 Region::RegionType getRegionType(unsigned flags){
00404     if(flags & STYP_TEXT)
00405         return Region::RT_TEXT;
00406     else if(flags & STYP_DATA)
00407         return Region::RT_DATA;
00408     else if(flags & STYP_DATA)
00409         return Region::RT_BSS;
00410     else if(flags & STYP_DATA)
00411         return Region::RT_DATA;
00412     else if(flags & STYP_DEBUG)
00413         return Region::RT_SYMTAB;
00414     else
00415         return Region::RT_OTHER;
00416 }
00417     
00418 // This function parses a 32-bit XCOFF file, either as part of an
00419 // archive (library) or from an a.out file. It takes an open file
00420 // descriptor from which it reads its data. In addition, it loads the
00421 // data segment from the pid given in AIX_PID_HACK, the pid of the
00422 // running process. We have to do this because the data segment
00423 // in memory is more correct than the one on disk. Specifically, the
00424 // TOC for inter-module function calls is incorrect on disk, because
00425 // offsets are calculated at runtime instead of link time.
00426 //
00427 // int fd: file descriptor for a.out object, not closed
00428 // int offset: offset to begin reading at (for archive libraries)
00429 
00430 // File parsing error macro, assumes errorLine defined
00431 #define PARSE_AOUT_DIE(errType, errCode) { \
00432       fprintf(stderr,"warning:parsing a.out file %s(%s): %s \n", \
00433               mf->filename().c_str(), member_.c_str(), errType); \
00434       err_func_(errType); \
00435       return; \
00436       }
00437 
00438 // ----------------------------------------------------------------------------
00439 // 32/64-bit section header member access macros.
00440 // These macros depend on the definition of variables scnh_base and is64,
00441 // and are only meant to be used from within Object::parse_aout().
00442 // 
00443 #define SCNH_NAME(i)           (char *)(scnh_base + scn_size * (i) + s_name_off)
00444 #define SCNH_PADDR(i)   ((*(uint64_t *)(scnh_base + scn_size * (i) + s_paddr_off)) >> word_shift)
00445 #define SCNH_VADDR(i)   ((*(uint64_t *)(scnh_base + scn_size * (i) + s_vaddr_off)) >> word_shift)
00446 #define SCNH_SIZE(i)    ((*(uint64_t *)(scnh_base + scn_size * (i) + s_size_off)) >> word_shift)
00447 #define SCNH_SCNPTR(i)  ((*(uint64_t *)(scnh_base + scn_size * (i) + s_scnptr_off)) >> word_shift)
00448 #define SCNH_RELPTR(i)  ((*(uint64_t *)(scnh_base + scn_size * (i) + s_relptr_off)) >> word_shift)
00449 #define SCNH_LNNOPTR(i) ((*(uint64_t *)(scnh_base + scn_size * (i) + s_lnnoptr_off)) >> word_shift)
00450 #define SCNH_EXCEPTPTR(i) ((*(uint64_t *)(scnh_base + scn_size * (i) + s_exceptptr_off)) >> word_shift)
00451 #define SCNH_NRELOC(i)  ((*(uint32_t *)(scnh_base + scn_size * (i) + s_nreloc_off)) >> half_shift)
00452 #define SCNH_NLNNO(i)   ((*(uint32_t *)(scnh_base + scn_size * (i) + s_nlnno_off)) >> half_shift)
00453 #define SCNH_FLAGS(i)    (*(uint32_t *)(scnh_base + scn_size * (i) + s_flags_off))
00454 
00455 // ----------------------------------------------------------------------------
00456 // 32/64-bit symbol table entry member access macros.
00457 // These macros depend on the definition of variables scnh_base and is64,
00458 // and are only meant to be used from within Object::parse_aout().
00459 // 
00460 
00461 bool Object::fillExceptionTable(struct exceptab *etab, unsigned int etab_size, bool is64,
00462         struct syment *symbols)
00463 
00464 {
00465     //  Unfortunately the xcoff exception table appears to hold locations for 
00466     //  trap instructions, but nothing to do with c++ exceptions??
00467     //  This routine is not what we want
00468     if (!etab)
00469     {
00470         fprintf(stderr, "%s[%d]:  FIXME!\n", FILE__, __LINE__);
00471         return false;
00472     }
00473 
00474     for (unsigned int i = 0; i < etab_size; ++i)
00475     {
00476         struct exceptab *tabentry = ((struct exceptab *)etab) + i;
00477         if (!tabentry)
00478         {
00479             fprintf(stderr, "%s[%d]:  bad table entry!\n", FILE__, __LINE__);
00480             continue;
00481         }
00482 
00483         //  Warn:  header files expressly warn against using sizeof(EXCEPTTAB)
00484         if (is64)
00485         {
00486             //char lang = tabentry->_u._s64._lang64;
00487             char reason = tabentry->_u._s64._reason64;
00488             if (reason == 0)
00489             {
00490                 //  This case happens for the first exception entry
00491                 //  for a given function.  If this is zero, the address
00492                 //  field contains the symbol table entry of the 
00493                 //  relevant function
00494                 //int symindex = tabentry->_u._s64._addr64.e_symndx;
00495                 //struct syment *sym = (struct syment *) (((char *)symbols) + symindex * SYMESZ);
00496                 //const char *name =  &stringPool[ sym->n_offset64 ];
00497             }
00498             else
00499             {
00500                 //uint64_t addr = tabentry->_u._s64._addr64.e_paddr;
00501             }
00502             //catch_addrs_.push_back(new ExceptionBlock(addr));
00503         }
00504         else 
00505         {
00506             //char lang = tabentry->_u._s32._lang32;
00507             char reason = tabentry->_u._s32._reason32;
00508             if (reason == 0)
00509             {
00510                 //  This case happens for the first exception entry
00511                 //  for a given function.  If this is zero, the address
00512                 //  field contains the symbol table entry of the 
00513                 //  relevant function
00514                 //int symindex = tabentry->_u._s32._addr32.e_symndx;
00515                 //struct syment *sym = (struct syment *) (((char *)symbols) + symindex * SYMESZ);
00516                 //const char *name =  &stringPool[ sym->n_offset32 ] ;
00517             }
00518             else
00519             {
00520                 //uint32_t addr = tabentry->_u._s32._addr32.e_paddr;
00521             }
00522         }
00523     }
00524     return true;
00525 }
00526 
00527 void Object::parse_aout(int offset, bool /*is_aout*/, bool alloc_syms)
00528 {
00529    // all these vrble declarations need to be up here due to the gotos,
00530    // which mustn't cross vrble initializations.  Too bad.
00531    long i,j;
00532    std::string name;
00533    unsigned long value;
00534    unsigned secno;
00535    unsigned textSecNo = 0, dataSecNo = 0, loaderSecNo = 0, exceptSecNo = 0;
00536    union auxent *aux = NULL;
00537    struct filehdr hdr;
00538    struct aouthdr aout;
00539    struct syment *sym = NULL;
00540    union auxent *csect = NULL;
00541    Symbol::SymbolType type; 
00542    stringPool = NULL;
00543    bool foundDebug = false;
00544    bool foundLoader = false;
00545    bool foundData = false;
00546    bool foundText = false;
00547        
00548    unsigned exceptab_size_ = 0;
00549 #if 0
00550    struct exceptab * exceptab_ = NULL;
00551 #endif
00552 
00553    stabs_ = NULL;
00554    nstabs_ = 0;
00555    stringpool_ = NULL;
00556    stabstr_ = NULL;
00557    linesptr_ = NULL;
00558    nlines_ = 0;
00559    linesfdptr_ = 0;
00560 
00561    struct syment *symbols = NULL;
00562    unsigned char *scnh_base = NULL;
00563    Symbol::SymbolLinkage linkage = Symbol::SL_UNKNOWN;
00564    Symbol::SymbolVisibility visibility = Symbol::SV_DEFAULT;
00565    unsigned toc_offset = 0;
00566    std::string modName;
00567    baseAddress_ = (Offset)fo_->getPtrAtOffset(offset);
00568 
00569    int linesfdptr=0;
00570    struct lineno* lines=NULL;
00571 
00572    // Get to the right place in the file (not necessarily 0)
00573    if (!fo_->set(offset))
00574       PARSE_AOUT_DIE("Seeking to correct offset", 49);
00575 
00576    // -------------------------------------------------------------------------
00577    // Read the 2 byte magic number.  Everything depends on it.
00578    //
00579    uint16_t magic;
00580    if (!fo_->read(&magic, 2))
00581       PARSE_AOUT_DIE("Reading magic number", 49);
00582 
00583    // Determine file address width.
00584    bool is64 = false;
00585    if (magic == 0x1EF /* XCOFF64 on AIX4.3 or earlier */ ||
00586        magic == 0x1F7 /* XCOFF64 on AIX5.1 or later   */) {
00587       is64 = true;
00588       addressWidth_nbytes = 8;
00589 
00590    } else if (magic != 0x1DF /* XCOFF32 */) {
00591       PARSE_AOUT_DIE("possible problem, invalid magic number", 49);
00592       //bperr("Possible problem, magic number is %x, should be %x\n",
00593       //       magic, 0x1df);
00594    }
00595    is64_ = is64;
00596 
00597    // -------------------------------------------------------------------------
00598    // Set up 32/64 bit offset variables.
00599    //
00600    uint64_t scn_size;
00601    uint64_t s_name_off, s_paddr_off, s_vaddr_off, s_size_off, s_scnptr_off;
00602    uint64_t s_relptr_off, s_lnnoptr_off;
00603    uint64_t s_nreloc_off, s_nlnno_off, s_flags_off;
00604    uint64_t word_shift, half_shift;
00605 
00606    if (is64) {
00607       scn_size      = SCNHSZ_64;
00608       s_name_off    = offsetof(struct scnhdr, s_name);
00609       s_paddr_off   = offsetof(struct scnhdr, s_paddr64);
00610       s_vaddr_off   = offsetof(struct scnhdr, s_vaddr64);
00611       s_size_off    = offsetof(struct scnhdr, s_size64);
00612       s_scnptr_off  = offsetof(struct scnhdr, s_scnptr64);
00613       s_relptr_off  = offsetof(struct scnhdr, s_relptr64);
00614       s_lnnoptr_off = offsetof(struct scnhdr, s_lnnoptr64);
00615       s_nreloc_off  = offsetof(struct scnhdr, s_nreloc64);
00616       s_nlnno_off   = offsetof(struct scnhdr, s_nlnno64);
00617       s_flags_off   = offsetof(struct scnhdr, s_flags64);
00618       word_shift    = 0;
00619       half_shift    = 0;
00620 
00621    } else {
00622       scn_size      = SCNHSZ_32;
00623       s_name_off    = offsetof(struct scnhdr, s_name);
00624       s_paddr_off   = offsetof(struct scnhdr, s_paddr32);
00625       s_vaddr_off   = offsetof(struct scnhdr, s_vaddr32);
00626       s_size_off    = offsetof(struct scnhdr, s_size32);
00627       s_scnptr_off  = offsetof(struct scnhdr, s_scnptr32);
00628       s_relptr_off  = offsetof(struct scnhdr, s_relptr32);
00629       s_lnnoptr_off = offsetof(struct scnhdr, s_lnnoptr32);
00630       s_nreloc_off  = offsetof(struct scnhdr, s_nreloc32);
00631       s_nlnno_off   = offsetof(struct scnhdr, s_nlnno32);
00632       s_flags_off   = offsetof(struct scnhdr, s_flags32);
00633       word_shift    = 32;
00634       half_shift    = 16;
00635    }
00636 
00637    // Begin file processing.  Re-seek to beginning of file.
00638    if (!fo_->set(offset))
00639       PARSE_AOUT_DIE("Seeking to correct offset", 49);
00640 
00641    // -------------------------------------------------------------------------
00642    // Read and process file header.
00643    //
00644    if (!fo_->read(&hdr, (is64 ? FILHSZ_64 : FILHSZ_32)))
00645       PARSE_AOUT_DIE("Reading file header", 49);
00646 
00647    uint64_t symptr, nsyms;
00648    if (is64) {
00649       symptr = hdr.f_symptr64;
00650       nsyms  = hdr.f_nsyms64;
00651 
00652    } else {
00653       symptr = hdr.f_symptr32;
00654       nsyms  = hdr.f_nsyms32;
00655    }
00656    is_aout_ = !(hdr.f_flags & F_SHROBJ);
00657 
00658 #if 0
00659    if (hdr.f_opthdr == 0)
00660       cout << "no aout header" << endl;
00661    if (hdr.f_opthdr == _AOUTHSZ_SHORT)
00662       cout << "short header" << endl;
00663 #endif
00664 
00665    // -------------------------------------------------------------------------
00666    // Read and process optional (a.out) header.
00667    //
00668    if (!fo_->read(&aout, hdr.f_opthdr))
00669       PARSE_AOUT_DIE("Reading a.out header", 49);
00670 
00671    uint64_t text_start, tsize;
00672    uint64_t data_start, dsize;
00673    uint64_t entry;
00674 
00675    if (is64) {
00676       text_start = aout.o_text_start64;
00677       data_start = aout.o_data_start64;
00678       tsize = aout.o_tsize64;
00679       dsize = aout.o_dsize64;
00680       entry = aout.o_entry64;
00681 
00682    } else {
00683       text_start = aout.o_text_start32;
00684       data_start = aout.o_data_start32;
00685       tsize = aout.o_tsize32;
00686       dsize = aout.o_dsize32;
00687       entry = aout.o_entry32;
00688    }
00689 
00690    scnh_base = (unsigned char *)fo_->ptr();
00691    if (!scnh_base)
00692       PARSE_AOUT_DIE("Reading section headers", 49);
00693    
00694    fo_->seek((is64 ? SCNHSZ_64 : SCNHSZ_32) * hdr.f_nscns);
00695    //if binary is not stripped 
00696 
00697    if ( symptr ) {
00698       fo_->set(offset + symptr);
00699       symbols = (struct syment *) fo_->ptr();
00700       fo_->seek(nsyms * SYMESZ);
00701        
00702       if (!symbols)
00703          PARSE_AOUT_DIE("Reading symbol table", 49);
00704    }
00705 
00706    // Consistency check
00707    if (hdr.f_opthdr == (is64 ? _AOUTHSZ_EXEC_64 : _AOUTHSZ_EXEC_32))
00708    {
00709       // complete aout header present
00710       if ( text_start != SCNH_PADDR(aout.o_sntext-1))
00711          PARSE_AOUT_DIE("Checking text address", 49);
00712       if ( data_start != SCNH_PADDR(aout.o_sndata-1))
00713          PARSE_AOUT_DIE("Checking data address", 49);
00714       if ( tsize != SCNH_SIZE(aout.o_sntext-1)) 
00715          PARSE_AOUT_DIE("Checking text size", 49);
00716       if ( dsize != SCNH_SIZE(aout.o_sndata-1))
00717          PARSE_AOUT_DIE("Checking data size", 49);
00718    }
00719    /* else if(hdr.f_opthdr == _AOUTHSZ_SHORT)
00720       {
00721       if ( text_start != SCNH_PADDR(aout.o_sntext-1))
00722       PARSE_AOUT_DIE("Checking text address", 49);
00723       if ( data_start != SCNH_PADDR(aout.o_sndata-1))
00724       PARSE_AOUT_DIE("Checking data address", 49);
00725       if ( tsize != SCNH_SIZE(aout.o_sntext-1))
00726       PARSE_AOUT_DIE("Checking text size", 49);
00727       if ( dsize != SCNH_SIZE(aout.o_sndata-1))
00728       PARSE_AOUT_DIE("Checking data size", 49);
00729       }*/
00730    if (hdr.f_opthdr !=  0)
00731       entryAddress_ = entry;
00732 
00733    /*
00734     * Get the string pool, if there is one
00735     */
00736    if ( nsyms ) 
00737    {
00738       // We want to jump past the symbol table...
00739       if (!fo_->set(offset + symptr + (nsyms*SYMESZ)))
00740          PARSE_AOUT_DIE("Could not seek to string pool", 49);
00741 
00742       stringPool = (char *)fo_->ptr();
00743       if (!stringPool)
00744          PARSE_AOUT_DIE("Getting pointer to string pool", 49);
00745 
00746       // First 4 bytes is the length; this is included in the string pool pointer
00747       Offset stringPoolSize;
00748       fo_->read(&stringPoolSize, 4);
00749    }
00750 
00751    /* find the text section such that we access the line information */
00752    nlines_ = 0;
00753    no_of_sections_ = hdr.f_nscns;
00754    foundLoader = false;
00755    foundData = false;
00756    
00757    for (i=0; i < hdr.f_nscns; i++)
00758    {
00759       if(SCNH_FLAGS(i) & STYP_DATA)
00760       {
00761          dataSecNo = i;
00762          foundData = true;
00763       }
00764       else if(SCNH_FLAGS(i) & STYP_LOADER)
00765       {
00766          loaderSecNo = i;
00767          foundLoader = true;
00768       }    
00769       if (SCNH_FLAGS(i) & STYP_TEXT) {
00770          textSecNo = i;
00771          foundText = true;
00772          nlines_ = SCNH_NLNNO(i);
00773 
00774          /* if there is overflow in the number of lines */
00775          if (!is64 && nlines_ == 65535)
00776             for (j=0; j < hdr.f_nscns; j++)
00777                if ((SCNH_FLAGS(j) & STYP_OVRFLO) &&
00778                    ((long) SCNH_NLNNO(j) == (i+1))) {
00779                   nlines_ = (unsigned int)(SCNH_VADDR(j));
00780                   break;
00781                }
00782 
00783          /* There may not be any line information. */
00784          if (nlines_ == 0)
00785             continue;
00786 
00787          /* read the line information table */
00788          if (!fo_->set(offset + SCNH_LNNOPTR(i)))
00789             PARSE_AOUT_DIE("Seeking to line information table", 49);
00790          lines = (struct lineno *)fo_->ptr();
00791          if (!lines)
00792             PARSE_AOUT_DIE("Reading line information table", 49);
00793          fo_->seek(nlines_ * (is64 ? LINESZ_64 : LINESZ_32));
00794            
00795          linesfdptr = offset + SCNH_LNNOPTR(i);
00796          //break;
00797       }
00798       if (SCNH_FLAGS(i) & STYP_BSS) {
00799          bss_size_ = SCNH_SIZE(i);
00800       }
00801       if (SCNH_FLAGS(i) & STYP_EXCEPT) {
00802           exceptSecNo = i;
00803          exceptab_size_ = SCNH_SIZE(i);
00804 #if 0
00805          if (!fo_->set(offset + SCNH_SCNPTR(i)))
00806             PARSE_AOUT_DIE("Seeking to exception table", 49);
00807          exceptab_ = (struct exceptab *)fo_->ptr();
00808          if (!exceptab_)
00809             PARSE_AOUT_DIE("Reading line information table", 49);
00810          if (!fillExceptionTable(exceptab_, exceptab_size_, is64, symbols))
00811          {
00812              fprintf(stderr, "%s[%d]:  WARNING:  failed to read exceptions\n", FILE__, __LINE__);
00813          }
00814 #endif
00815       }
00816    }
00817 
00818    if (alloc_syms)
00819       for (i=0; i < hdr.f_nscns; i++) {
00820           // the XCOFF spec says that only text and data sections are loaded
00821           Region::RegionType regionType = getRegionType(SCNH_FLAGS(i));
00822           bool isLoadable = regionType == Region::RT_TEXT || 
00823                             regionType == Region::RT_DATA;
00824           regions_.push_back(new Region(i, SCNH_NAME(i), SCNH_PADDR(i), SCNH_SIZE(i), SCNH_PADDR(i), SCNH_SIZE(i), (char *)fo_->getPtrAtOffset(offset+SCNH_SCNPTR(i)), getRegionPerms(SCNH_FLAGS(i)), regionType, isLoadable));
00825 //         regions_.push_back(new Section(i, SCNH_NAME(i), SCNH_PADDR(i),
00826 //                  fo_->getPtrAtOffset(offset+SCNH_SCNPTR(i)), SCNH_SIZE(i)));
00827          //fprintf(stderr, "%s[%d]:  section named %s\n", FILE__, __LINE__, SCNH_NAME(i));
00828       }
00829 
00830    // Time to set up a lot of variables.
00831    // code_ptr_: a pointer to the text segment
00832    // code_off_: Subtracted from an offset before lookup occurs
00833    // code_len_: Size of text in bytes
00834    // text_reloc_: the amount to add to the "base address" given us by the system.
00835 
00836    // data_ptr_: a pointer to the data segment
00837    // data_off_: subtracted from a data offset before lookup occurs
00838    // data_len_: size of data in bytes.
00839    // data_reloc_: the amount to add to the "base address" given us by the system.
00840 
00841    // Temporaries: the file is loaded read-only and thus we can't modify it.
00842    //Offset fileTextOffset = roundup4(SCNH_SCNPTR(aout.o_sntext-1));
00843    //Offset fileDataOffset = roundup4(SCNH_SCNPTR(aout.o_sndata-1));
00844 
00845    Offset fileTextOffset;
00846    Offset fileDataOffset;
00847 
00848    fileDataOffset = foundData ? roundup4(SCNH_SCNPTR(dataSecNo)) : (Offset) -1;
00849    fileTextOffset = foundText ? roundup4(SCNH_SCNPTR(textSecNo)) : (Offset) -1;
00850    code_off_ = foundText ? roundup4(SCNH_PADDR(textSecNo)) : (Offset) -1;
00851    data_off_ = foundData ? roundup4(SCNH_PADDR(dataSecNo)) : (Offset) -1;
00852    code_len_ = foundText ? SCNH_SIZE(textSecNo) : 0;
00853    data_len_ = foundData ? SCNH_SIZE(dataSecNo) : 0;
00854    text_reloc_ = fileTextOffset;
00855    data_reloc_ = fileDataOffset;
00856 
00857    if (foundText) 
00858    {
00859       if (!fo_->set(fileTextOffset + offset))
00860          PARSE_AOUT_DIE("Seeking to start of text segment", 49);
00861       code_ptr_ = (char *)fo_->ptr();
00862       if (!code_ptr_)
00863          PARSE_AOUT_DIE("Reading text segment", 49);
00864    }
00865    else
00866       code_ptr_ = NULL;
00867       
00868    if(foundData)
00869    {
00870       if (!fo_->set(fileDataOffset + offset))
00871          PARSE_AOUT_DIE("Seeking to start of data segment", 49);
00872       data_ptr_ = (char *)fo_->ptr();
00873       if (!data_ptr_)
00874          PARSE_AOUT_DIE("Reading data segment", 49);
00875    }
00876    else
00877       data_ptr_ = NULL;
00878 
00879    if(foundLoader)
00880    {
00881     //FIND LOADER INFO!
00882     loader_off_ = SCNH_SCNPTR(loaderSecNo);
00883     //loader_off_ = SCNH_SCNPTR(aout.o_snloader-1);
00884     loadAddress_ = loader_off_;
00885     loader_len_ = SCNH_SIZE(loaderSecNo); 
00886     //loader_len_ = SCNH_SIZE(aout.o_snloader-1);
00887    }    
00888 
00889    // And some debug output
00890    object_printf("Text offset in file: 0x%x (0x%x + 0x%x), virtual address 0x%x, size %d (0x%x) bytes\n",
00891                  fileTextOffset + offset, fileTextOffset, offset, code_off_, code_len_, code_len_);
00892    object_printf("Data offset in file: 0x%x (0x%x + 0x%x), virtual address 0x%x, size %d (0x%x) bytes\n",
00893                  fileDataOffset + offset, fileDataOffset, offset, data_off_, data_len_, data_len_);
00894    
00895    foundDebug = false;
00896 
00897    // Find the debug symbol table.
00898    for (i=0; i < hdr.f_nscns; i++)
00899    {
00900       if (SCNH_FLAGS(i) & STYP_DEBUG) 
00901       {
00902          foundDebug = true;
00903          break;
00904       }
00905    }
00906    if ( foundDebug ) 
00907    {
00908       stabs_ = (void *) symbols;
00909       nstabs_ = nsyms;
00910       stringpool_ = (void *) stringPool;
00911       if( nsyms ) {
00912          if (!fo_->set(SCNH_SCNPTR(i) + offset))
00913             PARSE_AOUT_DIE("Seeking to initialized debug section", 49);
00914 
00915          stabstr_ = fo_->ptr();
00916          if (!stabstr_) 
00917             PARSE_AOUT_DIE("Reading initialized debug section", 49);
00918       }
00919        
00920       linesptr_ = (void *) lines;
00921       linesfdptr_ = linesfdptr + offset;
00922    }
00923    else
00924    {
00925       // Not all files have debug information. Libraries tend not to.
00926       stabs_ = NULL;
00927       nstabs_ = 0;
00928       stringpool_ = NULL;
00929       stabstr_ = NULL;
00930       linesptr_ = NULL;
00931       nlines_ = 0;
00932       linesfdptr_ = 0;
00933    }
00934    
00935    no_of_symbols_ = nsyms;
00936    // Now the symbol table itself:
00937    if (alloc_syms) {
00938        object_printf("%d symbols present in file\n", nsyms);
00939    for (i=0; i < (signed)nsyms; i++) 
00940    {
00941       /* do the pointer addition by hand since sizeof(struct syment)
00942        *   seems to be 20 not 18 as it should be. Mmm alignment. */
00943       sym = (struct syment *) (((char *)symbols) + i * SYMESZ);
00944       unsigned long sym_value = (is64 ? sym->n_value64 : sym->n_value32);
00945 
00946       if (sym->n_sclass & DBXMASK) {
00947           object_printf("Skipping DBXMASK symbol %s\n", name.c_str());
00948           continue;
00949       }
00950 
00951       secno = sym->n_scnum;
00952       if ((C_WEAKEXT && (sym->n_sclass == C_WEAKEXT)) ||
00953           (sym->n_sclass == C_HIDEXT) || 
00954           (sym->n_sclass == C_EXT) ||
00955           (sym->n_sclass == C_FILE)) {
00956 
00957          if (is64) {
00958             name = std::string( &stringPool[ sym->n_offset64 ] );
00959          } else if (!sym->n_zeroes32) {
00960             name = std::string( &stringPool[ sym->n_offset32 ] );
00961          } else {
00962             char tempName[9];
00963             memset(tempName, 0, 9);
00964             strncpy(tempName, sym->n_name32, 8);
00965             name = std::string(tempName);
00966          }
00967       }
00968 
00969       unsigned long size = 0;
00970       if ((C_WEAKEXT && (sym->n_sclass == C_WEAKEXT)) ||
00971           (sym->n_sclass == C_HIDEXT) || 
00972           (sym->n_sclass == C_EXT)) {
00973          if (sym->n_sclass == C_HIDEXT) {
00974             linkage = Symbol::SL_LOCAL;
00975          } else {
00976             linkage = Symbol::SL_GLOBAL;
00977          }
00978 
00979          if (sym->n_scnum == aout.o_sntext) {
00980             type = Symbol::ST_FUNCTION;
00981             value = sym_value;
00982             /*
00983               fprintf(stderr, "Text symbol %s, at 0x%lx\n",
00984               name.c_str(), value);
00985             */
00986          } else {
00987             // bss or data
00988             csect = (union auxent *)
00989                ((char *) sym + sym->n_numaux * SYMESZ);
00990 
00991             // Bits 5-7 of x_smtyp (last three bits) hold symbol type.
00992             unsigned smtyp = csect->x_csect.x_smtyp & 0x3;
00993             if (smtyp == XTY_SD || smtyp == XTY_CM) {
00994                size = csect->x_csect.x_scnlen32;
00995                if (is64) size &= csect->x_csect.x_scnlen_hi64 * 0x10000;
00996             }
00997 
00998             if (csect->x_csect.x_smclas == XMC_TC0) 
00999             {
01000                //if (toc_offset);
01001                //logLine("Found more than one XMC_TC0 entry.");
01002                toc_offset = sym_value;
01003                object_printf("Found TOC offset: 0x%lx\n", toc_offset);
01004                continue;
01005             }
01006 
01007             if ((csect->x_csect.x_smclas == XMC_TC) ||
01008                 (csect->x_csect.x_smclas == XMC_DS)) {
01009                // table of contents related entry not a real symbol.
01010                //dump << " toc entry -- ignoring" << endl;
01011                 object_printf("TOC entry (%s/%d), ignoring (%s)\n", name.c_str(),sym_value,
01012                               (csect->x_csect.x_smclas == XMC_TC) ? "TC" : "DS");
01013                 continue;
01014             }
01015             type = Symbol::ST_OBJECT;
01016 
01017             if (foundData && sym_value < SCNH_PADDR(dataSecNo)) {
01018                // Very strange; skip
01019                 object_printf("Skipping odd case of data symbol not in data section (%s)\n", name.c_str());
01020                 continue;
01021             }
01022 
01023             value = sym_value;
01024 
01025             // Shift it back down; data_org will be added back in later.
01026 
01027             //fprintf(stderr, "Sym %s, at 0x%lx\n",
01028             //      name.c_str(), value);
01029          }
01030 
01031          // skip .text entries
01032          if (name == ".text")  {
01033              object_printf("Skipping .text symbol\n");
01034              continue;
01035          }
01036        
01037          if (name[0] == '.' ) {
01038             // XXXX - Hack to make names match assumptions of symtab.C
01039             name = std::string(name.c_str()+1);
01040          }
01041          else if (type == Symbol::ST_FUNCTION) {
01042             // text segment without a leading . is a toc item
01043             //dump << " (no leading . so assuming toc item & ignoring)" << endl;
01044              object_printf("Skipping text symbol without leading .\n");
01045              continue;
01046          }
01047        
01048          if (type == Symbol::ST_FUNCTION) {
01049             // Find address of inst relative to code_ptr_, instead of code_off_
01050            
01051             size = 0;
01052             Word *inst = (Word *)((char *)code_ptr_ + value - code_off_);
01053             // If the instruction we got is a unconditional branch, flag it.
01054             // I've seen that in some MPI functions as a poor man's aliasing
01055             instructUnion instr;
01056             instr.raw = inst[0];
01057             if ((instr.iform.op == Bop) &&
01058                 (instr.iform.lk == 0))
01059                size = 4; // Unconditional branch at the start of the func, no link
01060             else {
01061                while (inst[size] != 0) size++;
01062                size *= sizeof(Word);
01063             }
01064 
01065             // AIX linkage code appears as a function. Since we don't remove it from
01066             // the whereaxis yet, I append a _linkage tag to each so that they don't
01067             // appear as duplicate functions
01068 
01069             // 2/07 rutar - There are some good usages for having the _linkage functions
01070             // appear (such as distinguishing program information by the names of 
01071             // functions being callsed so I put these functions back in the mix ...
01072             // the name "_linkage" is appended so that the difference is noted
01073 
01074             // Template for linkage functions:
01075             // l      r12,<offset>(r2) // address of call into R12
01076             // st     r2,20(r1)        // Store old TOC on the stack
01077             // l      r0,0(r12)        // Address of callee func
01078             // l      r2,4(r12)        // callee TOC
01079             // mtctr  0                // We keep the LR static, use the CTR
01080             // bctr                    // non-saving branch to CTR
01081 
01082             if (size == 0x18) {
01083                // See if this is linkage code, and if so skip (so it doesn't go in the
01084                // list of functions). 
01085                Word *inst = (Word *)((char *)code_ptr_ + value - code_off_);
01086                instructUnion lr12, lr0, bctr;
01087                lr12.raw = inst[0];
01088                lr0.raw = inst[2];
01089                bctr.raw = inst[5];
01090 
01091                if ((lr12.dform.op == Lop) && (lr12.dform.rt == 12) && (lr12.dform.ra == 2) &&
01092                    (lr0.dform.op == Lop) && (lr0.dform.rt == 0) &&
01093                    (lr0.dform.ra == 1 || lr0.dform.ra == 12) &&
01094                    (bctr.xlform.op == BCLRop) && (bctr.xlform.xo == BCCTRxop))
01095                {
01096                   int sourceSize = strlen(name.c_str());
01097                   char tempLinkName[sourceSize + 9];
01098                   memset(tempLinkName, 0, sourceSize+8);
01099                   strncpy(tempLinkName, name.c_str(),sourceSize);
01100                   strcat(tempLinkName,"_linkage"); 
01101                   name = std::string(tempLinkName);
01102                }
01103             }
01104          }
01105 
01106          Region *sec;
01107          if(secno >= 1 && secno <= regions_.size())
01108             sec = regions_[secno-1];
01109          else
01110             sec = NULL;
01111 
01112          //fprintf(stderr, "Creating new symbol: %s, %s, %d, %d, 0x%lx, %d, %d\n",
01113          //name.c_str(), modName.c_str(), type, linkage, value, sec, size);
01114 
01115          Symbol *sym = new Symbol(name, 
01116                                   type, 
01117                                   linkage, 
01118                                   Symbol::SV_DEFAULT, 
01119                                   value, 
01120                                   NULL,
01121                                   sec, 
01122                                   size);
01123        
01124          symbols_[name].push_back(sym);
01125          symsByOffset_[value].push_back(sym);
01126          symsToModules_[sym] = modName;
01127 
01128          if (symbols_.find(modName)!=symbols_.end()) {
01129             // Adjust module's address, if necessary, to ensure that it's <= the
01130             // address of this new symbol
01131            
01132             std::vector< Symbol *> & mod_symbols = symbols_[modName];
01133            
01134             Symbol *mod_symbol = mod_symbols[ 0 ];
01135 
01136             for (unsigned i = 0; i < mod_symbols.size(); i++) {
01137                 if (mod_symbols[i]->getType() == Symbol::ST_MODULE) {
01138                     mod_symbol->offset_ = value;
01139                 }
01140             }
01141          }  
01142       } else if (sym->n_sclass == C_FILE) {
01143          if (!strcmp(name.c_str(), ".file")) {
01144             int j;
01145             /* has aux record with additional information. */
01146             for (j=1; j <= sym->n_numaux; j++) {
01147                aux = (union auxent *) ((char *) sym + j * SYMESZ);
01148                if (aux->x_file._x.x_ftype == XFT_FN) {
01149                   // this aux record contains the file name.
01150                   if (!aux->x_file._x.x_zeroes) {
01151                      name = std::string(&stringPool[aux->x_file._x.x_offset]);
01152                   } else {
01153                      // x_fname is 14 bytes
01154                      char tempName[15];
01155                      memset(tempName, 0, 15);
01156                      strncpy(tempName, aux->x_file.x_fname, 14);
01157                      name = std::string(tempName);
01158                   }
01159                }
01160             }
01161          }
01162 
01163          //dump << "found module \"" << name << "\"" << endl;
01164          
01165          // Hack time. Break it down
01166          // Problem: libc and others show up as file names. So if the
01167          // file being loaded is a .a (it's a hack, remember?) use the
01168          // .a as the modName instead of the symbol we just found.
01169          std::string::size_type len = mf->pathname().length(); 
01170          if (((len>2)&&(mf->pathname().substr(len-2,2)==".a")) ||
01171              ((len>3)&&(mf->pathname().substr(len-3,3)==".so")) ||
01172              ((len>5)&&(mf->pathname().substr(len-5,5)==".so.1")))
01173             modName = mf->pathname();
01174          else if (name == "glink.s")
01175             modName = std::string("Global_Linkage");
01176          else {
01177             modName = name;
01178          }
01179          Symbol *modSym = new Symbol(modName, 
01180                                      Symbol::ST_MODULE, 
01181                                      linkage, 
01182                                      visibility,
01183                                      UINT_MAX); // dummy address for now!
01184 
01185          /* The old code always had the last module win. */
01186          if ( symbols_[modName].size() == 0 ) {
01187             symbols_[modName].push_back( modSym );
01188          } else {
01189             //  not sure if this is dangerous (anyone else have a pointer to this object?)
01190             //  but if we don't delete, or do something else, its a leak.
01191             delete (symbols_[modName][0]);
01192             symbols_[modName][0] = modSym;
01193          }
01194          
01195          continue;
01196       }
01197    }
01198    }
01199 
01200    toc_offset_ = toc_offset;
01201       
01202    code_vldS_ = code_off_;
01203    code_vldE_ = code_off_ + code_len_;
01204    data_vldS_ = data_off_;
01205    data_vldE_ = data_off_ + data_len_;
01206 
01207    return;
01208 }
01209 
01210 // Archive parsing
01211 // Libraries on AIX can be archive files. These files are distinguished
01212 // by their magic number, and come in two types: 32-bit (small) and 
01213 // 64-bit (big). The structure of an either archive file is similar:
01214 // <Archive header> (magic number, offsets)
01215 // <Member header>  (member file name)
01216 //   <member file>
01217 // <Member header>
01218 //   <member file> 
01219 // and so on. Given a member name, we scan the archive until we find
01220 // that name, at which point parse_aout is called.
01221 // The only difference between small and big archive is the size of
01222 // the archive/member header variables (12 byte vs. 20 byte).
01223 // Both archives are handled in one parsing function, which keys off
01224 // the magic number of the archive.
01225 // Note: all data in the headers is in ASCII.
01226 
01227 // More macros
01228 #define PARSE_AR_DIE(errType, errCode) { \
01229       sprintf(errorLine, "Error parsing archive file %s: %s\n", \
01230               mf->pathname().c_str(), errType); \
01231       err_func_(errType); \
01232       return; \
01233       }
01234    
01235 void Object::load_archive(bool is_aout, bool alloc_syms) 
01236 {
01237     xcoffArchive *archive;
01238     
01239     // Determine archive type
01240     // Start at the beginning...
01241     if (!fo_->set(0))
01242         PARSE_AR_DIE("Seeking to file start", 49);
01243 
01244     char magic_number[SAIAMAG];
01245     if (!fo_->read(magic_number, SAIAMAG))
01246         PARSE_AR_DIE("Reading magic number", 49);
01247 
01248     if (!strncmp(magic_number, AIAMAG, SAIAMAG))
01249         archive = (xcoffArchive *) new xcoffArchive_32(fo_);
01250     else if (!strncmp(magic_number, AIAMAGBIG, SAIAMAG))
01251         archive = (xcoffArchive *) new xcoffArchive_64(fo_);
01252     else
01253         PARSE_AR_DIE("Unknown magic number", 49);
01254     
01255     if (archive->read_arhdr())
01256         PARSE_AR_DIE("Reading file header", 49);
01257     
01258     bool found = false;
01259     
01260     while (archive->next_offset != 0)
01261     {
01262         if (archive->read_mbrhdr())
01263             PARSE_AR_DIE("Reading member header", 49);
01264 
01265         if (!strncmp(archive->member_name,
01266                      member_.c_str(),
01267                      archive->member_len - 1)) 
01268  {
01269             found = true;
01270             break; // Got the right one
01271         }
01272     }
01273     if (found) // found the right member
01274     {
01275             // At this point, we should be able to read the a.out
01276             // file header.
01277             parse_aout(archive->aout_offset, is_aout, alloc_syms);
01278     }
01279     else
01280     {
01281      //Return error for not an ordinary file. Should have had a membername/offset if it was one.
01282  //probably reached here because openFile() was called instead of openArchive.
01283     }
01284 }
01285 
01286 // This is our all-purpose-parse-anything function. 
01287 // Takes a file and determines from the first two bytes the
01288 // file type (archive or a.out). Assumes that two bytes are
01289 // enough to identify the file format. 
01290 
01291 void Object::load_object(bool alloc_syms)
01292 {
01293    // Load in an object (archive, object, .so)
01294 
01295    assert(fo_);
01296 
01297    unsigned char magic_number[2];
01298    unsigned short f_flags;
01299 
01300    if (!fo_->set(0)) {
01301       sprintf(errorLine, "Error reading file %s\n", 
01302             mf->pathname().c_str());
01303       err_func_(errorLine); 
01304       //statusLine(errorLine);
01305       //showErrorCallback(49,(const char *) errorLine);
01306       return;
01307    }
01308 
01309    if (!fo_->read((void *)magic_number, 2)) {
01310       sprintf(errorLine, "Error reading file %s\n", 
01311             mf->pathname().c_str());
01312       err_func_(errorLine); 
01313       //statusLine(errorLine);
01314       //showErrorCallback(49,(const char *) errorLine);
01315       return;
01316    }
01317 
01318    if (!fo_->set(18)){
01319       sprintf(errorLine, "Error moving to the offset 18 file %s\n", 
01320             mf->pathname().c_str());
01321       err_func_(errorLine); 
01322       //statusLine(errorLine);
01323       //showErrorCallback(49,(const char *) errorLine);
01324    }   
01325 
01326    if (!fo_->read((void *)(&f_flags), 2)) {
01327       sprintf(errorLine, "Error reading file %s\n", 
01328             mf->pathname().c_str());
01329       err_func_(errorLine); 
01330       //statusLine(errorLine);
01331       //showErrorCallback(49,(const char *) errorLine);
01332       return;
01333    }
01334 
01335     if (magic_number[0] == 0x01) {
01336         if (magic_number[1] == 0xdf ||
01337         magic_number[1] == 0xef ||
01338         magic_number[1] == 0xf7)
01339     {
01340         parse_aout(0, is_aout_, alloc_syms);
01341     }
01342     }
01343     else if (magic_number[0] == '<') // archive of some sort
01344     {
01345     // What?  Why aren't we calling load_archive here?
01346     // load_archive(true, alloc_syms);
01347     is_aout_ = !(f_flags & F_SHROBJ);
01348     parse_aout(offset_, true, alloc_syms);
01349     }   
01350     else {// Fallthrough
01351         sprintf(errorLine, "Bad magic number in file %s\n",
01352                 mf->pathname().c_str());
01353     err_func_(errorLine);
01354         //statusLine(errorLine);
01355         //showErrorCallback(49,(const char *) errorLine);
01356     }
01357     return;
01358 }
01359 
01360 // There are three types of "shared" files:
01361 // archives (made with ar, end with .a)
01362 // objects (ld -bM:SRE)
01363 // new-style shared objects (.so)
01364 // load_shared_object determines from magic number which to use
01365 // since static objects are just a.outs, we can use the same
01366 // function for all
01367 
01368 Object::Object(const Object& obj) :
01369    AObject(obj) 
01370 {
01371    fo_ = fileOpener::openFile((void *)obj.fo_->mem_image(), obj.fo_->size());
01372 }
01373 
01374 
01375 Object::Object(MappedFile *mf_, MappedFile *mfd, bool, void (*err_func)(const char *), Offset offset, bool alloc_syms) :
01376    AObject(mf_, mfd, err_func), offset_(offset)
01377 {    
01378    fo_ = fileOpener::openFile((void *)mf_->base_addr(), mf_->size());
01379    fo_->set_file(mf_->filename());
01380    load_object(alloc_syms); 
01381 }
01382 
01383 Object::Object(MappedFile *mf_, MappedFile *mfd, std::string &member_name, Offset offset, void (*err_func)(const char *), void *) :
01384    AObject(mf_, mfd, err_func), member_(member_name), offset_(offset)
01385 {    
01386    fo_ = fileOpener::openFile((void *)mf_->base_addr(), mf_->size());
01387    fo_->set_file(member_name);
01388    load_object(true); 
01389 }
01390 
01391 Object& Object::operator=(const Object& obj) 
01392 {
01393    (void) AObject::operator=(obj);
01394    fo_ = fileOpener::openFile((void *)obj.fo_->mem_image(), obj.fo_->size());
01395    return *this;
01396 }
01397 
01398 
01399 void Object::get_stab_info(char *&stabstr, int &nstabs, void *&stabs, char *&stringpool) const {
01400    stabstr = (char *) stabstr_;
01401    nstabs = nstabs_;
01402    stabs = stabs_;
01403    stringpool = (char *) stringpool_;
01404 }
01405 
01406 //
01407 // parseCompilerType - parse for compiler that was used to generate object
01408 // return true for "native" compiler
01409 //
01410 //      XXX - This really should be done on a per module basis
01411 //
01412 bool parseCompilerType(Object *objPtr) 
01413 {
01414     bool is64 = (objPtr->getAddressWidth() == 8);
01415     SYMENT *syms;
01416     int stab_nsyms;
01417     char *stringPool;
01418     union auxent *aux;
01419     char *stabstr=NULL;
01420     void *syms_void = NULL;
01421 
01422     objPtr->get_stab_info(stabstr, stab_nsyms, syms_void, stringPool);
01423     syms = static_cast<SYMENT *>(syms_void);
01424     for (int i=0;i<stab_nsyms;i++) {
01425         SYMENT *sym = (SYMENT *) (((char *) syms) + i * SYMESZ);
01426         char tempName[15];
01427         char *compilerName = NULL;
01428 
01429         std::string name;
01430         if (sym->n_sclass == C_FILE) {
01431         if (is64) {
01432         name = std::string( &stringPool[ sym->n_offset64 ] );
01433 
01434         } else if (!sym->n_zeroes32) {
01435                 name = std::string( &stringPool[ sym->n_offset32 ] );
01436 
01437             } else {
01438                 char tempName[9];
01439                 memset(tempName, 0, 9);
01440                 strncpy(tempName, sym->n_name32, 8);
01441                 name = std::string(tempName);
01442             }
01443      if (!strcmp(name.c_str(), ".file")) {
01444                 int j;
01445                 /* has aux record with additional information. */
01446                 for (j=1; j <= sym->n_numaux; j++) {
01447       aux = (union auxent *) ((char *) sym + j * SYMESZ);
01448       if (aux->x_file._x.x_ftype == XFT_CV) {
01449                         // this aux record contains the file name.
01450                         if (!aux->x_file._x.x_zeroes) {
01451                             compilerName = &stringPool[aux->x_file._x.x_offset];
01452                         } else {
01453                             // x_fname is 14 bytes
01454                             memset(tempName, 0, 15);
01455                             strncpy(tempName, aux->x_file.x_fname, 14);
01456                             compilerName = tempName;
01457                         }
01458                     }
01459          }
01460   //
01461   // Use presence of string "IBM VisualAge C++" to confirm
01462   //   it's the IBM compiler
01463   //
01464                 const char * const compiler_strings[] = {
01465                    "IBM.*VisualAge.*C\\+\\+",
01466                    "IBM.* XL .*C\\+\\+",
01467                    NULL};
01468 
01469                 for (const char * const *cpp = compiler_strings; *cpp != NULL; cpp++) {
01470                    regex_t reg;
01471                    if (regcomp(&reg, *cpp, REG_NOSUB))
01472                       break;
01473                    if (!regexec(&reg, compilerName, 0, NULL, 0)) {
01474                       regfree(&reg);
01475                       return true;
01476                    }
01477                    regfree(&reg);
01478                 }
01479        }
01480        }
01481     }
01482     // bperr("compiler is GNU\n");
01483     return false;
01484 }
01485 
01486 // Moved to here from Dyn_Symtab.C
01487 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *)
01488 {
01489 }
01490 
01491 ObjectType Object::objType() const {
01492    return is_aout() ? obj_Executable : obj_SharedLib;
01493 }
01494 
01495 bool Object::emitDriver(Symtab * /*obj*/, 
01496       string /*fName*/, 
01497       std::vector<Symbol *>&/*allSymbols*/, 
01498       unsigned /*flag*/) 
01499 {
01500    return true;
01501 }
01502 
01503 bool AObject::getSegments(vector<Segment> &/*segs*/) const
01504 {
01505    return true;
01506 }
01507 
01508 /* FIXME: hack. */
01509 Offset trueBaseAddress = 0;
01510 
01511 void Object::parseFileLineInfo(Symtab *, dyn_hash_map<std::string, LineInformation> &li)
01512 {
01513    static set<std::string> haveParsedFileMap;
01514 
01515    //cerr << "parsing line info for file :" << mf->pathname() << endl;
01516 
01517    if ( haveParsedFileMap.count(mf->pathname()) != 0 ) { return; }
01518 
01519    // /* DEBUG */ fprintf( stderr, "%s[%d]: Considering image at 0x%lx\n", __FILE__, __LINE__, fileOnDisk );
01520 
01521    /* FIXME: hack.  Should be argument to parseLineInformation(), which should in turn be merged
01522       back into here so it can tell how far to extend the range of the last line information point. */
01523 
01524    //Offset baseAddress = obj()->codeBase();
01525 
01526    if (is_aout())
01527       trueBaseAddress = 0;
01528    else
01529       trueBaseAddress = baseAddress_;
01530 
01531    /* We haven't parsed this file already, so iterate over its stab entries. */
01532 
01533    char * stabstr = NULL;
01534    int nstabs = 0;
01535    SYMENT * syms = 0;
01536    char * stringpool = NULL;
01537    void *syms_void = NULL;
01538    get_stab_info( stabstr, nstabs, syms_void, stringpool );
01539    syms = (SYMENT *) syms_void;
01540    int nlines = 0;
01541    char * lines = NULL;
01542    unsigned long linesfdptr;
01543    get_line_info( nlines, lines, linesfdptr );
01544 
01545    /* I'm not sure why the original code thought it should copy (short) names (through here). */
01546    char temporaryName[256];
01547    char * funcName = NULL;
01548    char * currentSourceFile = NULL;
01549    char * moduleName = NULL;
01550 
01551    /* Iterate over STAB entries. */
01552 
01553    for ( int i = 0; i < nstabs; i++ ) 
01554    {
01555       /* sizeof( SYMENT ) is 20, not 18, as it should be. */
01556 
01557       SYMENT * sym = (SYMENT *)( (char *)syms + (i * SYMESZ) );
01558 
01559       /* Get the name (period) */
01560 
01561       if (is64_) 
01562       {
01563          moduleName = &stringpool[ sym->n_offset64 ];
01564       } 
01565       else if (!sym->n_zeroes32) 
01566       {
01567          moduleName = &stringpool[ sym->n_offset32 ];
01568       } 
01569       else 
01570       {
01571          memset(temporaryName, 0, 9);
01572          strncpy(temporaryName, sym->n_name32, 8);
01573          moduleName = temporaryName;
01574       }
01575 
01576       /* Extract the current source file from the C_FILE entries. */
01577 
01578       if ( sym->n_sclass == C_FILE ) 
01579       {
01580 
01581          if (!strcmp(moduleName, ".file")) 
01582          {
01583             // The actual name is in an aux record.
01584             int j;
01585 
01586             /* has aux record with additional information. */
01587 
01588             for (j=1; j <= sym->n_numaux; j++) 
01589             {
01590 
01591                union auxent *aux = (union auxent *) ((char *) sym + j * SYMESZ);
01592 
01593                if (aux->x_file._x.x_ftype == XFT_FN) 
01594                {
01595                   // this aux record contains the file name.
01596                   if (!aux->x_file._x.x_zeroes) 
01597                   {
01598                      moduleName = &stringpool[aux->x_file._x.x_offset];
01599                   } 
01600                   else 
01601                   {
01602                      // x_fname is 14 bytes
01603                      memset(temporaryName, 0, 15);
01604                      strncpy(temporaryName, aux->x_file.x_fname, 14);
01605                      moduleName = temporaryName;
01606                   }
01607                }
01608             }
01609          }
01610 
01611          currentSourceFile = strrchr( moduleName, '/' );
01612 
01613          if ( currentSourceFile == NULL ) 
01614          {
01615             currentSourceFile = moduleName; 
01616          }
01617          else 
01618          {
01619             ++currentSourceFile; 
01620          }
01621 
01622          /* We're done with this entry. */
01623          continue;
01624       }/* end if C_FILE */
01625 
01626       /* This apparently compensates for a bug in the naming of certain entries. */
01627 
01628       char * nmPtr = NULL;
01629 
01630       if (!sym->n_zeroes32 && ( ( sym->n_sclass & DBXMASK  ) ||
01631                ( sym->n_sclass == C_BINCL ) ||
01632                ( sym->n_sclass == C_EINCL ) ) ) 
01633       {
01634          long sym_offset = (is64_ ? sym->n_offset64 : sym->n_offset32);
01635 
01636          if ( sym_offset < 3 ) 
01637          {
01638             if ( sym_offset == 2 && stabstr[ 0 ] ) 
01639             {
01640                nmPtr = & stabstr[ 0 ];
01641             } 
01642             else 
01643             {
01644                nmPtr = & stabstr[ sym_offset ];
01645             }
01646          } 
01647          else if( ! stabstr[ sym_offset - 3 ] ) 
01648          {
01649             nmPtr = & stabstr[ sym_offset ];
01650          } 
01651          else 
01652          {
01653             /* has off by two error */
01654             nmPtr = & stabstr[ sym_offset - 2 ];
01655          }
01656       } 
01657       else if (is64_) 
01658       {
01659          nmPtr = &stringpool[sym->n_offset64];
01660 
01661       } 
01662       else if (!sym->n_zeroes32) 
01663       {
01664          nmPtr = &stringpool[sym->n_offset32];
01665       } 
01666       else 
01667       {
01668          // names 8 or less chars on inline, not in stabstr
01669          memset( temporaryName, 0, 9 );
01670          strncpy( temporaryName, sym->n_name32, 8 );
01671          nmPtr = temporaryName;
01672       } /* end bug compensation */
01673 
01674       /* Now that we've compensated for buggy naming, actually
01675          parse the line information. */
01676       if ( ( sym->n_sclass == C_BINCL ) ||
01677             ( sym->n_sclass == C_EINCL ) ||
01678             ( sym->n_sclass == C_FUN ) ) 
01679       {
01680 
01681          if ( funcName ) 
01682          {
01683             free( funcName );
01684             funcName = NULL;
01685          }
01686 
01687          funcName = strdup( nmPtr );
01688 
01689          std::string pdCSF( currentSourceFile );
01690          parseLineInformation(li, & pdCSF, funcName, (SYMENT *)sym, linesfdptr, lines, nlines );
01691       } /* end if we're actually parsing line information */
01692    } /* end iteration over STAB entries. */
01693 
01694    if ( funcName != NULL ) 
01695    {
01696       free( funcName );
01697    }
01698 
01699    haveParsedFileMap.insert(mf->pathname());
01700 } /* end parseFileLineInfo() */
01701 
01702 void Object::parseLineInformation(dyn_hash_map<std::string,  LineInformation> &lineInfo_, 
01703       std::string * currentSourceFile,
01704       char * symbolName,
01705       SYMENT * sym,
01706       Offset linesfdptr,
01707       char * lines,
01708       int nlines ) 
01709 {
01710    union auxent * aux;
01711    std::vector<IncludeFileInfo> includeFiles;
01712    unsigned long value = (is64_ ? sym->n_value64 : sym->n_value32);
01713    unsigned long LINESZ = (is64_ ? LINESZ_64 : LINESZ_32);
01714 
01715    /* if it is beginning of include files then update the data structure
01716       that keeps the beginning of the include files. If the include files contain
01717       information about the functions and lines we have to keep it */
01718 
01719    if ( sym->n_sclass == C_BINCL ) 
01720    {
01721       includeFiles.push_back( IncludeFileInfo( (value - linesfdptr)/LINESZ, symbolName ) );
01722    }
01723 
01724    /* similiarly if the include file contains function codes and line information
01725       we have to keep the last line information entry for this include file */
01726 
01727    else if (sym->n_sclass == C_EINCL) 
01728    {
01729       if (includeFiles.size() > 0) 
01730       {
01731          includeFiles[includeFiles.size()-1].end = (value - linesfdptr)/LINESZ;
01732       }
01733    }
01734    else if ( sym->n_sclass == C_FUN ) 
01735    {
01736       /* if the enrty is for a function than we have to collect all info
01737          about lines of the function */
01738 
01739       /* I have no idea what the old code did, except not work very well.
01740          Somebody who understands XCOFF should look at this. */
01741 
01742       int initialLine = 0;
01743       int initialLineIndex = 0;
01744       Offset funcStartAddress = 0;
01745       Offset funcEndAddress = 0;
01746 
01747       for (int j = -1; ; --j) 
01748       {
01749          SYMENT * extSym = (SYMENT *)( ((char *)sym) + (j * SYMESZ) );
01750 
01751          if ( extSym->n_sclass == C_EXT || extSym->n_sclass == C_HIDEXT ) 
01752          {
01753             aux = (union auxent *)( ((char *)extSym) + SYMESZ );
01754 
01755             initialLineIndex = (is64_ ? aux->x_fcn64.x_lnnoptr
01756                   : aux->x_sym32.x_fcnary.x_fcn.x_lnnoptr);
01757             initialLineIndex = (initialLineIndex - linesfdptr )/LINESZ;
01758 
01759             funcStartAddress = (is64_ ? extSym->n_value64 : extSym->n_value32);
01760             break;
01761          } /* end if C_EXT found */
01762 
01763       } /* end search for C_EXT */
01764 
01765       /* access the line information now using the C_FCN entry*/
01766 
01767       SYMENT * bfSym = (SYMENT *)( ((char *)sym) + SYMESZ );
01768 
01769       if ( bfSym->n_sclass != C_FCN ) 
01770       {
01771          //bperr("unable to process line info for %s\n", symbolName);
01772          return;
01773       }
01774 
01775       SYMENT * efSym = (SYMENT *)( ((char *)bfSym) + (2 * SYMESZ) );
01776 
01777       while (efSym->n_sclass != C_FCN)
01778       {
01779          efSym = (SYMENT *) ( ((Offset)efSym) + SYMESZ );
01780       }
01781 
01782       funcEndAddress = (is64_ ? efSym->n_value64 : efSym->n_value32);
01783 
01784       aux = (union auxent *)( ((char *)bfSym) + SYMESZ );
01785 
01786       initialLine = (is64_ ? aux->x_sym64.x_misc.x_lnsz.x_lnno
01787             : aux->x_sym32.x_misc.x_lnsz.x_lnno);
01788 
01789       std::string whichFile = *currentSourceFile;
01790 
01791       for (unsigned int j = 0; j < includeFiles.size(); j++) 
01792       {
01793          if ( (includeFiles[j].begin <= (unsigned)initialLineIndex) &&
01794                (includeFiles[j].end   >= (unsigned)initialLineIndex) ) 
01795          {
01796             whichFile = includeFiles[j].name;
01797             break;
01798          }
01799       } /* end iteration of include files */
01800 
01801       unsigned int previousLineNo = 0;
01802       Offset previousLineAddr = 0;
01803       bool isPreviousValid = false;
01804 
01805       /* Iterate over this entry's lines. */
01806 
01807       for (int j = initialLineIndex + 1; j < nlines; j++ ) 
01808       {
01809          LINENO * lptr = (LINENO *)( lines + (j * LINESZ) );
01810          unsigned long lnno = (is64_ ? lptr->l_lnno64 : lptr->l_lnno32);
01811          unsigned long paddr = (is64_ ? lptr->l_addr64.l_paddr : lptr->l_addr32.l_paddr);
01812 
01813          if (! lnno) 
01814          { 
01815             break; 
01816          }
01817 
01818          unsigned int lineNo = lnno + initialLine - 1;
01819          Offset lineAddr = paddr + trueBaseAddress;
01820 
01821          if (isPreviousValid) 
01822          {
01823             // /* DEBUG */ fprintf( stderr, "%s[%d]: adding %s:%d [0x%lx, 0x%lx).\n", __FILE__, __LINE__, whichFile.c_str(), previousLineNo, previousLineAddr, lineAddr );
01824 
01825             unsigned current_col = 0;
01826 
01827             //if (previousLineNo == 596 || previousLineNo == 597)
01828             //{
01829             //cerr << "FuncEndAddress: " <<setbase(16) << funcEndAddress << setbase(10) << ",totallines:" << nlines << ":" << endl;
01830             //cerr << __FILE__ <<"[" << __LINE__ << "]:inserted address range [" << setbase(16) << previousLineAddr << "," << lineAddr << ") for source " << whichFile << ":" << setbase(10) << previousLineNo << endl;
01831             //} 
01832 
01833             lineInfo_[whichFile].addLine(whichFile.c_str(), previousLineNo, current_col, previousLineAddr, lineAddr );
01834 
01835             //currentLineInformation.addLine( whichFile.c_str(), previousLineNo, current_col, previousLineAddr, lineAddr );
01836          }
01837 
01838          previousLineNo = lineNo;
01839          previousLineAddr = lineAddr;
01840          isPreviousValid = true;
01841       } /* end iteration over line information */
01842 
01843       if (isPreviousValid) 
01844       {
01845          /* Add the instruction (always 4 bytes on power) pointed at by the last entry.  We'd like to add a
01846             bigger range, but it's not clear how.  (If the function has inlined code, we won't know about
01847             it until we see the next section, so claiming "until the end of the function" will give bogus results.) */
01848          // /* DEBUG */ fprintf( stderr, "%s[%d]: adding %s:%d [0x%lx, 0x%lx).\n", __FILE__, __LINE__, whichFile.c_str(), previousLineNo, previousLineAddr, previousLineAddr + 4 );
01849 
01850          while (previousLineAddr < funcEndAddress) 
01851          {
01852             unsigned current_col = 0;
01853 
01854             //if(previousLineNo == 596 || previousLineNo == 597)
01855             //  cerr << __FILE__ <<"[" << __LINE__ << "]:inserted address range [" << setbase(16) << previousLineAddr << "," <<  previousLineAddr + 4 << ") for source " << whichFile << ":" << setbase(10) << previousLineNo << endl;
01856 
01857             lineInfo_[whichFile].addLine(whichFile.c_str(), previousLineNo, current_col, previousLineAddr,  previousLineAddr + 4);
01858 
01859             //currentLineInformation.addLine( whichFile.c_str(), previousLineNo, current_col, previousLineAddr, previousLineAddr + 4 );
01860 
01861             previousLineAddr += 4;
01862          }
01863       }
01864    } /* end if we found a C_FUN symbol */
01865 } /* end parseLineInformation() */
01866 
01867 
01868 // Gets the stab and stabstring section and parses it for types
01869 // and variables
01870 void Object::parseTypeInfo(Symtab *obj)
01871 {
01872    int i, j;
01873    int nstabs;
01874    SYMENT *syms;
01875    SYMENT *tsym;
01876    char *stringPool;
01877    char tempName[9];
01878    char *stabstr=NULL;
01879    union auxent *aux;
01880    std::string funcName;
01881    Offset staticBlockBaseAddr = 0;
01882    typeCommon *commonBlock = NULL;
01883    Symbol *commonBlockVar = NULL;
01884    std::string currentSourceFile;
01885    bool inCommonBlock = false;
01886    Module *mod = NULL;
01887 
01888    void *syms_void = NULL;
01889    get_stab_info(stabstr, nstabs, syms_void, stringPool);
01890    syms = (SYMENT *) syms_void;
01891 
01892    for (i=0; i < nstabs; i++) {
01893       /* do the pointer addition by hand since sizeof(struct syment)
01894        *   seems to be 20 not 18 as it should be */
01895       SYMENT *sym = (SYMENT *) (((char *) syms) + i * SYMESZ);
01896       unsigned long sym_value = (is64_ ? sym->n_value64 : sym->n_value32);
01897 
01898       if (sym->n_sclass == C_FILE) {
01899          char *moduleName;
01900          if (is64_) {
01901             moduleName = &stringPool[sym->n_offset64];
01902          } else if (!sym->n_zeroes32) {
01903             moduleName = &stringPool[sym->n_offset32];
01904          } else {
01905             memset(tempName, 0, 9);
01906             strncpy(tempName, sym->n_name32, 8);
01907             moduleName = tempName;
01908          }
01909          /* look in aux records */
01910          for (j=1; j <= sym->n_numaux; j++) {
01911             aux = (union auxent *) ((char *) sym + j * SYMESZ);
01912             if (aux->x_file._x.x_ftype == XFT_FN) {
01913                if (!aux->x_file._x.x_zeroes) {
01914                   moduleName = &stringPool[aux->x_file._x.x_offset];
01915                } else {
01916                   memset(moduleName, 0, 15);
01917                   strncpy(moduleName, aux->x_file.x_fname, 14);
01918                }
01919             }
01920          }
01921          currentSourceFile = std::string(moduleName);
01922          typeCollection *tc = typeCollection::getModTypeCollection(mod);
01923          assert(tc);
01924          tc->clearNumberedTypes();
01925          if(!obj->findModuleByName(mod, currentSourceFile) && 
01926             !obj->findModuleByName(mod,extract_pathname_tail(currentSourceFile)))
01927          {            
01928                mod = NULL;
01929          }
01930       }
01931 
01932       if (!mod)
01933          mod = obj->getDefaultModule();
01934 
01935       //num_active++;
01936       char *nmPtr;
01937       if (!sym->n_zeroes32 && ((sym->n_sclass & DBXMASK) ||
01938                                (sym->n_sclass == C_BINCL) ||
01939                                (sym->n_sclass == C_EINCL))) {
01940          long sym_offset = (is64_ ? sym->n_offset64 : sym->n_offset32);
01941 
01942          // Symbol name stored in STABS, not string pool.
01943          if(sym_offset < 3) {
01944             if (sym_offset == 2 && stabstr[0]) {
01945                nmPtr = &stabstr[0];
01946             } else {
01947                nmPtr = &stabstr[sym_offset];
01948             }
01949          } else if (!stabstr[sym_offset-3]) {
01950             nmPtr = &stabstr[sym_offset];
01951          } else {
01952             /* has off by two error */
01953             nmPtr = &stabstr[sym_offset-2];
01954          }
01955 #if 0    
01956          bperr("using nmPtr = %s\n", nmPtr);
01957          bperr("got n_offset = (%d) %s\n", sym_offset, &stabstr[sym_offset]);
01958          if (sym_offset>=2)
01959             bperr("got n_offset-2 = %s\n", &stabstr[sym_offset-2]);
01960          if (sym_offset>=3)
01961             bperr("got n_offset-3 = %x\n", stabstr[sym_offset-3]);
01962          if (sym_offset>=4)
01963             bperr("got n_offset-4 = %x\n", stabstr[sym_offset-4]);
01964 #endif
01965       } else if (is64_) {
01966          nmPtr = &stringPool[sym->n_offset64];
01967       } else if (!sym->n_zeroes32) {
01968          nmPtr = &stringPool[sym->n_offset32];
01969       } else {
01970          // names 8 or less chars on inline, not in stabstr
01971          memset(tempName, 0, 9);
01972          strncpy(tempName, sym->n_name32, 8);
01973          nmPtr = tempName;
01974       }
01975 
01976       if ((sym->n_sclass == C_BINCL) ||
01977             (sym->n_sclass == C_EINCL) ||
01978             (sym->n_sclass == C_FUN)) 
01979       {
01980          funcName = nmPtr;
01981          /* The call to parseLineInformation(), below, used to modify the symbols passed to it. */
01982          if (funcName.find(":") < funcName.length())
01983             funcName = funcName.substr(0,funcName.find(":"));
01984       }
01985       if (sym->n_sclass & DBXMASK) {
01986          if (sym->n_sclass == C_BCOMM) {
01987             char *commonBlockName;
01988 
01989             inCommonBlock = true;
01990             commonBlockName = nmPtr;
01991 
01992             std::vector<Symbol *>vars;
01993             if(!obj->findSymbolByType(vars, commonBlockName, Symbol::ST_OBJECT, mangledName)) {
01994                 if(!obj->findSymbolByType(vars, commonBlockName, Symbol::ST_OBJECT, prettyName))
01995                     commonBlockVar = NULL;
01996                 else
01997                     commonBlockVar = vars[0];
01998             }
01999             else
02000                commonBlockVar = vars[0];
02001 
02002             std::string cbName = commonBlockName;
02003             if (!commonBlockVar) {
02004                //bperr("unable to find variable %s\n", commonBlockName);
02005             } else {
02006                 typeCollection *tc = typeCollection::getModTypeCollection(mod);
02007                 assert(tc);
02008                commonBlock = dynamic_cast<typeCommon *>(tc->findVariableType(cbName));
02009                if (commonBlock == NULL) {
02010                   // its still the null type, create a new one for it
02011                   //TODO? ? ID for this typeCommon ?
02012                   commonBlock = new typeCommon(cbName);
02013                   tc->addGlobalVariable(cbName, commonBlock);
02014                }
02015                // reset field list
02016                commonBlock->beginCommonBlock();
02017             }
02018          } else if (sym->n_sclass == C_ECOMM) {
02019             inCommonBlock = false;
02020             if (commonBlock == NULL)
02021                continue;
02022 
02023             // copy this set of fields
02024             std::vector<Symbol *> bpmv;
02025             if (obj->findSymbolByType(bpmv, funcName, Symbol::ST_FUNCTION, mangledName) || !bpmv.size()) {
02026                string newName = "." + funcName;
02027                if (obj->findSymbolByType(bpmv, newName, Symbol::ST_FUNCTION, mangledName) || !bpmv.size()) {
02028                   //bperr("unable to locate current function %s\n", funcName.c_str());
02029                }
02030                else{
02031                   Symbol *func = bpmv[0];
02032                   commonBlock->endCommonBlock(func, (void *)commonBlockVar->getAddr());
02033                }
02034             } else {
02035                Symbol *func = bpmv[0];
02036                commonBlock->endCommonBlock(func, (void *)commonBlockVar->getAddr());
02037             }
02038 
02039             //TODO?? size for local variables??
02040             //        // update size if needed
02041             //        if (commonBlockVar)
02042             //        commonBlockVar->setSize(commonBlock->getSize());
02043             commonBlockVar = NULL;
02044             commonBlock = NULL;
02045          } else if (sym->n_sclass == C_BSTAT) {
02046             // begin static block
02047             // find the variable for the common block
02048             tsym = (SYMENT *) (((char *) syms) + sym_value * SYMESZ);
02049 
02050             // We can't lookup the value by name, because the name might have been
02051             // redefined later on (our lookup would then pick the last one)
02052 
02053             // Since this whole function is AIX only, we're ok to get this info
02054 
02055             staticBlockBaseAddr = (is64_ ? tsym->n_value64 : tsym->n_value32);
02056 
02057             /*
02058                char *staticName, tempName[9];
02059                if (is64_) {
02060                staticName = &stringPool[tsym->n_offset64];
02061                } else if (!tsym->n_zeroes32) {
02062                staticName = &stringPool[tsym->n_offset32];
02063                } else {
02064                memset(tempName, 0, 9);
02065                strncpy(tempName, tsym->n_name32, 8);
02066                staticName = tempName;
02067                }
02068 
02069                BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName);
02070                if (!staticBlockVar) {
02071                bperr("unable to find static block %s\n", staticName);
02072                staticBlockBaseAddr = 0;
02073                } else {
02074                staticBlockBaseAddr = (Offset) staticBlockVar->getBaseAddr();
02075                }
02076              */
02077 
02078          } else if (sym->n_sclass == C_ESTAT) {
02079             staticBlockBaseAddr = 0;
02080          }
02081 
02082          // There's a possibility that we were parsing a common block that
02083          // was never instantiated (meaning there's type info, but no
02084          // variable info
02085 
02086          if (inCommonBlock && commonBlock == NULL)
02087             continue;
02088 
02089          if(!mod){
02090             std::string modName = currentSourceFile;
02091             std::string fName = extract_pathname_tail(modName);
02092             if(!obj->findModuleByName(mod, fName))
02093             {
02094                modName = obj->file();
02095                if(!obj->findModuleByName(mod, modName))
02096                   continue;
02097             }
02098          }
02099 
02100          if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) {
02101             parseStabString(mod, 0, nmPtr, 
02102                   sym_value+staticBlockBaseAddr, commonBlock);
02103          } else {
02104             parseStabString(mod, 0, nmPtr, sym_value, commonBlock);
02105          }
02106       }
02107    }
02108 #if defined(TIMED_PARSE)
02109    struct timeval endtime;
02110    gettimeofday(&endtime, NULL);
02111    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02112    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02113    unsigned long difftime = lendtime - lstarttime;
02114    double dursecs = difftime/(1000 );
02115    cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< obj->exec()->file()
02116       <<") took "<<dursecs <<" msecs" << endl;
02117 #endif
02118 
02119    //  fprintf(stderr, "%s[%d]:  parseTypes for %s, num_active = %d\n", FILE__, __LINE__, mod->fileName().c_str(), num_active);
02120 }
02121 
02122 bool Region::isStandardCode()
02123 {
02124    return (getRegionPermissions() == RP_RX ||
02125            getRegionPermissions() == RP_RWX);
02126 }
02127 
02128 Dyninst::Architecture Object::getArch()
02129 {
02130    if (getAddressWidth() == 4)
02131       return Dyninst::Arch_ppc32;
02132    return Dyninst::Arch_ppc64;
02133 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1