import-trace: import debug info

If the --debug option is set, the line number table of the elf binary will
be imported into the database. The information will be stored in the
"dbg_mapping" table.

If the --sources option is set, the source files will be imported
into the database. Only the files that were actually used in the
elf binary will be imported.

Change-Id: I0e9de6b456bc42b329c1700c25e5839d9552cdbb
This commit is contained in:
Richard Hellwig
2014-01-24 16:44:56 +01:00
parent d307dd2ecb
commit 13175c259b
7 changed files with 551 additions and 6 deletions

View File

@ -11,6 +11,8 @@ set(SRCS
Demangler.cc
Disassembler.hpp
Disassembler.cc
DwarfReader.cc
DwarfReader.hpp
elfinfo/elfinfo.cc
elfinfo/elfinfo.h
gzstream/gzstream.C
@ -65,7 +67,7 @@ mark_as_advanced(FAIL_OBJDUMP)
add_library(fail-util ${SRCS})
add_dependencies(fail-util fail-comm)
target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${ZLIB_LIBRARIES})
target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${ZLIB_LIBRARIES} dwarf elf)
option(BUILD_LLVM_DISASSEMBLER "Build the LLVM-based disassembler (LLVM 3.3 preferred, for 3.1 and 3.2 read doc/how-to-build.txt)" OFF)
if (BUILD_LLVM_DISASSEMBLER)

View File

@ -0,0 +1,258 @@
#include <fstream>
#include <fcntl.h>
#include <unistd.h>
#include "DwarfReader.hpp"
#include "libdwarf.h"
#include "libelf.h"
#include "Logger.hpp"
/**
* This source code is based on bcov 0.2.
* Sourcefile: src/coverage.cpp
* http://bcov.sourceforge.net/
* GNU GENERAL PUBLIC LICENSE
*/
using namespace fail;
using namespace std;
static Logger LOG("DwarfReader");
static void dwarfErrorHandler(Dwarf_Error error, Dwarf_Ptr /*userData*/)
{
char* msg=dwarf_errmsg(error);
cerr << "dwarf error: " << msg << endl;
}
static string normalize(const string& filePath)
{
// A quick scan first...
bool hadSep=false,needsFix=false;
string::size_type len=filePath.length();
if (!needsFix)
for (string::size_type index=0;index<len;index++) {
char c=filePath[index];
if (c=='/') {
if (hadSep) {
needsFix=true;
}
hadSep=true;
} else {
if (c=='.') {
if (hadSep||(index==0)) {
needsFix=true;
}
}
hadSep=false;
}
}
if (!needsFix) {
return filePath;
}
hadSep=false;
// Construct the fixed result
string result;
for (string::size_type index=0;index<len;index++) {
char c=filePath[index];
if (c=='/') {
if (hadSep) {
} else result+=c;
hadSep=true;
} else {
if ((c=='.')&&(hadSep||(index==0))) {
if (index+1>=len) {
if (hadSep)
result.resize(result.length()-1);
} else {
result+=c;
}
continue;
}
char n=filePath[index+1];
if (n=='/') {
index++; continue;
}
if (n=='.') {
if (index+2>=len) {
index++;
string::size_type split=result.rfind('/',result.length()-2);
if (split!=string::npos) {
if (result.substr(split)!="/../") {
result.resize(split);
}
} else if (result.length()>0) {
if ((result!="../")&&(result!="/")) {
result.clear();
}
} else result="..";
continue;
} else {
n=filePath[index+2];
if (n=='/') {
index+=2;
string::size_type split=result.rfind('/',result.length()-2);
if (split!=string::npos) {
if (result.substr(split)!="/../") {
result.resize(split+1);
}
} else if (result.length()>0) {
if ((result!="../")&&(result!="/")) {
result.clear();
}
} else result="../";
continue;
}
}
}
}
result+=c; hadSep=false;
}
return result;
}
bool DwarfReader::read_source_files(const std::string& fileName,std::list<std::string>& lines) {
// Open The file
int fd=open(fileName.c_str(),O_RDONLY);
if (fd<0) return false;
// Initialize libdwarf
Dwarf_Debug dbg;
int status = dwarf_init(fd, DW_DLC_READ,dwarfErrorHandler,0,&dbg,0);
if (status==DW_DLV_ERROR) { close(fd); return false; }
if (status==DW_DLV_NO_ENTRY) { close(fd); return true; }
// Iterator over the headers
Dwarf_Unsigned header;
while (dwarf_next_cu_header(dbg,0,0,0,0,&header,0)==DW_DLV_OK) {
// Access the die
Dwarf_Die die;
if (dwarf_siblingof(dbg,0,&die,0)!=DW_DLV_OK)
return false;
// Get the source lines
Dwarf_Line* lineBuffer;
Dwarf_Signed lineCount;
if (dwarf_srclines(die,&lineBuffer,&lineCount,0)!=DW_DLV_OK)
continue; //return false;
// Store them
for (int index=0;index<lineCount;index++) {
Dwarf_Unsigned lineNo;
if (dwarf_lineno(lineBuffer[index],&lineNo,0)!=DW_DLV_OK)
return false;
char* lineSource;
if (dwarf_linesrc(lineBuffer[index],&lineSource,0)!=DW_DLV_OK)
return false;
Dwarf_Bool isCode;
if (dwarf_linebeginstatement(lineBuffer[index],&isCode,0)!=DW_DLV_OK)
return false;
Dwarf_Addr addr;
if (dwarf_lineaddr(lineBuffer[index],&addr,0)!=DW_DLV_OK)
return false;
if (lineNo&&isCode) {
//LOG << "lineNo: " << lineNo << " addr: " << reinterpret_cast<void*>(addr) << " line source:" << normalize(lineSource) << endl;
lines.push_back(normalize(lineSource));
}
dwarf_dealloc(dbg,lineSource,DW_DLA_STRING);
}
// Release the memory
for (int index=0;index<lineCount;index++)
dwarf_dealloc(dbg,lineBuffer[index],DW_DLA_LINE);
dwarf_dealloc(dbg,lineBuffer,DW_DLA_LIST);
}
//Remove duplicated entrys
lines.sort();
lines.unique();
// Shut down libdwarf
if (dwarf_finish(dbg,0)!=DW_DLV_OK)
return false;
close(fd);
return true;
}
bool DwarfReader::read_mapping(std::string fileName, std::list<addrToLine>& addrToLineList) {
// Open The file
int fd=open(fileName.c_str(),O_RDONLY);
if (fd<0) {
return false;
}
// Initialize libdwarf
Dwarf_Debug dbg;
int status = dwarf_init(fd, DW_DLC_READ,dwarfErrorHandler,0,&dbg,0);
if (status==DW_DLV_ERROR) {
close(fd);
return false;
}
if (status==DW_DLV_NO_ENTRY) {
close(fd);
return true;
}
// Iterator over the headers
Dwarf_Unsigned header;
while (dwarf_next_cu_header(dbg,0,0,0,0,&header,0)==DW_DLV_OK) {
// Access the die
Dwarf_Die die;
if (dwarf_siblingof(dbg,0,&die,0)!=DW_DLV_OK) {
return false;
}
// Get the source lines
Dwarf_Line* lineBuffer;
Dwarf_Signed lineCount;
if (dwarf_srclines(die,&lineBuffer,&lineCount,0)!=DW_DLV_OK) {
continue; //return false;
}
// Store them
for (int index=0;index<lineCount;index++) {
Dwarf_Unsigned lineNo;
if (dwarf_lineno(lineBuffer[index],&lineNo,0)!=DW_DLV_OK) {
return false;
}
char* lineSource;
if (dwarf_linesrc(lineBuffer[index],&lineSource,0)!=DW_DLV_OK) {
return false;
}
Dwarf_Bool isCode;
if (dwarf_linebeginstatement(lineBuffer[index],&isCode,0)!=DW_DLV_OK) {
return false;
}
Dwarf_Addr addr;
if (dwarf_lineaddr(lineBuffer[index],&addr,0)!=DW_DLV_OK) {
return false;
}
if (lineNo&&isCode) {
struct addrToLine newLine = { (int) addr, (int) lineNo, normalize(lineSource) };
addrToLineList.push_back(newLine);
}
dwarf_dealloc(dbg,lineSource,DW_DLA_STRING);
}
// Release the memory
for (int index=0;index<lineCount;index++) {
dwarf_dealloc(dbg,lineBuffer[index],DW_DLA_LINE);
}
dwarf_dealloc(dbg,lineBuffer,DW_DLA_LIST);
}
// Shut down libdwarf
if (dwarf_finish(dbg,0)!=DW_DLV_OK) {
return false;
}
close(fd);
return true;
}

View File

@ -0,0 +1,40 @@
#ifndef __DWARFREADER_HPP__
#define __DWARFREADER_HPP__
#include <string>
#include <ostream>
#include <list>
namespace fail {
/**
* This source code is based on bcov 0.2.
* Sourcefile: src/coverage.cpp
* http://bcov.sourceforge.net/
* GNU GENERAL PUBLIC LICENSE
*/
struct addrToLine {
int absoluteAddr;
int lineNumber;
std::string lineSource;
};
/**
* \class DwarfReader
* ToDO
*/
class DwarfReader {
public:
bool read_source_files(const std::string& fileName, std::list<std::string>& lines);
bool read_mapping(std::string fileName, std::list<addrToLine>& addrToLineList);
};
} // end-of-namespace fail
#endif //__DwarfREADER_HPP__