diff options
Diffstat (limited to 'lib/Plugins/CCpp.cpp')
-rw-r--r-- | lib/Plugins/CCpp.cpp | 197 |
1 files changed, 110 insertions, 87 deletions
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 82c5677d..83b0e9a3 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -33,6 +33,8 @@ #include "CommLayerInner.h" #include "Polkit.h" +using namespace std; + #define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern" #define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u" @@ -48,9 +50,9 @@ CAnalyzerCCpp::CAnalyzerCCpp() : m_nDebugInfoCacheMB(4000) {} -static std::string CreateHash(const std::string& pInput) +static string CreateHash(const char *pInput) { - std::string ret = ""; + string ret; HASHContext* hc; unsigned char hash[SHA1_LENGTH]; unsigned int len; @@ -61,7 +63,7 @@ static std::string CreateHash(const std::string& pInput) error_msg_and_die("HASH_Create(HASH_AlgSHA1) failed"); /* paranoia */ } HASH_Begin(hc); - HASH_Update(hc, reinterpret_cast<const unsigned char*>(pInput.c_str()), pInput.length()); + HASH_Update(hc, (const unsigned char*)pInput, strlen(pInput)); HASH_End(hc, hash, &len, sizeof(hash)); HASH_Destroy(hc); @@ -80,9 +82,9 @@ static std::string CreateHash(const std::string& pInput) return hash_str; } -static std::string concat_str_vector(char **strings) +static string concat_str_vector(char **strings) { - std::string result; + string result; while (*strings) { result += *strings++; @@ -92,7 +94,7 @@ static std::string concat_str_vector(char **strings) return result; } -static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) +static pid_t ExecVP(char** pArgs, uid_t uid, string& pOutput) { int pipeout[2]; pid_t child; @@ -100,7 +102,7 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) struct passwd* pw = getpwuid(uid); if (!pw) { - throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot get GID for UID."); + throw CABRTException(EXCEP_PLUGIN, string(__func__) + ": cannot get GID for UID."); } xpipe(pipeout); @@ -217,7 +219,7 @@ static int rate_backtrace(const char *backtrace) { if (backtrace[i] == '#') /* this separates frames from each other */ { - std::string s(backtrace + i + 1, len); + string s(backtrace + i + 1, len); for (j=0; j<len; j++) /* replace tabs with spaces */ if (s[j] == '\t') s[j] = ' '; @@ -249,12 +251,12 @@ static int rate_backtrace(const char *backtrace) return 0; } -static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace) +static void GetBacktrace(const char *pDebugDumpDir, const char *pDebugInfoDirs, string& pBacktrace) { update_client(_("Getting backtrace...")); - std::string UID; - std::string executable; + string UID; + string executable; { CDebugDump dd; dd.Open(pDebugDumpDir); @@ -270,10 +272,24 @@ static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace) char* args[11]; args[0] = (char*)"gdb"; args[1] = (char*)"-batch"; + // when/if gdb supports it: // (https://bugzilla.redhat.com/show_bug.cgi?id=528668): args[2] = (char*)"-ex"; - args[3] = (char*)"set debug-file-directory /usr/lib/debug:" DEBUGINFO_CACHE_DIR"/usr/lib/debug"; + string dfd = "set debug-file-directory /usr/lib/debug"; + const char *p = pDebugInfoDirs; + while (1) + { + const char *colon_or_nul = strchrnul(p, ':'); + dfd += ':'; + dfd.append(p, colon_or_nul - p); + dfd += "/usr/lib/debug"; + if (*colon_or_nul != ':') + break; + p = colon_or_nul + 1; + } + args[3] = (char*)dfd.c_str(); + /* * Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE * was deleted (as often happens during system updates): @@ -282,22 +298,23 @@ static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace) * See https://bugzilla.redhat.com/show_bug.cgi?id=525721 */ args[4] = (char*)"-ex"; - args[5] = xasprintf("file %s", executable.c_str()); + string file = ssprintf("file %s", executable.c_str()); + args[5] = (char*)file.c_str(); + args[6] = (char*)"-ex"; - args[7] = xasprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir); + string corefile = ssprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir); + args[7] = (char*)corefile.c_str(); + args[8] = (char*)"-ex"; args[9] = (char*)"thread apply all backtrace full"; args[10] = NULL; ExecVP(args, atoi(UID.c_str()), pBacktrace); - - free(args[5]); - free(args[7]); } -static std::string GetIndependentBacktrace(const std::string& pBacktrace) +static string GetIndependentBacktrace(const char *pBacktrace) { - std::string header; + string header; bool in_bracket = false; bool in_quote = false; bool in_header = false; @@ -305,7 +322,7 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace) bool has_at = false; bool has_filename = false; bool has_bracket = false; - std::set<std::string> set_headers; + set<string> set_headers; /* Backtrace example: #0 0x00007f047e21af70 in __nanosleep_nocancel () from /lib64/libc-2.10.1.so @@ -328,7 +345,7 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace) seconds = 1260 ok = true */ - const char *bk = pBacktrace.c_str(); + const char *bk = pBacktrace; while (*bk) { if (bk[0] == '#' @@ -348,11 +365,11 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace) { in_digit = true; } - else if (bk[0] == '\\' && bk[1] == '\"') + else if (bk[0] == '\\' && bk[1] == '"') { bk++; } - else if (*bk == '\"') + else if (*bk == '"') { in_quote = in_quote == true ? false : true; } @@ -406,8 +423,8 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace) bk++; } - std::string pIndependentBacktrace; - std::set<std::string>::iterator it = set_headers.begin(); + string pIndependentBacktrace; + set<string>::iterator it = set_headers.begin(); for (; it != set_headers.end(); it++) { pIndependentBacktrace += *it; @@ -416,39 +433,35 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace) return pIndependentBacktrace; } -static void GetIndependentBuildIdPC(const std::string& pBuildIdPC, std::string& pIndependentBuildIdPC) +static void GetIndependentBuildIdPC(const char *unstrip_n_output, string& pIndependentBuildIdPC) { - int ii = 0; - while (ii < pBuildIdPC.length()) + // lines look like this: + // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] + // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep /usr/lib/debug/bin/sleep.debug [exe] + // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . - linux-vdso.so.1 + const char *line = unstrip_n_output; + while (*line) { - std::string line; - int jj = 0; - - while (pBuildIdPC[ii] != '\n' && ii < pBuildIdPC.length()) - { - line += pBuildIdPC[ii]; - ii++; - } - while (line[jj] != '+' && jj < line.length()) + const char *eol = strchrnul(line, '\n'); + const char *plus = (char*)memchr(line, '+', eol - line); + if (plus) { - jj++; - } - jj++; - while (line[jj] != '@' && jj < line.length()) - { - if (!isspace(line[jj])) + while (++plus < eol && *plus != '@') { - pIndependentBuildIdPC += line[jj]; + if (!isspace(*plus)) + { + pIndependentBuildIdPC += *plus; + } } - jj++; } - ii++; + if (*eol != '\n') break; + line = eol + 1; } } -static std::string run_unstrip_n(const char *pDebugDumpDir) +static string run_unstrip_n(const char *pDebugDumpDir) { - std::string UID; + string UID; { CDebugDump dd; dd.Open(pDebugDumpDir); @@ -461,7 +474,7 @@ static std::string run_unstrip_n(const char *pDebugDumpDir) args[2] = (char*)"-n"; args[3] = NULL; - std::string output; + string output; ExecVP(args, atoi(UID.c_str()), output); free(args[1]); @@ -481,10 +494,10 @@ static bool is_hexstr(const char* str) } return true; } -static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) +static void InstallDebugInfos(const char *pDebugDumpDir, const char *debuginfo_dirs, string& build_ids) { log("Getting module names, file names, build IDs from core file"); - std::string unstrip_list = run_unstrip_n(pDebugDumpDir); + string unstrip_list = run_unstrip_n(pDebugDumpDir); log("Builting list of missing debuginfos"); // lines look like this: @@ -542,7 +555,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) } //missing vector is unused for now, but TODO: use it to install only needed debuginfos - std::string package; + string package; { CDebugDump dd; dd.Open(pDebugDumpDir); @@ -629,7 +642,7 @@ Another application is holding the yum lock, cannot continue bool already_installed = false; #endif char buff[1024]; - std::string packageName = package.substr(0, package.rfind("-", package.rfind("-")-1)); + string packageName = package.substr(0, package.rfind("-", package.rfind("-")-1)); while (fgets(buff, sizeof(buff), pipeout_fp)) { int last = strlen(buff) - 1; @@ -662,7 +675,7 @@ Another application is holding the yum lock, cannot continue fclose(pipeout_fp); kill(child, SIGTERM); wait(NULL); - throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot install debuginfos for " + pPackage); + throw CABRTException(EXCEP_PLUGIN, string(__func__) + ": cannot install debuginfos for " + pPackage); } #endif } @@ -674,7 +687,7 @@ Another application is holding the yum lock, cannot continue /* Needs gdb feature from here: https://bugzilla.redhat.com/show_bug.cgi?id=528668 * It is slated to be in F12/RHEL6. */ -static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) +static void InstallDebugInfos(const char *pDebugDumpDir, const char *debuginfo_dirs, string& build_ids) { update_client(_("Searching for debug-info packages...")); @@ -703,8 +716,8 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) /* SELinux guys are not happy with /tmp, using /var/run/abrt */ char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL)); /* log() goes to stderr/syslog, it's ok to use it here */ - VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR); - execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR, NULL); + VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs); + execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs, NULL); exit(1); } @@ -750,7 +763,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) wait(NULL); } -static double get_dir_size(const char *dirname, std::string *worst_file, double *maxsz) +static double get_dir_size(const char *dirname, string *worst_file, double *maxsz) { DIR *dp = opendir(dirname); if (dp == NULL) @@ -763,7 +776,7 @@ static double get_dir_size(const char *dirname, std::string *worst_file, double { if (dot_or_dotdot(ep->d_name)) continue; - std::string dname = concat_path_file(dirname, ep->d_name); + string dname = concat_path_file(dirname, ep->d_name); if (lstat(dname.c_str(), &stats) != 0) continue; if (S_ISDIR(stats.st_mode)) @@ -801,7 +814,7 @@ static void trim_debuginfo_cache(unsigned max_mb) { while (1) { - std::string worst_file; + string worst_file; double maxsz = 0; double cache_sz = get_dir_size(DEBUGINFO_CACHE_DIR, &worst_file, &maxsz); if (cache_sz / (1024 * 1024) < max_mb) @@ -813,12 +826,12 @@ static void trim_debuginfo_cache(unsigned max_mb) } } -std::string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir) +string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir) { log(_("Getting local universal unique identification...")); - std::string executable; - std::string package; + string executable; + string package; { CDebugDump dd; dd.Open(pDebugDumpDir); @@ -826,19 +839,19 @@ std::string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir) dd.LoadText(FILENAME_PACKAGE, package); } - std::string buildIdPC = run_unstrip_n(pDebugDumpDir); - std::string independentBuildIdPC; - GetIndependentBuildIdPC(buildIdPC, independentBuildIdPC); - return CreateHash(package + executable + independentBuildIdPC); + string unstrip_n_output = run_unstrip_n(pDebugDumpDir); + string independentBuildIdPC; + GetIndependentBuildIdPC(unstrip_n_output.c_str(), independentBuildIdPC); + return CreateHash((package + executable + independentBuildIdPC).c_str()); } -std::string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) +string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) { log(_("Getting global universal unique identification...")); - std::string backtrace; - std::string executable; - std::string package; + string backtrace; + string executable; + string package; { CDebugDump dd; dd.Open(pDebugDumpDir); @@ -846,8 +859,8 @@ std::string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) dd.LoadText(FILENAME_EXECUTABLE, executable); dd.LoadText(FILENAME_PACKAGE, package); } - std::string independentBacktrace = GetIndependentBacktrace(backtrace); - return CreateHash(package + executable + independentBacktrace); + string independentBacktrace = GetIndependentBacktrace(backtrace.c_str()); + return CreateHash((package + executable + independentBacktrace).c_str()); } static bool DebuginfoCheckPolkit(int uid) @@ -881,9 +894,9 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force) { update_client(_("Starting report creation...")); - std::string package; - std::string backtrace; - std::string UID; + string package; + string backtrace; + string UID; CDebugDump dd; dd.Open(pDebugDumpDir); @@ -901,18 +914,21 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force) dd.LoadText(FILENAME_UID, UID); dd.Close(); /* do not keep dir locked longer than needed */ - std::string build_ids; - if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str()))) { - if (m_nDebugInfoCacheMB > 0) + string build_ids; + if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str()))) + { + if (m_nDebugInfoCacheMB > 0) + { trim_debuginfo_cache(m_nDebugInfoCacheMB); - InstallDebugInfos(pDebugDumpDir, build_ids); + } + InstallDebugInfos(pDebugDumpDir, m_sDebugInfoDirs.c_str(), build_ids); } else { VERB1 log(_("Skipping debuginfo installation")); } - GetBacktrace(pDebugDumpDir, backtrace); + GetBacktrace(pDebugDumpDir, m_sDebugInfoDirs.c_str(), backtrace); dd.Open(pDebugDumpDir); dd.SaveText(FILENAME_BACKTRACE, (build_ids + backtrace).c_str()); @@ -926,7 +942,7 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force) void CAnalyzerCCpp::Init() { - std::ifstream fInCorePattern; + ifstream fInCorePattern; fInCorePattern.open(CORE_PATTERN_IFACE); if (fInCorePattern.is_open()) { @@ -951,22 +967,22 @@ void CAnalyzerCCpp::Init() } } - std::ofstream fOutCorePattern; + ofstream fOutCorePattern; fOutCorePattern.open(CORE_PATTERN_IFACE); if (fOutCorePattern.is_open()) { - fOutCorePattern << CORE_PATTERN << std::endl; + fOutCorePattern << CORE_PATTERN << endl; fOutCorePattern.close(); } } void CAnalyzerCCpp::DeInit() { - std::ofstream fOutCorePattern; + ofstream fOutCorePattern; fOutCorePattern.open(CORE_PATTERN_IFACE); if (fOutCorePattern.is_open()) { - fOutCorePattern << m_sOldCorePattern << std::endl; + fOutCorePattern << m_sOldCorePattern << endl; fOutCorePattern.close(); } } @@ -999,6 +1015,13 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings) { m_bInstallDebugInfo = string_to_bool(it->second.c_str()); } + m_sDebugInfoDirs = DEBUGINFO_CACHE_DIR; + it = pSettings.find("ReadonlyLocalDebugInfoDirs"); + if (it != end) + { + m_sDebugInfoDirs += ':'; + m_sDebugInfoDirs += it->second; + } } //ok to delete? @@ -1016,7 +1039,7 @@ PLUGIN_INFO(ANALYZER, CAnalyzerCCpp, "CCpp", "0.0.1", - "Simple C/C++ analyzer plugin.", + "Analyzes crashes in C/C++ programs", "zprikryl@redhat.com", "https://fedorahosted.org/abrt/wiki", ""); |