string Alien::toXML(uint oFlags) const { string self = ANode::toXML(oFlags) + " f" + MakeAttrStr(m_filenm) + " n" + MakeAttrStr(m_displaynm); self = self + " " + XMLLineRange(oFlags) + " " + XMLVMAIntervals(oFlags); // add information on the function definition // If the alien has an ancestor and the same procedure definition exists, // we'll add an attribute 'ln' to point to the ID of the function definition. // This is needed to inform hpcprof that the alien shouldn't be considered // as different function. // 1a: get the load module of the alien LM *lm = ancestorLM(); // 1b: check if the alien has the file pointer to its definition File *file = lm->findFile(m_filenm); if (file) { // 2: check if there's the same procedure name in the file Proc *proc = file->findProc(m_displaynm); if (proc) { #if 0 // 3: check if alien's line range is within the function definition bool inc = SrcFile::include(proc->begLine(), proc->endLine(), begLine(), endLine()); if (inc) { // 4: add the link attribute to the function definition self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id())); } #endif self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id())); } } return self; }
void BinUtil::TextSeg::ctor_initProcs() { Dbg::LM* dbgInfo = m_lm->getDebugInfo(); // Any procedure with a parent has a <Proc*, parentVMA> entry std::map<Proc*, VMA> parentMap; // ------------------------------------------------------------ // Each text section finds and creates its own routines. // Traverse the symbol table (which is sorted by VMA) searching // for function symbols in our section. Create a Proc for // each one found. // // Note that symbols can appear multiple times (e.g. a weak symbol // 'sbrk' along with a gloabl symbol '__sbrk'), but we should not // have multiple procedures. // ------------------------------------------------------------ bfd* abfd = m_lm->abfd(); asymbol** symtab = m_lm->bfdSymTab(); // sorted uint symtabSz = m_lm->bfdSymTabSz(); // FIXME:PERF: exploit sortedness of 'symtab' to start iteration for (uint i = 0; i < symtabSz; i++) { asymbol* sym = symtab[i]; if (isIn(bfd_asymbol_value(sym)) && Proc::isProcBFDSym(sym)) { // NOTE: initially we have [begVMA, endVMA) where endVMA is the // *end* of the last insn. This is changed after decoding below. VMA begVMA = bfd_asymbol_value(sym); VMA endVMA = 0; Proc::Type procType; if (sym->flags & BSF_LOCAL) { procType = Proc::Local; } else if (sym->flags & BSF_WEAK) { procType = Proc::Weak; } else if (sym->flags & BSF_GLOBAL) { procType = Proc::Global; } else { procType = Proc::Unknown; } Proc* proc = m_lm->findProc(begVMA); if (proc) { DIAG_Assert(proc->begVMA() == begVMA, "TextSeg::ctor_initProcs: Procedure beginning at 0x" << hex << begVMA << " overlaps with:\n" << proc->toString()); if (procType == Proc::Global) { // 'global' types take precedence proc->type(procType); } continue; } // Create a procedure based on best information we have. We // always prefer explicit debug information over that inferred // from the symbol table. string procNm; string symNm = bfd_asymbol_name(sym); Dbg::LM::iterator it = dbgInfo->find(begVMA); Dbg::Proc* dbg = (it != dbgInfo->end()) ? it->second : NULL; if (!dbg) { procNm = findProcName(abfd, sym); string pnm = BinUtil::canonicalizeProcName(procNm); Dbg::LM::iterator1 it1 = dbgInfo->find1(pnm); dbg = (it1 != dbgInfo->end1()) ? it1->second : NULL; } if (!dbg) { Dbg::LM::iterator1 it1 = dbgInfo->find1(symNm); dbg = (it1 != dbgInfo->end1()) ? it1->second : NULL; } // Finding the end VMA (end of last insn). The computation is // as follows because sometimes the debug information is // *wrong*. (Intel 9 has generated significant over-estimates). // // N.B. exploits the fact that the symbol table is sorted by vma VMA endVMA_approx = findProcEnd(i); if (dbg) { if (!dbg->name.empty()) { procNm = dbg->name; } else if (!symNm.empty()) { // sometimes a procedure name is in the symbol table even // though it is not in the dwarf section. this case occurs // when gcc outlines routines from OpenMP parallel sections. procNm = symNm; } #if 1 // Remove capability below... the DWARF sizes can be wrong!! endVMA = endVMA_approx; #else endVMA = std::min(dbg->endVMA, endVMA_approx); if (endVMA != endVMA_approx) { int64_t diff = endVMA - endVMA_approx; DIAG_DevMsg(0, procNm << ": inconsistent end VMA: " << diff << " [" << std::showbase << std::hex << begVMA << "-" << endVMA << "/" << endVMA_approx << std::dec << "]"); } #endif } if (!dbg || endVMA == 0) { endVMA = endVMA_approx; } uint size = endVMA - begVMA; if (size == 0) { continue; } // We now have a valid procedure. Initilize with [begVMA, endVMA), // but note this is changed after disassembly. proc = new Proc(this, procNm, symNm, procType, begVMA, endVMA, size); m_procs.push_back(proc); m_lm->insertProc(VMAInterval(begVMA, endVMA), proc); // Add symbolic info if (dbg) { proc->filename(dbg->filenm); proc->begLine(dbg->begLine); if (dbg->parent) { parentMap.insert(std::make_pair(proc, dbg->parent->begVMA)); } } } } // ------------------------------------------------------------ // If a text section does not have any function symbols, consider // the whole section a quasi procedure // ------------------------------------------------------------ if (numProcs() == 0) { // [begVMA, endVMA) Proc* proc = new Proc(this, name(), name(), Proc::Quasi, begVMA(), endVMA(), size()); m_procs.push_back(proc); m_lm->insertProc(VMAInterval(begVMA(), endVMA()), proc); } // ------------------------------------------------------------ // Embed parent information // ------------------------------------------------------------ for (std::map<Proc*, VMA>::iterator it = parentMap.begin(); it != parentMap.end(); ++it) { Proc* child = it->first; VMA parentVMA = it->second; Proc* parent = m_lm->findProc(parentVMA); DIAG_AssertWarn(parent, "Could not find parent within this section:\n" << child->toString()); if (parent == child) { DIAG_WMsg(0, "Procedure has itself as parent!\n" << child->toString()); continue; // skip } child->parent(parent); } }