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