13 #include <sys/types.h>
23 #include <sys/types.h>
53#include "abg-internal.h"
57ABG_BEGIN_EXPORT_DECLARATIONS
63ABG_END_EXPORT_DECLARATIONS
88#ifndef ABIGAIL_ROOT_SYSTEM_LIBDIR
89#error the macro ABIGAIL_ROOT_SYSTEM_LIBDIR must be set at compile time
92 static __thread
const char* system_libdir(ABIGAIL_ROOT_SYSTEM_LIBDIR);
106 |
static_cast<unsigned>(r));}
118 &
static_cast<unsigned>(r));}
131 |
static_cast<unsigned>(r));
176#define DECLARE_STAT(st) \
178 memset(&st, 0, sizeof(st))
186 struct timeval begin_timeval;
187 struct timeval end_timeval;
200 : priv_(new
timer::priv(k))
215 if (gettimeofday(&priv_->begin_timeval, 0))
229 if (gettimeofday(&priv_->end_timeval, 0))
240{
return priv_->end_timeval.tv_sec - priv_->begin_timeval.tv_sec;}
260 time_t& milliseconds)
const
262 time_t elapsed_seconds =
263 priv_->end_timeval.tv_sec - priv_->begin_timeval.tv_sec;
264 suseconds_t elapsed_usecs =
265 ((priv_->end_timeval.tv_sec * 1000000) + priv_->end_timeval.tv_usec)
266 - ((priv_->begin_timeval.tv_sec * 1000000) + priv_->begin_timeval.tv_usec);
270 hours = elapsed_seconds / 3600;
271 minutes = (elapsed_seconds % 3600) / 60;
272 seconds = (elapsed_seconds % 3600) % 60;
273 if (elapsed_seconds == 0)
274 milliseconds = elapsed_usecs / 1000;
285 time_t hours = 0, minutes = 0, seconds = 0;
288 value(hours, minutes, seconds, msecs);
290 std::ostringstream o;
338get_stat(
const string& path,
340{
return (lstat(path.c_str(), s) == 0);}
352 return get_stat(path, &st);
373 DIR* dir = opendir(path.c_str());
378 dirent *result = readdir(dir);
379 if (result == NULL && errno != 0)
384 return result == NULL;
398 if (!get_stat(path, &st))
401 if (S_ISREG(st.st_mode))
404 string symlink_target_path;
420 const string& archive_prefix)
422 string ctf_archive = directory +
"/" + archive_prefix +
".ctfa";
444 const vector<char**>& debug_info_root_paths)
451 debug_info_root_paths,
480 const vector<char**>& debug_info_root_paths)
487 debug_info_root_paths,
497 if (
dir_name(elf_file_path, dirname)
503 for (
const auto& path : debug_info_root_paths)
524 const vector<char**>& debug_info_root_paths)
530 elf::reader r(elf_file_path, debug_info_root_paths, env);
549 if (!get_stat(path, &st))
552 if (S_ISDIR(st.st_mode))
555 string symlink_target_path;
557 return is_dir(symlink_target_path);
562static const char* ANONYMOUS_STRUCT_INTERNAL_NAME =
"__anonymous_struct__";
563static const char* ANONYMOUS_UNION_INTERNAL_NAME =
"__anonymous_union__";
564static const char* ANONYMOUS_ENUM_INTERNAL_NAME =
"__anonymous_enum__";
565static const char* ANONYMOUS_SUBRANGE_INTERNAL_NAME =
"__anonymous_range__";
567static int ANONYMOUS_STRUCT_INTERNAL_NAME_LEN =
568 strlen(ANONYMOUS_STRUCT_INTERNAL_NAME);
570static int ANONYMOUS_UNION_INTERNAL_NAME_LEN =
571 strlen(ANONYMOUS_UNION_INTERNAL_NAME);
573static int ANONYMOUS_ENUM_INTERNAL_NAME_LEN =
574 strlen(ANONYMOUS_ENUM_INTERNAL_NAME);
581{
return ANONYMOUS_STRUCT_INTERNAL_NAME;}
588{
return ANONYMOUS_UNION_INTERNAL_NAME;}
590static int ANONYMOUS_SUBRANGE_INTERNAL_NAME_LEN =
591 strlen(ANONYMOUS_SUBRANGE_INTERNAL_NAME);
598{
return ANONYMOUS_ENUM_INTERNAL_NAME;}
605{
return ANONYMOUS_SUBRANGE_INTERNAL_NAME;}
641 string::size_type l_pos1 = 0, r_pos1 = 0;
642 const string::size_type l_length = l.length(), r_length = r.length();
644 while (l_pos1 < l_length && r_pos1 < r_length)
646 string::size_type l_pos2 = l.find(
"::", l_pos1);
647 string::size_type r_pos2 = r.find(
"::", r_pos1);
648 if (l_pos2 == string::npos)
650 if (r_pos2 == string::npos)
653 if (l.compare(l_pos1, l_pos2 - l_pos1, r,
654 r_pos1, r_pos2 - r_pos1)
655 && (l.compare(l_pos1,
656 ANONYMOUS_STRUCT_INTERNAL_NAME_LEN,
657 ANONYMOUS_STRUCT_INTERNAL_NAME)
659 ANONYMOUS_STRUCT_INTERNAL_NAME_LEN,
660 ANONYMOUS_STRUCT_INTERNAL_NAME))
661 && (l.compare(l_pos1,
662 ANONYMOUS_UNION_INTERNAL_NAME_LEN,
663 ANONYMOUS_UNION_INTERNAL_NAME)
665 ANONYMOUS_UNION_INTERNAL_NAME_LEN,
666 ANONYMOUS_UNION_INTERNAL_NAME))
667 && (l.compare(l_pos1,
668 ANONYMOUS_ENUM_INTERNAL_NAME_LEN,
669 ANONYMOUS_ENUM_INTERNAL_NAME)
671 ANONYMOUS_ENUM_INTERNAL_NAME_LEN,
672 ANONYMOUS_ENUM_INTERNAL_NAME)))
675 l_pos1 = l_pos2 == l_length ? l_pos2 : l_pos2 + 2;
676 r_pos1 = r_pos2 == r_length ? r_pos2 : r_pos2 + 2;
679 return (l_pos1 == l_length) == (r_pos1 == r_length);
700 if (!get_stat(file_path, &st))
703 if (!S_ISLNK(st.st_mode))
706 char *link_target_path = realpath(file_path.c_str(), NULL);
707 if (!link_target_path)
710 target_path = link_target_path;
711 free(link_target_path);
731 bool keep_separator_at_end)
739 char *p = strdup(path.c_str());
740 char *r = ::dirname(p);
743 if (keep_separator_at_end
744 &&
dir_name.length() < path.length())
767 char *p = strdup(path.c_str());
768 char *f = ::basename(p);
791 char *realp = realpath(path.c_str(), NULL);
808 memset(&st, 0,
sizeof (st));
812 stat_result = stat(dir_path.c_str(), &st);
813 if (stat_result == 0)
816 if (!S_ISDIR (st.st_mode))
822 cmd =
"mkdir -p " + dir_path;
824 if (system(cmd.c_str()))
863 if (!prog_name.empty())
864 out << prog_name <<
": ";
876check_file(
const string& path, ostream& out,
const string& prog_name)
880 emit_prefix(prog_name, out) <<
"file " << path <<
" does not exist\n";
886 emit_prefix(prog_name, out) << path <<
" is not a regular file\n";
904check_dir(
const string& path, ostream& out,
const string& prog_name)
908 emit_prefix(prog_name, out) <<
"path " << path <<
" does not exist\n";
914 emit_prefix(prog_name, out) << path <<
" is not a directory\n";
931 string::size_type str_len = str.length(), suffix_len = suffix.length();
933 if (str_len < suffix_len)
935 return str.compare(str_len - suffix_len, suffix_len, suffix) == 0;
954 string::size_type prefix_len = prefix.length();
955 if (prefix_len > str.length())
958 return str.compare(0, prefix.length(), prefix) == 0;
969 for (string::const_iterator i = str.begin(); i != str.end(); ++i)
994 for (string::const_iterator i = str.begin(); i != str.end(); ++i)
996 unsigned char c = *i;
999 || (c >= 0x7F && c <= 0x9F))
1021 const string& delims,
1022 vector<string>& result)
1024 size_t current = 0, next;
1025 bool did_split =
false;
1030 while (current < input_string.size() && isspace(input_string[current]))
1033 if (current >= input_string.size())
1036 next = input_string.find_first_of(delims, current);
1037 if (next == string::npos)
1039 string s = input_string.substr(current);
1041 result.push_back(input_string.substr(current));
1042 did_split = (current != 0);
1045 string s = input_string.substr(current, next - current);
1048 result.push_back(input_string.substr(current, next - current));
1053 while (next != string::npos);
1071 const string& prefix,
1075 if (prefix.length() >= input_string.length())
1078 if (input_string.compare(0, prefix.length(), prefix) != 0)
1083 suffix = input_string.substr(prefix.length());
1100common_prefix(
const string& s1,
const string& s2,
string &result)
1102 if (s1.length() == 0 || s2.length() == 0)
1106 for (
size_t i = 0; i < s1.length() && i< s2.length(); ++i)
1112 return !result.empty();
1131 string prefix_candidate;
1132 bool found_prefix =
false;
1134 if (input_strings.size() == 1)
1136 if (
dir_name(input_strings.front(), prefix,
1143 for (vector<string>::const_iterator i = input_strings.begin();
1144 i != input_strings.end();
1148 if (prefix_candidate.empty())
1150 prefix_candidate = cur_str;
1155 if (common_prefix(prefix_candidate, cur_str, s))
1158 prefix_candidate = s;
1159 found_prefix =
true;
1165 prefix = prefix_candidate;
1178 string major, minor, revision, version_string, suffix;
1180 version_string = major +
"." + minor +
"." + revision + suffix;
1181 return version_string;
1190 string major, minor, version_string;
1192 version_string = major +
"." + minor;
1193 return version_string;
1222#define TMP_BUF_LEN 1024 + 1
1223 char tmp_buf[TMP_BUF_LEN];
1224 memset(tmp_buf, 0, TMP_BUF_LEN);
1226 while (fgets(tmp_buf, TMP_BUF_LEN, stream))
1228 lines.push_back(tmp_buf);
1229 memset(tmp_buf, 0, TMP_BUF_LEN);
1232 if (pclose(stream) == -1)
1253 const string& option,
1254 vector<string>& arguments)
1256 string s = input_str;
1262 s = s.substr(0, s.size() - 1);
1284 vector<string> query_output;
1290 + rpm_path +
" 2> /dev/null | grep .so",
1293 for (vector<string>::const_iterator line = query_output.begin();
1294 line != query_output.end();
1297 string dso = line->substr(0, line->find(
'('));
1300 provided_dsos.insert(dso);
1317 string::size_type start, end;
1318 for (start = 0; start < str.length(); ++start)
1319 if (!isspace(str[start]))
1322 for (end = str.length() - 1; end > 0; --end)
1323 if (!isspace(str[end]))
1326 result = str.substr(start, end - start + 1);
1363 vector<char**>& char_star_stars)
1365 for (vector<char*>::const_iterator i = char_stars.begin();
1366 i != char_stars.end();
1368 char_star_stars.push_back(
const_cast<char**
>(&*i));
1372struct temp_file::priv
1374 char* path_template_;
1376 shared_ptr<std::fstream> fstream_;
1380 const char* templat =
"/tmp/libabigail-tmp-file-XXXXXX";
1381 int s = strlen(templat);
1382 path_template_ =
new char[s + 1];
1383 memset(path_template_, 0, s + 1);
1384 memcpy(path_template_, templat, s);
1386 fd_ = mkstemp(path_template_);
1390 fstream_.reset(
new std::fstream(path_template_,
1398 if (fd_ && fd_ != -1)
1402 remove(path_template_);
1404 delete [] path_template_;
1411temp_file::temp_file()
1420temp_file::is_good()
const
1421{
return priv_->fstream_->good();}
1428temp_file::get_path()
const
1431 return priv_->path_template_;
1445temp_file::get_stream()
1448 return *priv_->fstream_;
1459 if (result->is_good())
1471 static __thread
bool initialized =
false;
1488 std::ostringstream o;
1503 repr =
"unknown file type";
1506 repr =
"native binary instrumentation file type";
1509 repr =
"ELF file type";
1512 repr =
"archive file type";
1514 case FILE_TYPE_XML_CORPUS:
1515 repr =
"native XML corpus file type";
1517 case FILE_TYPE_XML_CORPUS_GROUP:
1518 repr =
"native XML corpus group file type";
1521 repr =
"RPM file type";
1524 repr =
"SRPM file type";
1527 repr =
"Debian binary file type";
1530 repr =
"Directory type";
1533 repr =
"GNU tar archive type";
1549 const unsigned BUF_LEN = 264;
1550 const unsigned NB_BYTES_TO_READ = 263;
1553 memset(buf, 0, BUF_LEN);
1555 std::streampos initial_pos = in.tellg();
1556 in.read(buf, NB_BYTES_TO_READ);
1557 in.seekg(initial_pos);
1559 if (in.gcount() < 4 || in.bad())
1576 if (strstr(buf,
"debian-binary"))
1613 return FILE_TYPE_XML_CORPUS_GROUP;
1627 return FILE_TYPE_XML_CORPUS;
1629 if ((
unsigned char) buf[0] == 0xed
1630 && (
unsigned char) buf[1] == 0xab
1631 && (
unsigned char) buf[2] == 0xee
1632 && (
unsigned char) buf[3] == 0xdb)
1636 else if (buf[7] == 0x01)
1680 ifstream in(file_path.c_str(), ifstream::binary);
1698 if (str.empty() || str[0] ==
'_')
1701 string::size_type str_len = str.length(), i = 0 ;
1703 for (; i < str_len; ++i)
1712 name = str.substr(0, i);
1728 if (str.empty() || str[0] ==
'-')
1731 string::size_type str_len = str.length(), i = 0;
1732 string::value_type c;
1734 for (; i < str_len; ++i)
1737 string::size_type next_index = i + 1;
1738 if ((next_index < str_len) && c ==
'-' && isdigit(str[next_index]))
1745 name = str.substr(0, i);
1768 string::size_type str_len = str.length(), i = 0;
1769 string::value_type c;
1770 string::size_type last_dot_index = 0, dot_before_last_index = 0;
1772 for (i = str_len - 1; i > 0; --i)
1785 for(--i; i > 0; --i)
1790 dot_before_last_index = i;
1798 arch = str.substr(dot_before_last_index + 1,
1799 last_dot_index - dot_before_last_index - 1);
1815 bool result =
false;
1826 string package_name;
1845 vector<string> query_output;
1851 + rpm_path +
" 2> /dev/null",
1854 for (
auto& line : query_output)
1875 bool result =
false;
1876 string package_name;
1882 result = (package_name ==
"kernel-debuginfo");
1898struct malloced_char_star_deleter
1901 operator()(
char* ptr)
1916std::shared_ptr<char>
1919 using std::shared_ptr;
1921 shared_ptr<char> result;
1923 if (p && p[0] !=
'/')
1925 shared_ptr<char> pwd(get_current_dir_name(),
1926 malloced_char_star_deleter());
1927 string s = string(pwd.get()) +
"/" + p;
1928 result.reset(strdup(s.c_str()), malloced_char_star_deleter());
1931 result.reset(strdup(p), malloced_char_star_deleter());
1952 if (p && p[0] !=
'/')
1954 char* pwd = get_current_dir_name();
1955 string s = string(pwd) +
"/" + p;
1957 result = strdup(s.c_str());
1981handle_file_entry(
const string& file_path,
1992 suppr->set_source_location_to_keep_regex_str(
"^/usr/include/");
1993 suppr->set_is_artificial(
true);
1999 suppr->get_source_locations_to_keep().insert(file_path);
2015handle_fts_entry(
const FTSENT *entry,
2019 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2020 || entry->fts_info == FTS_ERR
2021 || entry->fts_info == FTS_NS)
2024 string fname = entry->fts_name;
2030 handle_file_entry (fname, suppr);
2048gen_suppr_spec_from_headers_root_dir(
const string& headers_root_dir,
2051 if (!headers_root_dir.empty())
2053 char* paths[] = {
const_cast<char*
>(headers_root_dir.c_str()), 0};
2055 if (FTS *file_hierarchy = fts_open(paths, FTS_LOGICAL|FTS_NOCHDIR, NULL))
2058 while ((entry = fts_read(file_hierarchy)))
2059 handle_fts_entry(entry, result);
2060 fts_close(file_hierarchy);
2081 const vector<string>& header_files)
2085 for (vector<string>::const_iterator root_dir = headers_root_dirs.begin();
2086 root_dir != headers_root_dirs.end();
2088 gen_suppr_spec_from_headers_root_dir(*root_dir, result);
2090 for (vector<string>::const_iterator file = header_files.begin();
2091 file != header_files.end();
2093 handle_file_entry(*file, result);
2113 const vector<string>& header_files)
2116 vector<string> root_dirs;
2118 if (!headers_root_dir.empty())
2119 root_dirs.push_back(headers_root_dir);
2137 vector<string> header_files;
2168 (
const std::vector<std::string>& abi_whitelist_paths)
2171 std::vector<std::string> whitelisted_names;
2172 for (std::vector<std::string>::const_iterator
2173 path_iter = abi_whitelist_paths.begin(),
2174 path_end = abi_whitelist_paths.end();
2175 path_iter != path_end;
2186 for (ini::config::sections_type::const_iterator
2187 section_iter = whitelist_sections.begin(),
2188 section_end = whitelist_sections.end();
2189 section_iter != section_end;
2192 std::string section_name = (*section_iter)->get_name();
2196 for (ini::config::properties_type::const_iterator
2197 prop_iter = (*section_iter)->get_properties().begin(),
2198 prop_end = (*section_iter)->get_properties().end();
2199 prop_iter != prop_end;
2204 if (prop->has_empty_value())
2206 const std::string& name = prop->get_name();
2208 whitelisted_names.push_back(name);
2215 if (!whitelisted_names.empty())
2218 std::sort(whitelisted_names.begin(), whitelisted_names.end());
2219 whitelisted_names.erase(std::unique(whitelisted_names.begin(),
2220 whitelisted_names.end()),
2221 whitelisted_names.end());
2233 fn_suppr->set_label(
"whitelist");
2234 fn_suppr->set_symbol_name_not_regex_str(regex);
2235 fn_suppr->set_drops_artifact_from_ir(
true);
2236 result.push_back(fn_suppr);
2244 var_suppr->set_label(
"whitelist");
2245 var_suppr->set_symbol_name_not_regex_str(regex);
2246 var_suppr->set_drops_artifact_from_ir(
true);
2247 result.push_back(var_suppr);
2258 string default_system_suppr_path;
2260 const char *s = getenv(
"LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE");
2262 default_system_suppr_path = s;
2264 if (default_system_suppr_path.empty())
2265 default_system_suppr_path =
2268 return default_system_suppr_path;
2277 string default_user_suppr_path;
2278 const char *s = getenv(
"LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE");
2285 default_user_suppr_path = s;
2286 if (default_user_suppr_path.empty())
2287 default_user_suppr_path =
"~";
2288 default_user_suppr_path +=
"/.abignore";
2291 default_user_suppr_path = s;
2293 return default_user_suppr_path;
2307 string default_system_suppr_path =
2323 string default_user_suppr_path =
2344entry_of_file_with_name(
const FTSENT *entry,
2345 const string& fname,
2346 const string& root_dir)
2349 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2350 || entry->fts_info == FTS_ERR
2351 || entry->fts_info == FTS_NS)
2354 string fpath = ::basename(entry->fts_path);
2377 const string& file_path_to_look_for,
2380 char* paths[] = {
const_cast<char*
>(root_dir.c_str()), 0};
2382 FTS *file_hierarchy = fts_open(paths,
2383 FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2384 if (!file_hierarchy)
2387 string r = root_dir;
2392 while ((entry = fts_read(file_hierarchy)))
2394 if (entry_of_file_with_name(entry, file_path_to_look_for, r))
2396 result = entry->fts_path;
2400 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2402 fts_set(file_hierarchy, entry, FTS_SKIP);
2407 fts_close(file_hierarchy);
2424 const string& file_path_to_look_for,
2427 if (root_dirs.empty())
2430 for (
const auto& root_dir : root_dirs)
2459 const vector<string>& deps_dirs,
2460 set<string>& dependencies)
2462 const vector<string>& set_of_needed = korpus.
get_needed();
2463 if (set_of_needed.empty())
2466 bool found_at_least_one_dependency =
false;
2467 for (
const auto& n :set_of_needed)
2470 if (dependencies.find(n) == dependencies.end()
2473 dependencies.insert(dependency);
2474 found_at_least_one_dependency =
true;
2478 return found_at_least_one_dependency;
2496 const vector<string>& binaries,
2497 const vector<string>& deps_dirs,
2500 vector<string> bins;
2502 for (
const auto& b : binaries)
2506 bins.push_back(bin);
2509 for (
const auto& b : bins)
2514 reader->initialize(b);
2516 corpus_sptr c = reader->read_corpus(stat);
2537 const vector<string>& deps_dirs,
2545 for (
const auto& dep: deps)
2550 reader->initialize(dep);
2552 corpus_sptr c = reader->read_corpus(stat);
2580 const corpus_sptr& korpus,
2581 const vector<string>& binaries,
2582 const vector<string>& bins_dirs)
2584 corpus_group_sptr result (
new corpus_group(korpus->get_environment(),
2585 korpus->get_path()));
2586 result->add_corpus(korpus);
2609 const corpus_sptr& korpus,
2610 const vector<string>& deps_dirs)
2612 corpus_group_sptr result (
new corpus_group(korpus->get_environment(),
2613 korpus->get_path()));
2614 result->add_corpus(korpus);
2642 vector<string>& suppr_paths,
2643 vector<string>& kabi_whitelist_paths,
2648 for (vector<string>::const_iterator i = suppr_paths.begin();
2649 i != suppr_paths.end();
2656 supprs.insert(supprs.end(), wl_suppr.begin(), wl_suppr.end());
2669is_vmlinux(
const FTSENT *entry)
2672 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2673 || entry->fts_info == FTS_ERR
2674 || entry->fts_info == FTS_NS)
2677 string fname = entry->fts_name;
2679 if (fname ==
"vmlinux")
2682 dir_name(entry->fts_path, dirname);
2699is_kernel_module(
const FTSENT *entry)
2702 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2703 || entry->fts_info == FTS_ERR
2704 || entry->fts_info == FTS_NS)
2707 string fname = entry->fts_name;
2729find_vmlinux_and_module_paths(
const string& from,
2730 string &vmlinux_path,
2731 vector<string> &module_paths)
2733 char* path[] = {
const_cast<char*
>(from.c_str()), 0};
2735 FTS *file_hierarchy = fts_open(path, FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2736 if (!file_hierarchy)
2739 bool found_vmlinux = !vmlinux_path.empty();
2741 while ((entry = fts_read(file_hierarchy)))
2744 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2746 fts_set(file_hierarchy, entry, FTS_SKIP);
2750 if (!found_vmlinux && is_vmlinux(entry))
2752 vmlinux_path = entry->fts_path;
2753 found_vmlinux =
true;
2755 else if (is_kernel_module(entry))
2756 module_paths.push_back(entry->fts_path);
2759 fts_close(file_hierarchy);
2761 return found_vmlinux;
2772find_vmlinux_path(
const string& from,
2773 string &vmlinux_path)
2775 char* path[] = {
const_cast<char*
>(from.c_str()), 0};
2777 FTS *file_hierarchy = fts_open(path, FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2778 if (!file_hierarchy)
2781 bool found_vmlinux =
false;
2783 while ((entry = fts_read(file_hierarchy)))
2786 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2788 fts_set(file_hierarchy, entry, FTS_SKIP);
2792 if (!found_vmlinux && is_vmlinux(entry))
2794 vmlinux_path = entry->fts_path;
2795 found_vmlinux =
true;
2800 fts_close(file_hierarchy);
2802 return found_vmlinux;
2823 const string& debug_info_root_path,
2824 string& vmlinux_path,
2825 vector<string>& module_paths)
2838 string kernel_modules_root;
2839 string debug_info_root;
2842 kernel_modules_root = dist_root +
"/lib/modules";
2843 debug_info_root = debug_info_root_path.empty()
2844 ? dist_root +
"/usr/lib/debug"
2845 : debug_info_root_path;
2849 debug_info_root.clear();
2857 find_vmlinux_and_module_paths(kernel_modules_root,
2862 || find_vmlinux_and_module_paths(debug_info_root,
2867 std::sort(module_paths.begin(), module_paths.end());
2883 string& vmlinux_path)
2894 string dist_root = from;
2896 dist_root +=
"/lib/modules";
2899 if (find_vmlinux_path(dist_root, vmlinux_path))
2919 string& vmlinux_path,
2920 vector<string>& module_paths)
2922 string debug_info_root_path;
2924 debug_info_root_path,
2967load_vmlinux_corpus(elf_based_reader_sptr rdr,
2968 corpus_group_sptr& group,
2969 const string& vmlinux,
2970 vector<string>& modules,
2972 vector<char**>& di_roots,
2973 vector<string>& suppr_paths,
2974 vector<string>& kabi_wl_paths,
2981 rdr->options().do_log = verbose;
2984 load_generate_apply_suppressions(*rdr, suppr_paths,
2985 kabi_wl_paths, supprs);
2989 std::cerr <<
"loaded white list and generated suppr spec in: "
2995 rdr->corpus_group(group);
2998 std::cerr <<
"reading kernel binary '"
2999 << vmlinux <<
"' ...\n" << std::flush;
3003 rdr->read_and_add_corpus_to_group(*group, status);
3007 std::cerr << vmlinux
3011 if (group->is_empty())
3015 int total_nb_modules = modules.size();
3016 int cur_module_index = 1;
3017 for (vector<string>::const_iterator m = modules.begin();
3019 ++m, ++cur_module_index)
3022 std::cerr <<
"reading module '"
3025 <<
"/" << total_nb_modules
3026 <<
") ... " << std::flush;
3028 rdr->initialize(*m, di_roots,
3032 load_generate_apply_suppressions(*rdr, suppr_paths,
3033 kabi_wl_paths, supprs);
3035 rdr->corpus_group(group);
3038 rdr->read_and_add_corpus_to_group(*group, status);
3041 std::cerr <<
"module '"
3043 <<
"' reading DONE: "
3087 const string debug_info_root,
3088 const string& vmlinux_path,
3089 vector<string>& suppr_paths,
3090 vector<string>& kabi_wl_paths,
3096 string vmlinux = vmlinux_path;
3097 corpus_group_sptr group;
3098 vector<string> modules;
3101 std::cerr <<
"Analysing kernel dist root '"
3103 <<
"' with vmlinux path: '"
3105 <<
"' ... " << std::flush;
3110 bool got_binary_paths =
3115 std::cerr <<
"DONE: " << t <<
"\n";
3117 if (got_binary_paths)
3119 shared_ptr<char> di_root =
3121 char *di_root_ptr = di_root.get();
3122 vector<char**> di_roots;
3123 di_roots.push_back(&di_root_ptr);
3126 shared_ptr<char> di_root_ctf;
3127 if (requested_fe_kind & corpus::CTF_ORIGIN)
3130 char *di_root_ctf_ptr = di_root_ctf.get();
3131 di_roots.push_back(&di_root_ctf_ptr);
3135 abigail::elf_based_reader_sptr reader =
3143 load_vmlinux_corpus(reader, group, vmlinux,
3144 modules, root, di_roots,
3145 suppr_paths, kabi_wl_paths,
3146 supprs, verbose, t, env);
3187elf_based_reader_sptr
3189 const vector<char**>& debug_info_root_paths,
3192 bool show_all_types,
3193 bool linux_kernel_mode)
3195 elf_based_reader_sptr result;
3199 if (requested_fe_kind & corpus::CTF_ORIGIN)
3203 result = ctf::create_reader(elf_file_path, debug_info_root_paths, env);
3206 else if (requested_fe_kind & corpus::BTF_ORIGIN)
3210 result = btf::create_reader(elf_file_path, debug_info_root_paths, env);
3221 result = ctf::create_reader(elf_file_path, debug_info_root_paths, env);
3229 result = btf::create_reader(elf_file_path, debug_info_root_paths, env);
3239 debug_info_root_paths,
3268 std::vector<function_decl*>::const_iterator a_end,
3269 std::vector<function_decl*>::const_iterator b_begin,
3270 std::vector<function_decl*>::const_iterator b_end)
3271{abigail::fns_to_str(a_begin, a_end, b_begin, b_end, std::cerr);}
3285 std::vector<function_decl*>::const_iterator a_end,
3286 std::vector<function_decl*>::const_iterator b_begin,
3287 std::vector<function_decl*>::const_iterator b_end)
3289 std::vector<function_decl*>::const_iterator i;
3290 std::ostream& o = std::cerr;
3291 for (i = a_begin; i != a_end; ++i)
3292 o << (*i)->get_pretty_representation() <<
"\n";
3295 for (i = b_begin; i != b_end; ++i)
3296 o << (*i)->get_pretty_representation() <<
"\n";
3309 unsigned f1_index,
unsigned f2_index)
3314 return *fn1 == *fn2;
This file contains the declarations of the front-end to analyze the BTF information contained in an E...
This file contains the declarations of the entry points to de-serialize an instance of abigail::corpu...
This file contains the declarations of the entry points to de-serialize an instance of abigail::corpu...
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Types of the main internal representation of libabigail.
Wrappers around regex types and functions.
This is the interface an ELF reader.
const Dwarf * dwarf_debug_info() const
Getter of the handle used to access DWARF information from the current ELF file.
const Elf_Scn * find_ctf_section() const
Find and return a pointer to the the CTF section.
const Elf_Scn * find_btf_section() const
Find and return a pointer to the BTF section of the current ELF file.
The common interface of readers based on ELF.
status
The status of the fe_iface::read_corpus call.
@ STATUS_OK
This status is for when the call went OK.
@ STATUS_UNKNOWN
The status is in an unknown state.
void add_suppressions(const suppr::suppressions_type &)
Add suppressions specifications to the set of suppressions to be used during the construction of the ...
The abstraction of the structured content of an .ini file. This roughly follows what is explained at ...
vector< section_sptr > sections_type
A convenience typedef for a vector of config::section_sptr.
const sections_type & get_sections() const
Abstraction of a group of corpora.
bool has_corpus(const string &)
Test if a corpus of a given path has been added to the group.
void add_corpus(const corpus_sptr &)
Add a new corpus to the current instance of corpus_group.
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
const vector< string > & get_needed() const
Getter of the needed property of the corpus.
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Abstraction for a function declaration.
Abstraction of a function suppression specification.
Abstraction of a type suppression specification.
The abstraction of a variable suppression specification.
elf_based_reader_sptr create_reader(const std::string &elf_path, const vector< char ** > &debug_info_root_paths, environment &environment, bool load_all_types, bool linux_kernel_mode)
Create a dwarf::reader.
Namespace for handling ini-style files.
bool read_config(istream &input, config &conf)
Parse an ini config file from an input stream.
shared_ptr< simple_property > simple_property_sptr
Convenience typedef for a shared_ptr to an simple_property.
simple_property * is_simple_property(const property *p)
Tests if a property is a simple property.
std::string generate_from_strings(const std::vector< std::string > &strs)
Generate a regex pattern equivalent to testing set membership.
an engine to suppress the parts of the result of comparing two sets of ABI artifacts.
shared_ptr< variable_suppression > variable_suppression_sptr
A convenience typedef for a shared pointer to variable_suppression.
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
shared_ptr< function_suppression > function_suppression_sptr
Convenience typedef for a shared pointer to function_suppression.
const char * get_private_types_suppr_spec_label()
shared_ptr< type_suppression > type_suppression_sptr
Convenience typedef for a shared pointer to type_suppression.
void read_suppressions(std::istream &input, suppressions_type &suppressions)
Read suppressions specifications from an input stream.
Toplevel namespace for libabigail.
bool compare_functions(vector< function_decl * >::const_iterator base, unsigned f1_index, unsigned f2_index)
Compare two functions that are in a vector of functions.
void abigail_get_library_version(std::string &major, std::string &minor, std::string &revision, std::string &suffix)
Return the relevant version numbers of the library.
void dump_function_names(std::vector< function_decl * >::const_iterator a_begin, std::vector< function_decl * >::const_iterator a_end, std::vector< function_decl * >::const_iterator b_begin, std::vector< function_decl * >::const_iterator b_end)
Dump (to the standard error output stream) a pretty representation of the signatures of two sequences...
void abigail_get_abixml_version(std::string &major, std::string &minor)
Return the version numbers for the ABIXML format.
void dump_functions_as_string(std::vector< function_decl * >::const_iterator a_begin, std::vector< function_decl * >::const_iterator a_end, std::vector< function_decl * >::const_iterator b_begin, std::vector< function_decl * >::const_iterator b_end)
Dump (to the standard error stream) two sequences of strings where each string represent one of the f...
std::ostream & operator<<(std::ostream &o, const interned_string &s)
Streaming operator.