1) Cmake support for PPC64LE builds
[dyninst.git] / symtabAPI / src / Object-elf.h
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 /************************************************************************
32  * $Id: Object-elf.h,v 1.21 2008/06/23 18:45:42 legendre Exp $
33  * Object-elf.h: Object class for ELF file format
34 ************************************************************************/
35
36
37 #if !defined(_Object_elf_h_)
38 #define _Object_elf_h_
39
40 #if defined(cap_dwarf)
41 //#include "dwarf.h"
42 #include "libdwarf.h"
43 #include "dwarfHandle.h"
44 #endif
45
46 #include <vector>
47 #include "headers.h"
48 #include "Types.h"
49 #include "MappedFile.h"
50 #include "IntervalTree.h"
51
52 #include <elf.h>
53 #include <libelf.h>
54 #include <string>
55
56 #include "Elf_X.h"
57
58 #include <fcntl.h>
59 #include <stdlib.h>
60 #include <unistd.h>
61 #include <set>
62 #include <sys/types.h>
63 #include <sys/mman.h>
64 #include <sys/stat.h>
65
66
67 namespace Dyninst{
68
69 namespace Dwarf {
70    class DwarfFrameParser;
71    typedef boost::shared_ptr<DwarfFrameParser> DwarfFrameParserPtr;
72 }
73
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           return "bad_name";
144        }
145        return stabstr + ((stab32 *)stabptr)[i].name; 
146     }
147     unsigned long nameIdx(int i = 0) {
148        if (!stabptr) {
149           return 0L;
150        }
151        return ((stab32 *)stabptr)[i].name; 
152     }
153     unsigned char type(int i = 0) {
154        if (!stabptr) {
155           return 0;
156        }
157        return ((stab32 *)stabptr)[i].type; 
158     }
159     unsigned char other(int i = 0) {
160        if (!stabptr) {
161           return 0;
162        }
163        return ((stab32 *)stabptr)[i].other; 
164     }
165     unsigned short desc(int i = 0) { 
166        if (!stabptr) {
167           return 0;
168        }
169        return ((stab32 *)stabptr)[i].desc; 
170     }
171     unsigned long val(int i = 0) { 
172        if (!stabptr) {
173           return 0L;
174        }
175        return ((stab32 *)stabptr)[i].val; 
176     }
177 };
178
179 class stab_entry_64 : public stab_entry {
180   public:
181     stab_entry_64(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
182         : stab_entry(_stabptr, _stabstr, _nsyms) { }
183     virtual ~stab_entry_64() {};
184
185     const char *name(int i = 0) { 
186        if (!stabptr) {
187           return "bad_name";
188        }
189        return stabstr + ((stab64 *)stabptr)[i].name; 
190     }
191     unsigned long nameIdx(int i = 0) {
192        if (!stabptr) {
193           return 0L;
194        }
195        return ((stab64 *)stabptr)[i].name; 
196     }
197     unsigned char type(int i = 0) {
198        if (!stabptr) {
199           return 0;
200        }
201        return ((stab64 *)stabptr)[i].type; 
202     }
203     unsigned char other(int i = 0) { 
204        if (!stabptr) {
205           return 0;
206        }
207        return ((stab64 *)stabptr)[i].other; 
208     }
209     unsigned short desc(int i = 0) { 
210        if (!stabptr) {
211           return 0;
212        }
213        return ((stab64 *)stabptr)[i].desc; 
214     }
215     unsigned long val(int i = 0) { 
216        if (!stabptr) {
217           return 0L;
218        }
219        return ((stab64 *)stabptr)[i].val; 
220     }
221 };
222
223 // Types 
224 #define N_UNDF  0x00 /* start of object file */
225 #define N_GSYM  0x20 /* global symbol */
226 #define N_FUN   0x24 /* function or procedure */
227 #define N_STSYM 0x26 /* initialized static symbol */
228 #define N_LCSYM 0x28 /* unitialized static symbol */
229 #define N_ROSYM 0x2c /* read-only static symbol */
230 #define N_OPT   0x3c /* compiler options */
231 #define N_ENDM  0x62 /* end module */
232 #define N_SO    0x64 /* source directory and file */
233 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
234 #define N_BCOMM 0xe2 /* start fortran named common block */
235 #define N_ECOMM 0xe4 /* start fortran named common block */
236
237 // Language code -- the desc field in a N_SO entry is a language code
238 #define N_SO_AS      1 /* assembler source */
239 #define N_SO_C       2 /* K & R C source */
240 #define N_SO_ANSI_C  3 /* ANSI C source */
241 #define N_SO_CC      4 /* C++ source */
242 #define N_SO_FORTRAN 5 /* fortran source */
243 #define N_SO_PASCAL  6 /* Pascal source */
244 #define N_SO_F90     7 /* Fortran90 source */
245
246 //line information data
247 #define N_SLINE  0x44 /* line number in text segment */
248 #define N_SOL    0x84 /* name of the include file*/
249
250 // Symbol descriptors
251 // The format of a name is "<name>:<symbol descriptor><rest of name>
252 // The following are the descriptors of interest
253 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
254 #define SD_PROTOTYPE  'P'  /* function prototypes */
255 #define SD_GLOBAL_VAR 'G' /* global variable */
256
257 // end of stab declarations
258
259 class pdElfShdr;
260 class Symtab;
261 class Region;
262 class Object;
263
264         class Object : public AObject {
265
266   // declared but not implemented; no copying allowed
267   Object(const Object &);
268   const Object& operator=(const Object &);
269
270  public:
271   Object(MappedFile *, bool, void (*)(const char *) = log_msg, bool alloc_syms = true);
272   virtual ~Object();
273
274   bool emitDriver(Symtab *obj, std::string fName, std::vector<Symbol *>&allSymbols, unsigned flag);  
275   
276   const char *elf_vaddr_to_ptr(Offset vaddr) const;
277   bool hasStabInfo() const { return ! ( !stab_off_ || !stab_size_ || !stabstr_off_ ); }
278   bool hasDwarfInfo() const { return dwarvenDebugInfo; }
279   stab_entry * get_stab_info() const;
280   std::string getFileName() const;
281   void getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs);
282   void parseFileLineInfo(Symtab *obj);
283   
284   void parseTypeInfo(Symtab *obj);
285
286   bool needs_function_binding() const { return (plt_addr_ > 0); } 
287   bool get_func_binding_table(std::vector<relocationEntry> &fbt) const;
288   bool get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const;
289   void getDependencies(std::vector<std::string> &deps);
290   std::vector<std::string> &libsRMd();
291
292   bool addRelocationEntry(relocationEntry &re);
293
294   //getLoadAddress may return 0 on shared objects
295   Offset getLoadAddress() const { return loadAddress_; }
296
297   Offset getEntryAddress() const { return entryAddress_; }
298   // To be changed later - Giri
299   Offset getBaseAddress() const { return 0; }
300   static bool truncateLineFilenames;
301
302   void insertPrereqLibrary(std::string libname);
303   bool removePrereqLibrary(std::string libname);
304   void insertDynamicEntry(long name, long value);
305  
306   virtual char *mem_image() const 
307   {
308      assert(mf);
309      return (char *)mf->base_addr();
310   }
311
312   SYMTAB_EXPORT ObjectType objType() const;
313   const char *interpreter_name() const;
314
315
316   // On most platforms, the TOC offset doesn't exist and is thus null. 
317   // On PPC64, it varies _by function_ and is used to point into the GOT,
318   // a big data table. We can look it up by parsing the OPD, a function
319   // descriptor table. 
320   Offset getTOCoffset(Offset off) const;
321
322   // This is an override for the whole thing; we could do per-function but 
323   // we're missing a _lot_ of hardware for that. 
324   void setTOCoffset(Offset off);
325
326   const std::ostream &dump_state_info(std::ostream &s);
327   bool isEEL() { return EEL; }
328
329         //to determine if a mutation falls in the text section of
330         // a shared library
331         bool isinText(Offset addr, Offset baseaddr) const { 
332                 if(addr > text_addr_ + baseaddr     &&
333                    addr < text_addr_ + baseaddr + text_size_ ) {
334                         return true;
335                 }
336                 return false;
337         } 
338         // to determine where in the .plt this function is listed 
339         // returns an offset from the base address of the object
340         // so the entry can easily be located in memory
341         Offset getPltSlot(std::string funcName) const ;
342         Offset textAddress(){ return text_addr_;}
343         bool isText( Offset addr ) const
344         {
345             if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
346                 return true;
347             return false;
348         }
349
350    Dyninst::Architecture getArch();
351    bool isBigEndianDataEncoding() const;
352    int getABIVersion() const;
353         bool is_offset_in_plt(Offset offset) const;
354     Elf_X_Shdr *getRegionHdrByAddr(Offset addr);
355     int getRegionHdrIndexByAddr(Offset addr);
356     Elf_X_Shdr *getRegionHdrByIndex(unsigned index);
357     bool isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned newPerms);
358
359     bool getRegValueAtFrame(Address pc, 
360                             Dyninst::MachRegister reg, 
361                             Dyninst::MachRegisterVal &reg_result,
362                             MemRegReader *reader);
363     bool hasFrameDebugInfo();
364     
365     bool convertDebugOffset(Offset off, Offset &new_off);
366
367     std::vector< std::vector<Offset> > getMoveSecAddrRange() const {return moveSecAddrRange;};
368     dyn_hash_map<int, Region*> getTagRegionMapping() const { return secTagRegionMapping;}
369
370     bool hasReldyn() const {return hasReldyn_;}
371     bool hasReladyn() const {return hasReladyn_;}
372     bool hasRelplt() const {return hasRelplt_;}
373     bool hasRelaplt() const {return hasRelaplt_;}
374     bool isBlueGeneP() const {return isBlueGeneP_;}
375     bool isBlueGeneQ() const {return isBlueGeneQ_;}
376     bool hasNoteSection() const {return hasNoteSection_;}
377     Region::RegionType getRelType() const { return relType_; }
378
379     Offset getTextAddr() const {return text_addr_;}
380     Offset getSymtabAddr() const {return symtab_addr_;}
381     Offset getStrtabAddr() const {return strtab_addr_;}
382     Offset getDynamicAddr() const {return dynamic_addr_;}
383     Offset getDynsymSize() const {return dynsym_size_;}
384     Offset getElfHashAddr() const {return elf_hash_addr_;}
385     Offset getGnuHashAddr() const {return gnu_hash_addr_;}
386     Offset getRelPLTAddr() const { return rel_plt_addr_; }
387     Offset getRelPLTSize() const { return rel_plt_size_; }
388     Offset getRelDynAddr() const { return rel_addr_; }
389     Offset getRelDynSize() const { return rel_size_; }
390
391     std::vector<relocationEntry> &getPLTRelocs() { return fbt_; }
392     std::vector<relocationEntry> &getDynRelocs() { return relocation_table_; }
393
394     Offset getInitAddr() const {return init_addr_; }
395     Offset getFiniAddr() const { return fini_addr_; }
396
397     virtual void setTruncateLinePaths(bool value);
398     virtual bool getTruncateLinePaths();
399     
400     Elf_X * getElfHandle() { return elfHdr; }
401
402     unsigned gotSize() const { return got_size_; }
403     Offset gotAddr() const { return got_addr_; }
404
405     SYMTAB_EXPORT virtual void getSegmentsSymReader(std::vector<SymSegment> &segs); 
406
407   private:
408             std::vector<boost::shared_ptr<void> > freeList;
409   static void log_elferror (void (*)(const char *), const char *);
410     
411   Elf_X *elfHdr;
412  
413   std::vector< std::vector<Offset> > moveSecAddrRange;
414   dyn_hash_map<Offset, int> secAddrTagMapping;
415   dyn_hash_map<int, unsigned long> secTagSizeMapping;
416   dyn_hash_map<int, Region*> secTagRegionMapping;
417
418   bool hasReldyn_;
419   bool hasReladyn_;
420   bool hasRelplt_;
421   bool hasRelaplt_;
422   Region::RegionType relType_;
423
424   bool isBlueGeneP_;
425   bool isBlueGeneQ_;
426   bool hasNoteSection_;
427
428   Offset   elf_hash_addr_;       //.hash section 
429   Offset   gnu_hash_addr_;       //.gnu.hash section 
430
431   Offset   dynamic_offset_;
432   size_t   dynamic_size_;
433   size_t   dynsym_size_;
434   Offset   init_addr_;
435   Offset   fini_addr_;
436   Offset   text_addr_;   //.text section 
437   Offset   text_size_;   //.text section size
438   Offset   symtab_addr_;
439   Offset   strtab_addr_;
440   Offset   dynamic_addr_;        //.dynamic section
441   Offset   dynsym_addr_;        // .dynsym section
442   Offset   dynstr_addr_;        // .dynstr section
443   Offset   got_addr_;           // global offset table
444   unsigned got_size_;           // global offset table
445   Offset   plt_addr_;           // procedure linkage table
446   unsigned plt_size_;           // procedure linkage table
447   unsigned plt_entry_size_;     // procedure linkage table
448   Offset   rel_plt_addr_;       // .rel[a].plt section
449   unsigned rel_plt_size_;       // .rel[a].plt section
450   unsigned rel_plt_entry_size_; // .rel[a].plt section
451   Offset    rel_addr_;
452   unsigned  rel_size_;       // DT_REL/DT_RELA in dynamic section
453   unsigned  rel_entry_size_; // DT_REL/DT_RELA in dynamic section
454   Offset   opd_addr_;
455   unsigned opd_size_;
456
457   Offset   stab_off_;           // .stab section
458   unsigned stab_size_;          // .stab section
459   Offset   stabstr_off_;        // .stabstr section
460
461   Offset   stab_indx_off_;       // .stab.index section
462   unsigned  stab_indx_size_;     // .stab.index section
463   Offset   stabstr_indx_off_;    // .stabstr.index section
464
465   bool      dwarvenDebugInfo;    // is DWARF debug info present?
466   Offset   loadAddress_;      // The object may specify a load address
467                                //   Set to 0 if it may load anywhere
468   Offset entryAddress_;
469   char *interpreter_name_;
470   bool  isStripped;
471
472   std::map<Offset, Offset> TOC_table_;
473
474   public:
475   Dyninst::Dwarf::DwarfHandle::ptr dwarf;
476   private:
477
478   bool      EEL;                 // true if EEL rewritten
479   bool      did_open;           // true if the file has been mmapped
480   ObjectType obj_type_;
481
482   // for sparc-solaris this is a table of PLT entry addr, function_name
483   // for x86-solaris this is a table of GOT entry addr, function_name
484   // on sparc-solaris the runtime linker modifies the PLT entry when it
485   // binds a function, on X86 the PLT entry is not modified, but it uses
486   // an indirect jump to a GOT entry that is modified when the function 
487   // is bound....is this correct???? or should it be <PLTentry_addr, name> 
488   // for both?
489   std::vector<relocationEntry> relocation_table_;
490   std::vector<relocationEntry> fbt_;
491
492   // all section headers, sorted by address
493   // we use these to do a better job of finding the end of symbols
494   std::vector<Elf_X_Shdr*> allRegionHdrs;
495   std::vector<Elf_X_Shdr*> allRegionHdrsByShndx;
496
497   // Symbol version mappings. used to store symbol version names.
498   dyn_hash_map<unsigned, std::vector<std::string> >versionMapping;
499   dyn_hash_map<unsigned, std::string> versionFileNameMapping;
500
501   std::vector<std::string> deps_;
502   std::vector<std::string> rmd_deps;
503
504   bool loaded_elf( Offset &, Offset &,
505                     Elf_X_Shdr* &,
506                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
507                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
508                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
509                     Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
510                     Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
511                     Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& dynamic_scnp, Elf_X_Shdr*& eh_frame,
512                     Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp,
513                    Elf_X_Shdr *&opd_scnp,
514           bool a_out=false);
515   
516   Symbol *handle_opd_symbol(Region *opd, Symbol *sym);
517   void handle_opd_relocations();
518   void parse_opd(Elf_X_Shdr *);
519   void parseStabFileLineInfo(Symtab *);
520  public:
521   void parseDwarfFileLineInfo(Symtab* obj);
522   void parseLineInfoForAddr(Symtab* obj, Offset addr_to_find);
523   
524  private:
525             bool addrInCU(Dwarf_Debug dbg, Dwarf_Die cu, Address to_find);
526   void parseLineInfoForCU(Dwarf_Die cuDIE, LineInformation* li);
527   
528   
529   void createLineInfoForModules(dyn_hash_map<std::string, LineInformation> &li);
530   void parseDwarfTypes(Symtab *obj);
531   void parseStabTypes(Symtab *obj);
532
533   void load_object(bool);
534   void load_shared_object(bool);
535
536   // initialize relocation_table_ from .rel[a].plt section entries 
537   bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
538                               Elf_X_Shdr *&dynsym_scnp, 
539                               Elf_X_Shdr *&dynstr_scnp);
540
541   bool get_relocationDyn_entries( unsigned rel_index,
542                      Elf_X_Shdr *&dynsym_scnp,
543                      Elf_X_Shdr *&dynstr_scnp );
544
545   // Parses sections with relocations and links these relocations to
546   // existing symbols
547   bool parse_all_relocations(Elf_X &, Elf_X_Shdr *, Elf_X_Shdr *,
548           Elf_X_Shdr *, Elf_X_Shdr *);
549   
550   void parseDynamic(Elf_X_Shdr *& dyn_scnp, Elf_X_Shdr *&dynsym_scnp, 
551                     Elf_X_Shdr *&dynstr_scnp);
552   
553   bool parse_symbols(Elf_X_Data &symdata, Elf_X_Data &strdata,
554                      Elf_X_Shdr* bssscnp,
555                      Elf_X_Shdr* symscnp,
556                      bool shared_library,
557                      std::string module);
558   
559   void parse_dynamicSymbols( Elf_X_Shdr *& dyn_scnp, Elf_X_Data &symdata,
560                              Elf_X_Data &strdata, bool shared_library,
561                              std::string module);
562
563   void find_code_and_data(Elf_X &elf,
564        Offset txtaddr, Offset dataddr);
565   bool fix_global_symbol_modules_static_stab(Elf_X_Shdr *stabscnp,
566                                              Elf_X_Shdr *stabstrscnp);
567   bool fix_global_symbol_modules_static_dwarf();
568
569   void get_valid_memory_areas(Elf_X &elf);
570
571   bool find_catch_blocks(Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
572                          Address textaddr, Address dataaddr,
573                          std::vector<ExceptionBlock> &catch_addrs);
574   // Line info: CUs to skip
575   std::set<std::string> modules_parsed_for_line_info;
576 #if defined(cap_dwarf)
577   std::string find_symbol(std::string name); 
578   bool fixSymbolsInModule(Dwarf_Debug dbg, std::string & moduleName, Dwarf_Die dieEntry);
579   unsigned fixSymbolsInModuleByRange(IntervalTree<Dwarf_Addr, std::string> &module_ranges);
580
581 #endif
582
583  public:
584   struct DbgAddrConversion_t {
585      DbgAddrConversion_t() : dbg_offset(0x0), dbg_size(0x0), orig_offset(0x0) {}
586      std::string name;
587      Offset dbg_offset;
588      unsigned dbg_size;
589      Offset orig_offset;
590   };
591  private:
592   bool DbgSectionMapSorted;
593   std::vector<DbgAddrConversion_t> DebugSectionMap;
594
595  public:  
596   std::set<std::string> prereq_libs;
597   std::vector<std::pair<long, long> > new_dynamic_entries;
598  private:
599   const char* soname_;
600   
601 };
602
603 }//namespace SymtabAPI
604 }//namespace Dyninst
605
606 #endif /* !defined(_Object_elf_h_) */