Merge branch 'master' of git.dyninst.org:/pub/dyninst
[dyninst.git] / symtabAPI / src / Object-xcoff.C
1 /*
2  * Copyright (c) 1996-2007 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 // $Id: Object-xcoff.C,v 1.32 2008/09/20 03:56:10 jaw Exp $
33
34 // Define this before all others to insure xcoff.h is included
35 // with __XCOFF_HYBRID__ defined.
36 #define __XCOFF_HYBRID__
37
38 #include <regex.h>
39
40 #include "symtabAPI/src/Object.h"
41 #include "common/h/pathName.h"
42
43 #include "Collections.h"
44 #include "Symtab.h"
45 #include "Module.h"
46
47 using namespace Dyninst;
48 using namespace Dyninst::SymtabAPI;
49
50 #include "debug.h"
51
52 #include <procinfo.h>
53
54 #include <sys/ioctl.h>
55 #include <sys/types.h>
56 #include <fcntl.h>
57 #include <assert.h>
58 #include <stdlib.h>
59 #include <fcntl.h>
60 #include <unistd.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <sys/time.h>
64 #include <sys/reg.h>
65 #include <sys/user.h>
66 #include <sys/wait.h>
67 #include <procinfo.h> // struct procsinfo
68 #include <sys/types.h>
69 #include <sys/param.h> // PAGESIZE
70 #include <set>
71 using namespace std;
72 #include <iomanip>
73
74 #include <xcoff.h>
75 #define __AR_BIG__
76 #define __AR_SMALL__
77 #include <ar.h> // archive file format.
78 #include <scnhdr.h>
79
80 #include <dlfcn.h>
81 #include "common/h/debugOstream.h"
82
83 /* For some reason this symbol type isn't global */
84 #if !defined(C_WEAKEXT)
85 #define C_WEAKEXT 0
86 #endif
87
88 char errorLine[100];
89 std::string symt_current_func_name;
90 std::string symt_current_mangled_func_name;
91 Symbol *symt_current_func = NULL;
92
93 // 07/11/2006 giri: definitions below are borrowed from dyninstAPI/src/arch-power.h
94 // to remove the dependency on dyninst. Only the ones required have been borrowed
95
96 #define Bop             18      /* (unconditional) branch */
97 #define Lop             32      /* load (word) (aka lwz op in PowerPC) */
98 #define BCLRop          19      /* branch conditional link register */
99 #define BCCTRxop        528     /* branch conditional count register */
100
101 struct iform {            // unconditional branch +
102   unsigned op : 6;
103   signed   li : 24;
104   unsigned aa : 1;
105   unsigned lk : 1;
106
107 };
108
109 struct dform {
110     unsigned op : 6;
111     unsigned rt : 5;        // rt, rs, frt, frs, to, bf_l
112     unsigned ra : 5;
113     signed   d_or_si : 16;  // d, si, ui
114 };
115
116 struct xlform {
117   unsigned op : 6;
118   unsigned bt : 5;   // rt, bo, bf_
119   unsigned ba : 5;   // ba, bi, bfa_
120   unsigned bb : 5;
121   unsigned xo : 10;  // xo, eo
122   unsigned lk : 1;
123 };
124
125 typedef union {
126   struct iform  iform;  // branch;
127   struct dform  dform;
128   struct xlform xlform;
129   unsigned int  raw;
130 } instructUnion;
131
132 unsigned long roundup4(unsigned long val) {
133     val += 3;
134     return val - (val % 4);
135 }
136
137 // giri: Brought in here from dyninst/src/aix.C
138 typedef void *Name;
139 typedef enum { VirtualName, 
140                MemberVar, 
141                // Don't collide with our Function class...
142                Function_, 
143                MemberFunction, 
144                Class,
145                Special, 
146                Long } NameKind;
147 typedef enum { RegularNames = 0x1, ClassNames = 0x2, SpecialNames = 0x4,
148                ParameterText = 0x8, QualifierText = 0x10 } DemanglingOptions;
149
150 Name *(*P_native_demangle)(char *, char **, unsigned long) = NULL;
151 char *(*P_functionName)(Name *) = NULL;
152 char *(*P_varName)(Name *) = NULL;
153 char *(*P_text)(Name *) = NULL;
154 NameKind (*P_kind)(Name *) = NULL;
155
156 void *hDemangler = NULL;
157
158 void loadNativeDemangler() 
159 {
160    if (hDemangler) return;
161
162    P_native_demangle = NULL;
163    
164    hDemangler = dlopen("libdemangle.so.1", RTLD_LAZY|RTLD_MEMBER);
165    if (hDemangler != NULL) {
166       P_native_demangle = (Name*(*)(char*, char**, long unsigned int)) dlsym(hDemangler, "demangle");
167       //if (!P_native_demangle) 
168       //   BPatch_reportError(BPatchSerious,122,
169       //             "unable to locate function demangle in libdemangle.so.1\n");
170
171       P_functionName = (char*(*)(Name*)) dlsym(hDemangler, (const char *)"functionName");
172       //if (!P_functionName) 
173       //   BPatch_reportError(BPatchSerious,122,
174       //         "unable to locate function functionName in libdemangle.so.1\n");
175       
176       P_varName = (char*(*)(Name*)) dlsym(hDemangler, "varName");
177       //if (!P_varName) 
178       //   BPatch_reportError(BPatchSerious,122,
179       //              "unable to locate function varName in libdemangle.so.1\n");
180
181       P_kind = (NameKind(*)(Name*)) dlsym(hDemangler, "kind");
182       //if (!P_kind) 
183       //   BPatch_reportError(BPatchSerious,122,
184       //                      "unable to locate function kind in libdemangle.so.1\n");
185       
186       P_text = (char*(*)(Name*)) dlsym(hDemangler, "text");
187       //if (!P_text) 
188       //   BPatch_reportError(BPatchSerious,122,
189       //                 "unable to locate function text in libdemangle.so.1\n");
190    } 
191 }
192
193
194 extern "C" char *cplus_demangle(char *, int);
195 extern void dedemangle( char * demangled, char * dedemangled );
196
197 #define DMGL_PARAMS      (1 << 0)       /* Include function args */
198 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
199
200 char *P_cplus_demangle( const char * symbol, bool nativeCompiler, bool includeTypes ) {
201  /* If the symbol isn't from the native compiler, or the native demangler
202     isn't available, use the built-in. */
203  bool nativeDemanglerAvailable = P_native_demangle != NULL &&
204          P_text != NULL &&
205          P_varName != NULL &&
206          P_functionName != NULL;
207  if( !nativeCompiler || ! nativeDemanglerAvailable ) {
208   char * demangled = cplus_demangle( const_cast<char *>(symbol),
209      includeTypes ? DMGL_PARAMS | DMGL_ANSI : 0 );
210   if( demangled == NULL ) { return NULL; }
211
212   if( ! includeTypes ) {
213    /* De-demangling never makes a string longer. */
214    char * dedemangled = strdup( demangled );
215    assert( dedemangled != NULL );
216
217    dedemangle( demangled, dedemangled );
218    assert( dedemangled != NULL );
219
220    free( demangled );
221    return dedemangled;
222    }
223
224   return demangled;
225    } /* end if not using native demangler. */
226    else if( nativeDemanglerAvailable ) {
227   /* Use the native demangler, which apparently behaves funny. */
228   Name * name;
229   char * rest;
230   
231   /* P_native_demangle() won't actually demangled 'symbol'.
232      Find out what P_kind() of symbol it is and demangle from there. */
233   name = (P_native_demangle)( const_cast<char*>(symbol), (char **) & rest,
234    RegularNames | ClassNames | SpecialNames | ParameterText | QualifierText );
235   if( name == NULL ) { return NULL; }
236
237   char * demangled = NULL;
238   switch( P_kind( name ) ) {
239    case Function_:
240                            if (includeTypes)
241                                 demangled = (P_text)( name );
242                            else
243     demangled = (P_functionName)( name );   
244     break;
245    
246    case MemberFunction:
247     /* Doing it this way preserves the leading classnames. */
248     demangled = (P_text)( name );
249     break;
250
251    case MemberVar:
252     demangled = (P_varName)( name );
253     break;
254
255    case VirtualName:
256    case Class:
257    case Special:
258    case Long:
259     demangled = (P_text)( name );
260     break;
261    default: assert( 0 );
262    } /* end P_kind() switch */
263
264   /* Potential memory leak: no P_erase( name ) call.  Also, the
265      char *'s returned from a particular Name will be freed
266      when that name is erase()d or destroyed, so strdup if we're
267      fond of them. */
268    
269   if( ! includeTypes ) {
270    /* De-demangling never makes a string longer. */
271    char * dedemangled = strdup( demangled );
272    assert( dedemangled != NULL );
273
274    dedemangle( demangled, dedemangled );
275    assert( dedemangled != NULL );
276
277    return dedemangled;
278    }
279
280   return demangled;
281   } /* end if using native demangler. */
282  else {
283   /* We're trying to demangle a native binary but the native demangler isn't available.  Punt. */ 
284   return NULL;
285   }
286  } /* end P_cplus_demangle() */
287
288
289 // Methods to read file and ar header for both small (32-bit) and
290 // large (64-bit) archive files. This lets us have a single archive
291 // parsing method.
292 int xcoffArchive_32::read_arhdr()
293 {
294   char tmpstring[13];
295
296   if (!fo_->set(0))
297       return -1;
298   if (!fo_->read(&filehdr, sizeof(struct fl_hdr)))
299       return -1;
300   if (strncmp(filehdr.fl_magic, AIAMAG, SAIAMAG))
301     return -1;
302   strncpy(tmpstring, filehdr.fl_fstmoff, 12);
303   tmpstring[12] = 0; first_offset = atol(tmpstring);
304   if (first_offset % 2) first_offset++;
305   strncpy(tmpstring, filehdr.fl_lstmoff, 12);
306   tmpstring[12] = 0; last_offset = atol(tmpstring);
307   if (last_offset % 2) last_offset++;
308   next_offset = first_offset;
309   // Offsets are always even
310   return 0;
311 }
312
313 int xcoffArchive_64::read_arhdr()
314 {
315   char tmpstring[22];
316
317   if (!fo_->set(0))
318       return -1;
319
320   if (!fo_->read(&filehdr, sizeof(struct fl_hdr_big)))
321       return -1;
322
323   if (strncmp(filehdr.fl_magic, AIAMAGBIG, SAIAMAG))
324     return -1;
325   strncpy(tmpstring, filehdr.fl_fstmoff, 21);
326   tmpstring[21] = 0; first_offset = atol(tmpstring);
327   if (first_offset % 2) first_offset++;
328   strncpy(tmpstring, filehdr.fl_lstmoff, 21);
329   tmpstring[21] = 0; last_offset = atol(tmpstring);
330   if (last_offset % 2) last_offset++;
331   next_offset = first_offset;
332
333   return 0;
334 }
335
336 // Archive member header parsing function for 32/64-bit archives
337 // Pre:  takes an offset into the ar file which is the start point
338 //       of a member header
339 // Post: member_name contains the name of the file corresponding to
340 //       the member header
341 //       next_offset contains the offset to the next member header
342 //       or 0 if there are no members
343 //       aout_offset contains the offset to the file corresponding 
344 //       to the member name
345
346 int xcoffArchive_32::read_mbrhdr()
347 {
348     char tmpstring[13];
349     
350     if (next_offset == 0) return -1;
351
352     if (!fo_->set(next_offset))
353         return -1;
354
355     if (!fo_->read(&memberhdr, sizeof(struct ar_hdr) - 2))
356         return -1;
357
358     strncpy(tmpstring, memberhdr.ar_namlen, 4);
359     tmpstring[4] = 0; member_len = atol(tmpstring);
360     if (member_name) free(member_name);
361     member_name = (char *)malloc(member_len+1);
362     
363     if (!fo_->read(member_name, member_len))
364         return -1;
365     // Terminating null
366     member_name[member_len] = 0;
367     
368     // Set the file offset for this member
369     aout_offset = next_offset + sizeof(struct ar_hdr) + member_len;
370     if (aout_offset % 2) aout_offset += 1;
371     
372     // Fix up next_offset
373     if (next_offset == last_offset)
374         next_offset = 0; // termination condition
375     else {
376         strncpy(tmpstring, memberhdr.ar_nxtmem, 12);
377         tmpstring[12] = 0; next_offset = atol(tmpstring);
378         if (next_offset % 2) next_offset++;
379     }
380     
381     return 0;
382 }
383 // 64-bit function. Differences: structure size
384 // A lot of shared code. 
385 int xcoffArchive_64::read_mbrhdr()
386 {
387   char tmpstring[21];
388   
389   if (next_offset == 0) return -1;
390
391     if (!fo_->set(next_offset))
392         return -1;
393
394     if (!fo_->read(&memberhdr, sizeof(struct ar_hdr_big) - 2))
395         return -1;
396
397     strncpy(tmpstring, memberhdr.ar_namlen, 4);
398     tmpstring[4] = 0; member_len = atol(tmpstring);
399     if (member_name) free(member_name);
400     member_name = (char *)malloc(member_len+1);
401
402     if (!fo_->read(member_name, member_len))
403         return -1;
404     // Terminating null
405     member_name[member_len] = 0;
406     
407     // Set the file offset for this member
408     aout_offset = next_offset + sizeof(struct ar_hdr_big) + member_len;
409     if (aout_offset % 2) aout_offset += 1;
410     
411     // Fix up next_offset
412     if (next_offset == last_offset)
413         next_offset = 0; // termination condition
414     else {
415         strncpy(tmpstring, memberhdr.ar_nxtmem, 20);
416         tmpstring[20] = 0; next_offset = atol(tmpstring);
417         if (next_offset % 2) next_offset++;
418     }
419
420     return 0;
421 }
422
423 // Wrapper to handle the 1:many mapping of archives and members
424
425 std::vector<fileOpener *> fileOpener::openedFiles;
426
427 #if 0
428 fileOpener *fileOpener::openFile(const std::string &filename) {
429     // Logic: if we're opening a library, match by name. If
430     // we're opening an a.out, then we have to uniquely
431     // open each time (as we open in /proc, and exec has the
432     // same name).
433
434     if(filename.substr(0,5) != "/proc"){
435      for (unsigned i = 0; i < openedFiles.size(); i++) {
436             if (openedFiles[i]->file() == filename) {
437                 openedFiles[i]->refcount_++;
438                 return openedFiles[i];
439             }
440         }
441     }
442     
443     // Originally we were checking if its a shared Object. Now we 
444     // check if the filename does not start with a /proc
445     /*if (desc.isSharedObject()) {
446         for (unsigned i = 0; i < openedFiles.size(); i++) {
447             if (openedFiles[i]->file() == desc.file()) {
448                 openedFiles[i]->refcount_++;
449                 return openedFiles[i];
450             }
451         }
452     }*/
453     
454     // New file. Neeefty.
455     fileOpener *newFO = new fileOpener(filename);
456     assert(newFO);
457    
458     if (!newFO->open()) {
459         fprintf(stderr, "File %s\n", filename.c_str());
460         //perror("Opening file");
461         return NULL;
462     }
463     fprintf(stderr, "%s[%d]:  FIXME: DOING MMAP HERE!\n", FILE__, __LINE__);
464     abort();
465     if (!newFO->mmap()) {
466         fprintf(stderr, "File %s\n", filename.c_str());
467         //perror("mmaping file");
468         return NULL;
469     }
470     openedFiles.push_back(newFO);
471
472     return newFO;
473 }
474 #endif
475 fileOpener *fileOpener::openFile(void *ptr, unsigned size) {
476     // Logic: if we're opening a library, match by name. If
477     // we're opening an a.out, then we have to uniquely
478     // open each time (as we open in /proc, and exec has the
479     // same name).
480
481    for (unsigned i = 0; i < openedFiles.size(); i++) 
482    {
483        if ((openedFiles[i]->mem_image() == ptr) && (openedFiles[i]->size() == size)){
484            openedFiles[i]->refcount_++;
485            return openedFiles[i];
486        }
487     }
488     
489     // New file. Neeefty.
490     fileOpener *newFO = new fileOpener(ptr,size);
491     assert(newFO);
492     
493     openedFiles.push_back(newFO);
494
495     return newFO;
496 }
497
498 void fileOpener::closeFile() 
499 {
500    refcount_--;
501
502    if (refcount_ > 0) return;
503
504    // Remove us from the big list...
505    std::vector<fileOpener *>::iterator iter = openedFiles.begin();
506    for (; iter!=openedFiles.end(); iter++)
507    {
508       if (*iter == this)
509          openedFiles.erase(iter);
510    }
511
512    /*for (unsigned i = 0; i < openedFiles.size(); i++) {
513      if (openedFiles[i] == this)
514      openedFiles.erase(i));
515      }*/
516
517    if (file()!="") //only if its not a mem image
518    {
519       ::munmap(mmapStart_, size_);
520
521       ::close(fd_);
522    } 
523    mmapStart_ = 0;
524    fd_ = 0;
525    size_ = 0;
526
527    delete this;
528 }
529
530 fileOpener::~fileOpener() {
531    // Assert that we're already closed?
532    assert(fd_ == 0);
533    assert(mmapStart_ == 0);
534    assert(size_ == 0);
535 }
536
537 bool fileOpener::set(unsigned addr) 
538 {
539     //assert(fd_);     may not be present if its a mem image
540     assert(size_);
541     assert(mmapStart_);
542
543     if (addr >= size_) {
544         fprintf(stderr, "%s[%d]: Warning: attempting to set offset to address %d (0x%x) greater than size %d (0x%x)\n", FILE__, __LINE__, 
545                 addr, addr,
546                 size_, size_);
547         return false;
548     }
549     offset_ = addr;
550     return true;
551 }
552
553 bool fileOpener::read(void *buf, unsigned size) 
554 {
555     //assert(fd_); may not be present if its a mem image
556     assert(size_);
557     assert(mmapStart_);
558
559     if ((offset_ + size) >= size_)
560         return false;
561
562     memcpy(buf, ptr(), size);
563
564     offset_ += size;
565     return true;
566 }
567
568 bool fileOpener::seek(int offset) {
569     if ((((int) offset_ + offset) < 0) ||
570         ((offset_ + offset) >= size_))
571         return false;
572     offset_ += offset;
573     return true;
574 }
575
576 void *fileOpener::ptr() const {
577     // Return a pointer to the current offset
578     char *tmpPtr = (char *)mmapStart_ + offset_;
579     return (void *)tmpPtr;
580 }
581
582 void *fileOpener::getPtrAtOffset(unsigned offset) const
583 {
584     char *tmpPtr = (char *)mmapStart_ + offset;
585     return (void *)tmpPtr;
586 }
587
588 Region::perm_t getRegionPerms(unsigned flags){
589     if(flags & STYP_TEXT)
590         return Region::RP_RX;
591     else if(flags & STYP_DATA)
592         return Region::RP_RW;
593     else if(flags & STYP_DATA)
594         return Region::RP_RW;
595     else if(flags & STYP_DATA)
596         return Region::RP_RW;
597     else
598         return Region::RP_R;
599 }
600
601 Region::RegionType getRegionType(unsigned flags){
602     if(flags & STYP_TEXT)
603         return Region::RT_TEXT;
604     else if(flags & STYP_DATA)
605         return Region::RT_DATA;
606     else if(flags & STYP_DATA)
607         return Region::RT_BSS;
608     else if(flags & STYP_DATA)
609         return Region::RT_DATA;
610     else if(flags & STYP_DEBUG)
611         return Region::RT_SYMTAB;
612     else
613         return Region::RT_OTHER;
614 }
615     
616 // This function parses a 32-bit XCOFF file, either as part of an
617 // archive (library) or from an a.out file. It takes an open file
618 // descriptor from which it reads its data. In addition, it loads the
619 // data segment from the pid given in AIX_PID_HACK, the pid of the
620 // running process. We have to do this because the data segment
621 // in memory is more correct than the one on disk. Specifically, the
622 // TOC for inter-module function calls is incorrect on disk, because
623 // offsets are calculated at runtime instead of link time.
624 //
625 // int fd: file descriptor for a.out object, not closed
626 // int offset: offset to begin reading at (for archive libraries)
627
628 // File parsing error macro, assumes errorLine defined
629 #define PARSE_AOUT_DIE(errType, errCode) { \
630       fprintf(stderr,"warning:parsing a.out file %s(%s): %s \n", \
631               mf->filename().c_str(), member_.c_str(), errType); \
632       err_func_(errType); \
633       return; \
634       }
635
636 // ----------------------------------------------------------------------------
637 // 32/64-bit section header member access macros.
638 // These macros depend on the definition of variables scnh_base and is64,
639 // and are only meant to be used from within Object::parse_aout().
640 // 
641 #define SCNH_NAME(i)           (char *)(scnh_base + scn_size * (i) + s_name_off)
642 #define SCNH_PADDR(i)   ((*(uint64_t *)(scnh_base + scn_size * (i) + s_paddr_off)) >> word_shift)
643 #define SCNH_VADDR(i)   ((*(uint64_t *)(scnh_base + scn_size * (i) + s_vaddr_off)) >> word_shift)
644 #define SCNH_SIZE(i)    ((*(uint64_t *)(scnh_base + scn_size * (i) + s_size_off)) >> word_shift)
645 #define SCNH_SCNPTR(i)  ((*(uint64_t *)(scnh_base + scn_size * (i) + s_scnptr_off)) >> word_shift)
646 #define SCNH_RELPTR(i)  ((*(uint64_t *)(scnh_base + scn_size * (i) + s_relptr_off)) >> word_shift)
647 #define SCNH_LNNOPTR(i) ((*(uint64_t *)(scnh_base + scn_size * (i) + s_lnnoptr_off)) >> word_shift)
648 #define SCNH_NRELOC(i)  ((*(uint32_t *)(scnh_base + scn_size * (i) + s_nreloc_off)) >> half_shift)
649 #define SCNH_NLNNO(i)   ((*(uint32_t *)(scnh_base + scn_size * (i) + s_nlnno_off)) >> half_shift)
650 #define SCNH_FLAGS(i)    (*(uint32_t *)(scnh_base + scn_size * (i) + s_flags_off))
651
652 // ----------------------------------------------------------------------------
653 // 32/64-bit symbol table entry member access macros.
654 // These macros depend on the definition of variables scnh_base and is64,
655 // and are only meant to be used from within Object::parse_aout().
656 // 
657
658
659 void Object::parse_aout(int offset, bool /*is_aout*/, bool alloc_syms)
660 {
661    // all these vrble declarations need to be up here due to the gotos,
662    // which mustn't cross vrble initializations.  Too bad.
663    long i,j;
664    std::string name;
665    unsigned long value;
666    unsigned secno;
667    unsigned textSecNo = 0, dataSecNo = 0, loaderSecNo = 0;
668    union auxent *aux = NULL;
669    struct filehdr hdr;
670    struct aouthdr aout;
671    struct syment *sym = NULL;
672    union auxent *csect = NULL;
673    char *stringPool=NULL;
674    Symbol::SymbolType type; 
675    bool foundDebug = false;
676    bool foundLoader = false;
677    bool foundData = false;
678    bool foundText = false;
679        
680    stabs_ = NULL;
681    nstabs_ = 0;
682    stringpool_ = NULL;
683    stabstr_ = NULL;
684    linesptr_ = NULL;
685    nlines_ = 0;
686    linesfdptr_ = 0;
687
688    struct syment *symbols = NULL;
689    unsigned char *scnh_base = NULL;
690    Symbol::SymbolLinkage linkage = Symbol::SL_UNKNOWN;
691    Symbol::SymbolVisibility visibility = Symbol::SV_DEFAULT;
692    unsigned toc_offset = 0;
693    std::string modName;
694    baseAddress_ = (Offset)fo_->getPtrAtOffset(offset);
695 #if 0
696    baseAddress_ = offset + (Offset) mf->base_addr();
697 #endif
698
699    int linesfdptr=0;
700    struct lineno* lines=NULL;
701
702    // Get to the right place in the file (not necessarily 0)
703    if (!fo_->set(offset))
704       PARSE_AOUT_DIE("Seeking to correct offset", 49);
705
706    // -------------------------------------------------------------------------
707    // Read the 2 byte magic number.  Everything depends on it.
708    //
709    uint16_t magic;
710    if (!fo_->read(&magic, 2))
711       PARSE_AOUT_DIE("Reading magic number", 49);
712
713    // Determine file address width.
714    bool is64 = false;
715    if (magic == 0x1EF /* XCOFF64 on AIX4.3 or earlier */ ||
716        magic == 0x1F7 /* XCOFF64 on AIX5.1 or later   */) {
717       is64 = true;
718       addressWidth_nbytes = 8;
719
720    } else if (magic != 0x1DF /* XCOFF32 */) {
721       PARSE_AOUT_DIE("possible problem, invalid magic number", 49);
722       //bperr("Possible problem, magic number is %x, should be %x\n",
723       //       magic, 0x1df);
724    }
725    is64_ = is64;
726
727    // -------------------------------------------------------------------------
728    // Set up 32/64 bit offset variables.
729    //
730    uint64_t scn_size;
731    uint64_t s_name_off, s_paddr_off, s_vaddr_off, s_size_off, s_scnptr_off;
732    uint64_t s_relptr_off, s_lnnoptr_off, s_nreloc_off, s_nlnno_off, s_flags_off;
733    uint64_t word_shift, half_shift;
734
735    if (is64) {
736       scn_size      = SCNHSZ_64;
737       s_name_off    = offsetof(struct scnhdr, s_name);
738       s_paddr_off   = offsetof(struct scnhdr, s_paddr64);
739       s_vaddr_off   = offsetof(struct scnhdr, s_vaddr64);
740       s_size_off    = offsetof(struct scnhdr, s_size64);
741       s_scnptr_off  = offsetof(struct scnhdr, s_scnptr64);
742       s_relptr_off  = offsetof(struct scnhdr, s_relptr64);
743       s_lnnoptr_off = offsetof(struct scnhdr, s_lnnoptr64);
744       s_nreloc_off  = offsetof(struct scnhdr, s_nreloc64);
745       s_nlnno_off   = offsetof(struct scnhdr, s_nlnno64);
746       s_flags_off   = offsetof(struct scnhdr, s_flags64);
747       word_shift    = 0;
748       half_shift    = 0;
749
750    } else {
751       scn_size      = SCNHSZ_32;
752       s_name_off    = offsetof(struct scnhdr, s_name);
753       s_paddr_off   = offsetof(struct scnhdr, s_paddr32);
754       s_vaddr_off   = offsetof(struct scnhdr, s_vaddr32);
755       s_size_off    = offsetof(struct scnhdr, s_size32);
756       s_scnptr_off  = offsetof(struct scnhdr, s_scnptr32);
757       s_relptr_off  = offsetof(struct scnhdr, s_relptr32);
758       s_lnnoptr_off = offsetof(struct scnhdr, s_lnnoptr32);
759       s_nreloc_off  = offsetof(struct scnhdr, s_nreloc32);
760       s_nlnno_off   = offsetof(struct scnhdr, s_nlnno32);
761       s_flags_off   = offsetof(struct scnhdr, s_flags32);
762       word_shift    = 32;
763       half_shift    = 16;
764    }
765
766    // Begin file processing.  Re-seek to beginning of file.
767    if (!fo_->set(offset))
768       PARSE_AOUT_DIE("Seeking to correct offset", 49);
769
770    // -------------------------------------------------------------------------
771    // Read and process file header.
772    //
773    if (!fo_->read(&hdr, (is64 ? FILHSZ_64 : FILHSZ_32)))
774       PARSE_AOUT_DIE("Reading file header", 49);
775
776    uint64_t symptr, nsyms;
777    if (is64) {
778       symptr = hdr.f_symptr64;
779       nsyms  = hdr.f_nsyms64;
780
781    } else {
782       symptr = hdr.f_symptr32;
783       nsyms  = hdr.f_nsyms32;
784    }
785    is_aout_ = !(hdr.f_flags & F_SHROBJ);
786
787 #if 0
788    if (hdr.f_opthdr == 0)
789       cout << "no aout header" << endl;
790    if (hdr.f_opthdr == _AOUTHSZ_SHORT)
791       cout << "short header" << endl;
792 #endif
793
794    // -------------------------------------------------------------------------
795    // Read and process optional (a.out) header.
796    //
797    if (!fo_->read(&aout, hdr.f_opthdr))
798       PARSE_AOUT_DIE("Reading a.out header", 49);
799
800    uint64_t text_start, tsize;
801    uint64_t data_start, dsize;
802    uint64_t entry;
803
804    if (is64) {
805       text_start = aout.o_text_start64;
806       data_start = aout.o_data_start64;
807       tsize = aout.o_tsize64;
808       dsize = aout.o_dsize64;
809       entry = aout.o_entry64;
810
811    } else {
812       text_start = aout.o_text_start32;
813       data_start = aout.o_data_start32;
814       tsize = aout.o_tsize32;
815       dsize = aout.o_dsize32;
816       entry = aout.o_entry32;
817    }
818
819    scnh_base = (unsigned char *)fo_->ptr();
820    if (!scnh_base)
821       PARSE_AOUT_DIE("Reading section headers", 49);
822    
823    fo_->seek((is64 ? SCNHSZ_64 : SCNHSZ_32) * hdr.f_nscns);
824    //if binary is not stripped 
825
826    if ( symptr ) {
827       fo_->set(offset + symptr);
828       symbols = (struct syment *) fo_->ptr();
829       fo_->seek(nsyms * SYMESZ);
830        
831       if (!symbols)
832          PARSE_AOUT_DIE("Reading symbol table", 49);
833    }
834
835    // Consistency check
836    if (hdr.f_opthdr == (is64 ? _AOUTHSZ_EXEC_64 : _AOUTHSZ_EXEC_32))
837    {
838       // complete aout header present
839       if ( text_start != SCNH_PADDR(aout.o_sntext-1))
840          PARSE_AOUT_DIE("Checking text address", 49);
841       if ( data_start != SCNH_PADDR(aout.o_sndata-1))
842          PARSE_AOUT_DIE("Checking data address", 49);
843       if ( tsize != SCNH_SIZE(aout.o_sntext-1)) 
844          PARSE_AOUT_DIE("Checking text size", 49);
845       if ( dsize != SCNH_SIZE(aout.o_sndata-1))
846          PARSE_AOUT_DIE("Checking data size", 49);
847    }
848    /* else if(hdr.f_opthdr == _AOUTHSZ_SHORT)
849       {
850       if ( text_start != SCNH_PADDR(aout.o_sntext-1))
851       PARSE_AOUT_DIE("Checking text address", 49);
852       if ( data_start != SCNH_PADDR(aout.o_sndata-1))
853       PARSE_AOUT_DIE("Checking data address", 49);
854       if ( tsize != SCNH_SIZE(aout.o_sntext-1))
855       PARSE_AOUT_DIE("Checking text size", 49);
856       if ( dsize != SCNH_SIZE(aout.o_sndata-1))
857       PARSE_AOUT_DIE("Checking data size", 49);
858       }*/
859    if (hdr.f_opthdr !=  0)
860       entryAddress_ = entry;
861
862    /*
863     * Get the string pool, if there is one
864     */
865    if ( nsyms ) 
866    {
867       // We want to jump past the symbol table...
868       if (!fo_->set(offset + symptr + (nsyms*SYMESZ)))
869          PARSE_AOUT_DIE("Could not seek to string pool", 49);
870
871       stringPool = (char *)fo_->ptr();
872       if (!stringPool)
873          PARSE_AOUT_DIE("Getting pointer to string pool", 49);
874
875       // First 4 bytes is the length; this is included in the string pool pointer
876       Offset stringPoolSize;
877       fo_->read(&stringPoolSize, 4);
878    }
879
880    /* find the text section such that we access the line information */
881    nlines_ = 0;
882    no_of_sections_ = hdr.f_nscns;
883    foundLoader = false;
884    foundData = false;
885    
886    for (i=0; i < hdr.f_nscns; i++)
887    {
888       if(SCNH_FLAGS(i) & STYP_DATA)
889       {
890          dataSecNo = i;
891          foundData = true;
892       }
893       else if(SCNH_FLAGS(i) & STYP_LOADER)
894       {
895          loaderSecNo = i;
896          foundLoader = true;
897       }    
898       if (SCNH_FLAGS(i) & STYP_TEXT) {
899          textSecNo = i;
900          foundText = true;
901          nlines_ = SCNH_NLNNO(i);
902
903          /* if there is overflow in the number of lines */
904          if (!is64 && nlines_ == 65535)
905             for (j=0; j < hdr.f_nscns; j++)
906                if ((SCNH_FLAGS(j) & STYP_OVRFLO) &&
907                    ((long) SCNH_NLNNO(j) == (i+1))) {
908                   nlines_ = (unsigned int)(SCNH_VADDR(j));
909                   break;
910                }
911
912          /* There may not be any line information. */
913          if (nlines_ == 0)
914             continue;
915
916          /* read the line information table */
917          if (!fo_->set(offset + SCNH_LNNOPTR(i)))
918             PARSE_AOUT_DIE("Seeking to line information table", 49);
919          lines = (struct lineno *)fo_->ptr();
920          if (!lines)
921             PARSE_AOUT_DIE("Reading line information table", 49);
922          fo_->seek(nlines_ * (is64 ? LINESZ_64 : LINESZ_32));
923            
924          linesfdptr = offset + SCNH_LNNOPTR(i);
925          //break;
926       }
927       if (SCNH_FLAGS(i) & STYP_BSS) {
928          bss_size_ = SCNH_SIZE(i);
929       }
930    }
931
932    if (alloc_syms)
933       for (i=0; i < hdr.f_nscns; i++) {
934           // the XCOFF spec says that only text and data sections are loaded
935           Region::RegionType regionType = getRegionType(SCNH_FLAGS(i));
936           bool isLoadable = regionType == Region::RT_TEXT || 
937                             regionType == Region::RT_DATA;
938           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));
939 //         regions_.push_back(new Section(i, SCNH_NAME(i), SCNH_PADDR(i),
940 //                  fo_->getPtrAtOffset(offset+SCNH_SCNPTR(i)), SCNH_SIZE(i)));
941          //fprintf(stderr, "%s[%d]:  section named %s\n", FILE__, __LINE__, SCNH_NAME(i));
942       }
943
944    // Time to set up a lot of variables.
945    // code_ptr_: a pointer to the text segment
946    // code_off_: Subtracted from an offset before lookup occurs
947    // code_len_: Size of text in bytes
948    // text_reloc_: the amount to add to the "base address" given us by the system.
949
950    // data_ptr_: a pointer to the data segment
951    // data_off_: subtracted from a data offset before lookup occurs
952    // data_len_: size of data in bytes.
953    // data_reloc_: the amount to add to the "base address" given us by the system.
954
955    // Temporaries: the file is loaded read-only and thus we can't modify it.
956    //Offset fileTextOffset = roundup4(SCNH_SCNPTR(aout.o_sntext-1));
957    //Offset fileDataOffset = roundup4(SCNH_SCNPTR(aout.o_sndata-1));
958
959    Offset fileTextOffset;
960    Offset fileDataOffset;
961
962    fileDataOffset = foundData ? roundup4(SCNH_SCNPTR(dataSecNo)) : (Offset) -1;
963    fileTextOffset = foundText ? roundup4(SCNH_SCNPTR(textSecNo)) : (Offset) -1;
964    code_off_ = foundText ? roundup4(SCNH_PADDR(textSecNo)) : (Offset) -1;
965    data_off_ = foundData ? roundup4(SCNH_PADDR(dataSecNo)) : (Offset) -1;
966    code_len_ = foundText ? SCNH_SIZE(textSecNo) : 0;
967    data_len_ = foundData ? SCNH_SIZE(dataSecNo) : 0;
968    text_reloc_ = fileTextOffset;
969    data_reloc_ = fileDataOffset;
970
971    if (foundText) 
972    {
973       if (!fo_->set(fileTextOffset + offset))
974          PARSE_AOUT_DIE("Seeking to start of text segment", 49);
975       code_ptr_ = (char *)fo_->ptr();
976       if (!code_ptr_)
977          PARSE_AOUT_DIE("Reading text segment", 49);
978    }
979    else
980       code_ptr_ = NULL;
981       
982    if(foundData)
983    {
984       if (!fo_->set(fileDataOffset + offset))
985          PARSE_AOUT_DIE("Seeking to start of data segment", 49);
986       data_ptr_ = (char *)fo_->ptr();
987       if (!data_ptr_)
988          PARSE_AOUT_DIE("Reading data segment", 49);
989    }
990    else
991       data_ptr_ = NULL;
992
993    if(foundLoader)
994    {
995         //FIND LOADER INFO!
996         loader_off_ = SCNH_SCNPTR(loaderSecNo);
997         //loader_off_ = SCNH_SCNPTR(aout.o_snloader-1);
998         loadAddress_ = loader_off_;
999         loader_len_ = SCNH_SIZE(loaderSecNo); 
1000         //loader_len_ = SCNH_SIZE(aout.o_snloader-1);
1001    }    
1002
1003    // And some debug output
1004    object_printf("Text offset in file: 0x%x (0x%x + 0x%x), virtual address 0x%x, size %d (0x%x) bytes\n",
1005                  fileTextOffset + offset, fileTextOffset, offset, code_off_, code_len_, code_len_);
1006    object_printf("Data offset in file: 0x%x (0x%x + 0x%x), virtual address 0x%x, size %d (0x%x) bytes\n",
1007                  fileDataOffset + offset, fileDataOffset, offset, data_off_, data_len_, data_len_);
1008    
1009    foundDebug = false;
1010
1011    // Find the debug symbol table.
1012    for (i=0; i < hdr.f_nscns; i++)
1013    {
1014       if (SCNH_FLAGS(i) & STYP_DEBUG) 
1015       {
1016          foundDebug = true;
1017          break;
1018       }
1019    }
1020    if ( foundDebug ) 
1021    {
1022       stabs_ = (void *) symbols;
1023       nstabs_ = nsyms;
1024       stringpool_ = (void *) stringPool;
1025       if( nsyms ) {
1026          if (!fo_->set(SCNH_SCNPTR(i) + offset))
1027             PARSE_AOUT_DIE("Seeking to initialized debug section", 49);
1028
1029          stabstr_ = fo_->ptr();
1030          if (!stabstr_) 
1031             PARSE_AOUT_DIE("Reading initialized debug section", 49);
1032       }
1033        
1034       linesptr_ = (void *) lines;
1035       linesfdptr_ = linesfdptr + offset;
1036    }
1037    else
1038    {
1039       // Not all files have debug information. Libraries tend not to.
1040       stabs_ = NULL;
1041       nstabs_ = 0;
1042       stringpool_ = NULL;
1043       stabstr_ = NULL;
1044       linesptr_ = NULL;
1045       nlines_ = 0;
1046       linesfdptr_ = 0;
1047    }
1048    
1049    no_of_symbols_ = nsyms;
1050    // Now the symbol table itself:
1051    if (alloc_syms) {
1052        object_printf("%d symbols present in file\n", nsyms);
1053    for (i=0; i < (signed)nsyms; i++) 
1054    {
1055       /* do the pointer addition by hand since sizeof(struct syment)
1056        *   seems to be 20 not 18 as it should be. Mmm alignment. */
1057       sym = (struct syment *) (((char *)symbols) + i * SYMESZ);
1058       unsigned long sym_value = (is64 ? sym->n_value64 : sym->n_value32);
1059
1060       if (sym->n_sclass & DBXMASK) {
1061           object_printf("Skipping DBXMASK symbol %s\n", name.c_str());
1062           continue;
1063       }
1064
1065       secno = sym->n_scnum;
1066       if ((C_WEAKEXT && (sym->n_sclass == C_WEAKEXT)) ||
1067           (sym->n_sclass == C_HIDEXT) || 
1068           (sym->n_sclass == C_EXT) ||
1069           (sym->n_sclass == C_FILE)) {
1070
1071          if (is64) {
1072             name = std::string( &stringPool[ sym->n_offset64 ] );
1073          } else if (!sym->n_zeroes32) {
1074             name = std::string( &stringPool[ sym->n_offset32 ] );
1075          } else {
1076             char tempName[9];
1077             memset(tempName, 0, 9);
1078             strncpy(tempName, sym->n_name32, 8);
1079             name = std::string(tempName);
1080          }
1081       }
1082
1083       unsigned long size = 0;
1084       if ((C_WEAKEXT && (sym->n_sclass == C_WEAKEXT)) ||
1085           (sym->n_sclass == C_HIDEXT) || 
1086           (sym->n_sclass == C_EXT)) {
1087          if (sym->n_sclass == C_HIDEXT) {
1088             linkage = Symbol::SL_LOCAL;
1089          } else {
1090             linkage = Symbol::SL_GLOBAL;
1091          }
1092
1093          if (sym->n_scnum == aout.o_sntext) {
1094             type = Symbol::ST_FUNCTION;
1095             value = sym_value;
1096             /*
1097               fprintf(stderr, "Text symbol %s, at 0x%lx\n",
1098               name.c_str(), value);
1099             */
1100          } else {
1101             // bss or data
1102             csect = (union auxent *)
1103                ((char *) sym + sym->n_numaux * SYMESZ);
1104
1105             // Bits 5-7 of x_smtyp (last three bits) hold symbol type.
1106             unsigned smtyp = csect->x_csect.x_smtyp & 0x3;
1107             if (smtyp == XTY_SD || smtyp == XTY_CM) {
1108                size = csect->x_csect.x_scnlen32;
1109                if (is64) size &= csect->x_csect.x_scnlen_hi64 * 0x10000;
1110             }
1111
1112             if (csect->x_csect.x_smclas == XMC_TC0) 
1113             {
1114                //if (toc_offset);
1115                //logLine("Found more than one XMC_TC0 entry.");
1116                toc_offset = sym_value;
1117                object_printf("Found TOC offset: 0x%lx\n", toc_offset);
1118                continue;
1119             }
1120
1121             if ((csect->x_csect.x_smclas == XMC_TC) ||
1122                 (csect->x_csect.x_smclas == XMC_DS)) {
1123                // table of contents related entry not a real symbol.
1124                //dump << " toc entry -- ignoring" << endl;
1125                 object_printf("TOC entry (%s/%d), ignoring (%s)\n", name.c_str(),sym_value,
1126                               (csect->x_csect.x_smclas == XMC_TC) ? "TC" : "DS");
1127                 continue;
1128             }
1129             type = Symbol::ST_OBJECT;
1130
1131             if (foundData && sym_value < SCNH_PADDR(dataSecNo)) {
1132                // Very strange; skip
1133                 object_printf("Skipping odd case of data symbol not in data section (%s)\n", name.c_str());
1134                 continue;
1135             }
1136
1137             value = sym_value;
1138
1139             // Shift it back down; data_org will be added back in later.
1140
1141             //fprintf(stderr, "Sym %s, at 0x%lx\n",
1142             //      name.c_str(), value);
1143          }
1144
1145          // skip .text entries
1146          if (name == ".text")  {
1147              object_printf("Skipping .text symbol\n");
1148              continue;
1149          }
1150        
1151          if (name[0] == '.' ) {
1152             // XXXX - Hack to make names match assumptions of symtab.C
1153             name = std::string(name.c_str()+1);
1154          }
1155          else if (type == Symbol::ST_FUNCTION) {
1156             // text segment without a leading . is a toc item
1157             //dump << " (no leading . so assuming toc item & ignoring)" << endl;
1158              object_printf("Skipping text symbol without leading .\n");
1159              continue;
1160          }
1161        
1162          if (type == Symbol::ST_FUNCTION) {
1163             // Find address of inst relative to code_ptr_, instead of code_off_
1164            
1165             size = 0;
1166             Word *inst = (Word *)((char *)code_ptr_ + value - code_off_);
1167             // If the instruction we got is a unconditional branch, flag it.
1168             // I've seen that in some MPI functions as a poor man's aliasing
1169             instructUnion instr;
1170             instr.raw = inst[0];
1171             if ((instr.iform.op == Bop) &&
1172                 (instr.iform.lk == 0))
1173                size = 4; // Unconditional branch at the start of the func, no link
1174             else {
1175                while (inst[size] != 0) size++;
1176                size *= sizeof(Word);
1177             }
1178
1179             // AIX linkage code appears as a function. Since we don't remove it from
1180             // the whereaxis yet, I append a _linkage tag to each so that they don't
1181             // appear as duplicate functions
1182
1183             // 2/07 rutar - There are some good usages for having the _linkage functions
1184             // appear (such as distinguishing program information by the names of 
1185             // functions being callsed so I put these functions back in the mix ...
1186             // the name "_linkage" is appended so that the difference is noted
1187
1188             // Template for linkage functions:
1189             // l      r12,<offset>(r2) // address of call into R12
1190             // st     r2,20(r1)        // Store old TOC on the stack
1191             // l      r0,0(r12)        // Address of callee func
1192             // l      r2,4(r12)        // callee TOC
1193             // mtctr  0                // We keep the LR static, use the CTR
1194             // bctr                    // non-saving branch to CTR
1195
1196             if (size == 0x18) {
1197                // See if this is linkage code, and if so skip (so it doesn't go in the
1198                // list of functions). 
1199                Word *inst = (Word *)((char *)code_ptr_ + value - code_off_);
1200                instructUnion lr12, lr0, bctr;
1201                lr12.raw = inst[0];
1202                lr0.raw = inst[2];
1203                bctr.raw = inst[5];
1204
1205                if ((lr12.dform.op == Lop) && (lr12.dform.rt == 12) && (lr12.dform.ra == 2) &&
1206                    (lr0.dform.op == Lop) && (lr0.dform.rt == 0) &&
1207                    (lr0.dform.ra == 1 || lr0.dform.ra == 12) &&
1208                    (bctr.xlform.op == BCLRop) && (bctr.xlform.xo == BCCTRxop))
1209                {
1210                   int sourceSize = strlen(name.c_str());
1211                   char tempLinkName[sourceSize + 9];
1212                   memset(tempLinkName, 0, sourceSize+8);
1213                   strncpy(tempLinkName, name.c_str(),sourceSize);
1214                   strcat(tempLinkName,"_linkage"); 
1215                   name = std::string(tempLinkName);
1216                }
1217             }
1218          }
1219
1220          Region *sec;
1221          if(secno >= 1 && secno <= regions_.size())
1222             sec = regions_[secno-1];
1223          else
1224             sec = NULL;
1225
1226          object_printf("Creating new symbol: %s, %s, %d, %d, 0x%lx, %d, %d\n",
1227                        name.c_str(), modName.c_str(), type, linkage, value, sec, size);
1228
1229          Symbol *sym = new Symbol(name, modName, type, linkage, value, sec, size);
1230        
1231          symbols_[name].push_back( sym );
1232          if (symbols_.find(modName)!=symbols_.end()) {
1233             // Adjust module's address, if necessary, to ensure that it's <= the
1234             // address of this new symbol
1235            
1236             std::vector< Symbol *> & mod_symbols = symbols_[modName];
1237            
1238 #if defined( DEBUG )
1239             if( mod_symbols.size() != 1 ) {
1240                fprintf( stderr, "%s[%d]: module name has more than one symbol:\n", __FILE__, __LINE__  );
1241                for( unsigned int i = 0; i < mod_symbols.size(); i++ ) {
1242                   cerr << *(mod_symbols[i]) << endl;
1243                }
1244                fprintf( stderr, "\n" );
1245             }
1246 #endif /* defined( DEBUG ) */               
1247
1248             Symbol *mod_symbol = mod_symbols[ 0 ];
1249            
1250             if (value < mod_symbol->getAddr()) {
1251                //cerr << "adjusting addr of module " << modName
1252                //     << " to " << value << endl;
1253                mod_symbol->setAddr(value);
1254             }
1255          }  
1256       } else if (sym->n_sclass == C_FILE) {
1257          if (!strcmp(name.c_str(), ".file")) {
1258             int j;
1259             /* has aux record with additional information. */
1260             for (j=1; j <= sym->n_numaux; j++) {
1261                aux = (union auxent *) ((char *) sym + j * SYMESZ);
1262                if (aux->x_file._x.x_ftype == XFT_FN) {
1263                   // this aux record contains the file name.
1264                   if (!aux->x_file._x.x_zeroes) {
1265                      name = std::string(&stringPool[aux->x_file._x.x_offset]);
1266                   } else {
1267                      // x_fname is 14 bytes
1268                      char tempName[15];
1269                      memset(tempName, 0, 15);
1270                      strncpy(tempName, aux->x_file.x_fname, 14);
1271                      name = std::string(tempName);
1272                   }
1273                }
1274             }
1275          }
1276
1277          //dump << "found module \"" << name << "\"" << endl;
1278          
1279          // Hack time. Break it down
1280          // Problem: libc and others show up as file names. So if the
1281          // file being loaded is a .a (it's a hack, remember?) use the
1282          // .a as the modName instead of the symbol we just found.
1283          std::string::size_type len = mf->pathname().length(); 
1284          if (((len>2)&&(mf->pathname().substr(len-2,2)==".a")) ||
1285              ((len>3)&&(mf->pathname().substr(len-3,3)==".so")) ||
1286              ((len>5)&&(mf->pathname().substr(len-5,5)==".so.1")))
1287             modName = mf->pathname();
1288          else if (name == "glink.s")
1289             modName = std::string("Global_Linkage");
1290          else {
1291             modName = name;
1292          }
1293          Symbol *modSym = new Symbol(modName, modName,
1294                                      Symbol::ST_MODULE, linkage, visibility,
1295                                      UINT_MAX // dummy address for now!
1296                                      );
1297                              
1298          /* The old code always had the last module win. */
1299          if ( symbols_[modName].size() == 0 ) {
1300             symbols_[modName].push_back( modSym );
1301          } else {
1302             //  not sure if this is dangerous (anyone else have a pointer to this object?)
1303             //  but if we don't delete, or do something else, its a leak.
1304             delete (symbols_[modName][0]);
1305             symbols_[modName][0] = modSym;
1306          }
1307          
1308          continue;
1309       }
1310    }
1311    }
1312
1313    toc_offset_ = toc_offset;
1314       
1315    code_vldS_ = code_off_;
1316    code_vldE_ = code_off_ + code_len_;
1317    data_vldS_ = data_off_;
1318    data_vldE_ = data_off_ + data_len_;
1319
1320    return;
1321 }
1322
1323 // Archive parsing
1324 // Libraries on AIX can be archive files. These files are distinguished
1325 // by their magic number, and come in two types: 32-bit (small) and 
1326 // 64-bit (big). The structure of an either archive file is similar:
1327 // <Archive header> (magic number, offsets)
1328 // <Member header>  (member file name)
1329 //   <member file>
1330 // <Member header>
1331 //   <member file> 
1332 // and so on. Given a member name, we scan the archive until we find
1333 // that name, at which point parse_aout is called.
1334 // The only difference between small and big archive is the size of
1335 // the archive/member header variables (12 byte vs. 20 byte).
1336 // Both archives are handled in one parsing function, which keys off
1337 // the magic number of the archive.
1338 // Note: all data in the headers is in ASCII.
1339
1340 // More macros
1341 #define PARSE_AR_DIE(errType, errCode) { \
1342       sprintf(errorLine, "Error parsing archive file %s: %s\n", \
1343               mf->pathname().c_str(), errType); \
1344       err_func_(errType); \
1345       return; \
1346       }
1347    
1348 void Object::load_archive(bool is_aout, bool alloc_syms) 
1349 {
1350     xcoffArchive *archive;
1351     
1352     // Determine archive type
1353     // Start at the beginning...
1354     if (!fo_->set(0))
1355         PARSE_AR_DIE("Seeking to file start", 49);
1356
1357     char magic_number[SAIAMAG];
1358     if (!fo_->read(magic_number, SAIAMAG))
1359         PARSE_AR_DIE("Reading magic number", 49);
1360
1361     if (!strncmp(magic_number, AIAMAG, SAIAMAG))
1362         archive = (xcoffArchive *) new xcoffArchive_32(fo_);
1363     else if (!strncmp(magic_number, AIAMAGBIG, SAIAMAG))
1364         archive = (xcoffArchive *) new xcoffArchive_64(fo_);
1365     else
1366         PARSE_AR_DIE("Unknown magic number", 49);
1367     
1368     if (archive->read_arhdr())
1369         PARSE_AR_DIE("Reading file header", 49);
1370     
1371     bool found = false;
1372     
1373     while (archive->next_offset != 0)
1374     {
1375         if (archive->read_mbrhdr())
1376             PARSE_AR_DIE("Reading member header", 49);
1377
1378         if (!strncmp(archive->member_name,
1379                      member_.c_str(),
1380                      archive->member_len - 1)) 
1381  {
1382             found = true;
1383             break; // Got the right one
1384         }
1385     }
1386     if (found) // found the right member
1387     {
1388             // At this point, we should be able to read the a.out
1389             // file header.
1390             parse_aout(archive->aout_offset, is_aout, alloc_syms);
1391     }
1392     else
1393     {
1394      //Return error for not an ordinary file. Should have had a membername/offset if it was one.
1395  //probably reached here because openFile() was called instead of openArchive.
1396     }
1397 }
1398
1399 // This is our all-purpose-parse-anything function. 
1400 // Takes a file and determines from the first two bytes the
1401 // file type (archive or a.out). Assumes that two bytes are
1402 // enough to identify the file format. 
1403
1404 void Object::load_object(bool alloc_syms)
1405 {
1406    // Load in an object (archive, object, .so)
1407
1408    assert(fo_);
1409
1410    unsigned char magic_number[2];
1411    unsigned short f_flags;
1412
1413    if (!fo_->set(0)) {
1414       sprintf(errorLine, "Error reading file %s\n", 
1415             mf->pathname().c_str());
1416       err_func_(errorLine); 
1417       //statusLine(errorLine);
1418       //showErrorCallback(49,(const char *) errorLine);
1419       return;
1420    }
1421
1422    if (!fo_->read((void *)magic_number, 2)) {
1423       sprintf(errorLine, "Error reading file %s\n", 
1424             mf->pathname().c_str());
1425       err_func_(errorLine); 
1426       //statusLine(errorLine);
1427       //showErrorCallback(49,(const char *) errorLine);
1428       return;
1429    }
1430
1431    if (!fo_->set(18)){
1432       sprintf(errorLine, "Error moving to the offset 18 file %s\n", 
1433             mf->pathname().c_str());
1434       err_func_(errorLine); 
1435       //statusLine(errorLine);
1436       //showErrorCallback(49,(const char *) errorLine);
1437    }   
1438
1439    if (!fo_->read((void *)(&f_flags), 2)) {
1440       sprintf(errorLine, "Error reading file %s\n", 
1441             mf->pathname().c_str());
1442       err_func_(errorLine); 
1443       //statusLine(errorLine);
1444       //showErrorCallback(49,(const char *) errorLine);
1445       return;
1446    }
1447
1448     if (magic_number[0] == 0x01) {
1449         if (magic_number[1] == 0xdf ||
1450             magic_number[1] == 0xef ||
1451             magic_number[1] == 0xf7)
1452         {
1453             parse_aout(0, is_aout_, alloc_syms);
1454         }
1455     }
1456     else if (magic_number[0] == '<') // archive of some sort
1457     {
1458         // What?  Why aren't we calling load_archive here?
1459         // load_archive(true, alloc_syms);
1460         is_aout_ = !(f_flags & F_SHROBJ);
1461         parse_aout(offset_, true, alloc_syms);
1462     }   
1463     else {// Fallthrough
1464         sprintf(errorLine, "Bad magic number in file %s\n",
1465                 mf->pathname().c_str());
1466         err_func_(errorLine);
1467         //statusLine(errorLine);
1468         //showErrorCallback(49,(const char *) errorLine);
1469     }
1470     return;
1471 }
1472
1473 // There are three types of "shared" files:
1474 // archives (made with ar, end with .a)
1475 // objects (ld -bM:SRE)
1476 // new-style shared objects (.so)
1477 // load_shared_object determines from magic number which to use
1478 // since static objects are just a.outs, we can use the same
1479 // function for all
1480
1481 Object::Object(const Object& obj) :
1482    AObject(obj) 
1483 {
1484    fo_ = fileOpener::openFile((void *)obj.fo_->mem_image(), obj.fo_->size());
1485 }
1486
1487
1488 Object::Object(MappedFile *mf_, MappedFile *mfd, void (*err_func)(const char *), Offset offset, bool alloc_syms) :
1489    AObject(mf_, mfd, err_func), offset_(offset)
1490 {    
1491    loadNativeDemangler();
1492    fo_ = fileOpener::openFile((void *)mf_->base_addr(), mf_->size());
1493    fo_->set_file(mf_->filename());
1494    load_object(alloc_syms); 
1495 }
1496
1497 Object::Object(MappedFile *mf_, MappedFile *mfd, std::string &member_name, Offset offset, void (*err_func)(const char *), void *) :
1498    AObject(mf_, mfd, err_func), member_(member_name), offset_(offset)
1499 {    
1500    loadNativeDemangler();
1501    fo_ = fileOpener::openFile((void *)mf_->base_addr(), mf_->size());
1502    fo_->set_file(member_name);
1503    load_object(true); 
1504 }
1505
1506 Object& Object::operator=(const Object& obj) 
1507 {
1508    (void) AObject::operator=(obj);
1509    fo_ = fileOpener::openFile((void *)obj.fo_->mem_image(), obj.fo_->size());
1510    return *this;
1511 }
1512
1513
1514 void Object::get_stab_info(char *&stabstr, int &nstabs, void *&stabs, char *&stringpool) const {
1515    stabstr = (char *) stabstr_;
1516    nstabs = nstabs_;
1517    stabs = stabs_;
1518    stringpool = (char *) stringpool_;
1519 }
1520
1521 //
1522 // parseCompilerType - parse for compiler that was used to generate object
1523 // return true for "native" compiler
1524 //
1525 //      XXX - This really should be done on a per module basis
1526 //
1527 bool parseCompilerType(Object *objPtr) 
1528 {
1529     bool is64 = (objPtr->getAddressWidth() == 8);
1530     SYMENT *syms;
1531     int stab_nsyms;
1532     char *stringPool;
1533     union auxent *aux;
1534     char *stabstr=NULL;
1535     void *syms_void = NULL;
1536
1537     objPtr->get_stab_info(stabstr, stab_nsyms, syms_void, stringPool);
1538     syms = static_cast<SYMENT *>(syms_void);
1539     for (int i=0;i<stab_nsyms;i++) {
1540         SYMENT *sym = (SYMENT *) (((char *) syms) + i * SYMESZ);
1541         char tempName[15];
1542         char *compilerName = NULL;
1543
1544         std::string name;
1545         if (sym->n_sclass == C_FILE) {
1546             if (is64) {
1547                 name = std::string( &stringPool[ sym->n_offset64 ] );
1548
1549             } else if (!sym->n_zeroes32) {
1550                 name = std::string( &stringPool[ sym->n_offset32 ] );
1551
1552             } else {
1553                 char tempName[9];
1554                 memset(tempName, 0, 9);
1555                 strncpy(tempName, sym->n_name32, 8);
1556                 name = std::string(tempName);
1557             }
1558      if (!strcmp(name.c_str(), ".file")) {
1559                 int j;
1560                 /* has aux record with additional information. */
1561                 for (j=1; j <= sym->n_numaux; j++) {
1562       aux = (union auxent *) ((char *) sym + j * SYMESZ);
1563       if (aux->x_file._x.x_ftype == XFT_CV) {
1564                         // this aux record contains the file name.
1565                         if (!aux->x_file._x.x_zeroes) {
1566                             compilerName = &stringPool[aux->x_file._x.x_offset];
1567                         } else {
1568                             // x_fname is 14 bytes
1569                             memset(tempName, 0, 15);
1570                             strncpy(tempName, aux->x_file.x_fname, 14);
1571                             compilerName = tempName;
1572                         }
1573                     }
1574          }
1575   //
1576   // Use presence of string "IBM VisualAge C++" to confirm
1577   //   it's the IBM compiler
1578   //
1579                 const char * const compiler_strings[] = {
1580                    "IBM.*VisualAge.*C\\+\\+",
1581                    "IBM.* XL .*C\\+\\+",
1582                    NULL};
1583
1584                 for (const char * const *cpp = compiler_strings; *cpp != NULL; cpp++) {
1585                    regex_t reg;
1586                    if (regcomp(&reg, *cpp, REG_NOSUB))
1587                       break;
1588                    if (!regexec(&reg, compilerName, 0, NULL, 0)) {
1589                       regfree(&reg);
1590                       return true;
1591                    }
1592                    regfree(&reg);
1593                 }
1594        }
1595        }
1596     }
1597     // bperr("compiler is GNU\n");
1598     return false;
1599 }
1600
1601 // Moved to here from Dyn_Symtab.C
1602 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *)
1603 {
1604 }
1605
1606 ObjectType Object::objType() const {
1607    return is_aout() ? obj_Executable : obj_SharedLib;
1608 }
1609
1610 bool Object::emitDriver(Symtab * /*obj*/, 
1611       string /*fName*/, 
1612       std::vector<Symbol *>&/*allSymbols*/, 
1613       unsigned /*flag*/) 
1614 {
1615    return true;
1616 }
1617
1618 bool AObject::getSegments(vector<Segment> &/*segs*/) const
1619 {
1620    return true;
1621 }
1622
1623 /* FIXME: hack. */
1624 Offset trueBaseAddress = 0;
1625
1626 void Object::parseFileLineInfo(dyn_hash_map<std::string, LineInformation> &li)
1627 {
1628     static set<std::string> haveParsedFileMap;
1629
1630     //cerr << "parsing line info for file :" << mf->pathname() << endl;
1631
1632     if ( haveParsedFileMap.count(mf->pathname()) != 0 ) { return; }
1633
1634     // /* DEBUG */ fprintf( stderr, "%s[%d]: Considering image at 0x%lx\n", __FILE__, __LINE__, fileOnDisk );
1635
1636     /* FIXME: hack.  Should be argument to parseLineInformation(), which should in turn be merged
1637        back into here so it can tell how far to extend the range of the last line information point. */
1638  
1639     //Offset baseAddress = obj()->codeBase();
1640     if (is_aout())
1641         trueBaseAddress = 0;
1642     else
1643         trueBaseAddress = baseAddress_;
1644
1645     /* We haven't parsed this file already, so iterate over its stab entries. */
1646     char * stabstr = NULL;
1647     int nstabs = 0;
1648     SYMENT * syms = 0;
1649     char * stringpool = NULL;
1650     void *syms_void = NULL;
1651     get_stab_info( stabstr, nstabs, syms_void, stringpool );
1652     syms = (SYMENT *) syms_void;
1653     int nlines = 0;
1654     char * lines = NULL;
1655     unsigned long linesfdptr;
1656     get_line_info( nlines, lines, linesfdptr );
1657
1658     /* I'm not sure why the original code thought it should copy (short) names (through here). */
1659     char temporaryName[256];
1660     char * funcName = NULL;
1661     char * currentSourceFile = NULL;
1662     char * moduleName = NULL;
1663
1664     /* Iterate over STAB entries. */
1665     for( int i = 0; i < nstabs; i++ ) {
1666         /* sizeof( SYMENT ) is 20, not 18, as it should be. */
1667         SYMENT * sym = (SYMENT *)( (char *)syms + (i * SYMESZ) );
1668
1669         /* Get the name (period) */
1670         if (is64_) {
1671             moduleName = &stringpool[ sym->n_offset64 ];
1672         } else if (!sym->n_zeroes32) {
1673             moduleName = &stringpool[ sym->n_offset32 ];
1674         } else {
1675             memset(temporaryName, 0, 9);
1676             strncpy(temporaryName, sym->n_name32, 8);
1677             moduleName = temporaryName;
1678         }
1679
1680         /* Extract the current source file from the C_FILE entries. */
1681         if( sym->n_sclass == C_FILE ) {
1682             if (!strcmp(moduleName, ".file")) {
1683                 // The actual name is in an aux record.
1684                 int j;
1685                 /* has aux record with additional information. */
1686                 for (j=1; j <= sym->n_numaux; j++) {
1687                     union auxent *aux = (union auxent *) ((char *) sym + j * SYMESZ);
1688                     if (aux->x_file._x.x_ftype == XFT_FN) {
1689                         // this aux record contains the file name.
1690                         if (!aux->x_file._x.x_zeroes) {
1691                             moduleName = &stringpool[aux->x_file._x.x_offset];
1692                         } else {
1693                             // x_fname is 14 bytes
1694                             memset(temporaryName, 0, 15);
1695                             strncpy(temporaryName, aux->x_file.x_fname, 14);
1696                             moduleName = temporaryName;
1697                         }
1698                     }
1699                 }
1700             }
1701
1702             currentSourceFile = strrchr( moduleName, '/' );
1703             if( currentSourceFile == NULL ) { currentSourceFile = moduleName; }
1704             else { ++currentSourceFile; }
1705
1706             /* We're done with this entry. */
1707             continue;
1708         }/* end if C_FILE */
1709
1710         /* This apparently compensates for a bug in the naming of certain entries. */
1711         char * nmPtr = NULL;
1712         if (!sym->n_zeroes32 && ( ( sym->n_sclass & DBXMASK  ) ||
1713                                   ( sym->n_sclass == C_BINCL ) ||
1714                                   ( sym->n_sclass == C_EINCL ) ) ) {
1715             long sym_offset = (is64_ ? sym->n_offset64 : sym->n_offset32);
1716
1717             if( sym_offset < 3 ) {
1718                 if( sym_offset == 2 && stabstr[ 0 ] ) {
1719                     nmPtr = & stabstr[ 0 ];
1720                 } else {
1721                     nmPtr = & stabstr[ sym_offset ];
1722                 }
1723             } else if( ! stabstr[ sym_offset - 3 ] ) {
1724                 nmPtr = & stabstr[ sym_offset ];
1725             } else {
1726                 /* has off by two error */
1727                 nmPtr = & stabstr[ sym_offset - 2 ];
1728             }
1729         } else if (is64_) {
1730             nmPtr = &stringpool[sym->n_offset64];
1731
1732         } else if (!sym->n_zeroes32) {
1733             nmPtr = &stringpool[sym->n_offset32];
1734
1735         } else {
1736             // names 8 or less chars on inline, not in stabstr
1737             memset( temporaryName, 0, 9 );
1738             strncpy( temporaryName, sym->n_name32, 8 );
1739             nmPtr = temporaryName;
1740         } /* end bug compensation */
1741
1742         /* Now that we've compensated for buggy naming, actually
1743         parse the line information. */
1744         if( ( sym->n_sclass == C_BINCL ) ||
1745             ( sym->n_sclass == C_EINCL ) ||
1746             ( sym->n_sclass == C_FUN ) ) {
1747
1748             if( funcName ) {
1749                 free( funcName );
1750                 funcName = NULL;
1751             }
1752             funcName = strdup( nmPtr );
1753
1754             std::string pdCSF( currentSourceFile );
1755             parseLineInformation(li, & pdCSF, funcName, (SYMENT *)sym, linesfdptr, lines, nlines );
1756         } /* end if we're actually parsing line information */
1757     } /* end iteration over STAB entries. */
1758
1759     if( funcName != NULL ) {
1760         free( funcName );
1761     }
1762     haveParsedFileMap.insert(mf->pathname());
1763 } /* end parseFileLineInfo() */
1764
1765 void Object::parseLineInformation(dyn_hash_map<std::string,  LineInformation> &lineInfo_, std::string * currentSourceFile,
1766       char * symbolName,
1767       SYMENT * sym,
1768       Offset linesfdptr,
1769       char * lines,
1770       int nlines ) 
1771 {
1772    union auxent * aux;
1773    std::vector<IncludeFileInfo> includeFiles;
1774    unsigned long value = (is64_ ? sym->n_value64 : sym->n_value32);
1775    unsigned long LINESZ = (is64_ ? LINESZ_64 : LINESZ_32);
1776
1777    /* if it is beginning of include files then update the data structure
1778       that keeps the beginning of the include files. If the include files contain
1779       information about the functions and lines we have to keep it */
1780    if ( sym->n_sclass == C_BINCL ) {
1781       includeFiles.push_back( IncludeFileInfo( (value - linesfdptr)/LINESZ, symbolName ) );
1782    }
1783    /* similiarly if the include file contains function codes and line information
1784       we have to keep the last line information entry for this include file */
1785    else if (sym->n_sclass == C_EINCL) {
1786       if (includeFiles.size() > 0) {
1787          includeFiles[includeFiles.size()-1].end = (value - linesfdptr)/LINESZ;
1788       }
1789    }
1790
1791    /* if the enrty is for a function than we have to collect all info
1792       about lines of the function */
1793    else if ( sym->n_sclass == C_FUN ) {
1794       /* I have no idea what the old code did, except not work very well.
1795          Somebody who understands XCOFF should look at this. */
1796       int initialLine = 0;
1797       int initialLineIndex = 0;
1798       Offset funcStartAddress = 0;
1799       Offset funcEndAddress = 0;
1800
1801       for (int j = -1; ; --j) {
1802          SYMENT * extSym = (SYMENT *)( ((char *)sym) + (j * SYMESZ) );
1803          if( extSym->n_sclass == C_EXT || extSym->n_sclass == C_HIDEXT ) {
1804             aux = (union auxent *)( ((char *)extSym) + SYMESZ );
1805             initialLineIndex = (is64_ ? aux->x_fcn64.x_lnnoptr
1806                                       : aux->x_sym32.x_fcnary.x_fcn.x_lnnoptr);
1807             initialLineIndex = (initialLineIndex - linesfdptr )/LINESZ;
1808
1809             funcStartAddress = (is64_ ? extSym->n_value64 : extSym->n_value32);
1810             break;
1811          } /* end if C_EXT found */
1812       } /* end search for C_EXT */
1813
1814       /* access the line information now using the C_FCN entry*/
1815       SYMENT * bfSym = (SYMENT *)( ((char *)sym) + SYMESZ );
1816       if ( bfSym->n_sclass != C_FCN ) {
1817          //bperr("unable to process line info for %s\n", symbolName);
1818          return;
1819       }
1820
1821       SYMENT * efSym = (SYMENT *)( ((char *)bfSym) + (2 * SYMESZ) );
1822       while (efSym->n_sclass != C_FCN)
1823          efSym = (SYMENT *) ( ((Offset)efSym) + SYMESZ );
1824       funcEndAddress = (is64_ ? efSym->n_value64 : efSym->n_value32);
1825
1826       aux = (union auxent *)( ((char *)bfSym) + SYMESZ );
1827       initialLine = (is64_ ? aux->x_sym64.x_misc.x_lnsz.x_lnno
1828                            : aux->x_sym32.x_misc.x_lnsz.x_lnno);
1829
1830       std::string whichFile = *currentSourceFile;
1831       for (unsigned int j = 0; j < includeFiles.size(); j++) {
1832          if ( (includeFiles[j].begin <= (unsigned)initialLineIndex) &&
1833               (includeFiles[j].end   >= (unsigned)initialLineIndex) ) {
1834             whichFile = includeFiles[j].name;
1835             break;
1836          }
1837       } /* end iteration of include files */
1838
1839       unsigned int previousLineNo = 0;
1840       Offset previousLineAddr = 0;
1841       bool isPreviousValid = false;
1842
1843       /* Iterate over this entry's lines. */
1844       for (int j = initialLineIndex + 1; j < nlines; j++ ) {
1845          LINENO * lptr = (LINENO *)( lines + (j * LINESZ) );
1846          unsigned long lnno = (is64_ ? lptr->l_lnno64 : lptr->l_lnno32);
1847          unsigned long paddr = (is64_ ? lptr->l_addr64.l_paddr : lptr->l_addr32.l_paddr);
1848
1849          if (! lnno) { break; }
1850          unsigned int lineNo = lnno + initialLine - 1;
1851          Offset lineAddr = paddr + trueBaseAddress;
1852
1853          if (isPreviousValid) {
1854             // /* DEBUG */ fprintf( stderr, "%s[%d]: adding %s:%d [0x%lx, 0x%lx).\n", __FILE__, __LINE__, whichFile.c_str(), previousLineNo, previousLineAddr, lineAddr );
1855             unsigned current_col = 0;
1856             if (previousLineNo == 596 || previousLineNo == 597)
1857             {
1858                //cerr << "FuncEndAddress: " <<setbase(16) << funcEndAddress << setbase(10) << ",totallines:" << nlines << ":" << endl;
1859                //cerr << __FILE__ <<"[" << __LINE__ << "]:inserted address range [" << setbase(16) << previousLineAddr << "," << lineAddr << ") for source " << whichFile << ":" << setbase(10) << previousLineNo << endl;
1860             }   
1861             lineInfo_[whichFile].addLine(whichFile.c_str(), previousLineNo, current_col, previousLineAddr, lineAddr );
1862             //currentLineInformation.addLine( whichFile.c_str(), previousLineNo, current_col, previousLineAddr, lineAddr );
1863          }
1864
1865          previousLineNo = lineNo;
1866          previousLineAddr = lineAddr;
1867          isPreviousValid = true;
1868       } /* end iteration over line information */
1869
1870       if (isPreviousValid) {
1871          /* Add the instruction (always 4 bytes on power) pointed at by the last entry.  We'd like to add a
1872             bigger range, but it's not clear how.  (If the function has inlined code, we won't know about
1873             it until we see the next section, so claiming "until the end of the function" will give bogus results.) */
1874          // /* DEBUG */ fprintf( stderr, "%s[%d]: adding %s:%d [0x%lx, 0x%lx).\n", __FILE__, __LINE__, whichFile.c_str(), previousLineNo, previousLineAddr, previousLineAddr + 4 );
1875
1876          while (previousLineAddr < funcEndAddress) {
1877             unsigned current_col = 0;
1878             //if(previousLineNo == 596 || previousLineNo == 597)
1879              //  cerr << __FILE__ <<"[" << __LINE__ << "]:inserted address range [" << setbase(16) << previousLineAddr << "," <<  previousLineAddr + 4 << ") for source " << whichFile << ":" << setbase(10) << previousLineNo << endl;
1880
1881             lineInfo_[whichFile].addLine(whichFile.c_str(), previousLineNo, current_col, previousLineAddr,  previousLineAddr + 4);
1882
1883             //currentLineInformation.addLine( whichFile.c_str(), previousLineNo, current_col, previousLineAddr, previousLineAddr + 4 );
1884
1885             previousLineAddr += 4;
1886          }
1887       }
1888    } /* end if we found a C_FUN symbol */
1889 } /* end parseLineInformation() */
1890
1891
1892 // Gets the stab and stabstring section and parses it for types
1893 // and variables
1894 void Object::parseTypeInfo(Symtab *obj)
1895 {
1896    int i, j;
1897    int nstabs;
1898    SYMENT *syms;
1899    SYMENT *tsym;
1900    char *stringPool;
1901    char tempName[9];
1902    char *stabstr=NULL;
1903    union auxent *aux;
1904    std::string funcName;
1905    Offset staticBlockBaseAddr = 0;
1906    typeCommon *commonBlock = NULL;
1907    Symbol *commonBlockVar = NULL;
1908    std::string currentSourceFile;
1909    bool inCommonBlock = false;
1910    Module *mod = NULL;
1911
1912    void *syms_void = NULL;
1913    get_stab_info(stabstr, nstabs, syms_void, stringPool);
1914    syms = (SYMENT *) syms_void;
1915
1916    bool parseActive = true;
1917    //fprintf(stderr, "%s[%d]:  parseTypes for module %s: nstabs = %d\n", FILE__, __LINE__,mod->fileName().c_str(),nstabs);
1918    //int num_active = 0;
1919    //
1920    
1921    for (i=0; i < nstabs; i++) {
1922       /* do the pointer addition by hand since sizeof(struct syment)
1923        *   seems to be 20 not 18 as it should be */
1924       SYMENT *sym = (SYMENT *) (((char *) syms) + i * SYMESZ);
1925       unsigned long sym_value = (is64_ ? sym->n_value64 : sym->n_value32);
1926
1927       if (sym->n_sclass == C_FILE) {
1928          char *moduleName;
1929          if (is64_) {
1930              moduleName = &stringPool[sym->n_offset64];
1931          } else if (!sym->n_zeroes32) {
1932              moduleName = &stringPool[sym->n_offset32];
1933          } else {
1934             memset(tempName, 0, 9);
1935             strncpy(tempName, sym->n_name32, 8);
1936             moduleName = tempName;
1937          }
1938          /* look in aux records */
1939          for (j=1; j <= sym->n_numaux; j++) {
1940             aux = (union auxent *) ((char *) sym + j * SYMESZ);
1941             if (aux->x_file._x.x_ftype == XFT_FN) {
1942                if (!aux->x_file._x.x_zeroes) {
1943                   moduleName = &stringPool[aux->x_file._x.x_offset];
1944                } else {
1945                   memset(moduleName, 0, 15);
1946                   strncpy(moduleName, aux->x_file.x_fname, 14);
1947                }
1948             }
1949          }
1950          currentSourceFile = std::string(moduleName);
1951          if(!obj->findModuleByName(mod, currentSourceFile))
1952          {
1953             if(!obj->findModuleByName(mod,extract_pathname_tail(currentSourceFile)))
1954                 parseActive = false;
1955             else{
1956                 parseActive = true;
1957                 // Clear out old types
1958                 mod->getModuleTypes()->clearNumberedTypes();
1959             }
1960          }
1961          else{
1962             parseActive = true;
1963             // Clear out old types
1964             mod->getModuleTypes()->clearNumberedTypes();
1965          }
1966
1967          //TODO? check for process directories??
1968          //currentSourceFile = mod->processDirectories(currentSourceFile);
1969
1970       }
1971       if (!parseActive) continue;
1972
1973       //num_active++;
1974       char *nmPtr;
1975       if (!sym->n_zeroes32 && ((sym->n_sclass & DBXMASK) ||
1976                                (sym->n_sclass == C_BINCL) ||
1977                                (sym->n_sclass == C_EINCL))) {
1978           long sym_offset = (is64_ ? sym->n_offset64 : sym->n_offset32);
1979
1980           // Symbol name stored in STABS, not string pool.
1981           if(sym_offset < 3) {
1982               if (sym_offset == 2 && stabstr[0]) {
1983                   nmPtr = &stabstr[0];
1984               } else {
1985                   nmPtr = &stabstr[sym_offset];
1986               }
1987           } else if (!stabstr[sym_offset-3]) {
1988               nmPtr = &stabstr[sym_offset];
1989           } else {
1990               /* has off by two error */
1991               nmPtr = &stabstr[sym_offset-2];
1992           }
1993 #if 0    
1994          bperr("using nmPtr = %s\n", nmPtr);
1995          bperr("got n_offset = (%d) %s\n", sym_offset, &stabstr[sym_offset]);
1996          if (sym_offset>=2)
1997             bperr("got n_offset-2 = %s\n", &stabstr[sym_offset-2]);
1998          if (sym_offset>=3)
1999             bperr("got n_offset-3 = %x\n", stabstr[sym_offset-3]);
2000          if (sym_offset>=4)
2001             bperr("got n_offset-4 = %x\n", stabstr[sym_offset-4]);
2002 #endif
2003       } else if (is64_) {
2004           nmPtr = &stringPool[sym->n_offset64];
2005       } else if (!sym->n_zeroes32) {
2006           nmPtr = &stringPool[sym->n_offset32];
2007       } else {
2008          // names 8 or less chars on inline, not in stabstr
2009          memset(tempName, 0, 9);
2010          strncpy(tempName, sym->n_name32, 8);
2011          nmPtr = tempName;
2012       }
2013
2014       if ((sym->n_sclass == C_BINCL) ||
2015             (sym->n_sclass == C_EINCL) ||
2016             (sym->n_sclass == C_FUN)) 
2017       {
2018          funcName = nmPtr;
2019          /* The call to parseLineInformation(), below, used to modify the symbols passed to it. */
2020          if (funcName.find(":") < funcName.length())
2021             funcName = funcName.substr(0,funcName.find(":"));
2022       }
2023       if (sym->n_sclass & DBXMASK) {
2024          if (sym->n_sclass == C_BCOMM) {
2025             char *commonBlockName;
2026
2027             inCommonBlock = true;
2028             commonBlockName = nmPtr;
2029
2030             std::vector<Symbol *>vars;
2031             if(!obj->findSymbolByType(vars, commonBlockName, Symbol::ST_OBJECT))
2032             {
2033                if(!obj->findSymbolByType(vars, commonBlockName, Symbol::ST_OBJECT, true))
2034                   commonBlockVar = NULL;
2035                else
2036                   commonBlockVar = vars[0];
2037             }
2038             else
2039                commonBlockVar = vars[0];
2040
2041             std::string cbName = commonBlockName;
2042             if (!commonBlockVar) {
2043                //bperr("unable to find variable %s\n", commonBlockName);
2044             } else {
2045                commonBlock = dynamic_cast<typeCommon *>(mod->getModuleTypes()->findVariableType(cbName));
2046                if (commonBlock == NULL) {
2047                   // its still the null type, create a new one for it
2048                   //TODO? ? ID for this typeCommon ?
2049                   commonBlock = new typeCommon(cbName);
2050                   mod->getModuleTypes()->addGlobalVariable(cbName, commonBlock);
2051                }
2052                // reset field list
2053                commonBlock->beginCommonBlock();
2054             }
2055          } else if (sym->n_sclass == C_ECOMM) {
2056             inCommonBlock = false;
2057             if (commonBlock == NULL)
2058                continue;
2059
2060             // copy this set of fields
2061             std::vector<Symbol *> bpmv;
2062             if (obj->findSymbolByType(bpmv, funcName, Symbol::ST_FUNCTION) || !bpmv.size()) {
2063                 string newName = "." + funcName;
2064                 if (obj->findSymbolByType(bpmv, newName, Symbol::ST_FUNCTION) || !bpmv.size()) {
2065                    //bperr("unable to locate current function %s\n", funcName.c_str());
2066                 }
2067                 else{
2068                     Symbol *func = bpmv[0];
2069                     commonBlock->endCommonBlock(func, (void *)commonBlockVar->getAddr());
2070                 }
2071             } else {
2072                Symbol *func = bpmv[0];
2073                commonBlock->endCommonBlock(func, (void *)commonBlockVar->getAddr());
2074             }
2075
2076             //TODO?? size for local variables??
2077             //        // update size if needed
2078             //        if (commonBlockVar)
2079             //            commonBlockVar->setSize(commonBlock->getSize());
2080             commonBlockVar = NULL;
2081             commonBlock = NULL;
2082          } else if (sym->n_sclass == C_BSTAT) {
2083             // begin static block
2084             // find the variable for the common block
2085             tsym = (SYMENT *) (((char *) syms) + sym_value * SYMESZ);
2086
2087             // We can't lookup the value by name, because the name might have been
2088             // redefined later on (our lookup would then pick the last one)
2089
2090             // Since this whole function is AIX only, we're ok to get this info
2091
2092             staticBlockBaseAddr = (is64_ ? tsym->n_value64 : tsym->n_value32);
2093
2094             /*
2095             char *staticName, tempName[9];
2096             if (is64_) {
2097                 staticName = &stringPool[tsym->n_offset64];
2098             } else if (!tsym->n_zeroes32) {
2099                 staticName = &stringPool[tsym->n_offset32];
2100             } else {
2101                 memset(tempName, 0, 9);
2102                 strncpy(tempName, tsym->n_name32, 8);
2103                 staticName = tempName;
2104             }
2105
2106             BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName);
2107             if (!staticBlockVar) {
2108                 bperr("unable to find static block %s\n", staticName);
2109                 staticBlockBaseAddr = 0;
2110             } else {
2111                 staticBlockBaseAddr = (Offset) staticBlockVar->getBaseAddr();
2112             }
2113             */
2114
2115          } else if (sym->n_sclass == C_ESTAT) {
2116             staticBlockBaseAddr = 0;
2117          }
2118
2119          // There's a possibility that we were parsing a common block that
2120          // was never instantiated (meaning there's type info, but no
2121          // variable info
2122
2123          if (inCommonBlock && commonBlock == NULL)
2124             continue;
2125
2126          if(!mod){
2127             std::string modName = currentSourceFile;
2128             std::string fName = extract_pathname_tail(modName);
2129             if(!obj->findModuleByName(mod, fName))
2130             {
2131                modName = obj->file();
2132                if(!obj->findModuleByName(mod, modName))
2133                   continue;
2134             }
2135          }
2136
2137          if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) {
2138             parseStabString(mod, 0, nmPtr, 
2139                   sym_value+staticBlockBaseAddr, commonBlock);
2140          } else {
2141             parseStabString(mod, 0, nmPtr, sym_value, commonBlock);
2142          }
2143       }
2144    }
2145 #if defined(TIMED_PARSE)
2146    struct timeval endtime;
2147    gettimeofday(&endtime, NULL);
2148    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2149    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2150    unsigned long difftime = lendtime - lstarttime;
2151    double dursecs = difftime/(1000 );
2152    cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< obj->exec()->file()
2153       <<") took "<<dursecs <<" msecs" << endl;
2154 #endif
2155
2156    //  fprintf(stderr, "%s[%d]:  parseTypes for %s, num_active = %d\n", FILE__, __LINE__, mod->fileName().c_str(), num_active);
2157 }