arch,base,cpu,kern,sim: Encapsulate symbols in a class.
The SymbolTable class had been tracking symbols as two independent pieces, a name and an address, and acted as a way to translate between them. Symbols can be more complex than that, and so this change encapsulates the information associated with a symbol in a new class. As a step towards simplifying the API for reading symbols from a binary, this change also adds a "binding" field to that class so that global, local and weak symbols can all go in the same table and be differentiated later as needed. That should unify the current API which has a method for each symbol type. While the innards of SymbolTable were being reworked, this change also makes that class more STL like by adding iterators, and begin and end methods. These iterate over a new vector which holds all the symbols. The address and name keyed maps now hold indexes into that vector instead of the other half of the symbol. Change-Id: I8084f86fd737f697ec041bac86a635a315fd1194 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24784 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -88,8 +88,7 @@ FsFreebsd::initState()
|
||||
|
||||
// Check if the kernel image has a symbol that tells us it supports
|
||||
// device trees.
|
||||
Addr addr;
|
||||
fatal_if(!kernelSymtab->findAddress("fdt_get_range", addr),
|
||||
fatal_if(kernelSymtab->find("fdt_get_range") == kernelSymtab->end(),
|
||||
"Kernel must have fdt support.");
|
||||
fatal_if(params()->dtb_filename == "", "dtb file is not specified.");
|
||||
|
||||
|
||||
@@ -393,18 +393,19 @@ void
|
||||
ArmStaticInst::printTarget(std::ostream &os, Addr target,
|
||||
const Loader::SymbolTable *symtab) const
|
||||
{
|
||||
Addr symbolAddr;
|
||||
std::string symbol;
|
||||
|
||||
if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
|
||||
ccprintf(os, "<%s", symbol);
|
||||
if (symbolAddr != target)
|
||||
ccprintf(os, "+%d>", target - symbolAddr);
|
||||
else
|
||||
ccprintf(os, ">");
|
||||
} else {
|
||||
ccprintf(os, "%#x", target);
|
||||
if (symtab) {
|
||||
auto it = symtab->findNearest(target);
|
||||
if (it != symtab->end()) {
|
||||
ccprintf(os, "<%s", it->name);
|
||||
Addr delta = target - it->address;
|
||||
if (delta)
|
||||
ccprintf(os, "+%d>", delta);
|
||||
else
|
||||
ccprintf(os, ">");
|
||||
return;
|
||||
}
|
||||
}
|
||||
ccprintf(os, "%#x", target);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -477,13 +478,14 @@ ArmStaticInst::printMemSymbol(std::ostream &os,
|
||||
const Addr addr,
|
||||
const std::string &suffix) const
|
||||
{
|
||||
Addr symbolAddr;
|
||||
std::string symbol;
|
||||
if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
|
||||
ccprintf(os, "%s%s", prefix, symbol);
|
||||
if (symbolAddr != addr)
|
||||
ccprintf(os, "+%d", addr - symbolAddr);
|
||||
ccprintf(os, suffix);
|
||||
if (symtab) {
|
||||
auto it = symtab->findNearest(addr);
|
||||
if (it != symtab->end()) {
|
||||
ccprintf(os, "%s%s", prefix, it->name);
|
||||
if (it->address != addr)
|
||||
ccprintf(os, "+%d", addr - it->address);
|
||||
ccprintf(os, suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +82,10 @@ FsLinux::initState()
|
||||
}
|
||||
|
||||
// Setup boot data structure
|
||||
Addr addr;
|
||||
// Check if the kernel image has a symbol that tells us it supports
|
||||
// device trees.
|
||||
bool kernel_has_fdt_support =
|
||||
kernelSymtab->findAddress("unflatten_device_tree", addr);
|
||||
kernelSymtab->find("unflatten_device_tree") != kernelSymtab->end();
|
||||
bool dtb_file_specified = params()->dtb_filename != "";
|
||||
|
||||
if (kernel_has_fdt_support && dtb_file_specified) {
|
||||
|
||||
@@ -47,11 +47,10 @@ readSymbol(ThreadContext *tc, const std::string name)
|
||||
PortProxy &vp = tc->getVirtProxy();
|
||||
const auto *symtab = tc->getSystemPtr()->workload->symtab(tc);
|
||||
|
||||
Addr addr;
|
||||
if (!symtab->findAddress(name, addr))
|
||||
panic("thread info not compiled into kernel\n");
|
||||
auto it = symtab->find(name);
|
||||
panic_if(it == symtab->end(), "Thread info not compiled into kernel.");
|
||||
|
||||
return vp.read<int32_t>(addr, GuestByteOrder);
|
||||
return vp.read<int32_t>(it->address, GuestByteOrder);
|
||||
}
|
||||
|
||||
ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
|
||||
|
||||
@@ -46,15 +46,16 @@ class ThreadInfo
|
||||
bool
|
||||
get_data(const char *symbol, T &data)
|
||||
{
|
||||
Addr addr = 0;
|
||||
if (!sys->workload->symtab(tc)->findAddress(symbol, addr)) {
|
||||
auto *symtab = sys->workload->symtab(tc);
|
||||
auto it = symtab->find(symbol);
|
||||
if (it == symtab->end()) {
|
||||
warn_once("Unable to find kernel symbol %s\n", symbol);
|
||||
warn_once("Kernel not compiled with task_struct info; can't get "
|
||||
"currently executing task/process/thread name/ids!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
data = tc->getVirtProxy().read<T>(addr, TheISA::GuestByteOrder);
|
||||
data = tc->getVirtProxy().read<T>(it->address, TheISA::GuestByteOrder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -193,11 +193,11 @@ output decoder {{
|
||||
|
||||
Addr target = pc + 4 + disp;
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(target, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(target)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", target);
|
||||
ccprintf(ss, "%#x", target);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -213,9 +213,9 @@ output decoder {{
|
||||
Addr npc = pc + 4;
|
||||
ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
|
||||
} else if (_numSrcRegs == 0) {
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(disp, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(disp)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", disp);
|
||||
} else if (_numSrcRegs == 1) {
|
||||
|
||||
@@ -68,11 +68,11 @@ BranchPCRel::generateDisassembly(
|
||||
|
||||
Addr target = pc + disp;
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(target, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(target)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", target);
|
||||
ccprintf(ss, "%#x", target);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -91,11 +91,11 @@ BranchNonPCRel::generateDisassembly(
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(targetAddr, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(targetAddr)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", targetAddr);
|
||||
ccprintf(ss, "%#x", targetAddr);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -118,11 +118,11 @@ BranchPCRelCond::generateDisassembly(
|
||||
|
||||
Addr target = pc + disp;
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(target, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(target)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", target);
|
||||
ccprintf(ss, "%#x", target);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -143,11 +143,11 @@ BranchNonPCRelCond::generateDisassembly(
|
||||
|
||||
ss << bo << ", " << bi << ", ";
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(targetAddr, str))
|
||||
ss << str;
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->find(targetAddr)) != symtab->end())
|
||||
ss << it->name;
|
||||
else
|
||||
ccprintf(ss, "0x%x", targetAddr);
|
||||
ccprintf(ss, "%#x", targetAddr);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@ class BareMetal : public RiscvISA::FsWorkload
|
||||
return bootloaderSymtab;
|
||||
}
|
||||
bool
|
||||
insertSymbol(Addr address, const std::string &symbol) override
|
||||
insertSymbol(const Loader::Symbol &symbol) override
|
||||
{
|
||||
return bootloaderSymtab->insert(address, symbol);
|
||||
return bootloaderSymtab->insert(symbol);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ class FsWorkload : public Workload
|
||||
}
|
||||
|
||||
bool
|
||||
insertSymbol(Addr address, const std::string &symbol) override
|
||||
insertSymbol(const Loader::Symbol &symbol) override
|
||||
{
|
||||
return defaultSymtab.insert(address, symbol);
|
||||
return defaultSymtab.insert(symbol);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -77,18 +77,17 @@ BranchDisp::generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
std::string symbol;
|
||||
Addr symbol_addr;
|
||||
|
||||
Addr target = disp + pc;
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
ccprintf(response, "0x%x", target);
|
||||
ccprintf(response, "%#x", target);
|
||||
|
||||
if (symtab && symtab->findNearestSymbol(target, symbol, symbol_addr)) {
|
||||
ccprintf(response, " <%s", symbol);
|
||||
if (symbol_addr != target)
|
||||
ccprintf(response, "+%d>", target - symbol_addr);
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (symtab && (it = symtab->findNearest(target)) != symtab->end()) {
|
||||
ccprintf(response, " <%s", it->name);
|
||||
if (it->address != target)
|
||||
ccprintf(response, "+%d>", target - it->address);
|
||||
else
|
||||
ccprintf(response, ">");
|
||||
}
|
||||
|
||||
@@ -47,11 +47,10 @@ readSymbol(ThreadContext *tc, const std::string name)
|
||||
PortProxy &vp = tc->getVirtProxy();
|
||||
const auto *symtab = tc->getSystemPtr()->workload->symtab(tc);
|
||||
|
||||
Addr addr;
|
||||
if (!symtab->findAddress(name, addr))
|
||||
panic("thread info not compiled into kernel\n");
|
||||
auto it = symtab->find(name);
|
||||
panic_if(it == symtab->end(), "Thread info not compiled into kernel.");
|
||||
|
||||
return vp.read<int32_t>(addr, GuestByteOrder);
|
||||
return vp.read<int32_t>(it->address, GuestByteOrder);
|
||||
}
|
||||
|
||||
ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
|
||||
@@ -196,14 +195,15 @@ StackTrace::dump()
|
||||
std::string symbol;
|
||||
for (int i = 0, size = stack.size(); i < size; ++i) {
|
||||
Addr addr = stack[size - i - 1];
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (addr == user)
|
||||
symbol = "user";
|
||||
else if (addr == console)
|
||||
symbol = "console";
|
||||
else if (addr == unknown)
|
||||
symbol = "unknown";
|
||||
else
|
||||
symtab->findSymbol(addr, symbol);
|
||||
else if ((it = symtab->find(addr)) != symtab->end())
|
||||
symbol = it->name;
|
||||
|
||||
DPRINTFN("%#x: %s\n", addr, symbol);
|
||||
}
|
||||
|
||||
@@ -341,7 +341,23 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
|
||||
elf_strptr(elf, shdr.sh_link, sym.st_name);
|
||||
if (sym_name && sym_name[0] != '$') {
|
||||
Addr value = sym.st_value - base + offset;
|
||||
if (symtab->insert(value & mask, sym_name)) {
|
||||
Loader::Symbol symbol;
|
||||
symbol.address = value & mask;
|
||||
symbol.name = sym_name;
|
||||
switch (binding) {
|
||||
case STB_GLOBAL:
|
||||
symbol.binding = Loader::Symbol::Binding::Global;
|
||||
break;
|
||||
case STB_LOCAL:
|
||||
symbol.binding = Loader::Symbol::Binding::Local;
|
||||
break;
|
||||
case STB_WEAK:
|
||||
symbol.binding = Loader::Symbol::Binding::Weak;
|
||||
break;
|
||||
default:
|
||||
panic("Unrecognized binding type");
|
||||
}
|
||||
if (symtab->insert(symbol)) {
|
||||
DPRINTF(Loader, "Symbol: %-40s value %#x\n",
|
||||
sym_name, value);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "base/str.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "base/types.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
@@ -48,26 +49,48 @@ SymbolTable *debugSymbolTable = NULL;
|
||||
void
|
||||
SymbolTable::clear()
|
||||
{
|
||||
addrTable.clear();
|
||||
symbolTable.clear();
|
||||
addrMap.clear();
|
||||
nameMap.clear();
|
||||
symbols.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolTable::insert(Addr address, string symbol)
|
||||
SymbolTable::insert(const Symbol &symbol)
|
||||
{
|
||||
if (symbol.empty())
|
||||
if (symbol.name.empty())
|
||||
return false;
|
||||
|
||||
if (!symbolTable.insert(make_pair(symbol, address)).second)
|
||||
int idx = symbols.size();
|
||||
|
||||
if (!nameMap.insert({ symbol.name, idx }).second)
|
||||
return false;
|
||||
|
||||
// There can be multiple symbols for the same address, so always
|
||||
// update the addrTable multimap when we see a new symbol name.
|
||||
addrTable.insert(make_pair(address, symbol));
|
||||
addrMap.insert({ symbol.address, idx });
|
||||
|
||||
symbols.emplace_back(symbol);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolTable::insert(const SymbolTable &other)
|
||||
{
|
||||
// Check if any symbol in other already exists in our table.
|
||||
NameMap intersection;
|
||||
std::set_intersection(other.nameMap.begin(), other.nameMap.end(),
|
||||
nameMap.begin(), nameMap.end(),
|
||||
std::inserter(intersection, intersection.begin()),
|
||||
nameMap.value_comp());
|
||||
if (!intersection.empty())
|
||||
return false;
|
||||
|
||||
for (const Symbol &symbol: other)
|
||||
insert(symbol);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolTable::load(const string &filename)
|
||||
@@ -92,51 +115,54 @@ SymbolTable::load(const string &filename)
|
||||
if (address.empty())
|
||||
return false;
|
||||
|
||||
string symbol = buffer.substr(idx + 1);
|
||||
eat_white(symbol);
|
||||
if (symbol.empty())
|
||||
string name = buffer.substr(idx + 1);
|
||||
eat_white(name);
|
||||
if (name.empty())
|
||||
return false;
|
||||
|
||||
Addr addr;
|
||||
if (!to_number(address, addr))
|
||||
return false;
|
||||
|
||||
if (!insert(addr, symbol))
|
||||
if (!insert({ Symbol::Binding::Global, name, addr }))
|
||||
return false;
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SymbolTable::serialize(const string &base, CheckpointOut &cp) const
|
||||
{
|
||||
paramOut(cp, base + ".size", addrTable.size());
|
||||
paramOut(cp, base + ".size", symbols.size());
|
||||
|
||||
int i = 0;
|
||||
ATable::const_iterator p, end = addrTable.end();
|
||||
for (p = addrTable.begin(); p != end; ++p) {
|
||||
paramOut(cp, csprintf("%s.addr_%d", base, i), p->first);
|
||||
paramOut(cp, csprintf("%s.symbol_%d", base, i), p->second);
|
||||
++i;
|
||||
for (auto &symbol: symbols) {
|
||||
paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address);
|
||||
paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name);
|
||||
paramOut(cp, csprintf("%s.binding_%d", base, i), (int)symbol.binding);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SymbolTable::unserialize(const string &base, CheckpointIn &cp)
|
||||
SymbolTable::unserialize(const string &base, CheckpointIn &cp,
|
||||
Symbol::Binding default_binding)
|
||||
{
|
||||
clear();
|
||||
int size;
|
||||
paramIn(cp, base + ".size", size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
Addr addr;
|
||||
std::string symbol;
|
||||
Addr address;
|
||||
std::string name;
|
||||
Symbol::Binding binding = default_binding;
|
||||
|
||||
paramIn(cp, csprintf("%s.addr_%d", base, i), addr);
|
||||
paramIn(cp, csprintf("%s.symbol_%d", base, i), symbol);
|
||||
insert(addr, symbol);
|
||||
paramIn(cp, csprintf("%s.addr_%d", base, i), address);
|
||||
paramIn(cp, csprintf("%s.symbol_%d", base, i), name);
|
||||
if (!optParamIn(cp, csprintf("%s.binding_%d", base, i), binding))
|
||||
binding = default_binding;
|
||||
insert({binding, name, address});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,140 +32,123 @@
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "base/types.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
namespace Loader
|
||||
{
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
enum class Binding {
|
||||
Global,
|
||||
Local,
|
||||
Weak
|
||||
};
|
||||
|
||||
Binding binding;
|
||||
std::string name;
|
||||
Addr address;
|
||||
};
|
||||
|
||||
class SymbolTable
|
||||
{
|
||||
public:
|
||||
typedef std::multimap<Addr, std::string> ATable;
|
||||
typedef std::map<std::string, Addr> STable;
|
||||
|
||||
private:
|
||||
ATable addrTable;
|
||||
STable symbolTable;
|
||||
typedef std::vector<Symbol> SymbolVector;
|
||||
// Map addresses to an index into the symbol vector.
|
||||
typedef std::multimap<Addr, int> AddrMap;
|
||||
// Map a symbol name to an index into the symbol vector.
|
||||
typedef std::map<std::string, int> NameMap;
|
||||
|
||||
SymbolVector symbols;
|
||||
AddrMap addrMap;
|
||||
NameMap nameMap;
|
||||
|
||||
private:
|
||||
bool
|
||||
upperBound(Addr addr, ATable::const_iterator &iter) const
|
||||
upperBound(Addr addr, AddrMap::const_iterator &iter) const
|
||||
{
|
||||
// find first key *larger* than desired address
|
||||
iter = addrTable.upper_bound(addr);
|
||||
iter = addrMap.upper_bound(addr);
|
||||
|
||||
// if very first key is larger, we're out of luck
|
||||
if (iter == addrTable.begin())
|
||||
if (iter == addrMap.begin())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolTable() {}
|
||||
SymbolTable(const std::string &file) { load(file); }
|
||||
~SymbolTable() {}
|
||||
typedef SymbolVector::iterator iterator;
|
||||
typedef SymbolVector::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return symbols.begin(); }
|
||||
const_iterator end() const { return symbols.end(); }
|
||||
|
||||
void clear();
|
||||
bool insert(Addr address, std::string symbol);
|
||||
// Insert either a single symbol or the contents of an entire symbol table
|
||||
// into this one.
|
||||
bool insert(const Symbol &symbol);
|
||||
bool insert(const SymbolTable &other);
|
||||
bool load(const std::string &file);
|
||||
|
||||
const ATable &getAddrTable() const { return addrTable; }
|
||||
const STable &getSymbolTable() const { return symbolTable; }
|
||||
|
||||
public:
|
||||
void serialize(const std::string &base, CheckpointOut &cp) const;
|
||||
void unserialize(const std::string &base, CheckpointIn &cp);
|
||||
void unserialize(const std::string &base, CheckpointIn &cp,
|
||||
Symbol::Binding default_binding=Symbol::Binding::Global);
|
||||
|
||||
public:
|
||||
bool
|
||||
findSymbol(Addr address, std::string &symbol) const
|
||||
const_iterator
|
||||
find(Addr address) const
|
||||
{
|
||||
ATable::const_iterator i = addrTable.find(address);
|
||||
if (i == addrTable.end())
|
||||
return false;
|
||||
AddrMap::const_iterator i = addrMap.find(address);
|
||||
if (i == addrMap.end())
|
||||
return end();
|
||||
|
||||
// There are potentially multiple symbols that map to the same
|
||||
// address. For simplicity, just return the first one.
|
||||
symbol = (*i).second;
|
||||
return true;
|
||||
return symbols.begin() + i->second;
|
||||
}
|
||||
|
||||
bool
|
||||
findAddress(const std::string &symbol, Addr &address) const
|
||||
const_iterator
|
||||
find(const std::string &name) const
|
||||
{
|
||||
STable::const_iterator i = symbolTable.find(symbol);
|
||||
if (i == symbolTable.end())
|
||||
return false;
|
||||
NameMap::const_iterator i = nameMap.find(name);
|
||||
if (i == nameMap.end())
|
||||
return end();
|
||||
|
||||
address = (*i).second;
|
||||
return true;
|
||||
return symbols.begin() + i->second;
|
||||
}
|
||||
|
||||
/// Find the nearest symbol equal to or less than the supplied
|
||||
/// address (e.g., the label for the enclosing function).
|
||||
/// @param addr The address to look up.
|
||||
/// @param symbol Return reference for symbol string.
|
||||
/// @param symaddr Return reference for symbol address.
|
||||
/// @param nextaddr Address of following symbol (for
|
||||
/// determining valid range of symbol).
|
||||
/// @retval True if a symbol was found.
|
||||
bool
|
||||
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
|
||||
Addr &nextaddr) const
|
||||
/// @retval A const_iterator which points to the symbol if found, or end.
|
||||
const_iterator
|
||||
findNearest(Addr addr, Addr &nextaddr) const
|
||||
{
|
||||
ATable::const_iterator i;
|
||||
AddrMap::const_iterator i = addrMap.end();
|
||||
if (!upperBound(addr, i))
|
||||
return false;
|
||||
return end();
|
||||
|
||||
nextaddr = i->first;
|
||||
--i;
|
||||
symaddr = i->first;
|
||||
symbol = i->second;
|
||||
return true;
|
||||
return symbols.begin() + i->second;
|
||||
}
|
||||
|
||||
/// Overload for findNearestSymbol() for callers who don't care
|
||||
/// about nextaddr.
|
||||
bool
|
||||
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
|
||||
const_iterator
|
||||
findNearest(Addr addr) const
|
||||
{
|
||||
ATable::const_iterator i;
|
||||
AddrMap::const_iterator i = addrMap.end();
|
||||
if (!upperBound(addr, i))
|
||||
return false;
|
||||
return end();
|
||||
|
||||
--i;
|
||||
symaddr = i->first;
|
||||
symbol = i->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
|
||||
{
|
||||
ATable::const_iterator i;
|
||||
if (!upperBound(addr, i))
|
||||
return false;
|
||||
|
||||
nextaddr = i->first;
|
||||
--i;
|
||||
symaddr = i->first;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
findNearestAddr(Addr addr, Addr &symaddr) const
|
||||
{
|
||||
ATable::const_iterator i;
|
||||
if (!upperBound(addr, i))
|
||||
return false;
|
||||
|
||||
--i;
|
||||
symaddr = i->first;
|
||||
return true;
|
||||
return symbols.begin() + i->second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -757,15 +757,18 @@ BaseCPU::traceFunctionsInternal(Addr pc)
|
||||
// if pc enters different function, print new function symbol and
|
||||
// update saved range. Otherwise do nothing.
|
||||
if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
|
||||
string sym_str;
|
||||
bool found = Loader::debugSymbolTable->findNearestSymbol(
|
||||
pc, sym_str, currentFunctionStart, currentFunctionEnd);
|
||||
auto it = Loader::debugSymbolTable->findNearest(
|
||||
pc, currentFunctionEnd);
|
||||
|
||||
if (!found) {
|
||||
string sym_str;
|
||||
if (it == Loader::debugSymbolTable->end()) {
|
||||
// no symbol found: use addr as label
|
||||
sym_str = csprintf("0x%x", pc);
|
||||
sym_str = csprintf("%#x", pc);
|
||||
currentFunctionStart = pc;
|
||||
currentFunctionEnd = pc + 1;
|
||||
} else {
|
||||
sym_str = it->name;
|
||||
currentFunctionStart = it->address;
|
||||
}
|
||||
|
||||
ccprintf(*functionTraceStream, " (%d)\n%d: %s",
|
||||
|
||||
@@ -76,27 +76,28 @@ Trace::ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran)
|
||||
if (Debug::ExecThread)
|
||||
outs << "T" << thread->threadId() << " : ";
|
||||
|
||||
std::string sym_str;
|
||||
Addr sym_addr;
|
||||
Addr cur_pc = pc.instAddr();
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (Loader::debugSymbolTable && Debug::ExecSymbol &&
|
||||
(!FullSystem || !inUserMode(thread)) &&
|
||||
Loader::debugSymbolTable->findNearestSymbol(
|
||||
cur_pc, sym_str, sym_addr)) {
|
||||
if (cur_pc != sym_addr)
|
||||
sym_str += csprintf("+%d",cur_pc - sym_addr);
|
||||
outs << "@" << sym_str;
|
||||
(it = Loader::debugSymbolTable->findNearest(cur_pc)) !=
|
||||
Loader::debugSymbolTable->end()) {
|
||||
Addr delta = cur_pc - it->address;
|
||||
if (delta)
|
||||
ccprintf(outs, "@%s+%d", it->name, delta);
|
||||
else
|
||||
ccprintf(outs, "@%s", it->name);
|
||||
} else {
|
||||
outs << "0x" << hex << cur_pc;
|
||||
ccprintf(outs, "%#x", cur_pc);
|
||||
}
|
||||
|
||||
if (inst->isMicroop()) {
|
||||
outs << "." << setw(2) << dec << pc.microPC();
|
||||
ccprintf(outs, ".%2d", pc.microPC());
|
||||
} else {
|
||||
outs << " ";
|
||||
ccprintf(outs, " ");
|
||||
}
|
||||
|
||||
outs << " : ";
|
||||
ccprintf(outs, " : ");
|
||||
|
||||
//
|
||||
// Print decoded instruction
|
||||
|
||||
@@ -57,6 +57,7 @@ ProfileNode::dump(const string &symbol, uint64_t id,
|
||||
|
||||
ccprintf(os, "\n");
|
||||
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
for (i = children.begin(); i != end; ++i) {
|
||||
Addr addr = i->first;
|
||||
string symbol;
|
||||
@@ -66,7 +67,9 @@ ProfileNode::dump(const string &symbol, uint64_t id,
|
||||
symbol = "console";
|
||||
else if (addr == 3)
|
||||
symbol = "unknown";
|
||||
else if (!symtab->findSymbol(addr, symbol))
|
||||
else if ((it = symtab->find(addr)) != symtab->end())
|
||||
symbol = it->name;
|
||||
else
|
||||
panic("could not find symbol for address %#x\n", addr);
|
||||
|
||||
const ProfileNode *node = i->second;
|
||||
@@ -127,13 +130,15 @@ FunctionProfile::dump(ThreadContext *tc, ostream &os) const
|
||||
Addr pc = i->first;
|
||||
Counter count = i->second;
|
||||
|
||||
std::string symbol;
|
||||
if (pc == 1)
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (pc == 1) {
|
||||
ccprintf(os, "user %d\n", count);
|
||||
else if (symtab->findSymbol(pc, symbol) && !symbol.empty())
|
||||
ccprintf(os, "%s %d\n", symbol, count);
|
||||
else
|
||||
} else if ((it = symtab->find(pc)) != symtab->end() &&
|
||||
!it->name.empty()) {
|
||||
ccprintf(os, "%s %d\n", it->name, count);
|
||||
} else {
|
||||
ccprintf(os, "%#x %d\n", pc, count);
|
||||
}
|
||||
}
|
||||
|
||||
ccprintf(os, ">>>function data\n");
|
||||
@@ -145,9 +150,9 @@ FunctionProfile::sample(ProfileNode *node, Addr pc)
|
||||
{
|
||||
node->count++;
|
||||
|
||||
Addr symaddr;
|
||||
if (symtab->findNearestAddr(pc, symaddr)) {
|
||||
pc_count[symaddr]++;
|
||||
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
|
||||
|
||||
@@ -96,24 +96,25 @@ Linux::dumpDmesg(ThreadContext *tc, std::ostream &os)
|
||||
const auto *symtab = system->workload->symtab(tc);
|
||||
PortProxy &proxy = tc->getVirtProxy();
|
||||
|
||||
Addr addr_lb = 0, addr_lb_len = 0, addr_first = 0, addr_next = 0;
|
||||
const bool found_symbols =
|
||||
symtab->findAddress("__log_buf", addr_lb) &&
|
||||
symtab->findAddress("log_buf_len", addr_lb_len) &&
|
||||
symtab->findAddress("log_first_idx", addr_first) &&
|
||||
symtab->findAddress("log_next_idx", addr_next);
|
||||
auto lb = symtab->find("__log_buf");
|
||||
auto lb_len = symtab->find("log_buf_len");
|
||||
auto first = symtab->find("log_first_idx");
|
||||
auto next = symtab->find("log_next_idx");
|
||||
|
||||
if (!found_symbols) {
|
||||
auto end_it = symtab->end();
|
||||
|
||||
if (lb == end_it || lb_len == end_it ||
|
||||
first == end_it || next == end_it) {
|
||||
warn("Failed to find kernel dmesg symbols.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t log_buf_len =
|
||||
proxy.read<uint32_t>(addr_lb_len, TheISA::GuestByteOrder);
|
||||
proxy.read<uint32_t>(lb_len->address, TheISA::GuestByteOrder);
|
||||
uint32_t log_first_idx =
|
||||
proxy.read<uint32_t>(addr_first, TheISA::GuestByteOrder);
|
||||
proxy.read<uint32_t>(first->address, TheISA::GuestByteOrder);
|
||||
uint32_t log_next_idx =
|
||||
proxy.read<uint32_t>(addr_next, TheISA::GuestByteOrder);
|
||||
proxy.read<uint32_t>(next->address, TheISA::GuestByteOrder);
|
||||
|
||||
if (log_first_idx >= log_buf_len || log_next_idx >= log_buf_len) {
|
||||
warn("dmesg pointers/length corrupted\n");
|
||||
@@ -129,7 +130,7 @@ Linux::dumpDmesg(ThreadContext *tc, std::ostream &os)
|
||||
warn("Unexpected dmesg buffer length\n");
|
||||
return;
|
||||
}
|
||||
proxy.readBlob(addr_lb + log_first_idx, log_buf.data(), length);
|
||||
proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length);
|
||||
} else {
|
||||
const int length_2 = log_buf_len - log_first_idx;
|
||||
if (length_2 < 0 || length_2 + log_next_idx > log_buf.size()) {
|
||||
@@ -137,8 +138,8 @@ Linux::dumpDmesg(ThreadContext *tc, std::ostream &os)
|
||||
return;
|
||||
}
|
||||
length = log_buf_len;
|
||||
proxy.readBlob(addr_lb + log_first_idx, log_buf.data(), length_2);
|
||||
proxy.readBlob(addr_lb, log_buf.data() + length_2, log_next_idx);
|
||||
proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length_2);
|
||||
proxy.readBlob(lb->address, log_buf.data() + length_2, log_next_idx);
|
||||
}
|
||||
|
||||
// Print dmesg buffer content
|
||||
|
||||
@@ -98,9 +98,9 @@ class KernelWorkload : public Workload
|
||||
}
|
||||
|
||||
bool
|
||||
insertSymbol(Addr address, const std::string &symbol) override
|
||||
insertSymbol(const Loader::Symbol &symbol) override
|
||||
{
|
||||
return kernelSymtab->insert(address, symbol);
|
||||
return kernelSymtab->insert(symbol);
|
||||
}
|
||||
|
||||
void initState() override;
|
||||
|
||||
@@ -241,8 +241,10 @@ loadsymbol(ThreadContext *tc)
|
||||
if (!to_number(address, addr))
|
||||
continue;
|
||||
|
||||
if (!tc->getSystemPtr()->workload->insertSymbol(addr, symbol))
|
||||
if (!tc->getSystemPtr()->workload->insertSymbol(
|
||||
{ Loader::Symbol::Binding::Global, symbol, addr })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
|
||||
@@ -263,8 +265,10 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
|
||||
|
||||
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
|
||||
|
||||
tc->getSystemPtr()->workload->insertSymbol(addr, symbol);
|
||||
Loader::debugSymbolTable->insert(addr, symbol);
|
||||
tc->getSystemPtr()->workload->insertSymbol(
|
||||
{ Loader::Symbol::Binding::Global, symbol, addr });
|
||||
Loader::debugSymbolTable->insert(
|
||||
{ Loader::Symbol::Binding::Global, symbol, addr });
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
||||
@@ -50,7 +50,7 @@ class Workload : public SimObject
|
||||
virtual Loader::Arch getArch() const = 0;
|
||||
|
||||
virtual const Loader::SymbolTable *symtab(ThreadContext *tc) = 0;
|
||||
virtual bool insertSymbol(Addr address, const std::string &symbol) = 0;
|
||||
virtual bool insertSymbol(const Loader::Symbol &symbol) = 0;
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
@@ -70,14 +70,12 @@ class Workload : public SimObject
|
||||
addFuncEvent(const Loader::SymbolTable *symtab, const char *lbl,
|
||||
const std::string &desc, Args... args)
|
||||
{
|
||||
Addr addr M5_VAR_USED = 0; // initialize only to avoid compiler warning
|
||||
auto it = symtab->find(lbl);
|
||||
if (it == symtab->end())
|
||||
return nullptr;
|
||||
|
||||
if (symtab->findAddress(lbl, addr)) {
|
||||
return new T(system, desc, fixFuncEventAddr(addr),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return new T(system, desc, fixFuncEventAddr(it->address),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -52,27 +52,24 @@ main(int argc, char *argv[])
|
||||
obj->loadLocalSymbols(&symtab);
|
||||
|
||||
if (argc == 2) {
|
||||
Loader::SymbolTable::ATable::const_iterator i =
|
||||
symtab.getAddrTable().begin();
|
||||
Loader::SymbolTable::ATable::const_iterator end =
|
||||
symtab.getAddrTable().end();
|
||||
while (i != end) {
|
||||
cprintf("%#x %s\n", i->first, i->second);
|
||||
++i;
|
||||
}
|
||||
for (const Loader::Symbol &symbol: symtab)
|
||||
cprintf("%#x %s\n", symbol.address, symbol.name);
|
||||
} else {
|
||||
string symbol = argv[2];
|
||||
Addr address;
|
||||
|
||||
if (symbol[0] == '0' && symbol[1] == 'x') {
|
||||
Loader::SymbolTable::const_iterator it;
|
||||
if (to_number(symbol, address) &&
|
||||
symtab.findSymbol(address, symbol))
|
||||
cprintf("address = %#x, symbol = %s\n", address, symbol);
|
||||
else
|
||||
(it = symtab.find(address)) != symtab.end()) {
|
||||
cprintf("address = %#x, symbol = %s\n", address, it->name);
|
||||
} else {
|
||||
cprintf("address = %#x was not found\n", address);
|
||||
}
|
||||
} else {
|
||||
if (symtab.findAddress(symbol, address))
|
||||
cprintf("symbol = %s address = %#x\n", symbol, address);
|
||||
auto it = symtab.find(symbol);
|
||||
if (it != symtab.end())
|
||||
cprintf("symbol = %s address = %#x\n", symbol, it->address);
|
||||
else
|
||||
cprintf("symbol = %s was not found\n", symbol);
|
||||
}
|
||||
|
||||
@@ -60,19 +60,21 @@ main(int argc, char *argv[])
|
||||
Addr address;
|
||||
|
||||
if (!to_number(symbol, address)) {
|
||||
if (!symtab.findAddress(symbol, address)) {
|
||||
auto it = symtab.find(symbol);
|
||||
if (it == symtab.end()) {
|
||||
cout << "could not find symbol: " << symbol << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cout << symbol << " -> " << "0x" << hex << address << endl;
|
||||
cout << symbol << " -> " << "0x" << hex << it->address << endl;
|
||||
} else {
|
||||
if (!symtab.findSymbol(address, symbol)) {
|
||||
auto it = symtab.find(address);
|
||||
if (it == symtab.end()) {
|
||||
cout << "could not find address: " << address << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cout << "0x" << hex << address << " -> " << symbol<< endl;
|
||||
cout << "0x" << hex << address << " -> " << it->name << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user