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 
19 ABG_END_EXPORT_DECLARATIONS
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.
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
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:29
bool has_corpus_group() const
Test if there is a corpus group being built.
status
The status of the fe_iface::read_corpus call.
Definition: abg-fe-iface.h:38
@ STATUS_NO_SYMBOLS_FOUND
This status is for when the symbols of the ELF binaries could not be read.
Definition: abg-fe-iface.h:54
@ STATUS_DEBUG_INFO_NOT_FOUND
This status is for when the debug info could not be read.
Definition: abg-fe-iface.h:46
@ STATUS_ALT_DEBUG_INFO_NOT_FOUND
This status is for when the alternate debug info could not be found.
Definition: abg-fe-iface.h:50
const options_type & options() const
Getter of the the options of the current Front End Interface.
Definition: abg-fe-iface.cc:92
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...
corpus_sptr corpus()
Getter for the ABI corpus being built by the current front-end.
suppr::suppressions_type & suppressions()
Getter of the vector of suppression specifications associated with the current front-end.
corpus_group_sptr & corpus_group()
Getter for the ABI corpus group 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
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
Definition: abg-fe-iface.cc:82
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...
bool load_in_linux_kernel_mode() const
Test if the input binary is to be considered as a Linux Kernel binary.
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.
virtual ~fe_iface()
Desctructor of the Front End Interface.
Definition: abg-fe-iface.cc:74
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...
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
const string & dt_soname() const
Getter for the SONAME of the analyzed binary.
corpus_sptr main_corpus_from_current_group()
Return the main corpus from the current corpus group, if any.
void add_suppressions(const suppr::suppressions_type &)
Add suppressions specifications to the set of suppressions to be used during the construction of the ...
Abstracts the building of the set of exported variables and functions.
Definition: abg-corpus.h:334
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:25
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:140
Abstraction for a function declaration.
Definition: abg-ir.h:3111
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
Abstracts a variable declaration.
Definition: abg-ir.h:3008
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
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
Definition: abg-fwd.h:1658
Toplevel namespace for libabigail.
fe_iface::status & operator|=(fe_iface::status &l, fe_iface::status r)
The bitwise |= operator for the fe_iface::status type.
fe_iface::status & operator&=(fe_iface::status &l, fe_iface::status r)
The bitwise &= operator for the fe_iface::status type.
fe_iface::status operator&(fe_iface::status l, fe_iface::status r)
The bitwise AND operator for the fe_iface::status type.
fe_iface::status operator|(fe_iface::status l, fe_iface::status r)
The bitwise OR operator for the fe_iface::status type.
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...
The generic options that control the behaviour of all Front-End interfaces.
Definition: abg-fe-iface.h:60
options_type(environment &)
Constructor of the type fe_iface::options_type.
Definition: abg-fe-iface.cc:57