1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2 // -*- Mode: C++ -*- 3 // 4 // Copyright (C) 2013-2023 Red Hat, Inc. 5 6 ///@file 7 8 #ifndef __ABG_TOOLS_UTILS_H 9 #define __ABG_TOOLS_UTILS_H 10 11 #include <iostream> 12 #include <istream> 13 #include <memory> 14 #include <ostream> 15 #include <set> 16 #include <string> 17 #include "abg-suppression.h" 18 #include "abg-elf-based-reader.h" 19 20 namespace abigail 21 { 22 23 namespace tools_utils 24 { 25 26 using std::ostream; 27 using std::istream; 28 using std::ifstream; 29 using std::string; 30 using std::set; 31 using std::shared_ptr; 32 33 void initialize(); 34 const char* get_system_libdir(); 35 const char* get_anonymous_struct_internal_name_prefix(); 36 const char* get_anonymous_union_internal_name_prefix(); 37 const char* get_anonymous_enum_internal_name_prefix(); 38 const char* get_anonymous_subrange_internal_name_prefix(); 39 40 bool file_exists(const string&); 41 bool is_regular_file(const string&); 42 bool file_has_dwarf_debug_info(const string& elf_file_path, 43 const vector<char**>& debug_info_root_paths); 44 bool file_has_ctf_debug_info(const string& elf_file_path, 45 const vector<char**>& debug_info_root_paths); 46 bool file_has_btf_debug_info(const string& elf_file_path, 47 const vector<char**>& debug_info_root_paths); 48 bool is_dir(const string&); 49 bool dir_exists(const string&); 50 bool dir_is_empty(const string &); 51 bool decl_names_equal(const string&, const string&); 52 bool maybe_get_symlink_target_file_path(const string& file_path, 53 string& target_path); 54 bool base_name(string const& path, 55 string& file_name); 56 bool dir_name(string const &path, 57 string& path_dir_name, 58 bool keep_separator_at_end=false); 59 void real_path(const string&path, string& realpath); 60 bool ensure_dir_path_created(const string&); 61 bool ensure_parent_dir_created(const string&); 62 ostream& emit_prefix(const string& prog_name, ostream& out); 63 bool check_file(const string& path, ostream& out, const string& prog_name = ""); 64 bool check_dir(const string& path, ostream& out, const string& prog_name=""); 65 bool string_ends_with(const string&, const string&); 66 bool string_begins_with(const string&, const string&); 67 bool string_is_ascii(const string&); 68 bool string_is_ascii_identifier(const string&); 69 bool split_string(const string&, const string&, vector<string>&); 70 bool string_suffix(const string&, const string&, string&); 71 bool sorted_strings_common_prefix(vector<string>&, string&); 72 string get_library_version_string(); 73 string get_abixml_version_string(); 74 bool execute_command_and_get_output(const string&, vector<string>&); 75 void get_comma_separated_args_of_option(const string& input_str, 76 const string& option, 77 vector<string>& arguments); 78 bool get_dsos_provided_by_rpm(const string& rpm_path, 79 set<string>& provided_dsos); 80 string trim_white_space(const string&); 81 string trim_leading_string(const string& from, const string& to_trim); 82 void convert_char_stars_to_char_star_stars(const vector<char*>&, 83 vector<char**>&); 84 85 suppr::type_suppression_sptr 86 gen_suppr_spec_from_headers(const string& hdrs_root_dir); 87 88 suppr::type_suppression_sptr 89 gen_suppr_spec_from_headers(const string& hdrs_root_dir, 90 const vector<string>& hdr_files); 91 92 suppr::type_suppression_sptr 93 gen_suppr_spec_from_headers(const vector<string>& headers_root_dirs, 94 const vector<string>& header_files); 95 96 suppr::suppressions_type 97 gen_suppr_spec_from_kernel_abi_whitelists 98 (const vector<string>& abi_whitelist_paths); 99 100 bool 101 get_vmlinux_path_from_kernel_dist(const string& from, 102 string& vmlinux_path); 103 104 bool 105 get_binary_paths_from_kernel_dist(const string& dist_root, 106 const string& debug_info_root_path, 107 string& vmlinux_path, 108 vector<string>& module_paths); 109 110 bool 111 get_binary_paths_from_kernel_dist(const string& dist_root, 112 string& vmlinux_path, 113 vector<string>& module_paths); 114 115 string 116 get_default_system_suppression_file_path(); 117 118 string 119 get_default_user_suppression_file_path(); 120 121 void 122 load_default_system_suppressions(suppr::suppressions_type&); 123 124 void 125 load_default_user_suppressions(suppr::suppressions_type&); 126 127 bool 128 find_file_under_dir(const string& root_dir, 129 const string& file_path_to_look_for, 130 string& result); 131 132 bool 133 find_file_under_dirs(const vector<string>& root_dirs, 134 const string& file_path_to_look_for, 135 string& result); 136 137 bool 138 get_dependencies(const corpus&, const vector<string>&, set<string>&); 139 140 void 141 add_binaries_into_corpus_group(const fe_iface_sptr& reader, 142 const vector<string>& binaries, 143 const vector<string>& deps_dirs, 144 corpus_group& group); 145 146 void 147 add_dependencies_into_corpus_group(const fe_iface_sptr& reader, 148 const corpus& korpus, 149 const vector<string>& deps_dirs, 150 corpus_group& group); 151 152 corpus_group_sptr 153 stick_corpus_and_binaries_into_corpus_group(const fe_iface_sptr& reader, 154 const corpus_sptr& korpus, 155 const vector<string>& binaries, 156 const vector<string>& deps_dirs); 157 158 corpus_group_sptr 159 stick_corpus_and_dependencies_into_corpus_group(const fe_iface_sptr& reader, 160 const corpus_sptr& korpus, 161 const vector<string>& deps_dirs); 162 163 164 class temp_file; 165 166 /// Convenience typedef for a shared_ptr to @ref temp_file. 167 typedef shared_ptr<temp_file> temp_file_sptr; 168 169 /// A temporary file. 170 /// 171 /// This is a helper file around the mkstemp API. 172 /// 173 /// Once the temporary file is created, users can interact with it 174 /// using an fstream. They can also get the path to the newly 175 /// created temporary file. 176 /// 177 /// When the instance of @ref temp_file is destroyed, the underlying 178 /// resources are de-allocated, the underlying temporary file is 179 /// closed and removed. 180 class temp_file 181 { 182 struct priv; 183 std::unique_ptr<priv> priv_; 184 185 temp_file(); 186 187 public: 188 189 bool 190 is_good() const; 191 192 const char* 193 get_path() const; 194 195 std::fstream& 196 get_stream(); 197 198 static temp_file_sptr 199 create(); 200 }; // end class temp_file 201 202 size_t 203 get_random_number(); 204 205 string 206 get_random_number_as_string(); 207 208 /// The different types of files understood the bi* suite of tools. 209 enum file_type 210 { 211 /// A file type we don't know about. 212 FILE_TYPE_UNKNOWN, 213 /// The native xml file format representing a translation unit. 214 FILE_TYPE_NATIVE_BI, 215 /// An elf file. Read this kind of file should yield an 216 /// abigail::corpus type. 217 FILE_TYPE_ELF, 218 /// An archive (AR) file. 219 FILE_TYPE_AR, 220 // A native abixml file format representing a corpus of one or 221 // several translation units. 222 FILE_TYPE_XML_CORPUS, 223 // A native abixml file format representing a corpus group of one or 224 // several corpora. 225 FILE_TYPE_XML_CORPUS_GROUP, 226 /// An RPM (.rpm) binary file 227 FILE_TYPE_RPM, 228 /// An SRPM (.src.rpm) file 229 FILE_TYPE_SRPM, 230 /// A DEB (.deb) binary file 231 FILE_TYPE_DEB, 232 /// A plain directory 233 FILE_TYPE_DIR, 234 /// A tar archive. The archive can be compressed with the popular 235 /// compression schemes recognized by GNU tar. 236 FILE_TYPE_TAR 237 }; 238 239 /// Exit status for abidiff and abicompat tools. 240 /// 241 /// It's actually a bit mask. The value of each enumerator is a power 242 /// of two. 243 enum abidiff_status 244 { 245 /// This is for when the compared ABIs are equal. 246 /// 247 /// Its numerical value is 0. 248 ABIDIFF_OK = 0, 249 250 /// This bit is set if there is an application error. 251 /// 252 /// Its numerical value is 1. 253 ABIDIFF_ERROR = 1, 254 255 /// This bit is set if the tool is invoked in an non appropriate 256 /// manner. 257 /// 258 /// Its numerical value is 2. 259 ABIDIFF_USAGE_ERROR = 1 << 1, 260 261 /// This bit is set if the ABIs being compared are different. 262 /// 263 /// Its numerical value is 4. 264 ABIDIFF_ABI_CHANGE = 1 << 2, 265 266 /// This bit is set if the ABIs being compared are different *and* 267 /// are incompatible. 268 /// 269 /// Its numerical value is 8. 270 ABIDIFF_ABI_INCOMPATIBLE_CHANGE = 1 << 3 271 }; 272 273 abidiff_status 274 operator|(abidiff_status, abidiff_status); 275 276 abidiff_status 277 operator&(abidiff_status, abidiff_status); 278 279 abidiff_status& 280 operator|=(abidiff_status&l, abidiff_status r); 281 282 bool 283 abidiff_status_has_error(abidiff_status s); 284 285 bool 286 abidiff_status_has_abi_change(abidiff_status s); 287 288 bool 289 abidiff_status_has_incompatible_abi_change(abidiff_status s); 290 291 /// A type used to time various part of the libabigail system. 292 class timer 293 { 294 struct priv; 295 std::unique_ptr<priv> priv_; 296 297 public: 298 enum kind 299 { 300 /// Default timer kind. 301 DEFAULT_TIMER_KIND = 0, 302 /// This kind of timer starts upon instantiation. 303 START_ON_INSTANTIATION_TIMER_KIND = 1, 304 }; 305 306 timer (kind k = DEFAULT_TIMER_KIND); 307 bool start(); 308 bool stop(); 309 time_t value_in_seconds() const; 310 bool value(time_t& hours, 311 time_t& minutes, 312 time_t& seconds, 313 time_t& milliseconds) const; 314 string value_as_string() const; 315 ~timer(); 316 }; //end class timer 317 318 ostream& operator<<(ostream&, const timer&); 319 320 ostream& 321 operator<<(ostream& output, file_type r); 322 323 file_type guess_file_type(istream& in); 324 325 file_type guess_file_type(const string& file_path); 326 327 bool 328 get_rpm_name(const string& str, string& name); 329 330 bool 331 get_rpm_arch(const string& str, string& arch); 332 333 bool 334 get_deb_name(const string& str, string& name); 335 336 bool 337 file_is_kernel_package(const string& file_path, 338 file_type file_type); 339 340 bool 341 rpm_contains_file(const string& rpm_path, 342 const string& file_name); 343 344 bool 345 file_is_kernel_debuginfo_package(const string& file_path, 346 file_type file_type); 347 348 std::shared_ptr<char> 349 make_path_absolute(const char*p); 350 351 char* 352 make_path_absolute_to_be_freed(const char*p); 353 354 corpus_group_sptr 355 build_corpus_group_from_kernel_dist_under(const string& root, 356 const string debug_info_root, 357 const string& vmlinux_path, 358 vector<string>& suppr_paths, 359 vector<string>& kabi_wl_paths, 360 suppr::suppressions_type& supprs, 361 bool verbose, 362 environment& env, 363 corpus::origin requested_fe_kind = corpus::DWARF_ORIGIN); 364 365 elf_based_reader_sptr 366 create_best_elf_based_reader(const string& elf_file_path, 367 const vector<char**>& debug_info_root_paths, 368 environment& env, 369 corpus::origin requested_debug_info_kind, 370 bool show_all_types, 371 bool linux_kernel_mode = false); 372 373 }// end namespace tools_utils 374 375 /// A macro that expands to aborting the program when executed. 376 /// 377 /// Before aborting, the macro emits informatin about the source 378 /// location where it was expanded. 379 #define ABG_ASSERT_NOT_REACHED \ 380 do { \ 381 std::cerr << "in " << __FUNCTION__ \ 382 << " at: " << __FILE__ << ":" << __LINE__ \ 383 << ": execution should not have reached this point!\n"; \ 384 abort(); \ 385 } while (false) 386 }//end namespace abigail 387 388 #endif //__ABG_TOOLS_UTILS_H 389