removed assert that all globals in .stab should be defined in .symtab
[dyninst.git] / dyninstAPI / src / 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 fprintf(stderr, "#### elf machine = %d\n", ehdrp->e_machine);
202
203     if ((phdrp = elf32_getphdr(elfp)) == 0) {
204         log_elferror(err_func_, "loading pheader");
205         return false;
206     }
207
208     Elf_Scn*    shstrscnp  = 0;
209     Elf32_Shdr* shstrshdrp = 0;
210     Elf_Data*   shstrdatap = 0;
211     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
212         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
213         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
214         log_elferror(err_func_, "loading header section");
215         return false;
216     }
217
218     const char* shnames = (const char *) shstrdatap->d_buf;
219     Elf_Scn*    scnp    = 0;
220     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
221         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
222         if (!shdrp) {
223             log_elferror(err_func_, "scanning sections");
224             return false;
225         }
226
227         const char* TEXT_NAME   = ".text";
228         const char* BSS_NAME    = ".bss";
229         const char* SYMTAB_NAME = ".symtab";
230         const char* STRTAB_NAME = ".strtab";
231         const char* STAB_NAME   = ".stab";
232         const char* STABSTR_NAME= ".stabstr";
233         const char* name        = (const char *) &shnames[shdrp->sh_name];
234
235         if (strcmp(name, TEXT_NAME) == 0) {
236             txtaddr = shdrp->sh_addr;
237         }
238         else if (strcmp(name, BSS_NAME) == 0) {
239             bssaddr = shdrp->sh_addr;
240         }
241         else if (strcmp(name, SYMTAB_NAME) == 0) {
242             symscnp = scnp;
243         }
244         else if (strcmp(name, STRTAB_NAME) == 0) {
245             strscnp = scnp;
246         }
247         else if (strcmp(name, STAB_NAME) == 0) {
248             stabscnp = scnp;
249         }
250         else if (strcmp(name, STABSTR_NAME) == 0) {
251             stabstrscnp = scnp;
252         }
253     }
254     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
255         log_elferror(err_func_, "no text/bss/symbol/string section");
256         return false;
257     }
258
259     return true;
260 }
261
262 inline
263 bool
264 Object::loaded_elf_obj(int fd, bool& did_elf, Elf*& elfp, Elf32_Ehdr*& ehdrp,
265     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
266     Elf_Scn*& symscnp, Elf_Scn*& strscnp) {
267
268     elf_version(EV_CURRENT);
269     elf_errno();
270
271     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
272         || (elf_kind(elfp) != ELF_K_ELF)) {
273         log_elferror(err_func_, "opening file");
274         return false;
275     }
276     did_elf = true;
277
278     if (((ehdrp = elf32_getehdr(elfp)) == 0)
279         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
280         || (ehdrp->e_type != ET_DYN)
281         || (ehdrp->e_phoff == 0)
282         || (ehdrp->e_shoff == 0)
283         || (ehdrp->e_phnum == 0)
284         || (ehdrp->e_shnum == 0)) {
285         log_elferror(err_func_, "loading eheader");
286         return false;
287     }
288
289     if ((phdrp = elf32_getphdr(elfp)) == 0) {
290         log_elferror(err_func_, "loading pheader");
291         return false;
292     }
293
294     Elf_Scn*    shstrscnp  = 0;
295     Elf32_Shdr* shstrshdrp = 0;
296     Elf_Data*   shstrdatap = 0;
297     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
298         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
299         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
300         log_elferror(err_func_, "loading header section");
301         return false;
302     }
303
304     const char* shnames = (const char *) shstrdatap->d_buf;
305     Elf_Scn*    scnp    = 0;
306     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
307         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
308         if (!shdrp) {
309             log_elferror(err_func_, "scanning sections");
310             return false;
311         }
312
313         const char* TEXT_NAME   = ".text";
314         const char* BSS_NAME    = ".bss";
315         const char* SYMTAB_NAME = ".symtab";
316         const char* STRTAB_NAME = ".strtab";
317         const char* name        = (const char *) &shnames[shdrp->sh_name];
318
319         if (strcmp(name, TEXT_NAME) == 0) {
320             txtaddr = shdrp->sh_addr;
321         }
322         else if (strcmp(name, BSS_NAME) == 0) {
323             bssaddr = shdrp->sh_addr;
324         }
325         else if (strcmp(name, SYMTAB_NAME) == 0) {
326             symscnp = scnp;
327         }
328         else if (strcmp(name, STRTAB_NAME) == 0) {
329             strscnp = scnp;
330         }
331     }
332     string temp = string(" text: ");
333     temp += string((u_int)txtaddr);
334     temp += string(" bss: ");
335     temp += string((u_int)bssaddr);
336     temp += string(" symtab: ");
337     temp += string((u_int)symscnp);
338     temp += string(" strtab: ");
339     temp += string((u_int)strscnp);
340     temp += string(" ehdrp: ");
341     temp += string((u_int)ehdrp);
342     temp += string(" phdrp: ");
343     temp += string((u_int)phdrp);
344     temp += string("\n");
345     // log_elferror(err_func_, P_strdup(temp.string_of()));
346
347     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
348         log_elferror(err_func_, "no text/bss/symbol/string section");
349         return false;
350     }
351
352     return true;
353 }
354
355
356 static int symbol_compare(const void *x, const void *y) {
357     const Symbol *s1 = (const Symbol *)x;
358     const Symbol *s2 = (const Symbol *)y;
359     return (s1->addr() - s2->addr());
360 }
361
362
363 inline
364 void
365 Object::load_object() {
366     const char* file = file_.string_of();
367     struct stat st;
368     int         fd   = -1;
369     char*       ptr  = 0;
370     Elf*        elfp = 0;
371
372     bool        did_open = false;
373     bool        did_elf  = false;
374
375     /* try */ {
376         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
377             log_perror(err_func_, file);
378             /* throw exception */ goto cleanup;
379         }
380         did_open = true;
381
382         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
383             == (char *) -1) {
384             log_perror(err_func_, "mmap");
385             /* throw exception */ goto cleanup;
386         }
387
388         Elf32_Ehdr* ehdrp   = 0;
389         Elf32_Phdr* phdrp   = 0;
390         Elf_Scn*    symscnp = 0;
391         Elf_Scn*    strscnp = 0;
392         Elf_Scn*    stabscnp = 0;
393         Elf_Scn*    stabstrscnp = 0;
394         unsigned    txtaddr = 0;
395         unsigned    bssaddr = 0;
396
397         if (!loaded_elf(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
398                 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp)) {
399                 /* throw exception */ goto cleanup;
400         }
401
402         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
403             if ((phdrp[i0].p_vaddr <= txtaddr)
404                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
405                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
406                 code_off_ = (Address) phdrp[i0].p_vaddr;
407                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
408             }
409             else if ((phdrp[i0].p_vaddr <= bssaddr)
410                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
411                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
412                 data_off_ = (Address) phdrp[i0].p_vaddr;
413                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
414             }
415         }
416         if (!code_ptr_ || !code_off_ || !code_len_) {
417             log_printf(err_func_, "cannot locate instructions\n");
418             /* throw exception */ goto cleanup;
419         }
420         if (!data_ptr_ || !data_off_ || !data_len_) {
421             log_printf(err_func_, "cannot locate data segment\n");
422             /* throw exception */ goto cleanup;
423         }
424
425         Elf_Data* symdatap = elf_getdata(symscnp, 0);
426         Elf_Data* strdatap = elf_getdata(strscnp, 0);
427         if (!symdatap || !strdatap) {
428             log_elferror(err_func_, "locating symbol/string data");
429             /* throw exception */ goto cleanup;
430         }
431
432         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
433         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
434         const char* strs   = (const char *) strdatap->d_buf;
435         string      module = "DEFAULT_MODULE";
436         string      name   = "DEFAULT_NAME";
437
438         // global symbols are put in global_symbols. Later we read the
439         // stab section to find the module to where they belong.
440         dictionary_hash<string, Symbol> global_symbols(string::hash);
441
442         vector<Symbol> allsymbols;
443
444         for (unsigned i1 = 0; i1 < nsyms; i1++) {
445           // First, we must check st_shndx. 
446           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
447           // probably defined in a shared object that will be dynamically
448           // linked with the executable. We just ignore it for now.
449           if (syms[i1].st_shndx != SHN_UNDEF) {
450             bool st_kludge = false;
451             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
452             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
453             case STT_FILE:
454                 module = string(&strs[syms[i1].st_name]);
455                 type   = Symbol::PDST_MODULE;
456                 break;
457
458             case STT_OBJECT:
459                 type = Symbol::PDST_OBJECT;
460                 break;
461
462             case STT_FUNC:
463                 type = Symbol::PDST_FUNCTION;
464                 break;
465
466             default:
467                 continue;
468             }
469
470             name = string(&strs[syms[i1].st_name]);
471
472             if (ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) {
473                allsymbols += Symbol(name, module, type, Symbol::SL_LOCAL,
474                                     syms[i1].st_value, st_kludge, 
475                                     syms[i1].st_size);
476             }
477             else {
478                allsymbols += Symbol(name, string(""), type, Symbol::SL_GLOBAL,
479                                     syms[i1].st_value, st_kludge,
480                                     syms[i1].st_size);
481             }
482           }
483         }
484
485         // some functions may have size zero in the symbol table,
486         // we need to find the correct size
487         allsymbols.sort(symbol_compare);
488         unsigned nsymbols = allsymbols.size();
489         for (unsigned u = 0; u < nsymbols; u++) {
490           if (allsymbols[u].type() == Symbol::PDST_FUNCTION
491               && allsymbols[u].size() == 0) {
492             unsigned v = u+1;
493             while (v < nsymbols && allsymbols[v].addr() == allsymbols[u].addr())
494               v++;
495             if (v < nsymbols) {
496               allsymbols[u].change_size((unsigned)allsymbols[v].addr()
497                                         - (unsigned)allsymbols[u].addr());
498             }
499           }
500
501           // We are done with the local symbols. We save the global so that
502           // we can get their module from the .stab section.
503           if (allsymbols[u].linkage() == Symbol::SL_LOCAL)
504             symbols_[allsymbols[u].name()] = allsymbols[u];
505           else {
506             // globals should be unique
507             assert(!(global_symbols.defines(allsymbols[u].name()))); 
508             global_symbols[allsymbols[u].name()] = allsymbols[u];
509           }
510         }      
511         
512
513         // Read the stab section to find the module of global symbols.
514         // The symbols appear in the stab section by module. A module begins
515         // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
516         // All the symbols in between those two symbols belong to the module.
517
518         Elf_Data* stabdatap = elf_getdata(stabscnp, 0);
519         Elf_Data* stabstrdatap = elf_getdata(stabstrscnp, 0);
520         struct stab_entry *stabsyms = 0;
521         unsigned stab_nsyms;
522         const char *stabstrs = 0;
523
524         if (stabdatap && stabstrdatap) {
525           stabsyms = (struct stab_entry *) stabdatap->d_buf;
526           stab_nsyms = stabdatap->d_size / sizeof(struct stab_entry);
527           stabstrs = (const char *) stabstrdatap->d_buf;
528         }
529         else 
530           stab_nsyms = 0;
531
532         // the stabstr contains one string table for each module.
533         // stabstr_offset gives the offset from the begining of stabstr of the
534         // string table for the current module.
535         // stabstr_nextoffset gives the offset for the next module.
536         unsigned stabstr_offset = 0;
537         unsigned stabstr_nextoffset = 0;
538
539         bool is_fortran = false;  // is the current module fortran code?
540            /* we must know if we are reading a fortran module because fortran
541               symbol names are different in the .stab and .symtab sections.
542               A symbol that appears as 'foo' in the .stab section, appears
543               as 'foo_' in .symtab.
544            */
545         module = "";
546   
547         for (unsigned i = 0; i < stab_nsyms; i++) {
548           switch(stabsyms[i].type) {
549           case N_UNDF: /* start of object file */
550             assert(stabsyms[i].name == 1);
551             stabstr_offset = stabstr_nextoffset;
552             // stabsyms[i].val has the size of the string table of this module.
553             // We use this value to compute the offset of the next string table.
554             stabstr_nextoffset = stabstr_offset + stabsyms[i].val;
555             module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
556             break;
557
558           case N_ENDM: /* end of object file */
559             is_fortran = false;
560             module = "";
561             break;
562
563           case N_SO: /* compilation source or file name */
564             if (stabsyms[i].desc == N_SO_FORTRAN)
565               is_fortran = true;
566             break;
567
568           case N_ENTRY: /* fortran alternate subroutine entry point */
569           case N_FUN: /* function */
570           case N_GSYM: /* global symbol */
571             // the name string of a function or object appears in the stab string table
572             // as <symbol name>:<symbol descriptor><other stuff>
573             // where <symbol descriptor> is a one char code.
574             // we must extract the name and descriptor from the string
575           {
576             const char *p = &stabstrs[stabstr_offset+stabsyms[i].name];
577             const char *q = strchr(p,':');
578             assert(q);
579             unsigned len = q - p;
580             assert(len > 0);
581             char *sname = new char[len+1];
582             strncpy(sname, p, len);
583             sname[len] = 0;
584             
585             // q points to the ':' in the name string, so 
586             // q[1] is the symbol descriptor. We must check the symbol descriptor
587             // here to skip things we are not interested in, such as local functions
588             // and prototypes.
589             if (q[1] == SD_GLOBAL_FUN || q[1] == SD_GLOBAL_VAR || stabsyms[i].type==N_ENTRY) { 
590               string SymName = string(sname);
591               bool res = global_symbols.defines(SymName);
592               if (!res && is_fortran) {
593                 // Fortran symbols usually appear with an '_' appended in .symtab,
594                 // but not on .stab
595                 SymName += "_";
596                 res = global_symbols.defines(SymName);
597               }
598
599               if (!res) break;
600 //              assert(res); // All globals in .stab should be defined in .symtab
601
602               Symbol sym = global_symbols[SymName];
603               symbols_[SymName] = Symbol(sym.name(), module, sym.type(), sym.linkage(), 
604                                   sym.addr(), sym.kludge(), sym.size());
605             }
606           }
607             break;
608
609           default:
610             /* ignore other entries */
611             break;
612           }
613         }
614
615         /* The remaing symbols go without module */
616         vector<string> k = global_symbols.keys();
617         for (unsigned i2 = 0; i2 < k.size(); i2++) {
618           Symbol sym = global_symbols[k[i2]];
619           if (!(symbols_.defines(sym.name())))
620              symbols_[sym.name()] = sym;
621         }
622     }  /* try */
623
624     /* catch */
625 cleanup: {
626         if (did_elf && (elf_end(elfp) != 0)) {
627             log_elferror(err_func_, "closing file");
628         }
629         if (did_open && (close(fd) == -1)) {
630             log_perror(err_func_, "close");
631         }
632     }
633 }
634
635
636 inline
637 void
638 Object::load_shared_object() {
639     const char* file = file_.string_of();
640     struct stat st;
641     int         fd   = -1;
642     char*       ptr  = 0;
643     Elf*        elfp = 0;
644
645     bool        did_open = false;
646     bool        did_elf  = false;
647
648     /* try */ {
649         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
650             log_perror(err_func_, file);
651             /* throw exception */ goto cleanup2;
652         }
653         did_open = true;
654
655         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
656             == (char *) -1) {
657             log_perror(err_func_, "mmap");
658             /* throw exception */ goto cleanup2;
659         }
660
661         Elf32_Ehdr* ehdrp   = 0;  /* ELF header */
662         Elf32_Phdr* phdrp   = 0;  /* program header */
663         Elf_Scn*    symscnp = 0;
664         Elf_Scn*    strscnp = 0;
665         unsigned    txtaddr = 0;
666         unsigned    bssaddr = 0;
667
668         if (!loaded_elf_obj(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
669                             bssaddr, symscnp, strscnp)) {
670                 /* throw exception */ goto cleanup2;
671         }
672
673         for (unsigned i0 = 0; i0 < ehdrp->e_phnum; i0++) {
674             if ((phdrp[i0].p_vaddr <= txtaddr)
675                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
676                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
677                 code_off_ = (Address) phdrp[i0].p_vaddr;
678                 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
679             }
680             else if ((phdrp[i0].p_vaddr <= bssaddr)
681                 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
682                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
683                 data_off_ = (Address) phdrp[i0].p_vaddr;
684                 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
685             }
686         }
687
688         Elf_Data* symdatap = elf_getdata(symscnp, 0);
689         Elf_Data* strdatap = elf_getdata(strscnp, 0);
690         if (!symdatap || !strdatap) {
691             log_elferror(err_func_, "locating symbol/string data");
692             /* throw exception */ goto cleanup2;
693         }
694
695         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
696         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
697         const char* strs   = (const char *) strdatap->d_buf;
698         string      module = "DEFAULT_MODULE";
699         string      name   = "DEFAULT_NAME";
700
701         // for shared objects add a module that is the file name
702         // and add all the global symbols as functions 
703         const char *libname = file_.string_of();
704         // find short name
705         const char *last = 0;
706         for(u_int i=0; i < file_.length();i++) {
707             if(libname[i] == '/'){
708                 last = (const char *)(&(libname[i]));
709                 // log_elferror(err_func_, P_strdup(last));
710             }
711         }
712         if(last){
713             module = (const char *)(last +1);  
714         }
715         else{
716             module = string("DEFAULT_MODULE");  
717         }
718         // string blah = string("module name: ");
719         // blah += module.string_of();
720         // blah += ("\n");
721         // log_elferror(err_func_, P_strdup(blah.string_of()));
722
723         vector<Symbol> allsymbols;
724         bool found = false;
725         for (unsigned i1 = 0; i1 < nsyms; i1++) {
726           // First, we must check st_shndx. 
727           // if st_shndx == SHN_UNDEF, this is an undefined symbol,
728           // probably defined in a shared object that will be dynamically
729           // linked with the executable. We just ignore it for now.
730           if (syms[i1].st_shndx != SHN_UNDEF) {
731             bool st_kludge = false;
732             Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
733             switch (ELF32_ST_TYPE(syms[i1].st_info)) {
734             case STT_FILE: {
735                 string temp2 = string(&strs[syms[i1].st_name]);
736                 if(temp2 == module){
737                     module = string(&strs[syms[i1].st_name]);
738                     type   = Symbol::PDST_MODULE;
739                     found = true;
740                 }
741                 break;
742                 }
743
744             case STT_OBJECT:
745                 type = Symbol::PDST_OBJECT;
746                 break;
747
748             case STT_FUNC:
749                 type = Symbol::PDST_FUNCTION;
750                 break;
751
752             case STT_NOTYPE:
753                 type = Symbol::PDST_NOTYPE;
754                 break;
755
756             default:
757                 continue;
758             }
759
760             name = string(&strs[syms[i1].st_name]);
761
762             // only add symbols of type STB_LOCAL and  FILE if they are 
763             // the shared object name
764             if ((ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL) && (found)){
765                    symbols_[name] = Symbol(name, module, type, Symbol::SL_LOCAL,
766                                     syms[i1].st_value, st_kludge, 
767                                     syms[i1].st_size);
768                    found = false;
769             }
770             else if((ELF32_ST_BIND(syms[i1].st_info) == STB_LOCAL)
771                         && (ELF32_ST_TYPE(syms[i1].st_info) != STT_FUNC)) {
772                 allsymbols += Symbol(name, module, type, Symbol::SL_LOCAL,
773                                                 syms[i1].st_value, st_kludge,
774                                                 syms[i1].st_size);
775             }
776             else {
777                if(ELF32_ST_BIND(syms[i1].st_info) == STB_WEAK){
778                    allsymbols += Symbol(name, module, 
779                                         type, Symbol::SL_WEAK,
780                                         syms[i1].st_value, st_kludge,
781                                         syms[i1].st_size);
782                }
783                else{
784                    allsymbols += Symbol(name, module, 
785                                         type, Symbol::SL_GLOBAL,
786                                         syms[i1].st_value, st_kludge,
787                                         syms[i1].st_size);
788                }
789             }
790           }
791         }
792
793
794         // Sort all the symbols, and fix the sizes
795         allsymbols.sort(symbol_compare);
796
797         // if the symbol is type PDST_FUNCTION and the next symbol is 
798         // type PDST_FUNCTION size needs to be changed...this occurs when
799         // one function's binding is WEAK and the other is GLOBAL, or when
800         // two functions overlap 
801         for(u_int i=0; i < (allsymbols.size() -1); i++){
802             u_int new_size = 0;
803             bool  change_size = false;
804
805             // some functions may have size zero in the symbol table
806             // we have to fix the size of the global functions
807             if (allsymbols[i].type() == Symbol::PDST_FUNCTION
808                 && allsymbols[i].linkage() == Symbol::SL_GLOBAL
809                 && allsymbols[i].size() == 0) {
810                unsigned j = i+1;
811                while (j < allsymbols.size() 
812                       && allsymbols[j].addr() == allsymbols[i].addr())
813                  j++;
814                allsymbols[i].change_size(allsymbols[j].addr()-allsymbols[i].addr());
815             }
816
817             if((allsymbols[i].type() == Symbol::PDST_FUNCTION)
818                 && (allsymbols[i+1].type() == Symbol::PDST_FUNCTION)){
819                 u_int next_start=allsymbols[i].addr()+allsymbols[i].size();
820
821                 // if the symbols have the same address and one is weak
822                 // and the other is global keeep the global one
823                 if((allsymbols[i].addr() == allsymbols[i+1].addr()) && 
824                     (((allsymbols[i].linkage() == Symbol::SL_WEAK) &&
825                       (allsymbols[i+1].linkage() == Symbol::SL_GLOBAL)) || 
826                      ((allsymbols[i].linkage() == Symbol::SL_GLOBAL) &&
827                       (allsymbols[i+1].linkage() == Symbol::SL_WEAK)))) {
828
829                       if(allsymbols[i].linkage() == Symbol::SL_WEAK){
830                           allsymbols[i].change_size(0);
831                       } else {
832                           allsymbols[i+1].change_size(0);
833                       }
834                 }
835                 else if(next_start > allsymbols[i+1].addr()){
836                         new_size =  allsymbols[i+1].addr()-allsymbols[i].addr();
837                         change_size = true;
838                 }
839             }
840
841             if((allsymbols[i].type() == Symbol::PDST_FUNCTION) && change_size){
842                 symbols_[allsymbols[i].name()] =
843                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
844                     allsymbols[i].type(), allsymbols[i].linkage(),
845                     allsymbols[i].addr(), allsymbols[i].kludge(),
846                     new_size);
847             }
848             else {
849                 symbols_[allsymbols[i].name()] =
850                     Symbol(allsymbols[i].name(), allsymbols[i].module(),
851                     allsymbols[i].type(), allsymbols[i].linkage(),
852                     allsymbols[i].addr(), allsymbols[i].kludge(),
853                     allsymbols[i].size());
854             }
855         }
856         // add last symbol
857         u_int last_sym = allsymbols.size()-1;
858         symbols_[allsymbols[last_sym].name()] =
859             Symbol(allsymbols[last_sym].name(), allsymbols[last_sym].module(),
860             allsymbols[last_sym].type(), allsymbols[last_sym].linkage(),
861             allsymbols[last_sym].addr(), allsymbols[last_sym].kludge(),
862             allsymbols[last_sym].size());
863
864     }  /* try */
865
866     /* catch */
867
868 cleanup2: {
869         if (did_elf && (elf_end(elfp) != 0)) {
870             log_elferror(err_func_, "closing file");
871         }
872         if (did_open && (close(fd) == -1)) {
873             log_perror(err_func_, "close");
874         }
875     }
876 }
877
878
879 inline
880 Object::Object(const string file, void (*err_func)(const char *))
881     : AObject(file, err_func) {
882     load_object();
883 }
884
885 inline
886 Object::Object(const string file, u_int ,void (*err_func)(const char *))
887     : AObject(file, err_func) {
888     load_shared_object();
889 }
890
891 inline
892 Object::Object(const Object& obj)
893     : AObject(obj) {
894     load_object();
895 }
896
897
898 \f
899
900
901 #endif /* !defined(_Object_elf32_h_) */