13 #include <sys/types.h>
23 #include <sys/types.h>
28 #include <sys/types.h>
53 #include "abg-internal.h"
57 ABG_BEGIN_EXPORT_DECLARATIONS
63 ABG_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))
185 timer::kind timer_kind;
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;
338 get_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);
562 static const char* ANONYMOUS_STRUCT_INTERNAL_NAME =
"__anonymous_struct__";
563 static const char* ANONYMOUS_UNION_INTERNAL_NAME =
"__anonymous_union__";
564 static const char* ANONYMOUS_ENUM_INTERNAL_NAME =
"__anonymous_enum__";
565 static const char* ANONYMOUS_SUBRANGE_INTERNAL_NAME =
"__anonymous_range__";
567 static int ANONYMOUS_STRUCT_INTERNAL_NAME_LEN =
568 strlen(ANONYMOUS_STRUCT_INTERNAL_NAME);
570 static int ANONYMOUS_UNION_INTERNAL_NAME_LEN =
571 strlen(ANONYMOUS_UNION_INTERNAL_NAME);
573 static int ANONYMOUS_ENUM_INTERNAL_NAME_LEN =
574 strlen(ANONYMOUS_ENUM_INTERNAL_NAME);
581 {
return ANONYMOUS_STRUCT_INTERNAL_NAME;}
588 {
return ANONYMOUS_UNION_INTERNAL_NAME;}
590 static 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 <<
": ";
876 check_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";
904 check_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());
1100 common_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)
1256 vector<string> query_output;
1262 + rpm_path +
" 2> /dev/null | grep .so",
1265 for (vector<string>::const_iterator line = query_output.begin();
1266 line != query_output.end();
1269 string dso = line->substr(0, line->find(
'('));
1272 provided_dsos.insert(dso);
1289 string::size_type start, end;
1290 for (start = 0; start < str.length(); ++start)
1291 if (!isspace(str[start]))
1294 for (end = str.length() - 1; end > 0; --end)
1295 if (!isspace(str[end]))
1298 result = str.substr(start, end - start + 1);
1335 vector<char**>& char_star_stars)
1337 for (vector<char*>::const_iterator i = char_stars.begin();
1338 i != char_stars.end();
1340 char_star_stars.push_back(
const_cast<char**
>(&*i));
1344 struct temp_file::priv
1346 char* path_template_;
1348 shared_ptr<std::fstream> fstream_;
1352 const char* templat =
"/tmp/libabigail-tmp-file-XXXXXX";
1353 int s = strlen(templat);
1354 path_template_ =
new char[s + 1];
1355 memset(path_template_, 0, s + 1);
1356 memcpy(path_template_, templat, s);
1358 fd_ = mkstemp(path_template_);
1362 fstream_.reset(
new std::fstream(path_template_,
1370 if (fd_ && fd_ != -1)
1374 remove(path_template_);
1376 delete [] path_template_;
1383 temp_file::temp_file()
1392 temp_file::is_good()
const
1393 {
return priv_->fstream_->good();}
1400 temp_file::get_path()
const
1403 return priv_->path_template_;
1417 temp_file::get_stream()
1420 return *priv_->fstream_;
1431 if (result->is_good())
1443 static __thread
bool initialized =
false;
1460 std::ostringstream o;
1475 repr =
"unknown file type";
1478 repr =
"native binary instrumentation file type";
1481 repr =
"ELF file type";
1484 repr =
"archive file type";
1486 case FILE_TYPE_XML_CORPUS:
1487 repr =
"native XML corpus file type";
1489 case FILE_TYPE_XML_CORPUS_GROUP:
1490 repr =
"native XML corpus group file type";
1493 repr =
"RPM file type";
1496 repr =
"SRPM file type";
1499 repr =
"Debian binary file type";
1502 repr =
"Directory type";
1505 repr =
"GNU tar archive type";
1521 const unsigned BUF_LEN = 264;
1522 const unsigned NB_BYTES_TO_READ = 263;
1525 memset(buf, 0, BUF_LEN);
1527 std::streampos initial_pos = in.tellg();
1528 in.read(buf, NB_BYTES_TO_READ);
1529 in.seekg(initial_pos);
1531 if (in.gcount() < 4 || in.bad())
1548 if (strstr(buf,
"debian-binary"))
1585 return FILE_TYPE_XML_CORPUS_GROUP;
1599 return FILE_TYPE_XML_CORPUS;
1601 if ((
unsigned char) buf[0] == 0xed
1602 && (
unsigned char) buf[1] == 0xab
1603 && (
unsigned char) buf[2] == 0xee
1604 && (
unsigned char) buf[3] == 0xdb)
1608 else if (buf[7] == 0x01)
1652 ifstream in(file_path.c_str(), ifstream::binary);
1670 if (str.empty() || str[0] ==
'_')
1673 string::size_type str_len = str.length(), i = 0 ;
1675 for (; i < str_len; ++i)
1684 name = str.substr(0, i);
1700 if (str.empty() || str[0] ==
'-')
1703 string::size_type str_len = str.length(), i = 0;
1704 string::value_type c;
1706 for (; i < str_len; ++i)
1709 string::size_type next_index = i + 1;
1710 if ((next_index < str_len) && c ==
'-' && isdigit(str[next_index]))
1717 name = str.substr(0, i);
1740 string::size_type str_len = str.length(), i = 0;
1741 string::value_type c;
1742 string::size_type last_dot_index = 0, dot_before_last_index = 0;
1744 for (i = str_len - 1; i > 0; --i)
1757 for(--i; i > 0; --i)
1762 dot_before_last_index = i;
1770 arch = str.substr(dot_before_last_index + 1,
1771 last_dot_index - dot_before_last_index - 1);
1787 bool result =
false;
1798 string package_name;
1817 vector<string> query_output;
1823 + rpm_path +
" 2> /dev/null",
1826 for (
auto& line : query_output)
1847 bool result =
false;
1848 string package_name;
1854 result = (package_name ==
"kernel-debuginfo");
1870 struct malloced_char_star_deleter
1873 operator()(
char* ptr)
1888 std::shared_ptr<char>
1891 using std::shared_ptr;
1893 shared_ptr<char> result;
1895 if (p && p[0] !=
'/')
1897 shared_ptr<char> pwd(get_current_dir_name(),
1898 malloced_char_star_deleter());
1899 string s = string(pwd.get()) +
"/" + p;
1900 result.reset(strdup(s.c_str()), malloced_char_star_deleter());
1903 result.reset(strdup(p), malloced_char_star_deleter());
1924 if (p && p[0] !=
'/')
1926 char* pwd = get_current_dir_name();
1927 string s = string(pwd) +
"/" + p;
1929 result = strdup(s.c_str());
1953 handle_file_entry(
const string& file_path,
1964 suppr->set_source_location_to_keep_regex_str(
"^/usr/include/");
1965 suppr->set_is_artificial(
true);
1971 suppr->get_source_locations_to_keep().insert(file_path);
1987 handle_fts_entry(
const FTSENT *entry,
1991 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
1992 || entry->fts_info == FTS_ERR
1993 || entry->fts_info == FTS_NS)
1996 string fname = entry->fts_name;
2002 handle_file_entry (fname, suppr);
2020 gen_suppr_spec_from_headers_root_dir(
const string& headers_root_dir,
2023 if (!headers_root_dir.empty())
2025 char* paths[] = {
const_cast<char*
>(headers_root_dir.c_str()), 0};
2027 if (FTS *file_hierarchy = fts_open(paths, FTS_LOGICAL|FTS_NOCHDIR, NULL))
2030 while ((entry = fts_read(file_hierarchy)))
2031 handle_fts_entry(entry, result);
2032 fts_close(file_hierarchy);
2053 const vector<string>& header_files)
2057 for (vector<string>::const_iterator root_dir = headers_root_dirs.begin();
2058 root_dir != headers_root_dirs.end();
2060 gen_suppr_spec_from_headers_root_dir(*root_dir, result);
2062 for (vector<string>::const_iterator file = header_files.begin();
2063 file != header_files.end();
2065 handle_file_entry(*file, result);
2085 const vector<string>& header_files)
2088 vector<string> root_dirs;
2090 if (!headers_root_dir.empty())
2091 root_dirs.push_back(headers_root_dir);
2109 vector<string> header_files;
2140 (
const std::vector<std::string>& abi_whitelist_paths)
2143 std::vector<std::string> whitelisted_names;
2144 for (std::vector<std::string>::const_iterator
2145 path_iter = abi_whitelist_paths.begin(),
2146 path_end = abi_whitelist_paths.end();
2147 path_iter != path_end;
2158 for (ini::config::sections_type::const_iterator
2159 section_iter = whitelist_sections.begin(),
2160 section_end = whitelist_sections.end();
2161 section_iter != section_end;
2164 std::string section_name = (*section_iter)->get_name();
2168 for (ini::config::properties_type::const_iterator
2169 prop_iter = (*section_iter)->get_properties().begin(),
2170 prop_end = (*section_iter)->get_properties().end();
2171 prop_iter != prop_end;
2176 if (prop->has_empty_value())
2178 const std::string& name = prop->get_name();
2180 whitelisted_names.push_back(name);
2187 if (!whitelisted_names.empty())
2190 std::sort(whitelisted_names.begin(), whitelisted_names.end());
2191 whitelisted_names.erase(std::unique(whitelisted_names.begin(),
2192 whitelisted_names.end()),
2193 whitelisted_names.end());
2205 fn_suppr->set_label(
"whitelist");
2206 fn_suppr->set_symbol_name_not_regex_str(regex);
2207 fn_suppr->set_drops_artifact_from_ir(
true);
2208 result.push_back(fn_suppr);
2216 var_suppr->set_label(
"whitelist");
2217 var_suppr->set_symbol_name_not_regex_str(regex);
2218 var_suppr->set_drops_artifact_from_ir(
true);
2219 result.push_back(var_suppr);
2230 string default_system_suppr_path;
2232 const char *s = getenv(
"LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE");
2234 default_system_suppr_path = s;
2236 if (default_system_suppr_path.empty())
2237 default_system_suppr_path =
2240 return default_system_suppr_path;
2249 string default_user_suppr_path;
2250 const char *s = getenv(
"LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE");
2257 default_user_suppr_path = s;
2258 if (default_user_suppr_path.empty())
2259 default_user_suppr_path =
"~";
2260 default_user_suppr_path +=
"/.abignore";
2263 default_user_suppr_path = s;
2265 return default_user_suppr_path;
2279 string default_system_suppr_path =
2295 string default_user_suppr_path =
2316 entry_of_file_with_name(
const FTSENT *entry,
2317 const string& fname,
2318 const string& root_dir)
2321 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2322 || entry->fts_info == FTS_ERR
2323 || entry->fts_info == FTS_NS)
2326 string fpath = ::basename(entry->fts_path);
2349 const string& file_path_to_look_for,
2352 char* paths[] = {
const_cast<char*
>(root_dir.c_str()), 0};
2354 FTS *file_hierarchy = fts_open(paths,
2355 FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2356 if (!file_hierarchy)
2359 string r = root_dir;
2364 while ((entry = fts_read(file_hierarchy)))
2367 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2369 fts_set(file_hierarchy, entry, FTS_SKIP);
2372 if (entry_of_file_with_name(entry, file_path_to_look_for, r))
2374 result = entry->fts_path;
2379 fts_close(file_hierarchy);
2403 vector<string>& suppr_paths,
2404 vector<string>& kabi_whitelist_paths,
2409 for (vector<string>::const_iterator i = suppr_paths.begin();
2410 i != suppr_paths.end();
2417 supprs.insert(supprs.end(), wl_suppr.begin(), wl_suppr.end());
2430 is_vmlinux(
const FTSENT *entry)
2433 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2434 || entry->fts_info == FTS_ERR
2435 || entry->fts_info == FTS_NS)
2438 string fname = entry->fts_name;
2440 if (fname ==
"vmlinux")
2443 dir_name(entry->fts_path, dirname);
2460 is_kernel_module(
const FTSENT *entry)
2463 || (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
2464 || entry->fts_info == FTS_ERR
2465 || entry->fts_info == FTS_NS)
2468 string fname = entry->fts_name;
2490 find_vmlinux_and_module_paths(
const string& from,
2491 string &vmlinux_path,
2492 vector<string> &module_paths)
2494 char* path[] = {
const_cast<char*
>(from.c_str()), 0};
2496 FTS *file_hierarchy = fts_open(path, FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2497 if (!file_hierarchy)
2500 bool found_vmlinux = !vmlinux_path.empty();
2502 while ((entry = fts_read(file_hierarchy)))
2505 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2507 fts_set(file_hierarchy, entry, FTS_SKIP);
2511 if (!found_vmlinux && is_vmlinux(entry))
2513 vmlinux_path = entry->fts_path;
2514 found_vmlinux =
true;
2516 else if (is_kernel_module(entry))
2517 module_paths.push_back(entry->fts_path);
2520 fts_close(file_hierarchy);
2522 return found_vmlinux;
2533 find_vmlinux_path(
const string& from,
2534 string &vmlinux_path)
2536 char* path[] = {
const_cast<char*
>(from.c_str()), 0};
2538 FTS *file_hierarchy = fts_open(path, FTS_PHYSICAL|FTS_NOCHDIR|FTS_XDEV, 0);
2539 if (!file_hierarchy)
2542 bool found_vmlinux =
false;
2544 while ((entry = fts_read(file_hierarchy)))
2547 if (entry->fts_info == FTS_SL || entry->fts_info == FTS_SLNONE)
2549 fts_set(file_hierarchy, entry, FTS_SKIP);
2553 if (!found_vmlinux && is_vmlinux(entry))
2555 vmlinux_path = entry->fts_path;
2556 found_vmlinux =
true;
2561 fts_close(file_hierarchy);
2563 return found_vmlinux;
2584 const string& debug_info_root_path,
2585 string& vmlinux_path,
2586 vector<string>& module_paths)
2599 string kernel_modules_root;
2600 string debug_info_root;
2603 kernel_modules_root = dist_root +
"/lib/modules";
2604 debug_info_root = debug_info_root_path.empty()
2605 ? dist_root +
"/usr/lib/debug"
2606 : debug_info_root_path;
2610 debug_info_root.clear();
2618 find_vmlinux_and_module_paths(kernel_modules_root,
2623 || find_vmlinux_and_module_paths(debug_info_root,
2628 std::sort(module_paths.begin(), module_paths.end());
2644 string& vmlinux_path)
2655 string dist_root = from;
2657 dist_root +=
"/lib/modules";
2660 if (find_vmlinux_path(dist_root, vmlinux_path))
2680 string& vmlinux_path,
2681 vector<string>& module_paths)
2683 string debug_info_root_path;
2685 debug_info_root_path,
2728 load_vmlinux_corpus(elf_based_reader_sptr rdr,
2729 corpus_group_sptr& group,
2730 const string& vmlinux,
2731 vector<string>& modules,
2733 vector<char**>& di_roots,
2734 vector<string>& suppr_paths,
2735 vector<string>& kabi_wl_paths,
2742 rdr->options().do_log = verbose;
2745 load_generate_apply_suppressions(*rdr, suppr_paths,
2746 kabi_wl_paths, supprs);
2750 std::cerr <<
"loaded white list and generated suppr spec in: "
2756 rdr->corpus_group(group);
2759 std::cerr <<
"reading kernel binary '"
2760 << vmlinux <<
"' ...\n" << std::flush;
2764 rdr->read_and_add_corpus_to_group(*group, status);
2768 std::cerr << vmlinux
2772 if (group->is_empty())
2776 int total_nb_modules = modules.size();
2777 int cur_module_index = 1;
2778 for (vector<string>::const_iterator m = modules.begin();
2780 ++m, ++cur_module_index)
2783 std::cerr <<
"reading module '"
2786 <<
"/" << total_nb_modules
2787 <<
") ... " << std::flush;
2789 rdr->initialize(*m, di_roots,
2793 load_generate_apply_suppressions(*rdr, suppr_paths,
2794 kabi_wl_paths, supprs);
2796 rdr->corpus_group(group);
2799 rdr->read_and_add_corpus_to_group(*group, status);
2802 std::cerr <<
"module '"
2804 <<
"' reading DONE: "
2848 const string debug_info_root,
2849 const string& vmlinux_path,
2850 vector<string>& suppr_paths,
2851 vector<string>& kabi_wl_paths,
2857 string vmlinux = vmlinux_path;
2858 corpus_group_sptr group;
2859 vector<string> modules;
2862 std::cerr <<
"Analysing kernel dist root '"
2864 <<
"' with vmlinux path: '"
2866 <<
"' ... " << std::flush;
2871 bool got_binary_paths =
2876 std::cerr <<
"DONE: " << t <<
"\n";
2878 if (got_binary_paths)
2880 shared_ptr<char> di_root =
2882 char *di_root_ptr = di_root.get();
2883 vector<char**> di_roots;
2884 di_roots.push_back(&di_root_ptr);
2887 shared_ptr<char> di_root_ctf;
2888 if (requested_fe_kind & corpus::CTF_ORIGIN)
2891 char *di_root_ctf_ptr = di_root_ctf.get();
2892 di_roots.push_back(&di_root_ctf_ptr);
2896 abigail::elf_based_reader_sptr reader =
2904 load_vmlinux_corpus(reader, group, vmlinux,
2905 modules, root, di_roots,
2906 suppr_paths, kabi_wl_paths,
2907 supprs, verbose, t, env);
2948 elf_based_reader_sptr
2950 const vector<char**>& debug_info_root_paths,
2953 bool show_all_types,
2954 bool linux_kernel_mode)
2956 elf_based_reader_sptr result;
2960 if (requested_fe_kind & corpus::CTF_ORIGIN)
2967 else if (requested_fe_kind & corpus::BTF_ORIGIN)
3000 debug_info_root_paths,
3029 std::vector<function_decl*>::const_iterator a_end,
3030 std::vector<function_decl*>::const_iterator b_begin,
3031 std::vector<function_decl*>::const_iterator b_end)
3032 {abigail::fns_to_str(a_begin, a_end, b_begin, b_end, std::cerr);}
3046 std::vector<function_decl*>::const_iterator a_end,
3047 std::vector<function_decl*>::const_iterator b_begin,
3048 std::vector<function_decl*>::const_iterator b_end)
3050 std::vector<function_decl*>::const_iterator i;
3051 std::ostream& o = std::cerr;
3052 for (i = a_begin; i != a_end; ++i)
3053 o << (*i)->get_pretty_representation() <<
"\n";
3056 for (i = b_begin; i != b_end; ++i)
3057 o << (*i)->get_pretty_representation() <<
"\n";
3070 unsigned f1_index,
unsigned f2_index)
3075 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.
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.
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
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 &env, bool load_all_types=false, bool linux_kernel_mode=false)
Create and return a BTF reader (or front-end) which is an instance of btf::reader.
elf_based_reader_sptr create_reader(const std::string &elf_path, const vector< char ** > &debug_info_root_paths, environment &env)
Create and return a new read context to process CTF information from a given ELF file.
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.
function_suppression::change_kind operator|(function_suppression::change_kind l, function_suppression::change_kind r)
The bitwise 'or' operator for the enum function_suppression::change_kind.
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.
function_suppression::change_kind operator&(function_suppression::change_kind l, function_suppression::change_kind r)
The bitwise 'and' operator for the enum function_suppression::change_kind.
void read_suppressions(std::istream &input, suppressions_type &suppressions)
Read suppressions specifications from an input stream.
Toplevel namespace for libabigail.
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 abigail_get_abixml_version(std::string &major, std::string &minor)
Return the version numbers for the ABIXML format.
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.
fe_iface::status & operator|=(fe_iface::status &l, fe_iface::status r)
The bitwise |= operator for the fe_iface::status type.
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...
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...
std::ostream & operator<<(std::ostream &o, const interned_string &s)
Streaming operator.