added support for parsing shared object files for sparc-solaris platform
[dyninst.git] / common / h / Object-elf.h
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * Object-elf32.h: ELF-32 object files.
44 ************************************************************************/
45
46
47 \f
48
49
50 #if !defined(_Object_elf32_h_)
51 #define _Object_elf32_h_
52
53
54 \f
55
56
57 /************************************************************************
58  * header files.
59 ************************************************************************/
60
61 #include <util/h/DictionaryLite.h>
62 #include <util/h/String.h>
63 #include <util/h/Symbol.h>
64 #include <util/h/Types.h>
65 #include <util/h/Vector.h>
66
67 extern "C" {
68 #include <libelf.h>
69 #include <fcntl.h>
70 #include <stdlib.h>
71 #include <unistd.h>
72
73 #include <sys/types.h>
74 #include <sys/mman.h>
75 #include <sys/stat.h>
76 }
77
78 /***
79    The standard symbol table in an elf file is the .symtab section. This section does
80    not have information to find the module to which a global symbol belongs, so we must
81    also read the .stab section to get this info.
82 ***/
83
84 // Declarations for the .stab section.
85 // These are not declared in any system header files, so we must provide our own
86 // declarations. The declarations below were taken from:
87 //       SPARCWorks 3.0.x Debugger Interface, July 1994/
88
89 struct stab_entry { // an entry in the stab section
90   unsigned long name;  // stabstr table index for this symbol
91   unsigned char type; // type of this symbol
92   unsigned char other; 
93   unsigned short desc; 
94   unsigned long val; // value of this symbol -- usually zero. The real value must
95                      // be obtained from the symtab section
96 };
97
98 // Types 
99 #define N_UNDF  0x00 /* start of object file */
100 #define N_GSYM  0x20 /* global symbol */
101 #define N_FUN   0x24 /* function or procedure */
102 #define N_STSYM 0x26 /* initialized static symbol */
103 #define N_LCSYM 0x28 /* unitialized static symbol */
104 #define N_ROSYM 0x2c /* read-only static symbol */
105 #define N_ENDM  0x62 /* end module */
106 #define N_SO    0x64 /* source directory and file */
107 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
108
109 // Language code -- the desc field in a N_SO entry is a language code
110 #define N_SO_AS      1 /* assembler source */
111 #define N_SO_C       2 /* K & R C source */
112 #define N_SO_ANSI_C  3 /* ANSI C source */
113 #define N_SO_CC      4 /* C++ source */
114 #define N_SO_FORTRAN 5 /* fortran source */
115 #define N_SO_PASCAL  6 /* Pascal source */
116
117 // Symbol descriptors
118 // The format of a name is "<name>:<symbol descriptor><rest of name>
119 // The following are the descriptors of interest
120 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
121 #define SD_PROTOTYPE 'P'  /* function prototypes */
122 #define SD_GLOBAL_VAR 'G' /* global variable */
123
124 // end of stab declarations
125
126 \f
127
128
129 /************************************************************************
130  * class Object
131 ************************************************************************/
132
133 class Object : public AObject {
134 public:
135              Object (const string, void (*)(const char *) = log_msg);
136              Object (const string, u_int baseAddr, 
137                      void (*)(const char *) = log_msg);
138              Object (const Object &);
139     virtual ~Object ();
140
141     const Object& operator= (const Object &);
142
143 private:
144     static
145     void    log_elferror (void (*)(const char *), const char *);
146
147     bool      loaded_elf (int, bool &, Elf* &, Elf32_Ehdr* &, Elf32_Phdr* &,
148                           unsigned &, unsigned &, Elf_Scn* &, Elf_Scn* &,
149                           Elf_Scn* &, Elf_Scn* &);
150     bool      loaded_elf_obj (int, bool &, Elf* &, Elf32_Ehdr* &,Elf32_Phdr* &,
151                               unsigned &, unsigned &, Elf_Scn* &, Elf_Scn*&);
152     void     load_object ();
153     void     load_shared_object ();
154 };
155
156 inline
157 Object::~Object() {
158 }
159
160 inline
161 const Object&
162 Object::operator=(const Object& obj) {
163     (void) AObject::operator=(obj);
164     return *this;
165 }
166
167 inline
168 void
169 Object::log_elferror(void (*pfunc)(const char *), const char* msg) {
170     const char* err = elf_errmsg(elf_errno());
171     log_printf(pfunc, "%s: %s\n", msg, err ? err : "(bad elf error)");
172 }
173
174 inline
175 bool
176 Object::loaded_elf(int fd, bool& did_elf, Elf*& elfp, Elf32_Ehdr*& ehdrp,
177     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
178     Elf_Scn*& symscnp, Elf_Scn*& strscnp, Elf_Scn*& stabscnp, Elf_Scn*& stabstrscnp) {
179
180     elf_version(EV_CURRENT);
181     elf_errno();
182
183     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
184         || (elf_kind(elfp) != ELF_K_ELF)) {
185         log_elferror(err_func_, "opening file");
186         return false;
187     }
188     did_elf = true;
189
190     if (((ehdrp = elf32_getehdr(elfp)) == 0)
191         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
192         || (ehdrp->e_type != ET_EXEC)
193         || (ehdrp->e_phoff == 0)
194         || (ehdrp->e_shoff == 0)
195         || (ehdrp->e_phnum == 0)
196         || (ehdrp->e_shnum == 0)) {
197         log_elferror(err_func_, "loading eheader");
198         return false;
199     }
200
201     if ((phdrp = elf32_getphdr(elfp)) == 0) {
202         log_elferror(err_func_, "loading pheader");
203         return false;
204     }
205
206     Elf_Scn*    shstrscnp  = 0;
207     Elf32_Shdr* shstrshdrp = 0;
208     Elf_Data*   shstrdatap = 0;
209     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
210         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
211         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
212         log_elferror(err_func_, "loading header section");
213         return false;
214     }
215
216     const char* shnames = (const char *) shstrdatap->d_buf;
217     Elf_Scn*    scnp    = 0;
218     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
219         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
220         if (!shdrp) {
221             log_elferror(err_func_, "scanning sections");
222             return false;
223         }
224
225         const char* TEXT_NAME   = ".text";
226         const char* BSS_NAME    = ".bss";
227         const char* SYMTAB_NAME = ".symtab";
228         const char* STRTAB_NAME = ".strtab";
229         const char* STAB_NAME   = ".stab";
230         const char* STABSTR_NAME= ".stabstr";
231         const char* name        = (const char *) &shnames[shdrp->sh_name];
232
233         if (strcmp(name, TEXT_NAME) == 0) {
234             txtaddr = shdrp->sh_addr;
235         }
236         else if (strcmp(name, BSS_NAME) == 0) {
237             bssaddr = shdrp->sh_addr;
238         }
239         else if (strcmp(name, SYMTAB_NAME) == 0) {
240             symscnp = scnp;
241         }
242         else if (strcmp(name, STRTAB_NAME) == 0) {
243             strscnp = scnp;
244         }
245         else if (strcmp(name, STAB_NAME) == 0) {
246             stabscnp = scnp;
247         }
248         else if (strcmp(name, STABSTR_NAME) == 0) {
249             stabstrscnp = scnp;
250         }
251     }
252     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
253         log_elferror(err_func_, "no text/bss/symbol/string section");
254         return false;
255     }
256
257     return true;
258 }
259
260 inline
261 bool
262 Object::loaded_elf_obj(int fd, bool& did_elf, Elf*& elfp, Elf32_Ehdr*& ehdrp,
263     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
264     Elf_Scn*& symscnp, Elf_Scn*& strscnp) {
265
266     elf_version(EV_CURRENT);
267     elf_errno();
268
269     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
270         || (elf_kind(elfp) != ELF_K_ELF)) {
271         log_elferror(err_func_, "opening file");
272         return false;
273     }
274     did_elf = true;
275
276     if (((ehdrp = elf32_getehdr(elfp)) == 0)
277         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
278         || (ehdrp->e_type != ET_DYN)
279         || (ehdrp->e_phoff == 0)
280         || (ehdrp->e_shoff == 0)
281         || (ehdrp->e_phnum == 0)
282         || (ehdrp->e_shnum == 0)) {
283         log_elferror(err_func_, "loading eheader");
284         return false;
285     }
286
287     if ((phdrp = elf32_getphdr(elfp)) == 0) {
288         log_elferror(err_func_, "loading pheader");
289         return false;
290     }
291
292     Elf_Scn*    shstrscnp  = 0;
293     Elf32_Shdr* shstrshdrp = 0;
294     Elf_Data*   shstrdatap = 0;
295     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
296         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
297         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
298         log_elferror(err_func_, "loading header section");
299         return false;
300     }
301
302     const char* shnames = (const char *) shstrdatap->d_buf;
303     Elf_Scn*    scnp    = 0;
304     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
305         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
306         if (!shdrp) {
307             log_elferror(err_func_, "scanning sections");
308             return false;
309         }
310
311         const char* TEXT_NAME   = ".text";
312         const char* BSS_NAME    = ".bss";
313         const char* SYMTAB_NAME = ".symtab";
314         const char* STRTAB_NAME = ".strtab";
315         const char* name        = (const char *) &shnames[shdrp->sh_name];
316
317         if (strcmp(name, TEXT_NAME) == 0) {
318             txtaddr = shdrp->sh_addr;
319         }
320         else if (strcmp(name, BSS_NAME) == 0) {
321             bssaddr = shdrp->sh_addr;
322         }
323         else if (strcmp(name, SYMTAB_NAME) == 0) {
324             symscnp = scnp;
325         }
326         else if (strcmp(name, STRTAB_NAME) == 0) {
327             strscnp = scnp;
328         }
329     }
330     string temp = string(" text: ");
331     temp += string((u_int)txtaddr);
332     temp += string(" bss: ");
333     temp += string((u_int)bssaddr);
334     temp += string(" symtab: ");
335     temp += string((u_int)symscnp);
336     temp += string(" strtab: ");
337     temp += string((u_int)strscnp);
338     temp += string(" ehdrp: ");
339     temp += string((u_int)ehdrp);
340     temp += string(" phdrp: ");
341     temp += string((u_int)phdrp);
342     temp += string("\n");
343     // log_elferror(err_func_, P_strdup(temp.string_of()));
344
345     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
346         log_elferror(err_func_, "no text/bss/symbol/string section");
347         return false;
348     }
349
350     return true;
351 }
352
353 inline
354 void
355 Object::load_object() {
356     const char* file = file_.string_of();
357     struct stat st;
358     int         fd   = -1;
359     char*       ptr  = 0;
360     Elf*        elfp = 0;
361
362     bool        did_open = false;
363     bool        did_elf  = false;
364
365     /* try */ {
366         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
367             log_perror(err_func_, file);
368             /* throw exception */ goto cleanup;
369         }
370         did_open = true;
371
372         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
373             == (char *) -1) {
374             log_perror(err_func_, "mmap");
375             /* throw exception */ goto cleanup;
376         }
377
378         Elf32_Ehdr* ehdrp   = 0;
379         Elf32_Phdr* phdrp   = 0;
380         Elf_Scn*    symscnp = 0;
381         Elf_Scn*    strscnp = 0;
382         Elf_Scn*    stabscnp = 0;
383         Elf_Scn*    stabstrscnp = 0;
384         unsigned    txtaddr = 0;
385         unsigned    bssaddr = 0;
386
387         if (!loaded_elf(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
388                 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp)) {
389                 /* throw exception */ goto cleanup;
390         }
391
392         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
393             if ((phdrp[i0].p_vaddr <= txtaddr)
394                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
395                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
396                 code_off_ = (Address) phdrp[i0].p_vaddr;
397                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
398             }
399             else if ((phdrp[i0].p_vaddr <= bssaddr)
400                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
401                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
402                 data_off_ = (Address) phdrp[i0].p_vaddr;
403                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
404             }
405         }
406         if (!code_ptr_ || !code_off_ || !code_len_) {
407             log_printf(err_func_, "cannot locate instructions\n");
408             /* throw exception */ goto cleanup;
409         }
410         if (!data_ptr_ || !data_off_ || !data_len_) {
411             log_printf(err_func_, "cannot locate data segment\n");
412             /* throw exception */ goto cleanup;
413         }
414
415         Elf_Data* symdatap = elf_getdata(symscnp, 0);
416         Elf_Data* strdatap = elf_getdata(strscnp, 0);
417         if (!symdatap || !strdatap) {
418             log_elferror(err_func_, "locating symbol/string data");
419             /* throw exception */ goto cleanup;
420         }
421
422         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
423         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
424         const char* strs   = (const char *) strdatap->d_buf;
425         string      module = "DEFAULT_MODULE";
426         string      name   = "DEFAULT_NAME";
427
428         // global symbols are put in global_symbols. Later we read the
429         // stab section to find the module to where they belong.
430         dictionary_hash<string, Symbol> global_symbols(string::hash);
431
432         for (unsigned i1 = 0; i1 < nsyms; i1++) {
433           // First, we must check st_shndx. 
434           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
435           // probably defined in a shared object that will be dynamically
436           // linked with the executable. We just ignore it for now.
437           if (syms[i1].st_shndx != SHN_UNDEF) {
438             bool st_kludge = false;
439             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
440             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
441             case STT_FILE:
442                 module = string(&strs[syms[i1].st_name]);
443                 type   = Symbol::PDST_MODULE;
444                 break;
445
446             case STT_OBJECT:
447                 type = Symbol::PDST_OBJECT;
448                 break;
449
450             case STT_FUNC:
451                 type = Symbol::PDST_FUNCTION;
452                 break;
453
454             default:
455                 continue;
456             }
457
458             name = string(&strs[syms[i1].st_name]);
459
460             // We are done with the local symbols. We save the global so that
461             // we can get their module from the .stab section.
462             if (ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) {
463                symbols_[name] = Symbol(name, module, type, Symbol::SL_LOCAL,
464                                     syms[i1].st_value, st_kludge, 
465                                     syms[i1].st_size);
466             }
467             else {
468                assert(!(global_symbols.defines(name))); // globals should be unique
469                global_symbols[name] = Symbol(name, string(""), type, Symbol::SL_GLOBAL,
470                                     syms[i1].st_value, st_kludge,
471                                     syms[i1].st_size);
472             }
473           }
474         }
475
476         // Read the stab section to find the module of global symbols.
477         // The symbols appear in the stab section by module. A module begins
478         // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
479         // All the symbols in between those two symbols belong to the module.
480
481         Elf_Data* stabdatap = elf_getdata(stabscnp, 0);
482         Elf_Data* stabstrdatap = elf_getdata(stabstrscnp, 0);
483         struct stab_entry *stabsyms = 0;
484         unsigned stab_nsyms;
485         const char *stabstrs = 0;
486
487         if (stabdatap && stabstrdatap) {
488           stabsyms = (struct stab_entry *) stabdatap->d_buf;
489           stab_nsyms = stabdatap->d_size / sizeof(struct stab_entry);
490           stabstrs = (const char *) stabstrdatap->d_buf;
491         }
492         else 
493           stab_nsyms = 0;
494
495         // the stabstr contains one string table for each module.
496         // stabstr_offset gives the offset from the begining of stabstr of the
497         // string table for the current module.
498         // stabstr_nextoffset gives the offset for the next module.
499         unsigned stabstr_offset = 0;
500         unsigned stabstr_nextoffset = 0;
501
502         bool is_fortran = false;  // is the current module fortran code?
503            /* we must know if we are reading a fortran module because fortran
504               symbol names are different in the .stab and .symtab sections.
505               A symbol that appears as 'foo' in the .stab section, appears
506               as 'foo_' in .symtab.
507            */
508         module = "";
509   
510         for (unsigned i = 0; i < stab_nsyms; i++) {
511           switch(stabsyms[i].type) {
512           case N_UNDF: /* start of object file */
513             assert(stabsyms[i].name == 1);
514             stabstr_offset = stabstr_nextoffset;
515             // stabsyms[i].val has the size of the string table of this module.
516             // We use this value to compute the offset of the next string table.
517             stabstr_nextoffset = stabstr_offset + stabsyms[i].val;
518             module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
519             break;
520
521           case N_ENDM: /* end of object file */
522             is_fortran = false;
523             module = "";
524             break;
525
526           case N_SO: /* compilation source or file name */
527             if (stabsyms[i].desc == N_SO_FORTRAN)
528               is_fortran = true;
529             break;
530
531           case N_ENTRY: /* fortran alternate subroutine entry point */
532           case N_FUN: /* function */
533           case N_GSYM: /* global symbol */
534             // the name string of a function or object appears in the stab string table
535             // as <symbol name>:<symbol descriptor><other stuff>
536             // where <symbol descriptor> is a one char code.
537             // we must extract the name and descriptor from the string
538           {
539             const char *p = &stabstrs[stabstr_offset+stabsyms[i].name];
540             const char *q = strchr(p,':');
541             assert(q);
542             unsigned len = q - p;
543             assert(len > 0);
544             char *sname = new char[len+1];
545             strncpy(sname, p, len);
546             sname[len] = 0;
547             
548             // q points to the ':' in the name string, so 
549             // q[1] is the symbol descriptor. We must check the symbol descriptor
550             // here to skip things we are not interested in, such as local functions
551             // and prototypes.
552             if (q[1] == SD_GLOBAL_FUN || q[1] == SD_GLOBAL_VAR || stabsyms[i].type==N_ENTRY) { 
553               string SymName = string(sname);
554               bool res = global_symbols.defines(SymName);
555               if (!res && is_fortran) {
556                 // Fortran symbols usually appear with an '_' appended in .symtab,
557                 // but not on .stab
558                 SymName += "_";
559                 res = global_symbols.defines(SymName);
560               }
561               assert(res); // All globals in .stab should be defined in .symtab
562               Symbol sym = global_symbols[SymName];
563               symbols_[SymName] = Symbol(sym.name(), module, sym.type(), sym.linkage(), 
564                                   sym.addr(), sym.kludge(), sym.size());
565             }
566           }
567             break;
568
569           default:
570             /* ignore other entries */
571             break;
572           }
573         }
574
575         /* The remaing symbols go without module */
576         vector<string> k = global_symbols.keys();
577         for (unsigned i2 = 0; i2 < k.size(); i2++) {
578           Symbol sym = global_symbols[k[i2]];
579           if (!(symbols_.defines(sym.name())))
580              symbols_[sym.name()] = sym;
581         }
582     }  /* try */
583
584     /* catch */
585 cleanup: {
586         if (did_elf && (elf_end(elfp) != 0)) {
587             log_elferror(err_func_, "closing file");
588         }
589         if (did_open && (close(fd) == -1)) {
590             log_perror(err_func_, "close");
591         }
592     }
593 }
594
595 static int symbol_compare(const void *x, const void *y) {
596     Symbol *s1 = (Symbol *)x;
597     Symbol *s2 = (Symbol *)y;
598     return (s1->addr() - s2->addr());
599 }
600
601 inline
602 void
603 Object::load_shared_object() {
604     const char* file = file_.string_of();
605     struct stat st;
606     int         fd   = -1;
607     char*       ptr  = 0;
608     Elf*        elfp = 0;
609
610     bool        did_open = false;
611     bool        did_elf  = false;
612
613     /* try */ {
614         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
615             log_perror(err_func_, file);
616             /* throw exception */ goto cleanup2;
617         }
618         did_open = true;
619
620         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
621             == (char *) -1) {
622             log_perror(err_func_, "mmap");
623             /* throw exception */ goto cleanup2;
624         }
625
626         Elf32_Ehdr* ehdrp   = 0;  /* ELF header */
627         Elf32_Phdr* phdrp   = 0;  /* program header */
628         Elf_Scn*    symscnp = 0;
629         Elf_Scn*    strscnp = 0;
630         unsigned    txtaddr = 0;
631         unsigned    bssaddr = 0;
632
633         if (!loaded_elf_obj(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
634                             bssaddr, symscnp, strscnp)) {
635                 /* throw exception */ goto cleanup2;
636         }
637
638         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
639             if ((phdrp[i0].p_vaddr <= txtaddr)
640                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
641                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
642                 code_off_ = (Address) phdrp[i0].p_vaddr;
643                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
644             }
645             else if ((phdrp[i0].p_vaddr <= bssaddr)
646                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
647                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
648                 data_off_ = (Address) phdrp[i0].p_vaddr;
649                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
650             }
651         }
652 #ifdef ndef
653         if (!code_ptr_ || !code_len_) {
654             log_printf(err_func_, "cannot locate instructions\n");
655             /* throw exception */ goto cleanup2;
656         }
657         if (!data_ptr_ || !data_off_ || !data_len_) {
658             log_printf(err_func_, "cannot locate data segment\n");
659             /* throw exception */ goto cleanup2;
660         }
661 #endif
662
663         Elf_Data* symdatap = elf_getdata(symscnp, 0);
664         Elf_Data* strdatap = elf_getdata(strscnp, 0);
665         if (!symdatap || !strdatap) {
666             log_elferror(err_func_, "locating symbol/string data");
667             /* throw exception */ goto cleanup2;
668         }
669
670         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
671         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
672         const char* strs   = (const char *) strdatap->d_buf;
673         string      module = "DEFAULT_MODULE";
674         string      name   = "DEFAULT_NAME";
675
676         // for shared objects add a module that is the file name
677         // and add all the global symbols as functions 
678         const char *libname = file_.string_of();
679         // find short name
680         char *last = 0;
681         for(u_int i=0; i < file_.length();i++) {
682             if(libname[i] == '/'){
683                 last = (char *)(&(libname[i]));
684                 // log_elferror(err_func_, P_strdup(last));
685             }
686         }
687         if(last){
688             module = (const char *)(last +1);  
689         }
690         else{
691             module = string("DEFAULT_MODULE");  
692         }
693         // string blah = string("module name: ");
694         // blah += module.string_of();
695         // blah += ("\n");
696         // log_elferror(err_func_, P_strdup(blah.string_of()));
697
698         vector<Symbol> allsymbols;
699         bool found = false;
700         for (unsigned i1 = 0; i1 < nsyms; i1++) {
701           // First, we must check st_shndx. 
702           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
703           // probably defined in a shared object that will be dynamically
704           // linked with the executable. We just ignore it for now.
705           if (syms[i1].st_shndx != SHN_UNDEF) {
706             bool st_kludge = false;
707             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
708             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
709             case STT_FILE: {
710                 string temp2 = string(&strs[syms[i1].st_name]);
711                 if(temp2 == module){
712                     module = string(&strs[syms[i1].st_name]);
713                     type   = Symbol::PDST_MODULE;
714                     found = true;
715                 }
716                 break;
717                 }
718
719             case STT_OBJECT:
720                 type = Symbol::PDST_OBJECT;
721                 break;
722
723             case STT_FUNC:
724                 type = Symbol::PDST_FUNCTION;
725                 break;
726
727             case STT_NOTYPE:
728                 type = Symbol::PDST_NOTYPE;
729                 break;
730
731             default:
732                 continue;
733             }
734
735             name = string(&strs[syms[i1].st_name]);
736
737             // only add symbols of type STB_LOCAL and  FILE if they are 
738             // the shared object name
739             if ((ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) 
740                 &&((ELF32_ST_TYPE(syms[i1].st_info) != STT_FILE) || (found))){
741                    symbols_[name] = Symbol(name, module, type, Symbol::SL_LOCAL,
742                                     syms[i1].st_value, st_kludge, 
743                                     syms[i1].st_size);
744                    found = false;
745             }
746             else if(ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) {
747                 allsymbols += Symbol(name, module, type, Symbol::SL_LOCAL,
748                                                 syms[i1].st_value, st_kludge,
749                                                 syms[i1].st_size);
750             }
751             else {
752                allsymbols += Symbol(name, module, 
753                                     type, Symbol::SL_GLOBAL,
754                                     syms[i1].st_value, st_kludge,
755                                     syms[i1].st_size);
756             }
757           }
758         }
759
760
761         // Sort all the symbols, and fix the sizes
762         allsymbols.sort(symbol_compare);
763
764         for(u_int i=0; i < (allsymbols.size() -1); i++){
765             // if the symbol is type PDST_FUNCTION and the next symbol is 
766             // type PDST_FUNCTION or PDST_NOTYPE then see if its size needs
767             // to be changed...this occurs when the function's size is 
768             u_int new_size = 0;
769             bool  change_size = false;
770             if((allsymbols[i].type() == Symbol::PDST_FUNCTION)
771                 && ((allsymbols[i+1].type() == Symbol::PDST_FUNCTION) || 
772                      (allsymbols[i+1].type() == Symbol::PDST_NOTYPE))){
773                 u_int next_start = allsymbols[i].addr() + allsymbols[i].size();
774                 if(next_start > allsymbols[i+1].addr()){
775                     new_size =  allsymbols[i+1].addr() - allsymbols[i].addr();
776                     change_size = false;
777                     // printf("addr = %d size = %d new_size = %d nextaddr = %d next_start = %d name = %s\n",
778                     // allsymbols[i].addr(), allsymbols[i].size(), new_size, allsymbols[i+1].addr(),
779                     // next_start, (allsymbols[i].name()).string_of());
780                 }
781             }
782
783             if((allsymbols[i].type() == Symbol::PDST_FUNCTION) && change_size){
784                 symbols_[allsymbols[i].name()] =
785                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
786                     allsymbols[i].type(), allsymbols[i].linkage(),
787                     allsymbols[i].addr(), allsymbols[i].kludge(),
788                     new_size);
789             }
790             else {
791                 symbols_[allsymbols[i].name()] =
792                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
793                     allsymbols[i].type(), allsymbols[i].linkage(),
794                     allsymbols[i].addr(), allsymbols[i].kludge(),
795                     allsymbols[i].size());
796             }
797         }
798         // add last symbol
799         u_int last_sym = allsymbols.size()-1;
800         symbols_[allsymbols[last_sym].name()] =
801             Symbol(allsymbols[last_sym].name(), allsymbols[last_sym].module(),
802             allsymbols[last_sym].type(), allsymbols[last_sym].linkage(),
803             allsymbols[last_sym].addr(), allsymbols[last_sym].kludge(),
804             allsymbols[last_sym].size());
805
806     }  /* try */
807
808     /* catch */
809
810 cleanup2: {
811         if (did_elf && (elf_end(elfp) != 0)) {
812             log_elferror(err_func_, "closing file");
813         }
814         if (did_open && (close(fd) == -1)) {
815             log_perror(err_func_, "close");
816         }
817     }
818 }
819
820
821 inline
822 Object::Object(const string file, void (*err_func)(const char *))
823     : AObject(file, err_func) {
824     load_object();
825 }
826
827 inline
828 Object::Object(const string file, u_int ,void (*err_func)(const char *))
829     : AObject(file, err_func) {
830     load_shared_object();
831 }
832
833 inline
834 Object::Object(const Object& obj)
835     : AObject(obj) {
836     load_object();
837 }
838
839
840 \f
841
842
843 #endif /* !defined(_Object_elf32_h_) */