// to do this permanently, for but early bootup work
// it is helpful.
if (params()->early_kernel_symbols) {
- kernelObj->loadGlobalSymbols(kernelSymtab, 0, 0, _loadAddrMask);
- kernelObj->loadGlobalSymbols(
- &Loader::debugSymbolTable, 0, 0, _loadAddrMask);
+ auto phys_globals = kernelObj->symtab().globals()->mask(_loadAddrMask);
+ kernelSymtab.insert(*phys_globals);
+ Loader::debugSymbolTable.insert(*phys_globals);
}
// Check if the kernel image has a symbol that tells us it supports
// device trees.
- fatal_if(kernelSymtab->find("fdt_get_range") == kernelSymtab->end(),
+ fatal_if(kernelSymtab.find("fdt_get_range") == kernelSymtab.end(),
"Kernel must have fdt support.");
fatal_if(params()->dtb_filename == "", "dtb file is not specified.");
"Can't find a matching boot loader / kernel combination!");
if (bootldr)
- bootldr->loadGlobalSymbols(&Loader::debugSymbolTable);
+ Loader::debugSymbolTable.insert(*bootldr->symtab().globals());
}
void
// to do this permanently, for but early bootup work
// it is helpful.
if (params()->early_kernel_symbols) {
- kernelObj->loadGlobalSymbols(kernelSymtab, 0, 0, _loadAddrMask);
- kernelObj->loadGlobalSymbols(
- &Loader::debugSymbolTable, 0, 0, _loadAddrMask);
+ auto phys_globals = kernelObj->symtab().globals()->mask(_loadAddrMask);
+ kernelSymtab.insert(*phys_globals);
+ Loader::debugSymbolTable.insert(*phys_globals);
}
// Setup boot data structure
// Check if the kernel image has a symbol that tells us it supports
// device trees.
bool kernel_has_fdt_support =
- kernelSymtab->find("unflatten_device_tree") != kernelSymtab->end();
+ kernelSymtab.find("unflatten_device_tree") != kernelSymtab.end();
bool dtb_file_specified = params()->dtb_filename != "";
if (kernel_has_fdt_support && dtb_file_specified) {
readSymbol(ThreadContext *tc, const std::string name)
{
PortProxy &vp = tc->getVirtProxy();
- const auto *symtab = tc->getSystemPtr()->workload->symtab(tc);
+ const auto &symtab = tc->getSystemPtr()->workload->symtab(tc);
- auto it = symtab->find(name);
- panic_if(it == symtab->end(), "Thread info not compiled into kernel.");
+ auto it = symtab.find(name);
+ panic_if(it == symtab.end(), "Thread info not compiled into kernel.");
return vp.read<int32_t>(it->address, GuestByteOrder);
}
bool
get_data(const char *symbol, T &data)
{
- auto *symtab = sys->workload->symtab(tc);
- auto it = symtab->find(symbol);
- if (it == symtab->end()) {
+ 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");
{
BareMetal::BareMetal(Params *p) : RiscvISA::FsWorkload(p),
- bootloader(Loader::createObjectFile(p->bootloader)),
- bootloaderSymtab(new Loader::SymbolTable)
+ bootloader(Loader::createObjectFile(p->bootloader))
{
fatal_if(!bootloader, "Could not load bootloader file %s.", p->bootloader);
_resetVect = bootloader->entryPoint();
+ bootloaderSymtab = bootloader->symtab();
}
BareMetal::~BareMetal()
{
protected:
Loader::ObjectFile *bootloader;
- Loader::SymbolTable *bootloaderSymtab;
+ Loader::SymbolTable bootloaderSymtab;
public:
typedef RiscvBareMetalParams Params;
void initState() override;
Loader::Arch getArch() const override { return bootloader->getArch(); }
- const Loader::SymbolTable *
+ const Loader::SymbolTable &
symtab(ThreadContext *tc) override
{
return bootloaderSymtab;
bool
insertSymbol(const Loader::Symbol &symbol) override
{
- return bootloaderSymtab->insert(symbol);
+ return bootloaderSymtab.insert(symbol);
}
};
}
Loader::Arch getArch() const override { return Loader::SPARC64; }
- const Loader::SymbolTable *
+ const Loader::SymbolTable &
symtab(ThreadContext *tc) override
{
- return &defaultSymtab;
+ return defaultSymtab;
}
bool
readSymbol(ThreadContext *tc, const std::string name)
{
PortProxy &vp = tc->getVirtProxy();
- const auto *symtab = tc->getSystemPtr()->workload->symtab(tc);
+ const auto &symtab = tc->getSystemPtr()->workload->symtab(tc);
- auto it = symtab->find(name);
- panic_if(it == symtab->end(), "Thread info not compiled into kernel.");
+ auto it = symtab.find(name);
+ panic_if(it == symtab.end(), "Thread info not compiled into kernel.");
return vp.read<int32_t>(it->address, GuestByteOrder);
}
StackTrace::dump()
{
StringWrap name(tc->getCpuPtr()->name());
- const auto *symtab = tc->getSystemPtr()->workload->symtab(tc);
+ const auto &symtab = tc->getSystemPtr()->workload->symtab(tc);
DPRINTFN("------ Stack ------\n");
symbol = "console";
else if (addr == unknown)
symbol = "unknown";
- else if ((it = symtab->find(addr)) != symtab->end())
+ else if ((it = symtab.find(addr)) != symtab.end())
symbol = it->name;
DPRINTFN("%#x: %s\n", addr, symbol);
ObjectFile *obj = createObjectFile(interp_path);
interpreter = dynamic_cast<ElfObject *>(obj);
assert(interpreter != nullptr);
+ _symtab.insert(obj->symtab());
}
}
DPRINTFR(Loader, "%s\n", seg);
// We will actually read the sections when we need to load them
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // Get the first section
+ int sec_idx = 1; // there is a 0 but it is nothing, go figure
+ Elf_Scn *section = elf_getscn(elf, sec_idx);
+
+ // While there are no more sections
+ while (section) {
+ GElf_Shdr shdr;
+ gelf_getshdr(section, &shdr);
+
+ if (shdr.sh_type == SHT_SYMTAB) {
+ Elf_Data *data = elf_getdata(section, nullptr);
+ int count = shdr.sh_size / shdr.sh_entsize;
+ DPRINTF(Loader, "Found Symbol Table, %d symbols present.", count);
+
+ // Loop through all the symbols.
+ for (int i = 0; i < count; ++i) {
+ GElf_Sym sym;
+ gelf_getsym(data, i, &sym);
+
+ char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
+ if (!sym_name || sym_name[0] == '$')
+ continue;
+
+ Loader::Symbol symbol;
+ symbol.address = sym.st_value;
+ symbol.name = sym_name;
+
+ switch (GELF_ST_BIND(sym.st_info)) {
+ 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:
+ continue;
+ }
+
+ if (_symtab.insert(symbol)) {
+ DPRINTF(Loader, "Symbol: %-40s value %#x.\n",
+ symbol.name, symbol.address);
+ }
+ }
+ }
+ ++sec_idx;
+ section = elf_getscn(elf, sec_idx);
+ }
}
std::string
elf_end(elf);
}
-bool
-ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
- Addr base, Addr offset)
-{
- if (!symtab)
- return false;
-
- // check that header matches library version
- if (elf_version(EV_CURRENT) == EV_NONE)
- panic("wrong elf version number!");
-
- // get a pointer to elf structure
- Elf *elf = elf_memory((char *)const_cast<uint8_t *>(
- imageData->data()), imageData->len());
- assert(elf != NULL);
-
- // Get the first section
- int sec_idx = 1; // there is a 0 but it is nothing, go figure
- Elf_Scn *section = elf_getscn(elf, sec_idx);
-
- // While there are no more sections
- bool found = false;
- while (section != NULL) {
- GElf_Shdr shdr;
- gelf_getshdr(section, &shdr);
-
- if (shdr.sh_type == SHT_SYMTAB) {
- found = true;
- Elf_Data *data = elf_getdata(section, NULL);
- int count = shdr.sh_size / shdr.sh_entsize;
- DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
-
- // loop through all the symbols, only loading global ones
- for (int i = 0; i < count; ++i) {
- GElf_Sym sym;
- gelf_getsym(data, i, &sym);
- if (GELF_ST_BIND(sym.st_info) == binding) {
- char *sym_name =
- elf_strptr(elf, shdr.sh_link, sym.st_name);
- if (sym_name && sym_name[0] != '$') {
- Addr value = sym.st_value - base + offset;
- 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);
- }
- }
- }
- }
- }
- ++sec_idx;
- section = elf_getscn(elf, sec_idx);
- }
-
- elf_end(elf);
-
- return found;
-}
-
-bool
-ElfObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
- Addr addr_mask)
-{
- return (loadGlobalSymbols(symtab, base, offset, addr_mask) &&
- loadLocalSymbols(symtab, base, offset, addr_mask) &&
- loadWeakSymbols(symtab, base, offset, addr_mask));
-}
-
-bool
-ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
- Addr addr_mask)
-{
- if (interpreter) {
- interpreter->loadSomeSymbols(symtab, STB_GLOBAL, addr_mask,
- base, offset);
- }
- return loadSomeSymbols(symtab, STB_GLOBAL, addr_mask, base, offset);
-}
-
-bool
-ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
- Addr addr_mask)
-{
- if (interpreter) {
- interpreter->loadSomeSymbols(symtab, STB_LOCAL, addr_mask,
- base, offset);
- }
- return loadSomeSymbols(symtab, STB_LOCAL, addr_mask, base, offset);
-}
-
-bool
-ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr base, Addr offset,
- Addr addr_mask)
-{
- if (interpreter) {
- interpreter->loadSomeSymbols(symtab, STB_WEAK, addr_mask,
- base, offset);
- }
- return loadSomeSymbols(symtab, STB_WEAK, addr_mask, base, offset);
-}
-
void
ElfObject::getSections()
{
MemoryImage buildImage() const override { return image; }
- bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr addr_mask=MaxAddr) override;
- bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr addr_mask=MaxAddr) override;
- bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr addr_mask=MaxAddr) override;
- bool loadWeakSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr addr_mask=MaxAddr) override;
-
-
ObjectFile *getInterpreter() const override { return interpreter; }
std::string getInterpPath(const GElf_Phdr &phdr) const;
#include "base/loader/image_file.hh"
#include "base/loader/image_file_data.hh"
#include "base/loader/memory_image.hh"
+#include "base/loader/symtab.hh"
#include "base/logging.hh"
#include "base/types.hh"
Arch arch = UnknownArch;
OpSys opSys = UnknownOpSys;
+ SymbolTable _symtab;
+
ObjectFile(ImageFileDataPtr ifd);
public:
virtual ~ObjectFile() {};
- virtual bool
- loadAllSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr mask=MaxAddr)
- {
- return true;
- };
- virtual bool
- loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr mask=MaxAddr)
- {
- return true;
- }
- virtual bool
- loadLocalSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr mask=MaxAddr)
- {
- return true;
- }
- virtual bool
- loadWeakSymbols(SymbolTable *symtab, Addr base=0,
- Addr offset=0, Addr mask=MaxAddr)
- {
- return true;
- }
-
virtual ObjectFile *getInterpreter() const { return nullptr; }
virtual bool relocatable() const { return false; }
virtual Addr
Arch getArch() const { return arch; }
OpSys getOpSys() const { return opSys; }
+ const SymbolTable &symtab() const { return _symtab; }
+
protected:
Addr entry = 0;
void
ProfileNode::dump(const string &symbol, uint64_t id,
- const Loader::SymbolTable *symtab, ostream &os) const
+ const Loader::SymbolTable &symtab, ostream &os) const
{
ccprintf(os, "%#x %s %d ", id, symbol, count);
ChildList::const_iterator i, end = children.end();
symbol = "console";
else if (addr == 3)
symbol = "unknown";
- else if ((it = symtab->find(addr)) != symtab->end())
+ else if ((it = symtab.find(addr)) != symtab.end())
symbol = it->name;
else
panic("could not find symbol for address %#x\n", addr);
i->second->clear();
}
-FunctionProfile::FunctionProfile(const Loader::SymbolTable *_symtab)
+FunctionProfile::FunctionProfile(const Loader::SymbolTable &_symtab)
: reset(0), symtab(_symtab)
{
reset = new MakeCallback<FunctionProfile, &FunctionProfile::clear>(this);
Loader::SymbolTable::const_iterator it;
if (pc == 1) {
ccprintf(os, "user %d\n", count);
- } else if ((it = symtab->find(pc)) != symtab->end() &&
+ } else if ((it = symtab.find(pc)) != symtab.end() &&
!it->name.empty()) {
ccprintf(os, "%s %d\n", it->name, count);
} else {
{
node->count++;
- auto it = symtab->findNearest(pc);
- if (it != symtab->end()) {
+ 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
ProfileNode();
void dump(const std::string &symbol, uint64_t id,
- const Loader::SymbolTable *symtab, std::ostream &os) const;
+ const Loader::SymbolTable &symtab, std::ostream &os) const;
void clear();
};
{
private:
Callback *reset;
- const Loader::SymbolTable *symtab;
+ const Loader::SymbolTable &symtab;
ProfileNode top;
std::map<Addr, Counter> pc_count;
TheISA::StackTrace trace;
public:
- FunctionProfile(const Loader::SymbolTable *symtab);
+ FunctionProfile(const Loader::SymbolTable &symtab);
~FunctionProfile();
ProfileNode *consume(ThreadContext *tc, const StaticInstPtr &inst);
{
System *system = tc->getSystemPtr();
const ByteOrder bo = system->getGuestByteOrder();
- const auto *symtab = system->workload->symtab(tc);
+ const auto &symtab = system->workload->symtab(tc);
PortProxy &proxy = tc->getVirtProxy();
- 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");
+ 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");
- auto end_it = symtab->end();
+ auto end_it = symtab.end();
if (lb == end_it || lb_len == end_it ||
first == end_it || next == end_it) {
auto *object = Loader::createObjectFile(file, true);
fatal_if(!object, "%s: Could not load %s.", name(), file);
- panic_if(!object->loadGlobalSymbols(&Loader::debugSymbolTable),
- "%s: Could not load symbols from %s.", name(), file);
-
+ Loader::debugSymbolTable.insert(*object->symtab().globals());
Loader::MemoryImage image = object->buildImage();
AddrRange image_range(image.minAddr(), image.maxAddr());
KernelWorkload::KernelWorkload(const Params &p) : Workload(&p), _params(p),
_loadAddrMask(p.load_addr_mask), _loadAddrOffset(p.load_addr_offset),
- kernelSymtab(new Loader::SymbolTable), commandLine(p.command_line)
+ commandLine(p.command_line)
{
if (params().object_file == "") {
inform("No kernel set for full system simulation. "
return (a & _loadAddrMask) + _loadAddrOffset;
});
- // load symbols
- fatal_if(!kernelObj->loadGlobalSymbols(kernelSymtab),
- "Could not load kernel symbols.");
-
- fatal_if(!kernelObj->loadLocalSymbols(kernelSymtab),
- "Could not load kernel local symbols.");
-
- fatal_if(!kernelObj->loadGlobalSymbols(&Loader::debugSymbolTable),
- "Could not load kernel symbols.");
-
- fatal_if(!kernelObj->loadLocalSymbols(&Loader::debugSymbolTable),
- "Could not load kernel local symbols.");
+ kernelSymtab = kernelObj->symtab();
+ Loader::debugSymbolTable.insert(kernelSymtab);
}
// Loading only needs to happen once and after memory system is
}
}
-KernelWorkload::~KernelWorkload()
-{
- delete kernelSymtab;
-}
-
void
KernelWorkload::initState()
{
void
KernelWorkload::serialize(CheckpointOut &cp) const
{
- kernelSymtab->serialize("symtab", cp);
+ kernelSymtab.serialize("symtab", cp);
}
void
KernelWorkload::unserialize(CheckpointIn &cp)
{
- kernelSymtab->unserialize("symtab", cp);
+ kernelSymtab.unserialize("symtab", cp);
}
KernelWorkload *
std::vector<Loader::ObjectFile *> extras;
Loader::ObjectFile *kernelObj = nullptr;
- Loader::SymbolTable *kernelSymtab = nullptr;
+ // Keep a separate copy of the kernel's symbol table so we can add things
+ // to it.
+ Loader::SymbolTable kernelSymtab;
const std::string commandLine;
Addr loadAddrOffset() const { return _loadAddrOffset; }
KernelWorkload(const Params &p);
- ~KernelWorkload();
Addr getEntry() const override { return kernelObj->entryPoint(); }
Loader::Arch
return kernelObj->getArch();
}
- const Loader::SymbolTable *
+ const Loader::SymbolTable &
symtab(ThreadContext *tc) override
{
return kernelSymtab;
bool
insertSymbol(const Loader::Symbol &symbol) override
{
- return kernelSymtab->insert(symbol);
+ return kernelSymtab.insert(symbol);
}
void initState() override;
image = objFile->buildImage();
- if (::Loader::debugSymbolTable.empty()) {
- if (!objFile->loadGlobalSymbols(&::Loader::debugSymbolTable) ||
- !objFile->loadLocalSymbols(&::Loader::debugSymbolTable) ||
- !objFile->loadWeakSymbols(&::Loader::debugSymbolTable)) {
- ::Loader::debugSymbolTable.clear();
- }
- }
+ if (::Loader::debugSymbolTable.empty())
+ ::Loader::debugSymbolTable = objFile->symtab();
}
void
ffdp->getFileName());
if (lib) {
- lib->loadAllSymbols(&Loader::debugSymbolTable,
- lib->buildImage().minAddr(), start);
+ Addr offset = lib->buildImage().minAddr() + start;
+ Loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
}
}
}
virtual Addr getEntry() const = 0;
virtual Loader::Arch getArch() const = 0;
- virtual const Loader::SymbolTable *symtab(ThreadContext *tc) = 0;
+ virtual const Loader::SymbolTable &symtab(ThreadContext *tc) = 0;
virtual bool insertSymbol(const Loader::Symbol &symbol) = 0;
/** @{ */
*/
template <class T, typename... Args>
T *
- addFuncEvent(const Loader::SymbolTable *symtab, const char *lbl,
+ addFuncEvent(const Loader::SymbolTable &symtab, const char *lbl,
const std::string &desc, Args... args)
{
- auto it = symtab->find(lbl);
- if (it == symtab->end())
+ auto it = symtab.find(lbl);
+ if (it == symtab.end())
return nullptr;
return new T(system, desc, fixFuncEventAddr(it->address),
template <class T>
T *
- addFuncEvent(const Loader::SymbolTable *symtab, const char *lbl)
+ addFuncEvent(const Loader::SymbolTable &symtab, const char *lbl)
{
return addFuncEvent<T>(symtab, lbl, lbl);
}
template <class T, typename... Args>
T *
- addFuncEventOrPanic(const Loader::SymbolTable *symtab, const char *lbl,
+ addFuncEventOrPanic(const Loader::SymbolTable &symtab, const char *lbl,
Args... args)
{
T *e = addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...);
#include <vector>
#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
#include "base/logging.hh"
#include "base/str.hh"
if (!obj)
panic("file not found\n");
- Loader::SymbolTable symtab;
- obj->loadGlobalSymbols(&symtab);
- obj->loadLocalSymbols(&symtab);
-
if (argc == 2) {
- for (const Loader::Symbol &symbol: symtab)
+ for (const Loader::Symbol &symbol: obj->symtab())
cprintf("%#x %s\n", symbol.address, symbol.name);
} else {
string symbol = argv[2];
if (symbol[0] == '0' && symbol[1] == 'x') {
Loader::SymbolTable::const_iterator it;
if (to_number(symbol, address) &&
- (it = symtab.find(address)) != symtab.end()) {
+ (it = obj->symtab().find(address)) != obj->symtab().end()) {
cprintf("address = %#x, symbol = %s\n", address, it->name);
} else {
cprintf("address = %#x was not found\n", address);
}
} else {
- auto it = symtab.find(symbol);
- if (it != symtab.end())
+ auto it = obj->symtab().find(symbol);
+ if (it != obj->symtab().end())
cprintf("symbol = %s address = %#x\n", symbol, it->address);
else
cprintf("symbol = %s was not found\n", symbol);