windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / Object-elf.h
1 /*
2  * Copyright (c) 1996-2007 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 /************************************************************************
33  * $Id: Object-elf.h,v 1.21 2008/06/23 18:45:42 legendre Exp $
34  * Object-elf.h: Object class for ELF file format
35 ************************************************************************/
36
37
38 #if !defined(_Object_elf_h_)
39 #define _Object_elf_h_
40
41 #if defined(USES_DWARF_DEBUG)
42 #include "dwarf.h"
43 #include "libdwarf.h"
44 #endif
45
46
47 #include "common/h/headers.h"
48 #include "common/h/Types.h"
49 #include "common/h/MappedFile.h"
50 #include "common/h/IntervalTree.h"
51
52 #if 0
53 #include "symtabAPI/h/Symbol.h"
54 #include "symtabAPI/h/Symtab.h"
55 #endif
56
57
58 #include <elf.h>
59 #include <libelf.h>
60 #include <string>
61
62 #include "Elf_X.h"
63
64 #include <fcntl.h>
65 #include <stdlib.h>
66 #include <unistd.h>
67
68 #include <sys/types.h>
69 #include <sys/mman.h>
70 #include <sys/stat.h>
71
72
73 namespace Dyninst{
74 namespace SymtabAPI{
75 /*
76  * The standard symbol table in an elf file is the .symtab section. This section does
77  * not have information to find the module to which a global symbol belongs, so we must
78  * also read the .stab section to get this info.
79  */
80
81 // Declarations for the .stab section.
82 // These are not declared in any system header files, so we must provide our own
83 // declarations. The declarations below were taken from:
84 //       SPARCWorks 3.0.x Debugger Interface, July 1994
85 // 
86 struct stab32 {
87     unsigned int name;  // stabstr table index for this symbol
88     unsigned char type; // type of this symbol
89     unsigned char other;
90     unsigned short desc;
91     unsigned int val;   // value of this symbol -- usually zero. The real value must
92                         // be obtained from the symtab section
93 };
94 struct stab64 {
95     // XXX ELF stabs are currently not implementing actual 64-bit support
96     //     on AMD-64, for which this separation was introduced. Until we
97     //     start seeing stab records with fields of the appropriate length,
98     //     we should assume the smaller records.
99     //unsigned long name; // stabstr table index for this symbol
100     unsigned int name; // stabstr table index for this symbol
101     unsigned char type; // type of this symbol
102     unsigned char other;
103     unsigned short desc;
104     //unsigned long val;
105     unsigned int val;  // value of this symbol -- usually zero. The real value must
106                         // be obtained from the symtab section
107 };
108
109 // 
110 // Extended to a class for 32/64-bit stab entries at runtime. - Ray
111 // 
112 class stab_entry {
113   public:
114     stab_entry(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
115         : stabptr(_stabptr), stabstr(_stabstr), nsyms(_nsyms) { }
116     virtual ~stab_entry() {};
117
118     virtual const char *name(int i) = 0;
119     virtual unsigned long nameIdx(int i) = 0;
120     virtual unsigned char type(int i) = 0;
121     virtual unsigned char other(int i) = 0;
122     virtual unsigned short desc(int i) = 0;
123     virtual unsigned long val(int i) = 0;
124
125     unsigned long count() { return nsyms; }
126     void setStringBase(const char *ptr) { stabstr = const_cast<char *>(ptr); }
127     const char *getStringBase() { return stabstr; }
128
129   protected:
130     void *stabptr;
131     const char *stabstr;
132     long nsyms;
133 };
134
135 class stab_entry_32 : public stab_entry {
136   public:
137     stab_entry_32(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
138         : stab_entry(_stabptr, _stabstr, _nsyms) { }
139     virtual ~stab_entry_32() {};
140
141     const char *name(int i = 0) { 
142        if (!stabptr) {
143           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
144                 FILE__, __LINE__);
145           return "bad_name";
146        }
147        return stabstr + ((stab32 *)stabptr)[i].name; 
148     }
149     unsigned long nameIdx(int i = 0) {
150        if (!stabptr) {
151           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
152                 FILE__, __LINE__);
153           return 0L;
154        }
155        return ((stab32 *)stabptr)[i].name; 
156     }
157     unsigned char type(int i = 0) {
158        if (!stabptr) {
159           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
160                 FILE__, __LINE__);
161           return 0;
162        }
163        return ((stab32 *)stabptr)[i].type; 
164     }
165     unsigned char other(int i = 0) {
166        if (!stabptr) {
167           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
168                 FILE__, __LINE__);
169           return 0;
170        }
171        return ((stab32 *)stabptr)[i].other; 
172     }
173     unsigned short desc(int i = 0) { 
174        if (!stabptr) {
175           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
176                 FILE__, __LINE__);
177           return 0;
178        }
179        return ((stab32 *)stabptr)[i].desc; 
180     }
181     unsigned long val(int i = 0) { 
182        if (!stabptr) {
183           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
184                 FILE__, __LINE__);
185           return 0L;
186        }
187        return ((stab32 *)stabptr)[i].val; 
188     }
189 };
190
191 class stab_entry_64 : public stab_entry {
192   public:
193     stab_entry_64(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
194         : stab_entry(_stabptr, _stabstr, _nsyms) { }
195     virtual ~stab_entry_64() {};
196
197     const char *name(int i = 0) { 
198        if (!stabptr) {
199           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
200                 FILE__, __LINE__);
201           return "bad_name";
202        }
203        return stabstr + ((stab64 *)stabptr)[i].name; 
204     }
205     unsigned long nameIdx(int i = 0) {
206        if (!stabptr) {
207           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
208                 FILE__, __LINE__);
209           return 0L;
210        }
211        return ((stab64 *)stabptr)[i].name; 
212     }
213     unsigned char type(int i = 0) {
214        if (!stabptr) {
215           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
216                 FILE__, __LINE__);
217           return 0;
218        }
219        return ((stab64 *)stabptr)[i].type; 
220     }
221     unsigned char other(int i = 0) { 
222        if (!stabptr) {
223           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
224                 FILE__, __LINE__);
225           return 0;
226        }
227        return ((stab64 *)stabptr)[i].other; 
228     }
229     unsigned short desc(int i = 0) { 
230        if (!stabptr) {
231           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
232                 FILE__, __LINE__);
233           return 0;
234        }
235        return ((stab64 *)stabptr)[i].desc; 
236     }
237     unsigned long val(int i = 0) { 
238        if (!stabptr) {
239           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
240                 FILE__, __LINE__);
241           return 0L;
242        }
243        return ((stab64 *)stabptr)[i].val; 
244     }
245 };
246
247 // Types 
248 #define N_UNDF  0x00 /* start of object file */
249 #define N_GSYM  0x20 /* global symbol */
250 #define N_FUN   0x24 /* function or procedure */
251 #define N_STSYM 0x26 /* initialized static symbol */
252 #define N_LCSYM 0x28 /* unitialized static symbol */
253 #define N_ROSYM 0x2c /* read-only static symbol */
254 #define N_OPT   0x3c /* compiler options */
255 #define N_ENDM  0x62 /* end module */
256 #define N_SO    0x64 /* source directory and file */
257 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
258 #define N_BCOMM 0xe2 /* start fortran named common block */
259 #define N_ECOMM 0xe4 /* start fortran named common block */
260
261 // Language code -- the desc field in a N_SO entry is a language code
262 #define N_SO_AS      1 /* assembler source */
263 #define N_SO_C       2 /* K & R C source */
264 #define N_SO_ANSI_C  3 /* ANSI C source */
265 #define N_SO_CC      4 /* C++ source */
266 #define N_SO_FORTRAN 5 /* fortran source */
267 #define N_SO_PASCAL  6 /* Pascal source */
268 #define N_SO_F90     7 /* Fortran90 source */
269
270 //line information data
271 #define N_SLINE  0x44 /* line number in text segment */
272 #define N_SOL    0x84 /* name of the include file*/
273
274 // Symbol descriptors
275 // The format of a name is "<name>:<symbol descriptor><rest of name>
276 // The following are the descriptors of interest
277 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
278 #define SD_PROTOTYPE  'P'  /* function prototypes */
279 #define SD_GLOBAL_VAR 'G' /* global variable */
280
281 // end of stab declarations
282
283 class pdElfShdr;
284
285 class Symtab;
286 class Region;
287 class Object;
288
289 typedef struct {
290   Dwarf_Fde *fde_data;
291   Dwarf_Signed fde_count;
292   Dwarf_Cie *cie_data;
293   Dwarf_Signed cie_count;   
294 } fde_cie_data;
295
296 class DwarfHandle {
297    friend class Object;
298  private:
299    typedef enum {
300       dwarf_status_uninitialized,
301       dwarf_status_error,
302       dwarf_status_ok
303    } dwarf_status_t;
304    dwarf_status_t fde_dwarf_status;
305    dwarf_status_t init_dwarf_status;
306
307    std::vector<fde_cie_data> fde_data;
308    Dwarf_Debug dbg_data;
309    Object *obj;
310
311  public:
312   DwarfHandle(Object *obj_);
313   ~DwarfHandle();
314
315
316   Dwarf_Debug *dbg();
317   void setupFdeData();
318 };
319
320 class Object : public AObject {
321   friend class DwarfHandle;   
322  public:
323   Object() : dwarf(this) {}
324   Object(MappedFile *, MappedFile *, void (*)(const char *) = log_msg, bool alloc_syms = true);
325   Object(MappedFile *, MappedFile *, dyn_hash_map<std::string, LineInformation> &, std::vector<Region *> &, void (*)(const char *) = log_msg);
326   Object(MappedFile *, MappedFile *, std::string &member_name, Offset offset,   
327           void (*)(const char *) = log_msg, void *base = NULL, bool alloc_syms = true);
328   Object(const Object &);
329   virtual ~Object();
330   //const Object& operator=(const Object &);
331
332   bool emitDriver(Symtab *obj, std::string fName, std::vector<Symbol *>&allSymbols, unsigned flag);  
333   
334   const char *elf_vaddr_to_ptr(Offset vaddr) const;
335   bool hasStabInfo() const { return ! ( !stab_off_ || !stab_size_ || !stabstr_off_ ); }
336   bool hasDwarfInfo() const { return dwarvenDebugInfo; }
337   stab_entry * get_stab_info() const;
338   const char * getFileName() const { return mf->filename().c_str(); }
339   void getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs);
340   void parseFileLineInfo(Symtab *obj, dyn_hash_map<std::string, LineInformation> &li);
341   void parseTypeInfo(Symtab *obj);
342
343   bool needs_function_binding() const { return (plt_addr_ > 0); } 
344   bool get_func_binding_table(std::vector<relocationEntry> &fbt) const;
345   bool get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const;
346   void getDependencies(std::vector<std::string> &deps);
347
348   bool addRelocationEntry(relocationEntry &re);
349
350   //getLoadAddress may return 0 on shared objects
351   Offset getLoadAddress() const { return loadAddress_; }
352
353   Offset getEntryAddress() const { return entryAddress_; }
354   // To be changed later - Giri
355   Offset getBaseAddress() const { return 0; }
356   static bool truncateLineFilenames;
357  
358   virtual char *mem_image() const 
359   {
360      assert(mf);
361      return (char *)mf->base_addr();
362   }
363
364   SYMTAB_EXPORT ObjectType objType() const;
365   const char *interpreter_name() const;
366
367
368 //TODO Later - change this #ifdef later.. make getTOCoffset available for all platforms  
369
370 #if defined(arch_ia64)
371   Offset getTOCoffset() const { return gp; }
372 #elif defined(os_linux) && defined(arch_power) && defined(arch_64bit)
373   // 64-bit PowerPC ELF ABI Supplement, Version 1.9, 2004-10-23:
374   //   The TOC section contains a conventional ELF GOT, and may optionally
375   //   contain a small data area.
376   //   The TOC base is typically the first address in the TOC plus 0x8000.
377   // I don't understand why I can find a ".got" within binaries, but I can't
378   // find a ".toc".  ssuen  August 7, 2007
379   Offset getTOCoffset() const { return got_addr_ + 0x8000; }
380 #else
381   Offset getTOCoffset() const { return 0; }
382 #endif
383
384   const std::ostream &dump_state_info(std::ostream &s);
385   bool isEEL() { return EEL; }
386
387         //to determine if a mutation falls in the text section of
388         // a shared library
389         bool isinText(Offset addr, Offset baseaddr) const { 
390                 //printf(" baseaddr %x TESTING %x %x \n", baseaddr, text_addr_ + baseaddr  , text_addr_ + baseaddr + text_size_ );
391                 if(addr > text_addr_ + baseaddr     &&
392                    addr < text_addr_ + baseaddr + text_size_ ) {
393                         return true;
394                 }
395                 return false;
396         } 
397         // to determine where in the .plt this function is listed 
398         // returns an offset from the base address of the object
399         // so the entry can easily be located in memory
400         Offset getPltSlot(std::string funcName) const ;
401         Offset textAddress(){ return text_addr_;}
402         bool isText( Offset addr ) const
403         {
404             if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
405                 return true;
406             return false;
407         }
408
409         bool is_offset_in_plt(Offset offset) const;
410     Elf_X_Shdr *getRegionHdrByAddr(Offset addr);
411     bool isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned newPerms);
412
413     bool getRegValueAtFrame(Address pc, 
414                             Dyninst::MachRegister reg, 
415                             Dyninst::MachRegisterVal &reg_result,
416                             MemRegReader *reader);
417     bool hasFrameDebugInfo();
418
419     bool convertDebugOffset(Offset off, Offset &new_off);
420  private:
421   static void log_elferror (void (*)(const char *), const char *);
422     
423   Elf_X    elfHdr;
424
425   Elf_X    elfHdrForDebugInfo;
426   
427   Offset   fini_addr_;
428   Offset   text_addr_;   //.text section 
429   Offset   text_size_;   //.text section size
430   Offset   dynamic_addr_;        //.dynamic section
431   Offset   dynsym_addr_;        // .dynsym section
432   Offset   dynstr_addr_;        // .dynstr section
433   Offset   opd_addr_;
434   unsigned opd_size_;
435   Offset   got_addr_;           // global offset table
436   unsigned got_size_;           // global offset table
437   Offset   plt_addr_;           // procedure linkage table
438   unsigned plt_size_;           // procedure linkage table
439   unsigned plt_entry_size_;     // procedure linkage table
440   Offset   rel_plt_addr_;       // .rel[a].plt section
441   unsigned rel_plt_size_;       // .rel[a].plt section
442   unsigned rel_plt_entry_size_; // .rel[a].plt section
443   
444   unsigned  rel_size_;       // DT_REL/DT_RELA in dynamic section
445   unsigned  rel_entry_size_; // DT_REL/DT_RELA in dynamic section
446
447   Offset   stab_off_;           // .stab section
448   unsigned stab_size_;          // .stab section
449   Offset   stabstr_off_;        // .stabstr section
450
451   Offset   stab_indx_off_;       // .stab.index section
452   unsigned  stab_indx_size_;     // .stab.index section
453   Offset   stabstr_indx_off_;    // .stabstr.index section
454
455   bool      dwarvenDebugInfo;    // is DWARF debug info present?
456   Offset   loadAddress_;      // The object may specify a load address
457                                //   Set to 0 if it may load anywhere
458   Offset entryAddress_;
459   char *interpreter_name_;
460   bool  isStripped;
461   bool usesDebugFile;
462
463   DwarfHandle dwarf;
464
465 #if defined(arch_ia64)
466   Offset   gp;                   // The gp for this object.
467 #endif
468   bool      EEL;                 // true if EEL rewritten
469   bool      did_open;           // true if the file has been mmapped
470   ObjectType obj_type_;
471
472   // for sparc-solaris this is a table of PLT entry addr, function_name
473   // for x86-solaris this is a table of GOT entry addr, function_name
474   // on sparc-solaris the runtime linker modifies the PLT entry when it
475   // binds a function, on X86 the PLT entry is not modified, but it uses
476   // an indirect jump to a GOT entry that is modified when the function 
477   // is bound....is this correct???? or should it be <PLTentry_addr, name> 
478   // for both?
479   std::vector<relocationEntry> relocation_table_;
480   std::vector<relocationEntry> fbt_;
481
482   // all section headers, sorted by address
483   // we use these to do a better job of finding the end of symbols
484   std::vector<Elf_X_Shdr*> allRegionHdrs;
485
486   // Symbol version mappings. used to store symbol version names.
487   dyn_hash_map<unsigned, std::vector<std::string> >versionMapping;
488   dyn_hash_map<unsigned, std::string> versionFileNameMapping;
489
490   std::vector<std::string> deps_;
491
492   bool loaded_elf( Offset &, Offset &,
493                     Elf_X_Shdr* &,
494                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
495                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
496                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
497                     Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
498                     Elf_X_Shdr*& opd_scnp, Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
499                     Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& dynamic_scnp, Elf_X_Shdr*& eh_frame,
500                     Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp,
501           bool a_out=false);
502   
503   void parseStabFileLineInfo(Symtab *, dyn_hash_map<std::string, LineInformation> &li);
504   void parseDwarfFileLineInfo(dyn_hash_map<std::string, LineInformation> &li);
505
506   void parseDwarfTypes(Symtab *obj);
507   void parseStabTypes(Symtab *obj);
508
509   void load_object(bool);
510   void load_shared_object(bool);
511
512   // initialize relocation_table_ from .rel[a].plt section entries 
513   bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
514                               Elf_X_Shdr *&dynsym_scnp, 
515                               Elf_X_Shdr *&dynstr_scnp);
516
517   bool get_relocationDyn_entries( Elf_X_Shdr *&rel_scnp,
518                      Elf_X_Shdr *&dynsym_scnp,
519                      Elf_X_Shdr *&dynstr_scnp );
520   
521   void parseDynamic(Elf_X_Shdr *& dyn_scnp, Elf_X_Shdr *&dynsym_scnp, 
522                     Elf_X_Shdr *&dynstr_scnp);
523   
524   bool parse_symbols(Elf_X_Data &symdata, Elf_X_Data &strdata,
525                      Elf_X_Shdr* bssscnp,
526                      Elf_X_Shdr* symscnp,
527                      Elf_X_Shdr* opdscnp,
528                      bool shared_library,
529                      std::string module);
530   
531   void parse_dynamicSymbols( Elf_X_Shdr *& dyn_scnp, Elf_X_Data &symdata,
532                              Elf_X_Data &strdata, Elf_X_Shdr* opdscnp,
533                              bool shared_library, std::string module);
534
535   void find_code_and_data(Elf_X &elf,
536        Offset txtaddr, Offset dataddr);
537   //void insert_symbols_static(std::vector<Symbol *> &allsymbols);
538   bool fix_global_symbol_modules_static_stab(Elf_X_Shdr *stabscnp,
539                                              Elf_X_Shdr *stabstrscnp);
540   bool fix_global_symbol_modules_static_dwarf();
541
542   void get_valid_memory_areas(Elf_X &elf);
543
544   MappedFile *findMappedFileForDebugInfo();
545   bool find_catch_blocks(Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
546                          Address textaddr, Address dataaddr,
547                          std::vector<ExceptionBlock> &catch_addrs);
548
549 #if defined(USES_DWARF_DEBUG)
550   std::string find_symbol(std::string name); 
551   void fixSymbolsInModule(Dwarf_Debug dbg, std::string & moduleName, Dwarf_Die dieEntry);
552   unsigned fixSymbolsInModuleByRange(IntervalTree<Dwarf_Addr, std::string> &module_ranges);
553 #endif
554
555  public:
556   struct DbgAddrConversion_t {
557      DbgAddrConversion_t() : dbg_offset(0x0), dbg_size(0x0), orig_offset(0x0) {}
558      std::string name;
559      Offset dbg_offset;
560      unsigned dbg_size;
561      Offset orig_offset;
562   };
563  private:
564   bool DbgSectionMapSorted;
565   std::vector<DbgAddrConversion_t> DebugSectionMap;
566 };
567
568
569 //const char *pdelf_get_shnames(Elf *elfp, bool is64);
570
571 }//namespace SymtabAPI
572 }//namespace Dyninst
573
574 #endif /* !defined(_Object_elf_h_) */