00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "Type.h"
00037 #include "Variable.h"
00038 #include "Symbol.h"
00039 #include "Symtab.h"
00040 #include "Object.h"
00041
00042 #include "emitElf.h"
00043 #include "Module.h"
00044 #include "Aggregate.h"
00045 #include "Function.h"
00046
00047 #include "debug.h"
00048
00049 #include "dwarf/h/dwarfHandle.h"
00050
00051 #if defined(x86_64_unknown_linux2_4) || \
00052 defined(ppc64_linux) || \
00053 (defined(os_freebsd) && defined(arch_x86_64))
00054 #include "emitElf-64.h"
00055 #endif
00056
00057 #include "dwarfWalker.h"
00058
00059 using namespace Dyninst;
00060 using namespace Dyninst::SymtabAPI;
00061 using namespace Dyninst::Dwarf;
00062 using namespace std;
00063
00064 #if !defined(_Object_elf_h_)
00065 #error "Object-elf.h not #included"
00066 #endif
00067
00068 #include <elf.h>
00069 #include <stdio.h>
00070 #include <algorithm>
00071
00072 #if defined(USES_DWARF_DEBUG)
00073 #include "dwarf.h"
00074 #include "libdwarf.h"
00075 #endif
00076
00077
00078 #include "common/h/pathName.h"
00079 #include "Collections.h"
00080 #if defined(TIMED_PARSE)
00081 #include <sys/time.h>
00082 #endif
00083 #include <iostream>
00084 #include <iomanip>
00085
00086 #include <fstream>
00087 #include <sys/stat.h>
00088
00089 #include <boost/assign/list_of.hpp>
00090 #include <boost/assign/std/set.hpp>
00091
00092 #include "dynutil/h/SymReader.h"
00093
00094 using namespace boost::assign;
00095
00096 #include <libgen.h>
00097
00098
00099 #define EXTRA_SPACE 8
00100
00101 bool Object::truncateLineFilenames = true;
00102
00103 string symt_current_func_name;
00104 string symt_current_mangled_func_name;
00105 Symbol *symt_current_func = NULL;
00106
00107 std::vector<Symbol *> opdsymbols_;
00108
00109 extern void print_symbols( std::vector< Symbol *>& allsymbols );
00110 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
00111
00112 void (*dwarf_err_func)(const char *);
00113
00114 static bool pdelf_check_ehdr(Elf_X &elf)
00115 {
00116
00117
00118
00119
00120
00121 return ( (elf.e_type() == ET_EXEC || elf.e_type() == ET_DYN || elf.e_type() == ET_REL ) &&
00122 ( ((elf.e_shoff() != 0) && (elf.e_shnum() != 0))
00123 || ((elf.e_phoff() != 0) && (elf.e_phnum() != 0))
00124 )
00125 );
00126 }
00127
00128 const char *pdelf_get_shnames(Elf_X *elf)
00129 {
00130 const char *result = NULL;
00131 size_t shstrndx = elf->e_shstrndx();
00132
00133 Elf_X_Shdr &shstrscn = elf->get_shdr(shstrndx);
00134 if (shstrscn.isValid()) {
00135 Elf_X_Data shstrdata = shstrscn.get_data();
00136 if (shstrdata.isValid())
00137 result = shstrdata.get_string();
00138 }
00139 return result;
00140 }
00141
00142
00143
00144
00145
00146
00147 struct SectionHeaderSortFunction: public binary_function<Elf_X_Shdr *, Elf_X_Shdr *, bool>
00148 {
00149 bool operator()(Elf_X_Shdr *hdr1, Elf_X_Shdr *hdr2) {
00150 return (hdr1->sh_addr() < hdr2->sh_addr());
00151 }
00152 };
00153
00154 Region::perm_t getSegmentPerms(unsigned long flags){
00155 if(flags == 7)
00156 return Region::RP_RWX;
00157 else if(flags == 6)
00158 return Region::RP_RW;
00159 else if(flags == 5)
00160 return Region::RP_RX;
00161 else
00162 return Region::RP_R;
00163 }
00164
00165 Region::RegionType getSegmentType(unsigned long type, unsigned long flags)
00166 {
00167 if(type == PT_DYNAMIC)
00168 return Region::RT_DYNAMIC;
00169 if(flags == 7)
00170 return Region::RT_TEXTDATA;
00171 if(flags == 5)
00172 return Region::RT_TEXT;
00173 if(flags == 6)
00174 return Region::RT_DATA;
00175 return Region::RT_OTHER;
00176 }
00177
00178
00179 Elf_X_Shdr *Object::getRegionHdrByAddr(Offset addr)
00180 {
00181 unsigned end = allRegionHdrs.size() - 1, start = 0;
00182 unsigned mid = 0;
00183 while(start < end) {
00184 mid = start + (end-start)/2;
00185 if(allRegionHdrs[mid]->sh_addr() == addr)
00186 return allRegionHdrs[mid];
00187 else if(allRegionHdrs[mid]->sh_addr() < addr)
00188 start = mid + 1;
00189 else
00190 end = mid;
00191 }
00192 if(allRegionHdrs[start]->sh_addr() == addr)
00193 return allRegionHdrs[start];
00194 return NULL;
00195 }
00196
00197
00198
00199 int Object::getRegionHdrIndexByAddr(Offset addr)
00200 {
00201 int end = allRegionHdrs.size() - 1, start = 0;
00202 int mid = 0;
00203 while(start < end) {
00204 mid = start + (end-start)/2;
00205 if(allRegionHdrs[mid]->sh_addr() == addr)
00206 return mid;
00207 else if(allRegionHdrs[mid]->sh_addr() < addr)
00208 start = mid + 1;
00209 else
00210 end = mid;
00211 }
00212 if(allRegionHdrs[start]->sh_addr() == addr)
00213 return start;
00214 return -1;
00215 }
00216
00217 Elf_X_Shdr *Object::getRegionHdrByIndex(unsigned index)
00218 {
00219 if (index >= allRegionHdrs.size())
00220 return NULL;
00221 return allRegionHdrs[index];
00222 }
00223
00224
00225
00226 bool Object::isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned segPerms){
00227 bool present = false;
00228 for(unsigned i = 0; i < regions_.size() ;i++){
00229 if((regions_[i]->getDiskOffset() >= segmentStart) &&
00230 ((regions_[i]->getDiskOffset()+regions_[i]->getDiskSize()) <= (segmentStart+segmentSize))){
00231 present = true;
00232 regions_[i]->setRegionPermissions(getSegmentPerms(segPerms));
00233 }
00234
00235 }
00236 return present;
00237 }
00238
00239 Region::perm_t getRegionPerms(unsigned long flags){
00240 if((flags & SHF_WRITE) && !(flags & SHF_EXECINSTR))
00241 return Region::RP_RW;
00242 else if(!(flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
00243 return Region::RP_RX;
00244 else if((flags & SHF_WRITE) && (flags & SHF_EXECINSTR))
00245 return Region::RP_RWX;
00246 else
00247 return Region::RP_R;
00248 }
00249
00250 Region::RegionType getRegionType(unsigned long type, unsigned long flags, const char *reg_name){
00251 switch(type){
00252 case SHT_SYMTAB:
00253 case SHT_DYNSYM:
00254 return Region::RT_SYMTAB;
00255 case SHT_STRTAB:
00256 return Region::RT_STRTAB;
00257 case SHT_REL:
00258 return Region::RT_REL;
00259 case SHT_RELA:
00260 return Region::RT_RELA;
00261 case SHT_NOBITS:
00262
00263
00264 if (strcmp(reg_name, ".plt") == 0)
00265 return Region::RT_OTHER;
00266 else
00267 return Region::RT_BSS;
00268 case SHT_PROGBITS:
00269 if((flags & SHF_EXECINSTR) && (flags & SHF_WRITE))
00270 return Region::RT_TEXTDATA;
00271 else if(flags & SHF_EXECINSTR)
00272 return Region::RT_TEXT;
00273 else
00274 return Region::RT_DATA;
00275 case SHT_DYNAMIC:
00276 return Region::RT_DYNAMIC;
00277 case SHT_HASH:
00278 return Region::RT_HASH;
00279 case SHT_GNU_versym:
00280 return Region::RT_SYMVERSIONS;
00281 case SHT_GNU_verdef:
00282 return Region::RT_SYMVERDEF;
00283 case SHT_GNU_verneed:
00284 return Region::RT_SYMVERNEEDED;
00285 default:
00286 return Region::RT_OTHER;
00287 }
00288 }
00289
00290 static Region::RegionType getRelTypeByElfMachine(Elf_X *localHdr) {
00291 Region::RegionType ret;
00292 switch(localHdr->e_machine()) {
00293 case EM_SPARC:
00294 case EM_SPARC32PLUS:
00295 case EM_SPARCV9:
00296 case EM_PPC:
00297 case EM_PPC64:
00298 case EM_X86_64:
00299 case EM_IA_64:
00300 ret = Region::RT_RELA;
00301 break;
00302 default:
00303 ret = Region::RT_REL;
00304 break;
00305 }
00306 return ret;
00307 }
00308
00309 const char* EDITED_TEXT_NAME = ".edited.text";
00310
00311 const char *INTERP_NAME = ".interp";
00312 const char* FINI_NAME = ".fini";
00313 const char* TEXT_NAME = ".text";
00314 const char* BSS_NAME = ".bss";
00315 const char* SYMTAB_NAME = ".symtab";
00316 const char* STRTAB_NAME = ".strtab";
00317 const char* STAB_NAME = ".stab";
00318 const char* STABSTR_NAME = ".stabstr";
00319 const char* STAB_INDX_NAME = ".stab.index";
00320 const char* STABSTR_INDX_NAME= ".stab.indexstr";
00321 const char* COMMENT_NAME= ".comment";
00322 const char* OPD_NAME = ".opd";
00323
00324 const char* PLT_NAME = ".plt";
00325 #if defined(os_vxworks)
00326 const char* REL_PLT_NAME = ".rela.text";
00327 #else
00328 const char* REL_PLT_NAME = ".rela.plt";
00329 #endif
00330 const char* REL_PLT_NAME2 = ".rel.plt";
00331 const char* GOT_NAME = ".got";
00332 const char* DYNSYM_NAME = ".dynsym";
00333 const char* DYNSTR_NAME = ".dynstr";
00334 const char* DATA_NAME = ".data";
00335 const char* RO_DATA_NAME = ".ro_data";
00336 const char* DYNAMIC_NAME = ".dynamic";
00337 const char* EH_FRAME_NAME = ".eh_frame";
00338 const char* EXCEPT_NAME = ".gcc_except_table";
00339 const char* EXCEPT_NAME_ALT = ".except_table";
00340
00341 set<string> debugInfoSections = list_of(string(SYMTAB_NAME))
00342 (string(STRTAB_NAME));
00343
00344
00345
00346 bool Object::loaded_elf(Offset& txtaddr, Offset& dataddr,
00347 Elf_X_Shdr* &bssscnp,
00348 Elf_X_Shdr*& symscnp, Elf_X_Shdr*& strscnp,
00349 Elf_X_Shdr*& stabscnp, Elf_X_Shdr*& stabstrscnp,
00350 Elf_X_Shdr*& stabs_indxcnp, Elf_X_Shdr*& stabstrs_indxcnp,
00351 Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp,
00352 Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
00353 Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr* &dynamic_scnp,
00354 Elf_X_Shdr*& eh_frame, Elf_X_Shdr*& gcc_except,
00355 Elf_X_Shdr *& interp_scnp, Elf_X_Shdr *& opd_scnp,
00356 bool)
00357 {
00358 std::map<std::string, int> secnNameMap;
00359 dwarf_err_func = err_func_;
00360 entryAddress_ = elfHdr->e_entry();
00361
00362 no_of_sections_ = elfHdr->e_shnum();
00363
00364
00365 const char *shnames = pdelf_get_shnames(elfHdr);
00366 if (shnames == NULL) {
00367
00368 log_elferror(err_func_, ".shstrtab section");
00369
00370 }
00371
00372
00373
00374 text_addr_ = 0;
00375 text_size_ = 0;
00376
00377
00378
00379 elf_hash_addr_ = 0;
00380 gnu_hash_addr_ = 0;
00381
00382 dynamic_offset_ = 0;
00383 dynamic_addr_ = 0;
00384 dynsym_addr_ = 0;
00385 dynsym_size_ = 0;
00386 dynstr_addr_ = 0;
00387 init_addr_ = 0;
00388 fini_addr_ = 0;
00389 got_addr_ = 0;
00390 got_size_ = 0;
00391 plt_addr_ = 0;
00392 plt_size_ = 0;
00393 symtab_addr_ = 0;
00394 strtab_addr_ = 0;
00395 #if defined (ppc32_linux) || defined(ppc32_bgp)
00396 plt_entry_size_ = 8;
00397 rel_plt_entry_size_ = 8;
00398 #else
00399 plt_entry_size_ = 0;
00400 rel_plt_entry_size_ = 0;
00401 #endif
00402 rel_plt_addr_ = 0;
00403 rel_plt_size_ = 0;
00404 rel_addr_ = 0;
00405 rel_size_ = 0;
00406 rel_entry_size_ = 0;
00407 stab_off_ = 0;
00408 stab_size_ = 0;
00409 stabstr_off_ = 0;
00410 stab_indx_off_ = 0;
00411 stab_indx_size_ = 0;
00412 stabstr_indx_off_ = 0;
00413 #if defined(os_irix)
00414 MIPS_stubs_addr_ = 0;
00415 MIPS_stubs_off_ = 0;
00416 MIPS_stubs_size_ = 0;
00417 got_zero_index_ = -1;
00418 dynsym_zero_index_ = -1;
00419 #endif
00420 dwarvenDebugInfo = false;
00421
00422 txtaddr = 0;
00423
00424 set<string> sectionsInOriginalBinary;
00425
00426 #if defined(TIMED_PARSE)
00427 struct timeval starttime;
00428 gettimeofday(&starttime, NULL);
00429 #endif
00430
00431
00432 bool foundInterp = false;
00433 unsigned phdr_max_count = elfHdr->e_phnum();
00434
00435 for (unsigned i = 0; i < phdr_max_count; i++) {
00436 Elf_X_Phdr &elfPhdr = elfHdr->get_phdr(i);
00437 if(elfPhdr.p_type() == PT_DYNAMIC){
00438 dynamic_offset_ = elfPhdr.p_offset();
00439 dynamic_size_ = elfPhdr.p_memsz();
00440 } else if (elfPhdr.p_type() == PT_INTERP) {
00441 foundInterp = true;
00442 }
00443 }
00444
00445 if (elfHdr->e_type() == ET_DYN || foundInterp || elfHdr->e_type() == ET_REL) {
00446 is_static_binary_ = false;
00447 } else {
00448 is_static_binary_ = true;
00449 }
00450
00451 bool foundDynamicSection = false;
00452 int dynamic_section_index = -1;
00453 unsigned int dynamic_section_type = 0;
00454 size_t dynamic_section_size = 0;
00455 for (int i = 0; i < elfHdr->e_shnum();++i) {
00456 Elf_X_Shdr &scn = elfHdr->get_shdr(i);
00457 if (! scn.isValid()) {
00458 continue;
00459 }
00460 if ((dynamic_offset_ !=0) && (scn.sh_offset() == dynamic_offset_)) {
00461 if (!foundDynamicSection) {
00462 dynamic_section_index = i;
00463 dynamic_section_size = scn.sh_size();
00464 dynamic_section_type = scn.sh_type();
00465 foundDynamicSection = true;
00466 } else {
00467
00468
00469 if (dynamic_section_size == dynamic_size_ && dynamic_section_type == SHT_DYNAMIC) {
00470
00471 } else if ((scn.sh_size() == dynamic_size_ && scn.sh_type() == SHT_DYNAMIC) ||
00472 (scn.sh_size() == dynamic_size_)) {
00473
00474
00475 dynamic_section_index = i;
00476 dynamic_section_size = scn.sh_size();
00477 dynamic_section_type = scn.sh_type();
00478 }
00479 }
00480 }
00481 }
00482
00483 if (dynamic_section_index != -1) {
00484 Elf_X_Shdr &scn = elfHdr->get_shdr(dynamic_section_index);
00485 Elf_X_Data data = scn.get_data();
00486 Elf_X_Dyn dynsecData = data.get_dyn();
00487
00488 if (dynsecData.isValid()) {
00489 for (unsigned j = 0; j < dynsecData.count(); ++j) {
00490 switch (dynsecData.d_tag(j)) {
00491 case DT_REL:
00492 hasReldyn_ = true;
00493 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00494 break;
00495 case DT_RELA:
00496 hasReladyn_ = true;
00497 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00498 break;
00499 case DT_JMPREL:
00500 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00501 break;
00502 case DT_SYMTAB:
00503 case DT_STRTAB:
00504 case DT_VERSYM:
00505 case DT_VERNEED:
00506 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00507 break;
00508 case DT_HASH:
00509 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00510 elf_hash_addr_ = dynsecData.d_ptr(j);
00511 break;
00512 case 0x6ffffef5:
00513 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00514 gnu_hash_addr_ = dynsecData.d_ptr(j);
00515 break;
00516 case DT_PLTGOT:
00517 secAddrTagMapping[dynsecData.d_ptr(j)] = dynsecData.d_tag(j);
00518 break;
00519 case DT_RELSZ:
00520 secTagSizeMapping[DT_REL] = dynsecData.d_val(j);
00521 break;
00522 case DT_RELASZ:
00523 secTagSizeMapping[DT_RELA] = dynsecData.d_val(j);
00524 break;
00525 case DT_PLTRELSZ:
00526 secTagSizeMapping[DT_JMPREL] = dynsecData.d_val(j);
00527 break;
00528 case DT_STRSZ:
00529 secTagSizeMapping[DT_STRTAB] = dynsecData.d_val(j);
00530 break;
00531 case DT_PLTREL:
00532 if (dynsecData.d_val(j) == DT_REL)
00533 hasRelplt_ = true;
00534 else if (dynsecData.d_val(j) == DT_RELA)
00535 hasRelaplt_ = true;
00536 break;
00537
00538 }
00539 }
00540 }
00541 dyn_hash_map<Offset, int>::iterator it = secAddrTagMapping.begin();
00542 while (it != secAddrTagMapping.end()) {
00543 int tag = it->second;
00544 switch (tag) {
00545
00546 case DT_REL:
00547 case DT_RELA:
00548 case DT_JMPREL:
00549 case DT_SYMTAB:
00550 case DT_STRTAB:
00551 case DT_VERSYM:
00552 case DT_VERNEED:
00553 case DT_HASH:
00554 case 0x6ffffef5:
00555
00556 if (secTagSizeMapping.find(tag) != secTagSizeMapping.end()) {
00557 vector<Offset> row;
00558 row.push_back(it->first);
00559 row.push_back(it->first+ secTagSizeMapping[tag]);
00560 moveSecAddrRange.push_back(row);
00561 } else {
00562 vector<Offset> row;
00563 row.push_back(it->first);
00564 row.push_back(it->first);
00565 moveSecAddrRange.push_back(row);
00566 }
00567 break;
00568 }
00569 it++;
00570 }
00571 }
00572
00573 isBlueGeneP_ = false;
00574 isBlueGeneQ_ = false;
00575
00576 hasNoteSection_ = false;
00577
00578 const char *shnamesForDebugInfo = NULL;
00579 unsigned int elfHdrDbg_numSections = 0;
00580 unsigned int elfHdr_numSections = elfHdr->e_shnum();
00581 Elf_X *elfHdrDbg = dwarf->debugLinkFile();
00582 if (elfHdrDbg) {
00583 shnamesForDebugInfo = pdelf_get_shnames(elfHdrDbg);
00584 if (shnamesForDebugInfo == NULL) {
00585 log_elferror(err_func_, ".shstrtab section");
00586 }
00587 elfHdrDbg_numSections = elfHdrDbg->e_shnum();
00588 }
00589
00590 for (unsigned int i = 0; i < elfHdr_numSections + elfHdrDbg_numSections; i++) {
00591 const char *name;
00592
00593 bool isFromDebugFile = (i >= elfHdr_numSections);
00594 Elf_X_Shdr &scn = (!isFromDebugFile) ? elfHdr->get_shdr(i) :
00595 elfHdrDbg->get_shdr(i - elfHdr_numSections);
00596 if (! scn.isValid()) {
00597 continue;
00598 }
00599 Elf_X_Shdr *scnp = &scn;
00600
00601 if (!isFromDebugFile) {
00602 name = &shnames[scn.sh_name()];
00603 sectionsInOriginalBinary.insert(string(name));
00604
00605 if(scn.sh_flags() & SHF_ALLOC) {
00606 DbgAddrConversion_t orig;
00607 orig.name = std::string(name);
00608 orig.orig_offset = scn.sh_addr();
00609 secnNameMap[orig.name] = DebugSectionMap.size();
00610 DebugSectionMap.push_back(orig);
00611 }
00612 }
00613 else {
00614 if (!shnamesForDebugInfo)
00615 break;
00616 name = &shnamesForDebugInfo[scn.sh_name()];
00617
00618 std::string sname(name);
00619 std::map<std::string, int>::iterator s = secnNameMap.find(sname);
00620 if (s != secnNameMap.end()) {
00621 int i = (*s).second;
00622 DebugSectionMap[i].dbg_offset = scn.sh_addr();
00623 DebugSectionMap[i].dbg_size = scn.sh_size();
00624 }
00625 scn.setDebugFile(true);
00626
00627 if (scn.sh_type() == SHT_NOBITS) {
00628 continue;
00629 }
00630 }
00631
00632 if(scn.sh_type() == SHT_NOTE) {
00633 hasNoteSection_ = true;
00634 }
00635
00636
00637
00638
00639
00640
00641 if (!scn.isFromDebugFile()) {
00642 allRegionHdrs.push_back(&scn);
00643 if(scn.sh_flags() & SHF_ALLOC) {
00644
00645 unsigned long diskSize = (scn.sh_type() == SHT_NOBITS) ? 0 : scn.sh_size();
00646 Region *reg = new Region(i, name, scn.sh_addr(), diskSize,
00647 scn.sh_addr(), scn.sh_size(),
00648 (mem_image()+scn.sh_offset()),
00649 getRegionPerms(scn.sh_flags()),
00650 getRegionType(scn.sh_type(),
00651 scn.sh_flags(),
00652 name),
00653 true, ((scn.sh_flags() & SHF_TLS) != 0),
00654 scn.sh_addralign());
00655 reg->setFileOffset(scn.sh_offset());
00656 regions_.push_back(reg);
00657 }
00658 else {
00659 Region *reg = new Region(i, name, scn.sh_addr(), scn.sh_size(), 0, 0,
00660 (mem_image()+scn.sh_offset()),
00661 getRegionPerms(scn.sh_flags()),
00662 getRegionType(scn.sh_type(),
00663 scn.sh_flags(),
00664 name),
00665 false, ((scn.sh_flags() & SHF_TLS) != 0),
00666 scn.sh_addralign());
00667
00668 reg->setFileOffset(scn.sh_offset());
00669 regions_.push_back(reg);
00670 }
00671 }
00672
00673
00674 if (P_strcmp(name, EDITED_TEXT_NAME) == 0) {
00675
00676 EEL = true;
00677 if (txtaddr == 0)
00678 txtaddr = scn.sh_addr();
00679 char *file_ptr = (char *)mf->base_addr();
00680 code_ptr_ = (char *)(void*)&file_ptr[scn.sh_offset() - EXTRA_SPACE];
00681 code_off_ = scn.sh_addr() - EXTRA_SPACE;
00682 code_len_ = scn.sh_size() + EXTRA_SPACE;
00683 }
00684
00685 if (strcmp(name, TEXT_NAME) == 0) {
00686 text_addr_ = scn.sh_addr();
00687 text_size_ = scn.sh_size();
00688
00689 if (txtaddr == 0)
00690 txtaddr = scn.sh_addr();
00691
00692
00693
00694 if( !elfHdr->e_phnum() && !code_len_) {
00695
00696 code_ptr_ = reinterpret_cast<char *>(scn.get_data().d_buf());
00697 code_off_ = scn.sh_offset();
00698 code_len_ = scn.sh_size();
00699 }
00700 }
00701
00702
00703 else if (strcmp(name, DATA_NAME) == 0) {
00704 dataddr = scn.sh_addr();
00705
00706
00707
00708 if( !elfHdr->e_phnum() && !data_len_) {
00709
00710 data_ptr_ = reinterpret_cast<char *>(scn.get_data().d_buf());
00711 data_off_ = scn.sh_offset();
00712 data_len_ = scn.sh_size();
00713 }
00714 }
00715 else if (strcmp(name, RO_DATA_NAME) == 0) {
00716 if (!dataddr) dataddr = scn.sh_addr();
00717 }
00718 else if (strcmp(name, GOT_NAME) == 0) {
00719 got_scnp = scnp;
00720 got_addr_ = scn.sh_addr();
00721 got_size_ = scn.sh_size();
00722 if (!dataddr) dataddr = scn.sh_addr();
00723 }
00724 else if (strcmp(name, BSS_NAME) == 0) {
00725 bssscnp = scnp;
00726 if (!dataddr) dataddr = scn.sh_addr();
00727 }
00728
00729
00730
00731
00732 else if (strcmp(name, SYMTAB_NAME) == 0) {
00733 if (!symscnp) {
00734 symscnp = scnp;
00735 symtab_addr_ = scn.sh_addr();
00736 }
00737 }
00738 else if (strcmp(name, STRTAB_NAME) == 0) {
00739 if (!strscnp) {
00740 strscnp = scnp;
00741 strtab_addr_ = scn.sh_addr();
00742 }
00743 } else if (strcmp(name, STAB_INDX_NAME) == 0) {
00744 stabs_indxcnp = scnp;
00745 stab_indx_off_ = scn.sh_offset();
00746 stab_indx_size_ = scn.sh_size();
00747 } else if (strcmp(name, STABSTR_INDX_NAME) == 0) {
00748 stabstrs_indxcnp = scnp;
00749 stabstr_indx_off_ = scn.sh_offset();
00750 } else if (strcmp(name, STAB_NAME) == 0) {
00751 stabscnp = scnp;
00752 stab_off_ = scn.sh_offset();
00753 stab_size_ = scn.sh_size();
00754 } else if (strcmp(name, STABSTR_NAME) == 0) {
00755 stabstrscnp = scnp;
00756 stabstr_off_ = scn.sh_offset();
00757 }
00758 #if defined(os_vxworks)
00759 else if ((strcmp(name, REL_PLT_NAME) == 0) ||
00760 (strcmp(name, REL_PLT_NAME2) == 0)) {
00761 rel_plt_scnp = scnp;
00762 rel_plt_addr_ = scn.sh_addr();
00763 rel_plt_size_ = scn.sh_size();
00764 rel_plt_entry_size_ = scn.sh_entsize();
00765 }
00766 #else
00767 else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) &&
00768 secAddrTagMapping[scn.sh_addr()] == DT_JMPREL ) {
00769 rel_plt_scnp = scnp;
00770 rel_plt_addr_ = scn.sh_addr();
00771 rel_plt_size_ = scn.sh_size();
00772 rel_plt_entry_size_ = scn.sh_entsize();
00773 }
00774 #endif
00775 else if (strcmp(name, OPD_NAME) == 0) {
00776 opd_scnp = scnp;
00777 opd_addr_ = scn.sh_addr();
00778 opd_size_ = scn.sh_size();
00779 }
00780 else if (strcmp(name, PLT_NAME) == 0) {
00781 plt_scnp = scnp;
00782 plt_addr_ = scn.sh_addr();
00783 plt_size_ = scn.sh_size();
00784 #if defined(arch_x86) || defined(arch_x86_64)
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 plt_entry_size_ = 16;
00818 assert( plt_entry_size_ == 16 );
00819 #else
00820 plt_entry_size_ = scn.sh_entsize();
00821
00822
00823
00824 #if defined(arch_x86_64)
00825 if (addressWidth_nbytes == 4) {
00826 plt_entry_size_ = 16;
00827 assert( plt_entry_size_ == 16 );
00828 }
00829 else {
00830 assert(addressWidth_nbytes == 8);
00831 }
00832 #endif
00833
00834
00835 #if defined (ppc32_linux) || defined(ppc32_bgp)
00836 if (scn.sh_flags() & SHF_EXECINSTR) {
00837
00838 if (!plt_entry_size_)
00839 plt_entry_size_ = 8;
00840 else {
00841 if (plt_entry_size_ != 8)
00842 fprintf(stderr, "%s[%d]: weird plt_entry_size_ is %d, not 8\n",
00843 FILE__, __LINE__, plt_entry_size_);
00844 }
00845
00846 } else {
00847
00848 plt_entry_size_ = 16;
00849 }
00850 #endif
00851 #endif
00852 } else if (strcmp(name, COMMENT_NAME) == 0) {
00853
00854
00855
00856
00857 Elf_X_Data data = scn.get_data();
00858
00859 unsigned int index = 0;
00860 size_t size = data.d_size();
00861 char *buf = (char *) data.d_buf();
00862 while (buf && (index < size))
00863 {
00864 string comment = buf+index;
00865 size_t pos_p = comment.find("BGP");
00866 size_t pos_q = comment.find("BGQ");
00867 if (pos_p !=string::npos) {
00868 isBlueGeneP_ = true;
00869 break;
00870 } else if (pos_q !=string::npos) {
00871 isBlueGeneQ_ = true;
00872 break;
00873 }
00874 index += comment.size();
00875 if (comment.size() == 0) {
00876 index ++;
00877 }
00878 }
00879 }
00880
00881 else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) &&
00882 secAddrTagMapping[scn.sh_addr()] == DT_SYMTAB ) {
00883 is_dynamic_ = true;
00884 dynsym_scnp = scnp;
00885 dynsym_addr_ = scn.sh_addr();
00886 dynsym_size_ = scn.sh_size()/scn.sh_entsize();
00887 }
00888 else if ((secAddrTagMapping.find(scn.sh_addr()) != secAddrTagMapping.end() ) &&
00889 secAddrTagMapping[scn.sh_addr()] == DT_STRTAB ) {
00890 dynstr_scnp = scnp;
00891 dynstr_addr_ = scn.sh_addr();
00892 }
00893 else if (strcmp(name, ".debug_info") == 0) {
00894 dwarvenDebugInfo = true;
00895 }
00896 else if (strcmp(name, EH_FRAME_NAME) == 0) {
00897 eh_frame = scnp;
00898 }
00899 else if ((strcmp(name, EXCEPT_NAME) == 0) ||
00900 (strcmp(name, EXCEPT_NAME_ALT) == 0)) {
00901 gcc_except = scnp;
00902 }
00903 else if (strcmp(name, INTERP_NAME) == 0) {
00904 interp_scnp = scnp;
00905 }
00906 else if ((int) i == dynamic_section_index) {
00907 dynamic_scnp = scnp;
00908 dynamic_addr_ = scn.sh_addr();
00909 }
00910 }
00911
00912 if(!symscnp || !strscnp) {
00913 isStripped = true;
00914 if(dynsym_scnp && dynstr_scnp){
00915 symscnp = dynsym_scnp;
00916 strscnp = dynstr_scnp;
00917 }
00918 }
00919
00920 loadAddress_ = 0x0;
00921 #if defined(os_linux) || defined(os_freebsd)
00922
00923
00924
00925
00926
00927
00928 for (unsigned i = 0; i < elfHdr->e_phnum() && !loadAddress_; ++i) {
00929 Elf_X_Phdr &phdr = elfHdr->get_phdr(i);
00930
00931 if (phdr.p_type() == PT_LOAD) {
00932 loadAddress_ = phdr.p_vaddr();
00933 break;
00934 }
00935 }
00936 #endif
00937
00938
00939 allRegionHdrsByShndx = allRegionHdrs;
00940
00941
00942 sort(allRegionHdrs.begin(), allRegionHdrs.end(), SectionHeaderSortFunction());
00943
00944 for (unsigned j = 0 ; j < regions_.size() ; j++) {
00945 if (secAddrTagMapping.find(regions_[j]->getDiskOffset()) != secAddrTagMapping.end()) {
00946 secTagRegionMapping[secAddrTagMapping[regions_[j]->getDiskOffset()]] = regions_[j];
00947 }
00948 }
00949
00950 #if defined(TIMED_PARSE)
00951 struct timeval endtime;
00952 gettimeofday(&endtime, NULL);
00953 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
00954 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
00955 unsigned long difftime = lendtime - lstarttime;
00956 double dursecs = difftime/(1000 );
00957 cout << "main loop of loaded elf took "<<dursecs <<" msecs" << endl;
00958 #endif
00959
00960 if (!dataddr || !symscnp || !strscnp) {
00961
00962 }
00963
00964 return true;
00965 }
00966
00967 bool Object::is_offset_in_plt(Offset offset) const
00968 {
00969 return (offset > plt_addr_ && offset < plt_addr_ + plt_size_);
00970 }
00971
00972 void Object::parseDynamic(Elf_X_Shdr *&dyn_scnp, Elf_X_Shdr *&dynsym_scnp,
00973 Elf_X_Shdr *&dynstr_scnp)
00974 {
00975 Elf_X_Data data = dyn_scnp->get_data();
00976 Elf_X_Dyn dyns = data.get_dyn();
00977 int rel_scnp_index = -1;
00978
00979 for (unsigned i = 0; i < dyns.count(); ++i) {
00980 switch(dyns.d_tag(i)) {
00981 case DT_REL:
00982 case DT_RELA:
00983
00984 rel_addr_ = (Offset) dyns.d_ptr(i);
00985 rel_scnp_index = getRegionHdrIndexByAddr(dyns.d_ptr(i));
00986 break;
00987 case DT_JMPREL:
00988 rel_plt_addr_ = (Offset) dyns.d_ptr(i);
00989 break;
00990 case DT_PLTRELSZ:
00991 rel_plt_size_ = dyns.d_val(i) ;
00992 break;
00993 case DT_RELSZ:
00994 case DT_RELASZ:
00995 rel_size_ = dyns.d_val(i) ;
00996 break;
00997 case DT_RELENT:
00998 case DT_RELAENT:
00999 rel_entry_size_ = dyns.d_val(i);
01000
01001
01002 break;
01003 case DT_INIT:
01004 init_addr_ = dyns.d_val(i);
01005 break;
01006 case DT_FINI:
01007 fini_addr_ = dyns.d_val(i);
01008 break;
01009 default:
01010 break;
01011 }
01012 }
01013 if (rel_scnp_index != -1)
01014 get_relocationDyn_entries(rel_scnp_index, dynsym_scnp, dynstr_scnp);
01015 }
01016
01017
01018
01019
01020 bool Object::get_relocationDyn_entries( unsigned rel_scnp_index,
01021 Elf_X_Shdr *&dynsym_scnp,
01022 Elf_X_Shdr *&dynstr_scnp )
01023 {
01024 Elf_X_Data symdata = dynsym_scnp->get_data();
01025 Elf_X_Data strdata = dynstr_scnp->get_data();
01026 Elf_X_Shdr* rel_scnp = NULL;
01027 if( !symdata.isValid() || !strdata.isValid())
01028 return false;
01029 const char *strs = strdata.get_string();
01030 Elf_X_Sym sym = symdata.get_sym();
01031
01032 unsigned num_rel_entries_found = 0;
01033 unsigned num_rel_entries = rel_size_/rel_entry_size_;
01034
01035 if (rel_addr_ + rel_size_ > rel_plt_addr_){
01036
01037 num_rel_entries = (rel_plt_addr_-rel_addr_)/rel_entry_size_;
01038 }
01039 while (num_rel_entries_found != num_rel_entries) {
01040 rel_scnp = getRegionHdrByIndex(rel_scnp_index++);
01041 Elf_X_Data reldata = rel_scnp->get_data();
01042
01043 if( ! reldata.isValid()) return false;
01044 Elf_X_Rel rel = reldata.get_rel();
01045 Elf_X_Rela rela = reldata.get_rela();
01046
01047 if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
01048
01049 for( u_int i = 0; i < (reldata.d_size()/rel_entry_size_); ++i ) {
01050 num_rel_entries_found++;
01051 long offset;
01052 long addend;
01053 long index;
01054 unsigned long type;
01055 Region::RegionType rtype = Region::RT_REL;
01056
01057 switch (reldata.d_type()) {
01058 case ELF_T_REL:
01059 offset = rel.r_offset(i);
01060 addend = 0;
01061 index = rel.R_SYM(i);
01062 type = rel.R_TYPE(i);
01063 break;
01064
01065 case ELF_T_RELA:
01066 offset = rela.r_offset(i);
01067 addend = rela.r_addend(i);
01068 index = rela.R_SYM(i);
01069 type = rela.R_TYPE(i);
01070 rtype = Region::RT_RELA;
01071 break;
01072
01073 default:
01074
01075 return false;
01076 };
01077
01078 relocationEntry re( offset, string( &strs[ sym.st_name(index) ] ), NULL, type );
01079 re.setAddend(addend);
01080 re.setRegionType(rtype);
01081 if(symbols_.find(&strs[ sym.st_name(index)]) != symbols_.end()){
01082 vector<Symbol *> &syms = symbols_[&strs[ sym.st_name(index)]];
01083 for (vector<Symbol *>::iterator i = syms.begin(); i != syms.end(); i++) {
01084 if (!(*i)->isInDynSymtab())
01085 continue;
01086 re.addDynSym(*i);
01087 break;
01088 }
01089 }
01090
01091 relocation_table_.push_back(re);
01092 }
01093 } else {
01094 return false;
01095 }
01096
01097 }
01098 return true;
01099 }
01100
01101 bool Object::get_relocation_entries( Elf_X_Shdr *&rel_plt_scnp,
01102 Elf_X_Shdr *&dynsym_scnp,
01103 Elf_X_Shdr *&dynstr_scnp )
01104 {
01105 if (rel_plt_size_ && rel_plt_addr_) {
01106 Elf_X_Data reldata = rel_plt_scnp->get_data();
01107 Elf_X_Data symdata = dynsym_scnp->get_data();
01108 Elf_X_Data strdata = dynstr_scnp->get_data();
01109
01110 if( reldata.isValid() && symdata.isValid() && strdata.isValid() ) {
01111 Offset next_plt_entry_addr = plt_addr_;
01112
01113 #if defined(arch_x86) || defined(arch_x86_64)
01114 next_plt_entry_addr += plt_entry_size_;
01115
01116 #elif defined (ppc32_linux) || defined(ppc32_bgp)
01117 bool extraStubs = false;
01118
01119
01120 if (!plt_entry_size_) {
01121 fprintf(stderr, "%s[%d]: FIXME: plt_entry_size not established\n", FILE__, __LINE__);
01122 plt_entry_size_ = 8;
01123 }
01124
01125 if (plt_entry_size_ == 8) {
01126
01127 next_plt_entry_addr += 9*plt_entry_size_;
01128
01129 } else if (plt_entry_size_ == 16) {
01130
01131 Region *plt = NULL, *relplt = NULL, *dynamic = NULL,
01132 *got = NULL, *glink = NULL;
01133 unsigned int glink_addr = 0;
01134 unsigned int stub_addr = 0;
01135
01136
01137
01138
01139 for (unsigned iter = 0; iter < regions_.size(); ++iter) {
01140 std::string name = regions_[iter]->getRegionName();
01141 if (name == PLT_NAME) plt = regions_[iter];
01142 else if (name == REL_PLT_NAME) relplt = regions_[iter];
01143 else if (name == DYNAMIC_NAME) dynamic = regions_[iter];
01144 else if (name == GOT_NAME) got = regions_[iter];
01145 }
01146
01147
01148 if (dynamic != NULL) {
01149 Elf32_Dyn *dyn = (Elf32_Dyn *)dynamic->getPtrToRawData();
01150 unsigned int count = dynamic->getMemSize() / sizeof(Elf32_Dyn);
01151
01152 for (unsigned int i = 0; i < count; ++i) {
01153
01154
01155
01156 if (dyn[i].d_tag == DT_LOPROC) {
01157 unsigned int g_o_t = dyn[i].d_un.d_val;
01158 if (got != NULL) {
01159 unsigned char *data =
01160 (unsigned char *)got->getPtrToRawData();
01161 glink_addr = *(unsigned int *)
01162 (data + (g_o_t - got->getMemOffset() + 4));
01163 break;
01164 }
01165 }
01166 }
01167 }
01168
01169
01170 if (glink_addr == 0) {
01171 unsigned char *data = (unsigned char *)plt->getPtrToRawData();
01172 glink_addr = *(unsigned int *)(data);
01173 }
01174
01175
01176 for (unsigned iter = 0; iter < regions_.size(); ++iter) {
01177 unsigned int start = regions_[iter]->getMemOffset();
01178 unsigned int end = start + regions_[iter]->getMemSize();
01179 if (start <= glink_addr && glink_addr < end) {
01180 glink = regions_[iter];
01181 break;
01182 }
01183 }
01184
01185 if (!glink) {
01186
01187
01188
01189 return false;
01190 }
01191
01192
01193 stub_addr = glink_addr - (rel_plt_size_/rel_plt_entry_size_) * 16;
01194
01195 const unsigned int LWZ_11_30 = 0x817e0000;
01196 const unsigned int ADDIS_11_30 = 0x3d7e0000;
01197 const unsigned int LWZ_11_11 = 0x816b0000;
01198 const unsigned int MTCTR_11 = 0x7d6903a6;
01199 const unsigned int BCTR = 0x4e800420;
01200
01201 unsigned char *sec_data = (unsigned char *)glink->getPtrToRawData();
01202 unsigned int *insn = (unsigned int *)
01203 (sec_data + (stub_addr - glink->getMemOffset()));
01204
01205
01206 while (sec_data < (unsigned char *)insn) {
01207 unsigned int *back = insn - 4;
01208
01209 if (( (back[0] & 0xffff0000) == LWZ_11_30
01210 && back[1] == MTCTR_11
01211 && back[2] == BCTR)
01212
01213 || ( (back[0] & 0xffff0000) == ADDIS_11_30
01214 && (back[1] & 0xffff0000) == LWZ_11_11
01215 && back[2] == MTCTR_11
01216 && back[3] == BCTR))
01217 {
01218 extraStubs = true;
01219 stub_addr -= 16;
01220 insn = back;
01221 } else {
01222 break;
01223 }
01224 }
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 if (extraStubs == true) {
01244 std::string name;
01245 relocationEntry re;
01246
01247 while (stub_addr < glink_addr) {
01248 if (symsByOffset_.find(stub_addr) != symsByOffset_.end()) {
01249 name = (symsByOffset_[stub_addr])[0]->getMangledName();
01250 name = name.substr( name.rfind("plt_pic32.") + 10 );
01251 }
01252
01253 if (!name.empty()) {
01254 re = relocationEntry( stub_addr, 0, name, NULL, 0 );
01255 } else {
01256 re = relocationEntry( stub_addr, 0, "@plt", NULL, 0 );
01257 }
01258 fbt_.push_back(re);
01259 stub_addr += 16;
01260 }
01261
01262
01263 next_plt_entry_addr = plt_addr_;
01264 plt_entry_size_ = 4;
01265
01266 } else {
01267 next_plt_entry_addr = stub_addr;
01268 }
01269
01270 } else {
01271 fprintf(stderr, "ERROR: Can't handle %d PLT entry size\n",
01272 plt_entry_size_);
01273 return false;
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 #elif defined(arch_power) && defined(arch_64bit) && defined(os_linux)
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 dyn_hash_map<std::string, Offset> plt_rel_map;
01305
01306
01307
01308 Elf_X_Sym _sym = symdata.get_sym();
01309 Elf_X_Rel _rel = reldata.get_rel();
01310 Elf_X_Rela _rela = reldata.get_rela();
01311 const char *_strs = strdata.get_string();
01312
01313 for( u_int i = 0; i < (rel_plt_size_/rel_plt_entry_size_); ++i ) {
01314 long _offset;
01315 long _index;
01316
01317 switch (reldata.d_type()) {
01318 case ELF_T_REL:
01319 _offset = _rel.r_offset(i);
01320 _index = _rel.R_SYM(i);
01321 break;
01322
01323 case ELF_T_RELA:
01324 _offset = _rela.r_offset(i);
01325 _index = _rela.R_SYM(i);
01326 break;
01327
01328 default:
01329
01330 return false;
01331 };
01332
01333 std::string _name = &_strs[ _sym.st_name(_index) ];
01334
01335 assert(_name.length());
01336
01337 plt_rel_map[_name] = _offset;
01338 }
01339
01340
01341 dyn_hash_map<std::string, std::vector<Symbol *> >::iterator iter;
01342 for (iter = symbols_.begin(); iter != symbols_.end(); ++iter) {
01343 std::string name = iter->first;
01344 if (name.length() > 8) {
01345 if (name.substr(8, 10) == ".plt_call.")
01346 name = name.substr(8 + 10);
01347 else if (name.substr(8, 12) == ".plt_branch.")
01348 name = name.substr(8 + 12);
01349 else if (name.substr(8, 13) == ".long_branch.")
01350 name = name.substr(8 + 13);
01351 else if (name.substr(8, 18) == ".plt_branch_r2off.")
01352 name = name.substr(8 + 18);
01353 else if (name.substr(8, 19) == ".long_branch_r2off.")
01354 name = name.substr(8 + 19);
01355 else
01356 continue;
01357
01358
01359 std::string::size_type pos = name.rfind('+');
01360 if (pos != std::string::npos) name.erase(pos);
01361
01362
01363 pos = name.find('@');
01364 if (pos != std::string::npos) name.erase(pos);
01365
01366
01367 Symbol *targ_sym = NULL;
01368 if (symbols_.find(name) != symbols_.end())
01369 for (unsigned i = 0; i < symbols_[name].size(); ++i)
01370 if ( (symbols_[name])[i]->isInDynSymtab())
01371 targ_sym = (symbols_[name])[i];
01372
01373
01374
01375
01376 if (!targ_sym) continue;
01377
01378
01379 assert(iter->second.size() == 1);
01380 assert(plt_rel_map.count(name) == 1);
01381
01382 Symbol *stub_sym = iter->second[0];
01383 relocationEntry re(stub_sym->getOffset(),
01384 plt_rel_map[name],
01385 name,
01386 targ_sym);
01387 fbt_.push_back(re);
01388 }
01389 }
01390
01391
01392 next_plt_entry_addr += plt_entry_size_;
01393
01394 #else
01395 next_plt_entry_addr += 4*(plt_entry_size_);
01396 #endif
01397
01398 Elf_X_Sym sym = symdata.get_sym();
01399 Elf_X_Rel rel = reldata.get_rel();
01400 Elf_X_Rela rela = reldata.get_rela();
01401 const char *strs = strdata.get_string();
01402
01403 if (sym.isValid() && (rel.isValid() || rela.isValid()) && strs) {
01404
01405
01406
01407 int fbt_iter = -1;
01408 if (fbt_.size() > 0 && !fbt_[0].rel_addr() && fbt_[0].name() != "@plt")
01409 fbt_iter = 0;
01410
01411 for( u_int i = 0; i < (rel_plt_size_/rel_plt_entry_size_); ++i ) {
01412 long offset;
01413 long addend;
01414 long index;
01415 unsigned long type;
01416 Region::RegionType rtype;
01417
01418 switch (reldata.d_type()) {
01419 case ELF_T_REL:
01420 offset = rel.r_offset(i);
01421 addend = 0;
01422 index = rel.R_SYM(i);
01423 type = rel.R_TYPE(i);
01424 rtype = Region::RT_REL;
01425 break;
01426
01427 case ELF_T_RELA:
01428 offset = rela.r_offset(i);
01429 addend = rela.r_addend(i);
01430 index = rela.R_SYM(i);
01431 type = rela.R_TYPE(i);
01432 rtype = Region::RT_RELA;
01433 break;
01434
01435 default:
01436
01437 return false;
01438 };
01439
01440 std::string targ_name = &strs[ sym.st_name(index) ];
01441 vector<Symbol *> dynsym_list;
01442 if (symbols_.find(targ_name) != symbols_.end())
01443 {
01444 vector<Symbol *> &syms = symbols_[&strs[ sym.st_name(index)]];
01445 for (vector<Symbol *>::iterator i = syms.begin(); i != syms.end(); i++) {
01446 if (!(*i)->isInDynSymtab())
01447 continue;
01448 dynsym_list.push_back(*i);
01449 }
01450 }
01451 else {
01452 dynsym_list.clear();
01453 }
01454
01455 #if defined(os_vxworks)
01456
01457
01458
01459 next_plt_entry_addr = sym.st_value(index);
01460 #endif
01461
01462 if (fbt_iter == -1) {
01463 relocationEntry re( next_plt_entry_addr, offset, targ_name,
01464 NULL, type );
01465 re.setAddend(addend);
01466 re.setRegionType(rtype);
01467 if (dynsym_list.size() > 0)
01468 re.addDynSym(dynsym_list[0]);
01469 fbt_.push_back(re);
01470
01471 } else {
01472 while ((unsigned)fbt_iter < fbt_.size() &&
01473 fbt_[fbt_iter].name() == targ_name) {
01474
01475 fbt_[fbt_iter].setRelAddr(offset);
01476 fbt_[fbt_iter].setAddend(addend);
01477 fbt_[fbt_iter].setRegionType(rtype);
01478 if (dynsym_list.size() > 0)
01479 fbt_[fbt_iter].addDynSym(dynsym_list[0]);
01480
01481 ++fbt_iter;
01482 }
01483 }
01484
01485 #if defined(os_vxworks)
01486
01487 #else
01488 next_plt_entry_addr += plt_entry_size_;
01489 #endif
01490 }
01491 return true;
01492 }
01493 }
01494 }
01495 return false;
01496 }
01497
01498 void Object::load_object(bool alloc_syms)
01499 {
01500 Elf_X_Shdr *bssscnp = 0;
01501 Elf_X_Shdr *symscnp = 0;
01502 Elf_X_Shdr *strscnp = 0;
01503 Elf_X_Shdr *stabscnp = 0;
01504 Elf_X_Shdr *stabstrscnp = 0;
01505 Elf_X_Shdr *stabs_indxcnp = 0;
01506 Elf_X_Shdr *stabstrs_indxcnp = 0;
01507 Offset txtaddr = 0;
01508 Offset dataddr = 0;
01509 Elf_X_Shdr *rel_plt_scnp = 0;
01510 Elf_X_Shdr *plt_scnp = 0;
01511 Elf_X_Shdr *got_scnp = 0;
01512 Elf_X_Shdr *dynsym_scnp = 0;
01513 Elf_X_Shdr *dynstr_scnp = 0;
01514 Elf_X_Shdr *dynamic_scnp = 0;
01515 Elf_X_Shdr *eh_frame_scnp = 0;
01516 Elf_X_Shdr *gcc_except = 0;
01517 Elf_X_Shdr *interp_scnp = 0;
01518 Elf_X_Shdr *opd_scnp = NULL;
01519
01520 {
01521
01522
01523 code_ptr_ = 0;
01524 code_off_ = 0;
01525 code_len_ = 0;
01526 data_ptr_ = 0;
01527 data_off_ = 0;
01528 data_len_ = 0;
01529
01530
01531 code_vldS_ = (Offset) -1;
01532 code_vldE_ = 0;
01533 data_vldS_ = (Offset) -1;
01534 data_vldE_ = 0;
01535
01536
01537
01538
01539 if (!loaded_elf(txtaddr, dataddr, bssscnp, symscnp, strscnp,
01540 stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
01541 rel_plt_scnp, plt_scnp, got_scnp, dynsym_scnp, dynstr_scnp,
01542 dynamic_scnp, eh_frame_scnp,gcc_except, interp_scnp,
01543 opd_scnp, true))
01544 {
01545 goto cleanup;
01546 }
01547
01548 addressWidth_nbytes = elfHdr->wordSize();
01549
01550
01551 find_code_and_data(*elfHdr, txtaddr, dataddr);
01552
01553 if (elfHdr->e_type() != ET_REL)
01554 {
01555 if (!code_ptr_ || !code_len_)
01556 {
01557
01558 goto cleanup;
01559 }
01560
01561 if (!data_ptr_ || !data_len_)
01562 {
01563
01564 goto cleanup;
01565 }
01566 }
01567 get_valid_memory_areas(*elfHdr);
01568
01569
01570
01571 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
01572 if (eh_frame_scnp != 0 && gcc_except != 0)
01573 {
01574 find_catch_blocks(eh_frame_scnp, gcc_except,
01575 txtaddr, dataddr, catch_addrs_);
01576 }
01577 #endif
01578 if (interp_scnp) {
01579 interpreter_name_ = (char *) interp_scnp->get_data().d_buf();
01580 }
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591 #if defined(TIMED_PARSE)
01592 struct timeval starttime;
01593 gettimeofday(&starttime, NULL);
01594 #endif
01595 if (alloc_syms)
01596 {
01597
01598 #if defined(os_vxworks)
01599
01600 string module = mf->pathname();
01601 #else
01602 string module = "DEFAULT_MODULE";
01603 #endif
01604 string name = "DEFAULT_NAME";
01605 Elf_X_Data symdata, strdata;
01606
01607 if (symscnp && strscnp)
01608 {
01609 symdata = symscnp->get_data();
01610 strdata = strscnp->get_data();
01611 parse_symbols(symdata, strdata, bssscnp, symscnp, false, module);
01612 }
01613
01614 no_of_symbols_ = nsymbols();
01615
01616
01617
01618 fix_global_symbol_modules_static_stab(stabs_indxcnp, stabstrs_indxcnp);
01619
01620
01621 fix_global_symbol_modules_static_stab(stabscnp, stabstrscnp);
01622
01623
01624 fix_global_symbol_modules_static_dwarf();
01625
01626 if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
01627 {
01628 symdata = dynsym_scnp->get_data();
01629 strdata = dynstr_scnp->get_data();
01630 parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
01631 }
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 #if defined(TIMED_PARSE)
01644 struct timeval endtime;
01645 gettimeofday(&endtime, NULL);
01646 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
01647 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
01648 unsigned long difftime = lendtime - lstarttime;
01649 double dursecs = difftime/(1000);
01650 cout << "parsing/fixing/overriding elf took "<<dursecs <<" msecs" << endl;
01651 #endif
01652
01653 if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
01654 {
01655 parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
01656 }
01657
01658 #if defined(os_vxworks)
01659
01660
01661 if (rel_plt_scnp && symscnp && strscnp) {
01662 if (!get_relocation_entries(rel_plt_scnp, symscnp, strscnp))
01663 goto cleanup;
01664 }
01665 #endif
01666
01667
01668 if (rel_plt_scnp && dynsym_scnp && dynstr_scnp)
01669 {
01670 if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp))
01671 {
01672 goto cleanup;
01673 }
01674 }
01675 parse_all_relocations(*elfHdr, dynsym_scnp, dynstr_scnp,
01676 symscnp, strscnp);
01677
01678 handle_opd_relocations();
01679 }
01680
01681
01682 int e_type = elfHdr->e_type();
01683
01684 if (e_type == ET_DYN) {
01685 obj_type_ = obj_SharedLib;
01686 }else if (e_type == ET_EXEC) {
01687 obj_type_ = obj_Executable;
01688 }else if (e_type == ET_REL) {
01689 obj_type_ = obj_RelocatableFile;
01690 }
01691
01692
01693 relType_ = getRelTypeByElfMachine(elfHdr);
01694
01695 if (opd_scnp) {
01696 parse_opd(opd_scnp);
01697 }
01698
01699 return;
01700 }
01701
01702 cleanup:
01703 {
01704
01705
01706
01707 fprintf(stderr, "%s[%d]: failed to load elf object\n", FILE__, __LINE__);
01708 }
01709 }
01710
01711 void Object::load_shared_object(bool alloc_syms)
01712 {
01713 Elf_X_Shdr *bssscnp = 0;
01714 Elf_X_Shdr *symscnp = 0;
01715 Elf_X_Shdr *strscnp = 0;
01716 Elf_X_Shdr *stabscnp = 0;
01717 Elf_X_Shdr *stabstrscnp = 0;
01718 Elf_X_Shdr *stabs_indxcnp = 0;
01719 Elf_X_Shdr *stabstrs_indxcnp = 0;
01720 Offset txtaddr = 0;
01721 Offset dataddr = 0;
01722 Elf_X_Shdr *rel_plt_scnp = 0;
01723 Elf_X_Shdr *plt_scnp = 0;
01724 Elf_X_Shdr *got_scnp = 0;
01725 Elf_X_Shdr *dynsym_scnp = 0;
01726 Elf_X_Shdr *dynstr_scnp = 0;
01727 Elf_X_Shdr *dynamic_scnp = 0;
01728 Elf_X_Shdr *eh_frame_scnp = 0;
01729 Elf_X_Shdr *gcc_except = 0;
01730 Elf_X_Shdr *interp_scnp = 0;
01731 Elf_X_Shdr *opd_scnp = NULL;
01732
01733 {
01734
01735
01736 code_vldS_ = (Offset) -1;
01737 code_vldE_ = 0;
01738 data_vldS_ = (Offset) -1;
01739 data_vldE_ = 0;
01740
01741 if (!loaded_elf(txtaddr, dataddr, bssscnp, symscnp, strscnp,
01742 stabscnp, stabstrscnp, stabs_indxcnp, stabstrs_indxcnp,
01743 rel_plt_scnp, plt_scnp, got_scnp, dynsym_scnp, dynstr_scnp,
01744 dynamic_scnp, eh_frame_scnp, gcc_except, interp_scnp, opd_scnp))
01745 goto cleanup2;
01746
01747 if (interp_scnp)
01748 interpreter_name_ = (char *) interp_scnp->get_data().d_buf();
01749
01750 addressWidth_nbytes = elfHdr->wordSize();
01751
01752
01753 find_code_and_data(*elfHdr, txtaddr, dataddr);
01754
01755 get_valid_memory_areas(*elfHdr);
01756
01757 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
01758
01759 if (eh_frame_scnp != 0 && gcc_except != 0) {
01760 find_catch_blocks(eh_frame_scnp, gcc_except,
01761 txtaddr, dataddr, catch_addrs_);
01762 }
01763 #endif
01764
01765 #if defined(TIMED_PARSE)
01766 struct timeval starttime;
01767 gettimeofday(&starttime, NULL);
01768 #endif
01769
01770 if (alloc_syms) {
01771
01772 string module = mf->pathname();
01773 string name = "DEFAULT_NAME";
01774
01775 Elf_X_Data symdata, strdata;
01776 if (symscnp && strscnp)
01777 {
01778 symdata = symscnp->get_data();
01779 strdata = strscnp->get_data();
01780 if (!symdata.isValid() || !strdata.isValid()) {
01781 log_elferror(err_func_, "locating symbol/string data");
01782 goto cleanup2;
01783 }
01784 bool result = parse_symbols(symdata, strdata, bssscnp, symscnp, false, module);
01785 if (!result) {
01786 log_elferror(err_func_, "locating symbol/string data");
01787 goto cleanup2;
01788 }
01789 }
01790
01791 no_of_symbols_ = nsymbols();
01792
01793 if (dynamic_addr_ && dynsym_scnp && dynstr_scnp)
01794 {
01795 symdata = dynsym_scnp->get_data();
01796 strdata = dynstr_scnp->get_data();
01797 parse_dynamicSymbols(dynamic_scnp, symdata, strdata, false, module);
01798 }
01799
01800 #if defined(TIMED_PARSE)
01801 struct timeval endtime;
01802 gettimeofday(&endtime, NULL);
01803 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
01804 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
01805 unsigned long difftime = lendtime - lstarttime;
01806 double dursecs = difftime/(1000 * 1000);
01807 cout << "*INSERT SYMBOLS* elf took "<<dursecs <<" msecs" << endl;
01808
01809 #endif
01810 if(dynamic_addr_ && dynsym_scnp && dynstr_scnp) {
01811 parseDynamic(dynamic_scnp, dynsym_scnp, dynstr_scnp);
01812 }
01813
01814 #if defined(os_vxworks)
01815
01816
01817 if (rel_plt_scnp && symscnp && strscnp) {
01818 if (!get_relocation_entries(rel_plt_scnp, symscnp, strscnp))
01819 goto cleanup2;
01820 }
01821 #endif
01822
01823 if (rel_plt_scnp && dynsym_scnp && dynstr_scnp) {
01824 if (!get_relocation_entries(rel_plt_scnp,dynsym_scnp,dynstr_scnp)) {
01825 goto cleanup2;
01826 }
01827 }
01828
01829 parse_all_relocations(*elfHdr, dynsym_scnp, dynstr_scnp,
01830 symscnp, strscnp);
01831
01832 handle_opd_relocations();
01833 }
01834
01835
01836 int e_type = elfHdr->e_type();
01837 if (e_type == ET_DYN) {
01838 obj_type_ = obj_SharedLib;
01839 }
01840 else if (e_type == ET_EXEC) {
01841 obj_type_ = obj_Executable;
01842 }else if( e_type == ET_REL ) {
01843 obj_type_ = obj_RelocatableFile;
01844 }
01845
01846
01847 if (opd_scnp) {
01848 parse_opd(opd_scnp);
01849 }
01850
01851
01852 relType_ = getRelTypeByElfMachine(elfHdr);
01853
01854 }
01855
01856 cleanup2:
01857 {
01858 }
01859 }
01860
01861 static Symbol::SymbolType pdelf_type(int elf_type)
01862 {
01863 switch (elf_type) {
01864 case STT_FILE: return Symbol::ST_MODULE;
01865 case STT_SECTION:return Symbol::ST_SECTION;
01866 case STT_OBJECT: return Symbol::ST_OBJECT;
01867 case STT_TLS: return Symbol::ST_TLS;
01868 case STT_FUNC: return Symbol::ST_FUNCTION;
01869 case STT_NOTYPE: return Symbol::ST_NOTYPE;
01870 #if defined(STT_GNU_IFUNC)
01871 case STT_GNU_IFUNC: return Symbol::ST_INDIRECT;
01872 #endif
01873 default: return Symbol::ST_UNKNOWN;
01874 }
01875 }
01876
01877 static Symbol::SymbolLinkage pdelf_linkage(int elf_binding)
01878 {
01879 switch (elf_binding) {
01880 case STB_LOCAL: return Symbol::SL_LOCAL;
01881 case STB_WEAK: return Symbol::SL_WEAK;
01882 case STB_GLOBAL: return Symbol::SL_GLOBAL;
01883 }
01884 return Symbol::SL_UNKNOWN;
01885 }
01886
01887 static Symbol::SymbolVisibility pdelf_visibility(int elf_visibility)
01888 {
01889 switch (elf_visibility) {
01890 case STV_DEFAULT: return Symbol::SV_DEFAULT;
01891 case STV_INTERNAL: return Symbol::SV_INTERNAL;
01892 case STV_HIDDEN: return Symbol::SV_HIDDEN;
01893 case STV_PROTECTED: return Symbol::SV_PROTECTED;
01894 }
01895 return Symbol::SV_UNKNOWN;
01896 }
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907 bool lookUpSymbol( std::vector< Symbol *>& allsymbols, Offset& addr )
01908 {
01909 for( unsigned i = 0; i < allsymbols.size(); i++ )
01910 {
01911 if( allsymbols[ i ]->getOffset() == addr )
01912 {
01913 return true;
01914 }
01915 }
01916 return false;
01917 }
01918
01919 bool lookUpAddress( std::vector< Offset >& jumpTargets, Offset& addr )
01920 {
01921 for( unsigned i = 0; i < jumpTargets.size(); i++ )
01922 {
01923 if( jumpTargets[ i ] == addr )
01924 {
01925 return true;
01926 }
01927 }
01928 return false;
01929 }
01930
01931
01932 void printSyms( std::vector< Symbol *>& allsymbols )
01933 {
01934 for( unsigned i = 0; i < allsymbols.size(); i++ )
01935 {
01936 if( allsymbols[ i ]->getType() != Symbol::ST_FUNCTION )
01937 {
01938 continue;
01939 }
01940 cout << allsymbols[ i ] << endl;
01941 }
01942 }
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962 void Object::parse_opd(Elf_X_Shdr *opd_hdr) {
01963
01964 assert(opd_hdr);
01965
01966 Elf_X_Data data = opd_hdr->get_data();
01967 assert(data.isValid());
01968
01969
01970 unsigned long *buf = (unsigned long *)data.d_buf();
01971
01972
01973
01974
01975
01976
01977
01978
01979 Offset baseTOC = buf[1];
01980 TOC_table_[0] = baseTOC;
01981
01982
01983
01984 unsigned i = 0;
01985 while (i < (data.d_size() / sizeof(unsigned long))) {
01986 Offset func = buf[i];
01987 Offset toc = buf[i+1];
01988
01989 if (func == 0 && i != 0) break;
01990
01991 if (symsByOffset_.find(func) == symsByOffset_.end()) {
01992 i++;
01993 continue;
01994 }
01995
01996 if (toc != baseTOC) {
01997 TOC_table_[func] = toc;
01998 }
01999 i += 2;
02000 }
02001 }
02002
02003 void Object::handle_opd_relocations(){
02004
02005 unsigned int i = 0, opdregion = 0;
02006 while (i < regions_.size()) {
02007 if(regions_[i]->getRegionName().compare(".opd") == 0){
02008 opdregion = i;
02009 break;
02010 }
02011 i++;
02012 }
02013
02014 vector<relocationEntry> region_rels = (regions_[opdregion])->getRelocations();
02015 vector<relocationEntry>::iterator rel_it;
02016 vector<Symbol *>::iterator sym_it;
02017 for(sym_it = opdsymbols_.begin(); sym_it != opdsymbols_.end(); ++sym_it) {
02018 for(rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
02019 if((*sym_it)->getPtrOffset() == (*rel_it).rel_addr()) {
02020 i = 0;
02021 while (i < regions_.size()) {
02022 if(regions_[i]->getRegionName().compare((*rel_it).getDynSym()->getMangledName()) == 0){
02023 Region *targetRegion = regions_[i];
02024 Offset regionOffset = targetRegion->getDiskOffset()+(*rel_it).addend();
02025 (*sym_it)->setRegion(targetRegion);
02026 (*sym_it)->setOffset(regionOffset);
02027 break;
02028 }
02029 ++i;
02030 }
02031 }
02032 }
02033 }
02034 opdsymbols_.clear();
02035 }
02036
02037 Symbol *Object::handle_opd_symbol(Region *opd, Symbol *sym)
02038 {
02039 if (!sym) return NULL;
02040
02041 Offset soffset = sym->getOffset();
02042 Offset *opd_entry = (Offset *)(((char *)opd->getPtrToRawData()) +
02043 (soffset - opd->getDiskOffset()));
02044 assert(opd->isOffsetInRegion(soffset));
02045
02046 Symbol *retval = new Symbol(*sym);
02047 retval->setOffset(opd_entry[0]);
02048 retval->setLocalTOC(opd_entry[1]);
02049 retval->setPtrOffset(soffset);
02050
02051
02052 unsigned int i = 0;
02053 while (i < regions_.size()) {
02054 if (regions_[i]->isOffsetInRegion(opd_entry[0])) {
02055 retval->setRegion(regions_[i]);
02056 break;
02057 }
02058 ++i;
02059 }
02060 assert(i < regions_.size());
02061 retval->setSymbolType(Symbol::ST_FUNCTION);
02062 #if 0
02063 retval->tag_ = Symbol::TAG_INTERNAL;
02064
02065
02066
02067 #endif
02068
02069 return retval;
02070 }
02071
02072
02073 bool Object::parse_symbols(Elf_X_Data &symdata, Elf_X_Data &strdata,
02074 Elf_X_Shdr* bssscnp,
02075 Elf_X_Shdr* symscnp,
02076 bool , string smodule)
02077 {
02078 #if defined(TIMED_PARSE)
02079 struct timeval starttime;
02080 gettimeofday(&starttime, NULL);
02081 #endif
02082
02083 if (!symdata.isValid() || !strdata.isValid()) {
02084 return false;
02085 }
02086
02087 Elf_X_Sym syms = symdata.get_sym();
02088 const char *strs = strdata.get_string();
02089 if(syms.isValid()){
02090 for (unsigned i = 0; i < syms.count(); i++) {
02091
02092
02093
02094
02095
02096
02097
02098 int etype = syms.ST_TYPE(i);
02099 int ebinding = syms.ST_BIND(i);
02100 int evisibility = syms.ST_VISIBILITY(i);
02101
02102
02103 string sname = &strs[ syms.st_name(i) ];
02104 Symbol::SymbolType stype = pdelf_type(etype);
02105 Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
02106 Symbol::SymbolVisibility svisibility = pdelf_visibility(evisibility);
02107 unsigned ssize = syms.st_size(i);
02108 unsigned secNumber = syms.st_shndx(i);
02109
02110 Offset soffset;
02111 if (symscnp->isFromDebugFile()) {
02112 Offset soffset_dbg = syms.st_value(i);
02113 soffset = soffset_dbg;
02114 if (soffset_dbg) {
02115 bool result = convertDebugOffset(soffset_dbg, soffset);
02116 if (!result) {
02117
02118 continue;
02119 }
02120 }
02121 }
02122 else {
02123 soffset = syms.st_value(i);
02124 }
02125
02126
02127
02128
02129
02130
02131 if (bssscnp) {
02132 Offset bssStart = Offset(bssscnp->sh_addr());
02133 Offset bssEnd = Offset (bssStart + bssscnp->sh_size()) ;
02134
02135 if(( bssStart <= soffset) && ( soffset < bssEnd ) && (ssize > 0) &&
02136 (stype == Symbol::ST_NOTYPE))
02137 {
02138 stype = Symbol::ST_OBJECT;
02139 }
02140 }
02141
02142
02143 if (i==0 && sname == "" && soffset == (Offset)0)
02144 continue;
02145
02146
02147 Region *sec;
02148 if(secNumber >= 1 && secNumber < regions_.size()) {
02149 sec = regions_[secNumber];
02150 } else {
02151 sec = NULL;
02152 }
02153 int ind = int (i);
02154 int strindex = syms.st_name(i);
02155
02156 if(stype == Symbol::ST_SECTION && sec != NULL) {
02157 sname = sec->getRegionName();
02158 soffset = sec->getDiskOffset();
02159 }
02160
02161 if (stype == Symbol::ST_MODULE) {
02162 smodule = sname;
02163 }
02164 Symbol *newsym = new Symbol(sname,
02165 stype,
02166 slinkage,
02167 svisibility,
02168 soffset,
02169 NULL,
02170 sec,
02171 ssize,
02172 false,
02173 (secNumber == SHN_ABS),
02174 ind,
02175 strindex,
02176 (secNumber == SHN_COMMON));
02177
02178 if (stype == Symbol::ST_UNKNOWN)
02179 newsym->setInternalType(etype);
02180
02181 if (sec && sec->getRegionName() == OPD_NAME && stype == Symbol::ST_FUNCTION ) {
02182 newsym = handle_opd_symbol(sec, newsym);
02183
02184 opdsymbols_.push_back(newsym);
02185 symbols_[sname].push_back(newsym);
02186 symsByOffset_[newsym->getOffset()].push_back(newsym);
02187 symsToModules_[newsym] = smodule;
02188 } else {
02189 symbols_[sname].push_back(newsym);
02190 symsByOffset_[newsym->getOffset()].push_back(newsym);
02191 symsToModules_[newsym] = smodule;
02192 }
02193
02194 }
02195 }
02196 #if defined(TIMED_PARSE)
02197 struct timeval endtime;
02198 gettimeofday(&endtime, NULL);
02199 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02200 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02201 unsigned long difftime = lendtime - lstarttime;
02202 double dursecs = difftime/(1000 * 1000);
02203 cout << "parsing elf took "<<dursecs <<" secs" << endl;
02204 #endif
02205 return true;
02206 }
02207
02208
02209
02210
02211
02212 void Object::parse_dynamicSymbols (Elf_X_Shdr *&
02213 dyn_scnp
02214 , Elf_X_Data &symdata,
02215 Elf_X_Data &strdata,
02216 bool ,
02217 std::string smodule)
02218 {
02219 #if defined(TIMED_PARSE)
02220 struct timeval starttime;
02221 gettimeofday(&starttime, NULL);
02222 #endif
02223
02224 Elf_X_Sym syms = symdata.get_sym();
02225 const char *strs = strdata.get_string();
02226 Elf_X_Shdr *versymSec = NULL, *verneedSec = NULL, *verdefSec = NULL;
02227 Elf_X_Data data = dyn_scnp->get_data();
02228 Elf_X_Dyn dyns = data.get_dyn();
02229 unsigned verneednum = 0, verdefnum = 0;
02230 Elf_X_Versym symVersions;
02231 Elf_X_Verdef *symVersionDefs = NULL;
02232 Elf_X_Verneed *symVersionNeeds = NULL;
02233 for (unsigned i = 0; i < dyns.count(); ++i) {
02234 switch(dyns.d_tag(i)) {
02235 case DT_NEEDED:
02236 deps_.push_back(&strs[dyns.d_ptr(i)]);
02237 break;
02238 case DT_VERSYM:
02239 versymSec = getRegionHdrByAddr(dyns.d_ptr(i));
02240 break;
02241 case DT_VERNEED:
02242 verneedSec = getRegionHdrByAddr(dyns.d_ptr(i));
02243 break;
02244 case DT_VERDEF:
02245 verdefSec = getRegionHdrByAddr(dyns.d_ptr(i));
02246 break;
02247 case DT_VERNEEDNUM:
02248 verneednum = dyns.d_ptr(i);
02249 break;
02250 case DT_VERDEFNUM:
02251 verdefnum = dyns.d_ptr(i);
02252 break;
02253 default:
02254 break;
02255 }
02256 }
02257 if(versymSec)
02258 symVersions = versymSec->get_data().get_versyms();
02259 if(verdefSec)
02260 symVersionDefs = verdefSec->get_data().get_verDefSym();
02261 if(verneedSec)
02262 symVersionNeeds = verneedSec->get_data().get_verNeedSym();
02263
02264 for(unsigned i = 0; i < verdefnum ;i++) {
02265 Elf_X_Verdaux *aux = symVersionDefs->get_aux();
02266 for(unsigned j=0; j< symVersionDefs->vd_cnt(); j++){
02267 versionMapping[symVersionDefs->vd_ndx()].push_back(&strs[aux->vda_name()]);
02268 Elf_X_Verdaux *auxnext = aux->get_next();
02269 delete aux;
02270 aux = auxnext;
02271 }
02272 Elf_X_Verdef *symVersionDefsnext = symVersionDefs->get_next();
02273 delete symVersionDefs;
02274 symVersionDefs = symVersionDefsnext;
02275 }
02276
02277 for(unsigned i = 0; i < verneednum; i++){
02278 Elf_X_Vernaux *aux = symVersionNeeds->get_aux();
02279 for(unsigned j=0; j< symVersionNeeds->vn_cnt(); j++){
02280 versionMapping[aux->vna_other()].push_back(&strs[aux->vna_name()]);
02281 versionFileNameMapping[aux->vna_other()] = &strs[symVersionNeeds->vn_file()];
02282 Elf_X_Vernaux *auxnext = aux->get_next();
02283 delete aux;
02284 aux = auxnext;
02285 }
02286 Elf_X_Verneed *symVersionNeedsnext = symVersionNeeds->get_next();
02287 delete symVersionNeeds;
02288 symVersionNeeds = symVersionNeedsnext;
02289 }
02290
02291 if(syms.isValid()) {
02292 for (unsigned i = 0; i < syms.count(); i++) {
02293 int etype = syms.ST_TYPE(i);
02294 int ebinding = syms.ST_BIND(i);
02295 int evisibility = syms.ST_VISIBILITY(i);
02296
02297
02298 string sname = &strs[ syms.st_name(i) ];
02299 Symbol::SymbolType stype = pdelf_type(etype);
02300 Symbol::SymbolLinkage slinkage = pdelf_linkage(ebinding);
02301 Symbol::SymbolVisibility svisibility = pdelf_visibility(evisibility);
02302 unsigned ssize = syms.st_size(i);
02303 Offset soffset = syms.st_value(i);
02304 unsigned secNumber = syms.st_shndx(i);
02305
02306
02307 if (i==0 && sname == "" && soffset == (Offset)0)
02308 continue;
02309
02310 Region *sec;
02311 if(secNumber >= 1 && secNumber < regions_.size()) {
02312 sec = regions_[secNumber];
02313 } else {
02314 sec = NULL;
02315 }
02316
02317 int ind = int (i);
02318 int strindex = syms.st_name(i);
02319
02320 if (stype == Symbol::ST_MODULE) {
02321 smodule = sname;
02322 }
02323
02324 Symbol *newsym = new Symbol(sname,
02325 stype,
02326 slinkage,
02327 svisibility,
02328 soffset,
02329 NULL,
02330 sec,
02331 ssize,
02332 true,
02333 (secNumber == SHN_ABS),
02334 ind,
02335 strindex,
02336 (secNumber == SHN_COMMON));
02337
02338 if (stype == Symbol::ST_UNKNOWN)
02339 newsym->setInternalType(etype);
02340
02341 if(versymSec) {
02342 unsigned short raw = symVersions.get(i);
02343 bool hidden = raw >> 15;
02344 int index = raw & 0x7fff;
02345 if(versionFileNameMapping.find(index) != versionFileNameMapping.end()) {
02346
02347
02348 newsym->setVersionFileName(versionFileNameMapping[index]);
02349 }
02350 if(versionMapping.find(index) != versionMapping.end()) {
02351
02352
02353
02354 newsym->setVersions(versionMapping[index]);
02355
02356 }
02357 if (hidden) {
02358 newsym->setVersionHidden();
02359 }
02360 }
02361
02362
02363 if (sec && sec->getRegionName() == OPD_NAME && stype == Symbol::ST_FUNCTION ) {
02364 newsym = handle_opd_symbol(sec, newsym);
02365 opdsymbols_.push_back(newsym);
02366
02367 symbols_[sname].push_back(newsym);
02368 symsByOffset_[newsym->getOffset()].push_back(newsym);
02369 symsToModules_[newsym] = smodule;
02370 } else {
02371 symbols_[sname].push_back(newsym);
02372 symsByOffset_[newsym->getOffset()].push_back(newsym);
02373 symsToModules_[newsym] = smodule;
02374 }
02375 }
02376 }
02377
02378 #if defined(TIMED_PARSE)
02379 struct timeval endtime;
02380 gettimeofday(&endtime, NULL);
02381 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02382 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02383 unsigned long difftime = lendtime - lstarttime;
02384 double dursecs = difftime/(1000 * 1000);
02385 cout << "parsing elf took "<<dursecs <<" secs" << endl;
02386 #endif
02387 }
02388
02389 #if defined(USES_DWARF_DEBUG)
02390
02391 string Object::find_symbol(string name)
02392 {
02393 string name2;
02394
02395
02396 name2 = name;
02397 if (symbols_.find(name2)!=symbols_.end()) return name2;
02398
02399
02400 name2 = "_" + name;
02401 if (symbols_.find(name2)!=symbols_.end()) return name2;
02402
02403
02404 name2 = name + "_";
02405 if (symbols_.find(name2)!=symbols_.end())
02406 return name2;
02407
02408 return "";
02409 }
02410
02411 #endif
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424 #if defined(USES_DWARF_DEBUG)
02425
02426 void pd_dwarf_handler(Dwarf_Error error, Dwarf_Ptr )
02427 {
02428 if (error == NULL)
02429 return;
02430
02431 char *dwarf_msg = dwarf_errmsg(error);
02432 string str = string("DWARF Error: ")+ dwarf_msg;
02433 dwarf_err_func(str.c_str());
02434
02435
02436 }
02437
02438 Dwarf_Signed declFileNo = 0;
02439 char ** declFileNoToName = NULL;
02440
02441 bool Object::fixSymbolsInModule( Dwarf_Debug dbg, string & moduleName, Dwarf_Die dieEntry)
02442 {
02443 start:
02444
02445 Dwarf_Half dieTag;
02446 string useModuleName;
02447 int status = dwarf_tag( dieEntry, & dieTag, NULL );
02448 if (status != DW_DLV_OK) goto error;
02449
02450 useModuleName = moduleName;
02451
02452
02453 Dwarf_Off dieOffset;
02454 status = dwarf_die_CU_offset( dieEntry, & dieOffset, NULL );
02455 if (status != DW_DLV_OK) goto error;
02456
02457 switch( dieTag ) {
02458 case DW_TAG_subprogram:
02459 case DW_TAG_entry_point:
02460 {
02461
02462
02463 Dwarf_Bool isArtificial;
02464 status = dwarf_hasattr( dieEntry, DW_AT_artificial, & isArtificial, NULL );
02465 if (status != DW_DLV_OK) goto error;
02466
02467 if ( isArtificial )
02468 {
02469 break;
02470 }
02471
02472
02473
02474
02475
02476 Dwarf_Bool hasLowPC;
02477 status = dwarf_hasattr( dieEntry, DW_AT_low_pc, & hasLowPC, NULL );
02478 if (status != DW_DLV_OK) goto error;
02479
02480 Dwarf_Bool isAbstractOrigin;
02481 status = dwarf_hasattr( dieEntry, DW_AT_inline, & isAbstractOrigin, NULL );
02482 if (status != DW_DLV_OK) goto error;
02483
02484 if ( ! hasLowPC && ! isAbstractOrigin )
02485 {
02486 break;
02487 }
02488
02489 bool isDeclaredNotInlined = false;
02490
02491
02492
02493 if ( isAbstractOrigin )
02494 {
02495 Dwarf_Attribute inlineAttribute;
02496 status = dwarf_attr( dieEntry, DW_AT_inline, & inlineAttribute, NULL );
02497 if (status != DW_DLV_OK) goto error;
02498
02499 Dwarf_Unsigned inlineTag;
02500 status = dwarf_formudata( inlineAttribute, & inlineTag, NULL );
02501 if (status != DW_DLV_OK) goto error;
02502
02503 if ( inlineTag == DW_INL_inlined || inlineTag == DW_INL_declared_inlined )
02504 {
02505 break;
02506 }
02507
02508 if ( inlineTag == DW_INL_declared_not_inlined )
02509 {
02510 isDeclaredNotInlined = true;
02511 }
02512
02513 dwarf_dealloc( dbg, inlineAttribute, DW_DLA_ATTR );
02514 }
02515
02516
02517
02518
02519 Dwarf_Attribute specificationAttribute;
02520 status = dwarf_attr(dieEntry, DW_AT_specification, &specificationAttribute, NULL);
02521
02522 if (status == DW_DLV_ERROR) goto error;
02523
02524
02525 Dwarf_Die nameEntry = dieEntry;
02526
02527 if ( status == DW_DLV_OK )
02528 {
02529 Dwarf_Off specificationOffset;
02530 status = dwarf_global_formref(specificationAttribute, &specificationOffset, NULL);
02531 if (status != DW_DLV_OK) goto error;
02532
02533 status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
02534 if (status != DW_DLV_OK) goto error;
02535
02536 dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
02537 }
02538
02539
02540
02541 status = dwarf_hasattr( nameEntry, DW_AT_artificial, & isArtificial, NULL );
02542 if (status != DW_DLV_OK) goto error;
02543
02544 if ( isArtificial )
02545 {
02546 break;
02547 }
02548
02549
02550 char * dieName = NULL;
02551 status = dwarf_diename( nameEntry, & dieName, NULL );
02552 if (status == DW_DLV_ERROR) goto error;
02553
02554
02555 Dwarf_Attribute linkageNameAttribute;
02556 status = dwarf_attr(nameEntry, DW_AT_MIPS_linkage_name, &linkageNameAttribute, NULL);
02557 if (status == DW_DLV_ERROR) goto error;
02558
02559 bool hasLinkageName = false;
02560
02561 if ( status == DW_DLV_OK )
02562 {
02563 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02564 status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
02565 if (status != DW_DLV_OK) goto error;
02566 hasLinkageName = true;
02567 }
02568
02569
02570
02571 if ( dieName == NULL )
02572 {
02573 break;
02574 }
02575
02576
02577
02578 Dwarf_Die declEntry = nameEntry;
02579
02580 std::vector<Symbol *> foundSymbols;
02581
02582 string globalSymbol = find_symbol(dieName);
02583
02584 if (globalSymbol != "") {
02585 foundSymbols = symbols_[globalSymbol];
02586 }
02587 else if ( globalSymbol == "" && ! hasLinkageName && isDeclaredNotInlined )
02588 {
02589
02590
02591 bool first = true;
02592 Dwarf_Die siblingDie = dieEntry;
02593
02594 while ( true )
02595 {
02596 Dwarf_Die priorSibling = siblingDie;
02597 status = dwarf_siblingof( dbg, siblingDie, & siblingDie, NULL );
02598 if (status == DW_DLV_ERROR) goto error;
02599
02600 if ( ! first )
02601 {
02602 dwarf_dealloc( dbg, priorSibling, DW_DLA_DIE );
02603 }
02604 if ( status == DW_DLV_NO_ENTRY )
02605 {
02606 break;
02607 }
02608
02609 Dwarf_Attribute abstractOriginAttr;
02610 status = dwarf_attr(siblingDie, DW_AT_abstract_origin, &abstractOriginAttr, NULL);
02611
02612 if (status == DW_DLV_ERROR) goto error;
02613
02614
02615
02616 if ( status == DW_DLV_OK )
02617 {
02618 Dwarf_Off abstractOriginOffset;
02619 status = dwarf_formref( abstractOriginAttr, & abstractOriginOffset, NULL );
02620 if (status != DW_DLV_OK) goto error;
02621
02622 dwarf_dealloc( dbg, abstractOriginAttr, DW_DLA_ATTR );
02623
02624 if ( abstractOriginOffset == dieOffset )
02625 {
02626 Dwarf_Addr lowPC;
02627 status = dwarf_lowpc( siblingDie, & lowPC, NULL );
02628 if (status != DW_DLV_OK) goto error;
02629
02630
02631
02632 if ( symsByOffset_.find((Address)lowPC) !=
02633 symsByOffset_.end()) {
02634 foundSymbols = symsByOffset_[(Address)lowPC];
02635 }
02636
02637 dwarf_dealloc( dbg, siblingDie, DW_DLA_DIE );
02638 break;
02639
02640 }
02641 }
02642
02643 first = false;
02644
02645 }
02646 }
02647
02648 if (foundSymbols.size()) {
02649
02650
02651
02652 if ( isDeclaredNotInlined && nameEntry != dieEntry ) {
02653
02654
02655
02656
02657
02658 Dwarf_Attribute fileNoAttribute;
02659 status = dwarf_attr( declEntry, DW_AT_decl_file, & fileNoAttribute, NULL );
02660 if (status == DW_DLV_ERROR) goto error;
02661
02662
02663 if ( status == DW_DLV_OK ) {
02664 Dwarf_Unsigned fileNo;
02665 status = dwarf_formudata( fileNoAttribute, & fileNo, NULL );
02666 if (status != DW_DLV_OK) goto error;
02667
02668 dwarf_dealloc( dbg, fileNoAttribute, DW_DLA_ATTR );
02669
02670 useModuleName = declFileNoToName[ fileNo - 1 ];
02671
02672
02673
02674 }
02675 else {
02676
02677
02678 }
02679 }
02680
02681 if (foundSymbols.size() == 1) {
02682 symsToModules_[foundSymbols[0]] = useModuleName;
02683 }
02684 else {
02685 for ( unsigned int i = 0; i < foundSymbols.size(); i++ ) {
02686 if ( foundSymbols[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
02687 symsToModules_[foundSymbols[i]] = useModuleName;
02688 }
02689 }
02690 }
02691 }
02692 else if ( !isAbstractOrigin &&
02693 (symbols_.find(dieName) != symbols_.end())) {
02694 std::vector< Symbol *> & syms = symbols_[ dieName ];
02695
02696
02697
02698 if ( syms.size() == 1 ) {
02699 symsToModules_[syms[0]] = useModuleName;
02700 }
02701 else {
02702 for ( unsigned int i = 0; i < syms.size(); i++ ) {
02703 if ( syms[ i ]->getLinkage() == Symbol::SL_LOCAL ) {
02704 symsToModules_[syms[i]] = useModuleName;
02705 }
02706 }
02707 }
02708 }
02709 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02710 }
02711
02712 break;
02713
02714 case DW_TAG_variable:
02715 case DW_TAG_constant:
02716 {
02717
02718
02719 Dwarf_Attribute declAttr;
02720 status = dwarf_attr( dieEntry, DW_AT_declaration, & declAttr, NULL );
02721 if (status == DW_DLV_ERROR) goto error;
02722
02723 if ( status != DW_DLV_OK )
02724 {
02725 break;
02726 }
02727
02728 dwarf_dealloc( dbg, declAttr, DW_DLA_ATTR );
02729
02730
02731
02732
02733 Dwarf_Attribute specificationAttribute;
02734 status = dwarf_attr(dieEntry, DW_AT_specification, &specificationAttribute, NULL);
02735 if (status == DW_DLV_ERROR) goto error;
02736
02737 Dwarf_Die nameEntry = dieEntry;
02738
02739 if ( status == DW_DLV_OK )
02740 {
02741 Dwarf_Off specificationOffset;
02742 status = dwarf_global_formref(specificationAttribute, &specificationOffset, NULL);
02743 if (status != DW_DLV_OK) goto error;
02744
02745 dwarf_dealloc( dbg, specificationAttribute, DW_DLA_ATTR );
02746
02747 status = dwarf_offdie( dbg, specificationOffset, & nameEntry, NULL );
02748 if (status != DW_DLV_OK) goto error;
02749
02750 }
02751
02752
02753
02754 char * dieName = NULL;
02755 status = dwarf_diename( nameEntry, & dieName, NULL );
02756 if (status == DW_DLV_ERROR) goto error;
02757
02758
02759
02760 Dwarf_Attribute linkageNameAttribute;
02761 status = dwarf_attr(nameEntry, DW_AT_MIPS_linkage_name, &linkageNameAttribute, NULL);
02762 if (status == DW_DLV_ERROR) goto error;
02763
02764 if ( status == DW_DLV_OK )
02765 {
02766 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02767 status = dwarf_formstring( linkageNameAttribute, & dieName, NULL );
02768 if (status != DW_DLV_OK) goto error;
02769 }
02770
02771
02772 if ( dieName == NULL )
02773 {
02774 break;
02775 }
02776
02777
02778
02779 string symName = find_symbol(dieName);
02780
02781 if ( symName != "" )
02782 {
02783 assert(symbols_.find(symName)!=symbols_.end());
02784
02785
02786 std::vector< Symbol *> & syms = symbols_[ symName ];
02787
02788
02789 if ( syms.size() == 1 ) {
02790 symsToModules_[syms[0]] = useModuleName;
02791 }
02792 else {
02793 for ( unsigned int i = 0; i < syms.size(); i++ ) {
02794 if ( syms[ i ]->getLinkage() == Symbol::SL_GLOBAL ) {
02795 symsToModules_[syms[i]] = useModuleName;
02796 }
02797 }
02798 }
02799 }
02800
02801
02802
02803 dwarf_dealloc( dbg, dieName, DW_DLA_STRING );
02804
02805 }
02806
02807 break;
02808
02809 default:
02810
02811 break;
02812 }
02813
02814
02815
02816 Dwarf_Die childDwarf;
02817 status = dwarf_child( dieEntry, & childDwarf, NULL );
02818 if (status == DW_DLV_ERROR) goto error;
02819
02820 if ( status == DW_DLV_OK ) {
02821 fixSymbolsInModule(dbg, moduleName, childDwarf);
02822 }
02823
02824
02825
02826 Dwarf_Die siblingDwarf;
02827 status = dwarf_siblingof( dbg, dieEntry, & siblingDwarf, NULL );
02828 if (status == DW_DLV_ERROR) goto error;
02829
02830 if ( status == DW_DLV_OK )
02831 {
02832 dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02833
02834
02835 dieEntry = siblingDwarf;
02836 goto start;
02837 }
02838 else
02839 {
02840 dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02841 return true;
02842 }
02843 error:
02844 dwarf_dealloc( dbg, dieEntry, DW_DLA_DIE );
02845 return false;
02846 }
02847
02848
02849 unsigned Object::fixSymbolsInModuleByRange(IntervalTree<Dwarf_Addr, std::string> &modules)
02850 {
02851 if (modules.empty()) return 0;
02852
02853 unsigned nsyms_altered = 0;
02854
02855 for (dyn_hash_map<Offset, std::vector<Symbol *> >::iterator iter = symsByOffset_.begin();
02856 iter != symsByOffset_.end();
02857 iter++) {
02858 Offset off = iter->first;
02859 std::vector<Symbol *> &syms = iter->second;
02860
02861 std::string modname;
02862 if (modules.find((Dwarf_Addr) off, modname)) {
02863 for (unsigned i = 0; i < syms.size(); i++) {
02864 symsToModules_[syms[i]] = modname;
02865 nsyms_altered++;
02866 }
02867 }
02868 }
02869
02870 return nsyms_altered;
02871 }
02872
02873 bool Object::fix_global_symbol_modules_static_dwarf()
02874 {
02875 int status;
02876
02877 Dwarf_Debug *dbg_ptr = dwarf->type_dbg();
02878 if (!dbg_ptr)
02879 return false;
02880
02881 Dwarf_Debug &dbg = *dbg_ptr;
02882
02883 Dwarf_Unsigned hdr;
02884
02885 IntervalTree<Dwarf_Addr, std::string> module_ranges;
02886
02887
02888 while ( dwarf_next_cu_header_c( dbg, 1,
02889 NULL, NULL, NULL,
02890 NULL, NULL, NULL,
02891 NULL, NULL,
02892 & hdr, NULL ) == DW_DLV_OK )
02893 {
02894
02895 Dwarf_Die moduleDIE;
02896 status = dwarf_siblingof( dbg, NULL, & moduleDIE, NULL );
02897 if (status != DW_DLV_OK) goto error;
02898
02899
02900 Dwarf_Half moduleTag;
02901 status = dwarf_tag( moduleDIE, & moduleTag, NULL);
02902 if (status != DW_DLV_OK) goto error;
02903 if (moduleTag != DW_TAG_compile_unit) goto error;
02904
02905
02906 char * dwarfModuleName = NULL;
02907 status = dwarf_diename( moduleDIE, & dwarfModuleName, NULL );
02908 if (status == DW_DLV_ERROR) goto error;
02909
02910 string moduleName;
02911
02912 if ( status == DW_DLV_NO_ENTRY || dwarfModuleName == NULL )
02913 {
02914 moduleName = string( "{ANONYMOUS}" );
02915 }
02916 else
02917 {
02918 moduleName = extract_pathname_tail( string(dwarfModuleName) );
02919 }
02920
02921 Dwarf_Addr modLowPC = 0;
02922 Dwarf_Addr modHighPC = (Dwarf_Addr)(-1);
02923 Dwarf_Bool hasLowPC = false;
02924 Dwarf_Bool hasHighPC = false;
02925
02926 if (dwarf_hasattr(moduleDIE, DW_AT_low_pc, &hasLowPC, NULL) != DW_DLV_OK) {
02927 hasLowPC = false;
02928 }
02929 if (dwarf_hasattr(moduleDIE, DW_AT_high_pc, &hasHighPC, NULL) != DW_DLV_OK) {
02930 hasHighPC = false;
02931 }
02932 if (hasLowPC && hasHighPC) {
02933
02934 status = dwarf_lowpc(moduleDIE, &modLowPC, NULL);
02935 if (status != DW_DLV_OK) goto error;
02936
02937 status = dwarf_highpc(moduleDIE, &modHighPC, NULL);
02938 if (status != DW_DLV_OK) goto error;
02939
02940 if (modHighPC == 0)
02941 {
02942 modHighPC = (Dwarf_Addr)(-1);
02943 }
02944
02945
02946 module_ranges.insert(modLowPC, modHighPC, moduleName);
02947 }
02948 else
02949 {
02950
02951 status = dwarf_srcfiles( moduleDIE, & declFileNoToName, & declFileNo, NULL );
02952 if (status == DW_DLV_ERROR) goto error;
02953
02954 if ( status == DW_DLV_OK )
02955 {
02956
02957
02958
02959
02960
02961 bool result = fixSymbolsInModule(dbg, moduleName, moduleDIE);
02962 if (!result) goto error;
02963
02964
02965
02966 for ( Dwarf_Signed i = 0; i < declFileNo; i++ ) {
02967 dwarf_dealloc( dbg, declFileNoToName[i], DW_DLA_STRING );
02968 }
02969
02970 dwarf_dealloc( dbg, declFileNoToName, DW_DLA_LIST );
02971
02972 }
02973 }
02974
02975 modules_.push_back(std::pair<std::string, Offset>(moduleName, modLowPC));
02976 }
02977
02978 if (!module_ranges.empty()) {
02979 fixSymbolsInModuleByRange(module_ranges);
02980 }
02981
02982 return true;
02983 error:
02984 return false;
02985 }
02986
02987 #else
02988
02989
02990 bool Object::fix_global_symbol_modules_static_dwarf()
02991 { return false; }
02992
02993 #endif // USES_DWARF_DEBUG
02994
02995
02996
02997
02998
02999
03000
03001
03002 bool Object::fix_global_symbol_modules_static_stab(Elf_X_Shdr* stabscnp, Elf_X_Shdr* stabstrscnp)
03003 {
03004
03005
03006
03007
03008
03009 if (!stabscnp || !stabstrscnp) return false;
03010
03011 Elf_X_Data stabdata = stabscnp->get_data();
03012 Elf_X_Data stabstrdata = stabstrscnp->get_data();
03013 stab_entry *stabptr = NULL;
03014
03015 if (!stabdata.isValid() || !stabstrdata.isValid()) return false;
03016
03017 switch (addressWidth_nbytes)
03018 {
03019 case 4:
03020 stabptr = new stab_entry_32(stabdata.d_buf(),
03021 stabstrdata.get_string(),
03022 stabscnp->sh_size() / sizeof(stab32));
03023 break;
03024
03025 case 8:
03026 stabptr = new stab_entry_64(stabdata.d_buf(),
03027 stabstrdata.get_string(),
03028 stabscnp->sh_size() / sizeof(stab64));
03029 break;
03030 };
03031
03032 const char *next_stabstr = stabptr->getStringBase();
03033 string module = "DEFAULT_MODULE";
03034
03035
03036
03037
03038
03039 bool is_fortran = false;
03040
03041 for (unsigned i = 0; i < stabptr->count(); i++)
03042 {
03043 switch(stabptr->type(i))
03044 {
03045 case N_UNDF:
03046 stabptr->setStringBase(next_stabstr);
03047 next_stabstr = stabptr->getStringBase() + stabptr->val(i);
03048 break;
03049
03050 case N_ENDM:
03051 is_fortran = false;
03052 module = "DEFAULT_MODULE";
03053 break;
03054
03055 case N_SO:
03056 if ((stabptr->desc(i) == N_SO_FORTRAN) || (stabptr->desc(i) == N_SO_F90))
03057 is_fortran = true;
03058
03059 module = string(stabptr->name(i));
03060 break;
03061
03062 case N_ENTRY:
03063 case N_GSYM:
03064
03065
03066
03067
03068 {
03069 const char *p = stabptr->name(i);
03070
03071
03072
03073 if (strlen(p) == 0)
03074 {
03075
03076
03077 break;
03078 }
03079
03080 const char *q = strchr(p,':');
03081 unsigned len;
03082
03083 if (q)
03084 {
03085 len = q - p;
03086 }
03087 else
03088 {
03089 len = strlen(p);
03090 }
03091
03092 if (len == 0)
03093 {
03094
03095 break;
03096 }
03097
03098 char *sname = new char[len+1];
03099 strncpy(sname, p, len);
03100 sname[len] = 0;
03101
03102 string SymName = string(sname);
03103
03104
03105
03106
03107
03108 bool res = (symbols_.find(SymName)!=symbols_.end());
03109
03110 if (!res && is_fortran)
03111 {
03112
03113
03114 SymName += "_";
03115 res = (symbols_.find(SymName)!=symbols_.end());
03116 }
03117
03118 if (res && (q == 0 || q[1] != SD_PROTOTYPE))
03119 {
03120 unsigned int count = 0;
03121 std::vector< Symbol *> & syms = symbols_[SymName];
03122
03123
03124 if ( syms.size() == 1 )
03125 {
03126
03127
03128 }
03129 else
03130 {
03131 for ( unsigned int i = 0; i < syms.size(); i++ )
03132 {
03133 if ( syms[i]->getLinkage() == Symbol::SL_GLOBAL )
03134 {
03135
03136
03137 count++;
03138 }
03139 }
03140 }
03141 }
03142 break;
03143 }
03144 case N_FUN:
03145
03146 {
03147 const char *p = stabptr->name(i);
03148
03149 if (strlen(p) == 0)
03150 {
03151
03152
03153
03154 break;
03155 }
03156
03157 const char *q = strchr(p,':');
03158
03159 if (q == 0)
03160 {
03161
03162
03163 break;
03164 }
03165
03166 if (q[1] == SD_PROTOTYPE)
03167 {
03168
03169 break;
03170 }
03171
03172 unsigned long entryAddr = stabptr->val(i);
03173
03174 if (entryAddr == 0)
03175 {
03176
03177
03178
03179
03180
03181 unsigned len = q - p;
03182 if (len == 0)
03183 {
03184
03185 break;
03186 }
03187
03188 char *sname = new char[len+1];
03189 strncpy(sname, p, len);
03190 sname[len] = 0;
03191 string nameFromStab = string(sname);
03192 delete[] sname;
03193
03194 for (unsigned i = 0; i < symbols_[nameFromStab].size(); i++) {
03195 symsToModules_[symbols_[nameFromStab][i]] = module;
03196 }
03197 }
03198 else
03199 {
03200 if (symsByOffset_.find(entryAddr)==symsByOffset_.end()) {
03201
03202
03203 break;
03204 }
03205 for (unsigned i = 0; i < symsByOffset_[entryAddr].size(); i++) {
03206 symsToModules_[symsByOffset_[entryAddr][i]] = module;
03207 }
03208 }
03209 break;
03210 }
03211
03212 default:
03213
03214 break;
03215 }
03216 }
03217
03218 delete stabptr;
03219
03220 return true;
03221 }
03222
03223
03224
03225
03226
03227 void Object::find_code_and_data(Elf_X &elf,
03228 Offset txtaddr,
03229 Offset dataddr)
03230 {
03231
03232
03233
03234
03235
03236 for (int i = 0; i < elf.e_phnum(); ++i) {
03237 Elf_X_Phdr &phdr = elf.get_phdr(i);
03238
03239 char *file_ptr = (char *)mf->base_addr();
03240
03241 if(!isRegionPresent(phdr.p_paddr(), phdr.p_filesz(), phdr.p_flags())) {
03242 Region *reg = new Region(i, "", phdr.p_paddr(), phdr.p_filesz(),
03243 phdr.p_vaddr(), phdr.p_memsz(),
03244 &file_ptr[phdr.p_offset()],
03245 getSegmentPerms(phdr.p_flags()),
03246 getSegmentType(phdr.p_type(), phdr.p_flags()));
03247 reg->setFileOffset(phdr.p_offset());
03248 regions_.push_back(reg);
03249 }
03250
03251
03252
03253
03254 if (((phdr.p_vaddr() <= txtaddr) &&
03255 (phdr.p_vaddr() + phdr.p_filesz() >= txtaddr)) ||
03256 (!txtaddr && ((phdr.p_vaddr() <= entryAddress_) &&
03257 (phdr.p_vaddr() + phdr.p_filesz() >= entryAddress_)))) {
03258
03259 if (code_ptr_ == 0 && code_off_ == 0 && code_len_ == 0) {
03260 code_ptr_ = (char *)(void*)&file_ptr[phdr.p_offset()];
03261 code_off_ = (Offset)phdr.p_vaddr();
03262 code_len_ = (unsigned)phdr.p_filesz();
03263 }
03264
03265 } else if (((phdr.p_vaddr() <= dataddr) &&
03266 (phdr.p_vaddr() + phdr.p_filesz() >= dataddr)) ||
03267 (!dataddr && (phdr.p_type() == PT_LOAD))) {
03268 if (data_ptr_ == 0 && data_off_ == 0 && data_len_ == 0) {
03269 data_ptr_ = (char *)(void *)&file_ptr[phdr.p_offset()];
03270 data_off_ = (Offset)phdr.p_vaddr();
03271 data_len_ = (unsigned)phdr.p_filesz();
03272 }
03273 }
03274 }
03275
03276 }
03277
03278 const char *Object::elf_vaddr_to_ptr(Offset vaddr) const
03279 {
03280 const char *ret = NULL;
03281 unsigned code_size_ = code_len_;
03282 unsigned data_size_ = data_len_;
03283
03284 #if defined(os_irix)
03285 vaddr -= base_addr;
03286 #endif
03287
03288 if (vaddr >= code_off_ && vaddr < code_off_ + code_size_) {
03289 ret = ((char *)code_ptr_) + (vaddr - code_off_);
03290 } else if (vaddr >= data_off_ && vaddr < data_off_ + data_size_) {
03291 ret = ((char *)data_ptr_) + (vaddr - data_off_);
03292 }
03293
03294 return ret;
03295 }
03296
03297 stab_entry *Object::get_stab_info() const
03298 {
03299 char *file_ptr = (char *)mf->base_addr();
03300
03301
03302 if (stab_off_ && stab_size_ && stabstr_off_) {
03303 switch (addressWidth_nbytes) {
03304 case 4:
03305 return new stab_entry_32(file_ptr + stab_off_,
03306 file_ptr + stabstr_off_,
03307 stab_size_ / sizeof(stab32));
03308 break;
03309 case 8:
03310 return new stab_entry_64(file_ptr + stab_off_,
03311 file_ptr + stabstr_off_,
03312 stab_size_ / sizeof(stab64));
03313 break;
03314 };
03315 }
03316
03317
03318 return new stab_entry_64();
03319 }
03320
03321 Object::Object(MappedFile *mf_, bool, void (*err_func)(const char *),
03322 bool alloc_syms) :
03323 AObject(mf_, err_func),
03324 hasReldyn_(false),
03325 hasReladyn_(false),
03326 hasRelplt_(false),
03327 hasRelaplt_(false),
03328 relType_(Region::RT_REL),
03329 opd_addr_(0),
03330 opd_size_(0),
03331 dwarf(NULL),
03332 EEL(false),
03333 DbgSectionMapSorted(false)
03334 {
03335
03336 #if defined(TIMED_PARSE)
03337 struct timeval starttime;
03338 gettimeofday(&starttime, NULL);
03339 #endif
03340 is_aout_ = false;
03341 did_open = false;
03342 interpreter_name_ = NULL;
03343 isStripped = false;
03344
03345 if(mf->getFD() != -1) {
03346 elfHdr = Elf_X::newElf_X(mf->getFD(), ELF_C_READ, NULL, mf_->pathname());
03347 }
03348 else {
03349 elfHdr = Elf_X::newElf_X((char *)mf->base_addr(), mf->size(), mf_->pathname());
03350 }
03351
03352
03353
03354 if (!elfHdr->isValid()) {
03355 log_elferror(err_func_, "ELF header");
03356 has_error = true;
03357 return;
03358 }
03359 else if (!pdelf_check_ehdr(*elfHdr)) {
03360 log_elferror(err_func_, "ELF header failed integrity check");
03361 has_error = true;
03362 return;
03363 }
03364
03365 dwarf = DwarfHandle::createDwarfHandle(mf_->pathname(), elfHdr);
03366 if( elfHdr->e_type() == ET_DYN )
03367 load_shared_object(alloc_syms);
03368 else if( elfHdr->e_type() == ET_REL || elfHdr->e_type() == ET_EXEC ) {
03369
03370 if( elfHdr->e_phnum() ) is_aout_ = true;
03371 else is_aout_ = false;
03372
03373 load_object(alloc_syms);
03374 }
03375 else {
03376 log_perror(err_func_,"Invalid filetype in Elf header");
03377 has_error = true;
03378 return;
03379 }
03380
03381 #ifdef BINEDIT_DEBUG
03382 print_symbol_map(&symbols_);
03383 #endif
03384 #if defined(TIMED_PARSE)
03385 struct timeval endtime;
03386 gettimeofday(&endtime, NULL);
03387 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
03388 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
03389 unsigned long difftime = lendtime - lstarttime;
03390 double dursecs = difftime/(1000 );
03391 cout << "obj parsing in Object-elf took "<<dursecs <<" msecs" << endl;
03392 #endif
03393 }
03394
03395 Object::Object(const Object& obj)
03396 : AObject(obj),
03397 dwarf(NULL),
03398 EEL(false)
03399 {
03400 interpreter_name_ = obj.interpreter_name_;
03401 isStripped = obj.isStripped;
03402 loadAddress_ = obj.loadAddress_;
03403 entryAddress_ = obj.entryAddress_;
03404 relocation_table_ = obj.relocation_table_;
03405 fbt_ = obj.fbt_;
03406 elfHdr = obj.elfHdr;
03407 deps_ = obj.deps_;
03408 DbgSectionMapSorted = obj.DbgSectionMapSorted;
03409 relType_ = obj.relType_;
03410 }
03411
03412 Object::~Object()
03413 {
03414 unsigned i;
03415 relocation_table_.clear();
03416 fbt_.clear();
03417 for(i=0; i<allRegionHdrs.size();i++) {
03418 #if !defined(os_freebsd)
03419
03420 delete allRegionHdrs[i];
03421 #endif
03422 }
03423 allRegionHdrs.clear();
03424 versionMapping.clear();
03425 versionFileNameMapping.clear();
03426 deps_.clear();
03427 }
03428
03429 void Object::log_elferror(void (*err_func)(const char *), const char* msg)
03430 {
03431 const char* err = elf_errmsg(elf_errno());
03432 err = err ? err: "(bad elf error)";
03433 string str = string(err)+string(msg);
03434 err_func(str.c_str());
03435 }
03436
03437 bool Object::get_func_binding_table(std::vector<relocationEntry> &fbt) const
03438 {
03439 #if !defined(os_vxworks)
03440 if(!plt_addr_ || (!fbt_.size())) return false;
03441 #endif
03442 fbt = fbt_;
03443 return true;
03444 }
03445
03446 bool Object::get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const
03447 {
03448 if(!plt_addr_ || (!fbt_.size())) return false;
03449 fbt = &fbt_;
03450 return true;
03451 }
03452
03453 void Object::getDependencies(std::vector<std::string> &deps){
03454 deps = deps_;
03455 }
03456
03457 bool Object::addRelocationEntry(relocationEntry &re)
03458 {
03459 relocation_table_.push_back(re);
03460 return true;
03461 }
03462
03463 #ifdef DEBUG
03464
03465
03466 const ostream &Object::dump_state_info(ostream &s)
03467 {
03468 s << "Debugging Information for Object (address) : " << this << endl;
03469
03470 s << " <<begin debugging info for base object>>" << endl;
03471 AObject::dump_state_info(s);
03472 s << " <<end debuggingo info for base object>>" << endl;
03473
03474 s << " dynsym_addr_ = " << dynsym_addr_ << endl;
03475 s << " dynstr_addr_ = " << dynstr_addr_ << endl;
03476 s << " got_addr_ = " << got_addr_ << endl;
03477 s << " plt_addr_ = " << plt_addr_ << endl;
03478 s << " plt_size_ = " << plt_size_ << endl;
03479 s << " plt_entry_size_ = " << plt_entry_size_ << endl;
03480 s << " rel_plt_addr_ = " << rel_plt_addr_ << endl;
03481 s << " rel_plt_size_ = " << rel_plt_size_ << endl;
03482 s << " rel_plt_entry_size_ = " << rel_plt_entry_size_ << endl;
03483 s << " rel_size_ = " << rel_size_ << endl;
03484 s << " rel_entry_size_ = " << rel_entry_size_ << endl;
03485 s << " stab_off_ = " << stab_off_ << endl;
03486 s << " stab_size_ = " << stab_size_ << endl;
03487 s << " stabstr_off_ = " << stabstr_off_ << endl;
03488 s << " dwarvenDebugInfo = " << dwarvenDebugInfo << endl;
03489
03490
03491 s << " fbt_ = (field seperator :: )" << endl;
03492 for (unsigned i=0; i < fbt_.size(); i++) {
03493 s << fbt_[i] << " :: ";
03494 }
03495 s << endl;
03496
03497 return s;
03498 }
03499
03500 #endif
03501
03502
03503 Offset Object::getPltSlot(string funcName) const
03504 {
03505 relocationEntry re;
03506 Offset offset=0;
03507
03508 for ( unsigned int i = 0; i < fbt_.size(); i++ ){
03509 if (funcName == fbt_[i].name() ){
03510 offset = fbt_[i].rel_addr();
03511 }
03512 }
03513
03514 return offset;
03515 }
03516
03517
03518
03519
03520
03521
03522 void Object::get_valid_memory_areas(Elf_X &elf)
03523 {
03524 for (unsigned i = 0; i < elf.e_shnum(); ++i) {
03525 Elf_X_Shdr &shdr = elf.get_shdr(i);
03526 if ( !shdr.isValid()) {
03527 break;
03528 }
03529 if (shdr.sh_flags() & SHF_ALLOC) {
03530 if (code_off_ <= shdr.sh_addr() &&
03531 shdr.sh_addr() <= code_off_ + code_len_) {
03532 if (shdr.sh_addr() < code_vldS_)
03533 code_vldS_ = shdr.sh_addr();
03534 if (shdr.sh_addr() + shdr.sh_size() > code_vldE_)
03535 code_vldE_ = shdr.sh_addr() + shdr.sh_size();
03536
03537 } else if (data_off_ <= shdr.sh_addr() &&
03538 shdr.sh_addr() <= data_off_ + data_len_) {
03539 if (shdr.sh_addr() < data_vldS_)
03540 data_vldS_ = shdr.sh_addr();
03541 if (shdr.sh_addr() + shdr.sh_size() > data_vldE_)
03542 data_vldE_ = shdr.sh_addr() + shdr.sh_size();
03543 }
03544 }
03545 }
03546 }
03547
03548
03549
03550
03551
03552
03553 #if defined(os_linux)
03554
03555
03556
03557
03558 bool parseCompilerType(Object *objPtr)
03559 {
03560 dyn_hash_map<string, std::vector<Symbol *> >*syms = objPtr->getAllSymbols();
03561 if(syms->find("pgCC_compiled.") != syms->end())
03562 return true;
03563 return false;
03564 }
03565 #else
03566 bool parseCompilerType(Object *objPtr)
03567 {
03568 stab_entry *stabptr = objPtr->get_stab_info();
03569 const char *next_stabstr = stabptr->getStringBase();
03570
03571 for (unsigned int i=0; i < stabptr->count(); ++i) {
03572
03573 switch (stabptr->type(i)) {
03574
03575 case N_UNDF:
03576
03577
03578 stabptr->setStringBase(next_stabstr);
03579 next_stabstr = stabptr->getStringBase() + stabptr->val(i);
03580 break;
03581
03582 case N_OPT:
03583 delete stabptr;
03584 return false;
03585 }
03586 }
03587 delete stabptr;
03588 return false;
03589 }
03590 #endif
03591
03592
03593 #if (defined(os_linux) || defined(os_freebsd)) && (defined(arch_x86) || defined(arch_x86_64))
03594
03595 static unsigned long read_uleb128(const unsigned char *data, unsigned *bytes_read)
03596 {
03597 unsigned long result = 0;
03598 unsigned shift = 0;
03599 *bytes_read = 0;
03600 while (1)
03601 {
03602 result |= (data[*bytes_read] & 0x7f) << shift;
03603 if ((data[(*bytes_read)++] & 0x80) == 0)
03604 break;
03605 shift += 7;
03606 }
03607 return result;
03608 }
03609
03610 static signed long read_sleb128(const unsigned char *data, unsigned *bytes_read)
03611 {
03612 unsigned long result = 0;
03613 unsigned shift = 0;
03614 *bytes_read = 0;
03615 while (1)
03616 {
03617 result |= (data[*bytes_read] & 0x7f) << shift;
03618 shift += 7;
03619 if ((data[*bytes_read] & 0x80) == 0)
03620 break;
03621 (*bytes_read)++;
03622 }
03623 if (shift < sizeof(int) && (data[*bytes_read] & 0x40))
03624 result |= -(1 << shift);
03625 (*bytes_read)++;
03626 return result;
03627 }
03628
03629 #define DW_EH_PE_absptr 0x00
03630 #define DW_EH_PE_uleb128 0x01
03631 #define DW_EH_PE_udata2 0x02
03632 #define DW_EH_PE_udata4 0x03
03633 #define DW_EH_PE_udata8 0x04
03634 #define DW_EH_PE_sleb128 0x09
03635 #define DW_EH_PE_sdata2 0x0A
03636 #define DW_EH_PE_sdata4 0x0B
03637 #define DW_EH_PE_sdata8 0x0C
03638 #define DW_EH_PE_pcrel 0x10
03639 #define DW_EH_PE_textrel 0x20
03640 #define DW_EH_PE_datarel 0x30
03641 #define DW_EH_PE_funcrel 0x40
03642 #define DW_EH_PE_aligned 0x50
03643 #define DW_EH_PE_omit 0xff
03644
03645 typedef struct {
03646 int word_size;
03647 unsigned long pc;
03648 unsigned long text;
03649 unsigned long data;
03650 unsigned long func;
03651 } mach_relative_info;
03652
03653 static int read_val_of_type(int type, unsigned long *value, const unsigned char *addr,
03654 const mach_relative_info &mi)
03655 {
03656 unsigned size = 0;
03657 if (type == DW_EH_PE_omit)
03658 return 0;
03659
03660 unsigned long base = 0x0;
03661
03662
03663
03664
03665
03666
03667 switch (type & 0x70)
03668 {
03669 case DW_EH_PE_pcrel:
03670 base = mi.pc;
03671 break;
03672 case DW_EH_PE_textrel:
03673 base = mi.text;
03674 break;
03675 case DW_EH_PE_datarel:
03676 base = mi.data;
03677 break;
03678 case DW_EH_PE_funcrel:
03679 base = mi.func;
03680 break;
03681 }
03682
03683 switch (type & 0x0f)
03684 {
03685 case DW_EH_PE_absptr:
03686 if (mi.word_size == 4) {
03687 *value = (unsigned long) *((const uint32_t *) addr);
03688 size = 4;
03689 }
03690 else if (mi.word_size == 8) {
03691 *value = (unsigned long) *((const uint64_t *) addr);
03692 size = 8;
03693 }
03694 break;
03695 case DW_EH_PE_uleb128:
03696 *value = base + read_uleb128(addr, &size);
03697 break;
03698 case DW_EH_PE_sleb128:
03699 *value = base + read_sleb128(addr, &size);
03700 break;
03701 case DW_EH_PE_udata2:
03702 *value = base + *((const uint16_t *) addr);
03703 size = 2;
03704 break;
03705 case DW_EH_PE_sdata2:
03706 *value = base + *((const int16_t *) addr);
03707 size = 2;
03708 break;
03709 case DW_EH_PE_udata4:
03710 *value = base + *((const uint32_t *) addr);
03711 size = 4;
03712 break;
03713 case DW_EH_PE_sdata4:
03714 *value = base + *((const int32_t *) addr);
03715 size = 4;
03716 break;
03717 case DW_EH_PE_udata8:
03718 *value = base + *((const uint64_t *) addr);
03719 size = 8;
03720 break;
03721 case DW_EH_PE_sdata8:
03722 *value = base + *((const int64_t *) addr);
03723 size = 8;
03724 break;
03725 default:
03726 return -1;
03727 }
03728
03729 if ((type & 0x70) == DW_EH_PE_aligned)
03730 {
03731 if (mi.word_size == 4) {
03732 *value &= ~(0x3l);
03733 }
03734 else if (mi.word_size == 8) {
03735 *value &= ~(0x7l);
03736 }
03737 }
03738
03739 return size;
03740 }
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760 #define SHORT_FDE_HLEN 4
03761 #define LONG_FDE_HLEN 12
03762 static
03763 int read_except_table_gcc3(Dwarf_Fde *fde_data, Dwarf_Signed fde_count,
03764 mach_relative_info &mi,
03765 Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
03766 std::vector<ExceptionBlock> &addresses)
03767 {
03768 Dwarf_Error err = (Dwarf_Error) NULL;
03769 Dwarf_Addr low_pc;
03770 Dwarf_Unsigned bytes_in_cie;
03771 Dwarf_Off fde_offset, cie_offset;
03772 Dwarf_Fde fde;
03773 Dwarf_Cie cie;
03774 int status, result, ptr_size;
03775 char *augmentor;
03776 unsigned char lpstart_format, ttype_format, table_format;
03777 unsigned long value, table_end, region_start, region_size;
03778 unsigned long catch_block, action, augmentor_len;
03779 Dwarf_Small *fde_augdata, *cie_augdata;
03780 Dwarf_Unsigned fde_augdata_len, cie_augdata_len;
03781
03782
03783 for (int i = 0; i < fde_count; i++) {
03784 unsigned int j;
03785 unsigned char lsda_encoding = 0xff, personality_encoding = 0xff;
03786 unsigned char *lsda_ptr = NULL;
03787 unsigned char *cur_augdata;
03788 unsigned long except_off;
03789 unsigned long fde_addr, cie_addr;
03790 unsigned char *fde_bytes, *cie_bytes;
03791
03792
03793 status = dwarf_get_fde_n(fde_data, (Dwarf_Unsigned) i, &fde, &err);
03794 if (status != DW_DLV_OK) {
03795 pd_dwarf_handler(err, NULL);
03796 return false;
03797 }
03798
03799
03800
03801
03802
03803 status = dwarf_get_fde_range(fde, &low_pc, NULL, (void **) &fde_bytes,
03804 NULL, &cie_offset, NULL,
03805 &fde_offset, &err);
03806 if (status != DW_DLV_OK) {
03807 pd_dwarf_handler(err, NULL);
03808 return false;
03809 }
03810
03811
03812
03813 cie_offset = fde_offset - cie_offset +
03814 (*(uint32_t*)fde_bytes == 0xffffffff ? LONG_FDE_HLEN : SHORT_FDE_HLEN);
03815 cie_bytes = (unsigned char *)eh_frame->get_data().d_buf() + cie_offset;
03816
03817
03818 status = dwarf_get_cie_of_fde(fde, &cie, &err);
03819 if (status != DW_DLV_OK) {
03820 pd_dwarf_handler(err, NULL);
03821 return false;
03822 }
03823
03824
03825 status = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, &augmentor,
03826 NULL, NULL, NULL, NULL, NULL, &err);
03827 if (status != DW_DLV_OK) {
03828 pd_dwarf_handler(err, NULL);
03829 return false;
03830 }
03831
03832
03833
03834 augmentor_len = (augmentor == NULL) ? 0 : strlen(augmentor);
03835 for (j = 0; j < augmentor_len; j++) {
03836 if (augmentor[j] == 'L') {
03837 break;
03838 }
03839 }
03840 if (j == augmentor_len)
03841
03842
03843 continue;
03844
03845
03846
03847
03848
03849 fde_addr = eh_frame->sh_addr() + fde_offset;
03850 cie_addr = eh_frame->sh_addr() + cie_offset;
03851
03852
03853
03854
03855
03856
03857 status = dwarf_get_cie_augmentation_data(cie,
03858 &cie_augdata,
03859 &cie_augdata_len,
03860 &err);
03861 if (status != DW_DLV_OK) {
03862 pd_dwarf_handler(err, NULL);
03863 return false;
03864 }
03865
03866 cur_augdata = (unsigned char *) cie_augdata;
03867 lsda_encoding = DW_EH_PE_omit;
03868 for (j=0; j<augmentor_len; j++)
03869 {
03870 if (augmentor[j] == 'L')
03871 {
03872 lsda_encoding = *cur_augdata;
03873 cur_augdata++;
03874 }
03875 else if (augmentor[j] == 'P')
03876 {
03877
03878
03879 personality_encoding = *cur_augdata;
03880 cur_augdata++;
03881 unsigned long personality_val;
03882 mi.pc = cie_addr + (unsigned long) (cur_augdata - cie_bytes);
03883 cur_augdata += read_val_of_type(personality_encoding,
03884 &personality_val, cur_augdata, mi);
03885 }
03886 else if (augmentor[j] == 'z' || augmentor[j] == 'R')
03887 {
03888
03889 }
03890 else
03891 {
03892
03893
03894
03895 break;
03896 }
03897 }
03898 if (lsda_encoding == DW_EH_PE_omit)
03899 continue;
03900
03901
03902
03903
03904
03905
03906 status = dwarf_get_fde_augmentation_data(fde,
03907 &fde_augdata,
03908 &fde_augdata_len,
03909 &err);
03910 if (status != DW_DLV_OK) {
03911 pd_dwarf_handler(err, NULL);
03912 return false;
03913 }
03914 cur_augdata = (unsigned char *) fde_augdata;
03915 for (j=0; j<augmentor_len; j++)
03916 {
03917 if (augmentor[j] == 'L')
03918 {
03919 unsigned long lsda_val;
03920 mi.pc = fde_addr + (unsigned long) (cur_augdata - fde_bytes);
03921 ptr_size = read_val_of_type(lsda_encoding, &lsda_val, cur_augdata, mi);
03922 if (ptr_size == -1)
03923 break;
03924 lsda_ptr = (unsigned char *) lsda_val;
03925 cur_augdata += ptr_size;
03926 }
03927 else if (augmentor[j] == 'P' ||
03928 augmentor[j] == 'z' ||
03929 augmentor[j] == 'R')
03930 {
03931
03932 }
03933 else
03934 {
03935
03936 break;
03937 }
03938 }
03939 if (!lsda_ptr)
03940
03941
03942 continue;
03943
03944
03945 Elf_X_Data data = except_scn->get_data();
03946 if (!data.isValid()) {
03947 return false;
03948 }
03949
03950 const unsigned char *datap = (const unsigned char *) data.get_string();
03951 unsigned long int except_size = data.d_size();
03952
03953 except_off = (unsigned long) (lsda_ptr - except_scn->sh_addr());
03954 if (except_off >= except_size) {
03955 continue;
03956 }
03957
03958
03959
03960 lpstart_format = datap[except_off++];
03961 if (lpstart_format != DW_EH_PE_omit)
03962 except_off += read_val_of_type(DW_EH_PE_uleb128, &value, datap + except_off, mi);
03963 ttype_format = datap[except_off++];
03964 if (ttype_format != DW_EH_PE_omit)
03965 except_off += read_val_of_type(DW_EH_PE_uleb128, &value, datap + except_off, mi);
03966
03967
03968
03969 table_format = datap[except_off++];
03970 mi.pc = except_scn->sh_addr() + except_off;
03971 result = read_val_of_type(table_format, &table_end, datap + except_off, mi);
03972 if (result == -1) {
03973 continue;
03974 }
03975 except_off += result;
03976 table_end += except_off;
03977
03978 while (except_off < table_end && except_off < except_size) {
03979
03980
03981
03982
03983
03984
03985 mi.pc = except_scn->sh_addr() + except_off;
03986 except_off += read_val_of_type(table_format, ®ion_start,
03987 datap + except_off, mi);
03988 mi.pc = except_scn->sh_addr() + except_off;
03989 except_off += read_val_of_type(table_format, ®ion_size,
03990 datap + except_off, mi);
03991 mi.pc = except_scn->sh_addr() + except_off;
03992 except_off += read_val_of_type(table_format, &catch_block,
03993 datap + except_off, mi);
03994 except_off += read_val_of_type(DW_EH_PE_uleb128, &action,
03995 datap + except_off, mi);
03996
03997 if (catch_block == 0)
03998 continue;
03999 ExceptionBlock eb(region_start + low_pc, (unsigned) region_size,
04000 catch_block + low_pc);
04001 addresses.push_back(eb);
04002 }
04003 }
04004
04005 return true;
04006 }
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018 static bool read_except_table_gcc2(Elf_X_Shdr *except_table,
04019 std::vector<ExceptionBlock> &addresses,
04020 const mach_relative_info &mi)
04021 {
04022 Offset try_start;
04023 Offset try_end;
04024 Offset catch_start;
04025
04026 Elf_X_Data data = except_table->get_data();
04027 const unsigned char *datap = (const unsigned char *)data.get_string();
04028 unsigned long except_size = data.d_size();
04029
04030 unsigned i = 0;
04031 while (i < except_size) {
04032 if (mi.word_size == 4) {
04033 i += read_val_of_type(DW_EH_PE_udata4, &try_start, datap + i, mi);
04034 i += read_val_of_type(DW_EH_PE_udata4, &try_end, datap + i, mi);
04035 i += read_val_of_type(DW_EH_PE_udata4, &catch_start, datap + i, mi);
04036 }
04037 else if (mi.word_size == 8) {
04038 i += read_val_of_type(DW_EH_PE_udata8, &try_start, datap + i, mi);
04039 i += read_val_of_type(DW_EH_PE_udata8, &try_end, datap + i, mi);
04040 i += read_val_of_type(DW_EH_PE_udata8, &catch_start, datap + i, mi);
04041 }
04042
04043 if (try_start != (Offset) -1 && try_end != (Offset) -1) {
04044 ExceptionBlock eb(try_start, (unsigned) (try_end - try_start), catch_start);
04045 addresses.push_back(eb);
04046 }
04047 }
04048 return true;
04049 }
04050
04051 struct exception_compare: public binary_function<const ExceptionBlock &, const ExceptionBlock &, bool>
04052 {
04053 bool operator()(const ExceptionBlock &e1, const ExceptionBlock &e2) {
04054 if (e1.tryStart() < e2.tryStart())
04055 return true;
04056 return false;
04057 }
04058 };
04059
04060
04061
04062
04063
04064
04065
04066 bool Object::find_catch_blocks(Elf_X_Shdr *eh_frame,
04067 Elf_X_Shdr *except_scn,
04068 Address txtaddr, Address dataaddr,
04069 std::vector<ExceptionBlock> &catch_addrs)
04070 {
04071 Dwarf_Cie *cie_data;
04072 Dwarf_Fde *fde_data;
04073 Dwarf_Signed cie_count, fde_count;
04074 Dwarf_Error err = (Dwarf_Error) NULL;
04075 Dwarf_Unsigned bytes_in_cie;
04076 char *augmentor;
04077 int status, gcc_ver = 3;
04078 unsigned i;
04079 bool result = false;
04080
04081 if (except_scn == NULL) {
04082
04083 return true;
04084 }
04085
04086 Dwarf_Debug *dbg_ptr = dwarf->frame_dbg();
04087 if (!dbg_ptr) {
04088 pd_dwarf_handler(err, NULL);
04089 return false;
04090 }
04091 Dwarf_Debug &dbg = *dbg_ptr;
04092
04093
04094 status = dwarf_get_fde_list_eh(dbg, &cie_data, &cie_count,
04095 &fde_data, &fde_count, &err);
04096 if (status != DW_DLV_OK) {
04097
04098
04099 return false;
04100 }
04101
04102
04103 mach_relative_info mi;
04104 mi.text = txtaddr;
04105 mi.data = dataaddr;
04106 mi.pc = 0x0;
04107 mi.func = 0x0;
04108 mi.word_size = eh_frame->wordSize();
04109
04110
04111
04112 for (i = 0; i < cie_count; i++) {
04113 status = dwarf_get_cie_info(cie_data[i], &bytes_in_cie, NULL,
04114 &augmentor, NULL, NULL, NULL, NULL, NULL, &err);
04115 if (status != DW_DLV_OK) {
04116 pd_dwarf_handler(err, NULL);
04117 goto cleanup;
04118 }
04119 if (augmentor[0] == 'e' && augmentor[1] == 'h') {
04120 gcc_ver = 2;
04121 }
04122 }
04123
04124
04125 if (gcc_ver == 2) {
04126 result = read_except_table_gcc2(except_scn, catch_addrs, mi);
04127
04128 } else if (gcc_ver == 3) {
04129 result = read_except_table_gcc3(fde_data, fde_count, mi,
04130 eh_frame, except_scn,
04131 catch_addrs);
04132 }
04133 sort(catch_addrs.begin(),catch_addrs.end(),exception_compare());
04134
04135
04136 cleanup:
04137
04138 for (i = 0; i < cie_count; i++)
04139 dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
04140 for (i = 0; i < fde_count; i++)
04141 dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
04142 dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
04143 dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
04144
04145 return result;
04146 }
04147
04148 #endif
04149
04150 ObjectType Object::objType() const
04151 {
04152 return obj_type_;
04153 }
04154
04155 void Object::getModuleLanguageInfo(dyn_hash_map<string, supportedLanguages> *mod_langs)
04156 {
04157 string working_module;
04158 const char *ptr;
04159
04160
04161
04162
04163
04164 string mod_string;
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176 int fortran_kludge_flag = 0;
04177
04178
04179
04180
04181
04182 supportedLanguages working_lang = lang_Unknown;
04183 char *working_options = NULL;
04184 const char *working_name = NULL;
04185
04186 stab_entry *stabptr = NULL;
04187 const char *next_stabstr = NULL;
04188 #if defined(TIMED_PARSE)
04189 struct timeval starttime;
04190 gettimeofday(&starttime, NULL);
04191 #endif
04192
04193
04194
04195 stabptr = get_stab_info();
04196 next_stabstr = stabptr->getStringBase();
04197
04198 for( unsigned int i = 0; i < stabptr->count(); i++ )
04199 {
04200 if (stabptr->type(i) == N_UNDF)
04201 {
04202
04203
04204 stabptr->setStringBase(next_stabstr);
04205 next_stabstr = stabptr->getStringBase() + stabptr->val(i);
04206 }
04207 else if (stabptr->type(i) == N_OPT)
04208 {
04209
04210
04211
04212 if (working_name)
04213 working_options = const_cast<char *>(stabptr->name(i));
04214 }
04215 else if ((stabptr->type(i) == N_SO) || (stabptr->type(i) == N_ENDM))
04216 {
04217
04218
04219
04220
04221
04222
04223 if (working_name)
04224 {
04225 working_lang = pickLanguage(working_module, working_options, working_lang);
04226 if (working_lang == lang_Fortran_with_pretty_debug)
04227 fortran_kludge_flag = 1;
04228 (*mod_langs)[working_module] = working_lang;
04229
04230 }
04231
04232
04233
04234 working_lang = lang_Unknown;
04235 working_options = NULL;
04236
04237
04238
04239 if (stabptr->type(i) == N_ENDM)
04240 {
04241
04242
04243 working_name = "DEFAULT_MODULE";
04244 }
04245 else
04246 {
04247 working_name = stabptr->name(i);
04248 ptr = strrchr(working_name, '/');
04249 if (ptr)
04250 {
04251 ptr++;
04252 working_name = ptr;
04253 }
04254 }
04255 working_module = string(working_name);
04256
04257 if ((mod_langs->find(working_module) != mod_langs->end()) && (*mod_langs)[working_module] != lang_Unknown)
04258 {
04259
04260
04261 working_name = NULL;
04262 working_options = NULL;
04263 continue;
04264 }
04265 else
04266 {
04267
04268 switch (stabptr->desc(i))
04269 {
04270 case N_SO_FORTRAN:
04271 working_lang = lang_Fortran;
04272 break;
04273 case N_SO_F90:
04274 working_lang = lang_Fortran;
04275 break;
04276 case N_SO_AS:
04277 working_lang = lang_Assembly;
04278 break;
04279 case N_SO_ANSI_C:
04280 case N_SO_C:
04281 working_lang = lang_C;
04282 break;
04283 case N_SO_CC:
04284 working_lang = lang_CPlusPlus;
04285 break;
04286 default:
04287
04288
04289 working_lang = lang_Unknown;
04290 break;
04291 }
04292
04293 }
04294 }
04295 }
04296
04297
04298
04299
04300
04301 if (working_name)
04302 {
04303 working_lang = pickLanguage(working_module, working_options, working_lang);
04304 if (working_lang == lang_Fortran_with_pretty_debug)
04305 fortran_kludge_flag = 1;
04306 (*mod_langs)[working_module] = working_lang;
04307 }
04308
04309
04310 if (fortran_kludge_flag)
04311 {
04312
04313
04314 dyn_hash_map<string, supportedLanguages>::iterator iter = (*mod_langs).begin();
04315 string aname;
04316 supportedLanguages alang;
04317 for(;iter!=(*mod_langs).end();iter++)
04318 {
04319 aname = iter->first;
04320 alang = iter->second;
04321 if(lang_Fortran == alang)
04322 {
04323 (*mod_langs)[aname] = lang_Fortran_with_pretty_debug;
04324
04325 }
04326 }
04327 }
04328 #if defined(TIMED_PARSE)
04329 struct timeval endtime;
04330 gettimeofday(&endtime, NULL);
04331 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
04332 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
04333 unsigned long difftime = lendtime - lstarttime;
04334 double dursecs = difftime/(1000 );
04335 cout << __FILE__ << ":" << __LINE__ <<": getModuleLanguageInfo took "<<dursecs <<" msecs" << endl;
04336 #endif
04337 delete stabptr;
04338
04339 #if defined(cap_dwarf)
04340 if (hasDwarfInfo())
04341 {
04342 int status;
04343 Dwarf_Debug *dbg_ptr = dwarf->type_dbg();
04344 if (!dbg_ptr)
04345 return;
04346 Dwarf_Debug &dbg = *dbg_ptr;
04347
04348 Dwarf_Unsigned hdr;
04349 char * moduleName = NULL;
04350 Dwarf_Die moduleDIE = NULL;
04351 Dwarf_Attribute languageAttribute = NULL;
04352 bool done = false;
04353
04354 while( !done &&
04355 dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, & hdr, NULL) == DW_DLV_OK )
04356 {
04357 Dwarf_Half moduleTag;
04358 Dwarf_Unsigned languageConstant;
04359
04360 status = dwarf_siblingof(dbg, NULL, &moduleDIE, NULL);
04361 if (status != DW_DLV_OK) {
04362 done = true;
04363 goto cleanup_dwarf;
04364 }
04365
04366 status = dwarf_tag( moduleDIE, & moduleTag, NULL);
04367 if (status != DW_DLV_OK || moduleTag != DW_TAG_compile_unit) {
04368 done = true;
04369 goto cleanup_dwarf;
04370 }
04371
04372
04373 status = dwarf_diename( moduleDIE, & moduleName, NULL );
04374 if (status != DW_DLV_OK || !moduleName) {
04375 done = true;
04376 goto cleanup_dwarf;
04377 }
04378 ptr = strrchr(moduleName, '/');
04379 if (ptr)
04380 ptr++;
04381 else
04382 ptr = moduleName;
04383
04384 working_module = string(ptr);
04385
04386 status = dwarf_attr( moduleDIE, DW_AT_language, & languageAttribute, NULL );
04387 if (status == DW_DLV_ERROR) {
04388 done = true;
04389 goto cleanup_dwarf;
04390 }
04391
04392 status = dwarf_formudata( languageAttribute, & languageConstant, NULL );
04393 if (status != DW_DLV_OK) {
04394 done = true;
04395 goto cleanup_dwarf;
04396 }
04397
04398 switch( languageConstant )
04399 {
04400 case DW_LANG_C:
04401 case DW_LANG_C89:
04402 (*mod_langs)[working_module] = lang_C;
04403 break;
04404 case DW_LANG_C_plus_plus:
04405 (*mod_langs)[working_module] = lang_CPlusPlus;
04406 break;
04407 case DW_LANG_Fortran77:
04408 case DW_LANG_Fortran90:
04409 case DW_LANG_Fortran95:
04410 (*mod_langs)[working_module] = lang_Fortran;
04411 break;
04412 default:
04413
04414 break;
04415 }
04416 cleanup_dwarf:
04417 if (languageAttribute)
04418 dwarf_dealloc( dbg, languageAttribute, DW_DLA_ATTR );
04419 if (moduleName)
04420 dwarf_dealloc( dbg, moduleName, DW_DLA_STRING );
04421 if (moduleDIE)
04422 dwarf_dealloc( dbg, moduleDIE, DW_DLA_DIE );
04423 languageAttribute = NULL;
04424 moduleName = NULL;
04425 moduleDIE = NULL;
04426 }
04427
04428 }
04429 #endif
04430
04431 }
04432
04433 bool AObject::getSegments(vector<Segment> &segs) const
04434 {
04435 unsigned i;
04436 for(i=0;i<regions_.size();i++)
04437 {
04438 if((regions_[i]->getRegionName() == ".text") || (regions_[i]->getRegionName() == ".init") || (regions_[i]->getRegionName() == ".fini") ||
04439 (regions_[i]->getRegionName() == ".rodata") || (regions_[i]->getRegionName() == ".plt") || (regions_[i]->getRegionName() == ".data"))
04440 {
04441 Segment seg;
04442 seg.data = regions_[i]->getPtrToRawData();
04443 seg.loadaddr = regions_[i]->getDiskOffset();
04444 seg.size = regions_[i]->getDiskSize();
04445 seg.name = regions_[i]->getRegionName();
04446
04447 segs.push_back(seg);
04448 }
04449 }
04450 return true;
04451 }
04452
04453 bool Object::emitDriver(Symtab *obj, string fName,
04454 std::vector<Symbol *>&allSymbols,
04455 unsigned )
04456 {
04457 #ifdef BINEDIT_DEBUG
04458 printf("emitting...\n");
04459
04460 print_symbols(allSymbols);
04461 printf("%d total symbol(s)\n", allSymbols.size());
04462 #endif
04463 if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS32)
04464 {
04465 emitElf *em = new emitElf(elfHdr, isStripped, this, err_func_);
04466 if( !em->createSymbolTables(obj, allSymbols) ) return false;
04467 return em->driver(obj, fName);
04468 }
04469 #if defined(x86_64_unknown_linux2_4) || \
04470 defined(ppc64_linux) || \
04471 (defined(os_freebsd) && defined(arch_x86_64))
04472 else if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS64)
04473 {
04474 emitElf64 *em = new emitElf64(elfHdr, isStripped, this, err_func_);
04475 if( !em->createSymbolTables(obj, allSymbols) ) return false;
04476 return em->driver(obj, fName);
04477 }
04478 #endif
04479 return false;
04480 }
04481
04482 const char *Object::interpreter_name() const
04483 {
04484 return interpreter_name_;
04485 }
04486
04487
04488
04489 void Object::parseStabFileLineInfo(Symtab *st, dyn_hash_map<std::string, LineInformation> &li)
04490 {
04491 static dyn_hash_map< string, bool > haveParsedFileMap;
04492
04493
04494
04495 stab_entry * stabEntry = get_stab_info();
04496 assert( stabEntry != NULL );
04497 const char * nextStabString = stabEntry->getStringBase();
04498
04499 const char * currentSourceFile = NULL;
04500 const char * moduleName = NULL;
04501 Function *currentFunction = NULL;
04502 Offset currentAddress = 0;
04503 unsigned currentLineBase = 0;
04504 unsigned functionLineToPossiblyAdd = 0;
04505
04506
04507
04508 for ( unsigned int i = 0; i < stabEntry->count(); i++ )
04509 {
04510 switch (stabEntry->type( i ))
04511 {
04512 case N_UNDF:
04513 {
04514 stabEntry->setStringBase( nextStabString );
04515 nextStabString = stabEntry->getStringBase() + stabEntry->val( i );
04516
04517 currentSourceFile = NULL;
04518 }
04519 break;
04520
04521 case N_SO:
04522 {
04523 const char * sourceFile = stabEntry->name( i );
04524 currentSourceFile = strrchr( sourceFile, '/' );
04525
04526 if ( currentSourceFile == NULL )
04527 {
04528 currentSourceFile = sourceFile;
04529 }
04530 else
04531 {
04532 ++currentSourceFile;
04533 }
04534
04535 moduleName = currentSourceFile;
04536
04537
04538 }
04539 break;
04540
04541 case N_SOL:
04542 {
04543 const char * sourceFile = stabEntry->name( i );
04544 currentSourceFile = strrchr( sourceFile, '/' );
04545 if ( currentSourceFile == NULL )
04546 {
04547 currentSourceFile = sourceFile;
04548 }
04549 else
04550 {
04551 ++currentSourceFile;
04552 }
04553
04554
04555 }
04556 break;
04557
04558 case N_FUN:
04559 {
04560
04561
04562
04563
04564
04565 if ( *stabEntry->name( i ) == 0 )
04566 {
04567 currentFunction = NULL;
04568 currentLineBase = 0;
04569
04570 break;
04571 }
04572
04573 std::vector<Function *> funcs;
04574 char stringbuf[2048];
04575 const char *stabstr = stabEntry->name(i);
04576 unsigned iter = 0;
04577
04578 while (iter < 2048)
04579 {
04580 char c = stabstr[iter];
04581
04582 if ( (c == ':') || (c == '\0'))
04583 {
04584
04585 stringbuf[iter] = '\0';
04586 break;
04587 }
04588
04589 stringbuf[iter] = c;
04590
04591 iter++;
04592 }
04593
04594 if (iter >= 2047)
04595 {
04596 fprintf(stderr, "%s[%d]: something went horribly awry\n", FILE__, __LINE__);
04597 continue;
04598 }
04599 else
04600 {
04601 switch (stabstr[iter+1])
04602 {
04603 case 'F':
04604 case 'f':
04605
04606 break;
04607 case 'P':
04608 case 'p':
04609
04610
04611 continue;
04612 break;
04613 default:
04614 fprintf(stderr, "%s[%d]: discarding unknown %s, key = %c\n",
04615 FILE__, __LINE__, stabstr, stabstr[iter +1]);
04616 continue;
04617 break;
04618 };
04619 }
04620
04621 if (! st->findFunctionsByName(funcs, std::string(stringbuf))
04622 || !funcs.size())
04623 {
04624 fprintf(stderr, "%s[%d]: failed to find function with name %s\n",
04625 FILE__, __LINE__, stabEntry->name(i));
04626 continue;
04627 }
04628
04629 if (funcs.size() > 1)
04630 {
04631
04632 fprintf(stderr, "%s[%d]: WARN: found %lu functions with name %s (stringbuf %s)\n",
04633 FILE__, __LINE__, (unsigned long) funcs.size(), stabEntry->name(i), stringbuf);
04634 }
04635
04636 currentFunction = funcs[0];
04637 currentLineBase = stabEntry->desc(i);
04638 functionLineToPossiblyAdd = currentLineBase;
04639
04640 assert(currentFunction);
04641 currentAddress = currentFunction->getOffset();
04642
04643 }
04644 break;
04645
04646 case N_SLINE:
04647 {
04648 unsigned current_col = 0;
04649
04650
04651
04652
04653
04654
04655 if (!currentLineBase)
04656 {
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667 continue;
04668 }
04669
04670 unsigned newLineSpec = stabEntry->desc(i);
04671
04672
04673
04674
04675
04676
04677
04678 Offset newLineAddress = stabEntry->val(i) + currentFunction->getOffset();
04679
04680 if (newLineAddress <= currentAddress)
04681 {
04682
04683
04684 continue;
04685 }
04686
04687
04688
04689
04690
04691
04692
04693
04694 if (functionLineToPossiblyAdd)
04695 {
04696 if (functionLineToPossiblyAdd < newLineSpec)
04697 {
04698 li[moduleName].addLine(currentSourceFile,
04699 functionLineToPossiblyAdd,
04700 current_col, currentAddress,
04701 newLineAddress );
04702 }
04703
04704 functionLineToPossiblyAdd = 0;
04705 }
04706
04707
04708
04709
04710
04711 li[moduleName].addLine(currentSourceFile, newLineSpec,
04712 current_col, currentAddress,
04713 newLineAddress );
04714
04715 currentAddress = newLineAddress;
04716 currentLineBase = newLineSpec + 1;
04717
04718 }
04719 break;
04720
04721 }
04722
04723 }
04724
04725
04726 }
04727
04728
04729 void Object::parseDwarfFileLineInfo(dyn_hash_map<std::string, LineInformation> &li)
04730 {
04731 Dwarf_Debug *dbg_ptr = dwarf->line_dbg();
04732 if (!dbg_ptr)
04733 return;
04734 Dwarf_Debug &dbg = *dbg_ptr;
04735
04736
04737 Dwarf_Unsigned header;
04738 while ( dwarf_next_cu_header( dbg, NULL, NULL, NULL, NULL, & header, NULL ) == DW_DLV_OK )
04739 {
04740
04741 Dwarf_Die cuDIE;
04742 int status = dwarf_siblingof( dbg, NULL, & cuDIE, NULL);
04743 if ( status != DW_DLV_OK ) {
04744
04745 break;
04746 }
04747
04748 char * cuName;
04749 const char *moduleName;
04750 status = dwarf_diename( cuDIE, &cuName, NULL );
04751 if ( status == DW_DLV_NO_ENTRY ) {
04752 cuName = NULL;
04753 moduleName = "DEFAULT_MODULE";
04754 }
04755 else {
04756 moduleName = strrchr(cuName, '/');
04757 if (!moduleName)
04758 moduleName = strrchr(cuName, '\\');
04759 if (moduleName)
04760 moduleName++;
04761 else
04762 moduleName = cuName;
04763 }
04764
04765
04766
04767 Dwarf_Line * lineBuffer;
04768 Dwarf_Signed lineCount;
04769 status = dwarf_srclines( cuDIE, & lineBuffer, & lineCount, NULL );
04770
04771
04772
04773 assert( status != DW_DLV_ERROR );
04774
04775
04776 if ( status != DW_DLV_OK ) {
04777
04778 dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
04779 continue;
04780 }
04781 assert( status == DW_DLV_OK );
04782
04783
04784
04785
04786 bool isPreviousValid = false;
04787 Dwarf_Unsigned previousLineNo = 0;
04788 Dwarf_Signed previousLineColumn = 0;
04789 Dwarf_Addr previousLineAddr = 0x0;
04790 char * previousLineSource = NULL;
04791
04792
04793 Offset baseAddr = getBaseAddress();
04794
04795
04796 for ( int i = 0; i < lineCount; i++ )
04797 {
04798
04799 Dwarf_Unsigned lineNo;
04800 status = dwarf_lineno( lineBuffer[i], & lineNo, NULL );
04801 if ( status != DW_DLV_OK ) { continue; }
04802
04803 Dwarf_Signed lineOff;
04804 status = dwarf_lineoff( lineBuffer[i], & lineOff, NULL );
04805 if ( status != DW_DLV_OK ) { lineOff = 0; }
04806
04807 Dwarf_Addr lineAddr;
04808 status = dwarf_lineaddr( lineBuffer[i], & lineAddr, NULL );
04809 if ( status != DW_DLV_OK )
04810 {
04811 fprintf(stderr, "%s[%d]: dwarf_lineaddr() failed\n", FILE__, __LINE__);
04812 continue;
04813 }
04814
04815 lineAddr += baseAddr;
04816
04817 if (dwarf->debugLinkFile()) {
04818 Offset new_lineAddr;
04819 bool result = convertDebugOffset(lineAddr, new_lineAddr);
04820 if (result)
04821 lineAddr = new_lineAddr;
04822 }
04823
04824 char * lineSource;
04825 status = dwarf_linesrc( lineBuffer[i], & lineSource, NULL );
04826 if ( status != DW_DLV_OK ) { continue; }
04827
04828 Dwarf_Bool isEndOfSequence;
04829 status = dwarf_lineendsequence( lineBuffer[i], & isEndOfSequence, NULL );
04830 if ( status != DW_DLV_OK ) { continue; }
04831
04832 if ( isPreviousValid )
04833 {
04834
04835
04836
04837 if ( lineNo == previousLineNo && strcmp( lineSource, previousLineSource ) == 0
04838 && ! isEndOfSequence )
04839 {
04840
04841
04842 continue;
04843 }
04844
04845 char *canonicalLineSource;
04846 if (truncateLineFilenames) {
04847 canonicalLineSource = strrchr( previousLineSource, '/' );
04848 if( canonicalLineSource == NULL ) { canonicalLineSource = previousLineSource; }
04849 else { ++canonicalLineSource; }
04850 }
04851 else {
04852 canonicalLineSource = previousLineSource;
04853 }
04854
04855
04856
04857 Dyninst::Offset startAddrToUse = previousLineAddr;
04858 Dyninst::Offset endAddrToUse = lineAddr;
04859
04860 if (startAddrToUse && endAddrToUse)
04861 {
04862
04863
04864 li[std::string(moduleName)].addLine(canonicalLineSource,
04865 (unsigned int) previousLineNo,
04866 (unsigned int) previousLineColumn,
04867 startAddrToUse,
04868 endAddrToUse );
04869 }
04870
04871 }
04872
04873
04874 if ( isEndOfSequence )
04875 {
04876 dwarf_dealloc( dbg, lineSource, DW_DLA_STRING );
04877 isPreviousValid = false;
04878 }
04879 else {
04880 if( isPreviousValid ) { dwarf_dealloc( dbg, previousLineSource, DW_DLA_STRING ); }
04881 previousLineNo = lineNo;
04882 previousLineSource = lineSource;
04883 previousLineAddr = lineAddr;
04884 previousLineColumn = lineOff;
04885
04886 isPreviousValid = true;
04887 }
04888 }
04889
04890
04891 for ( int i = 0; i < lineCount; i++ ) {
04892 dwarf_dealloc( dbg, lineBuffer[i], DW_DLA_LINE );
04893 }
04894 dwarf_dealloc( dbg, lineBuffer, DW_DLA_LIST );
04895 if (cuName)
04896 dwarf_dealloc( dbg, cuName, DW_DLA_STRING );
04897
04898
04899 dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
04900 }
04901
04902 }
04903
04904 void Object::parseFileLineInfo(Symtab *st, dyn_hash_map<string, LineInformation> &li)
04905 {
04906 parseStabFileLineInfo(st, li);
04907 parseDwarfFileLineInfo(li);
04908 }
04909
04910 void Object::parseTypeInfo(Symtab *obj)
04911 {
04912 #if defined(TIMED_PARSE)
04913 struct timeval starttime;
04914 gettimeofday(&starttime, NULL);
04915 #endif
04916
04917 parseStabTypes(obj);
04918
04919 DwarfWalker walker(obj, *(dwarf->type_dbg()));
04920 walker.parse();
04921
04922
04923 #if defined(TIMED_PARSE)
04924 struct timeval endtime;
04925 gettimeofday(&endtime, NULL);
04926 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
04927 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
04928 unsigned long difftime = lendtime - lstarttime;
04929 double dursecs = difftime/(1000 );
04930 cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< obj->file()
04931 <<") took "<< dursecs <<" msecs" << endl;
04932 #endif
04933 }
04934
04935 void Object::parseStabTypes(Symtab *obj)
04936 {
04937 types_printf("Entry to parseStabTypes for %s\n", obj->name().c_str());
04938 stab_entry *stabptr = NULL;
04939 const char *next_stabstr = NULL;
04940
04941 unsigned i;
04942 char *modName = NULL;
04943 string temp;
04944 char *ptr = NULL, *ptr2 = NULL, *ptr3 = NULL;
04945 bool parseActive = false;
04946
04947 std::string *currentFunctionName = NULL;
04948 Symbol *commonBlockVar = NULL;
04949 string *commonBlockName = NULL;
04950 typeCommon *commonBlock = NULL;
04951 int mostRecentLinenum = 0;
04952
04953 Module *mod;
04954 typeCollection *tc = NULL;
04955
04956 #if defined(TIMED_PARSE)
04957 struct timeval starttime;
04958 gettimeofday(&starttime, NULL);
04959 unsigned int pss_count = 0;
04960 double pss_dur = 0;
04961 unsigned int src_count = 0;
04962 double src_dur = 0;
04963 unsigned int fun_count = 0;
04964 double fun_dur = 0;
04965 struct timeval t1, t2;
04966 #endif
04967
04968
04969 stabptr = get_stab_info();
04970 if (!stabptr) {
04971 types_printf("\tWarning: no stab ptr, returning immediately\n");
04972 return;
04973 }
04974
04975
04976
04977 next_stabstr = stabptr->getStringBase();
04978 types_printf("\t Parsing %d stab entries\n", stabptr->count());
04979 for (i=0; i<stabptr->count(); i++) {
04980 switch(stabptr->type(i)){
04981 case N_UNDF:
04982
04983
04984 stabptr->setStringBase(next_stabstr);
04985 next_stabstr = stabptr->getStringBase() + stabptr->val(i);
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001 break;
05002
05003 case N_ENDM:
05004 break;
05005
05006 case N_SO:
05007
05008 #ifdef TIMED_PARSE
05009 src_count++;
05010 gettimeofday(&t1, NULL);
05011 #endif
05012 symt_current_func_name = "";
05013 symt_current_mangled_func_name = "";
05014 symt_current_func = NULL;
05015
05016 modName = const_cast<char*>(stabptr->name(i));
05017
05018 ptr = strrchr(modName, '/');
05019
05020 if (ptr) {
05021 ptr++;
05022 modName = ptr;
05023 }
05024 if (obj->findModuleByName(mod, modName)) {
05025 tc = typeCollection::getModTypeCollection(mod);
05026 parseActive = true;
05027 if (!mod) {
05028 fprintf(stderr, "%s[%d]: FIXME\n", FILE__, __LINE__);
05029 }
05030 else if (!tc)
05031 {
05032 fprintf(stderr, "%s[%d]: FIXME\n", FILE__, __LINE__);
05033 }
05034 else
05035 tc->clearNumberedTypes();
05036 }
05037 else {
05038
05039 mod = obj->getDefaultModule();
05040 tc = typeCollection::getModTypeCollection(mod);
05041 types_printf("\t Warning: failed to find module name matching %s, using %s\n", modName, mod->fileName().c_str());
05042 }
05043
05044 #ifdef TIMED_PARSE
05045 gettimeofday(&t2, NULL);
05046 src_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05047
05048 #endif
05049 break;
05050 case N_SLINE:
05051 mostRecentLinenum = stabptr->desc(i);
05052 break;
05053 default:
05054 break;
05055 }
05056 if(parseActive || !is_aout()) {
05057 std::vector<Symbol *> bpfv;
05058 switch(stabptr->type(i)){
05059 case N_FUN:
05060 #ifdef TIMED_PARSE
05061 fun_count++;
05062 gettimeofday(&t1, NULL);
05063 #endif
05064
05065
05066 symt_current_func = NULL;
05067 int currentEntry = i;
05068 int funlen = strlen(stabptr->name(currentEntry));
05069 ptr = new char[funlen+1];
05070 strcpy(ptr, stabptr->name(currentEntry));
05071 while(strlen(ptr) != 0 && ptr[strlen(ptr)-1] == '\\'){
05072 ptr[strlen(ptr)-1] = '\0';
05073 currentEntry++;
05074 strcat(ptr,stabptr->name(currentEntry));
05075 }
05076 char* colonPtr = NULL;
05077 if(currentFunctionName) delete currentFunctionName;
05078 if(!ptr || !(colonPtr = strchr(ptr,':')))
05079 currentFunctionName = NULL;
05080 else {
05081 char* tmp = new char[colonPtr-ptr+1];
05082 strncpy(tmp,ptr,colonPtr-ptr);
05083 tmp[colonPtr-ptr] = '\0';
05084 currentFunctionName = new string(tmp);
05085
05086 std::vector<Symbol *>syms;
05087 if(!obj->findSymbol(syms,
05088 *currentFunctionName,
05089 Symbol::ST_FUNCTION,
05090 mangledName)) {
05091 if(!obj->findSymbol(syms,
05092 "_"+*currentFunctionName,
05093 Symbol::ST_FUNCTION,
05094 mangledName)) {
05095 string fortranName = *currentFunctionName + string("_");
05096 if (obj->findSymbol(syms,
05097 fortranName,
05098 Symbol::ST_FUNCTION,
05099 mangledName)) {
05100 delete currentFunctionName;
05101 currentFunctionName = new string(fortranName);
05102 }
05103 }
05104 }
05105 syms.clear();
05106 delete[] tmp;
05107 }
05108 delete[] ptr;
05109 #ifdef TIMED_PARSE
05110 gettimeofday(&t2, NULL);
05111 fun_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05112
05113 #endif
05114 break;
05115 }
05116 if (!parseActive) continue;
05117 switch(stabptr->type(i)){
05118 case N_BCOMM: {
05119
05120 string tmp = string(stabptr->name(i));
05121 commonBlockName = &tmp;
05122
05123
05124
05125 std::vector<Symbol *>vars;
05126 if(!obj->findSymbol(vars,
05127 *commonBlockName,
05128 Symbol::ST_OBJECT,
05129 mangledName)) {
05130 if(!obj->findSymbol(vars,
05131 *commonBlockName,
05132 Symbol::ST_OBJECT,
05133 mangledName,
05134 true))
05135 commonBlockVar = NULL;
05136 else
05137 commonBlockVar = vars[0];
05138 }
05139 else
05140 commonBlockVar = vars[0];
05141 if (!commonBlockVar) {
05142
05143 } else {
05144 commonBlock = dynamic_cast<typeCommon *>(tc->findVariableType(*commonBlockName));
05145 if (commonBlock == NULL) {
05146
05147 commonBlock = new typeCommon(*commonBlockName);
05148 tc->addGlobalVariable(*commonBlockName, commonBlock);
05149 }
05150
05151 commonBlock->beginCommonBlock();
05152 }
05153 break;
05154 }
05155 case N_ECOMM: {
05156
05157 assert(currentFunctionName);
05158 if(!obj->findSymbol(bpfv,
05159 *currentFunctionName,
05160 Symbol::ST_FUNCTION,
05161 mangledName)) {
05162 if(!obj->findSymbol(bpfv,
05163 *currentFunctionName,
05164 Symbol::ST_FUNCTION,
05165 mangledName,
05166 true)){
05167
05168 }
05169 else{
05170 Symbol *func = bpfv[0];
05171 commonBlock->endCommonBlock(func, (void *)commonBlockVar->getOffset());
05172 }
05173 } else {
05174 if (bpfv.size() > 1) {
05175
05176
05177
05178 }
05179 Symbol *func = bpfv[0];
05180 commonBlock->endCommonBlock(func, (void *)commonBlockVar->getOffset());
05181 }
05182
05183
05184
05185
05186 commonBlockVar = NULL;
05187 commonBlock = NULL;
05188 break;
05189 }
05190
05191
05192 case 32:
05193 case 38:
05194 case N_FUN:
05195 case 128:
05196 case 160:
05197 case 0xc6:
05198 case 0xc8:
05199 #ifdef TIMED_PARSE
05200 pss_count++;
05201 gettimeofday(&t1, NULL);
05202 #endif
05203 if (stabptr->type(i) == N_FUN) symt_current_func = NULL;
05204 ptr = const_cast<char *>(stabptr->name(i));
05205 while (ptr[strlen(ptr)-1] == '\\') {
05206
05207 ptr2 = const_cast<char *>(stabptr->name(i+1));
05208 ptr3 = (char *) malloc(strlen(ptr) + strlen(ptr2) + 1);
05209 strcpy(ptr3, ptr);
05210 ptr3[strlen(ptr)-1] = '\0';
05211 strcat(ptr3, ptr2);
05212 ptr = ptr3;
05213 i++;
05214
05215 }
05216
05217
05218
05219 if (parseCompilerType(this))
05220 temp = parseStabString(mod, mostRecentLinenum, (char *)ptr, stabptr->val(i), commonBlock);
05221 else
05222 temp = parseStabString(mod, stabptr->desc(i), (char *)ptr, stabptr->val(i), commonBlock);
05223 if (temp.length()) {
05224
05225
05226
05227
05228 }
05229 #ifdef TIMED_PARSE
05230 gettimeofday(&t2, NULL);
05231 pss_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
05232
05233 #endif
05234 break;
05235 default:
05236 break;
05237 }
05238 }
05239 }
05240 #if defined(TIMED_PARSE)
05241 struct timeval endtime;
05242 gettimeofday(&endtime, NULL);
05243 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
05244 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
05245 unsigned long difftime = lendtime - lstarttime;
05246 double dursecs = difftime/(1000 );
05247 cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName()
05248 <<") took "<<dursecs <<" msecs" << endl;
05249 cout << "Breakdown:" << endl;
05250 cout << " Functions: " << fun_count << " took " << fun_dur << "msec" << endl;
05251 cout << " Sources: " << src_count << " took " << src_dur << "msec" << endl;
05252 cout << " parseStabString: " << pss_count << " took " << pss_dur << "msec" << endl;
05253 cout << " Total: " << pss_dur + fun_dur + src_dur
05254 << " msec" << endl;
05255 #endif
05256 }
05257
05258 bool sort_dbg_map(const Object::DbgAddrConversion_t &a,
05259 const Object::DbgAddrConversion_t &b)
05260 {
05261 return (a.dbg_offset < b.dbg_offset);
05262 }
05263
05264 bool Object::convertDebugOffset(Offset off, Offset &new_off)
05265 {
05266 if (!DbgSectionMapSorted) {
05267 std::sort(DebugSectionMap.begin(), DebugSectionMap.end(), sort_dbg_map);
05268 DbgSectionMapSorted = true;
05269 }
05270
05271 int hi = DebugSectionMap.size();
05272 int low = 0;
05273 int cur = -1;
05274
05275 for (;;) {
05276 int last_cur = cur;
05277 cur = (low + hi) / 2;
05278 if (cur == last_cur) {
05279 new_off = off;
05280 return true;
05281 }
05282
05283 const DbgAddrConversion_t &cur_d = DebugSectionMap[cur];
05284
05285 if (off >= cur_d.dbg_offset && off < cur_d.dbg_offset+cur_d.dbg_size) {
05286 new_off = off - cur_d.dbg_offset + cur_d.orig_offset;
05287 return true;
05288 }
05289 else if (off > cur_d.dbg_offset)
05290 {
05291 low = cur;
05292 }
05293 else if (off < cur_d.dbg_offset)
05294 {
05295 hi = cur;
05296 }
05297 }
05298
05299 }
05300
05301 void Object::insertPrereqLibrary(std::string libname)
05302 {
05303 prereq_libs.insert(libname);
05304 }
05305
05306 bool Object::removePrereqLibrary(std::string libname)
05307 {
05308 rmd_deps.push_back(libname);
05309 return true;
05310 }
05311
05312 std::vector<std::string> &Object::libsRMd()
05313 {
05314 return rmd_deps;
05315 }
05316
05317 void Object::insertDynamicEntry(long name, long value)
05318 {
05319 new_dynamic_entries.push_back(std::pair<long, long>(name, value));
05320 }
05321
05322
05323
05324 bool Object::parse_all_relocations(Elf_X &elf, Elf_X_Shdr *dynsym_scnp,
05325 Elf_X_Shdr *dynstr_scnp, Elf_X_Shdr *symtab_scnp,
05326 Elf_X_Shdr *strtab_scnp) {
05327
05328
05329
05330 Offset dynsym_offset = 0;
05331 Elf_X_Data dynsym_data, dynstr_data;
05332 Elf_X_Sym dynsym;
05333 const char *dynstr = NULL;
05334 if( dynsym_scnp && dynstr_scnp ) {
05335 dynsym_offset = dynsym_scnp->sh_offset();
05336 dynsym_data = dynsym_scnp->get_data();
05337 dynstr_data = dynstr_scnp->get_data();
05338 if( !(dynsym_data.isValid() && dynstr_data.isValid()) ) {
05339 return false;
05340 }
05341 dynsym = dynsym_data.get_sym();
05342 dynstr = dynstr_data.get_string();
05343 }
05344
05345 Offset symtab_offset = 0;
05346 Elf_X_Data symtab_data, strtab_data;
05347 Elf_X_Sym symtab;
05348 const char *strtab = NULL;
05349 if( symtab_scnp && strtab_scnp) {
05350 symtab_offset = symtab_scnp->sh_offset();
05351 symtab_data = symtab_scnp->get_data();
05352 strtab_data = strtab_scnp->get_data();
05353 if( !(symtab_data.isValid() && strtab_data.isValid()) ) {
05354 return false;
05355 }
05356 symtab = symtab_data.get_sym();
05357 strtab = strtab_data.get_string();
05358 }
05359
05360 if( dynstr == NULL && strtab == NULL ) return false;
05361
05362
05363
05364
05365
05366 dyn_hash_map<int, Symbol *> symtabByIndex;
05367 dyn_hash_map<int, Symbol *> dynsymByIndex;
05368
05369 dyn_hash_map<std::string, std::vector<Symbol *> >::iterator symVec_it;
05370 for(symVec_it = symbols_.begin(); symVec_it != symbols_.end(); ++symVec_it) {
05371 std::vector<Symbol *>::iterator sym_it;
05372 for(sym_it = symVec_it->second.begin(); sym_it != symVec_it->second.end(); ++sym_it) {
05373
05374 if( (*sym_it)->getIndex() == STN_UNDEF ) {
05375 continue;
05376 }
05377 if( (*sym_it)->tag() == Symbol::TAG_INTERNAL ) {
05378 continue;
05379 }
05380
05381 std::pair<dyn_hash_map<int, Symbol *>::iterator, bool> result;
05382 if( (*sym_it)->isInDynSymtab() ) {
05383 result = dynsymByIndex.insert(std::make_pair((*sym_it)->getIndex(), (*sym_it)));
05384 }else{
05385 result = symtabByIndex.insert(std::make_pair((*sym_it)->getIndex(), (*sym_it)));
05386 }
05387
05388
05389 assert(result.second);
05390 }
05391 }
05392
05393
05394 std::vector<Region *>::iterator reg_it;
05395 dyn_hash_map<unsigned, Region *> shToRegion;
05396 for(reg_it = regions_.begin(); reg_it != regions_.end(); ++reg_it) {
05397 std::pair<dyn_hash_map<unsigned, Region *>::iterator, bool> result;
05398 result = shToRegion.insert(std::make_pair((*reg_it)->getRegionNumber(), (*reg_it)));
05399 }
05400
05401 for(unsigned i = 0; i < elf.e_shnum(); ++i) {
05402 Elf_X_Shdr *shdr = allRegionHdrsByShndx[i];
05403 if( shdr->sh_type() != SHT_REL && shdr->sh_type() != SHT_RELA ) continue;
05404
05405 Elf_X_Data reldata = shdr->get_data();
05406 Elf_X_Rel rel = reldata.get_rel();
05407 Elf_X_Rela rela = reldata.get_rela();
05408
05409 Elf_X_Shdr *curSymHdr = allRegionHdrsByShndx[shdr->sh_link()];
05410
05411
05412
05413 for(unsigned j = 0; j < (shdr->sh_size() / shdr->sh_entsize()); ++j) {
05414
05415
05416 Offset relOff, addend = 0;
05417 std::string name;
05418 unsigned long relType;
05419 Region::RegionType regType;
05420
05421 long symbol_index;
05422 switch(shdr->sh_type()) {
05423 case SHT_REL:
05424 relType = rel.R_TYPE(j);
05425 relOff = rel.r_offset(j);
05426 symbol_index = rel.R_SYM(j);
05427 regType = Region::RT_REL;
05428 break;
05429 case SHT_RELA:
05430 relType = rela.R_TYPE(j);
05431 relOff = rela.r_offset(j);
05432 symbol_index = rela.R_SYM(j);
05433 regType = Region::RT_RELA;
05434 addend = rela.r_addend(j);
05435 break;
05436 default:
05437 continue;
05438 }
05439
05440
05441 Symbol *sym = NULL;
05442
05443 if( dynstr && curSymHdr->sh_offset() == dynsym_offset ) {
05444 name = string( &dynstr[dynsym.st_name(symbol_index)] );
05445
05446 dyn_hash_map<int, Symbol *>::iterator sym_it;
05447 sym_it = dynsymByIndex.find(symbol_index);
05448 if( sym_it != dynsymByIndex.end() ) {
05449 sym = sym_it->second;
05450 if(sym->getType() == Symbol::ST_SECTION) {
05451 name = sym->getRegion()->getRegionName().c_str();
05452 }
05453 }
05454 }else if( strtab && curSymHdr->sh_offset() == symtab_offset ) {
05455 name = string( &strtab[symtab.st_name(symbol_index)] );
05456 dyn_hash_map<int, Symbol *>::iterator sym_it;
05457 sym_it = symtabByIndex.find(symbol_index);
05458 if( sym_it != symtabByIndex.end() ) {
05459 sym = sym_it->second;
05460 if(sym->getType() == Symbol::ST_SECTION) {
05461 name = sym->getRegion()->getRegionName().c_str();
05462 }
05463 }
05464 }
05465
05466 Region *region = NULL;
05467 dyn_hash_map<unsigned, Region *>::iterator shToReg_it;
05468 shToReg_it = shToRegion.find(i);
05469 if( shToReg_it != shToRegion.end() ) {
05470 region = shToReg_it->second;
05471 }
05472
05473 assert(region != NULL);
05474
05475 relocationEntry newrel(0, relOff, addend, name, sym, relType, regType);
05476 region->addRelocationEntry(newrel);
05477
05478
05479 if (sym) {
05480 if (shdr->sh_info() != 0) {
05481 Region *targetRegion = NULL;
05482 shToReg_it = shToRegion.find(shdr->sh_info());
05483 if( shToReg_it != shToRegion.end() ) {
05484 targetRegion = shToReg_it->second;
05485 }
05486 assert(targetRegion != NULL);
05487 targetRegion->addRelocationEntry(newrel);
05488 }
05489 }
05490
05491 }
05492 }
05493
05494 return true;
05495 }
05496
05497 bool Region::isStandardCode()
05498 {
05499 return ((getRegionPermissions() == RP_RX || getRegionPermissions() == RP_RWX) &&
05500 ((name_ == std::string(".text")) ||
05501 (name_ == std::string(".init")) ||
05502 (name_ == std::string(".fini"))));
05503 }
05504
05505 void Object::setTruncateLinePaths(bool value)
05506 {
05507 truncateLineFilenames = value;
05508 }
05509
05510 bool Object::getTruncateLinePaths()
05511 {
05512 return truncateLineFilenames;
05513 }
05514
05515 Dyninst::Architecture Object::getArch()
05516 {
05517 #if defined(arch_power)
05518 if (getAddressWidth() == 4) {
05519 return Dyninst::Arch_ppc32;
05520 }
05521 return Dyninst::Arch_ppc64;
05522 #elif defined(arch_x86) || defined(arch_x86_64)
05523 if (getAddressWidth() == 4) {
05524 return Dyninst::Arch_x86;
05525 }
05526 return Dyninst::Arch_x86_64;
05527 #else
05528 return Arch_none;
05529 #endif
05530 }
05531
05532 Offset Object::getTOCoffset(Offset off) const {
05533 if (TOC_table_.empty()) return 0;
05534 Offset baseTOC = TOC_table_.find(0)->second;
05535
05536
05537
05538 std::map<Offset, Offset>::const_iterator iter = TOC_table_.find(off);
05539 if (iter == TOC_table_.end()) {
05540 return baseTOC;
05541 }
05542 return iter->second;
05543 }
05544
05545 void Object::setTOCoffset(Offset off) {
05546 TOC_table_.clear();
05547 TOC_table_[0] = off;
05548 }
05549
05550 void Object::getSegmentsSymReader(vector<SymSegment> &segs) {
05551 for (unsigned i = 0; i < elfHdr->e_phnum(); ++i) {
05552 Elf_X_Phdr &phdr = elfHdr->get_phdr(i);
05553
05554 SymSegment seg;
05555 seg.file_offset = phdr.p_offset();
05556 seg.mem_addr = phdr.p_vaddr();
05557 seg.file_size = phdr.p_filesz();
05558 seg.mem_size = phdr.p_memsz();
05559 seg.type = phdr.p_type();
05560 seg.perms = phdr.p_flags() & 0x7;
05561
05562 segs.push_back(seg);
05563 }
05564 }