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