2 * Copyright (c) 1996 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 * 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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 #include "util/h/Object.h"
43 #include "util/h/Object-elf32.h"
45 /**********************************************
47 * Implementation of "Object" (descriptive name, huh??) class for
48 * 32 bit ELF format....
50 **********************************************/
52 #ifdef _Object_elf32_h_
58 Object::operator=(const Object& obj) {
60 (void) AObject::operator=(obj);
62 plt_addr_ = obj.plt_addr_;
63 plt_size_ = obj.plt_size_;
64 plt_entry_size_ = obj.plt_entry_size_;
65 got_addr_ = obj.got_addr_;
66 rel_plt_addr_ = obj.rel_plt_addr_;
67 rel_plt_size_ = obj.rel_plt_size_;
68 rel_plt_entry_size_ = obj.rel_plt_entry_size_;
69 dyn_sym_addr_ = obj.dyn_sym_addr_;
70 dyn_str_addr_ = obj.dyn_str_addr_;
71 relocation_table_ = obj.relocation_table_;
75 void Object::log_elferror(void (*pfunc)(const char *), const char* msg) {
76 const char* err = elf_errmsg(elf_errno());
77 log_printf(pfunc, "%s: %s\n", msg, err ? err : "(bad elf error)");
84 #define EXTRA_SPACE 8 //added some EXTRA_SPACE space, such that,
85 // we won't look for functions in the data space
88 // Added one extra parameter 'char *ptr', for EEL rewritten software
89 // code_ptr_, code_offset_, code_len_ is calculated in this function
90 // For more detail , see comments with the word 'EEL'
93 Object::loaded_elf(int fd, char *ptr, bool& did_elf, Elf*& elfp,
95 Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
96 Elf_Scn*& symscnp, Elf_Scn*& strscnp, Elf_Scn*& stabscnp,
97 Elf_Scn*& stabstrscnp, Elf_Scn*& rel_plt_scnp, Elf_Scn*& plt_scnp,
98 Elf_Scn*& got_scnp, Elf_Scn*& dynsym_scnp, Elf_Scn*& dynstr_scnp) {
100 elf_version(EV_CURRENT);
103 if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
104 || (elf_kind(elfp) != ELF_K_ELF)) {
105 log_elferror(err_func_, "opening file");
110 if (((ehdrp = elf32_getehdr(elfp)) == 0)
111 || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
112 || (ehdrp->e_type != ET_EXEC && ehdrp->e_type != ET_DYN)
113 // support shared library code here also....
114 || (ehdrp->e_phoff == 0)
115 || (ehdrp->e_shoff == 0)
116 || (ehdrp->e_phnum == 0)
117 || (ehdrp->e_shnum == 0)) {
118 log_elferror(err_func_, "2: loading eheader");
122 if ((phdrp = elf32_getphdr(elfp)) == 0) {
123 log_elferror(err_func_, "loading pheader");
127 Elf_Scn* shstrscnp = 0;
128 Elf32_Shdr* shstrshdrp = 0;
129 Elf_Data* shstrdatap = 0;
130 if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
131 || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
132 || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
133 log_elferror(err_func_, "loading header section");
137 const char* shnames = (const char *) shstrdatap->d_buf;
140 // moved const char declrs out of loop....
141 const char* EDITED_TEXT_NAME = ".edited_text";
142 const char* TEXT_NAME = ".text";
143 const char* BSS_NAME = ".bss";
144 const char* SYMTAB_NAME = ".symtab";
145 const char* STRTAB_NAME = ".strtab";
146 const char* STAB_NAME = ".stab";
147 const char* STABSTR_NAME= ".stabstr";
149 // sections from dynamic executables and shared objects
150 const char* PLT_NAME = ".plt";
151 const char* REL_PLT_NAME = ".rela.plt"; // sparc-solaris
152 const char* REL_PLT_NAME2 = ".rel.plt"; // x86-solaris
153 const char* GOT_NAME = ".got";
154 const char* DYNSYM_NAME = ".dynsym";
155 const char* DYNSTR_NAME = ".dynstr";
157 while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
158 Elf32_Shdr* shdrp = elf32_getshdr(scnp);
160 log_elferror(err_func_, "scanning sections");
164 const char* name = (const char *) &shnames[shdrp->sh_name];
166 if (strcmp(name, EDITED_TEXT_NAME) == 0) {
167 // EEL rewriten executable
168 printf("This is an EEL rewritten executable \n") ;
170 txtaddr = shdrp->sh_addr;
171 code_ptr_ = (Word *) ((void*)&ptr[shdrp->sh_offset-EXTRA_SPACE]);
172 code_off_ = (Address) shdrp->sh_addr -EXTRA_SPACE ;
173 code_len_ = ((unsigned) shdrp->sh_size + EXTRA_SPACE) / sizeof(Word);
175 if (strcmp(name, TEXT_NAME) == 0) {
176 txtaddr = shdrp->sh_addr;
178 else if (strcmp(name, BSS_NAME) == 0) {
179 bssaddr = shdrp->sh_addr;
181 else if (strcmp(name, SYMTAB_NAME) == 0) {
184 else if (strcmp(name, STRTAB_NAME) == 0) {
187 else if (strcmp(name, STAB_NAME) == 0) {
190 else if (strcmp(name, STABSTR_NAME) == 0) {
193 else if ((strcmp(name, REL_PLT_NAME) == 0)
194 || (strcmp(name, REL_PLT_NAME2) == 0)) {
196 rel_plt_addr_ = shdrp->sh_addr;
197 rel_plt_size_ = shdrp->sh_size;
198 rel_plt_entry_size_ = shdrp->sh_entsize;
200 else if (strcmp(name, PLT_NAME) == 0) {
202 plt_addr_ = shdrp->sh_addr;
203 plt_size_ = shdrp->sh_size;
204 plt_entry_size_ = shdrp->sh_entsize;
206 else if (strcmp(name, GOT_NAME) == 0) {
208 got_addr_ = shdrp->sh_addr;
210 else if (strcmp(name, DYNSYM_NAME) == 0) {
212 dyn_sym_addr_ = shdrp->sh_addr;
214 else if (strcmp(name, DYNSTR_NAME) == 0) {
216 dyn_str_addr_ = shdrp->sh_addr;
220 if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
221 log_elferror(err_func_, "no text/bss/symbol/string section");
228 static int symbol_compare(const void *x, const void *y) {
229 const Symbol *s1 = (const Symbol *)x;
230 const Symbol *s2 = (const Symbol *)y;
231 return (s1->addr() - s2->addr());
234 bool Object::get_relocation_entries(Elf_Scn*& rel_plt_scnp,
235 Elf_Scn*& dynsymscnp, Elf_Scn*& dynstrscnp) {
237 #if defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0)
238 Elf32_Rel *next_entry = 0;
239 Elf32_Rel *entries = 0;
241 Elf32_Rela *next_entry = 0;
242 Elf32_Rela *entries = 0;
245 if(rel_plt_size_ && rel_plt_addr_) {
246 Elf_Data *reldatap = elf_getdata(rel_plt_scnp, 0);
247 Elf_Data* symdatap = elf_getdata(dynsymscnp, 0);
248 Elf_Data* strdatap = elf_getdata(dynstrscnp, 0);
249 if(!reldatap || !symdatap || !strdatap) return false;
251 Elf32_Sym* syms = (Elf32_Sym *) symdatap->d_buf;
252 const char* strs = (const char *) strdatap->d_buf;
253 Address next_plt_entry_addr = plt_addr_;
255 #if defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0)
256 entries = (Elf32_Rel *) reldatap->d_buf;
257 next_plt_entry_addr += plt_entry_size_; // 1st PLT entry is special
259 entries = (Elf32_Rela *) reldatap->d_buf;
260 next_plt_entry_addr += 4*(plt_entry_size_); //1st 4 entries are special
262 if(!entries) return false;
264 next_entry = entries;
265 for(u_int i=0; i < (rel_plt_size_/rel_plt_entry_size_); i++) {
266 Elf32_Word sym_index = ELF32_R_SYM(next_entry->r_info);
267 relocationEntry re(next_plt_entry_addr, next_entry->r_offset,
268 string(&strs[syms[sym_index].st_name]));
269 relocation_table_ += re;
271 next_plt_entry_addr += plt_entry_size_;
277 /*************************************************************
279 * New (Experimenta) version of code for loading statically linked
282 *************************************************************/
283 void Object::load_object() {
284 const char* file = file_.string_of();
290 bool did_open = false;
291 bool did_elf = false;
294 // try to open file for reading, and also use fstat to read info
295 // about the file in st structure....
296 if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
297 log_perror(err_func_, file);
298 /* throw exception */ goto cleanup;
302 // attempt to memory map entire file. st.st_size should contain file
303 // size (in bytes)....
304 if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
306 log_perror(err_func_, "mmap");
307 /* throw exception */ goto cleanup;
310 Elf32_Ehdr* ehdrp = 0; /* ELF header */
311 Elf32_Phdr* phdrp = 0; /* program header */
312 Elf_Scn* symscnp = 0;
313 Elf_Scn* strscnp = 0;
314 Elf_Scn* stabscnp = 0;
315 Elf_Scn* stabstrscnp = 0;
316 unsigned txtaddr = 0;
317 unsigned bssaddr = 0;
318 Elf_Scn* rel_plt_scnp = 0;
319 Elf_Scn* plt_scnp = 0;
320 Elf_Scn* got_scnp = 0;
321 Elf_Scn* dynsym_scnp = 0;
322 Elf_Scn* dynstr_scnp = 0;
324 // EEL, initialize the stuff to zero, so that we know, it is not
325 // EEL rewritten, if they have not been changed by loaded_elf
327 code_ptr_ = 0; code_off_ = 0 ; code_len_ = 0 ;
329 // And attempt to parse the ELF data structures in the file....
330 // EEL, added one more parameter
331 if (!loaded_elf(fd, ptr, did_elf, elfp, ehdrp, phdrp, txtaddr,
332 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp,
333 rel_plt_scnp,plt_scnp,got_scnp,dynsym_scnp,dynstr_scnp)) {
334 /* throw exception */ goto cleanup;
337 // find code and data segments....
338 find_code_and_data(ehdrp, phdrp, ptr, txtaddr, bssaddr);
340 // if could not find code or data segments, log error....
341 if (!code_ptr_ || !code_off_ || !code_len_) {
342 log_printf(err_func_, "cannot locate instructions\n");
343 /* throw exception */ goto cleanup;
345 if (!data_ptr_ || !data_off_ || !data_len_) {
346 log_printf(err_func_, "cannot locate data segment\n");
347 /* throw exception */ goto cleanup;
350 Elf_Data* symdatap = elf_getdata(symscnp, 0);
351 Elf_Data* strdatap = elf_getdata(strscnp, 0);
352 if (!symdatap || !strdatap) {
353 log_elferror(err_func_, "locating symbol/string data");
354 /* throw exception */ goto cleanup;
357 Elf32_Sym* syms = (Elf32_Sym *) symdatap->d_buf;
358 unsigned nsyms = symdatap->d_size / sizeof(Elf32_Sym);
359 const char* strs = (const char *) strdatap->d_buf;
360 string module = "DEFAULT_MODULE";
361 string name = "DEFAULT_NAME";
363 // global symbols are put in global_symbols. Later we read the
364 // stab section to find the module to where they belong.
365 // Experiment : lets try to be a bit more intelligent about
366 // how we initially size the global_symbols table.
367 // dictionary_lite takes an initial # of bins (2nd param),
368 // a max bin load (3rd param), and a grow factor (4th param).
369 // Leaving aside the grow factor, lets allocate an initial #
370 // of bins = nsyms / max bin load.
371 dictionary_hash<string, Symbol> global_symbols(string::hash, \
374 vector<Symbol> allsymbols;
376 // try to resolve all symbols found in symbol table +
377 // enter them into <allsymbols>.
378 parse_symbols(allsymbols, syms, nsyms, strs, 1, \
381 // Sort all the symbols - for patching symbol data sizes....
382 allsymbols.sort(symbol_compare);
384 // patch 0 symbol sizes....
385 fix_zero_function_sizes(allsymbols, 0);
387 // override instances of weak symbols w/ instances of strong ones,
388 // also currently has effect of making sure that symbols dont
389 // extend beyond the marked beginning of the next symbo....
390 override_weak_symbols(allsymbols);
392 // and dump <allsymbols> into (data member) symbols_
393 // or (paramater) <global_symbols> accoriding to linkage....
394 insert_symbols_static(allsymbols, global_symbols);
396 // try to use the .stab section to figure modules for symbols
397 // in global <global_symbols>....
398 fix_global_symbol_modules_static(global_symbols, \
399 stabscnp, stabstrscnp);
401 if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
402 if(!get_relocation_entries(rel_plt_scnp,\
403 dynsym_scnp,dynstr_scnp)) {
413 if (did_elf && (elf_end(elfp) != 0)) {
414 log_elferror(err_func_, "closing file");
416 if (did_open && (close(fd) == -1)) {
417 log_perror(err_func_, "close");
423 /*************************************************************
425 * New (Experimental) version of code for loading shared
428 *************************************************************/
431 Object::load_shared_object() {
432 const char* file = file_.string_of();
438 bool did_open = false;
439 bool did_elf = false;
442 if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
443 log_perror(err_func_, file);
444 /* throw exception */ goto cleanup2;
448 if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
450 log_perror(err_func_, "mmap");
451 /* throw exception */ goto cleanup2;
454 Elf32_Ehdr* ehdrp = 0; /* ELF header */
455 Elf32_Phdr* phdrp = 0; /* program header */
456 Elf_Scn* symscnp = 0;
457 Elf_Scn* stabscnp = 0;
458 Elf_Scn* stabstrscnp = 0;
459 Elf_Scn* strscnp = 0;
460 unsigned txtaddr = 0;
461 unsigned bssaddr = 0;
462 Elf_Scn* rel_plt_scnp = 0;
463 Elf_Scn* plt_scnp = 0;
464 Elf_Scn* got_scnp = 0;
465 Elf_Scn* dynsym_scnp = 0;
466 Elf_Scn* dynstr_scnp = 0;
468 /*** ptr, stabscnp, stabstrscnp should NOT be filled in if the parsed
469 object was a shared library ***/
470 if (!loaded_elf(fd, ptr, did_elf, elfp, ehdrp, phdrp, txtaddr,
471 bssaddr, symscnp, strscnp, stabscnp, stabstrscnp,
472 rel_plt_scnp, plt_scnp,got_scnp,dynsym_scnp, dynstr_scnp)) {
473 /* throw exception */ goto cleanup2;
476 // find code and data segments....
477 find_code_and_data(ehdrp, phdrp, ptr, txtaddr, bssaddr);
479 Elf_Data* symdatap = elf_getdata(symscnp, 0);
480 Elf_Data* strdatap = elf_getdata(strscnp, 0);
481 if (!symdatap || !strdatap) {
482 log_elferror(err_func_, "locating symbol/string data");
483 /* throw exception */ goto cleanup2;
486 Elf32_Sym* syms = (Elf32_Sym *) symdatap->d_buf;
487 unsigned nsyms = symdatap->d_size / sizeof(Elf32_Sym);
488 const char* strs = (const char *) strdatap->d_buf;
489 string module = "DEFAULT_MODULE";
490 string name = "DEFAULT_NAME";
492 // for shared objects add a module that is the file name
493 // and add all the global symbols as functions
494 const char *libname = file_.string_of();
496 const char *last = 0;
497 for(u_int i=0; i < file_.length();i++) {
498 if(libname[i] == '/'){
499 last = (const char *)(&(libname[i]));
500 // log_elferror(err_func_, P_strdup(last));
504 module = (const char *)(last +1);
507 module = string("DEFAULT_MODULE");
510 // temporary vector of symbols
511 vector<Symbol> allsymbols;
513 // try to resolve all symbols found in symbol table +
514 // enter them into <allsymbols>.
515 parse_symbols(allsymbols, syms, nsyms, strs, 1, \
518 // Sort all the symbols - for patching symbol data sizes....
519 allsymbols.sort(symbol_compare);
521 // patch 0 symbol sizes....
522 fix_zero_function_sizes(allsymbols, 0);
524 // override instances of weak symbols w/ instances of strong ones,
525 // also currently has effect of making sure that symbols dont
526 // extend beyond the marked beginning of the next symbo....
527 override_weak_symbols(allsymbols);
529 // and inset all found (and theoretically patched) symbols
530 // into (data member) symbols_.
531 insert_symbols_shared(allsymbols);
533 if(rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
534 if(!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) {
544 if (did_elf && (elf_end(elfp) != 0)) {
545 log_elferror(err_func_, "closing file");
547 if (did_open && (close(fd) == -1)) {
548 log_perror(err_func_, "close");
554 /*************************************************************
556 * Run through symbol table <syms> (with <nsyms> entries, where
557 * <strs> points to string table), finding all symbols
558 * of type in {STT_FILE, STT_OBJECT, STT_FUNC, STT_NOTYPE}, and
559 * registering the symbol in allsymbols with appropriate type,
561 * shared - indicates whether the object file being parsed is a
563 * module - only filled in for shared libraries. Contains name
564 * of shared library module. As per origional (spaghetti) code
565 * scattered in old load_object && load_shared_object, the symbol
566 * reference with the same name as the shared library itself
567 * s stuffed directly itno (data member) symbols_ ....
569 **************************************************************/
570 void Object::parse_symbols(vector<Symbol> &allsymbols, Elf32_Sym* \
571 syms, unsigned nsyms, const char *strs, bool shared_library, \
575 // name of symbol, and name of module under which to register function,
577 string name, module_name_used;
580 Symbol::SymbolType type;
581 Symbol::SymbolLinkage linkage;
584 //cerr << "PARSING SYMBOLS FOR MODULE " << module << endl;
585 for (i1 = 0; i1 < nsyms; i1++) {
586 // First, we must check st_shndx.
587 // if st_shndx == SHN_UNDEF, this is an undefined symbol,
588 // probably defined in a shared object that will be dynamically
589 // linked with the executable. We just ignore it for now.
590 if (syms[i1].st_shndx != SHN_UNDEF) {
591 name = string(&strs[syms[i1].st_name]);
592 //cerr << " Found non undefined symbol : " << name << endl;
593 bool st_kludge = false;
594 type = Symbol::PDST_UNKNOWN;
595 // resolve symbol type....
596 switch (type = ELF32_ST_TYPE(syms[i1].st_info)) {
598 //cerr << " name matches module name" << endl;
599 type = Symbol::PDST_MODULE;
600 //cerr << " ELF32_ST_TYPE = STT_FILE";
604 //cerr << " ELF32_ST_TYPE = STT_OBJECT";
605 type = Symbol::PDST_OBJECT;
609 //cerr << " ELF32_ST_TYPE = STT_FUNC";
610 type = Symbol::PDST_FUNCTION;
614 //cerr << " ELF32_ST_TYPE = STT_NOTYPE";
615 type = Symbol::PDST_NOTYPE;
619 //cerr << " ELF32_ST_TYPE not supported";
623 // and resolve symbol binding....
624 switch (binding = ELF32_ST_BIND(syms[i1].st_info)) {
626 //cerr << " ELF_32_ST_BIND = STB_LOCAL" << endl;
627 linkage = Symbol::SL_LOCAL;
630 //cerr << " ELF_32_ST_BIND = STB_WEAK" << endl;
631 linkage = Symbol::SL_WEAK;
634 //cerr << " ELF_32_ST_BIND = STB_GLOBAL" << endl;
635 linkage = Symbol::SL_GLOBAL;
638 //cerr << " ELF_32_ST_BIND UNKNOWN!!!!" << endl;
642 // special case for shared libraries. If the symbol
643 // is of type file, and the binding is local binding, and
644 // name matches the module name, then stick the symbol
645 // directly into (data member) symbols_ (as SL_LOCAL).
646 if (type == STT_FILE && binding == STB_LOCAL && \
648 symbols_[name] = Symbol(name, module, type, linkage,
649 syms[i1].st_value, st_kludge,
652 // otherwise, register found symbol under its name &&
654 allsymbols += Symbol(name, module,
656 syms[i1].st_value, st_kludge,
665 /********************************************************
667 * Apparently, some compilers do not fill in the symbol sizes
668 * correctly (in the symbol table) for functions. Run through
669 * symbol vector allsymbols, and compute ?correct? sizes....
670 * This patch to symbol sizes runs through allsymbols && tries
671 * to patch all functions symbols recorded with a size of 0,
672 * or which have been EEL overwritten.
673 * Assumes that allsymbols is sorted, with e.g. symbol_compare....
675 ********************************************************/
676 void Object::fix_zero_function_sizes(vector<Symbol> &allsymbols, bool EEL) {
677 unsigned u, v, nsymbols;
679 nsymbols = allsymbols.size();
680 for (u=0; u < nsymbols; u++) {
681 // If function symbol, and size set to 0, or if the
682 // executable has been EEL rewritten, patch the size
683 // to the offset of next symbol - offset of this symbol....
684 if (allsymbols[u].type() == Symbol::PDST_FUNCTION
685 && (EEL || allsymbols[u].size() == 0)) {
687 while (v < nsymbols && allsymbols[v].addr() == allsymbols[u].addr())
690 allsymbols[u].change_size((unsigned)allsymbols[v].addr()
691 - (unsigned)allsymbols[u].addr());
697 /********************************************************
699 * Run over list of symbols found in a SHARED LIBRARY ONLY -
700 * Override weak AND LOCAL symbol references for which there is also
701 * a global symbol reference, by setting the size on the weak
703 * Also potentially patches the size on such symbols (note that
704 * Object::fix_symbol_sizes (above) patches sizes on functions
705 * recorded with a size of 0. This fixes nonero sized functions
706 * in the case where 2 functions follow eachother in the symbol
707 * table, and the first has a size which would extend into the
708 * second. WHY IS THIS ONLY DONE FOR SHARED LIBRARIES....
710 * Assumes that allsymbols is sorted, with e.g. symbol_compare....
712 ********************************************************/
713 void Object::override_weak_symbols(vector<Symbol> &allsymbols) {
714 unsigned i, nsymbols;
717 bool i_weak_or_local;
718 bool ip1_weak_or_local;
720 //cerr << "overriding weak symbols for which there is also a global symbol reference...." << endl;
721 nsymbols = allsymbols.size();
722 for (i=0; i < nsymbols; i++) {
723 if((allsymbols[i].type() == Symbol::PDST_FUNCTION)
724 && (allsymbols[i+1].type() == Symbol::PDST_FUNCTION)) {
726 // where symbol i+1 should start, based on start of symbol i
727 // and size of symbol i....
728 next_start=allsymbols[i].addr()+allsymbols[i].size();
730 // do symbols i and i+1 have weak or local bindings....
731 i_weak_or_local = ((allsymbols[i].linkage() == Symbol::SL_WEAK) || \
732 (allsymbols[i].linkage() == Symbol::SL_LOCAL));
733 ip1_weak_or_local = ((allsymbols[i+1].linkage() == Symbol::SL_WEAK) || \
734 (allsymbols[i+1].linkage() == Symbol::SL_LOCAL));
736 // if the symbols have the same address and one is weak or local
737 // and the other is global keeep the global one
738 if((allsymbols[i].addr() == allsymbols[i+1].addr()) &&
739 (((i_weak_or_local) &&
740 (allsymbols[i+1].linkage() == Symbol::SL_GLOBAL)) ||
741 ((allsymbols[i].linkage() == Symbol::SL_GLOBAL) &&
742 (ip1_weak_or_local)))) {
744 if (i_weak_or_local) {
745 allsymbols[i].change_size(0);
746 //cerr << " (type 1) removing symbol " << allsymbols[i];
748 allsymbols[i+1].change_size(0);
749 //cerr << " (type 1) removing symbol " << allsymbols[i+1];
752 // looks like may possibly need to patch size of symbol i
753 // based on start of symbol i + 1????
754 else if (next_start > allsymbols[i+1].addr()) {
755 next_size = allsymbols[i+1].addr() - allsymbols[i].addr();
756 allsymbols[i].change_size(next_size);
757 //cerr << " (type 2) changing symbol size of symbol " << \
758 allsymbols[i] << "to size " << next_size << endl;
764 /********************************************************
766 * For object files only....
767 * read the .stab section to find the module of global symbols
769 ********************************************************/
770 void Object::fix_global_symbol_modules_static( \
771 dictionary_hash<string, Symbol> global_symbols, \
772 Elf_Scn* stabscnp, Elf_Scn* stabstrscnp) {
773 // Read the stab section to find the module of global symbols.
774 // The symbols appear in the stab section by module. A module begins
775 // with a symbol of type N_UNDF and ends with a symbol of type N_ENDM.
776 // All the symbols in between those two symbols belong to the module.
778 Elf_Data* stabdatap = elf_getdata(stabscnp, 0);
779 Elf_Data* stabstrdatap = elf_getdata(stabstrscnp, 0);
780 struct stab_entry *stabsyms = 0;
782 const char *stabstrs = 0;
785 if (stabdatap && stabstrdatap) {
786 stabsyms = (struct stab_entry *) stabdatap->d_buf;
787 stab_nsyms = stabdatap->d_size / sizeof(struct stab_entry);
788 stabstrs = (const char *) stabstrdatap->d_buf;
793 // the stabstr contains one string table for each module.
794 // stabstr_offset gives the offset from the begining of stabstr of the
795 // string table for the current module.
796 // stabstr_nextoffset gives the offset for the next module.
797 unsigned stabstr_offset = 0;
798 unsigned stabstr_nextoffset = 0;
800 bool is_fortran = false; // is the current module fortran code?
801 /* we must know if we are reading a fortran module because fortran
802 symbol names are different in the .stab and .symtab sections.
803 A symbol that appears as 'foo' in the .stab section, appears
804 as 'foo_' in .symtab.
808 for (unsigned i = 0; i < stab_nsyms; i++) {
809 switch(stabsyms[i].type) {
810 case N_UNDF: /* start of object file */
811 assert(stabsyms[i].name == 1);
812 stabstr_offset = stabstr_nextoffset;
813 // stabsyms[i].val has the size of the string table of this module.
814 // We use this value to compute the offset of the next string table.
815 stabstr_nextoffset = stabstr_offset + stabsyms[i].val;
816 module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
819 case N_ENDM: /* end of object file */
824 case N_SO: /* compilation source or file name */
825 if (stabsyms[i].desc == N_SO_FORTRAN)
828 module = string(&stabstrs[stabstr_offset+stabsyms[i].name]);
831 case N_ENTRY: /* fortran alternate subroutine entry point */
832 case N_FUN: /* function */
833 case N_GSYM: /* global symbol */
834 // the name string of a function or object appears in the stab string table
835 // as <symbol name>:<symbol descriptor><other stuff>
836 // where <symbol descriptor> is a one char code.
837 // we must extract the name and descriptor from the string
839 const char *p = &stabstrs[stabstr_offset+stabsyms[i].name];
840 const char *q = strchr(p,':');
842 unsigned len = q - p;
844 char *sname = new char[len+1];
845 strncpy(sname, p, len);
848 // q points to the ':' in the name string, so
849 // q[1] is the symbol descriptor. We must check the symbol descriptor
850 // here to skip things we are not interested in, such as local functions
852 if (q[1] == SD_GLOBAL_FUN || q[1] == SD_GLOBAL_VAR || stabsyms[i].type==N_ENTRY) {
853 string SymName = string(sname);
854 bool res = global_symbols.defines(SymName);
855 if (!res && is_fortran) {
856 // Fortran symbols usually appear with an '_' appended in .symtab,
859 res = global_symbols.defines(SymName);
863 // assert(res); // All globals in .stab should be defined in .symtab
865 Symbol sym = global_symbols[SymName];
866 symbols_[SymName] = Symbol(sym.name(), module, \
867 sym.type(), sym.linkage(), sym.addr(), \
868 sym.kludge(), sym.size());
874 /* ignore other entries */
879 /* The remaing symbols go without module */
880 vector<string> k = global_symbols.keys();
881 for (unsigned i2 = 0; i2 < k.size(); i2++) {
882 Symbol sym = global_symbols[k[i2]];
883 if (!(symbols_.defines(sym.name())))
884 symbols_[sym.name()] = sym;
888 /********************************************************
890 * Run over allsymbols, and stuff symbols contained according
891 * to following rules:
892 * LOCAL symbols - into (data member) symbols_
893 * GLOBAL symbols - into (paramater) global_symbols
894 * WEAK symbols - looks like this case isnt handled correctly
895 * for static libraries....
897 ********************************************************/
898 void Object::insert_symbols_static(vector<Symbol> allsymbols, \
899 dictionary_hash<string, Symbol> &global_symbols) {
900 unsigned u, nsymbols = allsymbols.size();
902 for (u=0;u<nsymbols;u++) {
903 // We are done with the local symbols. We save the global so that
904 // we can get their module from the .stab section.
905 if (allsymbols[u].linkage() == Symbol::SL_LOCAL)
906 symbols_[allsymbols[u].name()] = allsymbols[u];
908 // globals should be unique
909 assert(!(global_symbols.defines(allsymbols[u].name())));
910 global_symbols[allsymbols[u].name()] = allsymbols[u];
915 /********************************************************
917 * Run over allsymbols, and stuff symbols it contains into (data
920 * Assumes that all kludges, patches, fixes, hacks, to objects
921 * in allsymbols have already been made, and that it safe to
922 * dump them into symbols_ (data member, instead of stack var....)....
924 ********************************************************/
925 void Object::insert_symbols_shared(vector<Symbol> allsymbols) {
926 unsigned i, nsymbols;
928 nsymbols = allsymbols.size();
929 for (i=0;i<nsymbols;i++) {
930 symbols_[allsymbols[i].name()] =
931 Symbol(allsymbols[i].name(), allsymbols[i].module(),
932 allsymbols[i].type(), allsymbols[i].linkage(),
933 allsymbols[i].addr(), allsymbols[i].kludge(),
934 allsymbols[i].size());
938 /*********************************************************
940 * Object::find_code_and_data - find addressm offset, and
941 * length of code and data sections of file described
944 * fills in (data members) code_ptr_, code_off_, code_len_,
945 * data_ptr_, data_off_, data_len_. As per origional code
946 * of which this is a severely cleaned up version, does not
947 * check here for success or failure.
951 *********************************************************/
952 void Object::find_code_and_data(Elf32_Ehdr* ehdrp, Elf32_Phdr* phdrp, \
953 char *ptr, unsigned txtaddr, unsigned bssaddr) {
956 for (i0 = 0; i0 < ehdrp-> e_phnum;i0++) {
957 if ((phdrp[i0].p_vaddr <= txtaddr)
958 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= txtaddr)) {
959 if (!code_ptr_ && !code_off_ && !code_len_) {
960 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i0].p_offset]);
961 code_off_ = (Address) phdrp[i0].p_vaddr;
962 code_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
965 else if ((phdrp[i0].p_vaddr <= bssaddr)
966 && ((phdrp[i0].p_vaddr+phdrp[i0].p_memsz) >= bssaddr)) {
967 if (!data_ptr_ && !data_off_ && !data_len_) {
968 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i0].p_offset]);
969 data_off_ = (Address) phdrp[i0].p_vaddr;
970 data_len_ = (unsigned) phdrp[i0].p_memsz / sizeof(Word);
976 Object::Object(const string file, void (*err_func)(const char *))
977 : AObject(file, err_func), EEL(false) {
979 //dump_state_info(cerr);
982 Object::Object(const string file, u_int ,void (*err_func)(const char *))
983 : AObject(file, err_func), EEL(false) {
984 load_shared_object();
985 //dump_state_info(cerr);
988 Object::Object(const Object& obj)
989 : AObject(obj), EEL(false) {
993 inline bool Object::get_func_binding_table(vector<relocationEntry> &fbt) const {
994 if(!plt_addr_ || (!relocation_table_.size())) return false;
995 fbt = relocation_table_;
999 inline bool Object::get_func_binding_table_ptr(const vector<relocationEntry> *&fbt) const {
1000 if(!plt_addr_ || (!relocation_table_.size())) return false;
1001 fbt = &relocation_table_;
1005 /**************************************************
1007 * Stream based debuggering output - for resgreesion testing.
1008 * Dump info on state of object *this....
1010 **************************************************/
1012 const ostream &Object::dump_state_info(ostream &s) {
1015 s << "Debugging Information for Object (address) : " << this << endl;
1017 s << " <<begin debugging info for base object>>" << endl;
1018 AObject::dump_state_info(s);
1019 s << " <<end debuggingo info for base object>>" << endl;
1021 s << " plt_addr_ = " << plt_addr_ << endl;
1022 s << " plt_size_ = " << plt_size_ << endl;
1023 s << " plt_entry_size_ = " << plt_entry_size_ << endl;
1024 s << " get_addr_ = " << got_addr_ << endl;
1025 s << " rel_plt_addr_ = " << rel_plt_addr_ << endl;
1026 s << " rel_plt_size_ = " << rel_plt_size_ << endl;
1027 s << " rel_plt_entry_size_ = " << rel_plt_entry_size_ << endl;
1028 s << " dyn_sym_addr_ = " << dyn_sym_addr_ << endl;
1029 s << " dyn_str_addr_ = " << dyn_str_addr_ << endl;
1031 // and dump the relocation table....
1032 s << " relocation_table_ = (field seperator :: )" << endl;
1033 for (i=0;i<relocation_table_.size();i++) {
1034 s << relocation_table_[i] << " :: ";
1041 #endif /* #ifdef Object_elf32_h_ */