/* * Copyright (c) 2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "cpu/profile.hh" #include #include "base/callback.hh" #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" namespace gem5 { void BaseStackTrace::dump() { StringWrap name(tc->getCpuPtr()->name()); auto *symtab = &tc->getSystemPtr()->workload->symtab(tc); DPRINTFN("------ Stack ------\n"); std::string symbol; for (int i = 0, size = stack.size(); i < size; ++i) { Addr addr = stack[size - i - 1]; getSymbol(symbol, addr, symtab); DPRINTFN("%#x: %s\n", addr, symbol); } } bool BaseStackTrace::tryGetSymbol(std::string &symbol, Addr addr, const loader::SymbolTable *symtab) { const auto it = symtab->find(addr); if (it == symtab->end()) return false; symbol = it->name; return true; } void ProfileNode::dump(const std::string &symbol, uint64_t id, const FunctionProfile &prof, std::ostream &os) const { ccprintf(os, "%#x %s %d ", id, symbol, count); for (const auto &p: children) ccprintf(os, "%#x ", (intptr_t)(p.second)); ccprintf(os, "\n"); for (const auto &p: children) { Addr addr = p.first; std::string symbol; prof.trace->getSymbol(symbol, addr, &prof.symtab); const auto *node = p.second; node->dump(symbol, (intptr_t)node, prof, os); } } void ProfileNode::clear() { count = 0; for (const auto &p: children) p.second->clear(); } FunctionProfile::FunctionProfile(std::unique_ptr _trace, const loader::SymbolTable &_symtab) : symtab(_symtab), trace(std::move(_trace)) { statistics::registerResetCallback([this]() { clear(); }); } ProfileNode * FunctionProfile::consume(const std::vector &stack) { ProfileNode *current = ⊤ for (int i = 0, size = stack.size(); i < size; ++i) { ProfileNode *&ptr = current->children[stack[size - i - 1]]; if (!ptr) ptr = new ProfileNode; current = ptr; } return current; } void FunctionProfile::clear() { top.clear(); pc_count.clear(); } void FunctionProfile::dump(std::ostream &os) const { ccprintf(os, ">>>PC data\n"); for (const auto &p: pc_count) { Addr pc = p.first; Counter count = p.second; std::string symbol; if (trace->tryGetSymbol(symbol, pc, &symtab)) ccprintf(os, "%s %d\n", symbol, count); else ccprintf(os, "%#x %d\n", pc, count); } ccprintf(os, ">>>function data\n"); top.dump("top", 0, *this, os); } void FunctionProfile::sample(ProfileNode *node, Addr pc) { node->count++; auto it = symtab.findNearest(pc); if (it != symtab.end()) { pc_count[it->address]++; } else { // record PC even if we don't have a symbol to avoid // silently biasing the histogram pc_count[pc]++; } } } // namespace gem5