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