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
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <limits>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ bool DwarfReader::read_source_files(const std::string& fileName,std::list<std::s
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DwarfReader::read_mapping(std::string fileName, std::list<addrToLine>& addrToLineList) {
|
bool DwarfReader::read_mapping(std::string fileName, std::list<DwarfLineMapping>& lineMapping) {
|
||||||
|
|
||||||
// Open The file
|
// Open The file
|
||||||
int fd=open(fileName.c_str(),O_RDONLY);
|
int fd=open(fileName.c_str(),O_RDONLY);
|
||||||
@ -200,9 +201,11 @@ bool DwarfReader::read_mapping(std::string fileName, std::list<addrToLine>& addr
|
|||||||
|
|
||||||
// Iterator over the headers
|
// Iterator over the headers
|
||||||
Dwarf_Unsigned header;
|
Dwarf_Unsigned header;
|
||||||
|
// iterate compilation unit headers
|
||||||
while (dwarf_next_cu_header(dbg,0,0,0,0,&header,0)==DW_DLV_OK) {
|
while (dwarf_next_cu_header(dbg,0,0,0,0,&header,0)==DW_DLV_OK) {
|
||||||
// Access the die
|
// Access the die
|
||||||
Dwarf_Die die;
|
Dwarf_Die die;
|
||||||
|
// XXX: "if there are no sibling headers, die" | semantics unclear!
|
||||||
if (dwarf_siblingof(dbg,0,&die,0)!=DW_DLV_OK) {
|
if (dwarf_siblingof(dbg,0,&die,0)!=DW_DLV_OK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -234,8 +237,21 @@ bool DwarfReader::read_mapping(std::string fileName, std::list<addrToLine>& addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lineNo&&isCode) {
|
if (lineNo&&isCode) {
|
||||||
struct addrToLine newLine = { addr, lineNo, normalize(lineSource) };
|
/* default the linetable's address range (->size) to the maximum
|
||||||
addrToLineList.push_back(newLine);
|
* 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<unsigned>::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);
|
dwarf_dealloc(dbg,lineSource,DW_DLA_STRING);
|
||||||
|
|||||||
@ -7,6 +7,16 @@
|
|||||||
|
|
||||||
namespace fail {
|
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.
|
* This source code is based on bcov 0.2.
|
||||||
@ -15,23 +25,16 @@ namespace fail {
|
|||||||
* GNU GENERAL PUBLIC LICENSE
|
* GNU GENERAL PUBLIC LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct addrToLine {
|
/**
|
||||||
unsigned absoluteAddr;
|
* \class DwarfReader
|
||||||
unsigned lineNumber;
|
* ToDO
|
||||||
std::string lineSource;
|
*/
|
||||||
};
|
class DwarfReader {
|
||||||
|
|
||||||
/**
|
|
||||||
* \class DwarfReader
|
|
||||||
* ToDO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class DwarfReader {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool read_source_files(const std::string& fileName, std::list<std::string>& lines);
|
bool read_source_files(const std::string& fileName, std::list<std::string>& lines);
|
||||||
bool read_mapping(std::string fileName, std::list<addrToLine>& addrToLineList);
|
bool read_mapping(std::string fileName, std::list<DwarfLineMapping>& lineMapping);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace fail
|
} // end-of-namespace fail
|
||||||
|
|||||||
@ -78,6 +78,7 @@ bool ElfImporter::create_database()
|
|||||||
create_statement << "CREATE TABLE IF NOT EXISTS dbg_mapping ("
|
create_statement << "CREATE TABLE IF NOT EXISTS dbg_mapping ("
|
||||||
" variant_id int(11) NOT NULL,"
|
" variant_id int(11) NOT NULL,"
|
||||||
" instr_absolute int(11) UNSIGNED NOT NULL,"
|
" instr_absolute int(11) UNSIGNED NOT NULL,"
|
||||||
|
" line_range_size int(11) UNSIGNED NOT NULL,"
|
||||||
" linenumber int(11) UNSIGNED NOT NULL,"
|
" linenumber int(11) UNSIGNED NOT NULL,"
|
||||||
" file_id int(11) NOT NULL,"
|
" file_id int(11) NOT NULL,"
|
||||||
" PRIMARY KEY (variant_id, instr_absolute ,linenumber)"
|
" 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)
|
bool ElfImporter::import_mapping(std::string fileName)
|
||||||
{
|
{
|
||||||
std::list<addrToLine> mapping;
|
std::list<DwarfLineMapping> mapping;
|
||||||
if (!dwReader.read_mapping(fileName, mapping)) {
|
if (!dwReader.read_mapping(fileName, mapping)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!mapping.empty()) {
|
while (!mapping.empty()) {
|
||||||
struct addrToLine temp_addrToLine;
|
DwarfLineMapping tmp_mapping = mapping.front();
|
||||||
temp_addrToLine = mapping.front();
|
|
||||||
|
|
||||||
// FIXME reuse file_id from previous iteration if file name stays constant
|
// FIXME reuse file_id from previous iteration if file name stays constant
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "SELECT file_id FROM dbg_filename "
|
ss << "SELECT file_id FROM dbg_filename "
|
||||||
<< "WHERE path = '" << temp_addrToLine.lineSource << "' "
|
<< "WHERE path = '" << tmp_mapping.line_source << "' "
|
||||||
<< "AND variant_id = " << m_variant_id;
|
<< "AND variant_id = " << m_variant_id;
|
||||||
|
|
||||||
MYSQL_RES *res = db->query(ss.str().c_str(), true);
|
MYSQL_RES *res = db->query(ss.str().c_str(), true);
|
||||||
@ -380,17 +380,18 @@ bool ElfImporter::import_mapping(std::string fileName)
|
|||||||
|
|
||||||
// INSERT group entry
|
// INSERT group entry
|
||||||
std::stringstream sql;
|
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) {
|
if (row != NULL) {
|
||||||
sql << row[0] << ")";
|
sql << row[0] << ")";
|
||||||
} else {
|
} else {
|
||||||
// this should not happen
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Skip duplicated entries with ON DUPLICATE KEY UPDATE (?)
|
// 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())) {
|
sql.str().c_str())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user