import-trace: record stats on failed register mappings
The import-trace tool now systematically collects statistics on which LLVM -> FAIL* register ID mappings failed during import, and presents those after the import finished. Change-Id: Ied67853d754483277868fe21bf2c6efeaeb60f09
This commit is contained in:
@ -15,8 +15,6 @@ static std::ostream& operator<<(std::ostream& stream, const llvm::StringRef& s)
|
|||||||
|
|
||||||
LLVMtoFailTranslator *LLVMDisassembler::getTranslator() {
|
LLVMtoFailTranslator *LLVMDisassembler::getTranslator() {
|
||||||
if (ltofail == 0) {
|
if (ltofail == 0) {
|
||||||
std::cout << "ArchType: " << llvm::Triple::getArchTypeName( llvm::Triple::ArchType(object->getArch()) ) << std::endl;
|
|
||||||
|
|
||||||
switch ( llvm::Triple::ArchType(object->getArch()) ) {
|
switch ( llvm::Triple::ArchType(object->getArch()) ) {
|
||||||
case llvm::Triple::x86:
|
case llvm::Triple::x86:
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
@ -26,7 +24,9 @@ LLVMtoFailTranslator *LLVMDisassembler::getTranslator() {
|
|||||||
ltofail = new LLVMtoFailGem5(this);
|
ltofail = new LLVMtoFailGem5(this);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << " not supported :(";
|
std::cerr << "ArchType "
|
||||||
|
<< llvm::Triple::getArchTypeName(llvm::Triple::ArchType(object->getArch()))
|
||||||
|
<< " not supported\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,9 +182,9 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
|
|||||||
it != opcode.reg_uses.end(); ++it) {
|
it != opcode.reg_uses.end(); ++it) {
|
||||||
const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it);
|
const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it);
|
||||||
if (&info == &m_ltof->notfound) {
|
if (&info == &m_ltof->notfound) {
|
||||||
LOG << "Could not find a mapping for LLVM input register #" << std::dec << *it
|
// record failed translation, report later
|
||||||
<< " at IP " << std::hex << ev.ip()
|
m_regnotfound[*it].count++;
|
||||||
<< ", skipping" << std::endl;
|
m_regnotfound[*it].address.insert(ev.ip());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,9 +202,9 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
|
|||||||
it != opcode.reg_defs.end(); ++it) {
|
it != opcode.reg_defs.end(); ++it) {
|
||||||
const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it);
|
const LLVMtoFailTranslator::reginfo_t &info = m_ltof->getFailRegisterInfo(*it);
|
||||||
if (&info == &m_ltof->notfound) {
|
if (&info == &m_ltof->notfound) {
|
||||||
LOG << "Could not find a mapping for LLVM output register #" << std::dec << *it
|
// record failed translation, report later
|
||||||
<< " at IP " << std::hex << ev.ip()
|
m_regnotfound[*it].count++;
|
||||||
<< ", skipping" << std::endl;
|
m_regnotfound[*it].address.insert(ev.ip());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,3 +219,30 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegisterImporter::trace_end_reached()
|
||||||
|
{
|
||||||
|
// report failed LLVM -> FAIL* register mappings, if any
|
||||||
|
if (m_regnotfound.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG << "WARNING: Some LLVM -> FAIL* register mappings failed during import, these will not be injected into:" << std::endl;
|
||||||
|
for (auto it = m_regnotfound.cbegin(); it != m_regnotfound.cend(); ++it) {
|
||||||
|
const LLVMDisassembler::register_t id = it->first;
|
||||||
|
const RegNotFound& rnf = it->second;
|
||||||
|
LOG << "LLVM register " << std::dec << id
|
||||||
|
<< " \"" << disas->getRegisterInfo().getName(id) << "\": "
|
||||||
|
<< "seen " << rnf.count << " times in the trace" << std::endl;
|
||||||
|
std::ostream& o = LOG << " corresponding instruction addresses in ELF binary: " << std::hex;
|
||||||
|
for (auto addr_it = rnf.address.cbegin(); addr_it != rnf.address.cend(); ++addr_it) {
|
||||||
|
if (addr_it != rnf.address.cbegin()) {
|
||||||
|
o << ", ";
|
||||||
|
}
|
||||||
|
o << "0x" << *addr_it;
|
||||||
|
}
|
||||||
|
o << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@ -24,6 +24,15 @@ class RegisterImporter : public Importer {
|
|||||||
std::set<unsigned> m_register_ids;
|
std::set<unsigned> m_register_ids;
|
||||||
unsigned m_ip_register_id;
|
unsigned m_ip_register_id;
|
||||||
|
|
||||||
|
// Data structures for recording failed LLVM -> FAIL* register mappings,
|
||||||
|
// including occurrence counts in the trace (to give an estimate on the
|
||||||
|
// impact) and instruction addresses (for debugging purposes).
|
||||||
|
struct RegNotFound {
|
||||||
|
uint64_t count = 0;
|
||||||
|
std::set<fail::guest_address_t> address;
|
||||||
|
};
|
||||||
|
std::map<fail::LLVMDisassembler::register_t, RegNotFound> m_regnotfound;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false),
|
RegisterImporter() : Importer(), do_gp(true), do_flags(false), do_ip(false),
|
||||||
do_split_registers(true), m_ip_register_id(0) {}
|
do_split_registers(true), m_ip_register_id(0) {}
|
||||||
@ -42,6 +51,8 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool trace_end_reached();
|
||||||
|
|
||||||
virtual void open_unused_ec_intervals() {
|
virtual void open_unused_ec_intervals() {
|
||||||
/* empty, Memory Map has a different meaning in this importer */
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user