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