Add an API call for accessing dependencies
[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.16 2008/04/01 18:52:34 giri 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
42 #include "common/h/MappedFile.h"
43 #include "symtabAPI/h/Symbol.h"
44 #include "common/h/headers.h"
45 #include "common/h/Types.h"
46 #include <elf.h>
47 #include <libelf.h>
48
49 #include "Elf_X.h"
50
51 #include <libelf.h>
52 #include <fcntl.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55
56 #include <sys/types.h>
57 #include <sys/mman.h>
58 #include <sys/stat.h>
59
60 namespace Dyninst{
61 namespace SymtabAPI{
62 /*
63  * The standard symbol table in an elf file is the .symtab section. This section does
64  * not have information to find the module to which a global symbol belongs, so we must
65  * also read the .stab section to get this info.
66  */
67
68 // Declarations for the .stab section.
69 // These are not declared in any system header files, so we must provide our own
70 // declarations. The declarations below were taken from:
71 //       SPARCWorks 3.0.x Debugger Interface, July 1994
72 // 
73 struct stab32 {
74     unsigned int name;  // stabstr table index for this symbol
75     unsigned char type; // type of this symbol
76     unsigned char other;
77     unsigned short desc;
78     unsigned int val;   // value of this symbol -- usually zero. The real value must
79                         // be obtained from the symtab section
80 };
81 struct stab64 {
82     // XXX ELF stabs are currently not implementing actual 64-bit support
83     //     on AMD-64, for which this separation was introduced. Until we
84     //     start seeing stab records with fields of the appropriate length,
85     //     we should assume the smaller records.
86     //unsigned long name; // stabstr table index for this symbol
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 long val;
92     unsigned int val;  // value of this symbol -- usually zero. The real value must
93                         // be obtained from the symtab section
94 };
95
96 // 
97 // Extended to a class for 32/64-bit stab entries at runtime. - Ray
98 // 
99 class stab_entry {
100   public:
101     stab_entry(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
102         : stabptr(_stabptr), stabstr(_stabstr), nsyms(_nsyms) { }
103     virtual ~stab_entry() {};
104
105     virtual const char *name(int i) = 0;
106     virtual unsigned long nameIdx(int i) = 0;
107     virtual unsigned char type(int i) = 0;
108     virtual unsigned char other(int i) = 0;
109     virtual unsigned short desc(int i) = 0;
110     virtual unsigned long val(int i) = 0;
111
112     unsigned long count() { return nsyms; }
113     void setStringBase(const char *ptr) { stabstr = const_cast<char *>(ptr); }
114     const char *getStringBase() { return stabstr; }
115
116   protected:
117     void *stabptr;
118     const char *stabstr;
119     long nsyms;
120 };
121
122 class stab_entry_32 : public stab_entry {
123   public:
124     stab_entry_32(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
125         : stab_entry(_stabptr, _stabstr, _nsyms) { }
126     virtual ~stab_entry_32() {};
127
128     const char *name(int i = 0) { 
129        if (!stabptr) {
130           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
131                 FILE__, __LINE__);
132           return "bad_name";
133        }
134        return stabstr + ((stab32 *)stabptr)[i].name; 
135     }
136     unsigned long nameIdx(int i = 0) {
137        if (!stabptr) {
138           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
139                 FILE__, __LINE__);
140           return 0L;
141        }
142        return ((stab32 *)stabptr)[i].name; 
143     }
144     unsigned char type(int i = 0) {
145        if (!stabptr) {
146           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
147                 FILE__, __LINE__);
148           return 0;
149        }
150        return ((stab32 *)stabptr)[i].type; 
151     }
152     unsigned char other(int i = 0) {
153        if (!stabptr) {
154           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
155                 FILE__, __LINE__);
156           return 0;
157        }
158        return ((stab32 *)stabptr)[i].other; 
159     }
160     unsigned short desc(int i = 0) { 
161        if (!stabptr) {
162           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
163                 FILE__, __LINE__);
164           return 0;
165        }
166        return ((stab32 *)stabptr)[i].desc; 
167     }
168     unsigned long val(int i = 0) { 
169        if (!stabptr) {
170           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
171                 FILE__, __LINE__);
172           return 0L;
173        }
174        return ((stab32 *)stabptr)[i].val; 
175     }
176 };
177
178 class stab_entry_64 : public stab_entry {
179   public:
180     stab_entry_64(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
181         : stab_entry(_stabptr, _stabstr, _nsyms) { }
182     virtual ~stab_entry_64() {};
183
184     const char *name(int i = 0) { 
185        if (!stabptr) {
186           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
187                 FILE__, __LINE__);
188           return "bad_name";
189        }
190        return stabstr + ((stab64 *)stabptr)[i].name; 
191     }
192     unsigned long nameIdx(int i = 0) {
193        if (!stabptr) {
194           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
195                 FILE__, __LINE__);
196           return 0L;
197        }
198        return ((stab64 *)stabptr)[i].name; 
199     }
200     unsigned char type(int i = 0) {
201        if (!stabptr) {
202           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
203                 FILE__, __LINE__);
204           return 0;
205        }
206        return ((stab64 *)stabptr)[i].type; 
207     }
208     unsigned char other(int i = 0) { 
209        if (!stabptr) {
210           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
211                 FILE__, __LINE__);
212           return 0;
213        }
214        return ((stab64 *)stabptr)[i].other; 
215     }
216     unsigned short desc(int i = 0) { 
217        if (!stabptr) {
218           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
219                 FILE__, __LINE__);
220           return 0;
221        }
222        return ((stab64 *)stabptr)[i].desc; 
223     }
224     unsigned long val(int i = 0) { 
225        if (!stabptr) {
226           fprintf(stderr, "%s[%d]:  warning, accessing uninitialized stab_entry\n",
227                 FILE__, __LINE__);
228           return 0L;
229        }
230        return ((stab64 *)stabptr)[i].val; 
231     }
232 };
233
234 // Types 
235 #define N_UNDF  0x00 /* start of object file */
236 #define N_GSYM  0x20 /* global symbol */
237 #define N_FUN   0x24 /* function or procedure */
238 #define N_STSYM 0x26 /* initialized static symbol */
239 #define N_LCSYM 0x28 /* unitialized static symbol */
240 #define N_ROSYM 0x2c /* read-only static symbol */
241 #define N_OPT   0x3c /* compiler options */
242 #define N_ENDM  0x62 /* end module */
243 #define N_SO    0x64 /* source directory and file */
244 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
245 #define N_BCOMM 0xe2 /* start fortran named common block */
246 #define N_ECOMM 0xe4 /* start fortran named common block */
247
248 // Language code -- the desc field in a N_SO entry is a language code
249 #define N_SO_AS      1 /* assembler source */
250 #define N_SO_C       2 /* K & R C source */
251 #define N_SO_ANSI_C  3 /* ANSI C source */
252 #define N_SO_CC      4 /* C++ source */
253 #define N_SO_FORTRAN 5 /* fortran source */
254 #define N_SO_PASCAL  6 /* Pascal source */
255 #define N_SO_F90     7 /* Fortran90 source */
256
257 //line information data
258 #define N_SLINE  0x44 /* line number in text segment */
259 #define N_SOL    0x84 /* name of the include file*/
260
261 // Symbol descriptors
262 // The format of a name is "<name>:<symbol descriptor><rest of name>
263 // The following are the descriptors of interest
264 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
265 #define SD_PROTOTYPE  'P'  /* function prototypes */
266 #define SD_GLOBAL_VAR 'G' /* global variable */
267
268 // end of stab declarations
269
270 class pdElfShdr;
271
272 class Symtab;
273 class Section;
274
275 class Object : public AObject {
276  public:
277   Object(){}
278   Object(MappedFile *, void (*)(const char *) = log_msg, bool alloc_syms = true);
279   Object(MappedFile *, hash_map<std::string, LineInformation> &, std::vector<Section *> &, void (*)(const char *) = log_msg);
280   Object(const Object &);
281   virtual ~Object();
282   const Object& operator=(const Object &);
283
284   bool emitDriver(Symtab *obj, std::string fName, std::vector<Symbol *>&functions, std::vector<Symbol *>&variables, std::vector<Symbol *>&mods, std::vector<Symbol *>&notypes, unsigned flag);  
285   
286   const char *elf_vaddr_to_ptr(Offset vaddr) const;
287   bool hasStabInfo() const { return ! ( !stab_off_ || !stab_size_ || !stabstr_off_ ); }
288   bool hasDwarfInfo() const { return dwarvenDebugInfo; }
289   stab_entry * get_stab_info() const;
290   const char * getFileName() const { return mf->filename().c_str(); }
291   void getModuleLanguageInfo(hash_map<std::string, supportedLanguages> *mod_langs);
292   void parseFileLineInfo(hash_map<std::string, LineInformation> &li);
293   void parseTypeInfo(Symtab *obj);
294   bool getMappedRegions(std::vector<Region> &regs) const;
295
296   bool needs_function_binding() const { return (plt_addr_ > 0); } 
297   bool get_func_binding_table(std::vector<relocationEntry> &fbt) const;
298   bool get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const;
299   void getDependencies(std::vector<std::string> &deps);
300
301   bool addRelocationEntry(relocationEntry &re);
302
303   //getLoadAddress may return 0 on shared objects
304   Offset getLoadAddress() const { return loadAddress_; }
305
306   Offset getEntryAddress() const { return entryAddress_; }
307   // To be changed later - Giri
308   Offset getBaseAddress() const { return 0; }
309   static bool truncateLineFilenames;
310  
311   virtual char *mem_image() const 
312   {
313      assert(mf);
314      return (char *)mf->base_addr();
315   }
316
317   DLLEXPORT ObjectType objType() const;
318   const char *interpreter_name() const;
319
320
321 //TODO Later - change this #ifdef later.. make getTOCoffset available for all platforms  
322
323 #if defined(arch_ia64)
324   Offset getTOCoffset() const { return gp; }
325 #elif defined(os_linux) && defined(arch_power) && defined(arch_64bit)
326   // 64-bit PowerPC ELF ABI Supplement, Version 1.9, 2004-10-23:
327   //   The TOC section contains a conventional ELF GOT, and may optionally
328   //   contain a small data area.
329   //   The TOC base is typically the first address in the TOC plus 0x8000.
330   // I don't understand why I can find a ".got" within binaries, but I can't
331   // find a ".toc".  ssuen  August 7, 2007
332   Offset getTOCoffset() const { return got_addr_ + 0x8000; }
333 #else
334   Offset getTOCoffset() const { return 0; }
335 #endif
336
337   const std::ostream &dump_state_info(std::ostream &s);
338   bool isEEL() { return EEL; }
339
340         //to determine if a mutation falls in the text section of
341         // a shared library
342         bool isinText(Offset addr, Offset baseaddr) const { 
343                 //printf(" baseaddr %x TESTING %x %x \n", baseaddr, text_addr_ + baseaddr  , text_addr_ + baseaddr + text_size_ );
344                 if(addr > text_addr_ + baseaddr     &&
345                    addr < text_addr_ + baseaddr + text_size_ ) {
346                         return true;
347                 }
348                 return false;
349         } 
350         // to determine where in the .plt this function is listed 
351         // returns an offset from the base address of the object
352         // so the entry can easily be located in memory
353         Offset getPltSlot(std::string funcName) const ;
354         bool hasSymAtAddr( Offset adr )
355         {
356             return (symbolNamesByAddr.find( adr )!=symbolNamesByAddr.end());
357         }
358         Offset textAddress(){ return text_addr_;}
359         bool isText( Offset addr ) const
360         {
361             if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
362                 return true;
363             return false;
364         }
365
366         bool is_offset_in_plt(Offset offset) const;
367     Elf_X_Shdr *getSectionHdrByAddr(Offset addr);
368
369  private:
370   static void log_elferror (void (*)(const char *), const char *);
371     
372   Elf_X    elfHdr;
373   
374   Offset   fini_addr_;
375   Offset   text_addr_;   //.text section 
376   Offset   text_size_;   //.text section size
377   Offset   dynamic_addr_;        //.dynamic section
378   Offset   dynsym_addr_;        // .dynsym section
379   Offset   dynstr_addr_;        // .dynstr section
380   Offset   got_addr_;           // global offset table
381   unsigned  got_size_;           // global offset table
382   Offset   plt_addr_;           // procedure linkage table
383   unsigned  plt_size_;           // procedure linkage table
384   unsigned  plt_entry_size_;     // procedure linkage table
385   Offset   rel_plt_addr_;       // .rel[a].plt section
386   unsigned  rel_plt_size_;       // .rel[a].plt section
387   unsigned  rel_plt_entry_size_; // .rel[a].plt section
388   
389   unsigned  rel_size_;       // DT_REL/DT_RELA in dynamic section
390   unsigned  rel_entry_size_; // DT_REL/DT_RELA in dynamic section
391
392   Offset   stab_off_;           // .stab section
393   unsigned  stab_size_;          // .stab section
394   Offset   stabstr_off_;        // .stabstr section
395
396   Offset   stab_indx_off_;       // .stab.index section
397   unsigned  stab_indx_size_;     // .stab.index section
398   Offset   stabstr_indx_off_;    // .stabstr.index section
399
400   bool      dwarvenDebugInfo;    // is DWARF debug info present?
401   Offset   loadAddress_;      // The object may specify a load address
402                                //   Set to 0 if it may load anywhere
403   Offset entryAddress_;
404   char *interpreter_name_;
405   bool  isStripped;
406
407 #if defined(arch_ia64)
408   Offset   gp;                   // The gp for this object.
409 #endif
410   bool      EEL;                 // true if EEL rewritten
411   bool      did_open;           // true if the file has been mmapped
412   ObjectType obj_type_;
413
414   // for sparc-solaris this is a table of PLT entry addr, function_name
415   // for x86-solaris this is a table of GOT entry addr, function_name
416   // on sparc-solaris the runtime linker modifies the PLT entry when it
417   // binds a function, on X86 the PLT entry is not modified, but it uses
418   // an indirect jump to a GOT entry that is modified when the function 
419   // is bound....is this correct???? or should it be <PLTentry_addr, name> 
420   // for both?
421   std::vector<relocationEntry> relocation_table_;
422   std::vector<relocationEntry> fbt_;
423
424   // all section headers, sorted by address
425   // we use these to do a better job of finding the end of symbols
426   std::vector<Elf_X_Shdr*> allSectionHdrs;
427
428   // It doesn't look like image's equivalent hashtable is built by
429   // the time we need it, and it's hard to get to anyway.
430   hash_map< Offset, std::string > symbolNamesByAddr;
431
432   // Symbol version mappings. used to store symbol version names.
433   hash_map<unsigned, std::vector<std::string> >versionMapping;
434   hash_map<unsigned, std::string> versionFileNameMapping;
435
436   std::vector<std::string> deps_;
437
438   bool loaded_elf( Offset &, Offset &,
439                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
440                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
441                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
442                     Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
443                     Elf_X_Shdr*& got_scnp,  Elf_X_Shdr*& dynsym_scnp,
444                     Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& dynamic_scnp, Elf_X_Shdr*& eh_frame,
445                     Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp,
446           bool a_out=false);
447   
448   void parseStabFileLineInfo(hash_map<std::string, LineInformation> &li);
449   void parseDwarfFileLineInfo(hash_map<std::string, LineInformation> &li);
450
451   void parseDwarfTypes(Symtab *obj);
452   void parseStabTypes(Symtab *obj);
453
454   void load_object(bool);
455   void load_shared_object(bool);
456
457   // initialize relocation_table_ from .rel[a].plt section entries 
458   bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
459                               Elf_X_Shdr *&dynsym_scnp, 
460                               Elf_X_Shdr *&dynstr_scnp);
461
462   bool get_relocationDyn_entries( Elf_X_Shdr *&rel_scnp,
463                      Elf_X_Shdr *&dynsym_scnp,
464                      Elf_X_Shdr *&dynstr_scnp );
465   
466   void parseDynamic(Elf_X_Shdr *& dyn_scnp, Elf_X_Shdr *&dynsym_scnp, 
467                     Elf_X_Shdr *&dynstr_scnp);
468   
469   void parse_symbols(std::vector<Symbol *> &allsymbols, 
470                      Elf_X_Data &symdata, Elf_X_Data &strdata,
471                      bool shared_library,
472                      std::string module);
473   
474   void parse_dynamicSymbols( Elf_X_Shdr *& dyn_scnp, Elf_X_Data &symdata,
475              Elf_X_Data &strdata, bool shared_library,
476                      std::string module);
477
478   void fix_zero_function_sizes(std::vector<Symbol *> &allsymbols, bool EEL);
479   void override_weak_symbols(std::vector<Symbol *> &allsymbols);
480   void insert_symbols_shared(std::vector<Symbol *> &allsymbols);
481   void find_code_and_data(Elf_X &elf,
482        Offset txtaddr, Offset dataddr);
483   void insert_symbols_static(std::vector<Symbol *> &allsymbols);
484   bool fix_global_symbol_modules_static_stab(Elf_X_Shdr *stabscnp,
485                                              Elf_X_Shdr *stabstrscnp);
486   bool fix_global_symbol_modules_static_dwarf(Elf_X &elf);
487
488   void get_valid_memory_areas(Elf_X &elf);
489
490 #if 0 
491 #if defined(os_irix)
492
493  public:
494   Offset     get_gp_value()  const { return gp_value; }
495   Offset     get_rbrk_addr() const { return rbrk_addr; }
496   Offset     get_base_addr() const { return base_addr; }
497   const char *got_entry_name(Offset entry_off) const;
498   int         got_gp_disp(const char *entry_name) const;
499   bool       
500
501   Offset     MIPS_stubs_addr_;   // .MIPS.stubs section
502   Offset     MIPS_stubs_off_;    // .MIPS.stubs section
503   unsigned    MIPS_stubs_size_;   // .MIPS.stubs section
504   
505  private:
506   Offset     gp_value;
507   Offset     rbrk_addr;
508   Offset     base_addr;
509   
510   int         got_zero_index_;
511   int         dynsym_zero_index_;
512
513 #endif /* mips_sgi_irix6_4 */
514 #endif
515 };
516
517 //const char *pdelf_get_shnames(Elf *elfp, bool is64);
518
519 }//namespace SymtabAPI
520 }//namespace Dyninst
521
522 #endif /* !defined(_Object_elf_h_) */