diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/loader/elf_object.cc | 282 | ||||
-rw-r--r-- | base/loader/elf_object.hh | 13 | ||||
-rw-r--r-- | base/statistics.cc | 123 | ||||
-rw-r--r-- | base/statistics.hh | 10 |
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); |