From 5378573b1d9cbe5b0d4748e1d2faba195e54c3ef Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 15 Oct 2014 17:41:08 +0200 Subject: [PATCH] util/DwarfReader, ElfImporter: import address ranges This change implements the following: -DwarfReader now exports the address range of linetable-entries instead of only the first address -ElfImporter saves this range alongside the mapping Change-Id: I7fe6361178f761a8f605a44bb0183c56a236cc95 --- src/core/util/DwarfReader.cc | 22 +++++++++++++++++++--- src/core/util/DwarfReader.hpp | 29 ++++++++++++++++------------- tools/import-trace/ElfImporter.cc | 15 ++++++++------- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/core/util/DwarfReader.cc b/src/core/util/DwarfReader.cc index 2a3bca1d..bb93f43d 100644 --- a/src/core/util/DwarfReader.cc +++ b/src/core/util/DwarfReader.cc @@ -1,4 +1,5 @@ #include +#include #include #include @@ -178,7 +179,7 @@ bool DwarfReader::read_source_files(const std::string& fileName,std::list& addrToLineList) { +bool DwarfReader::read_mapping(std::string fileName, std::list& lineMapping) { // Open The file int fd=open(fileName.c_str(),O_RDONLY); @@ -200,9 +201,11 @@ bool DwarfReader::read_mapping(std::string fileName, std::list& addr // Iterator over the headers Dwarf_Unsigned header; + // iterate compilation unit headers while (dwarf_next_cu_header(dbg,0,0,0,0,&header,0)==DW_DLV_OK) { // Access the die Dwarf_Die die; + // XXX: "if there are no sibling headers, die" | semantics unclear! if (dwarf_siblingof(dbg,0,&die,0)!=DW_DLV_OK) { return false; } @@ -234,8 +237,21 @@ bool DwarfReader::read_mapping(std::string fileName, std::list& addr } if (lineNo&&isCode) { - struct addrToLine newLine = { addr, lineNo, normalize(lineSource) }; - addrToLineList.push_back(newLine); + /* default the linetable's address range (->size) to the maximum + * possible range. this results in the last linetable entry having + * maximum range. as this always (?) is a function epilogue, its + * irrelevant for our use-case. */ + // TODO: properly determine the last interval's range, e.g. via __TEXT_END + + DwarfLineMapping mapping(addr, (std::numeric_limits::max() - addr), + lineNo, lineSource); + // the address range for the previous line ends with the current line's address + if (!lineMapping.empty()) { + DwarfLineMapping& back = lineMapping.back(); + // update the previous lineRangeSize appropriately + back.line_range_size = (addr - back.absolute_addr); + } + lineMapping.push_back(mapping); } dwarf_dealloc(dbg,lineSource,DW_DLA_STRING); diff --git a/src/core/util/DwarfReader.hpp b/src/core/util/DwarfReader.hpp index 7cbbda4d..de63cf2d 100644 --- a/src/core/util/DwarfReader.hpp +++ b/src/core/util/DwarfReader.hpp @@ -7,6 +7,16 @@ namespace fail { +class DwarfLineMapping { +public: + unsigned absolute_addr; + unsigned line_range_size; + unsigned line_number; + std::string line_source; + + DwarfLineMapping(unsigned addr, unsigned size, unsigned number, std::string src) + : absolute_addr(addr), line_range_size(size), line_number(number), line_source(src){} +}; /** * This source code is based on bcov 0.2. @@ -15,23 +25,16 @@ namespace fail { * GNU GENERAL PUBLIC LICENSE */ - struct addrToLine { - unsigned absoluteAddr; - unsigned lineNumber; - std::string lineSource; - }; - - /** - * \class DwarfReader - * ToDO - */ - - class DwarfReader { +/** +* \class DwarfReader +* ToDO +*/ +class DwarfReader { public: bool read_source_files(const std::string& fileName, std::list& lines); - bool read_mapping(std::string fileName, std::list& addrToLineList); + bool read_mapping(std::string fileName, std::list& lineMapping); }; } // end-of-namespace fail diff --git a/tools/import-trace/ElfImporter.cc b/tools/import-trace/ElfImporter.cc index 87d24f1b..6becbc77 100644 --- a/tools/import-trace/ElfImporter.cc +++ b/tools/import-trace/ElfImporter.cc @@ -78,6 +78,7 @@ bool ElfImporter::create_database() create_statement << "CREATE TABLE IF NOT EXISTS dbg_mapping (" " variant_id int(11) NOT NULL," " instr_absolute int(11) UNSIGNED NOT NULL," + " line_range_size int(11) UNSIGNED NOT NULL," " linenumber int(11) UNSIGNED NOT NULL," " file_id int(11) NOT NULL," " PRIMARY KEY (variant_id, instr_absolute ,linenumber)" @@ -356,19 +357,18 @@ bool ElfImporter::import_source_files(const std::string& elf_filename, std::list bool ElfImporter::import_mapping(std::string fileName) { - std::list mapping; + std::list mapping; if (!dwReader.read_mapping(fileName, mapping)) { return false; } while (!mapping.empty()) { - struct addrToLine temp_addrToLine; - temp_addrToLine = mapping.front(); + DwarfLineMapping tmp_mapping = mapping.front(); // FIXME reuse file_id from previous iteration if file name stays constant std::stringstream ss; ss << "SELECT file_id FROM dbg_filename " - << "WHERE path = '" << temp_addrToLine.lineSource << "' " + << "WHERE path = '" << tmp_mapping.line_source << "' " << "AND variant_id = " << m_variant_id; MYSQL_RES *res = db->query(ss.str().c_str(), true); @@ -380,17 +380,18 @@ bool ElfImporter::import_mapping(std::string fileName) // INSERT group entry std::stringstream sql; - sql << "(" << m_variant_id << "," << temp_addrToLine.absoluteAddr << "," << temp_addrToLine.lineNumber << ","; + sql << "(" << m_variant_id << "," << tmp_mapping.absolute_addr << "," + << tmp_mapping.line_range_size << "," << tmp_mapping.line_number << ","; if (row != NULL) { sql << row[0] << ")"; } else { // this should not happen - LOG << "error: no entry for '" << temp_addrToLine.lineSource << "' in dbg_filename, aborting" << std::endl; + LOG << "error: no entry for '" << tmp_mapping.line_source << "' in dbg_filename, aborting" << std::endl; return false; } // TODO: Skip duplicated entries with ON DUPLICATE KEY UPDATE (?) - if (!db->insert_multiple("INSERT IGNORE INTO dbg_mapping (variant_id, instr_absolute, linenumber, file_id) VALUES ", + if (!db->insert_multiple("INSERT IGNORE INTO dbg_mapping (variant_id, instr_absolute, line_range_size, linenumber, file_id) VALUES ", sql.str().c_str())) { return false; }