summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/loader/elf_object.cc282
-rw-r--r--base/loader/elf_object.hh13
-rw-r--r--base/statistics.cc123
-rw-r--r--base/statistics.hh10
4 files changed, 195 insertions, 233 deletions
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
index df3e15f76..929d455a5 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -28,6 +28,14 @@
#include <string>
+// Because of the -Wundef flag we have to do this
+#define __LIBELF_INTERNAL__ 0
+#define __LIBELF64_LINUX 1
+#define __LIBELF_NEED_LINK_H 0
+
+#include <libelf/libelf.h>
+#include <libelf/gelf.h>
+
#include "base/loader/elf_object.hh"
#include "mem/functional_mem/functional_memory.hh"
@@ -44,24 +52,21 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
Elf *elf;
GElf_Ehdr ehdr;
-
- /* check that header matches library version */
+ // check that header matches library version
assert(elf_version(EV_CURRENT) != EV_NONE);
- /* get a pointer to elf structure */
+ // get a pointer to elf structure
elf = elf_memory((char*)data,len);
- /* will only fail if fd is invalid */
+ // will only fail if fd is invalid
assert(elf != NULL);
- /* Check that we actually have a elf file */
- if(gelf_getehdr(elf, &ehdr) ==0)
- {
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
DPRINTFR(Loader, "Not ELF\n");
elf_end(elf);
return NULL;
}
- else
- {
+ else {
if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
panic("32 bit ELF Binary, Not Supported");
if (ehdr.e_machine != EM_ALPHA)
@@ -81,140 +86,107 @@ ElfObject::ElfObject(const string &_filename, int _fd,
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
{
-
Elf *elf;
GElf_Ehdr ehdr;
- /* check that header matches library version */
+ // check that header matches library version
assert(elf_version(EV_CURRENT) != EV_NONE);
- /* get a pointer to elf structure */
+ // get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
- /* will only fail if fd is invalid */
+ // will only fail if fd is invalid
assert(elf != NULL);
- /* Check that we actually have a elf file */
- if(gelf_getehdr(elf, &ehdr) ==0)
- {
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
panic("Not ELF, shouldn't be here");
}
-
entry = ehdr.e_entry;
- elf_end(elf);
- /* We will actually read the sections when we need to load them*/
-}
+ // initialize segment sizes to 0 in case they're not present
+ text.size = data.size = bss.size = 0;
+ for (int i = 0; i < ehdr.e_phnum; ++i) {
+ GElf_Phdr phdr;
+ if (gelf_getphdr(elf, i, &phdr) == 0) {
+ panic("gelf_getphdr failed for section %d", i);
+ }
-bool
-ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Elf *elf;
- int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/
- Elf_Scn *section;
- GElf_Shdr shdr;
- GElf_Ehdr ehdr;
- uint8_t *zero_mem;
- uint8_t *section_data;
-
- Addr address;
- char *sec_name;
-
-
-
- /* check that header matches library version */
- assert(elf_version(EV_CURRENT) != EV_NONE);
-
-
- /* get a pointer to elf structure */
- elf = elf_memory((char*)fileData,len);
-
- assert(elf != NULL);
-
- /* Check that we actually have a elf file */
- if(gelf_getehdr(elf, &ehdr) ==0)
- {
- panic("Not ELF, shouldn't be here");
+ // for now we don't care about non-loadable segments
+ if (!(phdr.p_type & PT_LOAD))
+ continue;
+
+ // the headers don't explicitly distinguish text from data,
+ // but empirically the text segment comes first.
+ if (text.size == 0) { // haven't seen text segment yet
+ text.baseAddr = phdr.p_vaddr;
+ text.size = phdr.p_filesz;
+ // remember where the data is for loadSections()
+ fileTextBits = fileData + phdr.p_offset;
+ // if there's any padding at the end that's not in the
+ // file, call it the bss. This happens in the "text"
+ // segment if there's only one loadable segment (as for
+ // kernel images).
+ bss.size = phdr.p_memsz - phdr.p_filesz;
+ bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ }
+ else if (data.size == 0) { // have text, this must be data
+ data.baseAddr = phdr.p_vaddr;
+ data.size = phdr.p_filesz;
+ // remember where the data is for loadSections()
+ fileDataBits = fileData + phdr.p_offset;
+ // if there's any padding at the end that's not in the
+ // file, call it the bss. Warn if this happens for both
+ // the text & data segments (should only have one bss).
+ if (phdr.p_memsz - phdr.p_filesz > 0 && bss.size != 0) {
+ warn("Two implied bss segments in file!\n");
+ }
+ bss.size = phdr.p_memsz - phdr.p_filesz;
+ bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ }
}
+ // should have found at least one loadable segment
+ assert(text.size != 0);
+ DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
+ text.baseAddr, text.size, data.baseAddr, data.size,
+ bss.baseAddr, bss.size);
- /* Get the first section */
- section = elf_getscn(elf, sec_idx);
-
- /* While there are no more sections */
- while (section != NULL)
- {
- gelf_getshdr(section, &shdr);
-
+ elf_end(elf);
- if (shdr.sh_flags & SHF_ALLOC)
- {
- /* we should load this */
- DPRINTF(Loader,"Name: %20s Address: 0x%016llx Size: 0x%08llx Offset: 0x%08llx Flags:0x%08llx %s\n",
- elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name), shdr.sh_addr,
- shdr.sh_size, shdr.sh_offset, shdr.sh_flags, shdr.sh_flags & SHF_ALLOC ? "ALLOC" : "");
- sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
+ // We will actually read the sections when we need to load them
+}
- section_data = fileData + shdr.sh_offset;
- if(sec_name)
- {
- if (strcmp(sec_name, ".text")==0)
- {
- text.baseAddr = shdr.sh_addr;
- text.size = shdr.sh_size;
- }
- if (strcmp(sec_name, ".data")==0)
- {
- data.baseAddr = shdr.sh_addr;
- data.size = shdr.sh_size;
- }
- if (strcmp(sec_name, ".bss")==0)
- {
- bss.baseAddr = shdr.sh_addr;
- bss.size = shdr.sh_size;
-
- /* If this is the .bss section it must be 0, so just
- to be extra causious, lets allocate some memory
- bzero it, and write that */
- zero_mem = (uint8_t*)malloc(shdr.sh_size);
- memset(zero_mem, 0, shdr.sh_size);
- section_data = zero_mem;
- }
- }
- if(shdr.sh_size != 0)
- {
- if (loadPhys)
- {
- address = shdr.sh_addr &= (ULL(1) << 40) - 1;
- mem->prot_write(address, section_data, shdr.sh_size);
- }
- else
- {
- mem->prot_write(shdr.sh_addr, section_data, shdr.sh_size);
- }
- }
-
- }
+bool
+ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
+{
+ Addr textAddr = text.baseAddr;
+ Addr dataAddr = data.baseAddr;
- ++sec_idx;
- section = elf_getscn(elf, sec_idx);
+ if (loadPhys) {
+ textAddr &= (ULL(1) << 40) - 1;
+ dataAddr &= (ULL(1) << 40) - 1;
}
- free(zero_mem);
- elf_end(elf);
+ // Since we don't really have an MMU and all memory is
+ // zero-filled, there's no need to set up the BSS segment.
+ if (text.size != 0)
+ mem->prot_write(textAddr, fileTextBits, text.size);
+ if (data.size != 0)
+ mem->prot_write(dataAddr, fileDataBits, data.size);
return true;
}
bool
-ElfObject::loadGlobalSymbols(SymbolTable *symtab)
+ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
{
Elf *elf;
- int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/
+ int sec_idx = 1; // there is a 0 but it is nothing, go figure
Elf_Scn *section;
GElf_Shdr shdr;
Elf_Data *data;
@@ -225,39 +197,33 @@ ElfObject::loadGlobalSymbols(SymbolTable *symtab)
if (!symtab)
return false;
- /* check that header matches library version */
+ // check that header matches library version
assert(elf_version(EV_CURRENT) != EV_NONE);
- /* get a pointer to elf structure */
+ // get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
assert(elf != NULL);
-
- /* Get the first section */
+ // Get the first section
section = elf_getscn(elf, sec_idx);
- /* While there are no more sections */
- while (section != NULL)
- {
+ // While there are no more sections
+ while (section != NULL) {
gelf_getshdr(section, &shdr);
-
- if(shdr.sh_type == SHT_SYMTAB)
- {
+ if (shdr.sh_type == SHT_SYMTAB) {
found = true;
data = elf_getdata(section, NULL);
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 (ii = 0; ii < count; ++ii)
- {
+ // loop through all the symbols, only loading global ones
+ for (ii = 0; ii < count; ++ii) {
gelf_getsym(data, ii, &sym);
- if ((GELF_ST_BIND(sym.st_info) & STB_GLOBAL) &&
- ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) || (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE)))
- {
- symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
+ if (GELF_ST_BIND(sym.st_info) & binding) {
+ symtab->insert(sym.st_value,
+ elf_strptr(elf, shdr.sh_link, sym.st_name));
}
}
}
@@ -271,61 +237,13 @@ ElfObject::loadGlobalSymbols(SymbolTable *symtab)
}
bool
-ElfObject::loadLocalSymbols(SymbolTable *symtab)
+ElfObject::loadGlobalSymbols(SymbolTable *symtab)
{
+ return loadSomeSymbols(symtab, STB_GLOBAL);
+}
- Elf *elf;
- int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/
- Elf_Scn *section;
- GElf_Shdr shdr;
- Elf_Data *data;
- int count, ii;
- bool found = false;
- GElf_Sym sym;
-
- if (!symtab)
- return false;
-
- /* check that header matches library version */
- assert(elf_version(EV_CURRENT) != EV_NONE);
-
- /* get a pointer to elf structure */
- elf = elf_memory((char*)fileData,len);
-
- assert(elf != NULL);
-
-
- /* Get the first section */
- section = elf_getscn(elf, sec_idx);
-
- /* While there are no more sections */
- while (section != NULL)
- {
- gelf_getshdr(section, &shdr);
-
-
- if(shdr.sh_type == SHT_SYMTAB)
- {
- found = true;
- data = elf_getdata(section, NULL);
- 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 (ii = 0; ii < count; ++ii)
- {
- gelf_getsym(data, ii, &sym);
- if (GELF_ST_BIND(sym.st_info) & STB_LOCAL)
- {
- symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
- }
- }
- }
- ++sec_idx;
- section = elf_getscn(elf, sec_idx);
- }
-
- elf_end(elf);
-
- return found;
+bool
+ElfObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ return loadSomeSymbols(symtab, STB_LOCAL);
}
diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh
index 9f0385d86..35a6c6d6e 100644
--- a/base/loader/elf_object.hh
+++ b/base/loader/elf_object.hh
@@ -29,19 +29,18 @@
#ifndef __ELF_OBJECT_HH__
#define __ELF_OBJECT_HH__
-/* Because of the -Wundef flag we have to do this */
-#define __LIBELF_INTERNAL__ 0
-#define __LIBELF64_LINUX 1
-#define __LIBELF_NEED_LINK_H 0
-
-#include <libelf/libelf.h>
-#include <libelf/gelf.h>
#include "base/loader/object_file.hh"
class ElfObject : public ObjectFile
{
protected:
+ uint8_t *fileTextBits; //!< Pointer to file's text segment image
+ uint8_t *fileDataBits; //!< Pointer to file's data segment image
+
+ /// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
+ bool loadSomeSymbols(SymbolTable *symtab, int binding);
+
ElfObject(const std::string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys);
diff --git a/base/statistics.cc b/base/statistics.cc
index 04d4032d3..5c9a2bc65 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -27,7 +27,7 @@
*/
#include <iomanip>
-#include <iostream>
+#include <fstream>
#include <list>
#include <map>
#include <string>
@@ -82,11 +82,19 @@ namespace Database
list_t printStats;
map_t statMap;
+ ofstream *stream;
+ Python *py;
+
public:
- void dump(ostream &stream, const string &name, DisplayMode mode);
+ Data();
+ ~Data();
+
+ void dump(ostream &stream, DisplayMode mode);
void display(ostream &stream, DisplayMode mode);
- void python(ostream &stream, const string &name);
- void python(Python &py, const string &name, const string &bin);
+ void python_start(const string &file);
+ void python_dump(const string &name, const string &subname);
+ void python(const string &name, const string &subname,
+ const string &bin);
StatData *find(void *stat);
void mapStat(void *stat, StatData *data);
@@ -99,16 +107,28 @@ namespace Database
static std::string name() { return "Statistics Database"; }
};
+Data::Data()
+ : stream(0), py(0)
+{
+}
+
+Data::~Data()
+{
+ if (stream) {
+ delete py;
+ ccprintf(*stream, "if __name__ == '__main__':\n");
+ ccprintf(*stream, " program_display()\n");
+ stream->close();
+ delete stream;
+ }
+}
void
-Data::dump(ostream &stream, const string &name, DisplayMode mode)
+Data::dump(ostream &stream, DisplayMode mode)
{
MainBin *orig = MainBin::curBin();
switch (mode) {
- case mode_python:
- python(stream, name);
- break;
case mode_m5:
case mode_simplescalar:
display(stream, mode);
@@ -158,50 +178,61 @@ Data::display(ostream &stream, DisplayMode mode)
}
void
-Data::python(ostream &stream, const string &name)
+Data::python_start(const string &file)
{
- Python py(stream);
+ if (stream)
+ panic("can't start python twice!");
- ccprintf(stream, "import sys\n");
- ccprintf(stream, "sys.path.append('.')\n");
- ccprintf(stream, "from m5stats import *\n\n");
+ stream = new ofstream(file.c_str(), ios::trunc);
+ py = new Python(*stream);
+
+ ccprintf(*stream, "import sys\n");
+ ccprintf(*stream, "sys.path.append('.')\n");
+ ccprintf(*stream, "from m5stats import *\n\n");
+}
+
+void
+Data::python_dump(const string &name, const string &subname)
+{
+ if (!py)
+ panic("Can't dump python without first opening the file");
if (bins.empty()) {
- python(py, name, "");
+ python(name, subname, "");
} else {
list<MainBin *>::iterator i = bins.begin();
list<MainBin *>::iterator end = bins.end();
while (i != end) {
(*i)->activate();
- python(py, name, (*i)->name());
+ python(name, subname, (*i)->name());
++i;
}
}
-
- py.next();
- ccprintf(stream, "if __name__ == '__main__':\n");
- ccprintf(stream, " program_display()\n");
+ py->next();
}
void
-Data::python(Python &py, const string &name, const string &bin)
+Data::python(const string &name, const string &subname, const string &bin)
{
- py.start("collections.append");
- py.start("Collection");
- py.qarg(name);
- py.qarg(bin);
- py.qarg(hostname());
- py.qarg(Time::start.date());
+ py->start("collections.append");
+ py->start("Collection");
+ py->qarg(name);
+ py->qarg(subname);
+ py->qarg(bin);
+ py->qarg(hostname());
+ py->qarg(Time::start.date());
+ py->startList();
list_t::iterator i = allStats.begin();
list_t::iterator end = allStats.end();
while (i != end) {
StatData *stat = *i;
- stat->python(py);
+ stat->python(*py);
++i;
}
- py.end();
- py.end();
+ py->endList();
+ py->end();
+ py->end();
}
StatData *
@@ -967,7 +998,7 @@ ScalarDataBase::python(Python &py) const
{
py.start("Scalar");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -984,7 +1015,7 @@ VectorDataBase::python(Python &py) const
py.start("Vector");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -1033,7 +1064,7 @@ FormulaDataBase::python(Python &py) const
py.start("Formula");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -1054,7 +1085,7 @@ DistDataBase::python(Python &py) const
py.start("Dist");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -1071,7 +1102,7 @@ VectorDistDataBase::python(Python &py) const
py.start("VectorDist");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -1101,7 +1132,7 @@ Vector2dDataBase::python(Python &py) const
py.start("Vector2d");
py.qarg(name);
- py.qarg(desc);
+ py.qqqarg(desc);
py.kwarg("binned", binned());
py.kwarg("precision", precision);
py.kwarg("flags", flags);
@@ -1124,13 +1155,14 @@ Vector2dDataBase::python(Python &py) const
void
FormulaBase::val(rvec_t &vec) const
{
- vec = root->val();
+ if (root)
+ vec = root->val();
}
result_t
FormulaBase::total() const
{
- return root->total();
+ return root ? root->total() : 0.0;
}
size_t
@@ -1240,11 +1272,24 @@ check()
}
void
-dump(ostream &stream, const string &name, DisplayMode mode)
+dump(ostream &stream, DisplayMode mode)
+{
+ Database::StatDB().dump(stream, mode);
+}
+
+void
+python_start(const string &file)
{
- Database::StatDB().dump(stream, name, mode);
+ Database::StatDB().python_start(file);
}
+void
+python_dump(const string &name, const string &subname)
+{
+ Database::StatDB().python_dump(name, subname);
+}
+
+
CallbackQueue resetQueue;
void
diff --git a/base/statistics.hh b/base/statistics.hh
index 8c7566391..ce20043a3 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -120,8 +120,7 @@ const StatFlags __reserved = init | print | __substat;
enum DisplayMode
{
mode_m5,
- mode_simplescalar,
- mode_python
+ mode_simplescalar
};
extern DisplayMode DefaultMode;
@@ -2931,7 +2930,7 @@ class Temp;
class Formula
: public WrapVec<Formula,
FormulaBase,
- VectorData>
+ FormulaData>
{
public:
/**
@@ -3132,8 +3131,9 @@ class Temp
*/
void check();
-void dump(std::ostream &stream, const std::string &name = "",
- DisplayMode mode = DefaultMode);
+void dump(std::ostream &stream, DisplayMode mode = DefaultMode);
+void python_start(const std::string &file);
+void python_dump(const std::string &name, const std::string &subname);
void reset();
void registerResetCallback(Callback *cb);