Move getModuleLanguageInfo function from Dyn_Symtab to Object - - - - -
[dyninst.git] / symtabAPI / src / Object-elf.h
1 /*
2  * Copyright (c) 1996-2004 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  * $Id: Object-elf.h,v 1.3 2007/02/15 23:30:45 giri Exp $
44  * Object-elf.h: Object class for ELF file format
45 ************************************************************************/
46
47
48 #if !defined(_Object_elf_h_)
49 #define _Object_elf_h_
50
51
52 #include "symtabAPI/h/Dyn_Symbol.h"
53 #include "common/h/Types.h"
54 #include "common/h/Vector.h"
55 #include <elf.h>
56 #include <libelf.h>
57
58 #include "Elf_X.h"
59
60 #include <libelf.h>
61 #include <fcntl.h>
62 #include <stdlib.h>
63 #include <unistd.h>
64
65 #include <sys/types.h>
66 #include <sys/mman.h>
67 #include <sys/stat.h>
68
69 /*
70  * The standard symbol table in an elf file is the .symtab section. This section does
71  * not have information to find the module to which a global symbol belongs, so we must
72  * also read the .stab section to get this info.
73  */
74
75 // Declarations for the .stab section.
76 // These are not declared in any system header files, so we must provide our own
77 // declarations. The declarations below were taken from:
78 //       SPARCWorks 3.0.x Debugger Interface, July 1994
79 // 
80 struct stab32 {
81     unsigned int name;  // stabstr table index for this symbol
82     unsigned char type; // type of this symbol
83     unsigned char other;
84     unsigned short desc;
85     unsigned int val;   // value of this symbol -- usually zero. The real value must
86                         // be obtained from the symtab section
87 };
88 struct stab64 {
89     // XXX ELF stabs are currently not implementing actual 64-bit support
90     //     on AMD-64, for which this separation was introduced. Until we
91     //     start seeing stab records with fields of the appropriate length,
92     //     we should assume the smaller records.
93     //unsigned long name; // stabstr table index for this symbol
94     unsigned int name; // stabstr table index for this symbol
95     unsigned char type; // type of this symbol
96     unsigned char other;
97     unsigned short desc;
98     //unsigned long val;
99     unsigned int val;  // value of this symbol -- usually zero. The real value must
100                         // be obtained from the symtab section
101 };
102
103 // 
104 // Extended to a class for 32/64-bit stab entries at runtime. - Ray
105 // 
106 class stab_entry {
107   public:
108     stab_entry(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
109         : stabptr(_stabptr), stabstr(_stabstr), nsyms(_nsyms) { }
110     virtual ~stab_entry() {};
111
112     virtual const char *name(int i) = 0;
113     virtual unsigned long nameIdx(int i) = 0;
114     virtual unsigned char type(int i) = 0;
115     virtual unsigned char other(int i) = 0;
116     virtual unsigned short desc(int i) = 0;
117     virtual unsigned long val(int i) = 0;
118
119     unsigned long count() { return nsyms; }
120     void setStringBase(const char *ptr) { stabstr = const_cast<char *>(ptr); }
121     const char *getStringBase() { return stabstr; }
122
123   protected:
124     void *stabptr;
125     const char *stabstr;
126     long nsyms;
127 };
128
129 class stab_entry_32 : public stab_entry {
130   public:
131     stab_entry_32(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
132         : stab_entry(_stabptr, _stabstr, _nsyms) { }
133     virtual ~stab_entry_32() {};
134
135     const char *name(int i = 0) { return stabstr + ((stab32 *)stabptr)[i].name; }
136     unsigned long nameIdx(int i = 0) { return ((stab32 *)stabptr)[i].name; }
137     unsigned char type(int i = 0) { return ((stab32 *)stabptr)[i].type; }
138     unsigned char other(int i = 0) { return ((stab32 *)stabptr)[i].other; }
139     unsigned short desc(int i = 0) { return ((stab32 *)stabptr)[i].desc; }
140     unsigned long val(int i = 0) { return ((stab32 *)stabptr)[i].val; }
141 };
142
143 class stab_entry_64 : public stab_entry {
144   public:
145     stab_entry_64(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
146         : stab_entry(_stabptr, _stabstr, _nsyms) { }
147     virtual ~stab_entry_64() {};
148
149     const char *name(int i = 0) { return stabstr + ((stab64 *)stabptr)[i].name; }
150     unsigned long nameIdx(int i = 0) { return ((stab64 *)stabptr)[i].name; }
151     unsigned char type(int i = 0) { return ((stab64 *)stabptr)[i].type; }
152     unsigned char other(int i = 0) { return ((stab64 *)stabptr)[i].other; }
153     unsigned short desc(int i = 0) { return ((stab64 *)stabptr)[i].desc; }
154     unsigned long val(int i = 0) { return ((stab64 *)stabptr)[i].val; }
155 };
156
157 // Types 
158 #define N_UNDF  0x00 /* start of object file */
159 #define N_GSYM  0x20 /* global symbol */
160 #define N_FUN   0x24 /* function or procedure */
161 #define N_STSYM 0x26 /* initialized static symbol */
162 #define N_LCSYM 0x28 /* unitialized static symbol */
163 #define N_ROSYM 0x2c /* read-only static symbol */
164 #define N_OPT   0x3c /* compiler options */
165 #define N_ENDM  0x62 /* end module */
166 #define N_SO    0x64 /* source directory and file */
167 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
168 #define N_BCOMM 0xe2 /* start fortran named common block */
169 #define N_ECOMM 0xe4 /* start fortran named common block */
170
171 // Language code -- the desc field in a N_SO entry is a language code
172 #define N_SO_AS      1 /* assembler source */
173 #define N_SO_C       2 /* K & R C source */
174 #define N_SO_ANSI_C  3 /* ANSI C source */
175 #define N_SO_CC      4 /* C++ source */
176 #define N_SO_FORTRAN 5 /* fortran source */
177 #define N_SO_PASCAL  6 /* Pascal source */
178 #define N_SO_F90     7 /* Fortran90 source */
179
180 //line information data
181 #define N_SLINE  0x44 /* line number in text segment */
182 #define N_SOL    0x84 /* name of the include file*/
183
184 // Symbol descriptors
185 // The format of a name is "<name>:<symbol descriptor><rest of name>
186 // The following are the descriptors of interest
187 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
188 #define SD_PROTOTYPE  'P'  /* function prototypes */
189 #define SD_GLOBAL_VAR 'G' /* global variable */
190
191 // end of stab declarations
192
193 class pdElfShdr;
194
195 class Object : public AObject {
196  public:
197   Object(){}
198   //void findMain( vector< Dyn_Symbol *> &allsymbols );
199   //OFFSET findDynamic( vector< Dyn_Symbol *> &allsymbols );
200   // "Filedescriptor" ctor
201   Object(string &filename, void (*)(const char *) = log_msg);
202   Object(char *mem_image, size_t image_size, void (*)(const char *) = log_msg);
203   Object(const Object &);
204   virtual ~Object();
205   const Object& operator=(const Object &);
206
207   const char *elf_vaddr_to_ptr(OFFSET vaddr) const;
208   bool hasStabInfo() const { return ! ( !stab_off_ || !stab_size_ || !stabstr_off_ ); }
209   bool hasDwarfInfo() const { return dwarvenDebugInfo; }
210   stab_entry * get_stab_info() const;
211   const char * getFileName() const { return fileName; }
212   void getModuleLanguageInfo(hash_map<string, supportedLanguages> *mod_langs);
213
214   bool needs_function_binding() const { return (plt_addr_ > 0); } 
215   bool get_func_binding_table(vector<relocationEntry> &fbt) const;
216   bool get_func_binding_table_ptr(const vector<relocationEntry> *&fbt) const;
217
218   //getLoadAddress may return 0 on shared objects
219   OFFSET getLoadAddress() const { return loadAddress_; }
220
221   OFFSET getEntryAddress() const { return entryAddress_; }
222   // To be changed later - Giri
223   OFFSET getBaseAddress() const { return 0; }
224   virtual char *  mem_image() const { 
225         if(fileName == NULL)
226                 return mem_image_;
227         return file_ptr_; 
228   }
229
230   DLLEXPORT ObjectType objType() const;
231
232
233 //TODO Later - change this #ifdef later.. make getTOCoffset available for all platforms  
234
235 #if defined(arch_ia64)
236   OFFSET getTOCoffset() const { return gp; }
237 #else
238   OFFSET getTOCoffset() const { return 0; }
239 #endif
240
241   const ostream &dump_state_info(ostream &s);
242   bool isEEL() { return EEL; }
243
244         //to determine if a mutation falls in the text section of
245         // a shared library
246         bool isinText(OFFSET addr, OFFSET baseaddr) const { 
247                 //printf(" baseaddr %x TESTING %x %x \n", baseaddr, text_addr_ + baseaddr  , text_addr_ + baseaddr + text_size_ );
248                 if(addr > text_addr_ + baseaddr     &&
249                    addr < text_addr_ + baseaddr + text_size_ ) {
250                         return true;
251                 }
252                 return false;
253         } 
254         // to determine where in the .plt this function is listed 
255         // returns an offset from the base address of the object
256         // so the entry can easily be located in memory
257         OFFSET getPltSlot(string funcName) const ;
258         bool hasSymAtAddr( OFFSET adr )
259         {
260             return (symbolNamesByAddr.find( adr )!=symbolNamesByAddr.end());
261         }
262         OFFSET textAddress(){ return text_addr_;}
263         bool isText( OFFSET addr ) const
264         {
265             if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
266                 return true;
267             return false;
268         }
269
270         bool is_offset_in_plt(OFFSET offset) const;
271
272  private:
273   static void log_elferror (void (*)(const char *), const char *);
274     
275   int       file_fd_;            // mapped ELF file
276   unsigned  file_size_;          // mapped ELF file
277   char     *file_ptr_;           // mapped ELF file
278   Elf_X    elfHdr;
279   
280   const char * fileName;
281   char *mem_image_;
282   //Symbol    mainSym_;
283   OFFSET   fini_addr_;
284   OFFSET   text_addr_;   //.text section 
285   OFFSET   text_size_;   //.text section size
286   OFFSET   dynamic_addr_;        //.dynamic section
287   OFFSET   dynsym_addr_;        // .dynsym section
288   OFFSET   dynstr_addr_;        // .dynstr section
289   OFFSET   got_addr_;           // global offset table
290   unsigned  got_size_;           // global offset table
291   OFFSET   plt_addr_;           // procedure linkage table
292   unsigned  plt_size_;           // procedure linkage table
293   unsigned  plt_entry_size_;     // procedure linkage table
294   OFFSET   rel_plt_addr_;       // .rel[a].plt section
295   unsigned  rel_plt_size_;       // .rel[a].plt section
296   unsigned  rel_plt_entry_size_; // .rel[a].plt section
297
298   OFFSET   stab_off_;           // .stab section
299   unsigned  stab_size_;          // .stab section
300   OFFSET   stabstr_off_;        // .stabstr section
301
302   OFFSET   stab_indx_off_;       // .stab.index section
303   unsigned  stab_indx_size_;     // .stab.index section
304   OFFSET   stabstr_indx_off_;    // .stabstr.index section
305
306   bool      dwarvenDebugInfo;    // is DWARF debug info present?
307   OFFSET   loadAddress_;      // The object may specify a load address
308                                //   Set to 0 if it may load anywhere
309   OFFSET entryAddress_;
310           
311 #if defined(arch_ia64)
312   OFFSET   gp;                   // The gp for this object.
313 #endif
314   bool      EEL;                 // true if EEL rewritten
315   bool      did_open;           // true if the file has been mmapped
316   ObjectType obj_type_;
317
318   // for sparc-solaris this is a table of PLT entry addr, function_name
319   // for x86-solaris this is a table of GOT entry addr, function_name
320   // on sparc-solaris the runtime linker modifies the PLT entry when it
321   // binds a function, on X86 the PLT entry is not modified, but it uses
322   // an indirect jump to a GOT entry that is modified when the function 
323   // is bound....is this correct???? or should it be <PLTentry_addr, name> 
324   // for both?
325   vector<relocationEntry> relocation_table_;
326
327   // all section headers, sorted by address
328   // we use these to do a better job of finding the end of symbols
329   vector<Elf_X_Shdr*> allSectionHdrs;
330
331   // It doesn't look like image's equivalent hashtable is built by
332   // the time we need it, and it's hard to get to anyway.
333   hash_map< OFFSET, string > symbolNamesByAddr;
334
335   // populates: file_fd_, file_size_, file_ptr_
336   bool mmap_file(const char *file, 
337                  bool &did_open, bool &did_mmap);
338
339   bool loaded_elf( OFFSET &, OFFSET &,
340                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
341                     Elf_X_Shdr* &, Elf_X_Shdr* &, 
342                     Elf_X_Shdr* &, Elf_X_Shdr* &,
343                     Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp, 
344                     Elf_X_Shdr*& got_scnp,  Elf_X_Shdr*& dynsym_scnp,
345                     Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& eh_frame,
346                     Elf_X_Shdr*& gcc_except, bool a_out=false);
347
348   void load_object();
349   void load_shared_object();
350
351   // initialize relocation_table_ from .rel[a].plt section entries 
352   bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
353                               Elf_X_Shdr *&dynsym_scnp, 
354                               Elf_X_Shdr *&dynstr_scnp);
355
356   void parse_symbols(vector<Dyn_Symbol *> &allsymbols, 
357                      Elf_X_Data &symdata, Elf_X_Data &strdata,
358                      bool shared_library,
359                      string module);
360   
361   void fix_zero_function_sizes(vector<Dyn_Symbol *> &allsymbols, bool EEL);
362   void override_weak_symbols(vector<Dyn_Symbol *> &allsymbols);
363   void insert_symbols_shared(vector<Dyn_Symbol *> &allsymbols);
364   void find_code_and_data(Elf_X &elf,
365        OFFSET txtaddr, OFFSET dataddr);
366   void insert_symbols_static(vector<Dyn_Symbol *> &allsymbols);
367   bool fix_global_symbol_modules_static_stab(Elf_X_Shdr *stabscnp,
368                                              Elf_X_Shdr *stabstrscnp);
369   bool fix_global_symbol_modules_static_dwarf(Elf_X &elf);
370
371   void get_valid_memory_areas(Elf_X &elf);
372
373 #if defined(os_irix)
374
375  public:
376   OFFSET     get_gp_value()  const { return gp_value; }
377   OFFSET     get_rbrk_addr() const { return rbrk_addr; }
378   OFFSET     get_base_addr() const { return base_addr; }
379   const char *got_entry_name(OFFSET entry_off) const;
380   int         got_gp_disp(const char *entry_name) const;
381
382   OFFSET     MIPS_stubs_addr_;   // .MIPS.stubs section
383   OFFSET     MIPS_stubs_off_;    // .MIPS.stubs section
384   unsigned    MIPS_stubs_size_;   // .MIPS.stubs section
385
386  private:
387   OFFSET     gp_value;
388   OFFSET     rbrk_addr;
389   OFFSET     base_addr;
390   
391   int         got_zero_index_;
392   int         dynsym_zero_index_;
393
394 #endif /* mips_sgi_irix6_4 */
395 };
396
397 const char *pdelf_get_shnames(Elf *elfp, bool is64);
398
399 #endif /* !defined(_Object_elf_h_) */