#include #include #include #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) { 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& 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(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& 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