2 * Copyright (c) 1996-2007 Barton P. Miller
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.
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.
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.
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.
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
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 ************************************************************************/
38 #if !defined(_Object_elf_h_)
39 #define _Object_elf_h_
42 #include "common/h/MappedFile.h"
43 #include "symtabAPI/h/Symbol.h"
44 #include "common/h/headers.h"
45 #include "common/h/Types.h"
55 #include <sys/types.h>
62 * The standard symbol table in an elf file is the .symtab section. This section does
63 * not have information to find the module to which a global symbol belongs, so we must
64 * also read the .stab section to get this info.
67 // Declarations for the .stab section.
68 // These are not declared in any system header files, so we must provide our own
69 // declarations. The declarations below were taken from:
70 // SPARCWorks 3.0.x Debugger Interface, July 1994
73 unsigned int name; // stabstr table index for this symbol
74 unsigned char type; // type of this symbol
77 unsigned int val; // value of this symbol -- usually zero. The real value must
78 // be obtained from the symtab section
81 // XXX ELF stabs are currently not implementing actual 64-bit support
82 // on AMD-64, for which this separation was introduced. Until we
83 // start seeing stab records with fields of the appropriate length,
84 // we should assume the smaller records.
85 //unsigned long name; // stabstr table index for this symbol
86 unsigned int name; // stabstr table index for this symbol
87 unsigned char type; // type of this symbol
91 unsigned int val; // value of this symbol -- usually zero. The real value must
92 // be obtained from the symtab section
96 // Extended to a class for 32/64-bit stab entries at runtime. - Ray
100 stab_entry(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
101 : stabptr(_stabptr), stabstr(_stabstr), nsyms(_nsyms) { }
102 virtual ~stab_entry() {};
104 virtual const char *name(int i) = 0;
105 virtual unsigned long nameIdx(int i) = 0;
106 virtual unsigned char type(int i) = 0;
107 virtual unsigned char other(int i) = 0;
108 virtual unsigned short desc(int i) = 0;
109 virtual unsigned long val(int i) = 0;
111 unsigned long count() { return nsyms; }
112 void setStringBase(const char *ptr) { stabstr = const_cast<char *>(ptr); }
113 const char *getStringBase() { return stabstr; }
121 class stab_entry_32 : public stab_entry {
123 stab_entry_32(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
124 : stab_entry(_stabptr, _stabstr, _nsyms) { }
125 virtual ~stab_entry_32() {};
127 const char *name(int i = 0) {
129 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
133 return stabstr + ((stab32 *)stabptr)[i].name;
135 unsigned long nameIdx(int i = 0) {
137 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
141 return ((stab32 *)stabptr)[i].name;
143 unsigned char type(int i = 0) {
145 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
149 return ((stab32 *)stabptr)[i].type;
151 unsigned char other(int i = 0) {
153 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
157 return ((stab32 *)stabptr)[i].other;
159 unsigned short desc(int i = 0) {
161 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
165 return ((stab32 *)stabptr)[i].desc;
167 unsigned long val(int i = 0) {
169 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
173 return ((stab32 *)stabptr)[i].val;
177 class stab_entry_64 : public stab_entry {
179 stab_entry_64(void *_stabptr = 0, const char *_stabstr = 0, long _nsyms = 0)
180 : stab_entry(_stabptr, _stabstr, _nsyms) { }
181 virtual ~stab_entry_64() {};
183 const char *name(int i = 0) {
185 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
189 return stabstr + ((stab64 *)stabptr)[i].name;
191 unsigned long nameIdx(int i = 0) {
193 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
197 return ((stab64 *)stabptr)[i].name;
199 unsigned char type(int i = 0) {
201 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
205 return ((stab64 *)stabptr)[i].type;
207 unsigned char other(int i = 0) {
209 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
213 return ((stab64 *)stabptr)[i].other;
215 unsigned short desc(int i = 0) {
217 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
221 return ((stab64 *)stabptr)[i].desc;
223 unsigned long val(int i = 0) {
225 fprintf(stderr, "%s[%d]: warning, accessing uninitialized stab_entry\n",
229 return ((stab64 *)stabptr)[i].val;
234 #define N_UNDF 0x00 /* start of object file */
235 #define N_GSYM 0x20 /* global symbol */
236 #define N_FUN 0x24 /* function or procedure */
237 #define N_STSYM 0x26 /* initialized static symbol */
238 #define N_LCSYM 0x28 /* unitialized static symbol */
239 #define N_ROSYM 0x2c /* read-only static symbol */
240 #define N_OPT 0x3c /* compiler options */
241 #define N_ENDM 0x62 /* end module */
242 #define N_SO 0x64 /* source directory and file */
243 #define N_ENTRY 0xa4 /* fortran alternate subroutine entry point */
244 #define N_BCOMM 0xe2 /* start fortran named common block */
245 #define N_ECOMM 0xe4 /* start fortran named common block */
247 // Language code -- the desc field in a N_SO entry is a language code
248 #define N_SO_AS 1 /* assembler source */
249 #define N_SO_C 2 /* K & R C source */
250 #define N_SO_ANSI_C 3 /* ANSI C source */
251 #define N_SO_CC 4 /* C++ source */
252 #define N_SO_FORTRAN 5 /* fortran source */
253 #define N_SO_PASCAL 6 /* Pascal source */
254 #define N_SO_F90 7 /* Fortran90 source */
256 //line information data
257 #define N_SLINE 0x44 /* line number in text segment */
258 #define N_SOL 0x84 /* name of the include file*/
260 // Symbol descriptors
261 // The format of a name is "<name>:<symbol descriptor><rest of name>
262 // The following are the descriptors of interest
263 #define SD_GLOBAL_FUN 'F' /* global function or procedure */
264 #define SD_PROTOTYPE 'P' /* function prototypes */
265 #define SD_GLOBAL_VAR 'G' /* global variable */
267 // end of stab declarations
274 class Object : public AObject {
277 Object(MappedFile *, MappedFile *, void (*)(const char *) = log_msg, bool alloc_syms = true);
278 Object(MappedFile *, MappedFile *, dyn_hash_map<std::string, LineInformation> &, std::vector<Region *> &, void (*)(const char *) = log_msg);
279 Object(MappedFile *, MappedFile *, std::string &member_name, Offset offset,
280 void (*)(const char *) = log_msg, void *base = NULL, bool alloc_syms = true);
281 Object(const Object &);
283 const Object& operator=(const Object &);
285 bool emitDriver(Symtab *obj, std::string fName, std::vector<Symbol *>&allSymbols, unsigned flag);
287 const char *elf_vaddr_to_ptr(Offset vaddr) const;
288 bool hasStabInfo() const { return ! ( !stab_off_ || !stab_size_ || !stabstr_off_ ); }
289 bool hasDwarfInfo() const { return dwarvenDebugInfo; }
290 stab_entry * get_stab_info() const;
291 const char * getFileName() const { return mf->filename().c_str(); }
292 void getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs);
293 void parseFileLineInfo(dyn_hash_map<std::string, LineInformation> &li);
294 void parseTypeInfo(Symtab *obj);
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);
301 bool addRelocationEntry(relocationEntry &re);
303 //getLoadAddress may return 0 on shared objects
304 Offset getLoadAddress() const { return loadAddress_; }
306 Offset getEntryAddress() const { return entryAddress_; }
307 // To be changed later - Giri
308 Offset getBaseAddress() const { return 0; }
309 static bool truncateLineFilenames;
311 virtual char *mem_image() const
314 return (char *)mf->base_addr();
317 SYMTAB_EXPORT ObjectType objType() const;
318 const char *interpreter_name() const;
321 //TODO Later - change this #ifdef later.. make getTOCoffset available for all platforms
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; }
334 Offset getTOCoffset() const { return 0; }
337 const std::ostream &dump_state_info(std::ostream &s);
338 bool isEEL() { return EEL; }
340 //to determine if a mutation falls in the text section of
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_ ) {
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 )
356 return (symbolNamesByAddr.find( adr )!=symbolNamesByAddr.end());
358 Offset textAddress(){ return text_addr_;}
359 bool isText( Offset addr ) const
361 if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
366 bool is_offset_in_plt(Offset offset) const;
367 Elf_X_Shdr *getRegionHdrByAddr(Offset addr);
368 bool isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned newPerms);
371 static void log_elferror (void (*)(const char *), const char *);
375 Elf_X elfHdrForDebugInfo;
378 Offset text_addr_; //.text section
379 Offset text_size_; //.text section size
380 Offset dynamic_addr_; //.dynamic section
381 Offset dynsym_addr_; // .dynsym section
382 Offset dynstr_addr_; // .dynstr section
383 Offset got_addr_; // global offset table
384 unsigned got_size_; // global offset table
385 Offset plt_addr_; // procedure linkage table
386 unsigned plt_size_; // procedure linkage table
387 unsigned plt_entry_size_; // procedure linkage table
388 Offset rel_plt_addr_; // .rel[a].plt section
389 unsigned rel_plt_size_; // .rel[a].plt section
390 unsigned rel_plt_entry_size_; // .rel[a].plt section
392 unsigned rel_size_; // DT_REL/DT_RELA in dynamic section
393 unsigned rel_entry_size_; // DT_REL/DT_RELA in dynamic section
395 Offset stab_off_; // .stab section
396 unsigned stab_size_; // .stab section
397 Offset stabstr_off_; // .stabstr section
399 Offset stab_indx_off_; // .stab.index section
400 unsigned stab_indx_size_; // .stab.index section
401 Offset stabstr_indx_off_; // .stabstr.index section
403 bool dwarvenDebugInfo; // is DWARF debug info present?
404 Offset loadAddress_; // The object may specify a load address
405 // Set to 0 if it may load anywhere
406 Offset entryAddress_;
407 char *interpreter_name_;
410 #if defined(arch_ia64)
411 Offset gp; // The gp for this object.
413 bool EEL; // true if EEL rewritten
414 bool did_open; // true if the file has been mmapped
415 ObjectType obj_type_;
417 // for sparc-solaris this is a table of PLT entry addr, function_name
418 // for x86-solaris this is a table of GOT entry addr, function_name
419 // on sparc-solaris the runtime linker modifies the PLT entry when it
420 // binds a function, on X86 the PLT entry is not modified, but it uses
421 // an indirect jump to a GOT entry that is modified when the function
422 // is bound....is this correct???? or should it be <PLTentry_addr, name>
424 std::vector<relocationEntry> relocation_table_;
425 std::vector<relocationEntry> fbt_;
427 // all section headers, sorted by address
428 // we use these to do a better job of finding the end of symbols
429 std::vector<Elf_X_Shdr*> allRegionHdrs;
431 // It doesn't look like image's equivalent hashtable is built by
432 // the time we need it, and it's hard to get to anyway.
433 dyn_hash_map< Offset, std::string > symbolNamesByAddr;
435 // Symbol version mappings. used to store symbol version names.
436 dyn_hash_map<unsigned, std::vector<std::string> >versionMapping;
437 dyn_hash_map<unsigned, std::string> versionFileNameMapping;
439 std::vector<std::string> deps_;
441 bool loaded_elf( Offset &, Offset &,
442 Elf_X_Shdr* &, Elf_X_Shdr* &,
443 Elf_X_Shdr* &, Elf_X_Shdr* &,
444 Elf_X_Shdr* &, Elf_X_Shdr* &,
445 Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp,
446 Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
447 Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& dynamic_scnp, Elf_X_Shdr*& eh_frame,
448 Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp,
451 void parseStabFileLineInfo(dyn_hash_map<std::string, LineInformation> &li);
452 void parseDwarfFileLineInfo(dyn_hash_map<std::string, LineInformation> &li);
454 void parseDwarfTypes(Symtab *obj);
455 void parseStabTypes(Symtab *obj);
457 void load_object(bool);
458 void load_shared_object(bool);
460 // initialize relocation_table_ from .rel[a].plt section entries
461 bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
462 Elf_X_Shdr *&dynsym_scnp,
463 Elf_X_Shdr *&dynstr_scnp);
465 bool get_relocationDyn_entries( Elf_X_Shdr *&rel_scnp,
466 Elf_X_Shdr *&dynsym_scnp,
467 Elf_X_Shdr *&dynstr_scnp );
469 void parseDynamic(Elf_X_Shdr *& dyn_scnp, Elf_X_Shdr *&dynsym_scnp,
470 Elf_X_Shdr *&dynstr_scnp);
472 void parse_symbols(std::vector<Symbol *> &allsymbols,
473 Elf_X_Data &symdata, Elf_X_Data &strdata,
477 void parse_dynamicSymbols( Elf_X_Shdr *& dyn_scnp, Elf_X_Data &symdata,
478 Elf_X_Data &strdata, bool shared_library,
481 void fix_zero_function_sizes(std::vector<Symbol *> &allsymbols, bool EEL);
482 void override_weak_symbols(std::vector<Symbol *> &allsymbols);
483 void insert_symbols_shared(std::vector<Symbol *> &allsymbols);
484 void find_code_and_data(Elf_X &elf,
485 Offset txtaddr, Offset dataddr);
486 void insert_symbols_static(std::vector<Symbol *> &allsymbols);
487 bool fix_global_symbol_modules_static_stab(Elf_X_Shdr *stabscnp,
488 Elf_X_Shdr *stabstrscnp);
489 bool fix_global_symbol_modules_static_dwarf(Elf_X &elf);
491 void get_valid_memory_areas(Elf_X &elf);
493 MappedFile *findMappedFileForDebugInfo();
499 Offset get_gp_value() const { return gp_value; }
500 Offset get_rbrk_addr() const { return rbrk_addr; }
501 Offset get_base_addr() const { return base_addr; }
502 const char *got_entry_name(Offset entry_off) const;
503 int got_gp_disp(const char *entry_name) const;
506 Offset MIPS_stubs_addr_; // .MIPS.stubs section
507 Offset MIPS_stubs_off_; // .MIPS.stubs section
508 unsigned MIPS_stubs_size_; // .MIPS.stubs section
516 int dynsym_zero_index_;
518 #endif /* mips_sgi_irix6_4 */
522 //const char *pdelf_get_shnames(Elf *elfp, bool is64);
524 }//namespace SymtabAPI
527 #endif /* !defined(_Object_elf_h_) */