libabigail
abg-fe-iface.cc
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2022-2023 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This file contains the definitions of the the fe_iface base type.
11 
12 #include "abg-internal.h"
13 // <headers defining libabigail's API go under here>
14 ABG_BEGIN_EXPORT_DECLARATIONS
15 
16 #include "abg-corpus.h"
17 #include "abg-fe-iface.h"
18 
20 // </headers defining libabigail's API>
21 
22 namespace abigail
23 {
24 
25 /// The private data structure for the @ref fe_iface type.
26 struct fe_iface::priv
27 {
28  std::string corpus_path;
29  std::string dt_soname;
30  fe_iface::options_type options;
32  ir::corpus_sptr corpus;
33  ir::corpus_group_sptr corpus_group;
34 
35  priv(const std::string& path, environment& e)
36  : corpus_path(path), options(e)
37  {
38  initialize();
39  }
40 
41  /// This function resets the data of @ref fe_iface::priv data so
42  /// that it can be re-used again.
43  void
44  initialize()
45  {
46  corpus_path.clear();
47  dt_soname.clear();
48  suppressions.clear();
49  corpus_group.reset();
50  corpus.reset();
51  }
52 }; //end struct fe_iface::priv
53 
54 /// Constructor of the type @ref fe_iface::options_type.
55 ///
56 /// @param e the environment used by the Front End Interface.
58  : env(e)
59 {
60 }
61 
62 /// Constructor of the type @ref fe_iface.
63 ///
64 /// @param corpus_path the path to the file represented by the ABI
65 /// corpus that is going to be built by this Front End.
66 ///
67 /// @param e the environment in which the Front End operates.
68 fe_iface::fe_iface(const std::string& corpus_path, environment& e)
69  : priv_(new priv(corpus_path, e))
70 {
71 }
72 
73 /// Desctructor of the Front End Interface.
75 {delete priv_;}
76 
77 /// Re-initialize the current Front End.
78 ///
79 /// @param corpus_path the path to the file for which a new corpus is
80 /// to be created.
81 void
82 fe_iface::initialize(const std::string& corpus_path)
83 {
84  priv_->initialize();
85  priv_->corpus_path = corpus_path;
86 }
87 
88 /// Getter of the the options of the current Front End Interface.
89 ///
90 /// @return the options of the current Front End Interface.
93 {return priv_->options;}
94 
95 /// Getter of the the options of the current Front End Interface.
96 ///
97 /// @return the options of the current Front End Interface.
100 {return priv_->options;}
101 
102 /// Getter of the path to the file which an ABI corpus is to be
103 /// created for.
104 ///
105 /// @return the path to the file which an ABI corpus is to be created
106 /// for.
107 const std::string&
109 {return priv_->corpus_path;}
110 
111 /// Setter of the path to the file which an ABI corpus is to be
112 /// created for.
113 ///
114 /// @param p the new path to the file which an ABI corpus is to be
115 /// created for.
116 void
117 fe_iface::corpus_path(const std::string& p)
118 {priv_->corpus_path = p;}
119 
120 /// Getter for the SONAME of the analyzed binary.
121 ///
122 /// @return the SONAME of the analyzed binary.
123 const string&
125 {return priv_->dt_soname;}
126 
127 /// Getter for the SONAME of the analyzed binary.
128 ///
129 /// @return the SONAME of the analyzed binary.
130 void
131 fe_iface::dt_soname(const string& soname)
132 {priv_->dt_soname = soname;}
133 
134 /// Test if the input binary is to be considered as a Linux Kernel
135 /// binary.
136 ///
137 /// @return true iff the input binary is to be considered as a Linux
138 /// Kernel binary.
139 bool
141 {return priv_->options.load_in_linux_kernel_mode;}
142 
143 /// Getter of the vector of suppression specifications associated with
144 /// the current front-end.
145 ///
146 /// @return the vector of suppression specifications associated with
147 /// the current front-end.
150 {return priv_->suppressions;}
151 
152 /// Getter of the vector of suppression specifications associated with
153 /// the current front-end.
154 ///
155 /// @return the vector of suppression specifications associated with
156 /// the current front-end.
159 {return priv_->suppressions;}
160 
161 /// Setter of the vector of suppression specifications associated with
162 /// the current front-end.
163 ///
164 /// @param supprs the new vector of suppression specifications
165 /// associated with the current front-end.
166 void
168 {priv_->suppressions = supprs;}
169 
170 /// Add suppressions specifications to the set of suppressions to be
171 /// used during the construction of the ABI internal representation
172 /// (the ABI corpus) from the input file.
173 ///
174 /// During the construction of the ABI corpus, ABI artifacts that
175 /// match a given suppression specification are dropped on the floor;
176 /// that is, they are discarded and won't be part of the final ABI
177 /// corpus. This is a way to reduce the amount of data held by the
178 /// final ABI corpus.
179 ///
180 /// Note that the suppression specifications provided to this function
181 /// are only considered during the construction of the ABI corpus.
182 /// For instance, they are not taken into account during e.g
183 /// comparisons of two ABI corpora that might happen later. If you
184 /// want to apply suppression specificatins to the comparison (or
185 /// reporting) of ABI corpora please refer to the documentation of the
186 /// @ref diff_context type to learn how to set suppressions that are
187 /// to be used in that context.
188 ///
189 /// @param supprs the suppression specifications to be applied during
190 /// the construction of the ABI corpus.
191 void
193 {
194  for (const auto& s : supprs)
195  if (s->get_drops_artifact_from_ir())
196  suppressions().push_back(s);
197 }
198 
199 /// Getter for the ABI corpus being built by the current front-end.
200 ///
201 /// @return the ABI corpus being built by the current front-end.
202 corpus_sptr
204 {
205  if (!priv_->corpus)
206  {
207  priv_->corpus = std::make_shared<ir::corpus>(options().env,
208  corpus_path());
209  }
210  return priv_->corpus;
211 }
212 
213 /// Getter for the ABI corpus being built by the current front-end.
214 ///
215 /// @return the ABI corpus being built by the current front-end.
216 const corpus_sptr
218 {return const_cast<fe_iface*>(this)->corpus();}
219 
220 /// Getter for the ABI corpus group being built by the current front-end.
221 ///
222 /// @return the ABI corpus group being built by the current front-end.
223 corpus_group_sptr&
225 {return priv_->corpus_group;}
226 
227 /// Getter for the ABI corpus group being built by the current front-end.
228 ///
229 /// @return the ABI corpus group being built by the current front-end.
230 const corpus_group_sptr&
232 {return const_cast<fe_iface*>(this)->corpus_group();}
233 
234 /// Setter for the ABI corpus group being built by the current
235 /// front-end.
236 ///
237 /// @param cg the new ABI corpus group being built by the current
238 /// front-end.
239 void
240 fe_iface::corpus_group(const ir::corpus_group_sptr& cg)
241 {priv_->corpus_group = cg;}
242 
243 /// Test if there is a corpus group being built.
244 ///
245 /// @return if there is a corpus group being built, false otherwise.
246 bool
248 {return bool(corpus_group());}
249 
250 /// Return the main corpus from the current corpus group, if any.
251 ///
252 /// @return the main corpus of the current corpus group, if any, nil
253 /// if no corpus group is being constructed.
254 corpus_sptr
256 {
257  if (corpus_group())
258  return corpus_group()->get_main_corpus();
259  return corpus_sptr();
260 }
261 
262 /// Test if the current corpus being built is the main corpus of the
263 /// current corpus group.
264 ///
265 /// @return return true iff the current corpus being built is the
266 /// main corpus of the current corpus group.
267 bool
269 {
270  corpus_sptr main_corpus = main_corpus_from_current_group();
271 
272  if (main_corpus.get() == corpus().get())
273  return true;
274 
275  return false;
276 }
277 
278 /// Return true if the current corpus is part of a corpus group
279 /// being built and if it's not the main corpus of the group.
280 ///
281 /// For instance, this would return true if we are loading a linux
282 /// kernel *module* that is part of the current corpus group that is
283 /// being built. In this case, it means we should re-use types
284 /// coming from the "vmlinux" binary that is the main corpus of the
285 /// group.
286 ///
287 /// @return the corpus group the current corpus belongs to, if the
288 /// current corpus is part of a corpus group being built. Nil otherwise.
289 corpus_sptr
291 {
292  if (has_corpus_group())
293  if (corpus_sptr main_corpus = main_corpus_from_current_group())
295  return corpus_group();
296 
297  return corpus_sptr();
298 }
299 
300 /// Add the representation of the ABI of a function to the set of
301 /// exported declarations or undefined declarations of the current
302 /// corpus.
303 ///
304 /// Note that if the function is defined and exported, then it's going
305 /// to be added to the set of functions exported by the current
306 /// corpus. Otherwise, if the function has an undefined symbol then
307 /// it's going to be added to the sef of undefined functions used by
308 /// the current corpus.
309 ///
310 /// @param fn the internal representation of the ABI of a function.
311 void
313 {
314  bool added = false;
315  if (fn)
317  corpus()->get_exported_decls_builder().get())
318  added = b->maybe_add_fn_to_exported_fns(const_cast<function_decl*>(fn));
319 
320  if (fn && !added)
321  {
322  if (!fn->get_symbol() || !fn->get_symbol()->is_defined())
323  corpus()->get_undefined_functions().insert(fn);
324  }
325 }
326 
327 /// Add the representation of the ABI of a variable to the set of
328 /// exported or undefined declarations of the current corpus.
329 ///
330 /// Note that if the variable is defined and exported, then it's going
331 /// to be added to the set of variables exported by the current
332 /// corpus. Otherwise, if the variable has an undefined symbol then
333 /// it's going to be added to the sef of undefined variables used by
334 /// the current corpus.
335 ///
336 /// @param var the internal representation of the ABI of a variable.
337 void
339 {
340  bool added = false;
341  if (var)
343  corpus()->get_exported_decls_builder().get())
344  added = b->maybe_add_var_to_exported_vars(var);
345 
346  if (var && !added)
347  {
348  if (!var->get_symbol() || !var->get_symbol()->is_defined())
349  corpus()->get_undefined_variables().insert(var);
350  }
351 }
352 
353 /// The bitwise OR operator for the @ref fe_iface::status type.
354 ///
355 /// @param l the left-hand side operand.
356 ///
357 /// @param r the right-hand side operand.
358 ///
359 /// @return the result of the operation.
362 {
363  return static_cast<fe_iface::status>(static_cast<unsigned>(l)
364  | static_cast<unsigned>(r));
365 }
366 
367 /// The bitwise AND operator for the @ref fe_iface::status type.
368 ///
369 /// @param l the left-hand side operand.
370 ///
371 /// @param r the right-hand side operand.
372 ///
373 /// @return the result of the operation.
376 {
377  return static_cast<fe_iface::status>(static_cast<unsigned>(l)
378  & static_cast<unsigned>(r));
379 }
380 
381 /// The bitwise |= operator for the @ref fe_iface::status type.
382 ///
383 /// @param l the left-hand side operand.
384 ///
385 /// @param r the right-hand side operand.
386 ///
387 /// @return the result of the operation.
390 {
391  l = l | r;
392  return l;
393 }
394 
395 /// The bitwise &= operator for the @ref fe_iface::status type.
396 ///
397 /// @param l the left-hand side operand.
398 ///
399 /// @param r the right-hand side operand.
400 ///
401 /// @return the result of the operation.
404 {
405  l = l & r;
406  return l;
407 }
408 
409 /// Return a diagnostic status with english sentences to describe the
410 /// problems encoded in a given abigail::elf_reader::status, if
411 /// there is an error.
412 ///
413 /// @param status the status to diagnose
414 ///
415 /// @return a string containing sentences that describe the possible
416 /// errors encoded in @p s. If there is no error to encode, then the
417 /// empty string is returned.
418 std::string
420 {
421  std::string str;
422 
424  str += "could not find debug info";
425 
427  str += "could not find alternate debug info";
428 
430  str += "could not load ELF symbols";
431 
432  return str;
433 }
434 
435 }// namespace abigail
suppr::suppressions_type & suppressions()
Getter of the vector of suppression specifications associated with the current front-end.
This file contains the declarations for the fe_iface a.k.a "Front End Interface". ...
The base class of all libabigail front-ends: The Front End Interface.
Definition: abg-fe-iface.h:28
fe_iface::status & operator|=(fe_iface::status &l, fe_iface::status r)
The bitwise |= operator for the fe_iface::status type.
const options_type & options() const
Getter of the the options of the current Front End Interface.
Definition: abg-fe-iface.cc:92
options_type(environment &)
Constructor of the type fe_iface::options_type.
Definition: abg-fe-iface.cc:57
const elf_symbol_sptr & get_symbol() const
Gets the the underlying ELF symbol for the current variable, that was set using function_decl::set_sy...
Definition: abg-ir.cc:22317
The generic options that control the behaviour of all Front-End interfaces.
Definition: abg-fe-iface.h:59
bool current_corpus_is_main_corpus_from_current_group()
Test if the current corpus being built is the main corpus of the current corpus group.
status
The status of the fe_iface::read_corpus call.
Definition: abg-fe-iface.h:37
const elf_symbol_sptr & get_symbol() const
Gets the the underlying ELF symbol for the current variable, that was set using var_decl::set_symbol(...
Definition: abg-ir.cc:20822
fe_iface::status & operator&=(fe_iface::status &l, fe_iface::status r)
The bitwise &= operator for the fe_iface::status type.
Abstracts a variable declaration.
Definition: abg-ir.h:3007
bool has_corpus_group() const
Test if there is a corpus group being built.
This status is for when the debug info could not be read.
Definition: abg-fe-iface.h:46
corpus_group_sptr & corpus_group()
Getter for the ABI corpus group being built by the current front-end.
void add_var_to_exported_or_undefined_decls(const var_decl *var)
Add the representation of the ABI of a variable to the set of exported or undefined declarations of t...
Toplevel namespace for libabigail.
std::string status_to_diagnostic_string(fe_iface::status s)
Return a diagnostic status with english sentences to describe the problems encoded in a given abigail...
Abstraction for a function declaration.
Definition: abg-ir.h:3110
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:139
corpus_sptr main_corpus_from_current_group()
Return the main corpus from the current corpus group, if any.
corpus_sptr corpus()
Getter for the ABI corpus being built by the current front-end.
fe_iface(const std::string &corpus_path, environment &e)
Constructor of the type fe_iface.
Definition: abg-fe-iface.cc:68
void add_fn_to_exported_or_undefined_decls(const function_decl *fn)
Add the representation of the ABI of a function to the set of exported declarations or undefined decl...
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
Definition: abg-fwd.h:1658
Abstracts the building of the set of exported variables and functions.
Definition: abg-corpus.h:333
This status is for when the symbols of the ELF binaries could not be read.
Definition: abg-fe-iface.h:54
fe_iface::status operator|(fe_iface::status l, fe_iface::status r)
The bitwise OR operator for the fe_iface::status type.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
fe_iface::status operator&(fe_iface::status l, fe_iface::status r)
The bitwise AND operator for the fe_iface::status type.
const string & dt_soname() const
Getter for the SONAME of the analyzed binary.
bool load_in_linux_kernel_mode() const
Test if the input binary is to be considered as a Linux Kernel binary.
corpus_sptr should_reuse_type_from_corpus_group()
Return true if the current corpus is part of a corpus group being built and if it's not the main corp...
virtual ~fe_iface()
Desctructor of the Front End Interface.
Definition: abg-fe-iface.cc:74
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
Definition: abg-fe-iface.cc:82
void add_suppressions(const suppr::suppressions_type &)
Add suppressions specifications to the set of suppressions to be used during the construction of the ...
This status is for when the alternate debug info could not be found.
Definition: abg-fe-iface.h:50